diff options
-rw-r--r-- | src/plugins/imageformats/tiff/qtiffhandler.cpp | 155 | ||||
-rw-r--r-- | tests/auto/qimagereader/images/grayscale-ref.tif | bin | 0 -> 256182 bytes | |||
-rw-r--r-- | tests/auto/qimagereader/images/grayscale.tif | bin | 0 -> 64162 bytes | |||
-rw-r--r-- | tests/auto/qimagereader/tst_qimagereader.cpp | 9 | ||||
-rw-r--r-- | tests/auto/qimagewriter/tst_qimagewriter.cpp | 17 |
5 files changed, 118 insertions, 63 deletions
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index 3669be7..9538745 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -192,7 +192,14 @@ bool QTiffHandler::read(QImage *image) return false; } - if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) { + uint16 bitPerSample; + if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { + TIFFClose(tiff); + return false; + } + + bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE; + if (grayscale && bitPerSample == 1) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) *image = QImage(width, height, QImage::Format_Mono); QVector<QRgb> colortable(2); @@ -208,42 +215,43 @@ bool QTiffHandler::read(QImage *image) if (!image->isNull()) { for (uint32 y=0; y<height; ++y) { if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { - TIFFClose(tiff); - return false; + TIFFClose(tiff); + return false; } } } } else { - uint16 bitPerSample; - if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { - TIFFClose(tiff); - return false; - } - if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) { + if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) *image = QImage(width, height, QImage::Format_Indexed8); if (!image->isNull()) { - // create the color table const uint16 tableSize = 256; - uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); - uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); - uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); - if (!redTable || !greenTable || !blueTable) { - TIFFClose(tiff); - return false; - } - if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { - TIFFClose(tiff); - return false; - } - QVector<QRgb> qtColorTable(tableSize); - for (int i = 0; i<tableSize ;++i) { - const int red = redTable[i] / 257; - const int green = greenTable[i] / 257; - const int blue = blueTable[i] / 257; - qtColorTable[i] = qRgb(red, green, blue); + if (grayscale) { + for (int i = 0; i<tableSize; ++i) { + const int c = (photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i); + qtColorTable[i] = qRgb(c, c, c); + } + } else { + // create the color table + uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } + if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { + TIFFClose(tiff); + return false; + } + for (int i = 0; i<tableSize ;++i) { + const int red = redTable[i] / 257; + const int green = greenTable[i] / 257; + const int blue = blueTable[i] / 257; + qtColorTable[i] = qRgb(red, green, blue); + } } image->setColorTable(qtColorTable); @@ -371,6 +379,20 @@ bool QTiffHandler::read(QImage *image) return true; } +static bool checkGrayscale(const QVector<QRgb> &colorTable) +{ + if (colorTable.size() != 256) + return false; + + const bool increasing = (colorTable.at(0) == 0xff000000); + for (int i = 0; i < 256; ++i) { + if (increasing && colorTable.at(i) != qRgb(i, i, i) + || !increasing && colorTable.at(i) != qRgb(255 - i, 255 - i, 255 - i)) + return false; + } + return true; +} + bool QTiffHandler::write(const QImage &image) { if (!device()->isWritable()) @@ -425,7 +447,8 @@ bool QTiffHandler::write(const QImage &image) if (image.colorTable().at(0) == 0xffffffff) photometric = PHOTOMETRIC_MINISWHITE; if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) - || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) { + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)) { TIFFClose(tiff); return false; } @@ -450,43 +473,55 @@ bool QTiffHandler::write(const QImage &image) } TIFFClose(tiff); } else if (format == QImage::Format_Indexed8) { - if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) - || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) - || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { - TIFFClose(tiff); - return false; - } - //// write the color table - // allocate the color tables - uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); - uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); - uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); - if (!redTable || !greenTable || !blueTable) { - TIFFClose(tiff); - return false; - } - - // set the color table const QVector<QRgb> colorTable = image.colorTable(); + bool isGrayscale = checkGrayscale(colorTable); + if (isGrayscale) { + uint16 photometric = PHOTOMETRIC_MINISBLACK; + if (image.colorTable().at(0) == 0xffffffff) + photometric = PHOTOMETRIC_MINISWHITE; + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } + } else { + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } + //// write the color table + // allocate the color tables + uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } - const int tableSize = colorTable.size(); - Q_ASSERT(tableSize <= 256); - for (int i = 0; i<tableSize; ++i) { - const QRgb color = colorTable.at(i); - redTable[i] = qRed(color) * 257; - greenTable[i] = qGreen(color) * 257; - blueTable[i] = qBlue(color) * 257; - } + // set the color table + const int tableSize = colorTable.size(); + Q_ASSERT(tableSize <= 256); + for (int i = 0; i<tableSize; ++i) { + const QRgb color = colorTable.at(i); + redTable[i] = qRed(color) * 257; + greenTable[i] = qGreen(color) * 257; + blueTable[i] = qBlue(color) * 257; + } - const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); + const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); - qFree(redTable); - qFree(greenTable); - qFree(blueTable); + qFree(redTable); + qFree(greenTable); + qFree(blueTable); - if (!setColorTableSuccess) { - TIFFClose(tiff); - return false; + if (!setColorTableSuccess) { + TIFFClose(tiff); + return false; + } } //// write the data diff --git a/tests/auto/qimagereader/images/grayscale-ref.tif b/tests/auto/qimagereader/images/grayscale-ref.tif Binary files differnew file mode 100644 index 0000000..960531e --- /dev/null +++ b/tests/auto/qimagereader/images/grayscale-ref.tif diff --git a/tests/auto/qimagereader/images/grayscale.tif b/tests/auto/qimagereader/images/grayscale.tif Binary files differnew file mode 100644 index 0000000..5f4e114 --- /dev/null +++ b/tests/auto/qimagereader/images/grayscale.tif diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 05b506c..15b1c1c 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -157,6 +157,8 @@ private slots: void tiffOrientation_data(); void tiffOrientation(); + + void tiffGrayscale(); #endif void autoDetectImageFormat(); @@ -1376,6 +1378,13 @@ void tst_QImageReader::tiffOrientation() QCOMPARE(expectedImage, orientedImage); } +void tst_QImageReader::tiffGrayscale() +{ + QImage actualImage(prefix + "grayscale.tif"); + QImage expectedImage(prefix + "grayscale-ref.tif"); + + QCOMPARE(expectedImage, actualImage.convertToFormat(expectedImage.format())); +} #endif void tst_QImageReader::dotsPerMeter_data() diff --git a/tests/auto/qimagewriter/tst_qimagewriter.cpp b/tests/auto/qimagewriter/tst_qimagewriter.cpp index 584a060..5ec287d3 100644 --- a/tests/auto/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/qimagewriter/tst_qimagewriter.cpp @@ -391,16 +391,27 @@ void tst_QImageWriter::readWriteNonDestructive_data() { QTest::addColumn<QImage::Format>("format"); QTest::addColumn<QImage::Format>("expectedFormat"); - QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono; - QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8; - QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32; + QTest::addColumn<bool>("grayscale"); + QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << false; + QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << false; + QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32 << false; + QTest::newRow("tiff grayscale") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << true; } void tst_QImageWriter::readWriteNonDestructive() { QFETCH(QImage::Format, format); QFETCH(QImage::Format, expectedFormat); + QFETCH(bool, grayscale); QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format); + + if (grayscale) { + QVector<QRgb> colors; + for (int i = 0; i < 256; ++i) + colors << qRgb(i, i, i); + image.setColorTable(colors); + } + QVERIFY(image.save(prefix + "gen-readWriteNonDestructive.tiff")); QImage image2 = QImage(prefix + "gen-readWriteNonDestructive.tiff"); |