From 454fb13c465e29f0d0f9a295bdb822b4a09c7e48 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 21 Apr 2015 13:07:11 +0200 Subject: Handle Grayscale8 TIFFs Correctly read and write Grayscale8 image format. Change-Id: I537c68f94077458c69ee1de08b5b37986b54aa26 Reviewed-by: Ivan Komissarov Reviewed-by: Gunnar Sletta --- src/plugins/imageformats/tiff/qtiffhandler.cpp | 43 +++++++++++++++++++++++--- tests/auto/tiff/tst_qtiff.cpp | 20 ++++-------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index ceb6935..a6b87af 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -245,6 +245,8 @@ bool QTiffHandlerPrivate::openForRead(QIODevice *device) if (grayscale && bitPerSample == 1 && samplesPerPixel == 1) format = QImage::Format_Mono; + else if (photometric == PHOTOMETRIC_MINISBLACK && bitPerSample == 8 && samplesPerPixel == 1) + format = QImage::Format_Grayscale8; else if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1) format = QImage::Format_Indexed8; else if (samplesPerPixel < 4) @@ -366,6 +368,15 @@ bool QTiffHandler::read(QImage *image) // free redTable, greenTable and greenTable done by libtiff } + } else if (format == QImage::Format_Grayscale8) { + if (!image->isNull()) { + for (uint32 y = 0; y < height; ++y) { + if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { + d->close(); + return false; + } + } + } } else { if (!image->isNull()) { const int stopOnError = 1; @@ -428,6 +439,29 @@ static bool checkGrayscale(const QVector &colorTable) return true; } +static QVector effectiveColorTable(const QImage &image) +{ + QVector colors; + switch (image.format()) { + case QImage::Format_Indexed8: + colors = image.colorTable(); + break; + case QImage::Format_Alpha8: + colors.resize(256); + for (int i = 0; i < 256; ++i) + colors[i] = qRgba(0, 0, 0, i); + break; + case QImage::Format_Grayscale8: + colors.resize(256); + for (int i = 0; i < 256; ++i) + colors[i] = qRgb(i, i, i); + break; + default: + Q_UNREACHABLE(); + } + return colors; +} + bool QTiffHandler::write(const QImage &image) { if (!device()->isWritable()) @@ -515,12 +549,14 @@ bool QTiffHandler::write(const QImage &image) } } TIFFClose(tiff); - } else if (format == QImage::Format_Indexed8) { - const QVector colorTable = image.colorTable(); + } else if (format == QImage::Format_Indexed8 + || format == QImage::Format_Grayscale8 + || format == QImage::Format_Alpha8) { + QVector colorTable = effectiveColorTable(image); bool isGrayscale = checkGrayscale(colorTable); if (isGrayscale) { uint16 photometric = PHOTOMETRIC_MINISBLACK; - if (image.colorTable().at(0) == 0xffffffff) + if (colorTable.at(0) == 0xffffffff) photometric = PHOTOMETRIC_MINISWHITE; if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) @@ -579,7 +615,6 @@ bool QTiffHandler::write(const QImage &image) } } TIFFClose(tiff); - } else if (!image.hasAlphaChannel()) { if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW) diff --git a/tests/auto/tiff/tst_qtiff.cpp b/tests/auto/tiff/tst_qtiff.cpp index a073025..70837a5 100644 --- a/tests/auto/tiff/tst_qtiff.cpp +++ b/tests/auto/tiff/tst_qtiff.cpp @@ -364,31 +364,23 @@ void tst_qtiff::readWriteNonDestructive_data() { QTest::addColumn("format"); QTest::addColumn("expectedFormat"); - QTest::addColumn("grayscale"); QTest::addColumn("transformation"); - QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << false << QImageIOHandler::TransformationNone; - QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << false << QImageIOHandler::TransformationMirror; - QTest::newRow("tiff argb32pm") << QImage::Format_ARGB32_Premultiplied << QImage::Format_ARGB32_Premultiplied << false << QImageIOHandler::TransformationRotate90; - QTest::newRow("tiff rgb32") << QImage::Format_RGB32 << QImage::Format_RGB32 << false << QImageIOHandler::TransformationRotate270; - QTest::newRow("tiff grayscale") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << true << QImageIOHandler::TransformationFlip; + QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << QImageIOHandler::TransformationNone; + QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << QImageIOHandler::TransformationMirror; + QTest::newRow("tiff argb32pm") << QImage::Format_ARGB32_Premultiplied << QImage::Format_ARGB32_Premultiplied << QImageIOHandler::TransformationRotate90; + QTest::newRow("tiff rgb32") << QImage::Format_RGB32 << QImage::Format_RGB32 << QImageIOHandler::TransformationRotate270; + QTest::newRow("tiff grayscale") << QImage::Format_Grayscale8 << QImage::Format_Grayscale8 << QImageIOHandler::TransformationFlip; } void tst_qtiff::readWriteNonDestructive() { QFETCH(QImage::Format, format); QFETCH(QImage::Format, expectedFormat); - QFETCH(bool, grayscale); QFETCH(QImageIOHandler::Transformation, transformation); + QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format); QVERIFY(!image.isNull()); - if (grayscale) { - QVector colors; - for (int i = 0; i < 256; ++i) - colors << qRgb(i, i, i); - image.setColorTable(colors); - } - QByteArray output; QBuffer buf(&output); QVERIFY(buf.open(QIODevice::WriteOnly)); -- cgit v1.2.3