C# 下载网络上的GIF图片的时候,怎么保持动画效果?

下载网络上GIF图片,发现没有动画效果,怎么能把gif图片完整的保存下来呢?

在 C# 中下载 GIF 图片,应该使用 WebClient 进行下载。但是需要注意的是,WebClient 默认只下载 GIF 图片的第一帧,而不是整个动画。如果你想下载整个 GIF 图片,需要使用更高级的方法。

一种方法是使用 HttpWebRequest 手动下载整个 GIF 文件,然后解析文件中的每一帧图像,最终将它们合并为一个 GIF 动画。这个过程需要用到 ImageFrameDimension 类,可以参考下面的代码示例:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;

public void DownloadGif(string url, string savePath)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    Bitmap animatedGif;

    using (Stream responseStream = response.GetResponseStream())
    {
        Image image = Image.FromStream(responseStream);

        FrameDimension dimension = new FrameDimension(image.FrameDimensionsList[0]);
        int frameCount = image.GetFrameCount(dimension);

        int delay = 0;

        using (MemoryStream memoryStream = new MemoryStream())
        {
            image.Save(memoryStream, ImageFormat.Gif);
            animatedGif = (Bitmap)Image.FromStream(memoryStream);
        }

        for (int i = 0; i < frameCount; i++)
        {
            image.SelectActiveFrame(dimension, i);
            using (MemoryStream memoryStream = new MemoryStream())
            {
                image.Save(memoryStream, ImageFormat.Gif);
                Image frame = Image.FromStream(memoryStream);
                FrameDimension frameDimension = new FrameDimension(frame.FrameDimensionsList[0]);
                FrameDelayProperty frameDelay = (FrameDelayProperty)frame.GetPropertyItem(20736);

                if (frameDelay != null)
                {
                    var byteArray = frameDelay.Value;
                    var numerator = BitConverter.ToInt32(byteArray, 0);
                    var denominator = BitConverter.ToInt32(byteArray, 4);

                    if (denominator == 0)
                    {
                        delay += numerator * 10;
                    }
                    else
                    {
                        delay += numerator * 10 / denominator;
                    }
                }
                else
                {
                    delay = 100;
                }

                animatedGif.SaveAdd(frame, frameDimension, Encoder.SaveFlag);
            }
        }
    }

    response.Close();
    animatedGif.Save(savePath, ImageFormat.Gif);
}

使用这个方法下载 GIF 图片时,需要将 savePath 参数设置为保存图片的路径,例如:"C:\test.gif"。

另一种方法是使用开源的 GifskiSharp 库,它可以将一系列图像转化为 GIF 动画。你可以使用 HttpClient 下载 GIF 图片并将其转换为字节数组,然后将字节数组转换为位图列表,最后使用 GifskiSharp 将其保存为 GIF 动画。这个过程需要使用异步操作,示例代码如下:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using GifskiSharp;

public async Task DownloadAndSaveAnimatedGifAsync(string url, string savePath)
{
    HttpClient httpClient = new HttpClient();
    HttpResponseMessage httpResponse = await httpClient.GetAsync(url);

    byte[] gifBytes = await httpResponse.Content.ReadAsByteArrayAsync();

    Image gifImage = Image.FromStream(new MemoryStream(gifBytes));
    FrameDimension dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
    int frameCount = gifImage.GetFrameCount(dimension);

    List<Bitmap> bitmaps = new List<Bitmap>();

    for (int i = 0; i < frameCount; i++)
    {
        gifImage.SelectActiveFrame(dimension, i);
        bitmaps.Add(new Bitmap(gifImage));
    }

    var encoder = new GifskiEncoder(new GifskiEncoderOptions { Quality = 100 });
    encoder.AddFrames(bitmaps.Select(bmp => bmp.ToByteArray(ImageFormat.Png, 100)).ToArray());
    encoder.Finish();

    File.WriteAllBytes(savePath, encoder.Encode());
}

这个方法使用了 GifskiSharp 库,可以使用 NuGet 包管理器安装。

无论使用哪种方法,都需要注意 GIF 图片的大小和下载速度,以避免程序出现性能问题。此外,下载和处理 GIF 图片时可能会使用到较大的内存,也需要注意内存管理。