diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-04-27 14:43:50 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-04-30 15:26:26 +0000 |
commit | 68faf3a9bb496d655de575196b7070855ef096e0 (patch) | |
tree | 160b1585bc04f4e268ebebf806fcd6b2ed8447d7 /src | |
parent | 4e88f1aaea94ae021b31d914d54a35ae89125e15 (diff) |
Fix QImage format after inplace conversion
Some inplace conversions would not set the requested image format in
the returned image, due to the same conversion being used for several
destination formats.
This patch ensures all inplace conversions return the right format,
and adds testing infrastructure to easily test iterate over all formats
so that they all can be tested.
Change-Id: I68ab17a713ddb2aa8ed6aaf0a0a1ec8bbcb56090
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 126 |
1 files changed, 92 insertions, 34 deletions
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index e1be032215..74ad1127a9 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -425,25 +425,25 @@ static void convert_ARGB_to_RGBA(QImageData *dest, const QImageData *src, Qt::Im } } +template<QImage::Format DestFormat> static bool convert_ARGB_to_RGBA_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_ARGB32_Premultiplied); const int pad = (data->bytes_per_line >> 2) - data->width; quint32 *rgb_data = (quint32 *) data->data; + Q_CONSTEXPR uint mask = (DestFormat == QImage::Format_RGBX8888) ? 0xff000000 : 0; for (int i = 0; i < data->height; ++i) { const quint32 *end = rgb_data + data->width; while (rgb_data < end) { - *rgb_data = ARGB2RGBA(*rgb_data); + *rgb_data = ARGB2RGBA(*rgb_data | mask); ++rgb_data; } rgb_data += pad; } - if (data->format == QImage::Format_ARGB32) - data->format = QImage::Format_RGBA8888; - else - data->format = QImage::Format_RGBA8888_Premultiplied; + + data->format = DestFormat; return true; } @@ -567,6 +567,7 @@ static inline uint qUnpremultiplyRgb30(uint rgb30) return 0; } +template<bool rgbswap> static void convert_A2RGB30_PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied); @@ -582,7 +583,8 @@ static void convert_A2RGB30_PM_to_RGB30(QImageData *dest, const QImageData *src, for (int i = 0; i < src->height; ++i) { const quint32 *end = src_data + src->width; while (src_data < end) { - *dest_data = 0xc0000000 | qUnpremultiplyRgb30(*src_data); + const uint p = 0xc0000000 | qUnpremultiplyRgb30(*src_data); + *dest_data = (rgbswap) ? qRgbSwapRgb30(p) : p; ++src_data; ++dest_data; } @@ -591,6 +593,7 @@ static void convert_A2RGB30_PM_to_RGB30(QImageData *dest, const QImageData *src, } } +template<bool rgbswap> static bool convert_A2RGB30_PM_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied); @@ -601,16 +604,17 @@ static bool convert_A2RGB30_PM_to_RGB30_inplace(QImageData *data, Qt::ImageConve for (int i = 0; i < data->height; ++i) { const uint *end = rgb_data + data->width; while (rgb_data < end) { - *rgb_data = 0xc0000000 | qUnpremultiplyRgb30(*rgb_data); + const uint p = 0xc0000000 | qUnpremultiplyRgb30(*rgb_data); + *rgb_data = (rgbswap) ? qRgbSwapRgb30(p) : p; ++rgb_data; } rgb_data += pad; } if (data->format == QImage::Format_A2RGB30_Premultiplied) - data->format = QImage::Format_RGB30; + data->format = (rgbswap) ? QImage::Format_BGR30 : QImage::Format_RGB30; else - data->format = QImage::Format_BGR30; + data->format = (rgbswap) ? QImage::Format_RGB30 : QImage::Format_BGR30; return true; } @@ -678,6 +682,19 @@ static bool convert_BGR30_to_RGB30_inplace(QImageData *data, Qt::ImageConversion return true; } +static bool convert_BGR30_to_A2RGB30_inplace(QImageData *data, Qt::ImageConversionFlags flags) +{ + Q_ASSERT(data->format == QImage::Format_RGB30 || data->format == QImage::Format_BGR30); + if (!convert_BGR30_to_RGB30_inplace(data, flags)) + return false; + + if (data->format == QImage::Format_RGB30) + data->format = QImage::Format_A2RGB30_Premultiplied; + else + data->format = QImage::Format_A2BGR30_Premultiplied; + return true; +} + static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); @@ -732,7 +749,7 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve return true; } -static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags) +static bool convert_indexed8_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); if (!data->own_data) @@ -775,7 +792,7 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio } data->colortable = QVector<QRgb>(); - data->format = QImage::Format_RGB32; + data->format = QImage::Format_ARGB32; data->bytes_per_line = dst_bytes_per_line; data->depth = depth; data->nbytes = nbytes; @@ -783,6 +800,24 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio return true; } +static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags flags) +{ + Q_ASSERT(data->format == QImage::Format_Indexed8); + if (!data->own_data) + return false; + + if (data->has_alpha_clut) { + for (int i = 0; i < data->colortable.size(); ++i) + data->colortable[i] |= 0xff000000; + } + + if (!convert_indexed8_to_ARGB_inplace(data, flags)) + return false; + + data->format = QImage::Format_RGB32; + return true; +} + static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); @@ -965,8 +1000,9 @@ static void mask_alpha_converter(QImageData *dest, const QImageData *src, Qt::Im template<QImage::Format DestFormat> static bool mask_alpha_converter_inplace(QImageData *data, Qt::ImageConversionFlags) { - Q_ASSERT(data->format == QImage::Format_RGB32 || DestFormat == QImage::Format_RGB32); - + Q_ASSERT(data->format == QImage::Format_RGB32 + || DestFormat == QImage::Format_RGB32 + || DestFormat == QImage::Format_RGBX8888); const int pad = (data->bytes_per_line >> 2) - data->width; QRgb *rgb_data = (QRgb *) data->data; @@ -1009,6 +1045,29 @@ static void mask_alpha_converter_RGBx(QImageData *dest, const QImageData *src, Q #endif } +static bool mask_alpha_converter_rgbx_inplace(QImageData *data, Qt::ImageConversionFlags flags) +{ +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + return mask_alpha_converter_inplace<QImage::Format_RGBX8888>(data, flags); +#else + Q_UNUSED(flags); + + const int pad = (data->bytes_per_line >> 2) - data->width; + QRgb *rgb_data = (QRgb *) data->data; + + for (int i = 0; i < data->height; ++i) { + const QRgb *end = rgb_data + data->width; + while (rgb_data < end) { + *rgb_data = *rgb_data | 0x000000fff; + ++rgb_data; + } + rgb_data += pad; + } + data->format = DestFormat; + return true; +#endif +} + static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format) { QVector<QRgb> colorTable = ctbl; @@ -2323,9 +2382,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_A2RGB30_PM_to_RGB30, - 0, + convert_A2RGB30_PM_to_RGB30<false>, 0, + convert_A2RGB30_PM_to_RGB30<true>, convert_BGR30_to_RGB30, 0, 0 }, // Format_BGR30A2_Premultiplied @@ -2375,12 +2434,11 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, + convert_A2RGB30_PM_to_RGB30<true>, convert_BGR30_to_RGB30, - convert_A2RGB30_PM_to_RGB30, - 0, - 0, + convert_A2RGB30_PM_to_RGB30<false>, 0, + 0, 0 }, // Format_RGB30A2_Premultiplied { 0, @@ -2440,8 +2498,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, convert_indexed8_to_RGB_inplace, + convert_indexed8_to_ARGB_inplace, convert_indexed8_to_ARGB_PM_inplace, convert_indexed8_to_RGB16_inplace, 0, @@ -2501,8 +2559,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, - convert_ARGB_to_RGBA_inplace, + convert_ARGB_to_RGBA_inplace<QImage::Format_RGBX8888>, + convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888>, 0, 0, 0, 0, 0, 0, 0 }, // Format_ARGB32 @@ -2525,7 +2583,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - convert_ARGB_to_RGBA_inplace, + convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888_Premultiplied>, 0, 0, 0, 0, 0, 0 }, // Format_ARGB32_Premultiplied { @@ -2594,7 +2652,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, + mask_alpha_converter_rgbx_inplace, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__ 0, convert_ARGB_to_ARGB_PM_inplace_sse2, @@ -2646,10 +2704,10 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, + 0, // self convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>, convert_BGR30_to_RGB30_inplace, - convert_BGR30_to_RGB30_inplace, + convert_BGR30_to_A2RGB30_inplace, 0, 0 }, // Format_BGR30 { @@ -2672,9 +2730,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - convert_A2RGB30_PM_to_RGB30_inplace, - 0, - 0, + convert_A2RGB30_PM_to_RGB30_inplace<false>, + 0, // self + convert_A2RGB30_PM_to_RGB30_inplace<true>, convert_BGR30_to_RGB30_inplace, 0, 0 }, // Format_BGR30A2_Premultiplied @@ -2699,8 +2757,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, convert_BGR30_to_RGB30_inplace, - convert_BGR30_to_RGB30_inplace, - 0, + convert_BGR30_to_A2RGB30_inplace, + 0, // self convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>, 0, 0 }, // Format_RGB30 @@ -2724,10 +2782,10 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, + convert_A2RGB30_PM_to_RGB30_inplace<true>, convert_BGR30_to_RGB30_inplace, - convert_A2RGB30_PM_to_RGB30_inplace, - 0, + convert_A2RGB30_PM_to_RGB30_inplace<false>, + 0, // self 0, 0 }, // Format_RGB30A2_Premultiplied { |