2

I want to convert an .avi with alpha channel into a .gif.
Firstly, I use

ffmpeg -i source.avi -vf scale=720:-1:flags=lanczos,fps=10 frames/ffout%03d.png

to convert .avi to sequence of .png's with aplha channel.
Then, I use

gm convert -loop 0 frames/ffout*.png output.gif

to collect a .gif.
But it seems that pixels of the output.gif just get stuck when something opaque is rendered on top of the transparent areas.

Here's an example:

img

As you can see the hearts and explosions do not get derendered.

P.S. FFMPEG output (collection on .png's) is fine.

Community
  • 1
  • 1

1 Answers1

3

I do not use Graphicsmagick but your GIF has image disposal mode 0 (no animation). You should use disposal mode 2 (clear with background) or 3 (restore previous image) both works for your GIF. The disposal is present in gfx extension of each frame in the Packed value.

So if you can try to configure encoder to use disposal = 2 or 3 or write script that direct stream copy your GIF and change the Packed value of gfx extension chunk frame by frame. Similar to this:

If you need help with the script then take a look at:

When I tried this (C++ script) on your GIF using disposal 2 I got this result:

disposal=2

The disposal is changed in C++ like this:

struct __gfxext
    {
    BYTE Introducer;        /* Extension Introducer (always 21h) */
    BYTE Label;             /* Graphic Control Label (always F9h) */
    BYTE BlockSize;         /* Size of remaining fields (always 04h) */
    BYTE Packed;            /* Method of graphics disposal to use */
    WORD DelayTime;         /* Hundredths of seconds to wait    */
    BYTE ColorIndex;        /* Transparent Color Index */
    BYTE Terminator;        /* Block Terminator (always 0) */
    __gfxext(){}; __gfxext(__gfxext& a){ *this=a; }; ~__gfxext(){}; __gfxext* operator = (const __gfxext *a) { *this=*a; return this; }; /*__gfxext* operator = (const __gfxext &a) { ...copy... return this; };*/
    };

__gfxext p;
p.Packed&=255-(7<<2);   // clear old disposal and leave the rest as is
p.Packed|=     2<<2;    // set new disposal=2 (the first 2 is disposal , the <<2 just shifts it to the correct position in Packed)

It is a good idea to leave other bits of Packed as are because no one knows what could be encoded in there in time ...

Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • 2
    Excellent sleuthing! A simple way to implement this (which I have tested and it works) with **GraphicsMagick** is to use OP's original script modified like this: `gm convert -loop 0 -dispose 2 frames/*.png output.gif` – Mark Setchell Apr 10 '17 at 08:11
  • 2
    @MarkSetchell it was easy to spot as mine own C++ encoder/decoder throws info like disposal, number of clear codes per frame and much much more for debugging purposes ... I just click on the file and see what is wrong on one look :) – Spektre Apr 10 '17 at 15:58
  • Thank you very much! This is exactly what I wanted. I cannot thank you enough! – Ivan Ivanov Apr 10 '17 at 18:38
  • 1
    @IvanIvanov btw this [Animated gif only loops once in Chrome and Firefox](http://stackoverflow.com/a/38082881/2521214) might interest you too as you are constructing GIFs ... – Spektre Apr 10 '17 at 19:08