From 36e6376755ce0f5dcd022e11d2539f125980a96b Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 3 Jul 2013 15:13:55 +0200 Subject: Support RGBA image format Support the byte-ordered RGBA format which is used by OpenGL, and many endian neutral byte formats. Task-number: QTBUG-32201 Change-Id: I77cffb4c30c69545fa96ded2f537b2ebd9351acb Reviewed-by: Allan Sandfeld Jensen --- src/gui/image/qimage.cpp | 689 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 656 insertions(+), 33 deletions(-) (limited to 'src/gui/image/qimage.cpp') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 98f3aeeeb9..8e5f6391a7 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -212,6 +212,16 @@ bool QImageData::checkForAlphaPixels() const } } break; + case QImage::Format_RGBA8888: + case QImage::Format_RGBA8888_Premultiplied: { + uchar *bits = data; + for (int y=0; yformat == Format_RGB32) + if (d->format == Format_RGB32 || d->format == Format_RGBX8888) pixel |= 0xff000000; + if (d->format == Format_RGBX8888 || d->format == Format_RGBA8888 || d->format == Format_RGBA8888_Premultiplied) + pixel = ARGB2RGBA(pixel); + qt_rectfill(reinterpret_cast(d->data), pixel, 0, 0, d->width, d->height, d->bytes_per_line); } @@ -1716,7 +1738,7 @@ void QImage::fill(const QColor &color) if (d->depth == 32) { uint pixel = color.rgba(); - if (d->format == QImage::Format_ARGB32_Premultiplied) + if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied) pixel = PREMUL(pixel); fill((uint) pixel); @@ -1871,8 +1893,8 @@ typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFla static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { - Q_ASSERT(src->format == QImage::Format_ARGB32); - Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); + Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied); Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); @@ -1912,6 +1934,191 @@ static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversio return true; } +static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32); + Q_ASSERT(dest->format == QImage::Format_RGBX8888); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const quint32 *src_data = (quint32 *) src->data; + quint32 *dest_data = (quint32 *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const quint32 *end = src_data + src->width; + while (src_data < end) { + *dest_data = ARGB2RGBA(0xff000000 | *src_data); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_ARGB_to_RGBA(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_RGBA8888 || dest->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const quint32 *src_data = (quint32 *) src->data; + quint32 *dest_data = (quint32 *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const quint32 *end = src_data + src->width; + while (src_data < end) { + *dest_data = ARGB2RGBA(*src_data); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +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; + + 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; + } + rgb_data += pad; + } + if (data->format == QImage::Format_ARGB32) + data->format = QImage::Format_RGBA8888; + else + data->format = QImage::Format_RGBA8888_Premultiplied; + return true; +} + +static void convert_ARGB_to_RGBA_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32); + Q_ASSERT(dest->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const quint32 *src_data = (quint32 *) src->data; + quint32 *dest_data = (quint32 *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const quint32 *end = src_data + src->width; + while (src_data < end) { + *dest_data = ARGB2RGBA(PREMUL(*src_data)); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_RGBA_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGBX8888 || src->format == QImage::Format_RGBA8888 || src->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const quint32 *src_data = (quint32 *) src->data; + quint32 *dest_data = (quint32 *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const quint32 *end = src_data + src->width; + while (src_data < end) { + *dest_data = RGBA2ARGB(*src_data); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static bool convert_RGBA_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_RGBX8888 || data->format == QImage::Format_RGBA8888 || data->format == QImage::Format_RGBA8888_Premultiplied); + + 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 = RGBA2ARGB(*rgb_data); + ++rgb_data; + } + rgb_data += pad; + } + if (data->format == QImage::Format_RGBA8888_Premultiplied) + data->format = QImage::Format_ARGB32_Premultiplied; + else if (data->format == QImage::Format_RGBX8888) + data->format = QImage::Format_RGB32; + else + data->format = QImage::Format_ARGB32; + return true; +} + +static void convert_RGBA_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGBA8888); + Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const quint32 *src_data = (quint32 *) src->data; + quint32 *dest_data = (quint32 *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const quint32 *end = src_data + src->width; + while (src_data < end) { + *dest_data = PREMUL(RGBA2ARGB(*src_data)); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static bool convert_RGBA_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_RGBA8888); + + 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 = PREMUL(RGBA2ARGB(*rgb_data)); + ++rgb_data; + } + rgb_data += pad; + } + data->format = QImage::Format_ARGB32_Premultiplied; + return true; +} + static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); @@ -2099,8 +2306,8 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { - Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied); - Q_ASSERT(dest->format == QImage::Format_ARGB32); + Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied || src->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); @@ -2122,12 +2329,132 @@ static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt: } static void convert_ARGB_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied || src->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_RGBX8888); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const QRgb *src_data = (QRgb *) src->data; + QRgb *dest_data = (QRgb *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const QRgb *end = src_data + src->width; + while (src_data < end) { + *dest_data = 0xff000000 | INV_PREMUL(*src_data); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_ARGB_PM_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_RGBX8888); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const QRgb *src_data = (QRgb *) src->data; + QRgb *dest_data = (QRgb *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const QRgb *end = src_data + src->width; + while (src_data < end) { + *dest_data = ARGB2RGBA(0xff000000 | INV_PREMUL(*src_data)); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_ARGB_PM_to_RGBA(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_RGBA8888); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const QRgb *src_data = (QRgb *) src->data; + QRgb *dest_data = (QRgb *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const QRgb *end = src_data + src->width; + while (src_data < end) { + *dest_data = ARGB2RGBA(INV_PREMUL(*src_data)); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_RGBA_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGBA8888 || src->format == QImage::Format_RGBX8888); Q_ASSERT(dest->format == QImage::Format_RGB32); Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const uint *src_data = (const uint *)src->data; + uint *dest_data = (uint *)dest->data; + + for (int i = 0; i < src->height; ++i) { + const uint *end = src_data + src->width; + while (src_data < end) { + *dest_data = RGBA2ARGB(*src_data) | 0xff000000; + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_RGB_to_RGBA(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGB32); + Q_ASSERT(dest->format == QImage::Format_RGBX8888 || dest->format == QImage::Format_RGBA8888 || dest->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const uint *src_data = (const uint *)src->data; + uint *dest_data = (uint *)dest->data; + + for (int i = 0; i < src->height; ++i) { + const uint *end = src_data + src->width; + while (src_data < end) { + *dest_data = ARGB2RGBA(*src_data | 0xff000000); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_RGBA_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_ARGB32); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + const int src_pad = (src->bytes_per_line >> 2) - src->width; const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; const QRgb *src_data = (QRgb *) src->data; @@ -2136,7 +2463,31 @@ static void convert_ARGB_PM_to_RGB(QImageData *dest, const QImageData *src, Qt:: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = 0xff000000 | INV_PREMUL(*src_data); + *dest_data = INV_PREMUL(RGBA2ARGB(*src_data)); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +static void convert_RGBA_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(dest->format == QImage::Format_RGB32); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const QRgb *src_data = (QRgb *) src->data; + QRgb *dest_data = (QRgb *) dest->data; + + for (int i = 0; i < src->height; ++i) { + const QRgb *end = src_data + src->width; + while (src_data < end) { + *dest_data = 0xff000000 | INV_PREMUL(RGBA2ARGB(*src_data)); ++src_data; ++dest_data; } @@ -2188,6 +2539,33 @@ static void mask_alpha_converter(QImageData *dest, const QImageData *src, Qt::Im } } +static void mask_alpha_converter_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags) +{ +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + return mask_alpha_converter(dest, src, flags); +#else + Q_UNUSED(flags); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const int src_pad = (src->bytes_per_line >> 2) - src->width; + const int dest_pad = (dest->bytes_per_line >> 2) - dest->width; + const uint *src_data = (const uint *)src->data; + uint *dest_data = (uint *)dest->data; + + for (int i = 0; i < src->height; ++i) { + const uint *end = src_data + src->width; + while (src_data < end) { + *dest_data = *src_data | 0x000000ff; + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +#endif +} + static QVector fix_color_table(const QVector &ctbl, QImage::Format format) { QVector colorTable = ctbl; @@ -2941,6 +3319,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_Mono @@ -2960,6 +3341,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_MonoLSB @@ -2979,6 +3363,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_Indexed8 @@ -2998,7 +3385,10 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat convert_generic, convert_generic, convert_generic, - convert_generic + convert_generic, + convert_RGB_to_RGBA, + convert_RGB_to_RGBA, + convert_RGB_to_RGBA }, // Format_RGB32 { @@ -3017,7 +3407,10 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat convert_generic, convert_generic, convert_generic, - convert_generic + convert_generic, + convert_ARGB_to_RGBx, + convert_ARGB_to_RGBA, + convert_ARGB_to_RGBA_PM, }, // Format_ARGB32 { @@ -3036,7 +3429,10 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0 + 0, + convert_ARGB_PM_to_RGBx, + convert_ARGB_PM_to_RGBA, + convert_ARGB_to_RGBA, }, // Format_ARGB32_Premultiplied { @@ -3056,6 +3452,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat #else 0, #endif + 0, + 0, + 0, 0, 0, 0, @@ -3078,6 +3477,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_ARGB8565_Premultiplied @@ -3097,6 +3499,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_RGB666 @@ -3116,6 +3521,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_ARGB6666_Premultiplied @@ -3139,6 +3547,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_RGB555 @@ -3158,6 +3569,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_ARGB8555_Premultiplied @@ -3177,6 +3591,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_RGB888 @@ -3196,6 +3613,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, + 0, 0 }, // Format_RGB444 @@ -3215,20 +3635,97 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + 0, + 0, 0 - } // Format_ARGB4444_Premultiplied + }, // Format_ARGB4444_Premultiplied + { + 0, + 0, + 0, + 0, + convert_RGBA_to_RGB, + convert_RGBA_to_ARGB, + convert_RGBA_to_ARGB_PM, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + mask_alpha_converter_RGBx, + mask_alpha_converter_RGBx, + }, // Format_RGBX8888 + { + 0, + 0, + 0, + 0, + convert_RGBA_to_RGB, + convert_RGBA_to_ARGB, + convert_RGBA_to_ARGB_PM, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + mask_alpha_converter_RGBx, +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + 0, + convert_ARGB_to_ARGB_PM, +#else + 0, + 0 +#endif + }, // Format_RGBA8888 + + { + 0, + 0, + 0, + 0, + convert_RGBA_PM_to_RGB, + convert_RGBA_PM_to_ARGB, + convert_RGBA_to_ARGB, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + convert_ARGB_PM_to_RGB, + convert_ARGB_PM_to_ARGB, + 0, +#else + 0, + 0, + 0 +#endif + } // Format_RGBA8888_Premultiplied }; static InPlace_Image_Converter 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 }, // 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 }, // Format_MonoLSB { 0, @@ -3247,6 +3744,9 @@ static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, + 0, + 0, + 0, }, // Format_Indexed8 { 0, @@ -3265,7 +3765,10 @@ static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - }, // Format_ARGB32 + 0, + 0, + 0, + }, // Format_RGB32 { 0, 0, @@ -3283,37 +3786,118 @@ static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, + 0, + convert_ARGB_to_RGBA_inplace, + 0, }, // Format_ARGB32 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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_ARGB_to_RGBA_inplace }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // Format_RGB444 { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - } // Format_ARGB4444_Premultiplied + 0, + 0, + 0, + 0, + 0, + convert_RGBA_to_ARGB_inplace, + convert_RGBA_to_ARGB_inplace, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, // Format_RGBX8888 + { + 0, + 0, + 0, + 0, + 0, + 0, + convert_RGBA_to_ARGB_inplace, + convert_RGBA_to_ARGB_PM_inplace, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, // Format_RGBA8888 + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + convert_RGBA_to_ARGB_inplace, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + } // Format_RGBA8888_Premultiplied }; void qInitImageConversions() @@ -3633,6 +4217,10 @@ QRgb QImage::pixel(int x, int y) const case Format_ARGB32: // Keep old behaviour. case Format_ARGB32_Premultiplied: return reinterpret_cast(s)[x]; + case Format_RGBX8888: + case Format_RGBA8888: // Match ARGB32 behavior. + case Format_RGBA8888_Premultiplied: + return RGBA2ARGB(reinterpret_cast(s)[x]); case Format_RGB16: return qConvertRgb16To32(reinterpret_cast(s)[x]); default: @@ -3716,6 +4304,13 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) case Format_RGB16: ((quint16 *)s)[x] = qConvertRgb32To16(INV_PREMUL(index_or_rgb)); return; + case Format_RGBX8888: + ((uint *)s)[x] = ARGB2RGBA(index_or_rgb | 0xff000000); + return; + case Format_RGBA8888: + case Format_RGBA8888_Premultiplied: + ((uint *)s)[x] = ARGB2RGBA(index_or_rgb); + return; case Format_Invalid: case NImageFormats: Q_ASSERT(false); @@ -3756,6 +4351,11 @@ bool QImage::allGray() const case Format_RGB32: case Format_ARGB32: case Format_ARGB32_Premultiplied: +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + case Format_RGBX8888: + case Format_RGBA8888: + case Format_RGBA8888_Premultiplied: +#endif for (int j = 0; j < d->height; ++j) { const QRgb *b = (const QRgb *)constScanLine(j); for (int i = 0; i < d->width; ++i) { @@ -4330,6 +4930,11 @@ QImage QImage::rgbSwapped() const case Format_RGB32: case Format_ARGB32: case Format_ARGB32_Premultiplied: +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + case Format_RGBX8888: + case Format_RGBA8888: + case Format_RGBA8888_Premultiplied: +#endif res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); for (int i = 0; i < d->height; i++) { @@ -5373,7 +5978,11 @@ QImage QImage::alphaChannel() const } } else { QImage alpha32 = *this; - if (d->format != Format_ARGB32 && d->format != Format_ARGB32_Premultiplied) + bool canSkipConversion = (d->format == Format_ARGB32 || d->format == Format_ARGB32_Premultiplied); +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + canSkipConversion = canSkipConversion || (d->format == Format_RGBA8888 || d->format == Format_RGBA8888_Premultiplied); +#endif + if (!canSkipConversion) alpha32 = convertToFormat(Format_ARGB32); const uchar *src_data = alpha32.d->data; @@ -5408,6 +6017,8 @@ bool QImage::hasAlphaChannel() const || d->format == Format_ARGB8555_Premultiplied || d->format == Format_ARGB6666_Premultiplied || d->format == Format_ARGB4444_Premultiplied + || d->format == Format_RGBA8888 + || d->format == Format_RGBA8888_Premultiplied || (d->has_alpha_clut && (d->format == Format_Indexed8 || d->format == Format_Mono || d->format == Format_MonoLSB))); @@ -5434,6 +6045,7 @@ int QImage::bitPlaneCount() const case QImage::Format_Invalid: break; case QImage::Format_RGB32: + case QImage::Format_RGBX8888: bpc = 24; break; case QImage::Format_RGB666: @@ -5457,9 +6069,11 @@ int QImage::bitPlaneCount() const static QImage smoothScaled(const QImage &source, int w, int h) { QImage src = source; - if (src.format() == QImage::Format_ARGB32) - src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied); - else if (src.depth() < 32) { + bool canSkipConversion = (src.format() == QImage::Format_RGB32 || src.format() == QImage::Format_ARGB32_Premultiplied); +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + canSkipConversion = canSkipConversion || (src.format() == QImage::Format_RGBX8888 || src.format() == QImage::Format_RGBA8888_Premultiplied); +#endif + if (!canSkipConversion) { if (src.hasAlphaChannel()) src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied); else @@ -5480,6 +6094,9 @@ static QImage rotated90(const QImage &image) { case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + case QImage::Format_RGBA8888_Premultiplied: qt_memrotate270(reinterpret_cast(image.bits()), w, h, image.bytesPerLine(), reinterpret_cast(out.bits()), @@ -5539,6 +6156,9 @@ static QImage rotated270(const QImage &image) { case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + case QImage::Format_RGBA8888_Premultiplied: qt_memrotate90(reinterpret_cast(image.bits()), w, h, image.bytesPerLine(), reinterpret_cast(out.bits()), @@ -5684,6 +6304,9 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode case QImage::Format_RGB444: target_format = Format_ARGB4444_Premultiplied; break; + case QImage::Format_RGBX8888: + target_format = Format_RGBA8888_Premultiplied; + break; default: target_format = Format_ARGB32_Premultiplied; break; -- cgit v1.2.3