dwa_uncompress() writes the RLE section, which carries the alpha channel, to slot 0, and guards that with nb_channels >= 4. That is a proxy for "this image has an alpha channel" and it is wrong as soon as the image carries other channels instead. With four or more channels and no alpha, slot 0 belongs to B, and the RLE data overwrites the blue plane. Whether it does depends on whether the encoder placed any channel into the RLE section, so the same channel list decodes correctly or loses its blue depending on the file.
Test the actual condition instead: the alpha channel has to be the one sitting in slot 0. The patch is attached as git format-patch output.
From 68472d1b10103688bca6f2b2472607c83ee8adc1 Mon Sep 17 00:00:00 2001 From: Nexory <[email protected]> Date: Sat, 22 Aug 2026 15:51:24 +0200 Subject: [PATCH 1/2] avcodec/exr: Write the DWA alpha slot only when alpha occupies it dwa_uncompress() writes the RLE section, which carries the alpha channel, to slot 0, and guards that with nb_channels >= 4. That is a proxy for "this image has an alpha channel" and it is wrong as soon as the image carries other channels instead. With four or more channels and no alpha, slot 0 belongs to B, and the RLE data overwrites the blue plane. Whether it does depends on whether the encoder placed any channel into the RLE section, so the same channel list decodes correctly or loses its blue depending on the file. Test the actual condition instead: the alpha channel has to be the one sitting in slot 0. Signed-off-by: Nexory <[email protected]> --- libavcodec/exr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 0e9c734a..cbd80d75 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1210,7 +1210,13 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse } } - if (s->nb_channels < 4) + /* The RLE section carries the alpha channel, and the loops below write it + * to slot 0. nb_channels >= 4 is only a proxy for "this image has an alpha + * channel"; the accurate test is that the alpha channel is the one sitting + * in slot 0. Without it an image that carries extra channels after B, G + * and R loses its blue plane whenever the encoder put a channel into the + * RLE section. */ + if (s->channel_offsets[3] != 0) return 0; if (s->pixel_type == EXR_HALF) { -- 2.47.3
_______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
