From 041cbe4b38fcd19212fec2af35140d947a3dac91 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 27 Apr 2015 15:03:09 +0200 Subject: Add missing RGB32 <-> RGB30 convertions Completes the inplace converters so that we can rely on inplace conversions to succede as long as the image depth is the same. Change-Id: Ia1ae34b5de1bc16e87ff5403bdacfcae44a22791 Reviewed-by: Gunnar Sletta --- src/gui/image/qimage_conversions.cpp | 120 +++++++++++++++------ tests/auto/gui/image/qimage/tst_qimage.cpp | 11 +- .../qimageconversion/tst_qimageconversion.cpp | 110 ++++++++++++++----- 3 files changed, 172 insertions(+), 69 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 74ad1127a9..e0ca2c5331 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -497,8 +497,7 @@ static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::Im { Q_ASSERT(src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32); - Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_A2BGR30_Premultiplied - || dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_A2RGB30_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); @@ -520,28 +519,24 @@ static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::Im } template -static void convert_RGB30_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +static bool convert_RGB_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags) { - Q_ASSERT(src->format == QImage::Format_BGR30 || src->format == QImage::Format_RGB30); - Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied); - Q_ASSERT(src->width == dest->width); - Q_ASSERT(src->height == dest->height); + Q_ASSERT(data->format == QImage::Format_RGB32 || data->format == QImage::Format_ARGB32); - 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; + const int pad = (data->bytes_per_line >> 2) - data->width; + QRgb *rgb_data = (QRgb *) data->data; - for (int i = 0; i < src->height; ++i) { - const quint32 *end = src_data + src->width; - while (src_data < end) { - *dest_data = qConvertA2rgb30ToArgb32(*src_data); - ++src_data; - ++dest_data; + for (int i = 0; i < data->height; ++i) { + const QRgb *end = rgb_data + data->width; + while (rgb_data < end) { + *rgb_data = qConvertRgb32ToRgb30(*rgb_data); + ++rgb_data; } - src_data += src_pad; - dest_data += dest_pad; + rgb_data += pad; } + + data->format = (PixelOrder == PixelOrderRGB) ? QImage::Format_RGB30 : QImage::Format_BGR30; + return true; } static inline uint qUnpremultiplyRgb30(uint rgb30) @@ -695,6 +690,51 @@ static bool convert_BGR30_to_A2RGB30_inplace(QImageData *data, Qt::ImageConversi return true; } +template +static void convert_A2RGB30_PM_to_ARGB(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_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 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(qUnpremultiplyRgb30(*src_data)); + ++src_data; + ++dest_data; + } + src_data += src_pad; + dest_data += dest_pad; + } +} + +template +static bool convert_A2RGB30_PM_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied); + + const int pad = (data->bytes_per_line >> 2) - data->width; + uint *rgb_data = (uint *) data->data; + + for (int i = 0; i < data->height; ++i) { + const uint *end = rgb_data + data->width; + while (rgb_data < end) { + *rgb_data = qConvertA2rgb30ToArgb32(qUnpremultiplyRgb30(*rgb_data)); + ++rgb_data; + } + rgb_data += pad; + } + data->format = QImage::Format_ARGB32; + return true; +} + static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); @@ -2007,9 +2047,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, convert_RGB_to_RGB30, - convert_RGB_to_RGB30, - convert_RGB_to_RGB30, + 0, convert_RGB_to_RGB30, + 0, 0, 0 }, // Format_RGB32 @@ -2341,9 +2381,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_RGB30_to_RGB, - convert_RGB30_to_RGB, - convert_RGB30_to_RGB, + 0, + 0, + 0, 0, 0, 0, @@ -2368,7 +2408,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, + convert_A2RGB30_PM_to_ARGB, 0, 0, 0, @@ -2393,9 +2433,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_RGB30_to_RGB, - convert_RGB30_to_RGB, - convert_RGB30_to_RGB, + 0, + 0, + 0, 0, 0, 0, @@ -2420,7 +2460,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - 0, + convert_A2RGB30_PM_to_ARGB, 0, 0, 0, @@ -2536,7 +2576,11 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, 0, 0, 0, 0, 0 + convert_RGB_to_RGB30_inplace, + 0, + convert_RGB_to_RGB30_inplace, + 0, + 0, 0 }, // Format_RGB32 { 0, @@ -2562,7 +2606,11 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_ARGB_to_RGBA_inplace, convert_ARGB_to_RGBA_inplace, 0, - 0, 0, 0, 0, 0, 0 + convert_RGB_to_RGB30_inplace, + 0, + convert_RGB_to_RGB30_inplace, + 0, + 0, 0 }, // Format_ARGB32 { 0, @@ -2584,7 +2632,11 @@ 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 }, // 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 @@ -2716,7 +2768,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, + convert_A2RGB30_PM_to_ARGB_inplace, 0, 0, 0, @@ -2768,7 +2820,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - 0, + convert_A2RGB30_PM_to_ARGB_inplace, 0, 0, 0, diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index fa2aae6658..2931185c8b 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -2664,16 +2664,7 @@ void tst_QImage::inplaceRgbConversion() QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16); } } - bool expectInplace = image.depth() == imageConverted.depth(); - // RGB30 <-> RGB32 have a few direct conversions without inplace counterparts. - if (format >= QImage::Format_BGR30 && format <= QImage::Format_A2RGB30_Premultiplied - && dest_format >= QImage::Format_RGB32 && dest_format <= QImage::Format_ARGB32_Premultiplied) - expectInplace = false; - if (dest_format >= QImage::Format_BGR30 && dest_format <= QImage::Format_A2RGB30_Premultiplied - && format >= QImage::Format_RGB32 && format <= QImage::Format_ARGB32_Premultiplied) - expectInplace = false; - - if (expectInplace) + if (image.depth() == imageConverted.depth()) QCOMPARE(imageConverted.constScanLine(0), originalPtr); { diff --git a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp index 2d4a453b58..bca5868c3f 100644 --- a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp +++ b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp @@ -49,6 +49,12 @@ private slots: void convertRgb32ToRgb888_data(); void convertRgb32ToRgb888(); + void convertRgb16_data(); + void convertRgb16(); + + void convertRgb32_data(); + void convertRgb32(); + void convertGeneric_data(); void convertGeneric(); @@ -146,55 +152,96 @@ void tst_QImageConversion::convertRgb32ToRgb888() } } - -void tst_QImageConversion::convertGeneric_data() +void tst_QImageConversion::convertRgb16_data() { QTest::addColumn("inputImage"); QTest::addColumn("outputFormat"); QImage rgb16 = generateImageRgb16(1000, 1000); + + QTest::newRow("rgb32") << rgb16 << QImage::Format_RGB32; + QTest::newRow("rgb888") << rgb16 << QImage::Format_RGB888; + QTest::newRow("rgb666") << rgb16 << QImage::Format_RGB666; + QTest::newRow("rgb555") << rgb16 << QImage::Format_RGB555; +} + +void tst_QImageConversion::convertRgb16() +{ + QFETCH(QImage, inputImage); + QFETCH(QImage::Format, outputFormat); + + QBENCHMARK { + QImage output = inputImage.convertToFormat(outputFormat); + output.constBits(); + } +} + +void tst_QImageConversion::convertRgb32_data() +{ + QTest::addColumn("inputImage"); + QTest::addColumn("outputFormat"); QImage rgb32 = generateImageRgb32(1000, 1000); QImage argb32 = generateImageArgb32(1000, 1000); QImage argb32pm = argb32.convertToFormat(QImage::Format_ARGB32_Premultiplied); - QImage rgba32 = argb32.convertToFormat(QImage::Format_RGBA8888); - QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied); - - QTest::newRow("rgb16 -> rgb32") << rgb16 << QImage::Format_RGB32; - QTest::newRow("rgb16 -> rgb888") << rgb16 << QImage::Format_RGB888; - QTest::newRow("rgb16 -> rgb666") << rgb16 << QImage::Format_RGB666; - QTest::newRow("rgb16 -> rgb555") << rgb16 << QImage::Format_RGB555; QTest::newRow("rgb32 -> rgb16") << rgb32 << QImage::Format_RGB16; - QTest::newRow("rgb32 -> rgb888") << rgb32 << QImage::Format_RGB888; - QTest::newRow("rgb32 -> rgb666") << rgb32 << QImage::Format_RGB666; - QTest::newRow("rgb32 -> rgb555") << rgb32 << QImage::Format_RGB555; QTest::newRow("rgb32 -> argb32") << rgb32 << QImage::Format_ARGB32; QTest::newRow("rgb32 -> argb32pm") << rgb32 << QImage::Format_ARGB32_Premultiplied; QTest::newRow("rgb32 -> rgbx8888") << rgb32 << QImage::Format_RGBX8888; QTest::newRow("rgb32 -> rgba8888") << rgb32 << QImage::Format_RGBA8888; QTest::newRow("rgb32 -> rgba8888pm") << rgb32 << QImage::Format_RGBA8888_Premultiplied; QTest::newRow("rgb32 -> rgb30") << rgb32 << QImage::Format_RGB30; - QTest::newRow("rgb32 -> bgr30") << rgb32 << QImage::Format_BGR30; + QTest::newRow("rgb32 -> a2bgr30") << rgb32 << QImage::Format_A2BGR30_Premultiplied; + QTest::newRow("rgb32 -> rgb888") << rgb32 << QImage::Format_RGB888; + QTest::newRow("rgb32 -> rgb666") << rgb32 << QImage::Format_RGB666; + QTest::newRow("rgb32 -> rgb555") << rgb32 << QImage::Format_RGB555; - QTest::newRow("argb32 -> rgb888") << argb32 << QImage::Format_RGB888; - QTest::newRow("argb32 -> rgb666") << argb32 << QImage::Format_RGB666; - QTest::newRow("argb32 -> argb8565pm") << argb32 << QImage::Format_ARGB8565_Premultiplied; - QTest::newRow("argb32 -> argb4444pm") << argb32 << QImage::Format_ARGB4444_Premultiplied; + QTest::newRow("argb32 -> rgb16") << argb32 << QImage::Format_RGB16; QTest::newRow("argb32 -> rgb32") << argb32 << QImage::Format_RGB32; QTest::newRow("argb32 -> argb32pm") << argb32 << QImage::Format_ARGB32_Premultiplied; QTest::newRow("argb32 -> rgbx8888") << argb32 << QImage::Format_RGBX8888; QTest::newRow("argb32 -> rgba8888") << argb32 << QImage::Format_RGBA8888; QTest::newRow("argb32 -> rgba8888pm") << argb32 << QImage::Format_RGBA8888_Premultiplied; QTest::newRow("argb32 -> rgb30") << argb32 << QImage::Format_RGB30; - QTest::newRow("argb32 -> a2rgb30") << argb32 << QImage::Format_A2RGB30_Premultiplied; + QTest::newRow("argb32 -> a2bgr30") << argb32 << QImage::Format_A2BGR30_Premultiplied; + QTest::newRow("argb32 -> rgb888") << argb32 << QImage::Format_RGB888; + QTest::newRow("argb32 -> rgb666") << argb32 << QImage::Format_RGB666; + QTest::newRow("argb32 -> argb8565pm") << argb32 << QImage::Format_ARGB8565_Premultiplied; + QTest::newRow("argb32 -> argb4444pm") << argb32 << QImage::Format_ARGB4444_Premultiplied; - QTest::newRow("argb32pm -> argb4444pm") << argb32pm << QImage::Format_ARGB4444_Premultiplied; + QTest::newRow("argb32pm -> rgb16") << argb32pm << QImage::Format_RGB16; QTest::newRow("argb32pm -> rgb32") << argb32pm << QImage::Format_RGB32; QTest::newRow("argb32pm -> argb32") << argb32pm << QImage::Format_ARGB32; QTest::newRow("argb32pm -> rgbx8888") << argb32pm << QImage::Format_RGBX8888; QTest::newRow("argb32pm -> rgba8888") << argb32pm << QImage::Format_RGBA8888; QTest::newRow("argb32pm -> rgba8888pm") << argb32pm << QImage::Format_RGBA8888_Premultiplied; QTest::newRow("argb32pm -> rgb30") << argb32pm << QImage::Format_RGB30; - QTest::newRow("argb32pm -> a2rgb30") << argb32pm << QImage::Format_A2RGB30_Premultiplied; + QTest::newRow("argb32pm -> a2bgr30") << argb32pm << QImage::Format_A2BGR30_Premultiplied; + QTest::newRow("argb32pm -> rgb888") << argb32pm << QImage::Format_RGB888; + QTest::newRow("argb32pm -> rgb666") << argb32pm << QImage::Format_RGB666; + QTest::newRow("argb32pm -> argb8565pm") << argb32pm << QImage::Format_ARGB8565_Premultiplied; + QTest::newRow("argb32pm -> argb4444pm") << argb32pm << QImage::Format_ARGB4444_Premultiplied; +} + +void tst_QImageConversion::convertRgb32() +{ + QFETCH(QImage, inputImage); + QFETCH(QImage::Format, outputFormat); + + QBENCHMARK { + QImage output = inputImage.convertToFormat(outputFormat); + output.constBits(); + } +} + +void tst_QImageConversion::convertGeneric_data() +{ + QTest::addColumn("inputImage"); + QTest::addColumn("outputFormat"); + QImage rgb32 = generateImageRgb32(1000, 1000); + QImage argb32 = generateImageArgb32(1000, 1000); + QImage rgba32 = argb32.convertToFormat(QImage::Format_RGBA8888); + QImage bgr30 = rgb32.convertToFormat(QImage::Format_BGR30); + QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied); QTest::newRow("rgba8888 -> rgb32") << rgba32 << QImage::Format_RGB32; QTest::newRow("rgba8888 -> argb32") << rgba32 << QImage::Format_ARGB32; @@ -202,7 +249,16 @@ void tst_QImageConversion::convertGeneric_data() QTest::newRow("rgba8888 -> rgbx8888") << rgba32 << QImage::Format_RGBX8888; QTest::newRow("rgba8888 -> rgba8888pm") << rgba32 << QImage::Format_RGBA8888_Premultiplied; QTest::newRow("rgba8888 -> rgb30") << rgba32 << QImage::Format_RGB30; - QTest::newRow("rgba8888 -> a2rgb30") << rgba32 << QImage::Format_A2RGB30_Premultiplied; + QTest::newRow("rgba8888 -> a2bgr30") << rgba32 << QImage::Format_A2BGR30_Premultiplied; + + QTest::newRow("bgr30 -> rgb32") << bgr30 << QImage::Format_RGB32; + QTest::newRow("bgr30 -> argb32") << bgr30 << QImage::Format_ARGB32; + QTest::newRow("bgr30 -> argb32pm") << bgr30 << QImage::Format_ARGB32_Premultiplied; + QTest::newRow("bgr30 -> rgbx8888") << bgr30 << QImage::Format_RGBX8888; + QTest::newRow("bgr30 -> rgba8888") << bgr30 << QImage::Format_RGBA8888; + QTest::newRow("bgr30 -> rgba8888pm") << bgr30 << QImage::Format_RGBA8888_Premultiplied; + QTest::newRow("bgr30 -> rgb30") << bgr30 << QImage::Format_RGB30; + QTest::newRow("bgr30 -> a2bgr30") << bgr30 << QImage::Format_A2BGR30_Premultiplied; QTest::newRow("a2rgb30 -> rgb32") << a2rgb30 << QImage::Format_RGB32; QTest::newRow("a2rgb30 -> argb32") << a2rgb30 << QImage::Format_ARGB32; @@ -210,7 +266,9 @@ void tst_QImageConversion::convertGeneric_data() QTest::newRow("a2rgb30 -> rgbx8888") << a2rgb30 << QImage::Format_RGBX8888; QTest::newRow("a2rgb30 -> rgba8888") << a2rgb30 << QImage::Format_RGBA8888; QTest::newRow("a2rgb30 -> rgba8888pm") << a2rgb30 << QImage::Format_RGBA8888_Premultiplied; + QTest::newRow("a2rgb30 -> rgb30") << a2rgb30 << QImage::Format_RGB30; QTest::newRow("a2rgb30 -> bgr30") << a2rgb30 << QImage::Format_BGR30; + QTest::newRow("a2rgb30 -> a2bgr30") << a2rgb30 << QImage::Format_A2BGR30_Premultiplied; } void tst_QImageConversion::convertGeneric() @@ -316,12 +374,14 @@ QImage tst_QImageConversion::generateImageRgb32(int width, int height) QImage tst_QImageConversion::generateImageArgb32(int width, int height) { QImage image(width, height, QImage::Format_ARGB32); - const int byteWidth = width * 4; for (int y = 0; y < image.height(); ++y) { - uchar *scanline = image.scanLine(y); - for (int x = 0; x < byteWidth; ++x) - scanline[x] = x ^ y; + QRgb *scanline = (QRgb*)image.scanLine(y); + for (int x = 0; x < width; ++x) { + int alpha = (x ^ y) & 0x1ff; + alpha = qMax(0, qMin(alpha - 128, 255)); + scanline[x] = qRgba(x, y, x ^ y, alpha); + } } return image; } -- cgit v1.2.3