EXR: fix alpha channel imperpretation

This commit is contained in:
Mirco Miranda
2026-09-04 18:40:44 +02:00
committed by Mirco Miranda
parent 0862db49b8
commit a738553dc9
20 changed files with 8 additions and 6 deletions
+2 -1
View File
@@ -402,7 +402,8 @@ When writing, it is also possible to specify a subtype:
subsampling or loss of chromatic detail. subsampling or loss of chromatic detail.
- `YC`: converts RGB data into luminance (Y) and 2x2 subsampled chroma - `YC`: converts RGB data into luminance (Y) and 2x2 subsampled chroma
(RY, BY), cutting raw color data by ~50% for significantly smaller file (RY, BY), cutting raw color data by ~50% for significantly smaller file
sizes. sizes. **If the image does not have a height and width that are multiples
of 2, `RGB` is used.**
> [!note] > [!note]
> When writing grayscale images, the subtype makes no difference. > When writing grayscale images, the subtype makes no difference.
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.
+6 -5
View File
@@ -230,7 +230,7 @@ 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;
return (isRgba ? QImage::Format_RGBA16FPx4 : QImage::Format_RGBX16FPx4); return (isRgba ? QImage::Format_RGBA16FPx4_Premultiplied : QImage::Format_RGBX16FPx4);
} }
/*! /*!
@@ -519,9 +519,9 @@ bool makePreview(const QImage &image, Imf::Array2D<Imf::PreviewRgba> &pixels)
QImage preview; QImage preview;
if (w > h) { if (w > h) {
preview = image.scaledToWidth(256).convertToFormat(QImage::Format_ARGB32); preview = image.scaledToWidth(256).convertToFormat(QImage::Format_ARGB32_Premultiplied);
} else { } else {
preview = image.scaledToHeight(256).convertToFormat(QImage::Format_ARGB32); preview = image.scaledToHeight(256).convertToFormat(QImage::Format_ARGB32_Premultiplied);
} }
if (preview.isNull()) { if (preview.isNull()) {
return false; return false;
@@ -693,7 +693,8 @@ bool EXRHandler::write(const QImage &image)
// write the EXR // write the EXR
K_OStream ostr(device()); K_OStream ostr(device());
auto channelsType = image.hasAlphaChannel() ? Imf::RgbaChannels::WRITE_RGBA : Imf::RgbaChannels::WRITE_RGB; auto channelsType = image.hasAlphaChannel() ? Imf::RgbaChannels::WRITE_RGBA : Imf::RgbaChannels::WRITE_RGB;
if (m_subType == EXR_SUBFORMAT_YC) { if (m_subType == EXR_SUBFORMAT_YC && !(width % 2) && !(height % 2)) {
// Works only with images with height and width that are multiples of 2.
channelsType = channelsType == Imf::RgbaChannels::WRITE_RGBA ? Imf::RgbaChannels::WRITE_YCA : Imf::RgbaChannels::WRITE_YC; channelsType = channelsType == Imf::RgbaChannels::WRITE_RGBA ? Imf::RgbaChannels::WRITE_YCA : Imf::RgbaChannels::WRITE_YC;
} }
if (image.format() == QImage::Format_Mono || if (image.format() == QImage::Format_Mono ||
@@ -707,7 +708,7 @@ bool EXRHandler::write(const QImage &image)
pixels.resizeErase(EXR_LINES_PER_BLOCK, width); pixels.resizeErase(EXR_LINES_PER_BLOCK, width);
// convert the image and write into the stream // convert the image and write into the stream
auto convFormat = image.hasAlphaChannel() ? QImage::Format_RGBA32FPx4 : QImage::Format_RGBX32FPx4; auto convFormat = image.hasAlphaChannel() ? QImage::Format_RGBA32FPx4_Premultiplied : QImage::Format_RGBX32FPx4;
ScanLineConverter slc(convFormat); ScanLineConverter slc(convFormat);
slc.setDefaultSourceColorSpace(QColorSpace(QColorSpace::SRgb)); slc.setDefaultSourceColorSpace(QColorSpace(QColorSpace::SRgb));
slc.setTargetColorSpace(QColorSpace(QColorSpace::SRgbLinear)); slc.setTargetColorSpace(QColorSpace(QColorSpace::SRgbLinear));