diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-11-20 10:04:28 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-12-12 22:26:49 +0000 |
commit | fc2ec95587c431b1916ec5590b7ef634be96c985 (patch) | |
tree | 37e38ef0fbf21af77001bc97f1080dd6ae92edef | |
parent | d20c9805763ab3dc504ebf2cefd33499d89ef22c (diff) |
Add Grayscale16 Image Format
[ChangeLog][QtGui][QImage] Added support for 16-bit grayscale format.
Together-with: Aaron Linville<aaron@linville.org>
Task-number: QTBUG-41176
Change-Id: I5fe4f54a55ebe1413aa71b882c19627fe22362ac
Reviewed-by: Nick D'Ademo <nickdademo@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/gui/image/qimage.cpp | 25 | ||||
-rw-r--r-- | src/gui/image/qimage.h | 3 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 209 | ||||
-rw-r--r-- | src/gui/image/qimage_p.h | 1 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 3 | ||||
-rw-r--r-- | src/gui/image/qpnghandler.cpp | 20 | ||||
-rw-r--r-- | src/gui/opengl/qopenglpaintengine.cpp | 5 | ||||
-rw-r--r-- | src/gui/opengl/qopengltextureuploader.cpp | 28 | ||||
-rw-r--r-- | src/gui/opengl/qopengltextureuploader_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 89 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 2 | ||||
-rw-r--r-- | tests/auto/gui/image/qimage/tst_qimage.cpp | 42 | ||||
-rw-r--r-- | tests/auto/gui/image/qimagereader/tst_qimagereader.cpp | 2 | ||||
-rw-r--r-- | tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp | 6 |
14 files changed, 348 insertions, 89 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 0105f1decd..b6d93331e6 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -288,6 +288,7 @@ bool QImageData::checkForAlphaPixels() const case QImage::Format_BGR30: case QImage::Format_RGB30: case QImage::Format_Grayscale8: + case QImage::Format_Grayscale16: case QImage::Format_RGBX64: break; case QImage::Format_Invalid: @@ -710,6 +711,7 @@ bool QImageData::checkForAlphaPixels() const \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4) \value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5) \value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5) + \value Format_Grayscale16 The image is stored using an 16-bit grayscale format. (added in Qt 5.13) \value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16). This is the same as the Format_RGBX64 except alpha must always be 65535. (added in Qt 5.12) \value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12) @@ -2038,6 +2040,7 @@ static bool highColorPrecision(QImage::Format format) case QImage::Format_RGBX64: case QImage::Format_RGBA64: case QImage::Format_RGBA64_Premultiplied: + case QImage::Format_Grayscale16: return true; default: break; @@ -2531,6 +2534,10 @@ QColor QImage::pixelColor(int x, int y) const case Format_RGBA64_Premultiplied: c = reinterpret_cast<const QRgba64 *>(s)[x]; break; + case Format_Grayscale16: { + quint16 v = reinterpret_cast<const quint16 *>(s)[x]; + return QColor(qRgba64(v, v, v, 0xffff)); + } default: c = QRgba64::fromArgb32(pixel(x, y)); break; @@ -2641,6 +2648,7 @@ bool QImage::allGray() const case Format_Alpha8: return false; case Format_Grayscale8: + case Format_Grayscale16: return true; case Format_RGB32: case Format_ARGB32: @@ -2707,7 +2715,7 @@ bool QImage::isGrayscale() const if (d->format == QImage::Format_Alpha8) return false; - if (d->format == QImage::Format_Grayscale8) + if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16) return true; switch (depth()) { @@ -3341,6 +3349,7 @@ QImage QImage::rgbSwapped_helper() const break; case Format_Alpha8: case Format_Grayscale8: + case Format_Grayscale16: return *this; case Format_Mono: case Format_MonoLSB: @@ -3452,6 +3461,7 @@ void QImage::rgbSwapped_inplace() break; case Format_Alpha8: case Format_Grayscale8: + case Format_Grayscale16: return; case Format_Mono: case Format_MonoLSB: @@ -5349,6 +5359,19 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = { /*PREMULTIPLIED*/ QPixelFormat::Premultiplied, /*INTERPRETATION*/ QPixelFormat::UnsignedShort, /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian), + //QImage::Format_Grayscale16: + QPixelFormat(QPixelFormat::Grayscale, + /*GRAY*/ 16, + /*SECOND*/ 0, + /*THIRD*/ 0, + /*FOURTH*/ 0, + /*FIFTH*/ 0, + /*ALPHA*/ 0, + /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha, + /*ALPHA POSITION*/ QPixelFormat::AtBeginning, + /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied, + /*INTERPRETATION*/ QPixelFormat::UnsignedShort, + /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian), }; Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats); diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 4b7a3b1ead..7a1f37c5cf 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -128,10 +128,7 @@ public: Format_RGBX64, Format_RGBA64, Format_RGBA64_Premultiplied, -#if 0 - // reserved for future use Format_Grayscale16, -#endif #ifndef Q_QDOC NImageFormats #endif diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 215dd33499..ea9347183e 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -1447,6 +1447,56 @@ static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConver return true; } +static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_Grayscale16); + Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64 || + dest->format == QImage::Format_RGBA64_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const qsizetype sbpl = src->bytes_per_line; + const qsizetype dbpl = dest->bytes_per_line; + const uchar *src_data = src->data; + uchar *dest_data = dest->data; + + for (int i = 0; i < src->height; ++i) { + const quint16 *src_line = reinterpret_cast<const quint16 *>(src_data); + QRgba64 *dest_line = reinterpret_cast<QRgba64 *>(dest_data); + for (int j = 0; j < src->width; ++j) { + quint16 s = src_line[j]; + dest_line[j] = qRgba64(s, s, s, 0xFFFF); + } + src_data += sbpl; + dest_data += dbpl; + } +} + +static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(dest->format == QImage::Format_Grayscale16); + Q_ASSERT(src->format == QImage::Format_RGBX64 || + src->format == QImage::Format_RGBA64_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const qsizetype sbpl = src->bytes_per_line; + const qsizetype dbpl = dest->bytes_per_line; + const uchar *src_data = src->data; + uchar *dest_data = dest->data; + + for (int i = 0; i < src->height; ++i) { + const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data); + quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data); + for (int j = 0; j < src->width; ++j) { + QRgba64 s = src_line[j].unpremultiplied(); + dest_line[j] = qGray(s.red(), s.green(), s.blue()); + } + src_data += sbpl; + dest_data += dbpl; + } +} + static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format) { QVector<QRgb> colorTable = ctbl; @@ -2291,7 +2341,7 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] = { { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, @@ -2312,7 +2362,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_Mono { @@ -2334,7 +2384,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_MonoLSB { @@ -2359,7 +2409,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, 0, 0, convert_Indexed8_to_Alpha8, convert_Indexed8_to_Grayscale8, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_Indexed8 { @@ -2387,7 +2437,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_RGB_to_RGB30<PixelOrderRGB, false>, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_RGB32 { @@ -2417,7 +2467,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, convert_ARGB32_to_RGBA64<false>, - 0 + 0, 0 }, // Format_ARGB32 { @@ -2442,7 +2492,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_ARGB_to_RGBA, 0, 0, 0, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_ARGB32_Premultiplied { @@ -2464,7 +2514,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB16 { @@ -2486,7 +2536,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8565_Premultiplied { @@ -2508,7 +2558,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB666 { @@ -2530,7 +2580,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB6666_Premultiplied { @@ -2552,7 +2602,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB555 { @@ -2574,7 +2624,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8555_Premultiplied { @@ -2597,7 +2647,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_RGB888_to_RGB<true>, convert_RGB888_to_RGB<true>, convert_RGB888_to_RGB<true>, - 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB888 { @@ -2619,7 +2669,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB444 { @@ -2640,7 +2690,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB4444_Premultiplied { 0, @@ -2667,7 +2717,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_RGB_to_RGB30<PixelOrderRGB, true>, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_RGBX8888 { 0, @@ -2696,7 +2746,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, convert_ARGB32_to_RGBA64<true>, - 0 + 0, 0 }, // Format_RGBA8888 { @@ -2718,7 +2768,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888_Premultiplied { @@ -2746,7 +2796,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_BGR30_to_RGB30, convert_BGR30_to_RGB30, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_BGR30 { 0, @@ -2773,8 +2823,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_A2RGB30_PM_to_RGB30<true>, convert_BGR30_to_RGB30, 0, 0, - 0, 0, 0 - }, // Format_BGR30A2_Premultiplied + 0, 0, 0, 0 + }, // Format_A2BGR30_Premultiplied { 0, 0, @@ -2799,7 +2849,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_BGR30_to_RGB30, 0, convert_passthrough, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGB30 { 0, @@ -2826,8 +2876,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_A2RGB30_PM_to_RGB30<false>, 0, 0, 0, - 0, 0, 0 - }, // Format_RGB30A2_Premultiplied + 0, 0, 0, 0 + }, // Format_A2RGB30_Premultiplied { 0, 0, @@ -2846,7 +2896,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_Alpha8 { 0, @@ -2872,7 +2922,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // self convert_passthrough, - convert_passthrough + convert_passthrough, + convert_RGBA64_to_gray16 }, // Format_RGBX64 { 0, @@ -2898,7 +2949,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, convert_RGBA64_to_RGBx64, 0, // self - convert_RGBA64_to_RGBA64PM + convert_RGBA64_to_RGBA64PM, + 0 }, // Format_RGBA64 { 0, @@ -2927,20 +2979,51 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, convert_RGBA64PM_to_RGBA64<true>, convert_RGBA64PM_to_RGBA64<false>, - 0 // self - } // Format_RGBA64_Premultiplied + 0, // self + convert_RGBA64_to_gray16 + }, // Format_RGBA64_Premultiplied + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 0, + convert_gray16_to_RGBA64, + convert_gray16_to_RGBA64, + convert_gray16_to_RGBA64, + 0 // self + }, // Format_Grayscale16 }; InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = { { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_Mono { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_MonoLSB { 0, @@ -2964,7 +3047,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, 0, 0, convert_Indexed8_to_Alpha8_inplace, convert_Indexed8_to_Grayscale8_inplace, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_Indexed8 { 0, @@ -2991,7 +3074,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_RGB32 { 0, @@ -3018,7 +3101,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_ARGB32 { 0, @@ -3042,34 +3125,34 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888_Premultiplied>, 0, 0, 0, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_ARGB32_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB16 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8565_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB666 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB6666_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB555 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB8555_Premultiplied { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB888 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB444 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB4444_Premultiplied { 0, @@ -3096,7 +3179,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_RGBX8888 { 0, @@ -3123,7 +3206,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_RGBA8888 { 0, @@ -3145,7 +3228,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888_Premultiplied { 0, @@ -3172,7 +3255,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_BGR30_to_RGB30_inplace, convert_BGR30_to_A2RGB30_inplace, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_BGR30 { 0, @@ -3198,8 +3281,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, // self convert_A2RGB30_PM_to_RGB30_inplace<true>, convert_BGR30_to_RGB30_inplace, - 0, 0, 0, 0, 0 - }, // Format_BGR30A2_Premultiplied + 0, 0, 0, 0, 0, 0 + }, // Format_A2BGR30_Premultiplied { 0, 0, @@ -3224,7 +3307,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_BGR30_to_A2RGB30_inplace, 0, // self convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }, // Format_RGB30 { 0, @@ -3251,8 +3334,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_A2RGB30_PM_to_RGB30_inplace<false>, 0, // self 0, 0, - 0, 0, 0 - }, // Format_RGB30A2_Premultiplied + 0, 0, 0, 0 + }, // Format_A2RGB30_Premultiplied { 0, 0, @@ -3276,7 +3359,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, 0, 0, // self 0, - 0, 0, 0 + 0, 0, 0, 0 }, // Format_Alpha8 { 0, @@ -3301,26 +3384,32 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, 0, 0, 0, // self - 0, 0, 0 + 0, 0, 0, 0 }, // Format_Grayscale8 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // self convert_passthrough_inplace<QImage::Format_RGBA64>, convert_passthrough_inplace<QImage::Format_RGBA64_Premultiplied>, + 0 }, // Format_RGBX64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, convert_RGBA64_to_RGBx64_inplace, 0, // self - convert_RGBA64_to_RGBA64PM_inplace + convert_RGBA64_to_RGBA64PM_inplace, + 0 }, // Format_RGBA64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, convert_RGBA64PM_to_RGBA64_inplace<true>, convert_RGBA64PM_to_RGBA64_inplace<false>, - 0 // self - } // Format_RGBA64_Premultiplied + 0, // self + 0 + }, // Format_RGBA64_Premultiplied + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, // Format_Grayscale16 }; static void qInitImageConversions() diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index e3a6c53833..de12a313e8 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -189,6 +189,7 @@ inline int qt_depthForFormat(QImage::Format format) case QImage::Format_RGB16: case QImage::Format_RGB444: case QImage::Format_ARGB4444_Premultiplied: + case QImage::Format_Grayscale16: depth = 16; break; case QImage::Format_RGB666: diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 13c1c29d5b..2732bbd197 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -203,6 +203,9 @@ void QRasterPlatformPixmap::fill(const QColor &color) pixel = qAlpha(color.rgba()); } else if (image.format() == QImage::Format_Grayscale8) { pixel = qGray(color.rgba()); + } else if (image.format() == QImage::Format_Grayscale16) { + QRgba64 c = color.rgba64(); + pixel = qGray(c.red(), c.green(), c.blue()); } else { pixel = 0; diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 8ae03d5d38..3655c39326 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -266,6 +266,18 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal else if (g == 1) image.setColor(0, qRgba(255, 255, 255, 0)); } + } else if (bit_depth == 16 + && png_get_channels(png_ptr, info_ptr) == 1 + && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale16) { + image = QImage(width, height, QImage::Format_Grayscale16); + if (image.isNull()) + return; + } + + png_read_update_info(png_ptr, info_ptr); + if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) + png_set_swap(png_ptr); } else if (bit_depth == 16) { bool hasMask = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); if (!hasMask) @@ -687,7 +699,7 @@ QImage::Format QPngHandlerPrivate::readImageFormat() if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { format = QImage::Format_Mono; } else if (bit_depth == 16) { - format = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? QImage::Format_RGBA64 : QImage::Format_RGBX64; + format = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? QImage::Format_RGBA64 : QImage::Format_Grayscale16; } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { format = QImage::Format_Grayscale8; } else { @@ -861,7 +873,8 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i else color_type = PNG_COLOR_TYPE_PALETTE; } - else if (image.format() == QImage::Format_Grayscale8) + else if (image.format() == QImage::Format_Grayscale8 + || image.format() == QImage::Format_Grayscale16) color_type = PNG_COLOR_TYPE_GRAY; else if (image.hasAlphaChannel()) color_type = PNG_COLOR_TYPE_RGB_ALPHA; @@ -877,6 +890,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i case QImage::Format_RGBX64: case QImage::Format_RGBA64: case QImage::Format_RGBA64_Premultiplied: + case QImage::Format_Grayscale16: bpc = 16; break; default: @@ -988,6 +1002,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i case QImage::Format_RGBX64: case QImage::Format_RGBA64: case QImage::Format_RGBA64_Premultiplied: + case QImage::Format_Grayscale16: png_set_swap(png_ptr); break; default: @@ -1018,6 +1033,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i case QImage::Format_MonoLSB: case QImage::Format_Indexed8: case QImage::Format_Grayscale8: + case QImage::Format_Grayscale16: case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_RGB888: diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index 001cb839fa..042b9ebd79 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -1574,14 +1574,15 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c case QImage::Format_Alpha8: if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) { d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::AlphaImageSrc); - bindOption = QOpenGLTextureUploader::UseRedFor8BitBindOption; + bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption; } else d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); break; case QImage::Format_Grayscale8: + case QImage::Format_Grayscale16: if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) { d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::GrayscaleImageSrc); - bindOption = QOpenGLTextureUploader::UseRedFor8BitBindOption; + bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption; } else d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); break; diff --git a/src/gui/opengl/qopengltextureuploader.cpp b/src/gui/opengl/qopengltextureuploader.cpp index 42e309b733..90253546c8 100644 --- a/src/gui/opengl/qopengltextureuploader.cpp +++ b/src/gui/opengl/qopengltextureuploader.cpp @@ -104,7 +104,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3; const bool sRgbBinding = (options & SRgbBindOption); Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES()); - Q_ASSERT((options & (SRgbBindOption | UseRedFor8BitBindOption)) != (SRgbBindOption | UseRedFor8BitBindOption)); + Q_ASSERT((options & (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)) != (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)); switch (image.format()) { case QImage::Format_RGB32: @@ -213,7 +213,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag if (sRgbBinding) { // Always needs conversion break; - } else if (options & UseRedFor8BitBindOption) { + } else if (options & UseRedForAlphaAndLuminanceBindOption) { externalFormat = internalFormat = GL_RED; pixelType = GL_UNSIGNED_BYTE; targetFormat = image.format(); @@ -223,7 +223,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag if (sRgbBinding) { // Always needs conversion break; - } else if (options & UseRedFor8BitBindOption) { + } else if (options & UseRedForAlphaAndLuminanceBindOption) { externalFormat = internalFormat = GL_RED; pixelType = GL_UNSIGNED_BYTE; targetFormat = image.format(); @@ -243,7 +243,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag if (sRgbBinding) { // Always needs conversion break; - } else if (options & UseRedFor8BitBindOption) { + } else if (options & UseRedForAlphaAndLuminanceBindOption) { externalFormat = internalFormat = GL_RED; pixelType = GL_UNSIGNED_BYTE; targetFormat = image.format(); @@ -259,6 +259,26 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag targetFormat = image.format(); } break; + case QImage::Format_Grayscale16: + if (sRgbBinding) { + // Always needs conversion + break; + } else if (options & UseRedForAlphaAndLuminanceBindOption) { + externalFormat = internalFormat = GL_RED; + pixelType = GL_UNSIGNED_SHORT; + targetFormat = image.format(); + } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) { + externalFormat = internalFormat = GL_LUMINANCE; + pixelType = GL_UNSIGNED_SHORT; + targetFormat = image.format(); + } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { + GLint swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_ONE }; + funcs->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + externalFormat = internalFormat = GL_RED; + pixelType = GL_UNSIGNED_SHORT; + targetFormat = image.format(); + } + break; default: break; } diff --git a/src/gui/opengl/qopengltextureuploader_p.h b/src/gui/opengl/qopengltextureuploader_p.h index d758b3787b..0dcf709d7e 100644 --- a/src/gui/opengl/qopengltextureuploader_p.h +++ b/src/gui/opengl/qopengltextureuploader_p.h @@ -65,7 +65,7 @@ public: enum BindOption { NoBindOption = 0x0000, PremultipliedAlphaBindOption = 0x0001, - UseRedFor8BitBindOption = 0x0002, + UseRedForAlphaAndLuminanceBindOption = 0x0002, SRgbBindOption = 0x0004, PowerOfTwoBindOption = 0x0008 }; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 9ef210cc68..af9375fcec 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -857,6 +857,44 @@ static const QRgba64 *QT_FASTCALL fetchGrayscale8ToRGB64(QRgba64 *buffer, const return buffer; } +static void QT_FASTCALL convertGrayscale16ToRGB32(uint *buffer, int count, const QVector<QRgb> *) +{ + for (int i = 0; i < count; ++i) { + const uint x = qt_div_257(buffer[i]); + buffer[i] = qRgb(x, x, x); + } +} + +static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index; + for (int i = 0; i < count; ++i) { + const uint x = qt_div_257(s[i]); + buffer[i] = qRgb(x, x, x); + } + return buffer; +} + +static const QRgba64 *QT_FASTCALL convertGrayscale16ToRGBA64(QRgba64 *buffer, const uint *src, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + const unsigned short *s = reinterpret_cast<const unsigned short *>(src); + for (int i = 0; i < count; ++i) + buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535); + return buffer; +} + +static const QRgba64 *QT_FASTCALL fetchGrayscale16ToRGBA64(QRgba64 *buffer, const uchar *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index; + for (int i = 0; i < count; ++i) { + buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535); + } + return buffer; +} + static void QT_FASTCALL storeARGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count, const QVector<QRgb> *, QDitherInfo *) { @@ -1362,6 +1400,22 @@ static void QT_FASTCALL storeGrayscale8FromARGB32PM(uchar *dest, const uint *src dest[index + i] = qGray(qUnpremultiply(src[i])); } +static void QT_FASTCALL storeGrayscale16FromRGB32(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + unsigned short *d = reinterpret_cast<unsigned short *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = qGray(src[i]) * 257; +} + +static void QT_FASTCALL storeGrayscale16FromARGB32PM(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + unsigned short *d = reinterpret_cast<unsigned short *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = qGray(qUnpremultiply(src[i])) * 257; +} + static const uint *QT_FASTCALL fetchRGB64ToRGB32(uint *buffer, const uchar *src, int index, int count, const QVector<QRgb> *, QDitherInfo *) { @@ -1488,7 +1542,11 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { { true, true, QPixelLayout::BPP64, nullptr, convertPassThrough, nullptr, fetchRGB64ToRGB32, fetchPassThrough64, - storeRGB64FromRGB32, storeRGB64FromRGB32 } // Format_RGBA64_Premultiplied + storeRGB64FromRGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied + { false, false, QPixelLayout::BPP16, nullptr, + convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64, + fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64, + storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 } // Format_Grayscale16 }; Q_STATIC_ASSERT(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats); @@ -1564,6 +1622,16 @@ static void QT_FASTCALL storeRGBA64PMFromRGBA64PM(uchar *dest, const QRgba64 *sr memcpy(d, src, count * sizeof(QRgba64)); } +static void QT_FASTCALL storeGray16FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + quint16 *d = reinterpret_cast<quint16*>(dest) + index; + for (int i = 0; i < count; ++i) { + QRgba64 s = src[i].unpremultiplied(); + d[i] = qGray(s.red(), s.green(), s.blue()); + } +} + ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = { nullptr, nullptr, @@ -1592,7 +1660,8 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = { storeGenericFromRGBA64PM<QImage::Format_Grayscale8>, storeRGBX64FromRGBA64PM, storeRGBA64FromRGBA64PM, - storeRGBA64PMFromRGBA64PM + storeRGBA64PMFromRGBA64PM, + storeGray16FromRGBA64PM }; /* @@ -1696,6 +1765,7 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] = destFetch, // Format_RGBX64 destFetch, // Format_RGBA64 destFetch, // Format_RGBA64_Premultiplied + destFetch, // Format_Grayscale16 }; static DestFetchProc64 destFetchProc64[QImage::NImageFormats] = @@ -1728,6 +1798,7 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] = destFetchRGB64, // Format_RGBX64 destFetch64, // Format_RGBA64 destFetchRGB64, // Format_RGBA64_Premultiplied + destFetch64, // Format_Grayscale16 }; /* @@ -1881,6 +1952,7 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] = destStore, // Format_RGBX64 destStore, // Format_RGBA64 destStore, // Format_RGBA64_Premultiplied + destStore, // Format_Grayscale16 }; static DestStoreProc64 destStoreProc64[QImage::NImageFormats] = @@ -1912,7 +1984,8 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] = destStore64, // Format_Grayscale8 0, // Format_RGBX64 destStore64RGBA64, // Format_RGBA64 - 0 // Format_RGBA64_Premultiplied + 0, // Format_RGBA64_Premultiplied + destStore64, // Format_Grayscale16 }; /* @@ -3839,6 +3912,7 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = { fetchUntransformed, // RGBX64 fetchUntransformed, // RGBA64 fetchUntransformed, // RGBA64_Premultiplied + fetchUntransformed, // Grayscale16 }; static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = { @@ -5253,6 +5327,7 @@ void qBlendTexture(int count, const QSpan *spans, void *userData) case QImage::Format_RGBX64: case QImage::Format_RGBA64: case QImage::Format_RGBA64_Premultiplied: + case QImage::Format_Grayscale16: proc = processTextureSpansGeneric64[blendType]; break; case QImage::Format_Invalid: @@ -6259,6 +6334,14 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = qt_alphargbblit_generic, qt_rectfill_quint64 }, + // Format_Grayscale16 + { + blend_color_generic_rgb64, + 0, + qt_alphamapblit_generic, + qt_alphargbblit_generic, + qt_rectfill_quint16 + }, }; #if !defined(__SSE2__) diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 4dcfbc813b..37108949d6 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -879,6 +879,8 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { // qt_div_255 is a fast rounded division by 255 using an approximation that is accurate for all positive 16-bit integers static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257(uint x) { return qt_div_257_floor(x + 128); } static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c) diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 5ffd75f931..2e2cb52b3e 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -298,6 +298,8 @@ static QLatin1String formatToString(QImage::Format format) return QLatin1String("RGBA64"); case QImage::Format_RGBA64_Premultiplied: return QLatin1String("RGBA64pm"); + case QImage::Format_Grayscale16: + return QLatin1String("Grayscale16"); default: break; }; @@ -2366,8 +2368,11 @@ void tst_QImage::rgbSwapped_data() QTest::addColumn<QImage::Format>("format"); for (int i = QImage::Format_Indexed8; i < QImage::NImageFormats; ++i) { - if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8) + if (i == QImage::Format_Alpha8 + || i == QImage::Format_Grayscale8 + || i == QImage::Format_Grayscale16) { continue; + } QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i); } } @@ -2612,8 +2617,11 @@ void tst_QImage::inplaceMirrored_data() QTest::addColumn<bool>("swap_horizontal"); for (int i = QImage::Format_Mono; i < QImage::NImageFormats; ++i) { - if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8) + if (i == QImage::Format_Alpha8 + || i == QImage::Format_Grayscale8 + || i == QImage::Format_Grayscale16) { continue; + } if (i == QImage::Format_RGB444 || i == QImage::Format_ARGB4444_Premultiplied) continue; const auto fmt = formatToString(QImage::Format(i)); @@ -2785,11 +2793,11 @@ void tst_QImage::genericRgbConversion_data() QTest::addColumn<QImage::Format>("dest_format"); for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) { - if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8) + if (i == QImage::Format_Alpha8) continue; const QLatin1String formatI = formatToString(QImage::Format(i)); for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) { - if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8) + if (j == QImage::Format_Alpha8) continue; if (i == j) continue; @@ -2805,6 +2813,9 @@ void tst_QImage::genericRgbConversion() QFETCH(QImage::Format, format); QFETCH(QImage::Format, dest_format); + bool srcGrayscale = format == QImage::Format_Grayscale8 || format == QImage::Format_Grayscale16; + bool dstGrayscale = dest_format == QImage::Format_Grayscale8 || dest_format == QImage::Format_Grayscale16; + QImage image(16, 16, format); for (int i = 0; i < image.height(); ++i) @@ -2816,8 +2827,12 @@ void tst_QImage::genericRgbConversion() for (int i = 0; i < imageConverted.height(); ++i) { for (int j = 0; j < imageConverted.width(); ++j) { QRgb convertedColor = imageConverted.pixel(j,i); - QCOMPARE(qRed(convertedColor) & 0xF0, j * 16); - QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16); + if (srcGrayscale || dstGrayscale) { + QVERIFY(qAbs(qGray(convertedColor) - qGray(qRgb(j*16, i*16, 0))) < 15); + } else { + QCOMPARE(qRed(convertedColor) & 0xF0, j * 16); + QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16); + } } } } @@ -2828,11 +2843,17 @@ void tst_QImage::inplaceRgbConversion_data() QTest::addColumn<QImage::Format>("dest_format"); for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) { - if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8) + if (i == QImage::Format_Alpha8 + || i == QImage::Format_Grayscale8 + || i == QImage::Format_Grayscale16) { continue; + } for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) { - if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8) + if (j == QImage::Format_Alpha8 + || j == QImage::Format_Grayscale8 + || j == QImage::Format_Grayscale16) { continue; + } if (i == j) continue; QTest::addRow("%s -> %s", formatToString(QImage::Format(i)).data(), formatToString(QImage::Format(j)).data()) @@ -3002,8 +3023,11 @@ void tst_QImage::invertPixelsRGB_data() QTest::addColumn<QImage::Format>("image_format"); for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) { - if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8) + if (i == QImage::Format_Alpha8 + || i == QImage::Format_Grayscale8 + || i == QImage::Format_Grayscale16) { continue; + } QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i); } } diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index c2ec5b8925..1cf01133b2 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -525,7 +525,7 @@ void tst_QImageReader::imageFormat_data() QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32; QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32; QTest::newRow("png-3") << QString("kollada-16bpc.png") << QByteArray("png") << QImage::Format_RGBA64; - QTest::newRow("png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_RGBX64; // Grayscale16 + QTest::newRow("png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_Grayscale16; QTest::newRow("png-5") << QString("basn2c16.png") << QByteArray("png") << QImage::Format_RGBX64; QTest::newRow("png-6") << QString("basn4a16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16Alpha16 QTest::newRow("png-7") << QString("basn6a16.png") << QByteArray("png") << QImage::Format_RGBA64; diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index 77851cd7d0..aaa8475c74 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -239,7 +239,7 @@ void tst_QImageWriter::writeImage2_data() // QLatin1String("jpeg"), }; - QImage image0(70, 70, QImage::Format_ARGB32); + QImage image0(70, 70, QImage::Format_RGB32); image0.fill(QColor(Qt::red).rgb()); QImage::Format imgFormat = QImage::Format_Mono; @@ -304,10 +304,10 @@ void tst_QImageWriter::writeImage2() if (!equalImageContents(written, image)) { qDebug() << "image" << image.format() << image.width() << image.height() << image.depth() - << hex << image.pixel(0, 0); + << image.pixelColor(0, 0); qDebug() << "written" << written.format() << written.width() << written.height() << written.depth() - << hex << written.pixel(0, 0); + << written.pixelColor(0, 0); } QVERIFY(equalImageContents(written, image)); |