Improve CMYK writing support

Closes #11 

Requires MR !279

On formats that does not support CMYK and does not use the ScanLineConverter class during write operation, the CMYK images must be converted using the color space conversion functions of `QImage` (if ICC profile is valid).
This commit is contained in:
Mirco Miranda 2024-11-28 06:57:01 +00:00
parent b5d8b6638e
commit 374961dab4
18 changed files with 3328 additions and 7 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -686,7 +686,18 @@ bool QAVIFHandler::write(const QImage &image)
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
QImage tmpcolorimage;
auto cs = image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
tmpcolorimage = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), tmpformat);
}
else {
tmpcolorimage = image.convertToFormat(tmpformat);
}
#else
QImage tmpcolorimage = image.convertToFormat(tmpformat);
#endif
avifPixelFormat pixel_format = AVIF_PIXEL_FORMAT_YUV420;
if (m_quality >= KIMG_AVIF_QUALITY_HIGH) {

View File

@ -159,7 +159,18 @@ bool HEIFHandler::write_helper(const QImage &image)
}
}
const QImage tmpimage = image.convertToFormat(tmpformat);
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
QImage tmpimage;
auto cs = image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
tmpimage = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), tmpformat);
}
else {
tmpimage = image.convertToFormat(tmpformat);
}
#else
QImage tmpimage = image.convertToFormat(tmpformat);
#endif
struct heif_context *context = heif_context_alloc();
struct heif_error err;

View File

@ -584,6 +584,9 @@ bool QJpegXLHandler::write(const QImage &image)
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
case QImage::Format_CMYK8888:
#endif
save_depth = 8;
break;
case QImage::Format_Grayscale16:
@ -757,7 +760,20 @@ bool QJpegXLHandler::write(const QImage &image)
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
// TODO: add native CMYK support (libjxl supports CMYK images)
QImage tmpimage;
auto cs = image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
tmpimage = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), tmpformat);
}
else {
tmpimage = image.convertToFormat(tmpformat);
}
#else
QImage tmpimage = image.convertToFormat(tmpformat);
#endif
const size_t xsize = tmpimage.width();
const size_t ysize = tmpimage.height();

View File

@ -9,6 +9,7 @@
#include "util_p.h"
#include <QColor>
#include <QColorSpace>
#include <QDataStream>
#include <QDebug>
#include <QImage>
@ -877,6 +878,12 @@ bool PCXHandler::write(const QImage &image)
s.setByteOrder(QDataStream::LittleEndian);
QImage img = image;
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
auto cs = image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb));
}
#endif
const int w = img.width();
const int h = img.height();

View File

@ -17,10 +17,12 @@
#include "rle_p.h"
#include "util_p.h"
#include <QColorSpace>
#include <QDataStream>
#include <QDebug>
#include <QImage>
#include <QVariant>
#include <algorithm>
#include <functional>
#include <qendian.h>
@ -264,7 +266,16 @@ bool SoftimagePICHandler::read(QImage *image)
bool SoftimagePICHandler::write(const QImage &_image)
{
bool alpha = _image.hasAlphaChannel();
const QImage image = _image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
QImage image;
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
auto cs = _image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && _image.format() == QImage::Format_CMYK8888) {
image = _image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32);
}
#endif
if (image.isNull()) {
image = _image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
}
if (image.width() < 0 || image.height() < 0) {
qDebug() << "Image size invalid:" << image.width() << image.height();
@ -289,7 +300,7 @@ bool SoftimagePICHandler::write(const QImage &_image)
stream << channels;
for (int r = 0; r < image.height(); r++) {
const QRgb *row = reinterpret_cast<const QRgb *>(image.scanLine(r));
const QRgb *row = reinterpret_cast<const QRgb *>(image.constScanLine(r));
/* Write the RGB part of the scanline */
auto rgbEqual = [](QRgb p1, QRgb p2) -> bool {

View File

@ -24,11 +24,11 @@
#include <cstring>
#include <QList>
#include <QMap>
#include <QColorSpace>
#include <QDebug>
#include <QImage>
#include <QList>
#include <QMap>
class RLEData : public QList<uchar>
{
@ -750,7 +750,14 @@ bool SGIImagePrivate::writeImage(const QImage &image)
_dim = 3, _zsize++;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
auto cs = image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32);
} else if (hasAlpha && img.format() != QImage::Format_ARGB32) {
#else
if (hasAlpha && img.format() != QImage::Format_ARGB32) {
#endif
img = img.convertToFormat(QImage::Format_ARGB32);
} else if (!hasAlpha && img.format() != QImage::Format_RGB32) {
img = img.convertToFormat(QImage::Format_RGB32);

View File

@ -21,6 +21,7 @@
#include <assert.h>
#include <QColorSpace>
#include <QDataStream>
#include <QDebug>
#include <QImage>
@ -474,7 +475,14 @@ bool TGAHandler::write(const QImage &image)
QImage img(image);
const bool hasAlpha = img.hasAlphaChannel();
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
auto cs = image.colorSpace();
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32);
} else if (hasAlpha && img.format() != QImage::Format_ARGB32) {
#else
if (hasAlpha && img.format() != QImage::Format_ARGB32) {
#endif
img = img.convertToFormat(QImage::Format_ARGB32);
} else if (!hasAlpha && img.format() != QImage::Format_RGB32) {
img = img.convertToFormat(QImage::Format_RGB32);
@ -497,7 +505,7 @@ bool TGAHandler::write(const QImage &image)
s << quint8(hasAlpha ? originTopLeft + alphaChannel8Bits : originTopLeft); // top left image (0x20) + 8 bit alpha (0x8)
for (int y = 0; y < img.height(); y++) {
auto ptr = reinterpret_cast<QRgb *>(img.scanLine(y));
auto ptr = reinterpret_cast<const QRgb *>(img.constScanLine(y));
for (int x = 0; x < img.width(); x++) {
auto color = *(ptr + x);
s << quint8(qBlue(color));