Skip to content

Commit b0039a7

Browse files
authored
fix(gif): Preserve RGB values of transparent pixels (#5188)
Preserve RGB of transparent color index pixels in GIF files. When reading GIF files, pixels of transparent color index were skipped. This left their RGB channels zeroed, discarding possible valid colormap data. To preserve the RGB values, we change to always write the colormap's RGB and set alpha conditionally. According to [GIF spec](https://www.w3.org/Graphics/GIF/spec-gif89a.txt): >viii) Transparency Index - The Transparency Index is such that when encountered, the corresponding pixel of the display device is not modified and processing goes on to the next pixel. The index is present if and only if the Transparency Flag is set to 1. So basically, it just defines a display compositing behavior but says nothing about the color table entry for that index being invalid or empty. In practice, encoders may still assign meaningful RGB values to the transparent index, and those values are perfectly well-defined in the colormap. For example, GIMP reads the valid RGB values ​​of transparent pixels (see attachment below). ### Tests A new test image and test case is added: AcademySoftwareFoundation/OpenImageIO-images#11 <img width="847" height="695" alt="image" src="https://github.com/user-attachments/assets/484c8b53-5a1b-4732-b95c-55a2f52021b5" /> Signed-off-by: Lumina Wang <lumina.wang@autodesk.com>
1 parent 42b6359 commit b0039a7

3 files changed

Lines changed: 11 additions & 4 deletions

File tree

src/gif.imageio/gifinput.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,13 @@ GIFInput::read_subimage_data()
366366
}
367367
int x = window_left + wx;
368368
int idx = m_spec.nchannels * (y * m_spec.width + x);
369-
if (0 <= x && x < m_spec.width
370-
&& fscanline[wx] != m_transparent_color) {
369+
if (0 <= x && x < m_spec.width) {
371370
m_canvas[idx] = colormap[fscanline[wx]].Red;
372371
m_canvas[idx + 1] = colormap[fscanline[wx]].Green;
373372
m_canvas[idx + 2] = colormap[fscanline[wx]].Blue;
374-
m_canvas[idx + 3] = 0xff;
373+
m_canvas[idx + 3] = (fscanline[wx] != m_transparent_color)
374+
? 0xff
375+
: 0x00;
375376
}
376377
}
377378
}

testsuite/gif/ref/out.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ Reading ../oiio-images/gif/gif_test_loop_count.gif
9090
gif:LoopCount: 12345
9191
oiio:ColorSpace: "srgb_rec709_scene"
9292
oiio:LoopCount: 12345
93+
Reading ../oiio-images/gif/gif_transparent_rgb.gif
94+
../oiio-images/gif/gif_transparent_rgb.gif : 2 x 1, 4 channel, uint8 gif
95+
SHA-1: 0F690404DA2B75EFC8CE225B19C0F49FEF39F9DE
96+
channel list: R, G, B, A
97+
gif:Interlacing: 0
98+
oiio:ColorSpace: "srgb_rec709_scene"
9399
Reading tahoe-tiny.gif
94100
tahoe-tiny.gif : 128 x 96, 4 channel, uint8 gif
95101
SHA-1: B05CB30B2108904DAAD7B39E1BD7AA68D1D844CC

testsuite/gif/run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"gif_tahoe.gif", "gif_tahoe_interlaced.gif",
99
"gif_bluedot.gif", "gif_diagonal_interlaced.gif",
1010
"gif_triangle_interlaced.gif", "gif_test_disposal_method.gif",
11-
"gif_test_loop_count.gif"]
11+
"gif_test_loop_count.gif", "gif_transparent_rgb.gif"]
1212
for f in files:
1313
command += info_command (OIIO_TESTSUITE_IMAGEDIR + "/" + f)
1414

0 commit comments

Comments
 (0)