mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-06-03 17:08:08 -04:00
EXR: Full support for gray image/colorspace
Starting with Qt 6.8, QColorSpace supports Gray and CMYK color profiles. - On saving, grayscale images are converted to linear gray profile; - On loading, a Grayscale image is stored in a QImage::Format_Grayscale16 instead a RGB one; - ScanlineConverter class was updated to gray conversions.
This commit is contained in:
parent
63e21ee5f3
commit
81b7263d73
@ -99,6 +99,11 @@
|
|||||||
#define EXR_USE_QT6_FLOAT_IMAGE // default uncommented
|
#define EXR_USE_QT6_FLOAT_IMAGE // default uncommented
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Qt 6.8 allow to create and use Gray profile, so we can load a Gray image as Grayscale format instead RGB one.
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
|
#define EXR_GRAY_SUPPORT_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
class K_IStream : public Imf::IStream
|
class K_IStream : public Imf::IStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -248,10 +253,15 @@ bool EXRHandler::canRead() const
|
|||||||
static QImage::Format imageFormat(const Imf::RgbaInputFile &file)
|
static QImage::Format imageFormat(const Imf::RgbaInputFile &file)
|
||||||
{
|
{
|
||||||
auto isRgba = file.channels() & Imf::RgbaChannels::WRITE_A;
|
auto isRgba = file.channels() & Imf::RgbaChannels::WRITE_A;
|
||||||
|
#ifdef EXR_GRAY_SUPPORT_ENABLED
|
||||||
|
auto isGray = file.channels() & Imf::RgbaChannels::WRITE_Y;
|
||||||
|
#else
|
||||||
|
auto isGray = false;
|
||||||
|
#endif
|
||||||
#if defined(EXR_USE_LEGACY_CONVERSIONS)
|
#if defined(EXR_USE_LEGACY_CONVERSIONS)
|
||||||
return (isRgba ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
return (isRgba ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||||
#elif defined(EXR_USE_QT6_FLOAT_IMAGE)
|
#elif defined(EXR_USE_QT6_FLOAT_IMAGE)
|
||||||
return (isRgba ? QImage::Format_RGBA16FPx4 : QImage::Format_RGBX16FPx4);
|
return (isRgba ? QImage::Format_RGBA16FPx4 : isGray ? QImage::Format_Grayscale16 : QImage::Format_RGBX16FPx4);
|
||||||
#else
|
#else
|
||||||
return (isRgba ? QImage::Format_RGBA64 : QImage::Format_RGBX64);
|
return (isRgba ? QImage::Format_RGBA64 : QImage::Format_RGBX64);
|
||||||
#endif
|
#endif
|
||||||
@ -373,7 +383,16 @@ static void readColorSpace(const Imf::Header &header, QImage &image)
|
|||||||
QColorSpace::TransferFunction::Linear);
|
QColorSpace::TransferFunction::Linear);
|
||||||
}
|
}
|
||||||
if (!cs.isValid()) {
|
if (!cs.isValid()) {
|
||||||
|
#ifdef EXR_GRAY_SUPPORT_ENABLED
|
||||||
|
if (image.format() == QImage::Format_Grayscale16 || image.format() == QImage::Format_Grayscale8) {
|
||||||
|
cs = QColorSpace(QPointF(0.31271, 0.32902), QColorSpace::TransferFunction::Linear);
|
||||||
|
cs.setDescription(QStringLiteral("Gray Linear build-in"));
|
||||||
|
} else {
|
||||||
|
cs = QColorSpace(QColorSpace::SRgbLinear);
|
||||||
|
}
|
||||||
|
#else
|
||||||
cs = QColorSpace(QColorSpace::SRgbLinear);
|
cs = QColorSpace(QColorSpace::SRgbLinear);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
image.setColorSpace(cs);
|
image.setColorSpace(cs);
|
||||||
|
|
||||||
@ -443,6 +462,13 @@ bool EXRHandler::read(QImage *outImage)
|
|||||||
file.readPixels(my, std::min(my + EXR_LINES_PER_BLOCK - 1, dw.max.y));
|
file.readPixels(my, std::min(my + EXR_LINES_PER_BLOCK - 1, dw.max.y));
|
||||||
|
|
||||||
for (n = 0; n < std::min(EXR_LINES_PER_BLOCK, height - y); ++n) {
|
for (n = 0; n < std::min(EXR_LINES_PER_BLOCK, height - y); ++n) {
|
||||||
|
if (image.format() == QImage::Format_Grayscale16) { // grayscale image
|
||||||
|
auto scanLine = reinterpret_cast<quint16 *>(image.scanLine(y + n));
|
||||||
|
for (int x = 0; x < width; ++x) {
|
||||||
|
*(scanLine + x) = quint16(qBound(0.f, float(pixels[n][x].r) * 65535.f + 0.5f, 65535.f));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#if defined(EXR_USE_LEGACY_CONVERSIONS)
|
#if defined(EXR_USE_LEGACY_CONVERSIONS)
|
||||||
Q_UNUSED(isRgba)
|
Q_UNUSED(isRgba)
|
||||||
auto scanLine = reinterpret_cast<QRgb *>(image.scanLine(y + n));
|
auto scanLine = reinterpret_cast<QRgb *>(image.scanLine(y + n));
|
||||||
@ -639,7 +665,16 @@ bool EXRHandler::write(const QImage &image)
|
|||||||
auto convFormat = image.hasAlphaChannel() ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
|
auto convFormat = image.hasAlphaChannel() ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
|
||||||
#endif
|
#endif
|
||||||
ScanLineConverter slc(convFormat);
|
ScanLineConverter slc(convFormat);
|
||||||
|
#ifdef EXR_GRAY_SUPPORT_ENABLED
|
||||||
|
if (channelsType == Imf::RgbaChannels::WRITE_Y) {
|
||||||
|
slc.setDefaultSourceColorSpace(QColorSpace(QColorSpace(QColorSpace::SRgb).whitePoint(), QColorSpace::TransferFunction::SRgb)); // Creates a custom grayscale color space
|
||||||
|
} else {
|
||||||
|
slc.setDefaultSourceColorSpace(QColorSpace(QColorSpace::SRgb));
|
||||||
|
}
|
||||||
|
#else
|
||||||
slc.setDefaultSourceColorSpace(QColorSpace(QColorSpace::SRgb));
|
slc.setDefaultSourceColorSpace(QColorSpace(QColorSpace::SRgb));
|
||||||
|
#endif
|
||||||
|
|
||||||
slc.setTargetColorSpace(QColorSpace(QColorSpace::SRgbLinear));
|
slc.setTargetColorSpace(QColorSpace(QColorSpace::SRgbLinear));
|
||||||
for (int y = 0, n = 0; y < height; y += n) {
|
for (int y = 0, n = 0; y < height; y += n) {
|
||||||
for (n = 0; n < std::min(EXR_LINES_PER_BLOCK, height - y); ++n) {
|
for (n = 0; n < std::min(EXR_LINES_PER_BLOCK, height - y); ++n) {
|
||||||
|
@ -72,9 +72,18 @@ const uchar *ScanLineConverter::convertedScanLine(const QImage &image, qint32 y)
|
|||||||
if (!cs.isValid()) {
|
if (!cs.isValid()) {
|
||||||
cs = _defaultColorSpace;
|
cs = _defaultColorSpace;
|
||||||
}
|
}
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||||
|
if (tmp.depth() < 8 && cs.colorModel() == QColorSpace::ColorModel::Gray) {
|
||||||
|
tmp.convertTo(QImage::Format_Grayscale8);
|
||||||
|
}
|
||||||
|
else if (tmp.depth() < 24 && cs.colorModel() == QColorSpace::ColorModel::Rgb) {
|
||||||
|
tmp.convertTo(tmp.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (tmp.depth() < 24) {
|
if (tmp.depth() < 24) {
|
||||||
tmp.convertTo(tmp.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
tmp.convertTo(tmp.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
tmp.setColorSpace(cs);
|
tmp.setColorSpace(cs);
|
||||||
tmp.convertToColorSpace(_colorSpace);
|
tmp.convertToColorSpace(_colorSpace);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user