使用C#压缩动画GIF图像大小

5

我想使用C#从多个图像创建动画gif图像,因此我使用了以下的Github解决方案来实现。

https://github.com/DataDink/Bumpkit

我正在使用以下代码来做到这一点。
using (var gif = File.OpenWrite(@"C:\IMG_TEST.gif"))
using (var encoder = new GifEncoder(gif))
    for (int i = 0, count = imageFilePaths.Length; i < count; i++)
    {
        Image image = Image.FromFile(imageFilePaths[i]);
        encoder.AddFrame(image,0,0);
    }

它的工作非常出色,但创建的gif大小为45 MB。如果我检查实际图像大小,则只有11MB,共47个图像。但是不知何故,gif生成了较大的大小。
现在我想压缩使用c#创建的gif图像的大小。
那么是否有任何方法可以压缩gif图像的大小?

在Google上搜索如何在C#中创建Zip文件,有很多可行的示例在线。同时,请使用 { } 正确地格式化您的第二个代码块。 - MethodMan
1
我不想创建zip文件,我想压缩正在创建的动态gif的大小。 - User5590
1
请在谷歌上搜索如何在 C# 中压缩 GIF 的大小。 - MethodMan
这个问题能帮到你。虽然是关于JPG的,但很容易适应处理GIF:https://dev59.com/questions/HnI-5IYBdhLWcg3wy70d。它不是针对所讨论的库,但实际上并没有真正需要使用它。在C#中已经存在了。 - ManoDestra
1个回答

1
我知道这是一个老问题,但我想分享一下我的解决方案。
我遇到了同样的问题,并发现每个帧应该只包含与上一帧不同的像素。我以为编码器会为我做图像差异,但显然它没有。
因此,在添加每个帧之前,我使用我编写的这个方法将其与前一帧进行比较。然后我添加仅包含更改像素的结果图像。
这是我使用它的地方:https://github.com/Jay-Rad/CleanShot/blob/master/CleanShot/Classes/GIFRecorder.cs
public class ImageDiff
{
    public static Bitmap GetDifference(Bitmap bitmap1, Bitmap bitmap2)
    {
        if (bitmap1.Height != bitmap2.Height || bitmap1.Width != bitmap2.Width)
        {
            throw new Exception("Bitmaps are not of equal dimensions.");
        }
        if (!Bitmap.IsAlphaPixelFormat(bitmap1.PixelFormat) || !Bitmap.IsAlphaPixelFormat(bitmap2.PixelFormat) ||
            !Bitmap.IsCanonicalPixelFormat(bitmap1.PixelFormat) || !Bitmap.IsCanonicalPixelFormat(bitmap2.PixelFormat))
        {
            throw new Exception("Bitmaps must be 32 bits per pixel and contain alpha channel.");
        }
        var newImage = new Bitmap(bitmap1.Width, bitmap1.Height);

        var bd1 = bitmap1.LockBits(new System.Drawing.Rectangle(0, 0, bitmap1.Width, bitmap1.Height), ImageLockMode.ReadOnly, bitmap1.PixelFormat);
        var bd2 = bitmap2.LockBits(new System.Drawing.Rectangle(0, 0, bitmap2.Width, bitmap2.Height), ImageLockMode.ReadOnly, bitmap2.PixelFormat);
        // Get the address of the first line.
        IntPtr ptr1 = bd1.Scan0;
        IntPtr ptr2 = bd2.Scan0;

        // Declare an array to hold the bytes of the bitmap.
        int bytes = Math.Abs(bd1.Stride) * bitmap1.Height;
        byte[] rgbValues1 = new byte[bytes];
        byte[] rgbValues2 = new byte[bytes];

        // Copy the RGBA values into the array.
        Marshal.Copy(ptr1, rgbValues1, 0, bytes);
        Marshal.Copy(ptr2, rgbValues2, 0, bytes);

        // Check RGBA value for each pixel.
        for (int counter = 0; counter < rgbValues1.Length - 4; counter += 4)
        {
            if (rgbValues1[counter] != rgbValues2[counter] ||
                rgbValues1[counter + 1] != rgbValues2[counter + 1] ||
                rgbValues1[counter + 2] != rgbValues2[counter + 2] ||
                rgbValues1[counter + 3] != rgbValues2[counter + 3])
            {
                // Change was found.
                var pixel = counter / 4;
                var row = (int)Math.Floor((double)pixel / bd1.Width);
                var column = pixel % bd1.Width;
                newImage.SetPixel(column, row, Color.FromArgb(rgbValues1[counter + 3], rgbValues1[counter + 2], rgbValues1[counter + 1], rgbValues1[counter]));
            }
        }
        bitmap1.UnlockBits(bd1);
        bitmap2.UnlockBits(bd2);
        return newImage;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接