summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2023-10-24 02:44:08 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2024-04-08 08:36:43 +0200
commit3cf129582ba6bee6fc00784e57e99c95d594786d (patch)
tree175edd0fdbb86129f73fff2bc6aa4224f3d8c1fa
parent266f87720f9622ca75acacaa8e19987517df741e (diff)
TIFF: add support for CMYK image load/save
This work has been kindly sponsored by the QGIS project (https://qgis.org/). [ChangeLog][TIFF] Added support for loading and saving of 8-bit CMYK TIFF files. Change-Id: I380ef56023fea17f6155ee50fd09421891fbf192 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/plugins/imageformats/tiff/qtiffhandler.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp
index 0c6936c..549b142 100644
--- a/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -310,6 +310,15 @@ bool QTiffHandlerPrivate::readHeaders(QIODevice *device)
format = QImage::Format_RGBA32FPx4_Premultiplied;
else
format = QImage::Format_RGBA32FPx4;
+ } else if (samplesPerPixel == 4 && bitPerSample == 8 && photometric == PHOTOMETRIC_SEPARATED) {
+ uint16_t inkSet;
+ const bool gotInkSetField = TIFFGetField(tiff, TIFFTAG_INKSET, &inkSet);
+ if (!gotInkSetField || inkSet == INKSET_CMYK) {
+ format = QImage::Format_CMYK8888;
+ } else {
+ close();
+ return false;
+ }
} else {
if (premultiplied)
format = QImage::Format_ARGB32_Premultiplied;
@@ -411,12 +420,13 @@ bool QTiffHandler::read(QImage *image)
}
bool format8bit = (format == QImage::Format_Mono || format == QImage::Format_Indexed8 || format == QImage::Format_Grayscale8);
bool format16bit = (format == QImage::Format_Grayscale16);
+ bool formatCmyk32bit = (format == QImage::Format_CMYK8888);
bool format64bit = (format == QImage::Format_RGBX64 || format == QImage::Format_RGBA64 || format == QImage::Format_RGBA64_Premultiplied);
bool format64fp = (format == QImage::Format_RGBX16FPx4 || format == QImage::Format_RGBA16FPx4 || format == QImage::Format_RGBA16FPx4_Premultiplied);
bool format128fp = (format == QImage::Format_RGBX32FPx4 || format == QImage::Format_RGBA32FPx4 || format == QImage::Format_RGBA32FPx4_Premultiplied);
// Formats we read directly, instead of over RGBA32:
- if (format8bit || format16bit || format64bit || format64fp || format128fp) {
+ if (format8bit || format16bit || formatCmyk32bit || format64bit || format64fp || format128fp) {
int bytesPerPixel = image->depth() / 8;
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBX16FPx4)
bytesPerPixel = d->photometric == PHOTOMETRIC_RGB ? 6 : 2;
@@ -826,6 +836,25 @@ bool QTiffHandler::write(const QImage &image)
}
}
TIFFClose(tiff);
+ } else if (format == QImage::Format_CMYK8888) {
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
+ || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
+ || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)
+ || !TIFFSetField(tiff, TIFFTAG_INKSET, INKSET_CMYK)
+ || !TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, defaultStripSize(tiff))) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ for (int y = 0; y < image.height(); ++y) {
+ if (TIFFWriteScanline(tiff, (void*)image.scanLine(y), y) != 1) {
+ TIFFClose(tiff);
+ return false;
+ }
+ }
+
+ TIFFClose(tiff);
} else if (!image.hasAlphaChannel()) {
if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
|| !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)