Make convert_generic_to_rgb64 more generic
This makes it possible to get rid of specialized functions for converting to RGBA64PM, while at the same time making the conversion faster as the painter routines are better optimized. Change-Id: I3e73856b2c1411977450e72af1741aab0ecf537e Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
e6a7b61d27
commit
c961d1a6d2
@ -2062,13 +2062,7 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
|
||||
Image_Converter converter = qimage_converter_map[d->format][format];
|
||||
if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
|
||||
if (highColorPrecision(format) && highColorPrecision(d->format)) {
|
||||
// Convert over RGBA64_Premultiplied
|
||||
if (format == QImage::Format_RGBA64_Premultiplied)
|
||||
converter = convert_generic_to_rgb64;
|
||||
else {
|
||||
Q_ASSERT(d->format != QImage::Format_RGBA64_Premultiplied);
|
||||
return convertToFormat(Format_RGBA64_Premultiplied, flags).convertToFormat(format, flags);
|
||||
}
|
||||
converter = convert_generic_to_rgb64;
|
||||
} else
|
||||
converter = convert_generic;
|
||||
}
|
||||
|
@ -223,18 +223,29 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
||||
|
||||
void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
|
||||
Q_ASSERT(dest->format > QImage::Format_Indexed8);
|
||||
Q_ASSERT(src->format > QImage::Format_Indexed8);
|
||||
QRgba64 buf[BufferSize];
|
||||
QRgba64 *buffer = buf;
|
||||
const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
|
||||
const QPixelLayout *destLayout = &qPixelLayouts[dest->format];
|
||||
const uchar *srcData = src->data;
|
||||
uchar *destData = dest->data;
|
||||
|
||||
const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM;
|
||||
const ConvertAndStorePixelsFunc64 store = qStoreFromRGBA64PM[dest->format];
|
||||
|
||||
for (int y = 0; y < src->height; ++y) {
|
||||
const QRgba64 *ptr = fetch((QRgba64*)destData, srcData, 0, src->width, nullptr, nullptr);
|
||||
if (ptr != (const QRgba64*)destData) {
|
||||
memcpy(destData, ptr, dest->bytes_per_line);
|
||||
int x = 0;
|
||||
while (x < src->width) {
|
||||
int l = src->width - x;
|
||||
if (destLayout->bpp == QPixelLayout::BPP64)
|
||||
buffer = reinterpret_cast<QRgba64 *>(destData) + x;
|
||||
else
|
||||
l = qMin(l, BufferSize);
|
||||
const QRgba64 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
|
||||
store(destData, ptr, x, l, nullptr, nullptr);
|
||||
x += l;
|
||||
}
|
||||
srcData += src->bytes_per_line;
|
||||
destData += dest->bytes_per_line;
|
||||
@ -1204,33 +1215,6 @@ static void convert_RGBA64_to_ARGB32(QImageData *dest, const QImageData *src, Qt
|
||||
}
|
||||
}
|
||||
|
||||
template<bool RGBA>
|
||||
static void convert_RGBA64PM_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
|
||||
Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32);
|
||||
Q_ASSERT(!RGBA || 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 >> 3) - src->width;
|
||||
const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
uint *dest_data = reinterpret_cast<uint *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
QRgba64 s = src_data->unpremultiplied();
|
||||
*dest_data = RGBA ? ARGB2RGBA(s.toArgb32()) : s.toArgb32();
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool RGBA>
|
||||
static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
@ -1240,74 +1224,14 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt
|
||||
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 >> 3) - dest->width;
|
||||
const uint *src_data = reinterpret_cast<const uint *>(src->data);
|
||||
QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
|
||||
const uchar *src_data = src->data;
|
||||
uchar *dest_data = dest->data;
|
||||
const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM;
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const uint *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
if (RGBA)
|
||||
*dest_data = QRgba64::fromArgb32(RGBA2ARGB(*src_data));
|
||||
else
|
||||
*dest_data = QRgba64::fromArgb32(*src_data);
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
template<QtPixelOrder PixelOrder>
|
||||
static void convert_RGBA64PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30);
|
||||
Q_ASSERT(src->width == dest->width);
|
||||
Q_ASSERT(src->height == dest->height);
|
||||
|
||||
const int src_pad = (src->bytes_per_line >> 3) - src->width;
|
||||
const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
uint *dest_data = reinterpret_cast<uint *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = 0xc0000000 | qConvertRgb64ToRgb30<PixelOrder>(src_data->unpremultiplied());
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
template<QtPixelOrder PixelOrder>
|
||||
static void convert_RGBA64PM_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
|
||||
Q_ASSERT(dest->format == QImage::Format_A2RGB30_Premultiplied
|
||||
|| dest->format == QImage::Format_A2BGR30_Premultiplied);
|
||||
Q_ASSERT(src->width == dest->width);
|
||||
Q_ASSERT(src->height == dest->height);
|
||||
|
||||
const int src_pad = (src->bytes_per_line >> 3) - src->width;
|
||||
const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
uint *dest_data = reinterpret_cast<uint *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = qConvertRgb64ToRgb30<PixelOrder>(*src_data);
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
fetch(reinterpret_cast<QRgba64 *>(dest_data), src_data, 0, src->width, nullptr, nullptr);
|
||||
src_data += src->bytes_per_line;;
|
||||
dest_data += dest->bytes_per_line;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2958,7 +2882,6 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
convert_RGBA64PM_to_ARGB32<false>,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@ -2970,12 +2893,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
convert_RGBA64PM_to_ARGB32<true>,
|
||||
0,
|
||||
convert_RGBA64PM_to_RGB30<PixelOrderBGR>,
|
||||
convert_RGBA64PM_to_A2RGB30<PixelOrderBGR>,
|
||||
convert_RGBA64PM_to_RGB30<PixelOrderRGB>,
|
||||
convert_RGBA64PM_to_A2RGB30<PixelOrderRGB>,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
0, 0,
|
||||
convert_RGBA64PM_to_RGBA64<true>,
|
||||
convert_RGBA64PM_to_RGBA64<false>,
|
||||
|
@ -200,6 +200,8 @@ void tst_QImageConversion::convertRgb32_data()
|
||||
QTest::newRow("argb32 -> argb8565pm") << argb32 << QImage::Format_ARGB8565_Premultiplied;
|
||||
QTest::newRow("argb32 -> argb4444pm") << argb32 << QImage::Format_ARGB4444_Premultiplied;
|
||||
QTest::newRow("argb32 -> argb6666pm") << argb32 << QImage::Format_ARGB6666_Premultiplied;
|
||||
QTest::newRow("argb32 -> rgba64") << argb32 << QImage::Format_RGBA64;
|
||||
QTest::newRow("argb32 -> rgba64pm") << argb32 << QImage::Format_RGBA64_Premultiplied;
|
||||
|
||||
QTest::newRow("argb32pm -> rgb16") << argb32pm << QImage::Format_RGB16;
|
||||
QTest::newRow("argb32pm -> rgb32") << argb32pm << QImage::Format_RGB32;
|
||||
@ -239,6 +241,7 @@ void tst_QImageConversion::convertGeneric_data()
|
||||
QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied);
|
||||
QImage rgb666 = rgb32.convertToFormat(QImage::Format_RGB666);
|
||||
QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied);
|
||||
QImage rgba64pm = argb32.convertToFormat(QImage::Format_RGBA64_Premultiplied);
|
||||
|
||||
QTest::newRow("indexed8 -> rgb32") << i8 << QImage::Format_RGB32;
|
||||
QTest::newRow("indexed8 -> argb32") << i8 << QImage::Format_ARGB32;
|
||||
@ -289,6 +292,13 @@ void tst_QImageConversion::convertGeneric_data()
|
||||
QTest::newRow("argb4444pm -> rgba8888pm") << argb4444 << QImage::Format_RGBA8888_Premultiplied;
|
||||
QTest::newRow("argb4444pm -> rgb30") << argb4444 << QImage::Format_RGB30;
|
||||
QTest::newRow("argb4444pm -> a2bgr30") << argb4444 << QImage::Format_A2BGR30_Premultiplied;
|
||||
|
||||
QTest::newRow("rgba64pm -> argb32") << rgba64pm << QImage::Format_ARGB32;
|
||||
QTest::newRow("rgba64pm -> rgbx8888") << rgba64pm << QImage::Format_RGBX8888;
|
||||
QTest::newRow("rgba64pm -> rgba8888pm") << rgba64pm << QImage::Format_RGBA8888_Premultiplied;
|
||||
QTest::newRow("rgba64pm -> rgb30") << rgba64pm << QImage::Format_RGB30;
|
||||
QTest::newRow("rgba64pm -> a2bgr30") << rgba64pm << QImage::Format_A2BGR30_Premultiplied;
|
||||
QTest::newRow("rgba64pm -> rgba64") << rgba64pm << QImage::Format_RGBA64;
|
||||
}
|
||||
|
||||
void tst_QImageConversion::convertGeneric()
|
||||
|
Loading…
Reference in New Issue
Block a user