Introduce float QImage formats and rendering
Useful for some HDR representations and HDR rendering. Change-Id: If6e8a661faa3d2afdf17b6ed4d8ff5c5b2aeb30e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>bb10
parent
e51831260a
commit
93cd9130d6
|
|
@ -195,6 +195,7 @@ qt_internal_add_module(Gui
|
|||
painting/qregion.cpp painting/qregion.h
|
||||
painting/qrgb.h
|
||||
painting/qrgba64.h painting/qrgba64_p.h
|
||||
painting/qrgbaf.h
|
||||
painting/qstroker.cpp painting/qstroker_p.h
|
||||
painting/qtextureglyphcache.cpp painting/qtextureglyphcache_p.h
|
||||
painting/qtransform.cpp painting/qtransform.h
|
||||
|
|
|
|||
|
|
@ -1154,6 +1154,11 @@ qt_feature("raster-64bit" PRIVATE
|
|||
LABEL "QPainter - 64 bit raster"
|
||||
PURPOSE "Internal painting support for 64 bit (16 bpc) rasterization."
|
||||
)
|
||||
qt_feature("raster-fp" PRIVATE
|
||||
SECTION "Painting"
|
||||
LABEL "QPainter - floating point raster"
|
||||
PURPOSE "Internal painting support for floating point rasterization."
|
||||
)
|
||||
qt_feature("undocommand" PUBLIC
|
||||
SECTION "Utilities"
|
||||
LABEL "QUndoCommand"
|
||||
|
|
|
|||
|
|
@ -1663,6 +1663,12 @@
|
|||
"section": "Painting",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"raster-fp": {
|
||||
"label": "QPainter - floating point raster",
|
||||
"purpose": "Internal painting support for floating point rasterization.",
|
||||
"section": "Painting",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"undocommand": {
|
||||
"label": "QUndoCommand",
|
||||
"purpose": "Applies (redo or) undo of a single change in a document.",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
|
|
@ -42,10 +42,12 @@
|
|||
#include "qbuffer.h"
|
||||
#include "qdatastream.h"
|
||||
#include "qcolortransform.h"
|
||||
#include "qfloat16.h"
|
||||
#include "qmap.h"
|
||||
#include "qtransform.h"
|
||||
#include "qimagereader.h"
|
||||
#include "qimagewriter.h"
|
||||
#include "qrgbaf.h"
|
||||
#include "qstringlist.h"
|
||||
#include "qvariant.h"
|
||||
#include "qimagepixmapcleanuphooks_p.h"
|
||||
|
|
@ -293,6 +295,24 @@ bool QImageData::checkForAlphaPixels() const
|
|||
bits += bytes_per_line;
|
||||
}
|
||||
} break;
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied: {
|
||||
uchar *bits = data;
|
||||
for (int y = 0; y < height && !has_alpha_pixels; ++y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
|
||||
bits += bytes_per_line;
|
||||
}
|
||||
} break;
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied: {
|
||||
uchar *bits = data;
|
||||
for (int y = 0; y < height && !has_alpha_pixels; ++y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
has_alpha_pixels |= ((float *)bits)[x * 4 + 3] < 1.0f;
|
||||
bits += bytes_per_line;
|
||||
}
|
||||
} break;
|
||||
|
||||
case QImage::Format_RGB32:
|
||||
case QImage::Format_RGB16:
|
||||
|
|
@ -307,6 +327,8 @@ bool QImageData::checkForAlphaPixels() const
|
|||
case QImage::Format_Grayscale8:
|
||||
case QImage::Format_Grayscale16:
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
break;
|
||||
case QImage::Format_Invalid:
|
||||
case QImage::NImageFormats:
|
||||
|
|
@ -735,6 +757,16 @@ bool QImageData::checkForAlphaPixels() const
|
|||
\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)
|
||||
\value Format_BGR888 The image is stored using a 24-bit BGR format. (added in Qt 5.14)
|
||||
\value Format_RGBX16FPx4 The image is stored using a 4 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
|
||||
This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0. (added in Qt 6.2)
|
||||
\value Format_RGBA16FPx4 The image is stored using a 4 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
|
||||
\value Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied 4 16-bit halfword floating point
|
||||
RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
|
||||
\value Format_RGBX32FPx4 The image is stored using a 4 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
|
||||
This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0. (added in Qt 6.2)
|
||||
\value Format_RGBA32FPx4 The image is stored using a 4 32-bit floating point RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
|
||||
\value Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied 4 32-bit floating point
|
||||
RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
|
||||
|
||||
\note Drawing into a QImage with QImage::Format_Indexed8 is not
|
||||
supported.
|
||||
|
|
@ -1741,11 +1773,29 @@ 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) {
|
||||
} else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
|
||||
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
|
||||
0, 0, d->width, d->height, d->bytes_per_line);
|
||||
return;
|
||||
} else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
|
||||
quint64 cu;
|
||||
QRgba16F cf = QRgba16F::fromArgb32(pixel);
|
||||
::memcpy(&cu, &cf, sizeof(quint64));
|
||||
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), cu,
|
||||
0, 0, d->width, d->height, d->bytes_per_line);
|
||||
return;
|
||||
} else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
|
||||
QRgba32F cf = QRgba32F::fromArgb32(pixel);
|
||||
uchar *data = d->data;
|
||||
for (int y = 0; y < d->height; ++y) {
|
||||
QRgba32F *line = reinterpret_cast<QRgba32F *>(data);
|
||||
for (int x = 0; x < d->width; ++x)
|
||||
line[x] = cf;
|
||||
data += d->bytes_per_line;
|
||||
}
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(d->depth == 32);
|
||||
|
||||
if (d->format == Format_RGB32)
|
||||
pixel |= 0xff000000;
|
||||
|
|
@ -1907,7 +1957,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 (depth() > 32) {
|
||||
if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
|
||||
if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
|
||||
*this = convertToFormat(QImage::Format_RGBA16FPx4);
|
||||
} else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
|
||||
if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
|
||||
*this = convertToFormat(QImage::Format_RGBA32FPx4);
|
||||
} else if (depth() > 32) {
|
||||
if (!d->convertInPlace(QImage::Format_RGBA64, { }))
|
||||
*this = convertToFormat(QImage::Format_RGBA64);
|
||||
} else {
|
||||
|
|
@ -1926,8 +1982,32 @@ void QImage::invertPixels(InvertMode mode)
|
|||
*sl++ ^= 0xff;
|
||||
sl += pad;
|
||||
}
|
||||
}
|
||||
else if (depth() == 64) {
|
||||
} else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
|
||||
qfloat16 *p = reinterpret_cast<qfloat16 *>(d->data);
|
||||
qfloat16 *end = reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
|
||||
while (p < end) {
|
||||
p[0] = 1.0f - p[0];
|
||||
p[1] = 1.0f - p[1];
|
||||
p[2] = 1.0f - p[2];
|
||||
if (mode == InvertRgba)
|
||||
p[3] = 1.0f - p[3];
|
||||
p += 4;
|
||||
}
|
||||
} else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
|
||||
uchar *data = d->data;
|
||||
for (int y = 0; y < d->height; ++y) {
|
||||
float *p = reinterpret_cast<float *>(data);
|
||||
for (int x = 0; x < d->width; ++x) {
|
||||
p[0] = 1.0f - p[0];
|
||||
p[1] = 1.0f - p[1];
|
||||
p[2] = 1.0f - p[2];
|
||||
if (mode == InvertRgba)
|
||||
p[3] = 1.0f - p[3];
|
||||
p += 4;
|
||||
}
|
||||
data += d->bytes_per_line;
|
||||
}
|
||||
} else if (depth() == 64) {
|
||||
quint16 *p = (quint16*)d->data;
|
||||
quint16 *end = (quint16*)(d->data + d->nbytes);
|
||||
quint16 xorbits = 0xffff;
|
||||
|
|
@ -2085,7 +2165,12 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
|
|||
if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
|
||||
if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
|
||||
&& qt_highColorPrecision(format, !hasAlphaChannel())) {
|
||||
converter = convert_generic_over_rgb64;
|
||||
#if QT_CONFIG(raster_fp)
|
||||
if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
|
||||
converter = convert_generic_over_rgba32f;
|
||||
else
|
||||
#endif
|
||||
converter = convert_generic_over_rgb64;
|
||||
} else
|
||||
converter = convert_generic;
|
||||
}
|
||||
|
|
@ -2418,6 +2503,14 @@ QRgb QImage::pixel(int x, int y) const
|
|||
case Format_RGBA64: // Match ARGB32 behavior.
|
||||
case Format_RGBA64_Premultiplied:
|
||||
return reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
|
||||
case Format_RGBX16FPx4:
|
||||
case Format_RGBA16FPx4: // Match ARGB32 behavior.
|
||||
case Format_RGBA16FPx4_Premultiplied:
|
||||
return reinterpret_cast<const QRgba16F *>(s)[x].toArgb32();
|
||||
case Format_RGBX32FPx4:
|
||||
case Format_RGBA32FPx4: // Match ARGB32 behavior.
|
||||
case Format_RGBA32FPx4_Premultiplied:
|
||||
return reinterpret_cast<const QRgba32F *>(s)[x].toArgb32();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -2519,6 +2612,20 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
|
|||
case Format_RGBA64_Premultiplied:
|
||||
((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
|
||||
return;
|
||||
case Format_RGBX16FPx4:
|
||||
((QRgba16F *)s)[x] = QRgba16F::fromArgb32(index_or_rgb | 0xff000000);
|
||||
return;
|
||||
case Format_RGBA16FPx4:
|
||||
case Format_RGBA16FPx4_Premultiplied:
|
||||
((QRgba16F *)s)[x] = QRgba16F::fromArgb32(index_or_rgb);
|
||||
return;
|
||||
case Format_RGBX32FPx4:
|
||||
((QRgba32F *)s)[x] = QRgba32F::fromArgb32(index_or_rgb | 0xff000000);
|
||||
return;
|
||||
case Format_RGBA32FPx4:
|
||||
case Format_RGBA32FPx4_Premultiplied:
|
||||
((QRgba32F *)s)[x] = QRgba32F::fromArgb32(index_or_rgb);
|
||||
return;
|
||||
case Format_Invalid:
|
||||
case NImageFormats:
|
||||
Q_ASSERT(false);
|
||||
|
|
@ -2583,6 +2690,26 @@ QColor QImage::pixelColor(int x, int y) const
|
|||
quint16 v = reinterpret_cast<const quint16 *>(s)[x];
|
||||
return QColor(qRgba64(v, v, v, 0xffff));
|
||||
}
|
||||
case Format_RGBX16FPx4:
|
||||
case Format_RGBA16FPx4:
|
||||
case Format_RGBA16FPx4_Premultiplied: {
|
||||
QRgba16F p = reinterpret_cast<const QRgba16F *>(s)[x];
|
||||
if (d->format == Format_RGBA16FPx4_Premultiplied)
|
||||
p = p.unpremultiplied();
|
||||
QColor color;
|
||||
color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
|
||||
return color;
|
||||
}
|
||||
case Format_RGBX32FPx4:
|
||||
case Format_RGBA32FPx4:
|
||||
case Format_RGBA32FPx4_Premultiplied: {
|
||||
QRgba32F p = reinterpret_cast<const QRgba32F *>(s)[x];
|
||||
if (d->format == Format_RGBA32FPx4_Premultiplied)
|
||||
p = p.unpremultiplied();
|
||||
QColor color;
|
||||
color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
|
||||
return color;
|
||||
}
|
||||
default:
|
||||
c = QRgba64::fromArgb32(pixel(x, y));
|
||||
break;
|
||||
|
|
@ -2658,6 +2785,32 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
|
|||
case Format_RGBA64_Premultiplied:
|
||||
((QRgba64 *)s)[x] = c;
|
||||
return;
|
||||
case Format_RGBX16FPx4:
|
||||
case Format_RGBA16FPx4:
|
||||
case Format_RGBA16FPx4_Premultiplied: {
|
||||
float r, g, b, a;
|
||||
color.getRgbF(&r, &g, &b, &a);
|
||||
if (d->format == Format_RGBX16FPx4)
|
||||
a = 1.0f;
|
||||
QRgba16F c16f{r, g, b, a};
|
||||
if (d->format == Format_RGBA16FPx4_Premultiplied)
|
||||
c16f = c16f.premultiplied();
|
||||
((QRgba16F *)s)[x] = c16f;
|
||||
return;
|
||||
}
|
||||
case Format_RGBX32FPx4:
|
||||
case Format_RGBA32FPx4:
|
||||
case Format_RGBA32FPx4_Premultiplied: {
|
||||
float r, g, b, a;
|
||||
color.getRgbF(&r, &g, &b, &a);
|
||||
if (d->format == Format_RGBX32FPx4)
|
||||
a = 1.0f;
|
||||
QRgba32F c32f{r, g, b, a};
|
||||
if (d->format == Format_RGBA32FPx4_Premultiplied)
|
||||
c32f = c32f.premultiplied();
|
||||
((QRgba32F *)s)[x] = c32f;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
setPixel(x, y, c.toArgb32());
|
||||
return;
|
||||
|
|
@ -3218,6 +3371,9 @@ inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool ve
|
|||
}
|
||||
|
||||
switch (depth) {
|
||||
case 128:
|
||||
do_mirror_data<QRgba32F>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
|
||||
break;
|
||||
case 64:
|
||||
do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
|
||||
break;
|
||||
|
|
@ -4409,8 +4565,12 @@ int QImage::bitPlaneCount() const
|
|||
bpc = 12;
|
||||
break;
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
bpc = 48;
|
||||
break;
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
bpc = 96;
|
||||
break;
|
||||
default:
|
||||
bpc = qt_depthForFormat(d->format);
|
||||
break;
|
||||
|
|
@ -4429,7 +4589,8 @@ int QImage::bitPlaneCount() const
|
|||
if necessary. To avoid unnecessary conversion the result is returned in the format
|
||||
internally used, and not in the original format.
|
||||
*/
|
||||
QImage QImage::smoothScaled(int w, int h) const {
|
||||
QImage QImage::smoothScaled(int w, int h) const
|
||||
{
|
||||
QImage src = *this;
|
||||
switch (src.format()) {
|
||||
case QImage::Format_RGB32:
|
||||
|
|
@ -4443,14 +4604,28 @@ QImage QImage::smoothScaled(int w, int h) const {
|
|||
case QImage::Format_RGBA64_Premultiplied:
|
||||
break;
|
||||
case QImage::Format_RGBA64:
|
||||
src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied);
|
||||
case QImage::Format_Grayscale16:
|
||||
src.convertTo(QImage::Format_RGBA64_Premultiplied);
|
||||
break;
|
||||
#endif
|
||||
#if QT_CONFIG(raster_fp)
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
break;
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
src.convertTo(QImage::Format_RGBX32FPx4);
|
||||
break;
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (src.hasAlphaChannel())
|
||||
src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
src.convertTo(QImage::Format_ARGB32_Premultiplied);
|
||||
else
|
||||
src = src.convertToFormat(QImage::Format_RGB32);
|
||||
src.convertTo(QImage::Format_RGB32);
|
||||
}
|
||||
src = qSmoothScaleImage(src, w, h);
|
||||
if (!src.isNull())
|
||||
|
|
@ -4903,6 +5078,10 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
|
|||
// any direct ones are probably better even if not inplace.
|
||||
if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
|
||||
&& qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
|
||||
#if QT_CONFIG(raster_fp)
|
||||
if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
|
||||
return convert_generic_inplace_over_rgba32f(this, newFormat, flags);
|
||||
#endif
|
||||
return convert_generic_inplace_over_rgb64(this, newFormat, flags);
|
||||
}
|
||||
return convert_generic_inplace(this, newFormat, flags);
|
||||
|
|
@ -5328,6 +5507,84 @@ static constexpr QPixelFormat pixelformats[] = {
|
|||
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBX16FPx4:
|
||||
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::FloatingPoint,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBA16FPx4:
|
||||
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::FloatingPoint,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBA16FPx4_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::FloatingPoint,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBX32FPx4:
|
||||
QPixelFormat(QPixelFormat::RGB,
|
||||
/*RED*/ 32,
|
||||
/*GREEN*/ 32,
|
||||
/*BLUE*/ 32,
|
||||
/*FOURTH*/ 0,
|
||||
/*FIFTH*/ 0,
|
||||
/*ALPHA*/ 32,
|
||||
/*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
|
||||
/*ALPHA POSITION*/ QPixelFormat::AtEnd,
|
||||
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::FloatingPoint,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBA32FPx4:
|
||||
QPixelFormat(QPixelFormat::RGB,
|
||||
/*RED*/ 32,
|
||||
/*GREEN*/ 32,
|
||||
/*BLUE*/ 32,
|
||||
/*FOURTH*/ 0,
|
||||
/*FIFTH*/ 0,
|
||||
/*ALPHA*/ 32,
|
||||
/*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
|
||||
/*ALPHA POSITION*/ QPixelFormat::AtEnd,
|
||||
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::FloatingPoint,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
//QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
QPixelFormat(QPixelFormat::RGB,
|
||||
/*RED*/ 32,
|
||||
/*GREEN*/ 32,
|
||||
/*BLUE*/ 32,
|
||||
/*FOURTH*/ 0,
|
||||
/*FIFTH*/ 0,
|
||||
/*ALPHA*/ 32,
|
||||
/*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
|
||||
/*ALPHA POSITION*/ QPixelFormat::AtEnd,
|
||||
/*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
|
||||
/*INTERPRETATION*/ QPixelFormat::FloatingPoint,
|
||||
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
|
||||
};
|
||||
static_assert(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
|
|
@ -104,6 +104,12 @@ public:
|
|||
Format_RGBA64_Premultiplied,
|
||||
Format_Grayscale16,
|
||||
Format_BGR888,
|
||||
Format_RGBX16FPx4,
|
||||
Format_RGBA16FPx4,
|
||||
Format_RGBA16FPx4_Premultiplied,
|
||||
Format_RGBX32FPx4,
|
||||
Format_RGBA32FPx4,
|
||||
Format_RGBA32FPx4_Premultiplied,
|
||||
#ifndef Q_QDOC
|
||||
NImageFormats
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
|
|
@ -47,6 +47,7 @@
|
|||
#include <private/qimage_p.h>
|
||||
|
||||
#include <qendian.h>
|
||||
#include <qrgbaf.h>
|
||||
#if QT_CONFIG(thread)
|
||||
#include <qsemaphore.h>
|
||||
#include <qthreadpool.h>
|
||||
|
|
@ -313,6 +314,61 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
|
|||
#endif
|
||||
}
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(dest->format >= QImage::Format_RGBX16FPx4);
|
||||
Q_ASSERT(src->format >= QImage::Format_RGBX16FPx4);
|
||||
|
||||
const FetchAndConvertPixelsFuncFP fetch = qFetchToRGBA32F[src->format];
|
||||
const ConvertAndStorePixelsFuncFP store = qStoreFromRGBA32F[dest->format];
|
||||
|
||||
auto convertSegment = [=](int yStart, int yEnd) {
|
||||
QRgba32F buf[BufferSize];
|
||||
QRgba32F *buffer = buf;
|
||||
const uchar *srcData = src->data + yStart * src->bytes_per_line;
|
||||
uchar *destData = dest->data + yStart * dest->bytes_per_line;
|
||||
for (int y = yStart; y < yEnd; ++y) {
|
||||
int x = 0;
|
||||
while (x < src->width) {
|
||||
int l = src->width - x;
|
||||
if (dest->depth == 128)
|
||||
buffer = reinterpret_cast<QRgba32F *>(destData) + x;
|
||||
else
|
||||
l = qMin(l, BufferSize);
|
||||
const QRgba32F *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
|
||||
store(destData, ptr, x, l, nullptr, nullptr);
|
||||
x += l;
|
||||
}
|
||||
srcData += src->bytes_per_line;
|
||||
destData += dest->bytes_per_line;
|
||||
}
|
||||
};
|
||||
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
|
||||
int segments = (qsizetype(src->width) * src->height) >> 16;
|
||||
segments = std::min(segments, src->height);
|
||||
|
||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
||||
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
|
||||
return convertSegment(0, src->height);
|
||||
|
||||
QSemaphore semaphore;
|
||||
int y = 0;
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
int yn = (src->height - y) / (segments - i);
|
||||
threadPool->start([&, y, yn]() {
|
||||
convertSegment(y, y + yn);
|
||||
semaphore.release(1);
|
||||
});
|
||||
y += yn;
|
||||
}
|
||||
semaphore.acquire(segments);
|
||||
#else
|
||||
convertSegment(0, src->height);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
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.
|
||||
|
|
@ -337,7 +393,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
|||
return false;
|
||||
}
|
||||
|
||||
Q_ASSERT(destLayout->bpp != QPixelLayout::BPP64);
|
||||
Q_ASSERT(destLayout->bpp < QPixelLayout::BPP64);
|
||||
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
|
||||
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
|
|
@ -535,6 +591,102 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
|
|||
return true;
|
||||
}
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(data->format >= QImage::Format_RGBX16FPx4);
|
||||
Q_ASSERT(dst_format >= QImage::Format_RGBX16FPx4);
|
||||
const int destDepth = qt_depthForFormat(dst_format);
|
||||
if (data->depth < destDepth)
|
||||
return false;
|
||||
|
||||
const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
|
||||
const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
|
||||
|
||||
QImageData::ImageSizeParameters params = { data->bytes_per_line, data->nbytes };
|
||||
if (data->depth != destDepth) {
|
||||
params = QImageData::calculateImageParameters(data->width, data->height, destDepth);
|
||||
if (!params.isValid())
|
||||
return false;
|
||||
}
|
||||
|
||||
FetchAndConvertPixelsFuncFP fetch = qFetchToRGBA32F[data->format];
|
||||
ConvertAndStorePixelsFuncFP store = qStoreFromRGBA32F[dst_format];
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
|
||||
// This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
|
||||
fetch = qFetchToRGBA32F[data->format + 1];
|
||||
store = qStoreFromRGBA32F[dst_format + 1];
|
||||
}
|
||||
|
||||
auto convertSegment = [=](int yStart, int yEnd) {
|
||||
QRgba32F buf[BufferSize];
|
||||
QRgba32F *buffer = buf;
|
||||
uchar *srcData = data->data + yStart * data->bytes_per_line;
|
||||
uchar *destData = srcData;
|
||||
for (int y = yStart; y < yEnd; ++y) {
|
||||
int x = 0;
|
||||
while (x < data->width) {
|
||||
int l = data->width - x;
|
||||
if (srcLayout->bpp == QPixelLayout::BPP32FPx4)
|
||||
buffer = reinterpret_cast<QRgba32F *>(srcData) + x;
|
||||
else
|
||||
l = qMin(l, BufferSize);
|
||||
const QRgba32F *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
|
||||
store(destData, ptr, x, l, nullptr, nullptr);
|
||||
x += l;
|
||||
}
|
||||
srcData += data->bytes_per_line;
|
||||
destData += params.bytesPerLine;
|
||||
}
|
||||
};
|
||||
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
|
||||
int segments = (qsizetype(data->width) * data->height) >> 16;
|
||||
segments = std::min(segments, data->height);
|
||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
||||
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
|
||||
QSemaphore semaphore;
|
||||
int y = 0;
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
int yn = (data->height - y) / (segments - i);
|
||||
threadPool->start([&, y, yn]() {
|
||||
convertSegment(y, y + yn);
|
||||
semaphore.release(1);
|
||||
});
|
||||
y += yn;
|
||||
}
|
||||
semaphore.acquire(segments);
|
||||
if (data->bytes_per_line != params.bytesPerLine) {
|
||||
// Compress segments to a continuous block
|
||||
y = 0;
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
int yn = (data->height - y) / (segments - i);
|
||||
uchar *srcData = data->data + data->bytes_per_line * y;
|
||||
uchar *destData = data->data + params.bytesPerLine * y;
|
||||
if (srcData != destData)
|
||||
memmove(destData, srcData, params.bytesPerLine * yn);
|
||||
y += yn;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
convertSegment(0, data->height);
|
||||
if (params.totalSize != data->nbytes) {
|
||||
Q_ASSERT(params.totalSize < data->nbytes);
|
||||
void *newData = realloc(data->data, params.totalSize);
|
||||
if (newData) {
|
||||
data->data = (uchar *)newData;
|
||||
data->nbytes = params.totalSize;
|
||||
}
|
||||
data->bytes_per_line = params.bytesPerLine;
|
||||
}
|
||||
data->depth = destDepth;
|
||||
data->format = dst_format;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->width == dest->width);
|
||||
|
|
@ -1424,6 +1576,55 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
|
|||
}
|
||||
}
|
||||
|
||||
template<bool MaskAlpha>
|
||||
static void convert_RGBA16FPM_to_RGBA16F(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA16FPx4_Premultiplied);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBA16FPx4 || dest->format == QImage::Format_RGBX16FPx4);
|
||||
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 QRgba16F *src_data = reinterpret_cast<const QRgba16F *>(src->data);
|
||||
QRgba16F *dest_data = reinterpret_cast<QRgba16F *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba16F *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = src_data->unpremultiplied();
|
||||
if (MaskAlpha)
|
||||
dest_data->setAlpha(1.0f);
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool MaskAlpha>
|
||||
static bool convert_RGBA16FPM_to_RGBA16F_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(data->format == QImage::Format_RGBA16FPx4_Premultiplied);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 3) - data->width;
|
||||
QRgba16F *rgb_data = reinterpret_cast<QRgba16F *>(data->data);
|
||||
|
||||
for (int i = 0; i < data->height; ++i) {
|
||||
const QRgba16F *end = rgb_data + data->width;
|
||||
while (rgb_data < end) {
|
||||
*rgb_data = rgb_data->unpremultiplied();
|
||||
if (MaskAlpha)
|
||||
rgb_data->setAlpha(1.0f);
|
||||
++rgb_data;
|
||||
}
|
||||
rgb_data += pad;
|
||||
}
|
||||
data->format = MaskAlpha ? QImage::Format_RGBX16FPx4 : QImage::Format_RGBA16FPx4;
|
||||
return true;
|
||||
}
|
||||
|
||||
static QList<QRgb> fix_color_table(const QList<QRgb> &ctbl, QImage::Format format)
|
||||
{
|
||||
QList<QRgb> colorTable = ctbl;
|
||||
|
|
@ -2421,6 +2622,12 @@ static void qInitImageConversions()
|
|||
qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888_Premultiplied] = convert_RGB888_to_RGB<false>;
|
||||
#endif
|
||||
|
||||
qimage_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4] = convert_passthrough;
|
||||
qimage_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4_Premultiplied] = convert_passthrough;
|
||||
|
||||
qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] = convert_passthrough;
|
||||
qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] = convert_passthrough;
|
||||
|
||||
// Inline converters:
|
||||
qimage_inplace_converter_map[QImage::Format_Indexed8][QImage::Format_Grayscale8] =
|
||||
convert_Indexed8_to_Grayscale8_inplace;
|
||||
|
|
@ -2526,6 +2733,16 @@ static void qInitImageConversions()
|
|||
qimage_inplace_converter_map[QImage::Format_BGR888][QImage::Format_RGB888] =
|
||||
convert_rgbswap_generic_inplace;
|
||||
|
||||
qimage_inplace_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4] =
|
||||
convert_passthrough_inplace<QImage::Format_RGBA16FPx4>;
|
||||
qimage_inplace_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4_Premultiplied] =
|
||||
convert_passthrough_inplace<QImage::Format_RGBA16FPx4_Premultiplied>;
|
||||
|
||||
qimage_inplace_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] =
|
||||
convert_passthrough_inplace<QImage::Format_RGBA32FPx4>;
|
||||
qimage_inplace_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] =
|
||||
convert_passthrough_inplace<QImage::Format_RGBA32FPx4_Premultiplied>;
|
||||
|
||||
// Now architecture specific conversions:
|
||||
#if defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSSE3)
|
||||
if (qCpuHasFeature(SSSE3)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
|
|
@ -161,6 +161,10 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
|||
void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
|
||||
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
|
||||
bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
|
||||
#if QT_CONFIG(raster_fp)
|
||||
void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
|
||||
bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
|
||||
#endif
|
||||
|
||||
void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
|
||||
|
||||
|
|
@ -216,8 +220,16 @@ inline int qt_depthForFormat(QImage::Format format)
|
|||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
depth = 64;
|
||||
break;
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
depth = 128;
|
||||
break;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
|
@ -247,6 +259,12 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
|
|||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
return QImage::Format_RGBX64;
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
return QImage::Format_RGBX16FPx4;
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
return QImage::Format_RGBX32FPx4;
|
||||
case QImage::Format_ARGB32_Premultiplied:
|
||||
case QImage::Format_ARGB32:
|
||||
return QImage::Format_RGB32;
|
||||
|
|
@ -261,6 +279,8 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
|
|||
case QImage::Format_BGR30:
|
||||
case QImage::Format_RGB30:
|
||||
case QImage::Format_RGBX64:
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_Grayscale8:
|
||||
case QImage::Format_Grayscale16:
|
||||
return format;
|
||||
|
|
@ -300,6 +320,12 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
|
|||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_Grayscale16:
|
||||
return QImage::Format_RGBA64_Premultiplied;
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
return QImage::Format_RGBA16FPx4_Premultiplied;
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
return QImage::Format_RGBA32FPx4_Premultiplied;
|
||||
case QImage::Format_ARGB32_Premultiplied:
|
||||
case QImage::Format_ARGB8565_Premultiplied:
|
||||
case QImage::Format_ARGB8555_Premultiplied:
|
||||
|
|
@ -309,6 +335,8 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
|
|||
case QImage::Format_A2BGR30_Premultiplied:
|
||||
case QImage::Format_A2RGB30_Premultiplied:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
return format;
|
||||
case QImage::Format_Mono:
|
||||
case QImage::Format_MonoLSB:
|
||||
|
|
@ -339,6 +367,12 @@ inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
|
|||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA64_Premultiplied:
|
||||
case QImage::Format_Grayscale16:
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -346,6 +380,21 @@ inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool qt_fpColorPrecision(QImage::Format format)
|
||||
{
|
||||
switch (format) {
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
|
||||
{
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -143,7 +143,6 @@ INTERPOLATE_PIXEL_RGB64_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alph
|
|||
dstVector = _mm256_or_si256(finalAG, finalRB);
|
||||
}
|
||||
|
||||
|
||||
// See BLEND_SOURCE_OVER_ARGB32_SSE2 for details.
|
||||
inline static void Q_DECL_VECTORCALL BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *src, const int length)
|
||||
{
|
||||
|
|
@ -457,6 +456,40 @@ void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *dst, const QRgba64 *sr
|
|||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
void QT_FASTCALL comp_func_SourceOver_rgbafp_avx2(QRgba32F *dst, const QRgba32F *src, int length, uint const_alpha)
|
||||
{
|
||||
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
|
||||
|
||||
const float a = const_alpha / 255.0f;
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 constAlphaVector = _mm_set1_ps(a);
|
||||
const __m256 one256 = _mm256_set1_ps(1.0f);
|
||||
const __m256 constAlphaVector256 = _mm256_set1_ps(a);
|
||||
int x = 0;
|
||||
for (; x < length - 1; x += 2) {
|
||||
__m256 srcVector = _mm256_loadu_ps((const float *)&src[x]);
|
||||
__m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
|
||||
srcVector = _mm256_mul_ps(srcVector, constAlphaVector256);
|
||||
__m256 alphaChannel = _mm256_permute_ps(srcVector, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
alphaChannel = _mm256_sub_ps(one256, alphaChannel);
|
||||
dstVector = _mm256_mul_ps(dstVector, alphaChannel);
|
||||
dstVector = _mm256_add_ps(dstVector, srcVector);
|
||||
_mm256_storeu_ps((float *)(dst + x), dstVector);
|
||||
}
|
||||
if (x < length) {
|
||||
__m128 srcVector = _mm_load_ps((float *)(src + x));
|
||||
__m128 dstVector = _mm_load_ps((const float *)(dst + x));
|
||||
srcVector = _mm_mul_ps(srcVector, constAlphaVector);
|
||||
__m128 alphaChannel = _mm_permute_ps(srcVector, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
alphaChannel = _mm_sub_ps(one, alphaChannel);
|
||||
dstVector = _mm_mul_ps(dstVector, alphaChannel);
|
||||
dstVector = _mm_add_ps(dstVector, srcVector);
|
||||
_mm_store_ps((float *)(dst + x), dstVector);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void QT_FASTCALL comp_func_Source_avx2(uint *dst, const uint *src, int length, uint const_alpha)
|
||||
{
|
||||
if (const_alpha == 255) {
|
||||
|
|
@ -523,6 +556,41 @@ void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, i
|
|||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
void QT_FASTCALL comp_func_Source_rgbafp_avx2(QRgba32F *dst, const QRgba32F *src, int length, uint const_alpha)
|
||||
{
|
||||
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
|
||||
if (const_alpha == 255) {
|
||||
::memcpy(dst, src, length * sizeof(QRgba32F));
|
||||
} else {
|
||||
const float ca = const_alpha / 255.f;
|
||||
const float cia = 1.0f - ca;
|
||||
|
||||
const __m128 constAlphaVector = _mm_set1_ps(ca);
|
||||
const __m128 oneMinusConstAlpha = _mm_set1_ps(cia);
|
||||
const __m256 constAlphaVector256 = _mm256_set1_ps(ca);
|
||||
const __m256 oneMinusConstAlpha256 = _mm256_set1_ps(cia);
|
||||
int x = 0;
|
||||
for (; x < length - 1; x += 2) {
|
||||
__m256 srcVector = _mm256_loadu_ps((const float *)&src[x]);
|
||||
__m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
|
||||
srcVector = _mm256_mul_ps(srcVector, constAlphaVector256);
|
||||
dstVector = _mm256_mul_ps(dstVector, oneMinusConstAlpha256);
|
||||
dstVector = _mm256_add_ps(dstVector, srcVector);
|
||||
_mm256_storeu_ps((float *)&dst[x], dstVector);
|
||||
}
|
||||
if (x < length) {
|
||||
__m128 srcVector = _mm_load_ps((const float *)&src[x]);
|
||||
__m128 dstVector = _mm_load_ps((const float *)&dst[x]);
|
||||
srcVector = _mm_mul_ps(srcVector, constAlphaVector);
|
||||
dstVector = _mm_mul_ps(dstVector, oneMinusConstAlpha);
|
||||
dstVector = _mm_add_ps(dstVector, srcVector);
|
||||
_mm_store_ps((float *)&dst[x], dstVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha)
|
||||
{
|
||||
if ((const_alpha & qAlpha(color)) == 255) {
|
||||
|
|
@ -587,6 +655,69 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int
|
|||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
void QT_FASTCALL comp_func_solid_Source_rgbafp_avx2(QRgba32F *dst, int length, QRgba32F color, uint const_alpha)
|
||||
{
|
||||
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
|
||||
if (const_alpha == 255) {
|
||||
for (int i = 0; i < length; ++i)
|
||||
dst[i] = color;
|
||||
} else {
|
||||
const float a = const_alpha / 255.0f;
|
||||
const __m128 alphaVector = _mm_set1_ps(a);
|
||||
const __m128 minusAlphaVector = _mm_set1_ps(1.0f - a);
|
||||
__m128 colorVector = _mm_load_ps((const float *)&color);
|
||||
colorVector = _mm_mul_ps(colorVector, alphaVector);
|
||||
const __m256 colorVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(colorVector), colorVector, 1);
|
||||
const __m256 minusAlphaVector256 = _mm256_set1_ps(1.0f - a);
|
||||
int x = 0;
|
||||
for (; x < length - 1; x += 2) {
|
||||
__m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
|
||||
dstVector = _mm256_mul_ps(dstVector, minusAlphaVector256);
|
||||
dstVector = _mm256_add_ps(dstVector, colorVector256);
|
||||
_mm256_storeu_ps((float *)&dst[x], dstVector);
|
||||
}
|
||||
if (x < length) {
|
||||
__m128 dstVector = _mm_load_ps((const float *)&dst[x]);
|
||||
dstVector = _mm_mul_ps(dstVector, minusAlphaVector);
|
||||
dstVector = _mm_add_ps(dstVector, colorVector);
|
||||
_mm_store_ps((float *)&dst[x], dstVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QT_FASTCALL comp_func_solid_SourceOver_rgbafp_avx2(QRgba32F *dst, int length, QRgba32F color, uint const_alpha)
|
||||
{
|
||||
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
|
||||
if (const_alpha == 255 && color.a >= 1.0f) {
|
||||
for (int i = 0; i < length; ++i)
|
||||
dst[i] = color;
|
||||
} else {
|
||||
__m128 colorVector = _mm_load_ps((const float *)&color);
|
||||
if (const_alpha != 255)
|
||||
colorVector = _mm_mul_ps(colorVector, _mm_set1_ps(const_alpha / 255.f));
|
||||
__m128 minusAlphaOfColorVector =
|
||||
_mm_sub_ps(_mm_set1_ps(1.0f), _mm_permute_ps(colorVector, _MM_SHUFFLE(3, 3, 3, 3)));
|
||||
const __m256 colorVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(colorVector), colorVector, 1);
|
||||
const __m256 minusAlphaVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(minusAlphaOfColorVector),
|
||||
minusAlphaOfColorVector, 1);
|
||||
int x = 0;
|
||||
for (; x < length - 1; x += 2) {
|
||||
__m256 dstVector = _mm256_loadu_ps((const float *)&dst[x]);
|
||||
dstVector = _mm256_mul_ps(dstVector, minusAlphaVector256);
|
||||
dstVector = _mm256_add_ps(dstVector, colorVector256);
|
||||
_mm256_storeu_ps((float *)&dst[x], dstVector);
|
||||
}
|
||||
if (x < length) {
|
||||
__m128 dstVector = _mm_load_ps((const float *)&dst[x]);
|
||||
dstVector = _mm_mul_ps(dstVector, minusAlphaOfColorVector);
|
||||
dstVector = _mm_add_ps(dstVector, colorVector);
|
||||
_mm_store_ps((float *)&dst[x], dstVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define interpolate_4_pixels_16_avx2(tlr1, tlr2, blr1, blr2, distx, disty, colorMask, v_256, b) \
|
||||
{ \
|
||||
/* Correct for later unpack */ \
|
||||
|
|
@ -1261,6 +1392,258 @@ const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM_avx2(QRgba64 *buffer, const uch
|
|||
return buffer;
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL fetchRGB16FToRGB32_avx2(uint *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
|
||||
const __m256 vf = _mm256_set1_ps(255.0f);
|
||||
const __m256 vh = _mm256_set1_ps(0.5f);
|
||||
int i = 0;
|
||||
for (; i + 1 < count; i += 2) {
|
||||
__m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
|
||||
vsf = _mm256_mul_ps(vsf, vf);
|
||||
vsf = _mm256_add_ps(vsf, vh);
|
||||
__m256i vsi = _mm256_cvttps_epi32(vsf);
|
||||
vsi = _mm256_packs_epi32(vsi, vsi);
|
||||
vsi = _mm256_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
__m128i vsi128 = _mm256_castsi256_si128(vsi);
|
||||
vsi128 = _mm_packus_epi16(vsi128, vsi128);
|
||||
_mm_storel_epi64((__m128i *)(buffer + i), vsi128);
|
||||
}
|
||||
if (i < count) {
|
||||
__m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
|
||||
vsf = _mm_mul_ps(vsf, _mm_set1_ps(255.0f));
|
||||
vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
|
||||
__m128i vsi = _mm_cvttps_epi32(vsf);
|
||||
vsi = _mm_packs_epi32(vsi, vsi);
|
||||
vsi = _mm_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
vsi = _mm_packus_epi16(vsi, vsi);
|
||||
buffer[i] = _mm_cvtsi128_si32(vsi);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL fetchRGBA16FToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
|
||||
const __m256 vf = _mm256_set1_ps(255.0f);
|
||||
const __m256 vh = _mm256_set1_ps(0.5f);
|
||||
int i = 0;
|
||||
for (; i + 1 < count; i += 2) {
|
||||
__m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
|
||||
__m256 vsa = _mm256_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm256_mul_ps(vsf, vsa);
|
||||
vsf = _mm256_blend_ps(vsf, vsa, 0x88);
|
||||
vsf = _mm256_mul_ps(vsf, vf);
|
||||
vsf = _mm256_add_ps(vsf, vh);
|
||||
__m256i vsi = _mm256_cvttps_epi32(vsf);
|
||||
vsi = _mm256_packus_epi32(vsi, vsi);
|
||||
vsi = _mm256_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
__m128i vsi128 = _mm256_castsi256_si128(vsi);
|
||||
vsi128 = _mm_packus_epi16(vsi128, vsi128);
|
||||
_mm_storel_epi64((__m128i *)(buffer + i), vsi128);
|
||||
}
|
||||
if (i < count) {
|
||||
__m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
|
||||
__m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm_mul_ps(vsf, vsa);
|
||||
vsf = _mm_insert_ps(vsf, vsa, 0x30);
|
||||
vsf = _mm_mul_ps(vsf, _mm_set1_ps(255.0f));
|
||||
vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
|
||||
__m128i vsi = _mm_cvttps_epi32(vsf);
|
||||
vsi = _mm_packus_epi32(vsi, vsi);
|
||||
vsi = _mm_shufflelo_epi16(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
vsi = _mm_packus_epi16(vsi, vsi);
|
||||
buffer[i] = _mm_cvtsi128_si32(vsi);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const QRgba64 *QT_FASTCALL fetchRGBA16FPMToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
|
||||
const __m256 vf = _mm256_set1_ps(65535.0f);
|
||||
const __m256 vh = _mm256_set1_ps(0.5f);
|
||||
int i = 0;
|
||||
for (; i + 1 < count; i += 2) {
|
||||
__m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
|
||||
vsf = _mm256_mul_ps(vsf, vf);
|
||||
vsf = _mm256_add_ps(vsf, vh);
|
||||
__m256i vsi = _mm256_cvttps_epi32(vsf);
|
||||
vsi = _mm256_packus_epi32(vsi, vsi);
|
||||
vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
_mm_storeu_si128((__m128i *)(buffer + i), _mm256_castsi256_si128(vsi));
|
||||
}
|
||||
if (i < count) {
|
||||
__m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
|
||||
vsf = _mm_mul_ps(vsf, _mm_set1_ps(65535.0f));
|
||||
vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
|
||||
__m128i vsi = _mm_cvttps_epi32(vsf);
|
||||
vsi = _mm_packus_epi32(vsi, vsi);
|
||||
_mm_storel_epi64((__m128i *)(buffer + i), vsi);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const QRgba64 *QT_FASTCALL fetchRGBA16FToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
|
||||
const __m256 vf = _mm256_set1_ps(65535.0f);
|
||||
const __m256 vh = _mm256_set1_ps(0.5f);
|
||||
int i = 0;
|
||||
for (; i + 1 < count; i += 2) {
|
||||
__m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
|
||||
__m256 vsa = _mm256_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm256_mul_ps(vsf, vsa);
|
||||
vsf = _mm256_blend_ps(vsf, vsa, 0x88);
|
||||
vsf = _mm256_mul_ps(vsf, vf);
|
||||
vsf = _mm256_add_ps(vsf, vh);
|
||||
__m256i vsi = _mm256_cvttps_epi32(vsf);
|
||||
vsi = _mm256_packus_epi32(vsi, vsi);
|
||||
vsi = _mm256_permute4x64_epi64(vsi, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
_mm_storeu_si128((__m128i *)(buffer + i), _mm256_castsi256_si128(vsi));
|
||||
}
|
||||
if (i < count) {
|
||||
__m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
|
||||
__m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm_mul_ps(vsf, vsa);
|
||||
vsf = _mm_insert_ps(vsf, vsa, 0x30);
|
||||
vsf = _mm_mul_ps(vsf, _mm_set1_ps(65535.0f));
|
||||
vsf = _mm_add_ps(vsf, _mm_set1_ps(0.5f));
|
||||
__m128i vsi = _mm_cvttps_epi32(vsf);
|
||||
vsi = _mm_packus_epi32(vsi, vsi);
|
||||
_mm_storel_epi64((__m128i *)(buffer + i), vsi);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGB16FFromRGB32_avx2(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
|
||||
const __m256 vf = _mm256_set1_ps(1.0f / 255.0f);
|
||||
int i = 0;
|
||||
for (; i + 1 < count; i += 2) {
|
||||
__m256i vsi = _mm256_cvtepu8_epi32(_mm_loadl_epi64((const __m128i *)(src + i)));
|
||||
vsi = _mm256_shuffle_epi32(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
__m256 vsf = _mm256_cvtepi32_ps(vsi);
|
||||
vsf = _mm256_mul_ps(vsf, vf);
|
||||
_mm_storeu_si128((__m128i *)(d + i), _mm256_cvtps_ph(vsf, 0));
|
||||
}
|
||||
if (i < count) {
|
||||
__m128i vsi = _mm_cvtsi32_si128(src[i]);
|
||||
vsi = _mm_cvtepu8_epi32(vsi);
|
||||
vsi = _mm_shuffle_epi32(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
__m128 vsf = _mm_cvtepi32_ps(vsi);
|
||||
vsf = _mm_mul_ps(vsf, _mm_set1_ps(1.0f / 255.0f));
|
||||
_mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBA16FFromARGB32PM_avx2(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
|
||||
const __m128 vf = _mm_set1_ps(1.0f / 255.0f);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const uint s = src[i];
|
||||
__m128i vsi = _mm_cvtsi32_si128(s);
|
||||
vsi = _mm_cvtepu8_epi32(vsi);
|
||||
vsi = _mm_shuffle_epi32(vsi, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
__m128 vsf = _mm_cvtepi32_ps(vsi);
|
||||
const uint8_t a = (s >> 24);
|
||||
if (a == 255)
|
||||
vsf = _mm_mul_ps(vsf, vf);
|
||||
else if (a == 0)
|
||||
vsf = _mm_set1_ps(0.0f);
|
||||
else {
|
||||
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
__m128 vsr = _mm_rcp_ps(vsa);
|
||||
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
|
||||
vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
|
||||
vsf = _mm_mul_ps(vsf, vsr);
|
||||
}
|
||||
_mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
const QRgba32F *QT_FASTCALL fetchRGBA16FToRGBA32F_avx2(QRgba32F *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const quint64 *s = reinterpret_cast<const quint64 *>(src) + index;
|
||||
int i = 0;
|
||||
for (; i + 1 < count; i += 2) {
|
||||
__m256 vsf = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(s + i)));
|
||||
__m256 vsa = _mm256_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm256_mul_ps(vsf, vsa);
|
||||
vsf = _mm256_blend_ps(vsf, vsa, 0x88);
|
||||
_mm256_storeu_ps((float *)(buffer + i), vsf);
|
||||
}
|
||||
if (i < count) {
|
||||
__m128 vsf = _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(s + i)));
|
||||
__m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm_mul_ps(vsf, vsa);
|
||||
vsf = _mm_insert_ps(vsf, vsa, 0x30);
|
||||
_mm_store_ps((float *)(buffer + i), vsf);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBX16FFromRGBA32F_avx2(uchar *dest, const QRgba32F *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
|
||||
const __m128 *s = reinterpret_cast<const __m128 *>(src);
|
||||
const __m128 zero = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
__m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
|
||||
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
const float a = _mm_cvtss_f32(vsa);
|
||||
if (a == 1.0f)
|
||||
{ }
|
||||
else if (a == 0.0f)
|
||||
vsf = zero;
|
||||
else {
|
||||
__m128 vsr = _mm_rcp_ps(vsa);
|
||||
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
|
||||
vsf = _mm_mul_ps(vsf, vsr);
|
||||
vsf = _mm_insert_ps(vsf, _mm_set_ss(1.0f), 0x30);
|
||||
}
|
||||
_mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBA16FFromRGBA32F_avx2(uchar *dest, const QRgba32F *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
quint64 *d = reinterpret_cast<quint64 *>(dest) + index;
|
||||
const __m128 *s = reinterpret_cast<const __m128 *>(src);
|
||||
const __m128 zero = _mm_set1_ps(0.0f);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
__m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
|
||||
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
const float a = _mm_cvtss_f32(vsa);
|
||||
if (a == 1.0f)
|
||||
{ }
|
||||
else if (a == 0.0f)
|
||||
vsf = zero;
|
||||
else {
|
||||
__m128 vsr = _mm_rcp_ps(vsa);
|
||||
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
|
||||
vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
|
||||
vsf = _mm_mul_ps(vsf, vsr);
|
||||
}
|
||||
_mm_storel_epi64((__m128i *)(d + i), _mm_cvtps_ph(vsf, 0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ class QRasterBuffer;
|
|||
class QClipData;
|
||||
class QRasterPaintEngineState;
|
||||
|
||||
template<typename F> class QRgbaF;
|
||||
typedef QRgbaF<float> QRgba32F;
|
||||
|
||||
typedef QT_FT_SpanFunc ProcessSpans;
|
||||
typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
|
||||
int x, int y, const QRgba64 &color,
|
||||
|
|
@ -194,8 +197,10 @@ extern void qt_memfill16(quint16 *dest, quint16 value, qsizetype count);
|
|||
|
||||
typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha);
|
||||
typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha);
|
||||
typedef void (QT_FASTCALL *CompositionFunctionFP)(QRgba32F *Q_DECL_RESTRICT dest, const QRgba32F *Q_DECL_RESTRICT src, int length, uint const_alpha);
|
||||
typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha);
|
||||
typedef void (QT_FASTCALL *CompositionFunctionSolid64)(QRgba64 *dest, int length, QRgba64 color, uint const_alpha);
|
||||
typedef void (QT_FASTCALL *CompositionFunctionSolidFP)(QRgba32F *dest, int length, QRgba32F color, uint const_alpha);
|
||||
|
||||
struct LinearGradientValues
|
||||
{
|
||||
|
|
@ -219,10 +224,13 @@ struct RadialGradientValues
|
|||
struct Operator;
|
||||
typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
|
||||
typedef QRgba64* (QT_FASTCALL *DestFetchProc64)(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
|
||||
typedef QRgba32F* (QT_FASTCALL *DestFetchProcFP)(QRgba32F *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
|
||||
typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
|
||||
typedef void (QT_FASTCALL *DestStoreProc64)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
|
||||
typedef void (QT_FASTCALL *DestStoreProcFP)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba32F *buffer, int length);
|
||||
typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
|
||||
typedef const QRgba64* (QT_FASTCALL *SourceFetchProc64)(QRgba64 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
|
||||
typedef const QRgba32F* (QT_FASTCALL *SourceFetchProcFP)(QRgba32F *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
|
||||
|
||||
struct Operator
|
||||
{
|
||||
|
|
@ -239,6 +247,12 @@ struct Operator
|
|||
CompositionFunctionSolid64 funcSolid64;
|
||||
CompositionFunction64 func64;
|
||||
|
||||
DestFetchProcFP destFetchFP;
|
||||
DestStoreProcFP destStoreFP;
|
||||
SourceFetchProcFP srcFetchFP;
|
||||
CompositionFunctionSolidFP funcSolidFP;
|
||||
CompositionFunctionFP funcFP;
|
||||
|
||||
union {
|
||||
LinearGradientValues linear;
|
||||
RadialGradientValues radial;
|
||||
|
|
@ -295,7 +309,7 @@ struct QGradientData
|
|||
#define GRADIENT_STOPTABLE_SIZE 1024
|
||||
#define GRADIENT_STOPTABLE_SIZE_SHIFT 10
|
||||
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
|
||||
const QRgba64 *colorTable64; //[GRADIENT_STOPTABLE_SIZE];
|
||||
#endif
|
||||
const QRgb *colorTable32; //[GRADIENT_STOPTABLE_SIZE];
|
||||
|
|
@ -473,7 +487,7 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe
|
|||
|
||||
while (buffer < end) {
|
||||
if (rw == 0) {
|
||||
*buffer = 0;
|
||||
*buffer = RadialFetchFunc::null();
|
||||
} else {
|
||||
qreal invRw = 1 / rw;
|
||||
qreal gx = rx * invRw - data->gradient.radial.focal.x;
|
||||
|
|
@ -845,6 +859,57 @@ static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba6
|
|||
}
|
||||
#endif // __SSE2__
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
static inline QRgba32F multiplyAlpha_rgba32f(QRgba32F c, float a)
|
||||
{
|
||||
return QRgba32F { c.r * a, c.g * a, c.b * a, c.a * a };
|
||||
}
|
||||
|
||||
static inline QRgba32F interpolate_rgba32f(QRgba32F x, float alpha1, QRgba32F y, float alpha2)
|
||||
{
|
||||
x = multiplyAlpha_rgba32f(x, alpha1);
|
||||
y = multiplyAlpha_rgba32f(y, alpha2);
|
||||
return QRgba32F { x.r + y.r, x.g + y.g, x.b + y.b, x.a + y.a };
|
||||
}
|
||||
#ifdef __SSE2__
|
||||
static inline __m128 Q_DECL_VECTORCALL interpolate_rgba32f(__m128 x, __m128 alpha1, __m128 y, __m128 alpha2)
|
||||
{
|
||||
return _mm_add_ps(_mm_mul_ps(x, alpha1), _mm_mul_ps(y, alpha2));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline QRgba32F interpolate_4_pixels_rgba32f(const QRgba32F t[], const QRgba32F b[], uint distx, uint disty)
|
||||
{
|
||||
constexpr float f = 1.0f / 65536.0f;
|
||||
const float dx = distx * f;
|
||||
const float dy = disty * f;
|
||||
const float idx = 1.0f - dx;
|
||||
const float idy = 1.0f - dy;
|
||||
#ifdef __SSE2__
|
||||
const __m128 vtl = _mm_load_ps((const float *)&t[0]);
|
||||
const __m128 vtr = _mm_load_ps((const float *)&t[1]);
|
||||
const __m128 vbl = _mm_load_ps((const float *)&b[0]);
|
||||
const __m128 vbr = _mm_load_ps((const float *)&b[1]);
|
||||
|
||||
const __m128 vdx = _mm_set1_ps(dx);
|
||||
const __m128 vidx = _mm_set1_ps(idx);
|
||||
__m128 vt = interpolate_rgba32f(vtl, vidx, vtr, vdx);
|
||||
__m128 vb = interpolate_rgba32f(vbl, vidx, vbr, vdx);
|
||||
const __m128 vdy = _mm_set1_ps(dy);
|
||||
const __m128 vidy = _mm_set1_ps(idy);
|
||||
vt = interpolate_rgba32f(vt, vidy, vb, vdy);
|
||||
QRgba32F res;
|
||||
_mm_store_ps((float*)&res, vt);
|
||||
return res;
|
||||
#else
|
||||
QRgba32F xtop = interpolate_rgba32f(t[0], idx, t[1], dx);
|
||||
QRgba32F xbot = interpolate_rgba32f(b[0], idx, b[1], dx);
|
||||
xtop = interpolate_rgba32f(xtop, idy, xbot, dy);
|
||||
return xtop;
|
||||
#endif
|
||||
}
|
||||
#endif // QT_CONFIG(raster_fp)
|
||||
|
||||
static inline uint BYTE_MUL_RGB16(uint x, uint a) {
|
||||
a += 1;
|
||||
uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
|
||||
|
|
@ -1024,70 +1089,6 @@ struct IntermediateBuffer
|
|||
quint32 buffer_ag[BufferSize+2];
|
||||
};
|
||||
|
||||
template <QPixelLayout::BPP bpp>
|
||||
inline uint QT_FASTCALL qFetchPixel(const uchar *, int)
|
||||
{
|
||||
Q_UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
|
||||
{
|
||||
return (src[index >> 3] >> (index & 7)) & 1;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
|
||||
{
|
||||
return (src[index >> 3] >> (~index & 7)) & 1;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
|
||||
{
|
||||
return src[index];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
|
||||
{
|
||||
return reinterpret_cast<const quint16 *>(src)[index];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
|
||||
{
|
||||
return reinterpret_cast<const quint24 *>(src)[index];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
|
||||
{
|
||||
return reinterpret_cast<const uint *>(src)[index];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP64>(const uchar *src, int index)
|
||||
{
|
||||
// We have to do the conversion in fetch to fit into a 32bit uint
|
||||
QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
|
||||
return c.toArgb32();
|
||||
}
|
||||
|
||||
typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
|
||||
|
||||
constexpr FetchPixelFunc qFetchPixelTable[QPixelLayout::BPPCount] = {
|
||||
nullptr, // BPPNone
|
||||
qFetchPixel<QPixelLayout::BPP1MSB>,
|
||||
qFetchPixel<QPixelLayout::BPP1LSB>,
|
||||
qFetchPixel<QPixelLayout::BPP8>,
|
||||
qFetchPixel<QPixelLayout::BPP16>,
|
||||
qFetchPixel<QPixelLayout::BPP24>,
|
||||
qFetchPixel<QPixelLayout::BPP32>,
|
||||
qFetchPixel<QPixelLayout::BPP64>,
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QDRAWHELPER_P_H
|
||||
|
|
|
|||
|
|
@ -502,6 +502,13 @@ void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, i
|
|||
d[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
|
||||
}
|
||||
|
||||
template
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *);
|
||||
template
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *);
|
||||
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
|
||||
{
|
||||
|
|
@ -544,12 +551,68 @@ void QT_FASTCALL storeRGBx64FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, i
|
|||
convertRGBA64FromRGBA64PM_sse4<true>(d, src, count);
|
||||
}
|
||||
|
||||
template
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *);
|
||||
template
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *);
|
||||
#if QT_CONFIG(raster_fp)
|
||||
const QRgba32F *QT_FASTCALL fetchRGBA32FToRGBA32F_sse4(QRgba32F *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const QRgba32F *s = reinterpret_cast<const QRgba32F *>(src) + index;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
__m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
|
||||
__m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
vsf = _mm_mul_ps(vsf, vsa);
|
||||
vsf = _mm_insert_ps(vsf, vsa, 0x30);
|
||||
_mm_store_ps(reinterpret_cast<float *>(buffer + i), vsf);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBX32FFromRGBA32F_sse4(uchar *dest, const QRgba32F *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
|
||||
const __m128 zero = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
__m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(src + i));
|
||||
const __m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
const float a = _mm_cvtss_f32(vsa);
|
||||
if (a == 1.0f)
|
||||
{ }
|
||||
else if (a == 0.0f)
|
||||
vsf = zero;
|
||||
else {
|
||||
__m128 vsr = _mm_rcp_ps(vsa);
|
||||
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
|
||||
vsf = _mm_mul_ps(vsf, vsr);
|
||||
vsf = _mm_insert_ps(vsf, _mm_set_ss(1.0f), 0x30);
|
||||
}
|
||||
_mm_store_ps(reinterpret_cast<float *>(d + i), vsf);
|
||||
}
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBA32FFromRGBA32F_sse4(uchar *dest, const QRgba32F *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
QRgba32F *d = reinterpret_cast<QRgba32F *>(dest) + index;
|
||||
const __m128 zero = _mm_set1_ps(0.0f);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
__m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(src + i));
|
||||
const __m128 vsa = _mm_shuffle_ps(vsf, vsf, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
const float a = _mm_cvtss_f32(vsa);
|
||||
if (a == 1.0f)
|
||||
{ }
|
||||
else if (a == 0.0f)
|
||||
vsf = zero;
|
||||
else {
|
||||
__m128 vsr = _mm_rcp_ps(vsa);
|
||||
vsr = _mm_sub_ps(_mm_add_ps(vsr, vsr), _mm_mul_ps(vsr, _mm_mul_ps(vsr, vsa)));
|
||||
vsr = _mm_insert_ps(vsr, _mm_set_ss(1.0f), 0x30);
|
||||
vsf = _mm_mul_ps(vsf, vsr);
|
||||
}
|
||||
_mm_store_ps(reinterpret_cast<float *>(d + i), vsf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,12 @@
|
|||
****************************************************************************/
|
||||
#include <private/qimagescale_p.h>
|
||||
#include <private/qdrawhelper_p.h>
|
||||
#include <private/qimage_p.h>
|
||||
|
||||
#include "qimage.h"
|
||||
#include "qcolor.h"
|
||||
#include "qrgba64_p.h"
|
||||
#include "qrgbaf.h"
|
||||
|
||||
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
|
||||
#include "qsemaphore.h"
|
||||
|
|
@ -789,6 +791,221 @@ static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
static void qt_qimageScaleRgbaFP_up_x_down_y(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow);
|
||||
|
||||
static void qt_qimageScaleRgbaFP_down_x_up_y(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow);
|
||||
|
||||
static void qt_qimageScaleRgbaFP_down_xy(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow);
|
||||
|
||||
static void qt_qimageScaleRgbaFP_up_xy(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow)
|
||||
{
|
||||
const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
|
||||
int *xpoints = isi->xpoints;
|
||||
int *xapoints = isi->xapoints;
|
||||
int *yapoints = isi->yapoints;
|
||||
|
||||
auto scaleSection = [&] (int yStart, int yEnd) {
|
||||
for (int y = yStart; y < yEnd; ++y) {
|
||||
const QRgba32F *sptr = ypoints[y];
|
||||
QRgba32F *dptr = dest + (y * dow);
|
||||
const int yap = yapoints[y];
|
||||
if (yap > 0) {
|
||||
for (int x = 0; x < dw; x++) {
|
||||
const QRgba32F *pix = sptr + xpoints[x];
|
||||
const int xap = xapoints[x];
|
||||
if (xap > 0)
|
||||
*dptr = interpolate_4_pixels_rgba32f(pix, pix + sow, xap * 256, yap * 256);
|
||||
else
|
||||
*dptr = interpolate_rgba32f(pix[0], 256 - yap, pix[sow], yap);
|
||||
dptr++;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < dw; x++) {
|
||||
const QRgba32F *pix = sptr + xpoints[x];
|
||||
const int xap = xapoints[x];
|
||||
if (xap > 0)
|
||||
*dptr = interpolate_rgba32f(pix[0], 256 - xap, pix[1], xap);
|
||||
else
|
||||
*dptr = pix[0];
|
||||
dptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
multithread_pixels_function(isi, dh, scaleSection);
|
||||
}
|
||||
|
||||
void qt_qimageScaleRgbaFP(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow)
|
||||
{
|
||||
if (isi->xup_yup == 3)
|
||||
qt_qimageScaleRgbaFP_up_xy(isi, dest, dw, dh, dow, sow);
|
||||
else if (isi->xup_yup == 1)
|
||||
qt_qimageScaleRgbaFP_up_x_down_y(isi, dest, dw, dh, dow, sow);
|
||||
else if (isi->xup_yup == 2)
|
||||
qt_qimageScaleRgbaFP_down_x_up_y(isi, dest, dw, dh, dow, sow);
|
||||
else
|
||||
qt_qimageScaleRgbaFP_down_xy(isi, dest, dw, dh, dow, sow);
|
||||
}
|
||||
|
||||
inline static void qt_qimageScaleRgbaFP_helper(const QRgba32F *pix, int xyap, int Cxy, int step, float &r, float &g, float &b, float &a)
|
||||
{
|
||||
constexpr float f = (1.0f / float(1<<14));
|
||||
const float xyapf = xyap * f;
|
||||
const float Cxyf = Cxy * f;
|
||||
r = pix->red() * xyapf;
|
||||
g = pix->green() * xyapf;
|
||||
b = pix->blue() * xyapf;
|
||||
a = pix->alpha() * xyapf;
|
||||
int j;
|
||||
for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy ){
|
||||
pix += step;
|
||||
r += pix->red() * Cxyf;
|
||||
g += pix->green() * Cxyf;
|
||||
b += pix->blue() * Cxyf;
|
||||
a += pix->alpha() * Cxyf;
|
||||
}
|
||||
pix += step;
|
||||
const float jf = j * f;
|
||||
r += pix->red() * jf;
|
||||
g += pix->green() * jf;
|
||||
b += pix->blue() * jf;
|
||||
a += pix->alpha() * jf;
|
||||
}
|
||||
|
||||
static void qt_qimageScaleRgbaFP_up_x_down_y(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow)
|
||||
{
|
||||
const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
|
||||
int *xpoints = isi->xpoints;
|
||||
int *xapoints = isi->xapoints;
|
||||
int *yapoints = isi->yapoints;
|
||||
|
||||
auto scaleSection = [&] (int yStart, int yEnd) {
|
||||
for (int y = yStart; y < yEnd; ++y) {
|
||||
int Cy = (yapoints[y]) >> 16;
|
||||
int yap = (yapoints[y]) & 0xffff;
|
||||
|
||||
QRgba32F *dptr = dest + (y * dow);
|
||||
for (int x = 0; x < dw; x++) {
|
||||
const QRgba32F *sptr = ypoints[y] + xpoints[x];
|
||||
float r, g, b, a;
|
||||
qt_qimageScaleRgbaFP_helper(sptr, yap, Cy, sow, r, g, b, a);
|
||||
|
||||
int xap = xapoints[x];
|
||||
float xapf = xap * (1.f / 256.f);
|
||||
if (xap > 0) {
|
||||
float rr, gg, bb, aa;
|
||||
qt_qimageScaleRgbaFP_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
|
||||
|
||||
r = (r * (1.0f - xapf) + (rr * xapf));
|
||||
g = (g * (1.0f - xapf) + (gg * xapf));
|
||||
b = (b * (1.0f - xapf) + (bb * xapf));
|
||||
a = (a * (1.0f - xapf) + (aa * xapf));
|
||||
}
|
||||
*dptr++ = QRgba32F{r, g, b, a};
|
||||
}
|
||||
}
|
||||
};
|
||||
multithread_pixels_function(isi, dh, scaleSection);
|
||||
}
|
||||
|
||||
static void qt_qimageScaleRgbaFP_down_x_up_y(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow)
|
||||
{
|
||||
const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
|
||||
int *xpoints = isi->xpoints;
|
||||
int *xapoints = isi->xapoints;
|
||||
int *yapoints = isi->yapoints;
|
||||
|
||||
auto scaleSection = [&] (int yStart, int yEnd) {
|
||||
for (int y = yStart; y < yEnd; ++y) {
|
||||
QRgba32F *dptr = dest + (y * dow);
|
||||
for (int x = 0; x < dw; x++) {
|
||||
int Cx = xapoints[x] >> 16;
|
||||
int xap = xapoints[x] & 0xffff;
|
||||
|
||||
const QRgba32F *sptr = ypoints[y] + xpoints[x];
|
||||
float r, g, b, a;
|
||||
qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, r, g, b, a);
|
||||
|
||||
int yap = yapoints[y];
|
||||
float yapf = yap * (1.f / 256.f);
|
||||
if (yap > 0) {
|
||||
float rr, gg, bb, aa;
|
||||
qt_qimageScaleRgbaFP_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
|
||||
|
||||
r = (r * (1.0f - yapf) + (rr * yapf));
|
||||
g = (g * (1.0f - yapf) + (gg * yapf));
|
||||
b = (b * (1.0f - yapf) + (bb * yapf));
|
||||
a = (a * (1.0f - yapf) + (aa * yapf));
|
||||
}
|
||||
*dptr++ = QRgba32F{r, g, b, a};
|
||||
}
|
||||
}
|
||||
};
|
||||
multithread_pixels_function(isi, dh, scaleSection);
|
||||
}
|
||||
|
||||
static void qt_qimageScaleRgbaFP_down_xy(QImageScaleInfo *isi, QRgba32F *dest,
|
||||
int dw, int dh, int dow, int sow)
|
||||
{
|
||||
const QRgba32F **ypoints = (const QRgba32F **)isi->ypoints;
|
||||
int *xpoints = isi->xpoints;
|
||||
int *xapoints = isi->xapoints;
|
||||
int *yapoints = isi->yapoints;
|
||||
|
||||
auto scaleSection = [&] (int yStart, int yEnd) {
|
||||
constexpr float f = 1.f / float(1 << 14);
|
||||
for (int y = yStart; y < yEnd; ++y) {
|
||||
int Cy = (yapoints[y]) >> 16;
|
||||
int yap = (yapoints[y]) & 0xffff;
|
||||
|
||||
QRgba32F *dptr = dest + (y * dow);
|
||||
for (int x = 0; x < dw; x++) {
|
||||
int Cx = xapoints[x] >> 16;
|
||||
int xap = xapoints[x] & 0xffff;
|
||||
|
||||
const QRgba32F *sptr = ypoints[y] + xpoints[x];
|
||||
float rx, gx, bx, ax;
|
||||
qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
|
||||
|
||||
const float yapf = yap * f;
|
||||
const float Cyf = Cy * f;
|
||||
float r = rx * yapf;
|
||||
float g = gx * yapf;
|
||||
float b = bx * yapf;
|
||||
float a = ax * yapf;
|
||||
int j;
|
||||
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
|
||||
sptr += sow;
|
||||
qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
|
||||
r += rx * Cyf;
|
||||
g += gx * Cyf;
|
||||
b += bx * Cyf;
|
||||
a += ax * Cyf;
|
||||
}
|
||||
sptr += sow;
|
||||
qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
|
||||
const float jf = j * f;
|
||||
r += rx * jf;
|
||||
g += gx * jf;
|
||||
b += bx * jf;
|
||||
a += ax * jf;
|
||||
|
||||
*dptr++ = QRgba32F{r, g, b, a};
|
||||
}
|
||||
}
|
||||
};
|
||||
multithread_pixels_function(isi, dh, scaleSection);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
|
||||
int dw, int dh, int dow, int sow);
|
||||
|
||||
|
|
@ -1014,6 +1231,12 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
|
|||
return QImage();
|
||||
}
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
if (qt_fpColorPrecision(src.format()))
|
||||
qt_qimageScaleRgbaFP(scaleinfo, (QRgba32F *)buffer.scanLine(0),
|
||||
dw, dh, dw, src.bytesPerLine() / 16);
|
||||
else
|
||||
#endif
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
if (src.depth() > 32)
|
||||
qt_qimageScaleRgba64(scaleinfo, (QRgba64 *)buffer.scanLine(0),
|
||||
|
|
|
|||
|
|
@ -224,24 +224,11 @@ inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, i
|
|||
{
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
// packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
|
||||
if (sizeof(quint32) % sizeof(T) == 0)
|
||||
qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
|
||||
else
|
||||
#endif
|
||||
static_assert(sizeof(quint32) % sizeof(T) == 0);
|
||||
qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
|
||||
#else
|
||||
qt_memrotate90_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void qt_memrotate90_template<quint32>(const quint32 *src, int w, int h, int sstride, quint32 *dest, int dstride)
|
||||
{
|
||||
// packed algorithm doesn't have any benefit for quint32
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
|
@ -268,24 +255,11 @@ inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight,
|
|||
{
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
// packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
|
||||
if (sizeof(quint32) % sizeof(T) == 0)
|
||||
qt_memrotate270_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
|
||||
else
|
||||
#endif
|
||||
static_assert(sizeof(quint32) % sizeof(T) == 0);
|
||||
qt_memrotate270_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
|
||||
#else
|
||||
qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void qt_memrotate270_template<quint32>(const quint32 *src, int w, int h, int sstride, quint32 *dest, int dstride)
|
||||
{
|
||||
// packed algorithm doesn't have any benefit for quint32
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define QT_IMPL_MEMROTATE(type) \
|
||||
|
|
@ -322,10 +296,11 @@ 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_SIMPLE_MEMROTATE(QRgba32F)
|
||||
QT_IMPL_SIMPLE_MEMROTATE(quint64)
|
||||
QT_IMPL_SIMPLE_MEMROTATE(quint32)
|
||||
QT_IMPL_SIMPLE_MEMROTATE(quint24)
|
||||
QT_IMPL_MEMROTATE(quint16)
|
||||
QT_IMPL_MEMROTATE(quint24)
|
||||
QT_IMPL_MEMROTATE(quint8)
|
||||
|
||||
void qt_memrotate90_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
|
|
@ -404,6 +379,21 @@ void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
|
|||
qt_memrotate270((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
void qt_memrotate90_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
{
|
||||
qt_memrotate90((const QRgba32F *)srcPixels, w, h, sbpl, (QRgba32F *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
void qt_memrotate180_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
{
|
||||
qt_memrotate180((const QRgba32F *)srcPixels, w, h, sbpl, (QRgba32F *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
void qt_memrotate270_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
|
||||
{
|
||||
qt_memrotate270((const QRgba32F *)srcPixels, w, h, sbpl, (QRgba32F *)destPixels, dbpl);
|
||||
}
|
||||
|
||||
MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
|
||||
// 90, 180, 270
|
||||
{
|
||||
|
|
@ -415,6 +405,8 @@ MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
|
|||
{ 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_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP16FPx4
|
||||
{ qt_memrotate90_128, qt_memrotate180_128, qt_memrotate270_128 }, // BPP32FPx4
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -4517,7 +4517,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
|
|||
|
||||
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
|
||||
gradient.colorTable32 = cacheInfo->buffer32;
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
|
||||
gradient.colorTable64 = cacheInfo->buffer64;
|
||||
#endif
|
||||
cachedGradient = std::move(cacheInfo);
|
||||
|
|
@ -4541,7 +4541,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
|
|||
|
||||
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
|
||||
gradient.colorTable32 = cacheInfo->buffer32;
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
|
||||
gradient.colorTable64 = cacheInfo->buffer64;
|
||||
#endif
|
||||
cachedGradient = std::move(cacheInfo);
|
||||
|
|
@ -4569,7 +4569,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
|
|||
|
||||
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
|
||||
gradient.colorTable32 = cacheInfo->buffer32;
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp)
|
||||
gradient.colorTable64 = cacheInfo->buffer64;
|
||||
#endif
|
||||
cachedGradient = std::move(cacheInfo);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -54,6 +54,7 @@
|
|||
#include <QtCore/qlist.h>
|
||||
#include <QtGui/qimage.h>
|
||||
#include <QtGui/qrgba64.h>
|
||||
#include <QtGui/qrgbaf.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -217,6 +218,16 @@ inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
|
|||
return (a << 30) | (r << 20) | (g << 10) | b;
|
||||
}
|
||||
|
||||
inline constexpr QRgba16F qConvertRgb64ToRgbaF16(QRgba64 c)
|
||||
{
|
||||
return QRgba16F::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
|
||||
}
|
||||
|
||||
inline constexpr QRgba32F qConvertRgb64ToRgbaF32(QRgba64 c)
|
||||
{
|
||||
return QRgba32F::fromRgba64(c.red(), c.green(), c.blue(), c.alpha());
|
||||
}
|
||||
|
||||
inline uint qRgbSwapRgb30(uint c)
|
||||
{
|
||||
const uint ag = c & 0xc00ffc00;
|
||||
|
|
@ -296,10 +307,19 @@ typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba6
|
|||
int count, const QList<QRgb> *clut,
|
||||
QDitherInfo *dither);
|
||||
|
||||
typedef void(QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut);
|
||||
typedef void(QT_FASTCALL *Convert64Func)(quint64 *buffer, int count, const QList<QRgb> *clut);
|
||||
typedef const QRgba32F *(QT_FASTCALL *FetchAndConvertPixelsFuncFP)(QRgba32F *buffer, const uchar *src, int index, int count,
|
||||
const QList<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *ConvertAndStorePixelsFuncFP)(uchar *dest, const QRgba32F *src, int index, int count,
|
||||
const QList<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut);
|
||||
typedef void (QT_FASTCALL *Convert64Func)(QRgba64 *buffer, int count);
|
||||
typedef void (QT_FASTCALL *ConvertFPFunc)(QRgba32F *buffer, int count);
|
||||
typedef void (QT_FASTCALL *Convert64ToFPFunc)(QRgba32F *buffer, const quint64 *src, int count);
|
||||
|
||||
typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
|
||||
const QList<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef const QRgba32F *(QT_FASTCALL *ConvertToFPFunc)(QRgba32F *buffer, const uint *src, int count,
|
||||
const QList<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
|
||||
|
||||
typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
|
||||
|
|
@ -316,6 +336,8 @@ struct QPixelLayout
|
|||
BPP24,
|
||||
BPP32,
|
||||
BPP64,
|
||||
BPP16FPx4,
|
||||
BPP32FPx4,
|
||||
BPPCount
|
||||
};
|
||||
|
||||
|
|
@ -333,6 +355,12 @@ struct QPixelLayout
|
|||
|
||||
extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
|
||||
|
||||
#if QT_CONFIG(raster_fp)
|
||||
extern ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats];
|
||||
extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats];
|
||||
extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats];
|
||||
#endif
|
||||
|
||||
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
|
||||
|
||||
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QRGBAF_H
|
||||
#define QRGBAF_H
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtCore/qfloat16.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
template<typename F>
|
||||
class alignas(sizeof(F) * 4) QRgbaF {
|
||||
public:
|
||||
F r;
|
||||
F g;
|
||||
F b;
|
||||
F a;
|
||||
|
||||
static constexpr
|
||||
QRgbaF fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
|
||||
{
|
||||
return QRgbaF{
|
||||
red * (1.0f / 65535.0f),
|
||||
green * (1.0f / 65535.0f),
|
||||
blue * (1.0f / 65535.0f),
|
||||
alpha * (1.0f / 65535.0f) };
|
||||
}
|
||||
|
||||
static constexpr
|
||||
QRgbaF fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
|
||||
{
|
||||
return QRgbaF{
|
||||
red * (1.0f / 255.0f),
|
||||
green * (1.0f / 255.0f),
|
||||
blue * (1.0f / 255.0f),
|
||||
alpha * (1.0f / 255.0f) };
|
||||
}
|
||||
static constexpr
|
||||
QRgbaF fromArgb32(uint rgb)
|
||||
{
|
||||
return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
|
||||
}
|
||||
|
||||
constexpr bool isOpaque() const { return a >= 1.0f; }
|
||||
constexpr bool isTransparent() const { return a <= 0.0f; }
|
||||
|
||||
constexpr float red() const { return r; }
|
||||
constexpr float green() const { return g; }
|
||||
constexpr float blue() const { return b; }
|
||||
constexpr float alpha() const { return a; }
|
||||
void setRed(float _red) { r = _red; }
|
||||
void setGreen(float _green) { g = _green; }
|
||||
void setBlue(float _blue) { b = _blue; }
|
||||
void setAlpha(float _alpha) { a = _alpha; }
|
||||
|
||||
constexpr float redNormalized() const { return std::clamp(static_cast<float>(r), 0.0f, 1.0f); }
|
||||
constexpr float greenNormalized() const { return std::clamp(static_cast<float>(g), 0.0f, 1.0f); }
|
||||
constexpr float blueNormalized() const { return std::clamp(static_cast<float>(b), 0.0f, 1.0f); }
|
||||
constexpr float alphaNormalized() const { return std::clamp(static_cast<float>(a), 0.0f, 1.0f); }
|
||||
|
||||
constexpr quint8 red8() const { return std::lround(redNormalized() * 255.0f); }
|
||||
constexpr quint8 green8() const { return std::lround(greenNormalized() * 255.0f); }
|
||||
constexpr quint8 blue8() const { return std::lround(blueNormalized() * 255.0f); }
|
||||
constexpr quint8 alpha8() const { return std::lround(alphaNormalized() * 255.0f); }
|
||||
constexpr uint toArgb32() const
|
||||
{
|
||||
return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
|
||||
}
|
||||
|
||||
constexpr quint16 red16() const { return std::lround(redNormalized() * 65535.0f); }
|
||||
constexpr quint16 green16() const { return std::lround(greenNormalized() * 65535.0f); }
|
||||
constexpr quint16 blue16() const { return std::lround(blueNormalized() * 65535.0f); }
|
||||
constexpr quint16 alpha16() const { return std::lround(alphaNormalized() * 65535.0f); }
|
||||
|
||||
constexpr Q_ALWAYS_INLINE QRgbaF premultiplied() const
|
||||
{
|
||||
return QRgbaF{r * a, g * a, b * a, a};
|
||||
}
|
||||
constexpr Q_ALWAYS_INLINE QRgbaF unpremultiplied() const
|
||||
{
|
||||
if (a <= 0.0f)
|
||||
return QRgbaF{0.0f, 0.0f, 0.0f, 0.0f};
|
||||
if (a >= 1.0f)
|
||||
return *this;
|
||||
const float ia = 1.0f / a;
|
||||
return QRgbaF{r * ia, g * ia, b * ia, a};
|
||||
}
|
||||
};
|
||||
|
||||
typedef QRgbaF<float> QRgba32F;
|
||||
typedef QRgbaF<qfloat16> QRgba16F;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QRGBAF_H
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:FDL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Free Documentation License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Free
|
||||
** Documentation License version 1.3 as published by the Free Software
|
||||
** Foundation and appearing in the file included in the packaging of
|
||||
** this file. Please review the following information to ensure
|
||||
** the GNU Free Documentation License version 1.3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\class QRgbaF
|
||||
\brief The QRgbaF struct contains a four part RGBA floating-point color.
|
||||
\since 6.2
|
||||
|
||||
\ingroup painting
|
||||
\inmodule QtGui
|
||||
|
||||
QRgba16F is a 64-bit data-structure containing four 16-bit floating point color channels: Red, green, blue and alpha.
|
||||
QRgba32F is a 128-bit data-structure containing four 32-bit floating point color channels: Red, green, blue and alpha.
|
||||
|
||||
\sa QRgb, QRgba64, QColor
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn static QRgbaF QRgbaF::fromRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
|
||||
|
||||
Constructs a QRgbaF value from the four 16-bit integer color channels \a red, \a green, \a blue and \a alpha.
|
||||
|
||||
\sa fromRgba()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn static QRgbaF QRgbaF::fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
|
||||
|
||||
Constructs a QRgbaF value from the four 8-bit color channels \a red, \a green, \a blue and \a alpha.
|
||||
|
||||
\sa fromArgb32()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn static QRgbaF QRgbaF::fromArgb32(uint rgb)
|
||||
|
||||
Constructs a QRgbaF value from the 32bit ARGB value \a rgb.
|
||||
|
||||
\sa fromRgba(), toArgb32()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QRgbaF::isOpaque() const
|
||||
|
||||
Returns whether the color is fully opaque.
|
||||
|
||||
\sa isTransparent(), alpha()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QRgbaF::isTransparent() const
|
||||
|
||||
Returns whether the color is fully transparent.
|
||||
|
||||
\sa isOpaque(), alpha()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::red() const
|
||||
|
||||
Returns the red color component.
|
||||
|
||||
\sa setRed()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QRgbaF::setRed(float red)
|
||||
|
||||
Sets the red color component of this color to \a red.
|
||||
|
||||
\sa red()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::green() const
|
||||
|
||||
Returns the green color component.
|
||||
|
||||
\sa setGreen()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QRgbaF::setGreen(float green)
|
||||
|
||||
Sets the green color component of this color to \a green.
|
||||
|
||||
\sa green()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::blue() const
|
||||
|
||||
Returns the blue color component.
|
||||
|
||||
\sa setBlue()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QRgbaF::setBlue(float blue)
|
||||
|
||||
Sets the blue color component of this color to \a blue.
|
||||
|
||||
\sa blue()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::alpha() const
|
||||
|
||||
Returns the alpha channel.
|
||||
|
||||
\sa setAlpha()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QRgbaF::setAlpha(float alpha)
|
||||
|
||||
Sets the alpha of this color to \a alpha.
|
||||
|
||||
\sa alpha()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::redNormalized() const
|
||||
|
||||
Returns the red color component normalized to values between \c 0.0f and \c 1.0f.
|
||||
|
||||
\sa setRed()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::greenNormalized() const
|
||||
|
||||
Returns the green color component normalized to values between \c 0.0f and \c 1.0f.
|
||||
|
||||
\sa setGreen()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::blueNormalized() const
|
||||
|
||||
Returns the blue color component normalized to values between \c 0.0f and \c 1.0f.
|
||||
|
||||
\sa setBlue()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn float QRgbaF::alphaNormalized() const
|
||||
|
||||
Returns the alpha channel normalized to values between \c 0.0f and \c 1.0f.
|
||||
|
||||
\sa alpha()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint8 QRgbaF::red8() const
|
||||
|
||||
Returns the red color component as an 8-bit.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint8 QRgbaF::green8() const
|
||||
|
||||
Returns the green color component as an 8-bit.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint8 QRgbaF::blue8() const
|
||||
|
||||
Returns the blue color component as an 8-bit.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint8 QRgbaF::alpha8() const
|
||||
|
||||
Returns the alpha channel as an 8-bit.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn uint QRgbaF::toArgb32() const
|
||||
|
||||
Returns the color as a 32-bit ARGB value.
|
||||
|
||||
\sa fromArgb32()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint16 QRgbaF::red16() const
|
||||
|
||||
Returns the red color component as a 16-bit integer.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint16 QRgbaF::green16() const
|
||||
|
||||
Returns the green color component as a 16-bit integer.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint16 QRgbaF::blue16() const
|
||||
|
||||
Returns the blue color component as a 16-bit integer.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn quint16 QRgbaF::alpha16() const
|
||||
|
||||
Returns the alpha channel as a 16-bit integer.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QRgbaF QRgbaF::premultiplied() const
|
||||
|
||||
Returns the color with the alpha premultiplied.
|
||||
|
||||
\sa unpremultiplied()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QRgbaF QRgbaF::unpremultiplied() const
|
||||
|
||||
Returns the color with the alpha unpremultiplied.
|
||||
|
||||
\sa premultiplied()
|
||||
*/
|
||||
|
|
@ -152,6 +152,25 @@ QT_BEGIN_NAMESPACE
|
|||
#define GL_DEPTH_STENCIL 0x84F9
|
||||
#endif
|
||||
|
||||
#ifndef GL_HALF_FLOAT
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA32F
|
||||
#define GL_RGBA32F 0x8814
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGB32F
|
||||
#define GL_RGB32F 0x8815
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA16F
|
||||
#define GL_RGBA16F 0x881A
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGB16F
|
||||
#define GL_RGB16F 0x881B
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
|
|
@ -554,6 +573,8 @@ void QOpenGLFramebufferObjectPrivate::initTexture(int idx)
|
|||
pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
else if (color.internalFormat == GL_RGB16 || color.internalFormat == GL_RGBA16)
|
||||
pixelType = GL_UNSIGNED_SHORT;
|
||||
else if (color.internalFormat == GL_RGB16F || color.internalFormat == GL_RGBA16F)
|
||||
pixelType = GL_HALF_FLOAT;
|
||||
|
||||
funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0,
|
||||
GL_RGBA, pixelType, nullptr);
|
||||
|
|
@ -1379,6 +1400,21 @@ static inline QImage qt_gl_read_framebuffer_rgba16(const QSize &size, bool inclu
|
|||
return img;
|
||||
}
|
||||
|
||||
static inline QImage qt_gl_read_framebuffer_rgba16f(const QSize &size, bool include_alpha, QOpenGLContext *context)
|
||||
{
|
||||
// We assume OpenGL (ES) 3.0+ here.
|
||||
QImage img(size, include_alpha ? QImage::Format_RGBA16FPx4_Premultiplied : QImage::Format_RGBX16FPx4);
|
||||
context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_HALF_FLOAT, img.bits());
|
||||
return img;
|
||||
}
|
||||
|
||||
static inline QImage qt_gl_read_framebuffer_rgba32f(const QSize &size, bool include_alpha, QOpenGLContext *context)
|
||||
{
|
||||
QImage img(size, include_alpha ? QImage::Format_RGBA32FPx4_Premultiplied : QImage::Format_RGBX32FPx4);
|
||||
context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_FLOAT, 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();
|
||||
|
|
@ -1400,6 +1436,14 @@ static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format,
|
|||
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_RGB16F:
|
||||
return qt_gl_read_framebuffer_rgba16f(size, false, ctx).mirrored(false, flip);
|
||||
case GL_RGBA16F:
|
||||
return qt_gl_read_framebuffer_rgba16f(size, include_alpha, ctx).mirrored(false, flip);
|
||||
case GL_RGB32F:
|
||||
return qt_gl_read_framebuffer_rgba32f(size, false, ctx).mirrored(false, flip);
|
||||
case GL_RGBA32F:
|
||||
return qt_gl_read_framebuffer_rgba32f(size, include_alpha, ctx).mirrored(false, flip);
|
||||
case GL_RGBA:
|
||||
case GL_RGBA8:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1572,6 +1572,8 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
|
|||
case QImage::Format_RGBA8888:
|
||||
case QImage::Format_ARGB32:
|
||||
case QImage::Format_RGBA64:
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::NonPremultipliedImageSrc);
|
||||
bindOption = { };
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@
|
|||
#include <private/qopenglcontext_p.h>
|
||||
#include <private/qopenglextensions_p.h>
|
||||
|
||||
#ifndef GL_HALF_FLOAT
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#endif
|
||||
|
||||
#ifndef GL_RED
|
||||
#define GL_RED 0x1903
|
||||
#endif
|
||||
|
|
@ -81,6 +85,14 @@
|
|||
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA16F
|
||||
#define GL_RGBA16F 0x881A
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA32F
|
||||
#define GL_RGBA32F 0x8814
|
||||
#endif
|
||||
|
||||
#ifndef GL_TEXTURE_SWIZZLE_R
|
||||
#define GL_TEXTURE_SWIZZLE_R 0x8E42
|
||||
#endif
|
||||
|
|
@ -236,6 +248,25 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
|
|||
pixelType = GL_UNSIGNED_SHORT;
|
||||
targetFormat = image.format();
|
||||
break;
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
if (context->format().majorVersion() >= 3) {
|
||||
externalFormat = GL_RGBA;
|
||||
internalFormat = GL_RGBA16F;
|
||||
pixelType = GL_HALF_FLOAT;
|
||||
targetFormat = image.format();
|
||||
}
|
||||
break;
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
externalFormat = internalFormat = GL_RGBA;
|
||||
if (context->format().majorVersion() >= 3)
|
||||
internalFormat = GL_RGBA32F;
|
||||
pixelType = GL_FLOAT;
|
||||
targetFormat = image.format();
|
||||
break;
|
||||
case QImage::Format_Indexed8:
|
||||
if (sRgbBinding) {
|
||||
// Always needs conversion
|
||||
|
|
@ -333,6 +364,10 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
|
|||
targetFormat = QImage::Format_RGBA8888_Premultiplied;
|
||||
else if (targetFormat == QImage::Format_RGBA64)
|
||||
targetFormat = QImage::Format_RGBA64_Premultiplied;
|
||||
else if (targetFormat == QImage::Format_RGBA16FPx4)
|
||||
targetFormat = QImage::Format_RGBA16FPx4_Premultiplied;
|
||||
else if (targetFormat == QImage::Format_RGBA32FPx4)
|
||||
targetFormat = QImage::Format_RGBA32FPx4_Premultiplied;
|
||||
} else {
|
||||
if (targetFormat == QImage::Format_ARGB32_Premultiplied)
|
||||
targetFormat = QImage::Format_ARGB32;
|
||||
|
|
@ -340,6 +375,10 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
|
|||
targetFormat = QImage::Format_RGBA8888;
|
||||
else if (targetFormat == QImage::Format_RGBA64_Premultiplied)
|
||||
targetFormat = QImage::Format_RGBA64;
|
||||
else if (targetFormat == QImage::Format_RGBA16FPx4_Premultiplied)
|
||||
targetFormat = QImage::Format_RGBA16FPx4;
|
||||
else if (targetFormat == QImage::Format_RGBA32FPx4_Premultiplied)
|
||||
targetFormat = QImage::Format_RGBA32FPx4;
|
||||
}
|
||||
|
||||
if (sRgbBinding) {
|
||||
|
|
|
|||
|
|
@ -323,6 +323,18 @@ static QLatin1String formatToString(QImage::Format format)
|
|||
return QLatin1String("Grayscale16");
|
||||
case QImage::Format_BGR888:
|
||||
return QLatin1String("BGR888");
|
||||
case QImage::Format_RGBX16FPx4:
|
||||
return QLatin1String("RGBx16FPx4");
|
||||
case QImage::Format_RGBA16FPx4:
|
||||
return QLatin1String("RGBA16FPx4");
|
||||
case QImage::Format_RGBA16FPx4_Premultiplied:
|
||||
return QLatin1String("RGBA16FPx4pm");
|
||||
case QImage::Format_RGBX32FPx4:
|
||||
return QLatin1String("RGBx32FPx4");
|
||||
case QImage::Format_RGBA32FPx4:
|
||||
return QLatin1String("RGBA32FPx4");
|
||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||
return QLatin1String("RGBA32FPx4pm");
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
|
@ -1765,7 +1777,17 @@ void tst_QImage::smoothScale2_data()
|
|||
QTest::addColumn<int>("size");
|
||||
|
||||
int sizes[] = { 2, 3, 4, 6, 7, 8, 10, 16, 20, 32, 40, 64, 100, 101, 128, 0 };
|
||||
QImage::Format formats[] = { QImage::Format_RGB32, QImage::Format_ARGB32_Premultiplied, QImage::Format_RGBX64, QImage::Format_RGBA64_Premultiplied, QImage::Format_Invalid };
|
||||
QImage::Format formats[] = { QImage::Format_RGB32,
|
||||
QImage::Format_ARGB32_Premultiplied,
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
QImage::Format_RGBX64,
|
||||
QImage::Format_RGBA64_Premultiplied,
|
||||
#endif
|
||||
#if QT_CONFIG(raster_fp)
|
||||
QImage::Format_RGBX32FPx4,
|
||||
QImage::Format_RGBA32FPx4_Premultiplied,
|
||||
#endif
|
||||
QImage::Format_Invalid };
|
||||
for (int j = 0; formats[j] != QImage::Format_Invalid; ++j) {
|
||||
QString formatstr = formatToString(formats[j]);
|
||||
for (int i = 0; sizes[i] != 0; ++i) {
|
||||
|
|
@ -1780,11 +1802,9 @@ void tst_QImage::smoothScale2()
|
|||
QFETCH(QImage::Format, format);
|
||||
QFETCH(int, size);
|
||||
|
||||
bool opaque = (format == QImage::Format_RGB32 || format == QImage::Format_RGBX64);
|
||||
|
||||
QRgb expected = opaque ? qRgb(63, 127, 255) : qRgba(31, 63, 127, 127);
|
||||
|
||||
QImage img(size, size, format);
|
||||
bool opaque = !img.hasAlphaChannel();
|
||||
QRgb expected = opaque ? qRgb(63, 127, 255) : qRgba(31, 63, 127, 127);
|
||||
img.fill(expected);
|
||||
|
||||
// scale x down, y down
|
||||
|
|
@ -1929,6 +1949,9 @@ void tst_QImage::smoothScale4_data()
|
|||
#if QT_CONFIG(raster_64bit)
|
||||
QTest::newRow("RGBx64") << QImage::Format_RGBX64;
|
||||
#endif
|
||||
#if QT_CONFIG(raster_fp)
|
||||
QTest::newRow("RGBx32FP") << QImage::Format_RGBX32FPx4;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QImage::smoothScale4()
|
||||
|
|
@ -2356,6 +2379,8 @@ void tst_QImage::fillColor_data()
|
|||
QImage::Format_RGBA8888_Premultiplied,
|
||||
QImage::Format_BGR30,
|
||||
QImage::Format_A2RGB30_Premultiplied,
|
||||
QImage::Format_RGBX16FPx4,
|
||||
QImage::Format_RGBA32FPx4_Premultiplied,
|
||||
};
|
||||
|
||||
for (int i=0; names[i] != 0; ++i) {
|
||||
|
|
@ -2678,7 +2703,6 @@ void tst_QImage::inplaceRgbSwapped_data()
|
|||
|
||||
void tst_QImage::inplaceRgbSwapped()
|
||||
{
|
||||
#if defined(Q_COMPILER_REF_QUALIFIERS)
|
||||
QFETCH(QImage::Format, format);
|
||||
|
||||
QImage image(64, 1, format);
|
||||
|
|
@ -2686,7 +2710,7 @@ void tst_QImage::inplaceRgbSwapped()
|
|||
|
||||
QList<QRgb> testColor(image.width());
|
||||
for (int i = 0; i < image.width(); ++i)
|
||||
testColor[i] = qRgb(i * 2, i * 3, 255 - i * 4);
|
||||
testColor[i] = qRgb(i * 2, i * 3, std::min(255 - i * 4, 0));
|
||||
|
||||
if (format == QImage::Format_Indexed8) {
|
||||
for (int i = 0; i < image.width(); ++i) {
|
||||
|
|
@ -2739,7 +2763,6 @@ void tst_QImage::inplaceRgbSwapped()
|
|||
QCOMPARE(dataSwapped, orig.rgbSwapped());
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3006,6 +3029,7 @@ void tst_QImage::inplaceRgbConversion_data()
|
|||
|
||||
void tst_QImage::inplaceRgbConversion()
|
||||
{
|
||||
// Test that conversions between RGB formats of the same bitwidth can be done inplace.
|
||||
QFETCH(QImage::Format, format);
|
||||
QFETCH(QImage::Format, dest_format);
|
||||
|
||||
|
|
|
|||
|
|
@ -1060,6 +1060,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;
|
||||
QTest::newRow("rgbaFP16pm") << QImage::Format_RGBA16FPx4_Premultiplied;
|
||||
}
|
||||
|
||||
void tst_QPainter::fillRect()
|
||||
|
|
@ -1558,6 +1559,8 @@ void tst_QPainter::qimageFormats_data()
|
|||
QTest::newRow("Qimage::Format_BGR888") << QImage::Format_BGR888;
|
||||
QTest::newRow("Qimage::Format_A2RGB30_Premultiplied") << QImage::Format_A2RGB30_Premultiplied;
|
||||
QTest::newRow("Qimage::Format_RGB30") << QImage::Format_RGB30;
|
||||
QTest::newRow("QImage::Format_RGBX16FPx4") << QImage::Format_RGBX16FPx4;
|
||||
QTest::newRow("QImage::Format_RGBA32FPx4_Premultiplied") << QImage::Format_RGBA32FPx4_Premultiplied;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -182,6 +182,14 @@ const char *PaintCommands::imageFormatTable[] = {
|
|||
"RGBx64",
|
||||
"RGBA64",
|
||||
"RGBA64_Premultiplied",
|
||||
"Grayscale16",
|
||||
"BGR888",
|
||||
"RGBx16FPx4",
|
||||
"RGBA16FPx4",
|
||||
"RGBA16FPx4_Premultiplied",
|
||||
"RGBx32FPx4",
|
||||
"RGBA32FPx4",
|
||||
"RGBA32FPx4_Premultiplied",
|
||||
};
|
||||
|
||||
int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit)
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ private slots:
|
|||
void testRasterGrayscale8();
|
||||
void testRasterRGBA64PM_data();
|
||||
void testRasterRGBA64PM();
|
||||
void testRasterRGBA16F_data();
|
||||
void testRasterRGBA16F();
|
||||
void testRasterRGBA32FPM_data();
|
||||
void testRasterRGBA32FPM();
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
void testOpenGL_data();
|
||||
|
|
@ -242,6 +246,27 @@ void tst_Lancelot::testRasterRGBA64PM()
|
|||
}
|
||||
|
||||
|
||||
void tst_Lancelot::testRasterRGBA16F_data()
|
||||
{
|
||||
setupTestSuite();
|
||||
}
|
||||
|
||||
void tst_Lancelot::testRasterRGBA16F()
|
||||
{
|
||||
runTestSuite(Raster, QImage::Format_RGBA16FPx4);
|
||||
}
|
||||
|
||||
void tst_Lancelot::testRasterRGBA32FPM_data()
|
||||
{
|
||||
setupTestSuite();
|
||||
}
|
||||
|
||||
void tst_Lancelot::testRasterRGBA32FPM()
|
||||
{
|
||||
runTestSuite(Raster, QImage::Format_RGBA32FPx4_Premultiplied);
|
||||
}
|
||||
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
bool tst_Lancelot::checkSystemGLSupport()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue