如果它们是相同的C#Drawing.Imaging下降GIF帧 [英] C# Drawing.Imaging dropping GIF frames if they are identical

查看:257
本文介绍了如果它们是相同的C#Drawing.Imaging下降GIF帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要加载GIF动画,并通过框架它们转换帧位图。要做到这一点,我被架使用Drawing.Imaging库中提取我的GIF文件框架,然后浇注每一帧位图。



在连续帧是相同的一切工作,除了时间就好了,当没有像素的差别。该库似乎丢弃这样的帧。



我来到了一个简单的测试conslusion。我创建了越来越大,到最后一圈自败,而新的是没有表现出刹那之间暂停缩小的圆的动画。当我播放动画由我提取位图的停顿不存在。如果我比较相同帧长度但不同量的相同帧的GIF文件,返回totalframescount值是不同的。我还观察到,化网页浏览器中正确显示相同的连续帧。

 公共无效DrawGif(图片IMG)
{

FrameDimension尺寸=新FrameDimension(img.FrameDimensionsList [0]);
INT frameCountTotal = img.GetFrameCount(尺寸);

为(INT framecount = 0; framecount< frameCountTotal; framecount ++)
{
img.SelectActiveFrame(尺寸,framecount);

BMP位图=新位图(IMG); //投图像类型为位图

的for(int i = 0; I< 16;我++)
{
为(INT J = 0; J< 16; J ++)
{
色色= bmp.GetPixel(I,J);
DrawPixel(I,J,0,color.R,color.G,color.B);

}
}




  1. 是否有人遇到这样的问题

  2. 当我非常新的C# - ?有没有修改.NET LIB办法

  3. 也许有我的问题的解决方案,我不知道,不涉及更改库?



更新代码 - 结果是一样的。



 公共无效DrawGif(IMG)
{
INT frameCountTotal = img.GetFrameCount(FrameDimension.Time);
为(INT framecount = 0; framecount< frameCountTotal; framecount ++)
{
img.SelectActiveFrame(FrameDimension.Time,framecount);
BMP位图=新位图(IMG);

的for(int i = 0; I< 16;我++)
{
为(INT J = 0; J< 16; J ++)
{
色色= bmp.GetPixel(I,J);
DrawPixel(I,J,0,color.R,color.G,color.B);

}


解决方案

图片不保存重复帧,所以你必须采取的时间每帧到账户。这是基于的这本书在Windows编程上如何让所有的帧和正确的时间。举个例子:

 公共类的Gif 
{
公共静态列表<车架和GT; LoadAnimatedGif(字符串路径)
{
//如果没有找到路径,我们应该抛出一个IO异常
如果(!File.Exists(路径))
抛出IOException的新( 文件不存在);

//加载图像
变种IMG = Image.FromFile(路径);

//计算帧
VAR frameCount = img.GetFrameCount(FrameDimension.Time);

//如果图像不是GIF动画,我们应该抛出一个
//参数异常
如果(frameCount< = 1)
抛出新的ArgumentException (图像不显示动画);

//名单,将持有的所有帧
变种帧=新的List<车架和GT;();

//获取存储在GIF
// PropertyTagFrameDelay((PROPID)0x5100)来自gdiplusimaging.h
// HTTP的更多信息时代:// MSDN。 microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
无功倍= img.GetPropertyItem(0x5100).value的;

//将4位持续时间块为一个int

的for(int i = 0; I< frameCount;我++)
{
/ /转换4位值整数
VAR持续时间= BitConverter.ToInt32(次,4 * I);

//添加一个新的框架,以我们的帧列表
frames.Add(
新帧()
{
图像=新位图(IMG ),
持续时间=持续时间
});

//之前,我们将它保存
img.SelectActiveFrame(FrameDimension.Time,I)将写帧;


}

//处置图像时,我们就大功告成了
img.Dispose();

返回帧;
}
}

我们需要一个结构来保存为位图和持续时间每一帧

  //类用于存储每一帧
公共类框架
{
公位图图像{搞定;组; }
公众诠释持续时间{搞定;设置;}
}



中的代码将加载一个位图,检查它是否是一个动画多帧 GIF 。然后循环,虽然所有的帧,构建独立的框架持有每帧的位图和持续时间对象的列表。使用简单:

  VAR框架列表= Gif.LoadAnimatedGif(A.GIF); 

变种i = 0;
的foreach(在页框VAR帧)
frame.Image.Save(frame_+ i ++在+png格式);


I need to load GIF animations and convert them frame by frame to bitmaps. To do that, I am extracting my GIF file frame by frame using Drawing.Imaging library and then casting each frame to bitmap.

Everything works just fine except the times when the consecutive frames are the same, when there is no pixel difference. The library seems to be dropping such frames.

I came to that conslusion with a simple test. I have created an animation of a circle that is growing and shrinking with a pause between the moment the last circle dissapears and the new one is not yet shown. When I play the animation consisting of my extracted bitmaps that pause is not present. If I compare the GIFs of the same frame-length but different amounts of identical frames, the returned totalframescount value is different. I have also observed that webbrowsers display identical consecutive frames correctly.

  public void DrawGif(Image img)
    {

        FrameDimension dimension = new FrameDimension(img.FrameDimensionsList[0]);
        int frameCountTotal = img.GetFrameCount(dimension);   

        for (int framecount = 0; framecount < frameCountTotal; framecount++)
        {
            img.SelectActiveFrame(dimension, framecount);  

            Bitmap bmp = new Bitmap(img);  //cast Image type to Bitmap

                for (int i = 0; i < 16; i++)
                {
                    for (int j = 0; j < 16; j++)
                    {
                        Color color = bmp.GetPixel(i, j);
                        DrawPixel(i, j, 0, color.R, color.G, color.B);

                    }
                }

  1. Does someone encountered such a problem?
  2. As I am pretty new to C# - is there a way to modify .NET lib ?
  3. Maybe there is a solution to my problem that I am not aware of, that does not involve changing the library?

Updated code - the result is the same

 public void DrawGif(img)
     {
      int frameCountTotal = img.GetFrameCount(FrameDimension.Time);
       for (int framecount = 0; framecount < frameCountTotal; framecount++)
            {
    img.SelectActiveFrame(FrameDimension.Time, framecount); 
     Bitmap bmp = new Bitmap(img);

    for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                        Color color = bmp.GetPixel(i, j);
                        DrawPixel(i, j, 0, color.R, color.G, color.B);

                }

解决方案

The Image is not saving duplicate frames, so you have to take the time of each frame into account. Here is some sample code based on this book in Windows Programming on how to get all the frames and the correct duration. An example:

public class Gif
{
    public static List<Frame> LoadAnimatedGif(string path)
    {
        //If path is not found, we should throw an IO exception
        if (!File.Exists(path))
            throw new IOException("File does not exist");

        //Load the image
        var img = Image.FromFile(path);

        //Count the frames
        var frameCount = img.GetFrameCount(FrameDimension.Time);

        //If the image is not an animated gif, we should throw an
        //argument exception
        if (frameCount <= 1)
            throw new ArgumentException("Image is not animated");

        //List that will hold all the frames
        var frames = new List<Frame>();

        //Get the times stored in the gif
        //PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h
        //More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
        var times = img.GetPropertyItem(0x5100).Value;

        //Convert the 4bit duration chunk into an int

        for (int i = 0; i < frameCount; i++)
        {
            //convert 4 bit value to integer
            var duration = BitConverter.ToInt32(times, 4*i);

            //Add a new frame to our list of frames
            frames.Add(
                new Frame()
                {
                    Image = new Bitmap(img),
                    Duration = duration
                });

            //Set the write frame before we save it
            img.SelectActiveFrame(FrameDimension.Time, i);


        }

        //Dispose the image when we're done
        img.Dispose();

        return frames;
    }
}

We need a structure to save the Bitmap and duration for each Frame

//Class to store each frame
public class Frame 
{ 
    public Bitmap Image { get; set; } 
    public int Duration { get; set;} 
}

The code will load a Bitmap, check whether it is a multi-frame animated GIF. It then loops though all the frames to construct a list of separate Frame objects that hold the bitmap and duration of each frame. Simple use:

var frameList = Gif.LoadAnimatedGif ("a.gif");

var i = 0;
foreach(var frame in frameList)
    frame.Image.Save ("frame_" + i++ + ".png");

这篇关于如果它们是相同的C#Drawing.Imaging下降GIF帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆