diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-04-20 16:53:25 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-04-23 10:14:48 +0000 |
commit | f657ecdc5ddef611a503ce460dc81fe2f0bbc2d6 (patch) | |
tree | 8fc435147a8a409a58f9e9e7c4f96effae121957 | |
parent | c3737573ced4dc2217f31aac627fa8070e7512c8 (diff) |
Fix inplace double mirroring on odd sized images
The QImage inplace mirroring method, failed to handle the middle line
when mirroring both ways (rotate 180). In both other mirroring cases
the middle can be left untouched, but in this case it needs to be
mirrored half way.
To make the logic simpler, double mirroring will now mirror half the
lines instead of half of every line.
Change-Id: Iaa1f1e1c3f7dedfb78891fc93207f6d0c64bcafe
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
-rw-r--r-- | src/gui/image/qimage.cpp | 12 | ||||
-rw-r--r-- | tests/auto/gui/image/qimage/tst_qimage.cpp | 51 |
2 files changed, 61 insertions, 2 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index f20800440d..f09e73f214 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2825,14 +2825,22 @@ template<class T> inline void do_mirror_data(QImageData *dst, QImageData *src, if (dst == src) { // When mirroring in-place, stop in the middle for one of the directions, since we // are swapping the bytes instead of merely copying. - const int srcXEnd = dstX0 ? w / 2 : w; - const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h; + const int srcXEnd = (dstX0 && !dstY0) ? w / 2 : w; + const int srcYEnd = dstY0 ? h / 2 : h; for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) { T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line); for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr) std::swap(srcPtr[srcX], dstPtr[dstX]); } + // If mirroring both ways, the middle line needs to be mirrored horizontally only. + if (dstX0 && dstY0 && (h & 1)) { + int srcY = h / 2; + int srcXEnd2 = w / 2; + T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); + for (int srcX = 0, dstX = dstX0; srcX < srcXEnd2; ++srcX, dstX += dstXIncr) + std::swap(srcPtr[srcX], srcPtr[dstX]); + } } else { for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) { T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line); diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 525d5b33a0..5691a654d7 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -155,6 +155,9 @@ private slots: void inplaceMirrored_data(); void inplaceMirrored(); + void inplaceMirroredOdd_data(); + void inplaceMirroredOdd(); + void inplaceRgbMirrored(); void inplaceConversion_data(); @@ -2471,6 +2474,54 @@ void tst_QImage::inplaceMirrored() #endif } +void tst_QImage::inplaceMirroredOdd_data() +{ + QTest::addColumn<QImage::Format>("format"); + QTest::addColumn<bool>("swap_vertical"); + QTest::addColumn<bool>("swap_horizontal"); + + QTest::newRow("Format_ARGB32, vertical") << QImage::Format_ARGB32 << true << false; + QTest::newRow("Format_RGB888, vertical") << QImage::Format_RGB888 << true << false; + QTest::newRow("Format_RGB16, vertical") << QImage::Format_RGB16 << true << false; + + QTest::newRow("Format_ARGB32, horizontal") << QImage::Format_ARGB32 << false << true; + QTest::newRow("Format_RGB888, horizontal") << QImage::Format_RGB888 << false << true; + QTest::newRow("Format_RGB16, horizontal") << QImage::Format_RGB16 << false << true; + + QTest::newRow("Format_ARGB32, horizontal+vertical") << QImage::Format_ARGB32 << true << true; + QTest::newRow("Format_RGB888, horizontal+vertical") << QImage::Format_RGB888 << true << true; + QTest::newRow("Format_RGB16, horizontal+vertical") << QImage::Format_RGB16 << true << true; +} + +void tst_QImage::inplaceMirroredOdd() +{ +#if defined(Q_COMPILER_REF_QUALIFIERS) + QFETCH(QImage::Format, format); + QFETCH(bool, swap_vertical); + QFETCH(bool, swap_horizontal); + + QImage image(15, 15, format); + + for (int i = 0; i < image.height(); ++i) + for (int j = 0; j < image.width(); ++j) + image.setPixel(j, i, qRgb(j*16, i*16, 0)); + + const uchar* originalPtr = image.constScanLine(0); + + QImage imageMirrored = std::move(image).mirrored(swap_horizontal, swap_vertical); + for (int i = 0; i < imageMirrored.height(); ++i) { + int mirroredI = swap_vertical ? (imageMirrored.height() - i - 1) : i; + for (int j = 0; j < imageMirrored.width(); ++j) { + int mirroredJ = swap_horizontal ? (imageMirrored.width() - j - 1) : j; + QRgb mirroredColor = imageMirrored.pixel(mirroredJ, mirroredI); + QCOMPARE(qRed(mirroredColor) & 0xF8, j * 16); + QCOMPARE(qGreen(mirroredColor) & 0xF8, i * 16); + } + } + QCOMPARE(imageMirrored.constScanLine(0), originalPtr); +#endif +} + void tst_QImage::inplaceRgbMirrored() { #if defined(Q_COMPILER_REF_QUALIFIERS) |