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>
This commit is contained in:
Allan Sandfeld Jensen 2015-04-20 16:53:25 +02:00
parent c3737573ce
commit f657ecdc5d
2 changed files with 61 additions and 2 deletions

View File

@ -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);

View File

@ -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)