问题
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:
As you can see the hearts and explosions do not get derendered.
P.S. FFMPEG output (collection on .png's) is fine.
回答1:
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:
- GIF Image getting distorted on interlacing
If you need help with the script then take a look at:
- How to find where does Image Block start in GIF images?
- Decode data bytes of GIF87a raster data stream
When I tried this (C++ script) on your GIF using disposal 2
I got this result:
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 ...
来源:https://stackoverflow.com/questions/43311478/how-to-fix-gif-with-corrupted-alpha-channel-stuck-pixels-collected-with-graph