Handle Grayscale8 TIFFs
Correctly read and write Grayscale8 image format. Change-Id: I537c68f94077458c69ee1de08b5b37986b54aa26 Reviewed-by: Ivan Komissarov <ABBAPOH@gmail.com> Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
This commit is contained in:
parent
40e9ba00a0
commit
454fb13c46
|
@ -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<QRgb> &colorTable)
|
|||
return true;
|
||||
}
|
||||
|
||||
static QVector<QRgb> effectiveColorTable(const QImage &image)
|
||||
{
|
||||
QVector<QRgb> 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<QRgb> colorTable = image.colorTable();
|
||||
} else if (format == QImage::Format_Indexed8
|
||||
|| format == QImage::Format_Grayscale8
|
||||
|| format == QImage::Format_Alpha8) {
|
||||
QVector<QRgb> 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)
|
||||
|
|
|
@ -364,31 +364,23 @@ void tst_qtiff::readWriteNonDestructive_data()
|
|||
{
|
||||
QTest::addColumn<QImage::Format>("format");
|
||||
QTest::addColumn<QImage::Format>("expectedFormat");
|
||||
QTest::addColumn<bool>("grayscale");
|
||||
QTest::addColumn<QImageIOHandler::Transformation>("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<QRgb> 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));
|
||||
|
|
Loading…
Reference in New Issue