summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-02-05 16:09:00 +0100
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-02-13 13:20:52 +0000
commit22b5c39e8e0f4d8cb8a2b2d661e0451e01b75929 (patch)
tree554d84acb212c909154da63063ada27c1d6fbbd5 /src/gui/image
parente9f30968ad777bc2d7fcd85adc4e9d38d70398d8 (diff)
Optimize generic conversion and remove now obsolete direct conversions
There are many direct QImage conversions that doesn't need to be direct but only are because they are faster than the generic conversion. This patch optimizes the generic conversions and then removes all the direct conversions that are now no faster than the generic. Change-Id: I3dc5f44cc7f6358fd66420e9974eebaf2c7ca59c Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/qimage.cpp4
-rw-r--r--src/gui/image/qimage_conversions.cpp537
-rw-r--r--src/gui/image/qimage_sse2.cpp7
3 files changed, 145 insertions, 403 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 86e739dd4f..57e7c9a7ab 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -4595,7 +4595,9 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
InPlace_Image_Converter converter = *converterPtr;
if (converter)
return converter(this, flags);
- else if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8)
+ else if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8 && !qimage_converter_map[format][newFormat])
+ // Convert inplace generic, but only if there are no direct converters,
+ // any direct ones are probably better even if not inplace.
return convert_generic_inplace(this, newFormat, flags);
else
return false;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index ff729981c0..a4c02bbbbe 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include <private/qdrawhelper_p.h>
+#include <private/qdrawingprimitive_sse2_p.h>
#include <private/qguiapplication_p.h>
#include <private/qsimd_p.h>
@@ -100,9 +101,37 @@ void qGamma_correct_back_to_linear_cs(QImage *image)
Internal routines for converting image depth.
*****************************************************************************/
-// Cannot be used with indexed formats.
+// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion.
+static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = 0xff000000 | qUnpremultiply(src[i]);
+ return buffer;
+}
+
+#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
+QT_FUNCTION_TARGET(SSE4_1)
+static const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]);
+ return buffer;
+}
+#endif
+
+static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = 0xff000000 |src[i];
+ return buffer;
+}
+
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
+ // Cannot be used with indexed formats.
Q_ASSERT(dest->format > QImage::Format_Indexed8);
Q_ASSERT(src->format > QImage::Format_Indexed8);
const int buffer_size = 2048;
@@ -112,16 +141,33 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
const uchar *srcData = src->data;
uchar *destData = dest->data;
- FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
- StorePixelsFunc store = qStorePixels[destLayout->bpp];
+ const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
+ const StorePixelsFunc store = qStorePixels[destLayout->bpp];
+ ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
+ ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM;
+ if (srcLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
+ convertFromARGB32PM = destLayout->convertFromRGB32;
+ } else {
+ if (src->format == QImage::Format_RGB32)
+ convertToARGB32PM = convertRGB32ToARGB32PM;
+ if (dest->format == QImage::Format_RGB32) {
+#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
+ if (qCpuHasFeature(SSE4_1))
+ convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
+ else
+#endif
+ convertFromARGB32PM = convertRGB32FromARGB32PM;
+ }
+ }
for (int y = 0; y < src->height; ++y) {
int x = 0;
while (x < src->width) {
int l = qMin(src->width - x, buffer_size);
const uint *ptr = fetch(buffer, srcData, x, l);
- ptr = srcLayout->convertToARGB32PM(buffer, ptr, l, srcLayout, 0);
- ptr = destLayout->convertFromARGB32PM(buffer, ptr, l, destLayout, 0);
+ ptr = convertToARGB32PM(buffer, ptr, l, srcLayout, 0);
+ ptr = convertFromARGB32PM(buffer, ptr, l, destLayout, 0);
store(destData, ptr, x, l);
x += l;
}
@@ -130,9 +176,9 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
}
}
-// Cannot be used with indexed formats or between formats with different pixel depths.
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags)
{
+ // Cannot be used with indexed formats or between formats with different pixel depths.
Q_ASSERT(dst_format > QImage::Format_Indexed8);
Q_ASSERT(data->format > QImage::Format_Indexed8);
if (data->depth != qt_depthForFormat(dst_format))
@@ -142,19 +188,35 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
uint buffer[buffer_size];
const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
-
uchar *srcData = data->data;
- FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
- StorePixelsFunc store = qStorePixels[destLayout->bpp];
+ const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
+ const StorePixelsFunc store = qStorePixels[destLayout->bpp];
+ ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
+ ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM;
+ if (srcLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
+ convertFromARGB32PM = destLayout->convertFromRGB32;
+ } else {
+ if (data->format == QImage::Format_RGB32)
+ convertToARGB32PM = convertRGB32ToARGB32PM;
+ if (dst_format == QImage::Format_RGB32) {
+#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
+ if (qCpuHasFeature(SSE4_1))
+ convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
+ else
+#endif
+ convertFromARGB32PM = convertRGB32FromARGB32PM;
+ }
+ }
for (int y = 0; y < data->height; ++y) {
int x = 0;
while (x < data->width) {
int l = qMin(data->width - x, buffer_size);
const uint *ptr = fetch(buffer, srcData, x, l);
- ptr = srcLayout->convertToARGB32PM(buffer, ptr, l, srcLayout, 0);
- ptr = destLayout->convertFromARGB32PM(buffer, ptr, l, destLayout, 0);
+ ptr = convertToARGB32PM(buffer, ptr, l, srcLayout, 0);
+ ptr = convertFromARGB32PM(buffer, ptr, l, destLayout, 0);
// The conversions might be passthrough and not use the buffer, in that case we are already done.
if (srcData != (const uchar*)ptr)
store(srcData, ptr, x, l);
@@ -230,27 +292,6 @@ static void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src
extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags);
-#ifndef __SSE2__
-static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
-{
- Q_ASSERT(data->format == QImage::Format_ARGB32);
-
- 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 = qPremultiply(*rgb_data);
- ++rgb_data;
- }
- rgb_data += pad;
- }
- data->format = QImage::Format_ARGB32_Premultiplied;
- return true;
-}
-#endif
-
static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_ARGB32);
@@ -321,39 +362,6 @@ static bool convert_ARGB_to_RGBA_inplace(QImageData *data, Qt::ImageConversionFl
return true;
}
-static inline 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(qPremultiply(*src_data));
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) && !defined(__SSE4_1__)
-QT_FUNCTION_TARGET(SSE4_1)
-static void convert_ARGB_to_RGBA_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags)
-{
- // Twice as fast autovectorized due to SSE4.1 PMULLD instructions.
- convert_ARGB_to_RGBA_PM(dest, src, flags);
-}
-#endif
-
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);
@@ -378,70 +386,24 @@ static void convert_RGBA_to_ARGB(QImageData *dest, const QImageData *src, Qt::Im
}
}
+template<QImage::Format DestFormat>
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;
+ Q_CONSTEXPR uint mask = (DestFormat == QImage::Format_RGB32) ? 0xff000000 : 0;
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 = qPremultiply(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 = qPremultiply(RGBA2ARGB(*rgb_data));
+ *rgb_data = mask | RGBA2ARGB(*rgb_data);
++rgb_data;
}
rgb_data += pad;
}
- data->format = QImage::Format_ARGB32_Premultiplied;
+ data->format = DestFormat;
return true;
}
@@ -497,106 +459,6 @@ static void convert_RGB30_to_RGB(QImageData *dest, const QImageData *src, Qt::Im
}
}
-template<QtPixelOrder PixelOrder>
-static void convert_A2RGB30_PM_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_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 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 = 0xff000000 | qUnpremultiply(qConvertA2rgb30ToArgb32<PixelOrder>(*src_data));
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-template<QtPixelOrder PixelOrder>
-static void convert_ARGB_PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_RGB30);
- 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 = qConvertRgb32ToRgb30<PixelOrder>(qUnpremultiply(*src_data));
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-template<QtPixelOrder PixelOrder>
-static void convert_ARGB_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_A2BGR30_Premultiplied || dest->format == QImage::Format_A2RGB30_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 = qConvertArgb32ToA2rgb30<PixelOrder>(*src_data);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-template<QtPixelOrder PixelOrder>
-static void convert_A2RGB30_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_A2BGR30_Premultiplied || src->format == QImage::Format_A2RGB30_Premultiplied);
- 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 = qConvertA2rgb30ToArgb32<PixelOrder>(*src_data);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
static inline uint qUnpremultiplyRgb30(uint rgb30)
{
const uint a = rgb30 >> 30;
@@ -916,7 +778,7 @@ 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)
+static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src)
{
Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied || src->format == QImage::Format_RGBA8888_Premultiplied);
Q_ASSERT(dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_RGBA8888);
@@ -940,78 +802,6 @@ 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 | qUnpremultiply(*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 | qUnpremultiply(*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(qUnpremultiply(*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);
@@ -1036,78 +826,6 @@ static void convert_RGBA_to_RGB(QImageData *dest, const QImageData *src, Qt::Ima
}
}
-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;
- 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 = qUnpremultiply(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 | qUnpremultiply(RGBA2ARGB(*src_data));
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
static void swap_bit_order(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_Mono || src->format == QImage::Format_MonoLSB);
@@ -1151,6 +869,26 @@ 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);
+
+ 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 | 0xff000000;
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+ data->format = DestFormat;
+ return true;
+}
+
static void mask_alpha_converter_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags)
{
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@@ -1475,7 +1213,7 @@ static void convert_X_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageC
static void convert_ARGB_PM_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
{
QScopedPointer<QImageData> tmp(QImageData::create(QSize(src->width, src->height), QImage::Format_ARGB32));
- convert_ARGB_PM_to_ARGB(tmp.data(), src, flags);
+ convert_ARGB_PM_to_ARGB(tmp.data(), src);
dither_to_Mono(dst, tmp.data(), flags, false);
}
@@ -1755,7 +1493,7 @@ static void convert_RGB_to_Indexed8(QImageData *dst, const QImageData *src, Qt::
static void convert_ARGB_PM_to_Indexed8(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags)
{
QScopedPointer<QImageData> tmp(QImageData::create(QSize(src->width, src->height), QImage::Format_ARGB32));
- convert_ARGB_PM_to_ARGB(tmp.data(), src, flags);
+ convert_ARGB_PM_to_ARGB(tmp.data(), src);
convert_RGB_to_Indexed8(dst, tmp.data(), flags);
}
@@ -2113,9 +1851,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_RGB_to_RGBA,
- convert_RGB_to_RGBA,
- convert_RGB_to_RGBA,
+ 0,
+ 0,
+ 0,
convert_RGB_to_RGB30<PixelOrderBGR>,
convert_RGB_to_RGB30<PixelOrderBGR>,
convert_RGB_to_RGB30<PixelOrderRGB>,
@@ -2142,7 +1880,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
convert_ARGB_to_RGBx,
convert_ARGB_to_RGBA,
- convert_ARGB_to_RGBA_PM,
+ 0,
convert_RGB_to_RGB30<PixelOrderBGR>,
0,
convert_RGB_to_RGB30<PixelOrderRGB>,
@@ -2155,8 +1893,6 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_PM_to_Mono,
convert_ARGB_PM_to_Mono,
convert_ARGB_PM_to_Indexed8,
- convert_ARGB_PM_to_RGB,
- convert_ARGB_PM_to_ARGB,
0,
0,
0,
@@ -2167,13 +1903,15 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_ARGB_PM_to_RGBx,
- convert_ARGB_PM_to_RGBA,
+ 0,
+ 0,
+ 0,
+ 0,
convert_ARGB_to_RGBA,
- convert_ARGB_PM_to_RGB30<PixelOrderBGR>,
- convert_ARGB_to_A2RGB30<PixelOrderBGR>,
- convert_ARGB_PM_to_RGB30<PixelOrderRGB>,
- convert_ARGB_to_A2RGB30<PixelOrderRGB>,
+ 0,
+ 0,
+ 0,
+ 0,
0, 0
}, // Format_ARGB32_Premultiplied
@@ -2402,7 +2140,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
convert_RGBA_to_RGB,
convert_RGBA_to_ARGB,
- convert_RGBA_to_ARGB_PM,
+ 0,
0,
0,
0,
@@ -2428,11 +2166,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_RGBA_PM_to_RGB,
- convert_RGBA_PM_to_ARGB,
- convert_RGBA_to_ARGB,
0,
0,
+ convert_RGBA_to_ARGB,
0,
0,
0,
@@ -2440,15 +2176,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
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
0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
@@ -2483,9 +2214,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_A2RGB30_PM_to_RGB<PixelOrderBGR>,
0,
- convert_A2RGB30_to_ARGB<PixelOrderBGR>,
+ 0,
+ 0,
0,
0,
0,
@@ -2535,9 +2266,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_A2RGB30_PM_to_RGB<PixelOrderRGB>,
0,
- convert_A2RGB30_to_ARGB<PixelOrderRGB>,
+ 0,
+ 0,
0,
0,
0,
@@ -2639,8 +2370,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0,
- 0,
+ mask_alpha_converter_inplace<QImage::Format_ARGB32>,
+ mask_alpha_converter_inplace<QImage::Format_ARGB32_Premultiplied>,
convert_RGB_to_RGB16_inplace,
0,
0,
@@ -2652,19 +2383,20 @@ 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
}, // Format_RGB32
{
0,
0,
0,
0,
- 0,
+ mask_alpha_converter_inplace<QImage::Format_RGB32>,
0,
#ifdef __SSE2__
convert_ARGB_to_ARGB_PM_inplace_sse2,
#else
- convert_ARGB_to_ARGB_PM_inplace,
+ 0,
#endif
0,
0,
@@ -2677,7 +2409,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
convert_ARGB_to_RGBA_inplace,
- 0, 0, 0, 0, 0, 0, 0
+ 0,
+ 0, 0, 0, 0, 0, 0
}, // Format_ARGB32
{
0,
@@ -2733,9 +2466,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_RGBA_to_ARGB_inplace,
- convert_RGBA_to_ARGB_inplace,
- convert_RGBA_to_ARGB_inplace,
+ convert_RGBA_to_ARGB_inplace<QImage::Format_RGB32>,
+ convert_RGBA_to_ARGB_inplace<QImage::Format_ARGB32>,
+ convert_RGBA_to_ARGB_inplace<QImage::Format_ARGB32_Premultiplied>,
0,
0,
0,
@@ -2755,9 +2488,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ convert_RGBA_to_ARGB_inplace<QImage::Format_RGB32>,
+ convert_RGBA_to_ARGB_inplace<QImage::Format_ARGB32>,
0,
- convert_RGBA_to_ARGB_inplace,
- convert_RGBA_to_ARGB_PM_inplace,
0,
0,
0,
@@ -2768,8 +2501,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__
0,
+ convert_ARGB_to_ARGB_PM_inplace_sse2,
+#else
0,
+ 0,
+#endif
0, 0, 0, 0, 0, 0
}, // Format_RGBA8888
{
@@ -2779,7 +2517,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_RGBA_to_ARGB_inplace,
+ convert_RGBA_to_ARGB_inplace<QImage::Format_ARGB32_Premultiplied>,
0,
0,
0,
@@ -2967,7 +2705,6 @@ void qInitImageConversions()
if (qCpuHasFeature(SSE4_1)) {
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_sse4;
qimage_converter_map[QImage::Format_RGBA8888][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_ARGB_PM_sse4;
- qimage_converter_map[QImage::Format_ARGB32][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_RGBA_PM_sse4;
}
#endif
diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp
index 6424e67cfc..4a719d4c26 100644
--- a/src/gui/image/qimage_sse2.cpp
+++ b/src/gui/image/qimage_sse2.cpp
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags)
{
- Q_ASSERT(data->format == QImage::Format_ARGB32);
+ Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888);
// extra pixels on each line
const int spare = data->width & 3;
@@ -92,7 +92,10 @@ bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionF
d = reinterpret_cast<__m128i*>(p+pad);
}
- data->format = QImage::Format_ARGB32_Premultiplied;
+ if (data->format == QImage::Format_ARGB32)
+ data->format = QImage::Format_ARGB32_Premultiplied;
+ else
+ data->format = QImage::Format_RGBA8888_Premultiplied;
return true;
}