diff options
Diffstat (limited to 'src/gui/image/qimage_conversions.cpp')
-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 { |