0

谁能告诉我为什么这会生成一个只有黑色的动画 gif?

该代码还输出每个在内存中生成的 gif 以显示它们是不同的

    public static void Test()
    {
        Image<Rgba32> img = null;
        Image<Rgba32> gif = null;

        TextGraphicsOptions textGraphicsOptions = new TextGraphicsOptions(true);
        SolidBrush<Rgba32> brushYellow = new SolidBrush<Rgba32>(Rgba32.Yellow);

        FontCollection fonts = new FontCollection();
        fonts.Install(fontLocation);
        Font font = fonts.CreateFont("Liberation Mono", PngFontHeight, FontStyle.Regular);


        gif = new Image<Rgba32>(400, 400);
        for (int i = 0; i < 10;++i)
        {
            img = new Image<Rgba32>(400, 400);
            img.Mutate(x => x.Fill(Rgba32.Black));
            img.Mutate(x => x.DrawText(textGraphicsOptions, i.ToString(), font, brushYellow, new PointF(1,1)));

            gif.Frames.AddFrame(img.Frames[0]);


            using (FileStream fs = File.Create(Path.Join(Program.workingDirectory, string.Format("Test-{0}.gif", i))))
            {
                img.SaveAsGif(fs);
            }

            img.Dispose();
        }

        using (FileStream fs = File.Create(Path.Join(Program.workingDirectory, "Test.gif")))
        {
            gif.SaveAsGif(fs);
        }
    }

如果我使用此代码对其进行编码以加载每个单独的物理文件,它会按预期制作动画 gif。

我只想在内存中创建动画 gif。

4

1 回答 1

2

当你创建一个Image<>...

gif = new Image<Rgba32>(400, 400);

...gif.Frames[0]是一个“透明黑色”帧(每个像素的 RGBA 值为#00000000)。您在for循环中创建的附加帧并添加...

gif.Frames.AddFrame(img.Frames[0]);

...gif.Frames[1]通过gif.Frames[10],总共 11 帧。

GIF 编码器用于GifColorTableMode决定是为每一帧生成一个颜色表,还是为所有帧使用第一帧的颜色表。默认值GifColorTableMode.Global加上第一个透明帧的组合会产生一个.gif只有一种颜色的 11 帧文件,即相同的“透明黑色”。这就是为什么您的黄色文本没有出现并且每一帧看起来都一样的原因。

为了解决这个问题,在保存文件之前的某个时间点,您需要删除初始透明帧,这样它就不会影响颜色表计算,并且因为它不是动画的一部分,无论如何...

gif.Frames.RemoveFrame(0);

您可能还想更改为,GifColorTableMode.Local以便您的.gif文件包含反映所有渲染颜色的颜色表...

gif.MetaData.GetFormatMetaData(GifFormat.Instance).ColorTableMode = GifColorTableMode.Local;

...尽管您的 10 个帧每个都使用几乎相同的一组颜色,但如果文件大小比颜色表示更受关注,您可能会不理会该属性。生成 400 × 400 动画GifColorTableMode.Global会生成9,835 字节的文件,而GifColorTableMode.Local生成16,703 字节的文件;大70%,但我无法分辨它们之间的区别。

GitHub 上的相关问题

顺便说一句,由于我在此过程中发现了这一点,如果您想更改动画帧的持续时间,您可以使用GetFormatMetaData()类似于上面显示的另一种方法来实现...

GifFrameMetaData frameMetaData = img.MetaData.GetFormatMetaData(GifFormat.Instance);

frameMetaData.FrameDelay = 100;// 1 second
于 2019-06-26T21:56:35.370 回答