From ba1cf5dae397031730fb77321db1807937e81617 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Fri, 13 Jan 2012 12:07:11 +0100 Subject: Removed image format specific template functions in raster engine. Simplified the raster engine by treating image formats in a more generic way and removed some unused code. Change-Id: Ib3979a1a6e3e6f17c5002248545779ec36fff7c9 Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 511 ++++++++++++++++++----------------------------- 1 file changed, 189 insertions(+), 322 deletions(-) (limited to 'src/gui/image/qimage.cpp') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 07af19d06a..5b23dbf4dc 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -74,30 +74,6 @@ static inline bool isLocked(QImageData *data) return data != 0 && data->is_locked; } -static inline bool checkPixelSize(const QImage::Format format) -{ - switch (format) { - case QImage::Format_ARGB8565_Premultiplied: - return (sizeof(qargb8565) == 3); - case QImage::Format_RGB666: - return (sizeof(qrgb666) == 3); - case QImage::Format_ARGB6666_Premultiplied: - return (sizeof(qargb6666) == 3); - case QImage::Format_RGB555: - return (sizeof(qrgb555) == 2); - case QImage::Format_ARGB8555_Premultiplied: - return (sizeof(qargb8555) == 3); - case QImage::Format_RGB888: - return (sizeof(qrgb888) == 3); - case QImage::Format_RGB444: - return (sizeof(qrgb444) == 2); - case QImage::Format_ARGB4444_Premultiplied: - return (sizeof(qargb4444) == 2); - default: - return true; - } -} - #if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001) #pragma message disable narrowptr #endif @@ -141,12 +117,6 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu if (!size.isValid() || numColors < 0 || format == QImage::Format_Invalid) return 0; // invalid parameter(s) - if (!checkPixelSize(format)) { - qWarning("QImageData::create(): Invalid pixel size for format %i", - format); - return 0; - } - uint width = size.width(); uint height = size.height(); uint depth = qt_depthForFormat(format); @@ -793,12 +763,6 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm if (format == QImage::Format_Invalid) return d; - if (!checkPixelSize(format)) { - qWarning("QImageData::create(): Invalid pixel size for format %i", - format); - return 0; - } - const int depth = qt_depthForFormat(format); const int calc_bytes_per_line = ((width * depth + 31)/32) * 4; const int min_bytes_per_line = (width * depth + 7)/8; @@ -1708,9 +1672,8 @@ void QImage::fill(const QColor &color) pixel = PREMUL(pixel); fill((uint) pixel); - } else if (d->depth == 16 && d->format == QImage::Format_RGB16) { - qrgb565 p(color.rgba()); - fill((uint) p.rawValue()); + } else if (d->format == QImage::Format_RGB16) { + fill((uint) qConvertRgb32To16(color.rgba())); } else if (d->depth == 1) { if (color == Qt::color1) @@ -2025,12 +1988,12 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers quint16 colorTableRGB16[256]; if (data->colortable.isEmpty()) { for (int i = 0; i < 256; ++i) - colorTableRGB16[i] = qt_colorConvert(qRgb(i, i, i), 0); + colorTableRGB16[i] = qConvertRgb32To16(qRgb(i, i, i)); } else { // 1) convert the existing colors to RGB16 const int tableSize = data->colortable.size(); for (int i = 0; i < tableSize; ++i) - colorTableRGB16[i] = qt_colorConvert(data->colortable.at(i), 0); + colorTableRGB16[i] = qConvertRgb32To16(data->colortable.at(i)); data->colortable = QVector(); // 2) fill the rest of the table in case src_data > colortable.size() @@ -2068,7 +2031,8 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl quint16 *dst_data = (quint16 *) data->data; for (int i = 0; i < data->height; ++i) { - qt_memconvert(dst_data, src_data, data->width); + for (int j = 0; j < data->width; ++j) + dst_data[j] = qConvertRgb32To16(src_data[j]); src_data = (quint32 *) (((char*)src_data) + src_bytes_per_line); dst_data = (quint16 *) (((char*)dst_data) + dst_bytes_per_line); } @@ -2878,60 +2842,33 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt } } -#define CONVERT_DECL(DST, SRC) \ - static void convert_##SRC##_to_##DST(QImageData *dest, \ - const QImageData *src, \ - Qt::ImageConversionFlags) \ - { \ - qt_rectconvert(reinterpret_cast(dest->data), \ - reinterpret_cast(src->data), \ - 0, 0, src->width, src->height, \ - dest->bytes_per_line, src->bytes_per_line); \ +// Cannot be used with indexed formats. +static void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + const int buffer_size = 2048; + uint buffer[buffer_size]; + const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; + const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; + const uchar *srcData = src->data; + uchar *destData = dest->data; + + FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; + StorePixelsFunc store = qStorePixels[destLayout->bpp]; + + 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); + store(destData, ptr, x, l); + x += l; + } + srcData += src->bytes_per_line; + destData += dest->bytes_per_line; } - -CONVERT_DECL(quint32, quint16) -CONVERT_DECL(quint16, quint32) -CONVERT_DECL(quint32, qargb8565) -CONVERT_DECL(qargb8565, quint32) -CONVERT_DECL(quint32, qrgb555) -CONVERT_DECL(qrgb666, quint32) -CONVERT_DECL(quint32, qrgb666) -CONVERT_DECL(qargb6666, quint32) -CONVERT_DECL(quint32, qargb6666) -CONVERT_DECL(qrgb555, quint32) -#if (defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16)) -CONVERT_DECL(quint16, qrgb555) -CONVERT_DECL(qrgb555, quint16) -#endif -CONVERT_DECL(quint32, qrgb888) -CONVERT_DECL(qrgb888, quint32) -CONVERT_DECL(quint32, qargb8555) -CONVERT_DECL(qargb8555, quint32) -CONVERT_DECL(quint32, qrgb444) -CONVERT_DECL(qrgb444, quint32) -CONVERT_DECL(quint32, qargb4444) -CONVERT_DECL(qargb4444, quint32) -#undef CONVERT_DECL -#define CONVERT_PTR(DST, SRC) convert_##SRC##_to_##DST - -/* - Format_Invalid, - Format_Mono, - Format_MonoLSB, - Format_Indexed8, - Format_RGB32, - Format_ARGB32, - Format_ARGB32_Premultiplied, - Format_RGB16, - Format_ARGB8565_Premultiplied, - Format_RGB666, - Format_ARGB6666_Premultiplied, - Format_RGB555, - Format_ARGB8555_Premultiplied, - Format_RGB888 - Format_RGB444 - Format_ARGB4444_Premultiplied -*/ +} // first index source, second dest @@ -3005,15 +2942,15 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, mask_alpha_converter, mask_alpha_converter, - CONVERT_PTR(quint16, quint32), - CONVERT_PTR(qargb8565, quint32), - CONVERT_PTR(qrgb666, quint32), - CONVERT_PTR(qargb6666, quint32), - CONVERT_PTR(qrgb555, quint32), - CONVERT_PTR(qargb8555, quint32), - CONVERT_PTR(qrgb888, quint32), - CONVERT_PTR(qrgb444, quint32), - CONVERT_PTR(qargb4444, quint32) + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic }, // Format_RGB32 { @@ -3024,15 +2961,15 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat mask_alpha_converter, 0, convert_ARGB_to_ARGB_PM, - CONVERT_PTR(quint16, quint32), - CONVERT_PTR(qargb8565, quint32), - CONVERT_PTR(qrgb666, quint32), - CONVERT_PTR(qargb6666, quint32), - CONVERT_PTR(qrgb555, quint32), - CONVERT_PTR(qargb8555, quint32), - CONVERT_PTR(qrgb888, quint32), - CONVERT_PTR(qrgb444, quint32), - CONVERT_PTR(qargb4444, quint32) + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic }, // Format_ARGB32 { @@ -3059,15 +2996,15 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, quint16), - CONVERT_PTR(quint32, quint16), - CONVERT_PTR(quint32, quint16), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, 0, #if defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16) - CONVERT_PTR(qrgb555, quint16), + convert_generic, #else 0, #endif @@ -3082,9 +3019,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb8565), - CONVERT_PTR(quint32, qargb8565), - CONVERT_PTR(quint32, qargb8565), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3101,9 +3038,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb666), - CONVERT_PTR(quint32, qrgb666), - CONVERT_PTR(quint32, qrgb666), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3120,9 +3057,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb6666), - CONVERT_PTR(quint32, qargb6666), - CONVERT_PTR(quint32, qargb6666), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3139,11 +3076,11 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb555), - CONVERT_PTR(quint32, qrgb555), - CONVERT_PTR(quint32, qrgb555), + convert_generic, + convert_generic, + convert_generic, #if defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16) - CONVERT_PTR(quint16, qrgb555), + convert_generic, #else 0, #endif @@ -3162,9 +3099,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb8555), - CONVERT_PTR(quint32, qargb8555), - CONVERT_PTR(quint32, qargb8555), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3181,9 +3118,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb888), - CONVERT_PTR(quint32, qrgb888), - CONVERT_PTR(quint32, qrgb888), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3200,9 +3137,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb444), - CONVERT_PTR(quint32, qrgb444), - CONVERT_PTR(quint32, qrgb444), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3219,9 +3156,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb4444), - CONVERT_PTR(quint32, qargb4444), - CONVERT_PTR(quint32, qargb4444), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3626,35 +3563,28 @@ QRgb QImage::pixel(int x, int y) const qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y); return 12345; } - const uchar * s = scanLine(y); + + const uchar * s = constScanLine(y); switch(d->format) { case Format_Mono: - return d->colortable.at((*(s + (x >> 3)) >> (7- (x & 7))) & 1); + return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1); case Format_MonoLSB: return d->colortable.at((*(s + (x >> 3)) >> (x & 7)) & 1); case Format_Indexed8: return d->colortable.at((int)s[x]); - case Format_ARGB8565_Premultiplied: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_RGB666: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_ARGB6666_Premultiplied: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_RGB555: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_ARGB8555_Premultiplied: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_RGB888: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_RGB444: - return qt_colorConvert(reinterpret_cast(s)[x], 0); - case Format_ARGB4444_Premultiplied: - return qt_colorConvert(reinterpret_cast(s)[x], 0); + case Format_RGB32: + case Format_ARGB32: // Keep old behaviour. + case Format_ARGB32_Premultiplied: + return reinterpret_cast(s)[x]; case Format_RGB16: - return qt_colorConvert(reinterpret_cast(s)[x], 0); + return qConvertRgb16To32(reinterpret_cast(s)[x]); default: - return ((QRgb*)s)[x]; + break; } + const QPixelLayout *layout = &qPixelLayouts[d->format]; + uint result; + const uint *ptr = qFetchPixels[layout->bpp](&result, s, x, 1); + return *layout->convertToARGB32PM(&result, ptr, 1, layout, 0); } @@ -3693,7 +3623,6 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } // detach is called from within scanLine uchar * s = scanLine(y); - const quint32p p = quint32p::fromRawData(index_or_rgb); switch(d->format) { case Format_Mono: case Format_MonoLSB: @@ -3710,54 +3639,38 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) else *(s + (x >> 3)) |= (1 << (7-(x & 7))); } - break; + return; case Format_Indexed8: if (index_or_rgb >= (uint)d->colortable.size()) { qWarning("QImage::setPixel: Index %d out of range", index_or_rgb); return; } s[x] = index_or_rgb; - break; + return; case Format_RGB32: //make sure alpha is 255, we depend on it in qdrawhelper for cases // when image is set as a texture pattern on a qbrush ((uint *)s)[x] = uint(255 << 24) | index_or_rgb; - break; + return; case Format_ARGB32: case Format_ARGB32_Premultiplied: ((uint *)s)[x] = index_or_rgb; - break; + return; case Format_RGB16: - ((quint16 *)s)[x] = qt_colorConvert(p, 0); - break; - case Format_ARGB8565_Premultiplied: - ((qargb8565*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_RGB666: - ((qrgb666*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_ARGB6666_Premultiplied: - ((qargb6666*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_RGB555: - ((qrgb555*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_ARGB8555_Premultiplied: - ((qargb8555*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_RGB888: - ((qrgb888*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_RGB444: - ((qrgb444*)s)[x] = qt_colorConvert(p, 0); - break; - case Format_ARGB4444_Premultiplied: - ((qargb4444*)s)[x] = qt_colorConvert(p, 0); - break; + ((quint16 *)s)[x] = qConvertRgb32To16(INV_PREMUL(index_or_rgb)); + return; case Format_Invalid: case NImageFormats: Q_ASSERT(false); + return; + default: + break; } + + const QPixelLayout *layout = &qPixelLayouts[d->format]; + uint result; + const uint *ptr = layout->convertFromARGB32PM(&result, &index_or_rgb, 1, layout, 0); + qStorePixels[layout->bpp](s, ptr, x, 1); } /*! @@ -3774,30 +3687,56 @@ bool QImage::allGray() const if (!d) return true; - if (d->depth == 32) { - int p = width()*height(); - const QRgb* b = (const QRgb*)bits(); - while (p--) - if (!qIsGray(*b++)) - return false; - } else if (d->depth == 16) { - int p = width()*height(); - const ushort* b = (const ushort *)bits(); - while (p--) - if (!qIsGray(qt_colorConvert(*b++, 0))) - return false; - } else if (d->format == QImage::Format_RGB888) { - int p = width()*height(); - const qrgb888* b = (const qrgb888 *)bits(); - while (p--) - if (!qIsGray(qt_colorConvert(*b++, 0))) - return false; - } else { - if (d->colortable.isEmpty()) - return true; - for (int i = 0; i < colorCount(); i++) + switch (d->format) { + case Format_Mono: + case Format_MonoLSB: + case Format_Indexed8: + for (int i = 0; i < d->colortable.size(); ++i) { if (!qIsGray(d->colortable.at(i))) return false; + } + return true; + case Format_RGB32: + case Format_ARGB32: + case Format_ARGB32_Premultiplied: + for (int j = 0; j < d->height; ++j) { + const QRgb *b = (const QRgb *)constScanLine(j); + for (int i = 0; i < d->width; ++i) { + if (!qIsGray(b[i])) + return false; + } + } + return true; + case Format_RGB16: + for (int j = 0; j < d->height; ++j) { + const quint16 *b = (const quint16 *)constScanLine(j); + for (int i = 0; i < d->width; ++i) { + if (!qIsGray(qConvertRgb16To32(b[i]))) + return false; + } + } + return true; + default: + break; + } + + const int buffer_size = 2048; + uint buffer[buffer_size]; + const QPixelLayout *layout = &qPixelLayouts[d->format]; + FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + for (int j = 0; j < d->height; ++j) { + const uchar *b = constScanLine(j); + int x = 0; + while (x < d->width) { + int l = qMin(d->width - x, buffer_size); + const uint *ptr = fetch(buffer, b, x, l); + ptr = layout->convertToARGB32PM(buffer, ptr, l, layout, 0); + for (int i = 0; i < l; ++i) { + if (!qIsGray(ptr[i])) + return false; + } + x += l; + } } return true; } @@ -4320,7 +4259,7 @@ QImage QImage::rgbSwapped() const case Format_Invalid: case NImageFormats: Q_ASSERT(false); - break; + return res; case Format_Mono: case Format_MonoLSB: case Format_Indexed8: @@ -4329,7 +4268,7 @@ QImage QImage::rgbSwapped() const QRgb c = res.d->colortable.at(i); res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00)); } - break; + return res; case Format_RGB32: case Format_ARGB32: case Format_ARGB32_Premultiplied: @@ -4345,7 +4284,7 @@ QImage QImage::rgbSwapped() const q++; } } - break; + return res; case Format_RGB16: res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); @@ -4359,113 +4298,41 @@ QImage QImage::rgbSwapped() const q++; } } + return res; + default: break; - case Format_ARGB8565_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - const quint8 *p = constScanLine(i); - quint8 *q = res.scanLine(i); - const quint8 *end = p + d->width * sizeof(qargb8565); - while (p < end) { - q[0] = p[0]; - q[1] = (p[1] & 0xe0) | (p[2] >> 3); - q[2] = (p[2] & 0x07) | (p[1] << 3); - p += sizeof(qargb8565); - q += sizeof(qargb8565); - } - } - break; - case Format_RGB666: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - qrgb666 *q = reinterpret_cast(res.scanLine(i)); - const qrgb666 *p = reinterpret_cast(constScanLine(i)); - const qrgb666 *end = p + d->width; - while (p < end) { - const QRgb rgb = quint32(*p++); - *q++ = qRgb(qBlue(rgb), qGreen(rgb), qRed(rgb)); - } - } - break; - case Format_ARGB6666_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - const quint8 *p = constScanLine(i); - const quint8 *end = p + d->width * sizeof(qargb6666); - quint8 *q = res.scanLine(i); - while (p < end) { - q[0] = (p[1] >> 4) | ((p[2] & 0x3) << 4) | (p[0] & 0xc0); - q[1] = (p[1] & 0xf) | (p[0] << 4); - q[2] = (p[2] & 0xfc) | ((p[0] >> 4) & 0x3); - p += sizeof(qargb6666); - q += sizeof(qargb6666); - } - } - break; - case Format_RGB555: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint16 *q = (quint16*)res.scanLine(i); - const quint16 *p = (const quint16*)constScanLine(i); - const quint16 *end = p + d->width; - while (p < end) { - *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0); - p++; - q++; - } - } - break; - case Format_ARGB8555_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - const quint8 *p = constScanLine(i); - quint8 *q = res.scanLine(i); - const quint8 *end = p + d->width * sizeof(qargb8555); - while (p < end) { - q[0] = p[0]; - q[1] = (p[1] & 0xe0) | (p[2] >> 2); - q[2] = (p[2] & 0x03) | ((p[1] << 2) & 0x7f); - p += sizeof(qargb8555); - q += sizeof(qargb8555); - } - } - break; - case Format_RGB888: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint8 *q = res.scanLine(i); - const quint8 *p = constScanLine(i); - const quint8 *end = p + d->width * sizeof(qrgb888); - while (p < end) { - q[0] = p[2]; - q[1] = p[1]; - q[2] = p[0]; - q += sizeof(qrgb888); - p += sizeof(qrgb888); - } - } - break; - case Format_RGB444: - case Format_ARGB4444_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint16 *q = reinterpret_cast(res.scanLine(i)); - const quint16 *p = reinterpret_cast(constScanLine(i)); - const quint16 *end = p + d->width; - while (p < end) { - *q = (*p & 0xf0f0) | ((*p & 0x0f) << 8) | ((*p & 0xf00) >> 8); - p++; - q++; + } + + res = QImage(d->width, d->height, d->format); + QIMAGE_SANITYCHECK_MEMORY(res); + const QPixelLayout *layout = &qPixelLayouts[d->format]; + Q_ASSERT(layout->redWidth == layout->blueWidth); + FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + StorePixelsFunc store = qStorePixels[layout->bpp]; + + const uint redBlueMask = (1 << layout->redWidth) - 1; + const uint alphaGreenMask = (((1 << layout->alphaWidth) - 1) << layout->alphaShift) + | (((1 << layout->greenWidth) - 1) << layout->greenShift); + + const int buffer_size = 2048; + uint buffer[buffer_size]; + for (int i = 0; i < d->height; ++i) { + uchar *q = res.scanLine(i); + const uchar *p = constScanLine(i); + int x = 0; + while (x < d->width) { + int l = qMin(d->width - x, buffer_size); + const uint *ptr = fetch(buffer, p, x, l); + for (int j = 0; j < l; ++j) { + uint red = (ptr[j] >> layout->redShift) & redBlueMask; + uint blue = (ptr[j] >> layout->blueShift) & redBlueMask; + buffer[j] = (ptr[j] & alphaGreenMask) + | (red << layout->blueShift) + | (blue << layout->redShift); } + store(q, buffer, x, l); + x += l; } - break; } return res; } -- cgit v1.2.3