C#GIF编码器/解码器

时间:2018-03-29 16:58:54

标签: c# encoding gif decoding

我正在开发一个加载动画GIF文件并改变一些像素的程序,然后将其作为新的动画GIF文件吐出。输出的GIF在Windows,浏览器和Photoshop中都很好用。

但是,如果我尝试使用我的程序加载GIF,它将不会动画。另外,我无法获得正确的调色板。加载代码与我用于加载原始GIF的代码完全相同。

这是我的保存代码:

   public int saveAsGif(string absPath, byte[] mark)
    {
        BitmapPalette palette = new BitmapPalette(getPaletteAsMediaColorList(m_Pal));

        int width = m_CanvasWidth;
        int height = m_CanvasHeight;

        using (FileStream fs = new FileStream(absPath, FileMode.Create))
        {
            GifBitmapEncoder encoder = new GifBitmapEncoder();

            for (int f = 0; f < m_NumberOfFrames; f++)
            {
                FrameData frame = m_Frames[f];
                byte[] pixels = frame.pixels;

                BitmapSource image = BitmapSource.Create(
                    width,
                    height,
                    96,
                    96,
                    System.Windows.Media.PixelFormats.Indexed8,
                    palette,
                    pixels,
                    width);

                encoder.Frames.Add(BitmapFrame.Create(image));

            }
            encoder.Save(fs);

            fs.Close();
        }

        return RESULT_SUCCESFUL;
    }

为了确保它不是我的加载代码,我使用以下代码创建了一个普通的新项目:

    private void Form1_Load(object sender, EventArgs e)
    {
        Bitmap test1 = new Bitmap(@"F:\original.gif");
        pictureBox1.Image = test1;

        Bitmap test2 = new Bitmap(@"F:\exported.gif");
        pictureBox2.Image = test2;
    }

original.gif将完美加载和播放,exported.gif将只显示静止帧。但是,在Windows / Browser / Photoshop中,exported.gif将播放。

1 个答案:

答案 0 :(得分:0)

我找到了一个相对简单的解决方案。它并不完美,但它对我有用。它仅适用于GifBitmapEncoder,不需要额外的库。

您需要做的一切;

  1. 将GIF数据从编码器写入内存流。
  2. 二进制写入前13个字节(GIF89a标题和内容)。
  3. Binary写'ApplicationExtention'块。
  4. Binary写下剩余的GIF数据。
  5. ApplicationExtention块允许动画。如果未设置延迟时间,则使用默认时间100毫秒。如果您确实需要每帧的自定义延迟,则需要在它们之间添加几个字节(请参阅GIF文件格式文档)。

    代码:

    public void saveAsGif(string absPath)
    {
        int width = m_CanvasWidth;
        int height = m_CanvasHeight;
    
        GifBitmapEncoder encoder = new GifBitmapEncoder();
        BitmapPalette palette = new BitmapPalette(getPaletteAsMediaColorList(m_Pal));
    
        for (int f = 0; f < m_NumberOfFrames; f++)
        {
            FrameData frame = m_Frames[f];
            byte[] pixels = frame.pixels;
    
            BitmapSource image = BitmapSource.Create(
                width,
                height,
                96,
                96,
                System.Windows.Media.PixelFormats.Indexed8,
                palette,
                pixels,
                width);
    
            encoder.Frames.Add(BitmapFrame.Create(image));
        }
    
        byte[] GifData;
        using (MemoryStream ms = new MemoryStream())
        {
            encoder.Save(ms);
            GifData = ms.ToArray();
        }
    
        byte[] ApplicationExtention = { 33, 255, 11, 78, 69, 84, 83, 67, 65, 80, 69, 50, 46, 48, 3, 1, 0, 0, 0 };
    
        using (FileStream fs = new FileStream(absPath, FileMode.Create))
        {
            fs.Write(GifData, 0, 13);
            fs.Write(ApplicationExtention, 0, ApplicationExtention.Length);
            fs.Write(GifData, 13, GifData.Length - 13);
        }
    }