EXR: RGB / YC subtype support

This commit is contained in:
Mirco Miranda
2026-09-04 18:40:44 +02:00
committed by Mirco Miranda
parent 05af59e819
commit 0862db49b8
3 changed files with 54 additions and 0 deletions
+15
View File
@@ -392,6 +392,21 @@ The plugin can set the following additional metadata:
- `EXRLayerName`: A string containing the name of the EXR layer used to decode
the image.
When writing, it is possible to specify compression ratio and quality. The
values you can set depend on the version of the OpenEXR library you're using.
Please check the [exr_p.h](./src/imageformats/exr_p.h) for more
info.
When writing, it is also possible to specify a subtype:
- `RGB` (default): preserves full-resolution color data (R, G, B) without
subsampling or loss of chromatic detail.
- `YC`: converts RGB data into luminance (Y) and 2x2 subsampled chroma
(RY, BY), cutting raw color data by ~50% for significantly smaller file
sizes.
> [!note]
> When writing grayscale images, the subtype makes no difference.
### The EPS plugin
The plugin uses `Ghostscript` to convert the raster image. When reading it
+31
View File
@@ -200,12 +200,17 @@ void K_OStream::seekg(Imf::Int64 pos)
m_dev->seek(pos);
}
#define EXR_SUBFORMAT_RGB QByteArray("RGB")
#define EXR_SUBFORMAT_YC QByteArray("YC")
EXRHandler::EXRHandler()
: m_compressionRatio(-1)
, m_quality(-1)
, m_imageNumber(0)
, m_imageCount(0)
, m_startPos(-1)
, m_subType(EXR_SUBFORMAT_RGB)
{
// Set the number of threads to use (0 is allowed)
Imf::setGlobalThreadCount(QThread::idealThreadCount() / 2);
@@ -688,6 +693,9 @@ bool EXRHandler::write(const QImage &image)
// write the EXR
K_OStream ostr(device());
auto channelsType = image.hasAlphaChannel() ? Imf::RgbaChannels::WRITE_RGBA : Imf::RgbaChannels::WRITE_RGB;
if (m_subType == EXR_SUBFORMAT_YC) {
channelsType = channelsType == Imf::RgbaChannels::WRITE_RGBA ? Imf::RgbaChannels::WRITE_YCA : Imf::RgbaChannels::WRITE_YC;
}
if (image.format() == QImage::Format_Mono ||
image.format() == QImage::Format_MonoLSB ||
image.format() == QImage::Format_Grayscale16 ||
@@ -743,6 +751,15 @@ void EXRHandler::setOption(ImageOption option, const QVariant &value)
m_quality = q;
}
}
if (option == QImageIOHandler::SubType) {
auto subType = value.toByteArray();
auto list = EXRHandler::option(QImageIOHandler::SupportedSubTypes).value<QList<QByteArray>>();
if (list.contains(subType)) {
m_subType = subType;
} else {
m_subType = EXR_SUBFORMAT_RGB;
}
}
}
bool EXRHandler::supportsOption(ImageOption option) const
@@ -761,6 +778,12 @@ bool EXRHandler::supportsOption(ImageOption option) const
if (option == QImageIOHandler::Quality) {
return true;
}
if (option == QImageIOHandler::SubType) {
return true;
}
if (option == QImageIOHandler::SupportedSubTypes) {
return true;
}
return false;
}
@@ -815,6 +838,14 @@ QVariant EXRHandler::option(ImageOption option) const
v = QVariant(m_quality);
}
if (option == QImageIOHandler::SupportedSubTypes) {
return QVariant::fromValue(QList<QByteArray>() << EXR_SUBFORMAT_RGB << EXR_SUBFORMAT_YC);
}
if (option == QImageIOHandler::SubType) {
return QVariant::fromValue(m_subType);
}
return v;
}
+8
View File
@@ -118,6 +118,14 @@ private:
* The initial device position to allow multi image load (cache value).
*/
qint64 m_startPos;
/*!
* \brief m_subType
* The EXR subtype to use when writing:
* - RGB: preserves full-resolution color data (R, G, B) without subsampling or loss of chromatic detail (default).
* - YC: converts RGB data into luminance (Y) and 2x2 subsampled chroma (RY, BY), cutting raw color data by ~50% for significantly smaller file sizes.
*/
QByteArray m_subType;
};
class EXRPlugin : public QImageIOPlugin