From c7a6a451a5c277556e28dfb3b4b943719cdda7ff Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 16 Mar 2017 14:13:57 +0100 Subject: Extend support for tiled tiff files to all color formats This commit extends the recently added support for tiled tiff images of color index format to also cover grayscale and mono images. RGB images were already covered, since the libtiff API used for those handles tiled images transparently. This commit also simplifies the tiff read() function by sharing common code among the different formats. [ChangeLog][TIFF] Extend support for tiled tiff files to all color formats Change-Id: I13f94bbca65dd6a35384a415906034e245ad8b79 Reviewed-by: Allan Sandfeld Jensen --- src/plugins/imageformats/tiff/qtiffhandler.cpp | 169 +++++++++------------ tests/auto/tiff/tst_qtiff.cpp | 19 ++- tests/shared/images/tiff.qrc | 11 +- tests/shared/images/tiff/indexed_nontiled.tif | Bin 119486 -> 0 bytes tests/shared/images/tiff/indexed_tiled.tif | Bin 209220 -> 0 bytes tests/shared/images/tiff/oddsize_grayscale.tiff | Bin 0 -> 4553 bytes tests/shared/images/tiff/oddsize_mono.tiff | Bin 0 -> 886 bytes tests/shared/images/tiff/original_grayscale.tiff | Bin 0 -> 4432 bytes tests/shared/images/tiff/tiled_grayscale.tiff | Bin 0 -> 4584 bytes tests/shared/images/tiff/tiled_indexed.tiff | Bin 0 -> 6061 bytes tests/shared/images/tiff/tiled_mono.tiff | Bin 0 -> 926 bytes .../images/tiff/tiled_oddsize_grayscale.tiff | Bin 0 -> 5639 bytes tests/shared/images/tiff/tiled_oddsize_mono.tiff | Bin 0 -> 1114 bytes tests/shared/images/tiff/tiled_rgb.tiff | Bin 0 -> 12748 bytes 14 files changed, 100 insertions(+), 99 deletions(-) delete mode 100644 tests/shared/images/tiff/indexed_nontiled.tif delete mode 100644 tests/shared/images/tiff/indexed_tiled.tif create mode 100644 tests/shared/images/tiff/oddsize_grayscale.tiff create mode 100644 tests/shared/images/tiff/oddsize_mono.tiff create mode 100644 tests/shared/images/tiff/original_grayscale.tiff create mode 100644 tests/shared/images/tiff/tiled_grayscale.tiff create mode 100644 tests/shared/images/tiff/tiled_indexed.tiff create mode 100644 tests/shared/images/tiff/tiled_mono.tiff create mode 100644 tests/shared/images/tiff/tiled_oddsize_grayscale.tiff create mode 100644 tests/shared/images/tiff/tiled_oddsize_mono.tiff create mode 100644 tests/shared/images/tiff/tiled_rgb.tiff diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index e34ea25..81ad7e9 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -329,125 +329,106 @@ bool QTiffHandler::read(QImage *image) if (image->size() != d->size || image->format() != format) *image = QImage(d->size, format); + if (image->isNull()) { + d->close(); + return false; + } + TIFF *const tiff = d->tiff; const uint32 width = d->size.width(); const uint32 height = d->size.height(); - if (format == QImage::Format_Mono) { - QVector colortable(2); - if (d->photometric == PHOTOMETRIC_MINISBLACK) { - colortable[0] = 0xff000000; - colortable[1] = 0xffffffff; - } else { - colortable[0] = 0xffffffff; - colortable[1] = 0xff000000; - } - image->setColorTable(colortable); - - if (!image->isNull()) { - for (uint32 y=0; yscanLine(y), y, 0) < 0) { + if (format == QImage::Format_Mono || format == QImage::Format_Indexed8 || format == QImage::Format_Grayscale8) { + if (format == QImage::Format_Mono) { + QVector colortable(2); + if (d->photometric == PHOTOMETRIC_MINISBLACK) { + colortable[0] = 0xff000000; + colortable[1] = 0xffffffff; + } else { + colortable[0] = 0xffffffff; + colortable[1] = 0xff000000; + } + image->setColorTable(colortable); + } else if (format == QImage::Format_Indexed8) { + const uint16 tableSize = 256; + QVector qtColorTable(tableSize); + if (d->grayscale) { + for (int i = 0; iphotometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i); + qtColorTable[i] = qRgb(c, c, c); + } + } else { + // create the color table + uint16 *redTable = 0; + uint16 *greenTable = 0; + uint16 *blueTable = 0; + if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { d->close(); return false; } - } - } - } else { - if (format == QImage::Format_Indexed8) { - if (!image->isNull()) { - const uint16 tableSize = 256; - QVector qtColorTable(tableSize); - if (d->grayscale) { - for (int i = 0; iphotometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i); - qtColorTable[i] = qRgb(c, c, c); - } - } else { - // create the color table - uint16 *redTable = 0; - uint16 *greenTable = 0; - uint16 *blueTable = 0; - if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { - d->close(); - return false; - } - if (!redTable || !greenTable || !blueTable) { - d->close(); - return false; - } - - for (int i = 0; iclose(); + return false; } - image->setColorTable(qtColorTable); - - if (TIFFIsTiled(tiff)) { - quint32 tileWidth, tileLength; - TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth); - TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength); - uchar *buf = (uchar *)_TIFFmalloc(TIFFTileSize(tiff)); - if (!tileWidth || !tileLength || !buf) { - _TIFFfree(buf); - d->close(); - return false; - } - for (quint32 y = 0; y < height; y += tileLength) { - for (quint32 x = 0; x < width; x += tileWidth) { - if (TIFFReadTile(tiff, buf, x, y, 0, 0) < 0) { - _TIFFfree(buf); - d->close(); - return false; - } - quint32 linesToCopy = qMin(tileLength, height - y); - quint32 widthToCopy = qMin(tileWidth, width - x); - for (quint32 i = 0; i < linesToCopy; i++) - ::memcpy(image->scanLine(y + i) + x, buf + (i * tileWidth), widthToCopy); - } - } - _TIFFfree(buf); - } else { - for (uint32 y=0; yscanLine(y), y, 0) < 0) { - d->close(); - return false; - } - } + for (int i = 0; isetColorTable(qtColorTable); + // free redTable, greenTable and greenTable done by libtiff + } - // free redTable, greenTable and greenTable done by libtiff + if (TIFFIsTiled(tiff)) { + quint32 tileWidth, tileLength; + TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth); + TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength); + uchar *buf = (uchar *)_TIFFmalloc(TIFFTileSize(tiff)); + if (!tileWidth || !tileLength || !buf) { + _TIFFfree(buf); + d->close(); + return false; } - } 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) { + quint32 byteWidth = (format == QImage::Format_Mono) ? (width + 7)/8 : width; + quint32 byteTileWidth = (format == QImage::Format_Mono) ? tileWidth/8 : tileWidth; + for (quint32 y = 0; y < height; y += tileLength) { + for (quint32 x = 0; x < width; x += tileWidth) { + if (TIFFReadTile(tiff, buf, x, y, 0, 0) < 0) { + _TIFFfree(buf); d->close(); return false; } + quint32 linesToCopy = qMin(tileLength, height - y); + quint32 byteOffset = (format == QImage::Format_Mono) ? x/8 : x; + quint32 widthToCopy = qMin(byteTileWidth, byteWidth - byteOffset); + for (quint32 i = 0; i < linesToCopy; i++) { + ::memcpy(image->scanLine(y + i) + byteOffset, buf + (i * byteTileWidth), widthToCopy); + } } } + _TIFFfree(buf); } else { - if (!image->isNull()) { - const int stopOnError = 1; - if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), qt2Exif(d->transformation), stopOnError)) { - for (uint32 y=0; yscanLine(y), width); - } else { + for (uint32 y=0; yscanLine(y), y, 0) < 0) { d->close(); return false; } } } + } else { + const int stopOnError = 1; + if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), qt2Exif(d->transformation), stopOnError)) { + for (uint32 y=0; yscanLine(y), width); + } else { + d->close(); + return false; + } } - if (image->isNull()) { - d->close(); - return false; - } float resX = 0; float resY = 0; diff --git a/tests/auto/tiff/tst_qtiff.cpp b/tests/auto/tiff/tst_qtiff.cpp index bec2ca2..1a96ab3 100644 --- a/tests/auto/tiff/tst_qtiff.cpp +++ b/tests/auto/tiff/tst_qtiff.cpp @@ -139,6 +139,7 @@ void tst_qtiff::readImage_data() QTest::newRow("mono_orientation_7") << QString("mono_orientation_7.tiff") << QSize(64, 64); QTest::newRow("mono_orientation_8") << QString("mono_orientation_8.tiff") << QSize(64, 64); QTest::newRow("original_indexed") << QString("original_indexed.tiff") << QSize(64, 64); + QTest::newRow("original_grayscale") << QString("original_grayscale.tiff") << QSize(64, 64); QTest::newRow("original_mono") << QString("original_mono.tiff") << QSize(64, 64); QTest::newRow("original_rgb") << QString("original_rgb.tiff") << QSize(64, 64); QTest::newRow("rgba_adobedeflate_littleendian") << QString("rgba_adobedeflate_littleendian.tif") << QSize(200, 200); @@ -156,8 +157,14 @@ void tst_qtiff::readImage_data() QTest::newRow("rgb_orientation_7") << QString("rgb_orientation_7.tiff") << QSize(64, 64); QTest::newRow("rgb_orientation_8") << QString("rgb_orientation_8.tiff") << QSize(64, 64); QTest::newRow("teapot") << QString("teapot.tiff") << QSize(256, 256); - QTest::newRow("indexed_nontiled") << QString("indexed_nontiled.tif") << QSize(512, 384); - QTest::newRow("indexed_tiled") << QString("indexed_tiled.tif") << QSize(512, 384); + QTest::newRow("oddsize_grayscale") << QString("oddsize_grayscale.tiff") << QSize(59, 71); + QTest::newRow("oddsize_mono") << QString("oddsize_mono.tiff") << QSize(59, 71); + QTest::newRow("tiled_rgb") << QString("tiled_rgb.tiff") << QSize(64, 64); + QTest::newRow("tiled_indexed") << QString("tiled_indexed.tiff") << QSize(64, 64); + QTest::newRow("tiled_grayscale") << QString("tiled_grayscale.tiff") << QSize(64, 64); + QTest::newRow("tiled_mono") << QString("tiled_mono.tiff") << QSize(64, 64); + QTest::newRow("tiled_oddsize_grayscale") << QString("tiled_oddsize_grayscale.tiff") << QSize(59, 71); + QTest::newRow("tiled_oddsize_mono") << QString("tiled_oddsize_mono.tiff") << QSize(59, 71); } void tst_qtiff::readImage() @@ -566,7 +573,12 @@ void tst_qtiff::tiled_data() { QTest::addColumn("expectedFile"); QTest::addColumn("tiledFile"); - QTest::newRow("Indexed") << "indexed_nontiled.tif" << "indexed_tiled.tif"; + QTest::newRow("RGB") << "original_rgb.tiff" << "tiled_rgb.tiff"; + QTest::newRow("Indexed") << "original_indexed.tiff" << "tiled_indexed.tiff"; + QTest::newRow("Grayscale") << "original_grayscale.tiff" << "tiled_grayscale.tiff"; + QTest::newRow("Mono") << "original_mono.tiff" << "tiled_mono.tiff"; + QTest::newRow("Oddsize (Grayscale)") << "oddsize_grayscale.tiff" << "tiled_oddsize_grayscale.tiff"; + QTest::newRow("Oddsize (Mono)") << "oddsize_mono.tiff" << "tiled_oddsize_mono.tiff"; } void tst_qtiff::tiled() @@ -576,6 +588,7 @@ void tst_qtiff::tiled() QImage expectedImage(prefix + expectedFile); QImage tiledImage(prefix + tiledFile); + QVERIFY(!tiledImage.isNull()); QCOMPARE(expectedImage, tiledImage); } diff --git a/tests/shared/images/tiff.qrc b/tests/shared/images/tiff.qrc index 258acf0..19675ba 100644 --- a/tests/shared/images/tiff.qrc +++ b/tests/shared/images/tiff.qrc @@ -41,7 +41,14 @@ tiff/rgb_orientation_8.tiff tiff/teapot.tiff tiff/colorful.bmp - tiff/indexed_tiled.tif - tiff/indexed_nontiled.tif + tiff/tiled_grayscale.tiff + tiff/tiled_oddsize_grayscale.tiff + tiff/oddsize_grayscale.tiff + tiff/original_grayscale.tiff + tiff/tiled_indexed.tiff + tiff/tiled_mono.tiff + tiff/tiled_oddsize_mono.tiff + tiff/oddsize_mono.tiff + tiff/tiled_rgb.tiff diff --git a/tests/shared/images/tiff/indexed_nontiled.tif b/tests/shared/images/tiff/indexed_nontiled.tif deleted file mode 100644 index d0b7cef..0000000 Binary files a/tests/shared/images/tiff/indexed_nontiled.tif and /dev/null differ diff --git a/tests/shared/images/tiff/indexed_tiled.tif b/tests/shared/images/tiff/indexed_tiled.tif deleted file mode 100644 index 4ed11dd..0000000 Binary files a/tests/shared/images/tiff/indexed_tiled.tif and /dev/null differ diff --git a/tests/shared/images/tiff/oddsize_grayscale.tiff b/tests/shared/images/tiff/oddsize_grayscale.tiff new file mode 100644 index 0000000..d519cd2 Binary files /dev/null and b/tests/shared/images/tiff/oddsize_grayscale.tiff differ diff --git a/tests/shared/images/tiff/oddsize_mono.tiff b/tests/shared/images/tiff/oddsize_mono.tiff new file mode 100644 index 0000000..fbac0ed Binary files /dev/null and b/tests/shared/images/tiff/oddsize_mono.tiff differ diff --git a/tests/shared/images/tiff/original_grayscale.tiff b/tests/shared/images/tiff/original_grayscale.tiff new file mode 100644 index 0000000..174c2cf Binary files /dev/null and b/tests/shared/images/tiff/original_grayscale.tiff differ diff --git a/tests/shared/images/tiff/tiled_grayscale.tiff b/tests/shared/images/tiff/tiled_grayscale.tiff new file mode 100644 index 0000000..894ba8b Binary files /dev/null and b/tests/shared/images/tiff/tiled_grayscale.tiff differ diff --git a/tests/shared/images/tiff/tiled_indexed.tiff b/tests/shared/images/tiff/tiled_indexed.tiff new file mode 100644 index 0000000..2bd266a Binary files /dev/null and b/tests/shared/images/tiff/tiled_indexed.tiff differ diff --git a/tests/shared/images/tiff/tiled_mono.tiff b/tests/shared/images/tiff/tiled_mono.tiff new file mode 100644 index 0000000..cbcda19 Binary files /dev/null and b/tests/shared/images/tiff/tiled_mono.tiff differ diff --git a/tests/shared/images/tiff/tiled_oddsize_grayscale.tiff b/tests/shared/images/tiff/tiled_oddsize_grayscale.tiff new file mode 100644 index 0000000..27bc9d4 Binary files /dev/null and b/tests/shared/images/tiff/tiled_oddsize_grayscale.tiff differ diff --git a/tests/shared/images/tiff/tiled_oddsize_mono.tiff b/tests/shared/images/tiff/tiled_oddsize_mono.tiff new file mode 100644 index 0000000..e858e90 Binary files /dev/null and b/tests/shared/images/tiff/tiled_oddsize_mono.tiff differ diff --git a/tests/shared/images/tiff/tiled_rgb.tiff b/tests/shared/images/tiff/tiled_rgb.tiff new file mode 100644 index 0000000..90291b9 Binary files /dev/null and b/tests/shared/images/tiff/tiled_rgb.tiff differ -- cgit v1.2.1