Implement support for 16bpc image formats
Adds support for 16bit per color image formats in QImage. This makes it possible to read and write 16bpc PNGs, and take full advantage of the 16bpc paint engine. [ChangeLog][QtGui][QImage] QImage now supports 64bit image formats with 16 bits per color channel, compatible with 16bpc PNG or RGBA16 OpenGL formats. Task-number: QTBUG-45858 Change-Id: Icd28bd5868a6efcf65cb5bd56031d42941e04099 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
1c623bc6d1
commit
9c9f98f2ff
@ -277,6 +277,16 @@ bool QImageData::checkForAlphaPixels() const
|
||||
bits += bytes_per_line;
|
||||
}
|
||||
} break;
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied: {
|
||||
uchar *bits = data;
|
||||
for (int y=0; y<height && !has_alpha_pixels; ++y) {
|
||||
for (int x=0; x<width; ++x) {
|
||||
has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
|
||||
}
|
||||
bits += bytes_per_line;
|
||||
}
|
||||
} break;
|
||||
|
||||
case QImage::Format_RGB32:
|
||||
case QImage::Format_RGB16:
|
||||
@ -288,6 +298,7 @@ bool QImageData::checkForAlphaPixels() const
|
||||
case QImage::Format_BGR30:
|
||||
case QImage::Format_RGB30:
|
||||
case QImage::Format_Grayscale8:
|
||||
case QImage::Format_RGBX64:
|
||||
break;
|
||||
case QImage::Format_Invalid:
|
||||
case QImage::NImageFormats:
|
||||
@ -651,11 +662,7 @@ bool QImageData::checkForAlphaPixels() const
|
||||
/*!
|
||||
\enum QImage::Format
|
||||
|
||||
The following image formats are available in Qt. Values from Format_ARGB8565_Premultiplied
|
||||
to Format_ARGB4444_Premultiplied were added in Qt 4.4. Values Format_RGBX8888, Format_RGBA8888
|
||||
and Format_RGBA8888_Premultiplied were added in Qt 5.2. Values Format_BGR30, Format_A2BGR30_Premultiplied,
|
||||
Format_RGB30, Format_A2RGB30_Premultiplied were added in Qt 5.4. Format_Alpha8 and Format_Grayscale8
|
||||
were added in Qt 5.5.
|
||||
The following image formats are available in Qt.
|
||||
See the notes after the table.
|
||||
|
||||
\value Format_Invalid The image is invalid.
|
||||
@ -699,29 +706,32 @@ bool QImageData::checkForAlphaPixels() const
|
||||
\value Format_ARGB4444_Premultiplied The image is stored using a
|
||||
premultiplied 16-bit ARGB format (4-4-4-4).
|
||||
\value Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
|
||||
This is the same as the Format_RGBA8888 except alpha must always be 255.
|
||||
This is the same as the Format_RGBA8888 except alpha must always be 255. (added in Qt 5.2)
|
||||
\value Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
|
||||
Unlike ARGB32 this is a byte-ordered format, which means the 32bit
|
||||
encoding differs between big endian and little endian architectures,
|
||||
being respectively (0xRRGGBBAA) and (0xAABBGGRR). The order of the colors
|
||||
is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
|
||||
is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA. (added in Qt 5.2)
|
||||
\value Format_RGBA8888_Premultiplied The image is stored using a
|
||||
premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
|
||||
\value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
|
||||
\value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
|
||||
\value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10).
|
||||
\value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
|
||||
\value Format_Alpha8 The image is stored using an 8-bit alpha only format.
|
||||
\value Format_Grayscale8 The image is stored using an 8-bit grayscale format.
|
||||
premultiplied 32-bit byte-ordered RGBA format (8-8-8-8). (added in Qt 5.2)
|
||||
\value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10). (added in Qt 5.4)
|
||||
\value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10). (added in Qt 5.4)
|
||||
\value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10). (added in Qt 5.4)
|
||||
\value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4)
|
||||
\value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5)
|
||||
\value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5)
|
||||
\value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
|
||||
This is the same as the Format_RGBX64 except alpha must always be 65535. (added in Qt 5.12)
|
||||
\value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
|
||||
\value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
|
||||
RGBA format (16-16-16-16). (added in Qt 5.12)
|
||||
|
||||
\note Drawing into a QImage with QImage::Format_Indexed8 is not
|
||||
supported.
|
||||
|
||||
\note Do not render into ARGB32 images using QPainter. Using
|
||||
QImage::Format_ARGB32_Premultiplied is significantly faster.
|
||||
|
||||
\note Formats with more than 8 bit per color channel will only be processed by the raster engine using 8 bit
|
||||
per color.
|
||||
\note Avoid most rendering directly to most of these formats using QPainter. Rendering
|
||||
is best optimized to the \c Format_RGB32 and \c Format_ARGB32_Premultiplied formats, and secondarily for rendering to the
|
||||
\c Format_RGB16, \c Format_RGBX8888, \c Format_RGBA8888_Premultiplied, \c Format_RGBX64 and \c Format_RGBA64_Premultiplied formats
|
||||
|
||||
\sa format(), convertToFormat()
|
||||
*/
|
||||
@ -1708,6 +1718,10 @@ void QImage::fill(uint pixel)
|
||||
qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
|
||||
0, 0, d->width, d->height, d->bytes_per_line);
|
||||
return;
|
||||
} else if (d->depth == 64) {
|
||||
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
|
||||
0, 0, d->width, d->height, d->bytes_per_line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->format == Format_RGB32)
|
||||
@ -1815,6 +1829,12 @@ void QImage::fill(const QColor &color)
|
||||
else
|
||||
fill((uint) 0);
|
||||
break;
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(),
|
||||
0, 0, d->width, d->height, d->bytes_per_line);
|
||||
break;
|
||||
default: {
|
||||
QPainter p(this);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
@ -1838,7 +1858,8 @@ void QImage::fill(const QColor &color)
|
||||
changed.
|
||||
|
||||
If the image has a premultiplied alpha channel, the image is first
|
||||
converted to ARGB32 to be inverted and then converted back.
|
||||
converted to an unpremultiplied image format to be inverted and
|
||||
then converted back.
|
||||
|
||||
\sa {QImage#Image Transformations}{Image Transformations}
|
||||
*/
|
||||
@ -1857,8 +1878,13 @@ void QImage::invertPixels(InvertMode mode)
|
||||
QImage::Format originalFormat = d->format;
|
||||
// Inverting premultiplied pixels would produce invalid image data.
|
||||
if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
|
||||
if (!d->convertInPlace(QImage::Format_ARGB32, 0))
|
||||
*this = convertToFormat(QImage::Format_ARGB32);
|
||||
if (depth() > 32) {
|
||||
if (!d->convertInPlace(QImage::Format_RGBA64, 0))
|
||||
*this = convertToFormat(QImage::Format_RGBA64);
|
||||
} else {
|
||||
if (!d->convertInPlace(QImage::Format_ARGB32, 0))
|
||||
*this = convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
}
|
||||
|
||||
if (depth() < 32) {
|
||||
@ -1871,6 +1897,20 @@ void QImage::invertPixels(InvertMode mode)
|
||||
*sl++ ^= 0xff;
|
||||
sl += pad;
|
||||
}
|
||||
}
|
||||
else if (depth() == 64) {
|
||||
quint16 *p = (quint16*)d->data;
|
||||
quint16 *end = (quint16*)(d->data + d->nbytes);
|
||||
quint16 xorbits = 0xffff;
|
||||
while (p < end) {
|
||||
*p++ ^= xorbits;
|
||||
*p++ ^= xorbits;
|
||||
*p++ ^= xorbits;
|
||||
if (mode == InvertRgba)
|
||||
*p++ ^= xorbits;
|
||||
else
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
quint32 *p = (quint32*)d->data;
|
||||
quint32 *end = (quint32*)(d->data + d->nbytes);
|
||||
@ -1987,6 +2027,26 @@ QImage::Format QImage::format() const
|
||||
\sa {Image Formats}
|
||||
*/
|
||||
|
||||
static bool highColorPrecision(QImage::Format format)
|
||||
{
|
||||
// Formats with higher color precision than ARGB32_Premultiplied.
|
||||
switch (format) {
|
||||
case QImage::Format_ARGB32:
|
||||
case QImage::Format_RGBA8888:
|
||||
case QImage::Format_BGR30:
|
||||
case QImage::Format_RGB30:
|
||||
case QImage::Format_A2BGR30_Premultiplied:
|
||||
case QImage::Format_A2RGB30_Premultiplied:
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@ -1999,8 +2059,18 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
|
||||
return QImage();
|
||||
|
||||
Image_Converter converter = qimage_converter_map[d->format][format];
|
||||
if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8)
|
||||
converter = convert_generic;
|
||||
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);
|
||||
}
|
||||
} else
|
||||
converter = convert_generic;
|
||||
}
|
||||
if (converter) {
|
||||
QImage image(d->width, d->height, format);
|
||||
|
||||
@ -2298,6 +2368,10 @@ QRgb QImage::pixel(int x, int y) const
|
||||
return qConvertA2rgb30ToArgb32<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
|
||||
case Format_RGB16:
|
||||
return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]);
|
||||
case Format_RGBX64:
|
||||
case Format_RGBA64: // Match ARGB32 behavior.
|
||||
case Format_RGBA64_Premultiplied:
|
||||
return reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2447,6 +2521,11 @@ QColor QImage::pixelColor(int x, int y) const
|
||||
case Format_A2RGB30_Premultiplied:
|
||||
c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
|
||||
break;
|
||||
case Format_RGBX64:
|
||||
case Format_RGBA64:
|
||||
case Format_RGBA64_Premultiplied:
|
||||
c = reinterpret_cast<const QRgba64 *>(s)[x];
|
||||
break;
|
||||
default:
|
||||
c = QRgba64::fromArgb32(pixel(x, y));
|
||||
break;
|
||||
@ -2517,6 +2596,14 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
|
||||
case Format_A2RGB30_Premultiplied:
|
||||
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
|
||||
return;
|
||||
case Format_RGBX64:
|
||||
((QRgba64 *)s)[x] = color.rgba64();
|
||||
((QRgba64 *)s)[x].setAlpha(65535);
|
||||
return;
|
||||
case Format_RGBA64:
|
||||
case Format_RGBA64_Premultiplied:
|
||||
((QRgba64 *)s)[x] = color.rgba64();
|
||||
return;
|
||||
default:
|
||||
setPixel(x, y, c.toArgb32());
|
||||
return;
|
||||
@ -3100,6 +3187,9 @@ inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool ve
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 64:
|
||||
do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
|
||||
break;
|
||||
case 32:
|
||||
do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
|
||||
break;
|
||||
@ -3308,6 +3398,23 @@ QImage QImage::rgbSwapped_helper() const
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Format_RGBX64:
|
||||
case Format_RGBA64:
|
||||
case Format_RGBA64_Premultiplied:
|
||||
res = QImage(d->width, d->height, d->format);
|
||||
QIMAGE_SANITYCHECK_MEMORY(res);
|
||||
for (int i = 0; i < d->height; i++) {
|
||||
QRgba64 *q = reinterpret_cast<QRgba64 *>(res.scanLine(i));
|
||||
const QRgba64 *p = reinterpret_cast<const QRgba64 *>(constScanLine(i));
|
||||
const QRgba64 *end = p + d->width;
|
||||
while (p < end) {
|
||||
QRgba64 c = *p;
|
||||
*q = QRgba64::fromRgba64(c.blue(), c.green(), c.red(), c.alpha());
|
||||
p++;
|
||||
q++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
res = QImage(d->width, d->height, d->format);
|
||||
rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
|
||||
@ -3400,6 +3507,19 @@ void QImage::rgbSwapped_inplace()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Format_RGBX64:
|
||||
case Format_RGBA64:
|
||||
case Format_RGBA64_Premultiplied:
|
||||
for (int i = 0; i < d->height; i++) {
|
||||
QRgba64 *p = reinterpret_cast<QRgba64 *>(scanLine(i));
|
||||
QRgba64 *end = p + d->width;
|
||||
while (p < end) {
|
||||
QRgba64 c = *p;
|
||||
*p = QRgba64::fromRgba64(c.blue(), c.green(), c.red(), c.alpha());
|
||||
p++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rgbSwapped_generic(d->width, d->height, this, this, &qPixelLayouts[d->format]);
|
||||
break;
|
||||
@ -4473,6 +4593,9 @@ int QImage::bitPlaneCount() const
|
||||
case QImage::Format_RGB444:
|
||||
bpc = 12;
|
||||
break;
|
||||
case QImage::Format_RGBX64:
|
||||
bpc = 48;
|
||||
break;
|
||||
default:
|
||||
bpc = qt_depthForFormat(d->format);
|
||||
break;
|
||||
@ -5171,6 +5294,45 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
|
||||
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBX64:
|
||||
QPixelFormat(QPixelFormat::RGB,
|
||||
/*RED*/ 16,
|
||||
/*GREEN*/ 16,
|
||||
/*BLUE*/ 16,
|
||||
/*FOURTH*/ 0,
|
||||
/*FIFTH*/ 0,
|
||||
/*ALPHA*/ 16,
|
||||
/*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
|
||||
/*ALPHA POSITION*/ QPixelFormat::AtEnd,
|
||||
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::UnsignedShort,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBA64:
|
||||
QPixelFormat(QPixelFormat::RGB,
|
||||
/*RED*/ 16,
|
||||
/*GREEN*/ 16,
|
||||
/*BLUE*/ 16,
|
||||
/*FOURTH*/ 0,
|
||||
/*FIFTH*/ 0,
|
||||
/*ALPHA*/ 16,
|
||||
/*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
|
||||
/*ALPHA POSITION*/ QPixelFormat::AtEnd,
|
||||
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::UnsignedShort,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBA64_Premultiplied:
|
||||
QPixelFormat(QPixelFormat::RGB,
|
||||
/*RED*/ 16,
|
||||
/*GREEN*/ 16,
|
||||
/*BLUE*/ 16,
|
||||
/*FOURTH*/ 0,
|
||||
/*FIFTH*/ 0,
|
||||
/*ALPHA*/ 16,
|
||||
/*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
|
||||
/*ALPHA POSITION*/ QPixelFormat::AtEnd,
|
||||
/*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::UnsignedShort,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
};
|
||||
Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
|
||||
|
||||
|
@ -125,6 +125,9 @@ public:
|
||||
Format_A2RGB30_Premultiplied,
|
||||
Format_Alpha8,
|
||||
Format_Grayscale8,
|
||||
Format_RGBX64,
|
||||
Format_RGBA64,
|
||||
Format_RGBA64_Premultiplied,
|
||||
#if 0
|
||||
// reserved for future use
|
||||
Format_Grayscale16,
|
||||
|
@ -179,7 +179,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
||||
store = storeRGB32FromARGB32PM;
|
||||
}
|
||||
}
|
||||
if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) &&
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
|
||||
fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
|
||||
@ -212,6 +212,26 @@ 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(src->format > QImage::Format_Indexed8);
|
||||
const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
|
||||
const uchar *srcData = src->data;
|
||||
uchar *destData = dest->data;
|
||||
|
||||
const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM;
|
||||
|
||||
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);
|
||||
}
|
||||
srcData += src->bytes_per_line;
|
||||
destData += dest->bytes_per_line;
|
||||
}
|
||||
}
|
||||
|
||||
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags flags)
|
||||
{
|
||||
// Cannot be used with indexed formats or between formats with different pixel depths.
|
||||
@ -226,6 +246,8 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
|
||||
uchar *srcData = data->data;
|
||||
|
||||
Q_ASSERT(srcLayout->bpp == destLayout->bpp);
|
||||
Q_ASSERT(srcLayout->bpp != QPixelLayout::BPP64);
|
||||
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
|
||||
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
@ -243,7 +265,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
store = storeRGB32FromARGB32PM;
|
||||
}
|
||||
}
|
||||
if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) &&
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
|
||||
fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
|
||||
@ -282,20 +304,15 @@ static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::Ima
|
||||
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;
|
||||
const int src_bpl = src->bytes_per_line;
|
||||
const int dest_bpl = dest->bytes_per_line;
|
||||
const uchar *src_data = src->data;
|
||||
uchar *dest_data = dest->data;
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const quint32 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = *src_data;
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
memcpy(dest_data, src_data, src_bpl);
|
||||
src_data += src_bpl;
|
||||
dest_data += dest_bpl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1138,6 +1155,270 @@ static bool mask_alpha_converter_rgbx_inplace(QImageData *data, Qt::ImageConvers
|
||||
#endif
|
||||
}
|
||||
|
||||
template<bool RGBA>
|
||||
static void convert_RGBA64_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64);
|
||||
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 uchar *srcData = src->data;
|
||||
uchar *destData = dest->data;
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
uint *d = reinterpret_cast<uint *>(destData);
|
||||
const QRgba64 *s = reinterpret_cast<const QRgba64 *>(srcData);
|
||||
qt_convertRGBA64ToARGB32<RGBA>(d, s, src->width);
|
||||
srcData += src->bytes_per_line;
|
||||
destData += dest->bytes_per_line;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Q_ASSERT(RGBA || src->format == QImage::Format_ARGB32);
|
||||
Q_ASSERT(!RGBA || src->format == QImage::Format_RGBA8888);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBA64);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_RGBA64_to_RGBx64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBX64);
|
||||
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 >> 3) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = *src_data;
|
||||
dest_data->setAlpha(65535);
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
static bool convert_RGBA64_to_RGBx64_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(data->format == QImage::Format_RGBA64);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 3) - data->width;
|
||||
QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
|
||||
|
||||
for (int i = 0; i < data->height; ++i) {
|
||||
const QRgba64 *end = rgb_data + data->width;
|
||||
while (rgb_data < end) {
|
||||
rgb_data->setAlpha(65535);
|
||||
++rgb_data;
|
||||
}
|
||||
rgb_data += pad;
|
||||
}
|
||||
data->format = QImage::Format_RGBX64;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void convert_RGBA64_to_RGBA64PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBA64_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 >> 3) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = src_data->premultiplied();
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
static bool convert_RGBA64_to_RGBA64PM_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(data->format == QImage::Format_RGBA64);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 3) - data->width;
|
||||
QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
|
||||
|
||||
for (int i = 0; i < data->height; ++i) {
|
||||
const QRgba64 *end = rgb_data + data->width;
|
||||
while (rgb_data < end) {
|
||||
*rgb_data = rgb_data->premultiplied();
|
||||
++rgb_data;
|
||||
}
|
||||
rgb_data += pad;
|
||||
}
|
||||
data->format = QImage::Format_RGBA64_Premultiplied;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool MaskAlpha>
|
||||
static void convert_RGBA64PM_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64);
|
||||
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 >> 3) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = src_data->unpremultiplied();
|
||||
if (MaskAlpha)
|
||||
dest_data->setAlpha(65535);
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool MaskAlpha>
|
||||
static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(data->format == QImage::Format_RGBA64_Premultiplied);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 3) - data->width;
|
||||
QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
|
||||
|
||||
for (int i = 0; i < data->height; ++i) {
|
||||
const QRgba64 *end = rgb_data + data->width;
|
||||
while (rgb_data < end) {
|
||||
*rgb_data = rgb_data->unpremultiplied();
|
||||
if (MaskAlpha)
|
||||
rgb_data->setAlpha(65535);
|
||||
++rgb_data;
|
||||
}
|
||||
rgb_data += pad;
|
||||
}
|
||||
data->format = MaskAlpha ? QImage::Format_RGBX64 : QImage::Format_RGBA64;
|
||||
return true;
|
||||
}
|
||||
|
||||
static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format)
|
||||
{
|
||||
QVector<QRgb> colorTable = ctbl;
|
||||
@ -1982,7 +2263,7 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
|
||||
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
|
||||
{
|
||||
{
|
||||
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, 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
|
||||
},
|
||||
{
|
||||
0,
|
||||
@ -2003,7 +2284,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_Mono
|
||||
|
||||
{
|
||||
@ -2025,7 +2306,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_MonoLSB
|
||||
|
||||
{
|
||||
@ -2050,6 +2331,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0, 0, 0, 0, 0,
|
||||
convert_Indexed8_to_Alpha8,
|
||||
convert_Indexed8_to_Grayscale8,
|
||||
0, 0, 0
|
||||
}, // Format_Indexed8
|
||||
|
||||
{
|
||||
@ -2076,7 +2358,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
convert_RGB_to_RGB30<PixelOrderRGB>,
|
||||
0,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_RGB32
|
||||
|
||||
{
|
||||
@ -2103,7 +2386,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
convert_RGB_to_RGB30<PixelOrderRGB>,
|
||||
0,
|
||||
0, 0
|
||||
0, 0,
|
||||
0,
|
||||
convert_ARGB32_to_RGBA64<false>,
|
||||
0
|
||||
}, // Format_ARGB32
|
||||
|
||||
{
|
||||
@ -2126,11 +2412,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
convert_ARGB_to_RGBA,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0
|
||||
0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_ARGB32_Premultiplied
|
||||
|
||||
{
|
||||
@ -2152,7 +2436,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGB16
|
||||
|
||||
{
|
||||
@ -2174,7 +2458,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_ARGB8565_Premultiplied
|
||||
|
||||
{
|
||||
@ -2196,7 +2480,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGB666
|
||||
|
||||
{
|
||||
@ -2218,7 +2502,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_ARGB6666_Premultiplied
|
||||
|
||||
{
|
||||
@ -2240,7 +2524,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGB555
|
||||
|
||||
{
|
||||
@ -2262,7 +2546,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_ARGB8555_Premultiplied
|
||||
|
||||
{
|
||||
@ -2285,7 +2569,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
convert_RGB888_to_RGB<true>,
|
||||
convert_RGB888_to_RGB<true>,
|
||||
convert_RGB888_to_RGB<true>,
|
||||
0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGB888
|
||||
|
||||
{
|
||||
@ -2307,7 +2591,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGB444
|
||||
|
||||
{
|
||||
@ -2328,7 +2612,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_ARGB4444_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2348,9 +2632,11 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
mask_alpha_converter_RGBx,
|
||||
mask_alpha_converter_RGBx,
|
||||
0, 0, 0, 0, 0, 0
|
||||
convert_passthrough,
|
||||
convert_passthrough,
|
||||
0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_RGBX8888
|
||||
{
|
||||
0,
|
||||
@ -2372,7 +2658,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
mask_alpha_converter_RGBx,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
convert_ARGB32_to_RGBA64<true>,
|
||||
0
|
||||
}, // Format_RGBA8888
|
||||
|
||||
{
|
||||
@ -2394,7 +2683,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGBA8888_Premultiplied
|
||||
|
||||
{
|
||||
@ -2421,7 +2710,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
convert_passthrough,
|
||||
convert_BGR30_to_RGB30,
|
||||
convert_BGR30_to_RGB30,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_BGR30
|
||||
{
|
||||
0,
|
||||
@ -2447,7 +2737,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
convert_A2RGB30_PM_to_RGB30<true>,
|
||||
convert_BGR30_to_RGB30,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_BGR30A2_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2473,7 +2764,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
convert_BGR30_to_RGB30,
|
||||
0,
|
||||
convert_passthrough,
|
||||
0, 0
|
||||
0, 0, 0, 0, 0
|
||||
}, // Format_RGB30
|
||||
{
|
||||
0,
|
||||
@ -2499,7 +2790,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
convert_BGR30_to_RGB30,
|
||||
convert_A2RGB30_PM_to_RGB30<false>,
|
||||
0,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_RGB30A2_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2519,7 +2811,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_Alpha8
|
||||
{
|
||||
0,
|
||||
@ -2539,20 +2831,81 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
} // Format_Grayscale8
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_Grayscale8
|
||||
{
|
||||
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,
|
||||
0, // self
|
||||
convert_passthrough,
|
||||
convert_passthrough
|
||||
}, // Format_RGBX64
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
convert_RGBA64_to_ARGB32<false>,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
convert_RGBA64_to_ARGB32<true>,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
0, 0,
|
||||
convert_RGBA64_to_RGBx64,
|
||||
0, // self
|
||||
convert_RGBA64_to_RGBA64PM
|
||||
}, // Format_RGBA64
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
convert_RGBA64PM_to_ARGB32<false>,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
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,
|
||||
convert_RGBA64PM_to_RGBA64<true>,
|
||||
convert_RGBA64PM_to_RGBA64<false>,
|
||||
0 // self
|
||||
} // Format_RGBA64_Premultiplied
|
||||
};
|
||||
|
||||
InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
|
||||
{
|
||||
{
|
||||
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
|
||||
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, 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, 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, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_Mono
|
||||
{
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_MonoLSB
|
||||
{
|
||||
0,
|
||||
@ -2576,6 +2929,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0, 0, 0, 0, 0,
|
||||
convert_Indexed8_to_Alpha8_inplace,
|
||||
convert_Indexed8_to_Grayscale8_inplace,
|
||||
0, 0, 0
|
||||
}, // Format_Indexed8
|
||||
{
|
||||
0,
|
||||
@ -2601,7 +2955,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0,
|
||||
convert_RGB_to_RGB30_inplace<PixelOrderRGB>,
|
||||
0,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_RGB32
|
||||
{
|
||||
0,
|
||||
@ -2627,7 +2982,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0,
|
||||
convert_RGB_to_RGB30_inplace<PixelOrderRGB>,
|
||||
0,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_ARGB32
|
||||
{
|
||||
0,
|
||||
@ -2649,38 +3005,36 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0,
|
||||
0,
|
||||
convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888_Premultiplied>,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_RGB16
|
||||
{
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_ARGB8565_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
|
||||
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, 0, 0, 0
|
||||
}, // Format_RGB666
|
||||
{
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_ARGB6666_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
|
||||
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, 0, 0, 0
|
||||
}, // Format_RGB555
|
||||
{
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_ARGB8555_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
|
||||
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, 0, 0, 0
|
||||
}, // Format_RGB888
|
||||
{
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_RGB444
|
||||
{
|
||||
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
|
||||
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, 0, 0, 0
|
||||
}, // Format_ARGB4444_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2702,7 +3056,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0,
|
||||
convert_passthrough_inplace<QImage::Format_RGBA8888>,
|
||||
convert_passthrough_inplace<QImage::Format_RGBA8888_Premultiplied>,
|
||||
0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGBX8888
|
||||
{
|
||||
0,
|
||||
@ -2724,7 +3078,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
mask_alpha_converter_rgbx_inplace,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // Format_RGBA8888
|
||||
{
|
||||
0,
|
||||
@ -2746,7 +3100,7 @@ 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, 0
|
||||
}, // Format_RGBA8888_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2772,7 +3126,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>,
|
||||
convert_BGR30_to_RGB30_inplace,
|
||||
convert_BGR30_to_A2RGB30_inplace,
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_BGR30
|
||||
{
|
||||
0,
|
||||
@ -2798,7 +3153,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0, // self
|
||||
convert_A2RGB30_PM_to_RGB30_inplace<true>,
|
||||
convert_BGR30_to_RGB30_inplace,
|
||||
0, 0
|
||||
0, 0, 0, 0, 0
|
||||
}, // Format_BGR30A2_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2824,7 +3179,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
convert_BGR30_to_A2RGB30_inplace,
|
||||
0, // self
|
||||
convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>,
|
||||
0, 0
|
||||
0, 0, 0, 0, 0
|
||||
}, // Format_RGB30
|
||||
{
|
||||
0,
|
||||
@ -2850,7 +3205,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
convert_BGR30_to_RGB30_inplace,
|
||||
convert_A2RGB30_PM_to_RGB30_inplace<false>,
|
||||
0, // self
|
||||
0, 0
|
||||
0, 0,
|
||||
0, 0, 0
|
||||
}, // Format_RGB30A2_Premultiplied
|
||||
{
|
||||
0,
|
||||
@ -2872,11 +3228,10 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
0, // self
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0
|
||||
0, 0, 0
|
||||
}, // Format_Alpha8
|
||||
{
|
||||
0,
|
||||
@ -2898,12 +3253,29 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0
|
||||
} // Format_Grayscale8
|
||||
0, // self
|
||||
0, 0, 0
|
||||
}, // Format_Grayscale8
|
||||
{
|
||||
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,
|
||||
0, // self
|
||||
convert_passthrough_inplace<QImage::Format_RGBA64>,
|
||||
convert_passthrough_inplace<QImage::Format_RGBA64_Premultiplied>,
|
||||
}, // Format_RGBX64
|
||||
{
|
||||
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,
|
||||
convert_RGBA64_to_RGBx64_inplace,
|
||||
0, // self
|
||||
convert_RGBA64_to_RGBA64PM_inplace
|
||||
}, // Format_RGBA64
|
||||
{
|
||||
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,
|
||||
convert_RGBA64PM_to_RGBA64_inplace<true>,
|
||||
convert_RGBA64PM_to_RGBA64_inplace<false>,
|
||||
0 // self
|
||||
} // Format_RGBA64_Premultiplied
|
||||
};
|
||||
|
||||
static void qInitImageConversions()
|
||||
|
@ -113,6 +113,7 @@ extern Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImag
|
||||
extern InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats];
|
||||
|
||||
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
|
||||
void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
|
||||
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
|
||||
|
||||
void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
|
||||
@ -164,6 +165,11 @@ inline int qt_depthForFormat(QImage::Format format)
|
||||
case QImage::Format_RGB888:
|
||||
depth = 24;
|
||||
break;
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
depth = 64;
|
||||
break;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
@ -190,6 +196,9 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
|
||||
return QImage::Format_BGR30;
|
||||
case QImage::Format_A2RGB30_Premultiplied:
|
||||
return QImage::Format_RGB30;
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
return QImage::Format_RGBX64;
|
||||
case QImage::Format_ARGB32_Premultiplied:
|
||||
case QImage::Format_ARGB32:
|
||||
default:
|
||||
@ -214,6 +223,8 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
|
||||
return QImage::Format_A2BGR30_Premultiplied;
|
||||
case QImage::Format_RGB30:
|
||||
return QImage::Format_A2RGB30_Premultiplied;
|
||||
case QImage::Format_RGBX64:
|
||||
return QImage::Format_RGBA64_Premultiplied;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -352,6 +352,24 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
|
||||
);
|
||||
i++;
|
||||
}
|
||||
// Qt==ARGB==Big(ARGB)==Little(BGRA)
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
|
||||
png_set_bgr(png_ptr);
|
||||
}
|
||||
} else if (bit_depth == 16 && (color_type & PNG_COLOR_MASK_COLOR)) {
|
||||
QImage::Format format = QImage::Format_RGBA64;
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
|
||||
format = QImage::Format_RGBX64;
|
||||
}
|
||||
if (image.size() != QSize(width, height) || image.format() != format) {
|
||||
image = QImage(width, height, format);
|
||||
if (image.isNull())
|
||||
return;
|
||||
}
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
|
||||
png_set_swap(png_ptr);
|
||||
} else {
|
||||
// 32-bit
|
||||
if (bit_depth == 16)
|
||||
@ -388,12 +406,12 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
|
||||
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
|
||||
png_set_swap_alpha(png_ptr);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
}
|
||||
// Qt==ARGB==Big(ARGB)==Little(BGRA)
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
|
||||
png_set_bgr(png_ptr);
|
||||
}
|
||||
|
||||
// Qt==ARGB==Big(ARGB)==Little(BGRA)
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
|
||||
png_set_bgr(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -678,6 +696,10 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
|
||||
{
|
||||
// 1-bit and 8-bit color
|
||||
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
|
||||
} else if (bit_depth == 16 && (color_type & PNG_COLOR_MASK_COLOR)) {
|
||||
format = QImage::Format_RGBA64;
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
format = QImage::Format_RGBX64;
|
||||
} else {
|
||||
// 32-bit
|
||||
format = QImage::Format_ARGB32;
|
||||
@ -843,8 +865,24 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
|
||||
else
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
|
||||
int bpc = 0;
|
||||
switch (image.format()) {
|
||||
case QImage::Format_Mono:
|
||||
case QImage::Format_MonoLSB:
|
||||
bpc = 1;
|
||||
break;
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
bpc = 16;
|
||||
break;
|
||||
default:
|
||||
bpc = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
|
||||
image.depth() == 1 ? 1 : 8, // per channel
|
||||
bpc, // per channel
|
||||
color_type, 0, 0, 0); // sets #channels
|
||||
|
||||
if (gamma != 0.0) {
|
||||
@ -880,13 +918,31 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
|
||||
// Swap ARGB to RGBA (normal PNG format) before saving on
|
||||
// BigEndian machines
|
||||
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
||||
png_set_swap_alpha(png_ptr);
|
||||
switch (image.format()) {
|
||||
case QImage::Format_RGBX8888:
|
||||
case QImage::Format_RGBA8888:
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
break;
|
||||
default:
|
||||
png_set_swap_alpha(png_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
|
||||
&& image.format() != QImage::Format_RGB888) {
|
||||
png_set_bgr(png_ptr);
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
|
||||
switch (image.format()) {
|
||||
case QImage::Format_RGB888:
|
||||
case QImage::Format_RGBX8888:
|
||||
case QImage::Format_RGBA8888:
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
break;
|
||||
default:
|
||||
png_set_bgr(png_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (off_x || off_y) {
|
||||
@ -909,10 +965,32 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
|
||||
if (image.depth() != 1)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
|
||||
png_set_filler(png_ptr, 0,
|
||||
QSysInfo::ByteOrder == QSysInfo::BigEndian ?
|
||||
PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
|
||||
if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
switch (image.format()) {
|
||||
case QImage::Format_RGB888:
|
||||
break;
|
||||
case QImage::Format_RGBX8888:
|
||||
case QImage::Format_RGBX64:
|
||||
png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
|
||||
break;
|
||||
default:
|
||||
png_set_filler(png_ptr, 0,
|
||||
QSysInfo::ByteOrder == QSysInfo::BigEndian ?
|
||||
PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
|
||||
}
|
||||
}
|
||||
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
|
||||
switch (image.format()) {
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
png_set_swap(png_ptr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (looping >= 0 && frames_written == 0) {
|
||||
uchar data[13] = "NETSCAPE2.0";
|
||||
@ -940,6 +1018,10 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
|
||||
case QImage::Format_RGB32:
|
||||
case QImage::Format_ARGB32:
|
||||
case QImage::Format_RGB888:
|
||||
case QImage::Format_RGBX8888:
|
||||
case QImage::Format_RGBA8888:
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
{
|
||||
png_bytep* row_pointers = new png_bytep[height];
|
||||
for (int y=0; y<height; y++)
|
||||
@ -948,6 +1030,17 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
|
||||
delete [] row_pointers;
|
||||
}
|
||||
break;
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
{
|
||||
QImage row;
|
||||
png_bytep row_pointers[1];
|
||||
for (int y=0; y<height; y++) {
|
||||
row = image.copy(0, y, width, 1).convertToFormat(QImage::Format_RGBA64);
|
||||
row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0));
|
||||
png_write_rows(png_ptr, row_pointers, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
|
||||
|
@ -106,6 +106,10 @@ QT_BEGIN_NAMESPACE
|
||||
#define GL_RGB10 0x8052
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGB16
|
||||
#define GL_RGB16 0x8054
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA8
|
||||
#define GL_RGBA8 0x8058
|
||||
#endif
|
||||
@ -114,6 +118,10 @@ QT_BEGIN_NAMESPACE
|
||||
#define GL_RGB10_A2 0x8059
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA16
|
||||
#define GL_RGBA16 0x805B
|
||||
#endif
|
||||
|
||||
#ifndef GL_BGRA
|
||||
#define GL_BGRA 0x80E1
|
||||
#endif
|
||||
@ -127,6 +135,7 @@ QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\class QOpenGLFramebufferObjectFormat
|
||||
\brief The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL
|
||||
@ -522,6 +531,8 @@ void QOpenGLFramebufferObjectPrivate::initTexture(int idx)
|
||||
GLuint pixelType = GL_UNSIGNED_BYTE;
|
||||
if (color.internalFormat == GL_RGB10_A2 || color.internalFormat == GL_RGB10)
|
||||
pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
else if (color.internalFormat == GL_RGB16 || color.internalFormat == GL_RGBA16)
|
||||
pixelType = GL_UNSIGNED_SHORT;
|
||||
|
||||
funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0,
|
||||
GL_RGBA, pixelType, NULL);
|
||||
@ -1304,6 +1315,14 @@ static inline QImage qt_gl_read_framebuffer_rgb10a2(const QSize &size, bool incl
|
||||
return img;
|
||||
}
|
||||
|
||||
static inline QImage qt_gl_read_framebuffer_rgba16(const QSize &size, bool include_alpha, QOpenGLContext *context)
|
||||
{
|
||||
// We assume OpenGL 1.2+ or ES 3.0+ here.
|
||||
QImage img(size, include_alpha ? QImage::Format_RGBA64_Premultiplied : QImage::Format_RGBX64);
|
||||
context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_SHORT, img.bits());
|
||||
return img;
|
||||
}
|
||||
|
||||
static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)
|
||||
{
|
||||
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||
@ -1318,6 +1337,10 @@ static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format,
|
||||
return qt_gl_read_framebuffer_rgb10a2(size, false, ctx).mirrored(false, flip);
|
||||
case GL_RGB10_A2:
|
||||
return qt_gl_read_framebuffer_rgb10a2(size, include_alpha, ctx).mirrored(false, flip);
|
||||
case GL_RGB16:
|
||||
return qt_gl_read_framebuffer_rgba16(size, false, ctx).mirrored(false, flip);
|
||||
case GL_RGBA16:
|
||||
return qt_gl_read_framebuffer_rgba16(size, include_alpha, ctx).mirrored(false, flip);
|
||||
case GL_RGBA:
|
||||
case GL_RGBA8:
|
||||
default:
|
||||
@ -1346,7 +1369,8 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
|
||||
is used only when internalTextureFormat() is set to \c GL_RGB. Since Qt 5.2
|
||||
the function will fall back to premultiplied RGBA8888 or RGBx8888 when
|
||||
reading to (A)RGB32 is not supported, and this includes OpenGL ES. Since Qt
|
||||
5.4 an A2BGR30 image is returned if the internal format is RGB10_A2.
|
||||
5.4 an A2BGR30 image is returned if the internal format is RGB10_A2, and since
|
||||
Qt 5.12 a RGBA64 image is return if the internal format is RGBA16.
|
||||
|
||||
If the rendering in the framebuffer was not done with premultiplied alpha in mind,
|
||||
create a wrapper QImage with a non-premultiplied format. This is necessary before
|
||||
|
@ -1567,6 +1567,7 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
|
||||
switch (image.format()) {
|
||||
case QImage::Format_RGBA8888:
|
||||
case QImage::Format_ARGB32:
|
||||
case QImage::Format_RGBA64:
|
||||
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::NonPremultipliedImageSrc);
|
||||
bindOption = 0;
|
||||
break;
|
||||
|
@ -61,6 +61,10 @@
|
||||
#define GL_RGB10_A2 0x8059
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA16
|
||||
#define GL_RGBA16 0x805B
|
||||
#endif
|
||||
|
||||
#ifndef GL_BGRA
|
||||
#define GL_BGRA 0x80E1
|
||||
#endif
|
||||
@ -193,6 +197,15 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
targetFormat = image.format();
|
||||
break;
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
externalFormat = internalFormat = GL_RGBA;
|
||||
if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3))
|
||||
internalFormat = GL_RGBA16;
|
||||
pixelType = GL_UNSIGNED_SHORT;
|
||||
targetFormat = image.format();
|
||||
break;
|
||||
case QImage::Format_Indexed8:
|
||||
if (sRgbBinding) {
|
||||
// Always needs conversion
|
||||
@ -262,11 +275,15 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
|
||||
targetFormat = QImage::Format_ARGB32_Premultiplied;
|
||||
else if (targetFormat == QImage::Format_RGBA8888)
|
||||
targetFormat = QImage::Format_RGBA8888_Premultiplied;
|
||||
else if (targetFormat == QImage::Format_RGBA64)
|
||||
targetFormat = QImage::Format_RGBA64_Premultiplied;
|
||||
} else {
|
||||
if (targetFormat == QImage::Format_ARGB32_Premultiplied)
|
||||
targetFormat = QImage::Format_ARGB32;
|
||||
else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
|
||||
targetFormat = QImage::Format_RGBA8888;
|
||||
else if (targetFormat == QImage::Format_RGBA64_Premultiplied)
|
||||
targetFormat = QImage::Format_RGBA64;
|
||||
}
|
||||
|
||||
if (sRgbBinding) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1143,6 +1143,8 @@ static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, co
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
|
||||
|
||||
const uint qt_bayer_matrix[16][16] = {
|
||||
{ 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
|
||||
0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff},
|
||||
@ -1232,9 +1234,15 @@ typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const
|
||||
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
|
||||
typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src, int index, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
|
||||
typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QVector<QRgb> *clut);
|
||||
typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *Convert64Func)(quint64 *buffer, int count, const QVector<QRgb> *clut);
|
||||
typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
|
||||
|
||||
|
||||
@ -1249,6 +1257,7 @@ struct QPixelLayout
|
||||
BPP16,
|
||||
BPP24,
|
||||
BPP32,
|
||||
BPP64,
|
||||
BPPCount
|
||||
};
|
||||
|
||||
@ -1257,17 +1266,19 @@ struct QPixelLayout
|
||||
BPP bpp;
|
||||
RbSwapFunc rbSwap;
|
||||
ConvertFunc convertToARGB32PM;
|
||||
ConvertFunc64 convertToARGB64PM;
|
||||
ConvertTo64Func convertToRGBA64PM;
|
||||
FetchAndConvertPixelsFunc fetchToARGB32PM;
|
||||
FetchAndConvertPixelsFunc64 fetchToRGBA64PM;
|
||||
ConvertAndStorePixelsFunc storeFromARGB32PM;
|
||||
ConvertAndStorePixelsFunc storeFromRGB32;
|
||||
};
|
||||
|
||||
extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
|
||||
|
||||
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
|
||||
|
||||
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QDRAWHELPER_P_H
|
||||
|
@ -332,6 +332,20 @@ void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, in
|
||||
convertARGBFromRGBA64PM_sse4<true>(dest, buffer, length);
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeARGB32FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = (uint*)dest + index;
|
||||
convertARGBFromRGBA64PM_sse4<false>(d, src, count);
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBA8888FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = (uint*)dest + index;
|
||||
convertARGBFromRGBA64PM_sse4<true>(d, src, count);
|
||||
}
|
||||
|
||||
template
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
|
@ -239,6 +239,12 @@ inline void qt_memrotate90_template<quint32>(const quint32 *src, int w, int h, i
|
||||
qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void qt_memrotate90_template<quint64>(const quint64 *src, int w, int h, int sstride, quint64 *dest, int dstride)
|
||||
{
|
||||
qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Q_STATIC_TEMPLATE_FUNCTION
|
||||
inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T *dest, int dstride)
|
||||
@ -275,6 +281,12 @@ inline void qt_memrotate270_template<quint32>(const quint32 *src, int w, int h,
|
||||
qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void qt_memrotate270_template<quint64>(const quint64 *src, int w, int h, int sstride, quint64 *dest, int dstride)
|
||||
{
|
||||
qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
|
||||
}
|
||||
|
||||
#define QT_IMPL_MEMROTATE(type) \
|
||||
Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride, \
|
||||
type *dest, int dstride) \
|
||||
@ -309,9 +321,7 @@ Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
|
||||
qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QT_IMPL_MEMROTATE(quint64)
|
||||
QT_IMPL_MEMROTATE(quint32)
|
||||
QT_IMPL_MEMROTATE(quint16)
|
||||
QT_IMPL_MEMROTATE(quint24)
|
||||
@ -377,6 +387,22 @@ void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
|
||||
qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
|
||||
void qt_memrotate90_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
{
|
||||
qt_memrotate90((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
void qt_memrotate180_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
{
|
||||
qt_memrotate180((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
{
|
||||
qt_memrotate270((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
|
||||
// 90, 180, 270
|
||||
{
|
||||
@ -387,6 +413,7 @@ MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
|
||||
{ qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 }, // BPP16,
|
||||
{ qt_memrotate90_24, qt_memrotate180_24, qt_memrotate270_24 }, // BPP24
|
||||
{ qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // BPP32
|
||||
{ qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP64
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -65,6 +65,7 @@ QT_DECL_MEMROTATE(quint32);
|
||||
QT_DECL_MEMROTATE(quint16);
|
||||
QT_DECL_MEMROTATE(quint24);
|
||||
QT_DECL_MEMROTATE(quint8);
|
||||
QT_DECL_MEMROTATE(quint64);
|
||||
|
||||
#undef QT_DECL_MEMROTATE
|
||||
|
||||
|
@ -291,6 +291,12 @@ static QLatin1String formatToString(QImage::Format format)
|
||||
return QLatin1String("Alpha8");
|
||||
case QImage::Format_Grayscale8:
|
||||
return QLatin1String("Grayscale8");
|
||||
case QImage::Format_RGBX64:
|
||||
return QLatin1String("RGBx64");
|
||||
case QImage::Format_RGBA64:
|
||||
return QLatin1String("RGBA64");
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
return QLatin1String("RGBA64pm");
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -2347,7 +2353,9 @@ void tst_QImage::rgbSwapped_data()
|
||||
{
|
||||
QTest::addColumn<QImage::Format>("format");
|
||||
|
||||
for (int i = QImage::Format_Indexed8; i < QImage::Format_Alpha8; ++i) {
|
||||
for (int i = QImage::Format_Indexed8; i < QImage::NImageFormats; ++i) {
|
||||
if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
|
||||
continue;
|
||||
QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
|
||||
}
|
||||
}
|
||||
@ -2515,14 +2523,7 @@ void tst_QImage::mirrored()
|
||||
|
||||
void tst_QImage::inplaceRgbSwapped_data()
|
||||
{
|
||||
QTest::addColumn<QImage::Format>("format");
|
||||
|
||||
QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
|
||||
QTest::newRow("Format_RGBA8888") << QImage::Format_RGBA8888;
|
||||
QTest::newRow("Format_A2RGB30_Premultiplied") << QImage::Format_A2RGB30_Premultiplied;
|
||||
QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
|
||||
QTest::newRow("Format_RGB16") << QImage::Format_RGB16;
|
||||
QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8;
|
||||
rgbSwapped_data();
|
||||
}
|
||||
|
||||
void tst_QImage::inplaceRgbSwapped()
|
||||
@ -2553,9 +2554,9 @@ void tst_QImage::inplaceRgbSwapped()
|
||||
for (int i = 0; i < imageSwapped.width(); ++i) {
|
||||
QRgb referenceColor = testColor[i];
|
||||
QRgb swappedColor = imageSwapped.pixel(i, 0);
|
||||
QCOMPARE(qRed(swappedColor) & 0xf8, qBlue(referenceColor) & 0xf8);
|
||||
QCOMPARE(qGreen(swappedColor) & 0xf8, qGreen(referenceColor) & 0xf8);
|
||||
QCOMPARE(qBlue(swappedColor) & 0xf8, qRed(referenceColor) & 0xf8);
|
||||
QCOMPARE(qRed(swappedColor) & 0xf0, qBlue(referenceColor) & 0xf0);
|
||||
QCOMPARE(qGreen(swappedColor) & 0xf0, qGreen(referenceColor) & 0xf0);
|
||||
QCOMPARE(qBlue(swappedColor) & 0xf0, qRed(referenceColor) & 0xf0);
|
||||
}
|
||||
|
||||
QCOMPARE(imageSwapped.constScanLine(0), orginalPtr);
|
||||
@ -2771,9 +2772,13 @@ void tst_QImage::genericRgbConversion_data()
|
||||
QTest::addColumn<QImage::Format>("format");
|
||||
QTest::addColumn<QImage::Format>("dest_format");
|
||||
|
||||
for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
|
||||
for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
|
||||
if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
|
||||
continue;
|
||||
const QLatin1String formatI = formatToString(QImage::Format(i));
|
||||
for (int j = QImage::Format_RGB32; j < QImage::Format_Alpha8; ++j) {
|
||||
for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) {
|
||||
if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8)
|
||||
continue;
|
||||
if (i == j)
|
||||
continue;
|
||||
QTest::addRow("%s -> %s", formatI.data(), formatToString(QImage::Format(j)).data())
|
||||
@ -2810,8 +2815,12 @@ void tst_QImage::inplaceRgbConversion_data()
|
||||
QTest::addColumn<QImage::Format>("format");
|
||||
QTest::addColumn<QImage::Format>("dest_format");
|
||||
|
||||
for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
|
||||
for (int j = QImage::Format_RGB32; j < QImage::Format_Alpha8; ++j) {
|
||||
for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
|
||||
if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
|
||||
continue;
|
||||
for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) {
|
||||
if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8)
|
||||
continue;
|
||||
if (i == j)
|
||||
continue;
|
||||
QTest::addRow("%s -> %s", formatToString(QImage::Format(i)).data(), formatToString(QImage::Format(j)).data())
|
||||
@ -2844,10 +2853,10 @@ void tst_QImage::inplaceRgbConversion()
|
||||
QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16);
|
||||
}
|
||||
}
|
||||
if (image.depth() == imageConverted.depth())
|
||||
if (qt_depthForFormat(format) == qt_depthForFormat(dest_format))
|
||||
QCOMPARE(imageConverted.constScanLine(0), originalPtr);
|
||||
|
||||
{
|
||||
if (qt_depthForFormat(format) <= 32) {
|
||||
// Test attempted inplace conversion of images created on existing buffer
|
||||
static const quint32 readOnlyData[] = { 0xff0102ffU, 0xff0506ffU, 0xff0910ffU, 0xff1314ffU };
|
||||
quint32 readWriteData[] = { 0xff0102ffU, 0xff0506ffU, 0xff0910ffU, 0xff1314ffU };
|
||||
@ -2980,7 +2989,9 @@ void tst_QImage::invertPixelsRGB_data()
|
||||
{
|
||||
QTest::addColumn<QImage::Format>("image_format");
|
||||
|
||||
for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
|
||||
for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
|
||||
if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
|
||||
continue;
|
||||
QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
|
||||
}
|
||||
}
|
||||
|
BIN
tests/auto/gui/image/qimagereader/images/kollada-16bpc.png
Normal file
BIN
tests/auto/gui/image/qimagereader/images/kollada-16bpc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -234,6 +234,7 @@ void tst_QImageReader::readImage_data()
|
||||
QTest::newRow("BMP: high mask bit set") << QString("rgb32bf.bmp") << true << QByteArray("bmp");
|
||||
QTest::newRow("XPM: marble") << QString("marble.xpm") << true << QByteArray("xpm");
|
||||
QTest::newRow("PNG: kollada") << QString("kollada.png") << true << QByteArray("png");
|
||||
QTest::newRow("PNG: kollada 16bpc") << QString("kollada-16bpc.png") << true << QByteArray("png");
|
||||
QTest::newRow("PPM: teapot") << QString("teapot.ppm") << true << QByteArray("ppm");
|
||||
QTest::newRow("PPM: runners") << QString("runners.ppm") << true << QByteArray("ppm");
|
||||
QTest::newRow("PPM: test") << QString("test.ppm") << true << QByteArray("ppm");
|
||||
@ -523,6 +524,7 @@ void tst_QImageReader::imageFormat_data()
|
||||
QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
|
||||
QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
|
||||
QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
|
||||
QTest::newRow("png-3") << QString("kollada-16bpc.png") << QByteArray("png") << QImage::Format_RGBA64;
|
||||
QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg") << QImage::Format_ARGB32_Premultiplied;
|
||||
QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz") << QImage::Format_ARGB32_Premultiplied;
|
||||
}
|
||||
@ -1850,6 +1852,8 @@ void tst_QImageReader::saveFormat_data()
|
||||
QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
|
||||
QTest::newRow("Format_RGB444") << QImage::Format_RGB444;
|
||||
QTest::newRow("Format_ARGB4444_Premultiplied") << QImage::Format_ARGB4444_Premultiplied;
|
||||
QTest::newRow("Format_RGBA64") << QImage::Format_RGBA64;
|
||||
QTest::newRow("Format_RGBA64_Premultiplied") << QImage::Format_RGBA64_Premultiplied;
|
||||
}
|
||||
|
||||
void tst_QImageReader::saveFormat()
|
||||
|
@ -1091,6 +1091,7 @@ void tst_QPainter::fillRect_data()
|
||||
|
||||
QTest::newRow("argb32pm") << QImage::Format_ARGB32_Premultiplied;
|
||||
QTest::newRow("rgba8888pm") << QImage::Format_RGBA8888_Premultiplied;
|
||||
QTest::newRow("rgba64pm") << QImage::Format_RGBA64_Premultiplied;
|
||||
}
|
||||
|
||||
void tst_QPainter::fillRect()
|
||||
@ -2443,6 +2444,24 @@ void tst_QPainter::setOpacity_data()
|
||||
QTest::newRow("A2RGB30P on RGB30") << QImage::Format_RGB30
|
||||
<< QImage::Format_A2RGB30_Premultiplied;
|
||||
|
||||
QTest::newRow("RGBA64P on RGBA64P") << QImage::Format_RGBA64_Premultiplied
|
||||
<< QImage::Format_RGBA64_Premultiplied;
|
||||
|
||||
QTest::newRow("RGBA64 on RGBA64") << QImage::Format_RGBA64
|
||||
<< QImage::Format_RGBA64;
|
||||
|
||||
QTest::newRow("RGBx64 on RGBx64") << QImage::Format_RGBX64
|
||||
<< QImage::Format_RGBX64;
|
||||
|
||||
QTest::newRow("RGBA64P on ARGB32P") << QImage::Format_ARGB32_Premultiplied
|
||||
<< QImage::Format_RGBA64_Premultiplied;
|
||||
|
||||
QTest::newRow("RGBx64 on ARGB32P") << QImage::Format_ARGB32_Premultiplied
|
||||
<< QImage::Format_RGBX64;
|
||||
|
||||
QTest::newRow("ARGB32P on RGBA64P") << QImage::Format_RGBA64_Premultiplied
|
||||
<< QImage::Format_ARGB32_Premultiplied;
|
||||
|
||||
}
|
||||
|
||||
void tst_QPainter::setOpacity()
|
||||
@ -3847,6 +3866,8 @@ void tst_QPainter::gradientPixelFormat_data()
|
||||
QTest::newRow("rgbx8888") << QImage::Format_RGBX8888;
|
||||
QTest::newRow("rgba8888") << QImage::Format_RGBA8888;
|
||||
QTest::newRow("rgba8888_pm") << QImage::Format_RGBA8888_Premultiplied;
|
||||
QTest::newRow("rgbx64") << QImage::Format_RGBX64;
|
||||
QTest::newRow("rgba64_pm") << QImage::Format_RGBA64_Premultiplied;
|
||||
}
|
||||
|
||||
void tst_QPainter::gradientPixelFormat()
|
||||
@ -4784,7 +4805,19 @@ void tst_QPainter::blendARGBonRGB_data()
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 255 ;
|
||||
QTest::newRow("ARGB_PM source-in ARGB32") << QImage::Format_ARGB32 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 255;
|
||||
// Only ARGB does inverse premultiply, on the rest over and source gives similar results:
|
||||
QTest::newRow("ARGB over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB_PM over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_SourceOver << qRgba(127, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB_PM source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_Source << qRgba(127, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB_PM source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 255;
|
||||
// Only ARGB32 and RGBA8888 does inverse premultiply, on the rest over and source gives similar results:
|
||||
QTest::newRow("ARGB over RGB32") << QImage::Format_RGB32 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB_PM over RGB32") << QImage::Format_RGB32 << QImage::Format_ARGB32_Premultiplied
|
||||
@ -4821,18 +4854,6 @@ void tst_QPainter::blendARGBonRGB_data()
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB_PM source-in RGBx8888") << QImage::Format_RGBX8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB_PM over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_SourceOver << qRgba(127, 0, 0, 127) << 127;
|
||||
QTest::newRow("ARGB source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB_PM source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_Source << qRgba(127, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB_PM source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
|
||||
<< QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 255;
|
||||
QTest::newRow("ARGB over RGB16") << QImage::Format_RGB16 << QImage::Format_ARGB32
|
||||
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 123;
|
||||
QTest::newRow("ARGB_PM over RGB16") << QImage::Format_RGB16 << QImage::Format_ARGB32_Premultiplied
|
||||
|
@ -82,6 +82,8 @@ private slots:
|
||||
void fboRendering();
|
||||
void fboRenderingRGB30_data();
|
||||
void fboRenderingRGB30();
|
||||
void fboRenderingRGB64_data();
|
||||
void fboRenderingRGB64();
|
||||
void fboHandleNulledAfterContextDestroyed();
|
||||
void fboMRT();
|
||||
void fboMRT_differentFormats();
|
||||
@ -614,6 +616,10 @@ void tst_QOpenGL::fboRenderingRGB30_data()
|
||||
#define GL_RGB10_A2 0x8059
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA16
|
||||
#define GL_RGBA16 0x805B
|
||||
#endif
|
||||
|
||||
#ifndef GL_FRAMEBUFFER_RENDERABLE
|
||||
#define GL_FRAMEBUFFER_RENDERABLE 0x8289
|
||||
#endif
|
||||
@ -622,7 +628,7 @@ void tst_QOpenGL::fboRenderingRGB30_data()
|
||||
#define GL_FULL_SUPPORT 0x82B7
|
||||
#endif
|
||||
|
||||
static bool hasRGB10A2(QOpenGLContext *ctx)
|
||||
static bool supportsInternalFboFormat(QOpenGLContext *ctx, int glFormat)
|
||||
{
|
||||
if (ctx->format().majorVersion() < 3)
|
||||
return false;
|
||||
@ -631,7 +637,7 @@ static bool hasRGB10A2(QOpenGLContext *ctx)
|
||||
GLint value = -1;
|
||||
QOpenGLFunctions_4_2_Core* vFuncs = ctx->versionFunctions<QOpenGLFunctions_4_2_Core>();
|
||||
if (vFuncs && vFuncs->initializeOpenGLFunctions()) {
|
||||
vFuncs->glGetInternalformativ(GL_TEXTURE_2D, GL_RGB10_A2, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
|
||||
vFuncs->glGetInternalformativ(GL_TEXTURE_2D, glFormat, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
|
||||
if (value != GL_FULL_SUPPORT)
|
||||
return false;
|
||||
}
|
||||
@ -657,7 +663,7 @@ void tst_QOpenGL::fboRenderingRGB30()
|
||||
if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
|
||||
QSKIP("QOpenGLFramebufferObject not supported on this platform");
|
||||
|
||||
if (!hasRGB10A2(&ctx))
|
||||
if (!supportsInternalFboFormat(&ctx, GL_RGB10_A2))
|
||||
QSKIP("An internal RGB30_A2 format is not guaranteed on this platform");
|
||||
|
||||
// No multisample with combined depth/stencil attachment:
|
||||
@ -713,6 +719,71 @@ void tst_QOpenGL::fboRenderingRGB30()
|
||||
QVERIFY(((pixel >> 20) & 0x3f) > 0);
|
||||
}
|
||||
|
||||
void tst_QOpenGL::fboRenderingRGB64_data()
|
||||
{
|
||||
common_data();
|
||||
}
|
||||
|
||||
void tst_QOpenGL::fboRenderingRGB64()
|
||||
{
|
||||
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__)
|
||||
QSKIP("QTBUG-22617");
|
||||
#endif
|
||||
|
||||
QFETCH(int, surfaceClass);
|
||||
QScopedPointer<QSurface> surface(createSurface(surfaceClass));
|
||||
|
||||
QOpenGLContext ctx;
|
||||
QVERIFY(ctx.create());
|
||||
|
||||
QVERIFY(ctx.makeCurrent(surface.data()));
|
||||
|
||||
if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
|
||||
QSKIP("QOpenGLFramebufferObject not supported on this platform");
|
||||
|
||||
if (!supportsInternalFboFormat(&ctx, GL_RGBA16))
|
||||
QSKIP("An internal RGBA16 format is not guaranteed on this platform");
|
||||
|
||||
// No multisample with combined depth/stencil attachment:
|
||||
QOpenGLFramebufferObjectFormat fboFormat;
|
||||
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||
fboFormat.setInternalTextureFormat(GL_RGBA16);
|
||||
|
||||
// Uncomplicate things by using POT:
|
||||
const QSize size(256, 128);
|
||||
QOpenGLFramebufferObject fbo(size, fboFormat);
|
||||
|
||||
if (fbo.attachment() != QOpenGLFramebufferObject::CombinedDepthStencil)
|
||||
QSKIP("FBOs missing combined depth~stencil support");
|
||||
|
||||
QVERIFY(fbo.bind());
|
||||
|
||||
QPainter fboPainter;
|
||||
QOpenGLPaintDevice device(fbo.width(), fbo.height());
|
||||
bool painterBegun = fboPainter.begin(&device);
|
||||
QVERIFY(painterBegun);
|
||||
|
||||
qt_opengl_draw_test_pattern(&fboPainter, fbo.width(), fbo.height());
|
||||
|
||||
fboPainter.end();
|
||||
|
||||
QImage fb = fbo.toImage();
|
||||
QCOMPARE(fb.format(), QImage::Format_RGBA64_Premultiplied);
|
||||
QCOMPARE(fb.size(), size);
|
||||
|
||||
qt_opengl_check_test_pattern(fb);
|
||||
|
||||
// Check rendering can handle precise 16 bit color values.
|
||||
fboPainter.begin(&device);
|
||||
fboPainter.fillRect(QRect(0, 0, 256, 128), QColor::fromRgba64(5, 1002, 8001, 65535));
|
||||
fboPainter.end();
|
||||
fb = fbo.toImage();
|
||||
QRgba64 pixel = ((QRgba64*)fb.bits())[0];
|
||||
QCOMPARE(pixel.red(), 5);
|
||||
QCOMPARE(pixel.green(), 1002);
|
||||
QCOMPARE(pixel.blue(), 8001);
|
||||
}
|
||||
|
||||
void tst_QOpenGL::fboHandleNulledAfterContextDestroyed()
|
||||
{
|
||||
QWindow window;
|
||||
@ -844,7 +915,7 @@ void tst_QOpenGL::fboMRT_differentFormats()
|
||||
if (!f->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets))
|
||||
QSKIP("Multiple render targets not supported on this platform");
|
||||
|
||||
if (!hasRGB10A2(&ctx))
|
||||
if (!supportsInternalFboFormat(&ctx, GL_RGB10_A2))
|
||||
QSKIP("RGB10_A2 not supported on this platform");
|
||||
|
||||
// 3 color attachments, same size, different internal format, depth/stencil.
|
||||
|
@ -177,6 +177,9 @@ const char *PaintCommands::imageFormatTable[] = {
|
||||
"Format_A2RGB30_Premultiplied",
|
||||
"Alpha8",
|
||||
"Grayscale8",
|
||||
"RGBx64",
|
||||
"RGBA64",
|
||||
"RGBA64_Premultiplied",
|
||||
};
|
||||
|
||||
int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit)
|
||||
|
@ -649,6 +649,9 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps)
|
||||
"A2RGB30_pm",
|
||||
"Alpha8",
|
||||
"Grayscale8",
|
||||
"RGBx64",
|
||||
"RGBA64",
|
||||
"RGBA64_pm",
|
||||
};
|
||||
|
||||
const QImage::Format pixmapFormats[] = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user