Add support for reading monochromatic floating point formats

It seems the builtin converting reader doesn't support all formats.

Change-Id: Ia24b4d017476e2dd806861c3e98f3df19dce4584
Fixes: QTBUG-112947
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2023-05-04 11:11:10 +02:00
parent 46fa217d01
commit 2bf281891b
2 changed files with 52 additions and 8 deletions

View File

@ -277,9 +277,9 @@ bool QTiffHandlerPrivate::readHeaders(QIODevice *device)
else if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1)
format = QImage::Format_Indexed8;
else if (samplesPerPixel < 4)
if (bitPerSample == 16 && photometric == PHOTOMETRIC_RGB)
if (bitPerSample == 16 && (photometric == PHOTOMETRIC_RGB || photometric == PHOTOMETRIC_MINISBLACK))
format = floatingPoint ? QImage::Format_RGBX16FPx4 : QImage::Format_RGBX64;
else if (bitPerSample == 32 && floatingPoint && photometric == PHOTOMETRIC_RGB)
else if (bitPerSample == 32 && floatingPoint && (photometric == PHOTOMETRIC_RGB || photometric == PHOTOMETRIC_MINISBLACK))
format = QImage::Format_RGBX32FPx4;
else
format = QImage::Format_RGB32;
@ -419,9 +419,9 @@ bool QTiffHandler::read(QImage *image)
if (format8bit || format16bit || format64bit || format64fp || format128fp) {
int bytesPerPixel = image->depth() / 8;
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4)
bytesPerPixel = 6;
bytesPerPixel = d->photometric == PHOTOMETRIC_RGB ? 6 : 2;
else if (format == QImage::Format_RGBX32FPx4)
bytesPerPixel = 12;
bytesPerPixel = d->photometric == PHOTOMETRIC_RGB ? 12 : 4;
if (TIFFIsTiled(tiff)) {
quint32 tileWidth, tileLength;
TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth);
@ -470,10 +470,17 @@ bool QTiffHandler::read(QImage *image)
}
}
}
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4)
rgb48fixup(image, d->floatingPoint);
else if (format == QImage::Format_RGBX32FPx4)
rgb96fixup(image);
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4) {
if (d->photometric == PHOTOMETRIC_RGB)
rgb48fixup(image, d->floatingPoint);
else
rgbFixup(image);
} else if (format == QImage::Format_RGBX32FPx4) {
if (d->photometric == PHOTOMETRIC_RGB)
rgb96fixup(image);
else
rgbFixup(image);
}
} else {
const int stopOnError = 1;
if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32_t *>(image->bits()), qt2Exif(d->transformation), stopOnError)) {
@ -1016,6 +1023,42 @@ void QTiffHandler::rgb96fixup(QImage *image)
}
}
void QTiffHandler::rgbFixup(QImage *image)
{
Q_ASSERT(d->floatingPoint);
if (image->depth() == 64) {
const int h = image->height();
const int w = image->width();
uchar *scanline = image->bits();
const qsizetype bpl = image->bytesPerLine();
for (int y = 0; y < h; ++y) {
qfloat16 *dst = reinterpret_cast<qfloat16 *>(scanline);
for (int x = w - 1; x >= 0; --x) {
dst[x * 4 + 3] = qfloat16(1.0f);
dst[x * 4 + 2] = dst[x];
dst[x * 4 + 1] = dst[x];
dst[x * 4 + 0] = dst[x];
}
scanline += bpl;
}
} else {
const int h = image->height();
const int w = image->width();
uchar *scanline = image->bits();
const qsizetype bpl = image->bytesPerLine();
for (int y = 0; y < h; ++y) {
float *dst = reinterpret_cast<float *>(scanline);
for (int x = w - 1; x >= 0; --x) {
dst[x * 4 + 3] = 1.0f;
dst[x * 4 + 2] = dst[x];
dst[x * 4 + 1] = dst[x];
dst[x * 4 + 0] = dst[x];
}
scanline += bpl;
}
}
}
bool QTiffHandler::ensureHaveDirectoryCount() const
{
if (d->directoryCount > 0)

View File

@ -38,6 +38,7 @@ private:
void convert32BitOrder(void *buffer, int width);
void rgb48fixup(QImage *image, bool floatingPoint);
void rgb96fixup(QImage *image);
void rgbFixup(QImage *image);
const QScopedPointer<QTiffHandlerPrivate> d;
bool ensureHaveDirectoryCount() const;
};