Preserve QImage metadata in image transforms
Some QImage methods were not preserving image metadata, or only preserving some of it. This adds the missing parts and adds a test for metadata. Change-Id: Ib5892a23e49dfde5ea26074d3deaa887fa930c6b Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
This commit is contained in:
parent
1576f62eaf
commit
f15d6c3fa9
@ -1087,6 +1087,15 @@ void QImage::detach()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void copyMetadata(QImageData *dst, const QImageData *src)
|
||||||
|
{
|
||||||
|
// Doesn't copy colortable and alpha_clut, or offset.
|
||||||
|
dst->dpmx = src->dpmx;
|
||||||
|
dst->dpmy = src->dpmy;
|
||||||
|
dst->devicePixelRatio = src->devicePixelRatio;
|
||||||
|
dst->text = src->text;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QImage QImage::copy(int x, int y, int width, int height) const
|
\fn QImage QImage::copy(int x, int y, int width, int height) const
|
||||||
\overload
|
\overload
|
||||||
@ -1136,12 +1145,9 @@ QImage QImage::copy(const QRect& r) const
|
|||||||
} else
|
} else
|
||||||
memcpy(image.bits(), bits(), d->nbytes);
|
memcpy(image.bits(), bits(), d->nbytes);
|
||||||
image.d->colortable = d->colortable;
|
image.d->colortable = d->colortable;
|
||||||
image.d->dpmx = d->dpmx;
|
|
||||||
image.d->dpmy = d->dpmy;
|
|
||||||
image.d->devicePixelRatio = d->devicePixelRatio;
|
|
||||||
image.d->offset = d->offset;
|
image.d->offset = d->offset;
|
||||||
image.d->has_alpha_clut = d->has_alpha_clut;
|
image.d->has_alpha_clut = d->has_alpha_clut;
|
||||||
image.d->text = d->text;
|
copyMetadata(image.d, d);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1227,12 +1233,9 @@ QImage QImage::copy(const QRect& r) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image.d->dpmx = dotsPerMeterX();
|
copyMetadata(image.d, d);
|
||||||
image.d->dpmy = dotsPerMeterY();
|
|
||||||
image.d->devicePixelRatio = devicePixelRatio();
|
|
||||||
image.d->offset = offset();
|
image.d->offset = offset();
|
||||||
image.d->has_alpha_clut = d->has_alpha_clut;
|
image.d->has_alpha_clut = d->has_alpha_clut;
|
||||||
image.d->text = d->text;
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1983,11 +1986,8 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
|
|||||||
|
|
||||||
QIMAGE_SANITYCHECK_MEMORY(image);
|
QIMAGE_SANITYCHECK_MEMORY(image);
|
||||||
|
|
||||||
image.setDotsPerMeterY(dotsPerMeterY());
|
image.d->offset = offset();
|
||||||
image.setDotsPerMeterX(dotsPerMeterX());
|
copyMetadata(image.d, d);
|
||||||
image.setDevicePixelRatio(devicePixelRatio());
|
|
||||||
|
|
||||||
image.d->text = d->text;
|
|
||||||
|
|
||||||
converter(image.d, d, flags);
|
converter(image.d, d, flags);
|
||||||
return image;
|
return image;
|
||||||
@ -2112,9 +2112,9 @@ QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Q
|
|||||||
|
|
||||||
QImage image(d->width, d->height, format);
|
QImage image(d->width, d->height, format);
|
||||||
QIMAGE_SANITYCHECK_MEMORY(image);
|
QIMAGE_SANITYCHECK_MEMORY(image);
|
||||||
image.setDevicePixelRatio(devicePixelRatio());
|
|
||||||
|
|
||||||
image.d->text = d->text;
|
image.d->offset = offset();
|
||||||
|
copyMetadata(image.d, d);
|
||||||
|
|
||||||
converter(image.d, d, flags);
|
converter(image.d, d, flags);
|
||||||
return image;
|
return image;
|
||||||
@ -2952,9 +2952,7 @@ QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
|
|||||||
|
|
||||||
result.d->colortable = d->colortable;
|
result.d->colortable = d->colortable;
|
||||||
result.d->has_alpha_clut = d->has_alpha_clut;
|
result.d->has_alpha_clut = d->has_alpha_clut;
|
||||||
result.d->devicePixelRatio = d->devicePixelRatio;
|
copyMetadata(result.d, d);
|
||||||
result.d->dpmx = d->dpmx;
|
|
||||||
result.d->dpmy = d->dpmy;
|
|
||||||
|
|
||||||
do_mirror(result.d, d, horizontal, vertical);
|
do_mirror(result.d, d, horizontal, vertical);
|
||||||
|
|
||||||
@ -3103,6 +3101,7 @@ QImage QImage::rgbSwapped_helper() const
|
|||||||
rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
|
rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
copyMetadata(res.d, d);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4254,8 +4253,8 @@ int QImage::bitPlaneCount() const
|
|||||||
return bpc;
|
return bpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QImage smoothScaled(const QImage &source, int w, int h) {
|
QImage QImage::smoothScaled(int w, int h) const {
|
||||||
QImage src = source;
|
QImage src = *this;
|
||||||
switch (src.format()) {
|
switch (src.format()) {
|
||||||
case QImage::Format_RGB32:
|
case QImage::Format_RGB32:
|
||||||
case QImage::Format_ARGB32_Premultiplied:
|
case QImage::Format_ARGB32_Premultiplied:
|
||||||
@ -4270,11 +4269,11 @@ static QImage smoothScaled(const QImage &source, int w, int h) {
|
|||||||
else
|
else
|
||||||
src = src.convertToFormat(QImage::Format_RGB32);
|
src = src.convertToFormat(QImage::Format_RGB32);
|
||||||
}
|
}
|
||||||
|
src = qSmoothScaleImage(src, w, h);
|
||||||
return qSmoothScaleImage(src, w, h);
|
copyMetadata(src.d, d);
|
||||||
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static QImage rotated90(const QImage &image) {
|
static QImage rotated90(const QImage &image) {
|
||||||
QImage out(image.height(), image.width(), image.format());
|
QImage out(image.height(), image.width(), image.format());
|
||||||
if (image.colorCount() > 0)
|
if (image.colorCount() > 0)
|
||||||
@ -4475,13 +4474,13 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
|
|||||||
// Make use of the optimized algorithm when we're scaling
|
// Make use of the optimized algorithm when we're scaling
|
||||||
if (scale_xform && mode == Qt::SmoothTransformation) {
|
if (scale_xform && mode == Qt::SmoothTransformation) {
|
||||||
if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
|
if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
|
||||||
return smoothScaled(mirrored(true, true), wd, hd);
|
return smoothScaled(wd, hd).mirrored(true, true);
|
||||||
} else if (mat.m11() < 0.0F) { // horizontal flip
|
} else if (mat.m11() < 0.0F) { // horizontal flip
|
||||||
return smoothScaled(mirrored(true, false), wd, hd);
|
return smoothScaled(wd, hd).mirrored(true, false);
|
||||||
} else if (mat.m22() < 0.0F) { // vertical flip
|
} else if (mat.m22() < 0.0F) { // vertical flip
|
||||||
return smoothScaled(mirrored(false, true), wd, hd);
|
return smoothScaled(wd, hd).mirrored(false, true);
|
||||||
} else { // no flipping
|
} else { // no flipping
|
||||||
return smoothScaled(*this, wd, hd);
|
return smoothScaled(wd, hd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4533,9 +4532,6 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
|
|||||||
dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
|
dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
|
||||||
}
|
}
|
||||||
|
|
||||||
dImage.d->dpmx = dotsPerMeterX();
|
|
||||||
dImage.d->dpmy = dotsPerMeterY();
|
|
||||||
|
|
||||||
// initizialize the data
|
// initizialize the data
|
||||||
if (d->format == QImage::Format_Indexed8) {
|
if (d->format == QImage::Format_Indexed8) {
|
||||||
if (dImage.d->colortable.size() < 256) {
|
if (dImage.d->colortable.size() < 256) {
|
||||||
@ -4573,8 +4569,8 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
|
|||||||
int dbpl = dImage.bytesPerLine();
|
int dbpl = dImage.bytesPerLine();
|
||||||
qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
|
qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
|
||||||
}
|
}
|
||||||
|
copyMetadata(dImage.d, d);
|
||||||
|
|
||||||
dImage.d->devicePixelRatio = devicePixelRatio();
|
|
||||||
return dImage;
|
return dImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +328,7 @@ protected:
|
|||||||
void rgbSwapped_inplace();
|
void rgbSwapped_inplace();
|
||||||
QImage convertToFormat_helper(Format format, Qt::ImageConversionFlags flags) const;
|
QImage convertToFormat_helper(Format format, Qt::ImageConversionFlags flags) const;
|
||||||
bool convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags);
|
bool convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags);
|
||||||
|
QImage smoothScaled(int w, int h) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class QWSOnScreenSurface;
|
friend class QWSOnScreenSurface;
|
||||||
|
@ -184,6 +184,8 @@ private slots:
|
|||||||
|
|
||||||
void devicePixelRatio();
|
void devicePixelRatio();
|
||||||
|
|
||||||
|
void metadataPassthrough();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_prefix;
|
const QString m_prefix;
|
||||||
};
|
};
|
||||||
@ -2827,5 +2829,39 @@ void tst_QImage::devicePixelRatio()
|
|||||||
QCOMPARE(b.devicePixelRatio(), qreal(1.0));
|
QCOMPARE(b.devicePixelRatio(), qreal(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QImage::metadataPassthrough()
|
||||||
|
{
|
||||||
|
QImage a(64, 64, QImage::Format_ARGB32);
|
||||||
|
a.fill(Qt::white);
|
||||||
|
a.setText(QStringLiteral("Test"), QStringLiteral("Text"));
|
||||||
|
a.setDotsPerMeterX(100);
|
||||||
|
a.setDotsPerMeterY(80);
|
||||||
|
a.setDevicePixelRatio(2.0);
|
||||||
|
|
||||||
|
QImage scaled = a.scaled(QSize(32, 32), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
|
QCOMPARE(scaled.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
|
||||||
|
QCOMPARE(scaled.dotsPerMeterX(), a.dotsPerMeterX());
|
||||||
|
QCOMPARE(scaled.dotsPerMeterY(), a.dotsPerMeterY());
|
||||||
|
QCOMPARE(scaled.devicePixelRatio(), a.devicePixelRatio());
|
||||||
|
|
||||||
|
scaled = a.scaled(QSize(128, 128), Qt::IgnoreAspectRatio, Qt::FastTransformation);
|
||||||
|
QCOMPARE(scaled.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
|
||||||
|
QCOMPARE(scaled.dotsPerMeterX(), a.dotsPerMeterX());
|
||||||
|
QCOMPARE(scaled.dotsPerMeterY(), a.dotsPerMeterY());
|
||||||
|
QCOMPARE(scaled.devicePixelRatio(), a.devicePixelRatio());
|
||||||
|
|
||||||
|
QImage mirrored = a.mirrored();
|
||||||
|
QCOMPARE(mirrored.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
|
||||||
|
QCOMPARE(mirrored.dotsPerMeterX(), a.dotsPerMeterX());
|
||||||
|
QCOMPARE(mirrored.dotsPerMeterY(), a.dotsPerMeterY());
|
||||||
|
QCOMPARE(mirrored.devicePixelRatio(), a.devicePixelRatio());
|
||||||
|
|
||||||
|
QImage swapped = a.rgbSwapped();
|
||||||
|
QCOMPARE(swapped.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
|
||||||
|
QCOMPARE(swapped.dotsPerMeterX(), a.dotsPerMeterX());
|
||||||
|
QCOMPARE(swapped.dotsPerMeterY(), a.dotsPerMeterY());
|
||||||
|
QCOMPARE(swapped.devicePixelRatio(), a.devicePixelRatio());
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(tst_QImage)
|
QTEST_GUILESS_MAIN(tst_QImage)
|
||||||
#include "tst_qimage.moc"
|
#include "tst_qimage.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user