stb icon indicating copy to clipboard operation
stb copied to clipboard

Some GIF fixes stb_image

Open Nuk510 opened this issue 7 years ago • 8 comments

Fix 1: Disposal method 2 clears canvas

The old code was restoring pixels from an earlier frame with disposal method 2 in this test GIF. This disposal method should instead clear the canvas. Left: Original GIF Right: stb_image.h behavior, pre-fix test4b test4bstb

Fix 2: First frame preserves transparency for unspecified pixels.

The old code was clearing the pixels surrounding the first frame to a background color. They should instead remain transparent. Left: Boundaries of first frame Center: Original GIF Right: stb_image.h behavior, pre-fix mariofallboundaries mariofall mariofallstb

Nuk510 avatar Dec 17 '18 20:12 Nuk510

Should g.background even be allocated anymore? It looks to me like you've removed the only use of it, unless I'm missing something. Which then makes me wonder if this fix is even correct or if it's possible you've broken other cases.

nothings avatar Feb 07 '19 16:02 nothings

@rygorous is going to investigate some related issues in this code at some point, so I'm assigning it to him.

nothings avatar Mar 05 '19 07:03 nothings

Pinging @rygorous

nothings avatar Feb 02 '20 15:02 nothings

Just a note from a random passerby in a hope it will be useful -- I was dealing with GIF animations recently and while looking for test files I found dispose_bgnd.gif, dispose_none.gif and dispose_prev.gif in the Pillow repository. At least the first one renders differently with stb_image than in the browser, didn't check the other two.

mosra avatar Apr 06 '20 15:04 mosra

I have issues with GIF decoding as well and this PR unfortunately isn't quite right either.

The g->background array is not needed. This is used for dispose method 2. But instead the specification says it should be cleared to the background color which is g->pal[g->bgindex]. So to fix dispose method 2 one needs to copy g->pal[g->bgindex] over the array. Not use the g->background array and neither just set it to 0, like in this PR.

The PR also removes the block that begins with "if (first_frame && (g->bgindex > 0))" but I think that's wrong too. The condition should be changed to "if (first_frame && (g->bgindex > 0) && (g->eflags & 0x01) == 0)" instead.

Biohazard90 avatar Aug 10 '20 13:08 Biohazard90

There is also another problem, but with dispose method 3. I think to get the correct behavior, it should revert to the last non-disposable frame (dispose 0 or 1). This is something that must be fixed in the client code, but the parameter name two_back should be renamed to last_non_disposable or something. Then the client should store the values for this parameter by checking for (dispose == 0 || dispose == 1). Hope that makes sense.

All three GIFs mentioned by @mosra work for me now with the fixes I explained here.

Biohazard90 avatar Aug 10 '20 15:08 Biohazard90

We're going to fork animated gif support into a separate library, and this will have to be adapted when that happens.

nothings avatar Jul 11 '21 23:07 nothings

We're going to fork animated gif support into a separate library, and this will have to be adapted when that happens.

Oh cool! What's the library called?

celonymire avatar Dec 23 '21 16:12 celonymire