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)
|
if (grayscale && bitPerSample == 1 && samplesPerPixel == 1)
|
||||||
format = QImage::Format_Mono;
|
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)
|
else if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1)
|
||||||
format = QImage::Format_Indexed8;
|
format = QImage::Format_Indexed8;
|
||||||
else if (samplesPerPixel < 4)
|
else if (samplesPerPixel < 4)
|
||||||
|
@ -366,6 +368,15 @@ bool QTiffHandler::read(QImage *image)
|
||||||
|
|
||||||
// free redTable, greenTable and greenTable done by libtiff
|
// 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 {
|
} else {
|
||||||
if (!image->isNull()) {
|
if (!image->isNull()) {
|
||||||
const int stopOnError = 1;
|
const int stopOnError = 1;
|
||||||
|
@ -428,6 +439,29 @@ static bool checkGrayscale(const QVector<QRgb> &colorTable)
|
||||||
return true;
|
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)
|
bool QTiffHandler::write(const QImage &image)
|
||||||
{
|
{
|
||||||
if (!device()->isWritable())
|
if (!device()->isWritable())
|
||||||
|
@ -515,12 +549,14 @@ bool QTiffHandler::write(const QImage &image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TIFFClose(tiff);
|
TIFFClose(tiff);
|
||||||
} else if (format == QImage::Format_Indexed8) {
|
} else if (format == QImage::Format_Indexed8
|
||||||
const QVector<QRgb> colorTable = image.colorTable();
|
|| format == QImage::Format_Grayscale8
|
||||||
|
|| format == QImage::Format_Alpha8) {
|
||||||
|
QVector<QRgb> colorTable = effectiveColorTable(image);
|
||||||
bool isGrayscale = checkGrayscale(colorTable);
|
bool isGrayscale = checkGrayscale(colorTable);
|
||||||
if (isGrayscale) {
|
if (isGrayscale) {
|
||||||
uint16 photometric = PHOTOMETRIC_MINISBLACK;
|
uint16 photometric = PHOTOMETRIC_MINISBLACK;
|
||||||
if (image.colorTable().at(0) == 0xffffffff)
|
if (colorTable.at(0) == 0xffffffff)
|
||||||
photometric = PHOTOMETRIC_MINISWHITE;
|
photometric = PHOTOMETRIC_MINISWHITE;
|
||||||
if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
|
if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
|
||||||
|| !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
|
|| !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
|
||||||
|
@ -579,7 +615,6 @@ bool QTiffHandler::write(const QImage &image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TIFFClose(tiff);
|
TIFFClose(tiff);
|
||||||
|
|
||||||
} else if (!image.hasAlphaChannel()) {
|
} else if (!image.hasAlphaChannel()) {
|
||||||
if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
|
if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
|
||||||
|| !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
|
|| !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>("format");
|
||||||
QTest::addColumn<QImage::Format>("expectedFormat");
|
QTest::addColumn<QImage::Format>("expectedFormat");
|
||||||
QTest::addColumn<bool>("grayscale");
|
|
||||||
QTest::addColumn<QImageIOHandler::Transformation>("transformation");
|
QTest::addColumn<QImageIOHandler::Transformation>("transformation");
|
||||||
QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << false << QImageIOHandler::TransformationNone;
|
QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << QImageIOHandler::TransformationNone;
|
||||||
QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << false << QImageIOHandler::TransformationMirror;
|
QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << QImageIOHandler::TransformationMirror;
|
||||||
QTest::newRow("tiff argb32pm") << QImage::Format_ARGB32_Premultiplied << QImage::Format_ARGB32_Premultiplied << false << QImageIOHandler::TransformationRotate90;
|
QTest::newRow("tiff argb32pm") << QImage::Format_ARGB32_Premultiplied << QImage::Format_ARGB32_Premultiplied << QImageIOHandler::TransformationRotate90;
|
||||||
QTest::newRow("tiff rgb32") << QImage::Format_RGB32 << QImage::Format_RGB32 << false << QImageIOHandler::TransformationRotate270;
|
QTest::newRow("tiff rgb32") << QImage::Format_RGB32 << QImage::Format_RGB32 << QImageIOHandler::TransformationRotate270;
|
||||||
QTest::newRow("tiff grayscale") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << true << QImageIOHandler::TransformationFlip;
|
QTest::newRow("tiff grayscale") << QImage::Format_Grayscale8 << QImage::Format_Grayscale8 << QImageIOHandler::TransformationFlip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_qtiff::readWriteNonDestructive()
|
void tst_qtiff::readWriteNonDestructive()
|
||||||
{
|
{
|
||||||
QFETCH(QImage::Format, format);
|
QFETCH(QImage::Format, format);
|
||||||
QFETCH(QImage::Format, expectedFormat);
|
QFETCH(QImage::Format, expectedFormat);
|
||||||
QFETCH(bool, grayscale);
|
|
||||||
QFETCH(QImageIOHandler::Transformation, transformation);
|
QFETCH(QImageIOHandler::Transformation, transformation);
|
||||||
|
|
||||||
QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format);
|
QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format);
|
||||||
QVERIFY(!image.isNull());
|
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;
|
QByteArray output;
|
||||||
QBuffer buf(&output);
|
QBuffer buf(&output);
|
||||||
QVERIFY(buf.open(QIODevice::WriteOnly));
|
QVERIFY(buf.open(QIODevice::WriteOnly));
|
||||||
|
|
Loading…
Reference in New Issue