How to fix .gif with corrupted alpha channel (stuck pixels) collected with Graphicsmagick?

孤街醉人 提交于 2019-12-24 01:57:15

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!