diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2023-10-24 02:44:08 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2024-04-08 08:36:43 +0200 |
commit | 3cf129582ba6bee6fc00784e57e99c95d594786d (patch) | |
tree | 175edd0fdbb86129f73fff2bc6aa4224f3d8c1fa | |
parent | 266f87720f9622ca75acacaa8e19987517df741e (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.cpp | 31 |
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) |