summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qimage.cpp
diff options
context:
space:
mode:
authorKim Motoyoshi Kalland <kim.kalland@nokia.com>2012-01-13 12:07:11 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-07 15:52:01 +0100
commitba1cf5dae397031730fb77321db1807937e81617 (patch)
tree491f6eeeeba37dcb5764c0348ae4704c1e41c1e2 /src/gui/image/qimage.cpp
parentfe2344bd44e183b9893934d175c61a725af29b90 (diff)
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 <gunnar.sletta@nokia.com>
Diffstat (limited to 'src/gui/image/qimage.cpp')
-rw-r--r--src/gui/image/qimage.cpp511
1 files changed, 189 insertions, 322 deletions
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<quint16, quint32>(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<quint16, quint32>(data->colortable.at(i), 0);
+ colorTableRGB16[i] = qConvertRgb32To16(data->colortable.at(i));
data->colortable = QVector<QRgb>();
// 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<DST, SRC>(reinterpret_cast<DST*>(dest->data), \
- reinterpret_cast<const SRC*>(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<quint32, qargb8565>(reinterpret_cast<const qargb8565*>(s)[x], 0);
- case Format_RGB666:
- return qt_colorConvert<quint32, qrgb666>(reinterpret_cast<const qrgb666*>(s)[x], 0);
- case Format_ARGB6666_Premultiplied:
- return qt_colorConvert<quint32, qargb6666>(reinterpret_cast<const qargb6666*>(s)[x], 0);
- case Format_RGB555:
- return qt_colorConvert<quint32, qrgb555>(reinterpret_cast<const qrgb555*>(s)[x], 0);
- case Format_ARGB8555_Premultiplied:
- return qt_colorConvert<quint32, qargb8555>(reinterpret_cast<const qargb8555*>(s)[x], 0);
- case Format_RGB888:
- return qt_colorConvert<quint32, qrgb888>(reinterpret_cast<const qrgb888*>(s)[x], 0);
- case Format_RGB444:
- return qt_colorConvert<quint32, qrgb444>(reinterpret_cast<const qrgb444*>(s)[x], 0);
- case Format_ARGB4444_Premultiplied:
- return qt_colorConvert<quint32, qargb4444>(reinterpret_cast<const qargb4444*>(s)[x], 0);
+ case Format_RGB32:
+ case Format_ARGB32: // Keep old behaviour.
+ case Format_ARGB32_Premultiplied:
+ return reinterpret_cast<const QRgb *>(s)[x];
case Format_RGB16:
- return qt_colorConvert<quint32, quint16>(reinterpret_cast<const quint16*>(s)[x], 0);
+ return qConvertRgb16To32(reinterpret_cast<const quint16 *>(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<quint16, quint32p>(p, 0);
- break;
- case Format_ARGB8565_Premultiplied:
- ((qargb8565*)s)[x] = qt_colorConvert<qargb8565, quint32p>(p, 0);
- break;
- case Format_RGB666:
- ((qrgb666*)s)[x] = qt_colorConvert<qrgb666, quint32p>(p, 0);
- break;
- case Format_ARGB6666_Premultiplied:
- ((qargb6666*)s)[x] = qt_colorConvert<qargb6666, quint32p>(p, 0);
- break;
- case Format_RGB555:
- ((qrgb555*)s)[x] = qt_colorConvert<qrgb555, quint32p>(p, 0);
- break;
- case Format_ARGB8555_Premultiplied:
- ((qargb8555*)s)[x] = qt_colorConvert<qargb8555, quint32p>(p, 0);
- break;
- case Format_RGB888:
- ((qrgb888*)s)[x] = qt_colorConvert<qrgb888, quint32p>(p, 0);
- break;
- case Format_RGB444:
- ((qrgb444*)s)[x] = qt_colorConvert<qrgb444, quint32p>(p, 0);
- break;
- case Format_ARGB4444_Premultiplied:
- ((qargb4444*)s)[x] = qt_colorConvert<qargb4444, quint32p>(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<quint32, quint16>(*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<quint32, qrgb888>(*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<qrgb666*>(res.scanLine(i));
- const qrgb666 *p = reinterpret_cast<const qrgb666*>(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<quint16*>(res.scanLine(i));
- const quint16 *p = reinterpret_cast<const quint16*>(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;
}