【问题标题】:Bitmap animation stops working, after running a few frames运行几帧后位图动画停止工作
【发布时间】:2017-04-08 18:47:11
【问题描述】:

我尝试在 Windows 窗体应用程序上创建动画位图。一个定时器对象被设置为100ms的间隔,代码是这样工作的:

我有一个 2560x2560 的位图,这是我的地图,一个名为“pb”的图片框包含此地图,图片框的大小为 800x800,带有图像拉伸参数以提供更好的分辨率。我有一个包含火炬框架的 7 个元素的位图数组。这个想法是我将当前的火炬位图绘制到地图上,将“pb”的图像设置到地图上并调用无效过程来重绘它。然后将绘制有手电筒的位图恢复为原始地图位图“org_btm”。

代码如下:

        private void animationtick_Tick(object sender, EventArgs e)
        {
            using (Graphics g = Graphics.FromImage(btm))
            { g.DrawImage(torch_anim[torch_anim_c], new Point(20*64, 20*64)); }
            pb.Image = btm;
            pb.Invalidate();
            btm = org_btm;

            if (torch_anim_c < 6)
            {
                torch_anim_c++;
            }
            else
            {
                torch_anim_c = 0;
            }
            pb.Invalidate();
        }

'torch_anim_c' 是位图数组的索引计数器。 所以出现的问题是,火炬在前几帧工作,然后停止工作,卡在 1 帧上,当我在调试器中运行带有断点的代码时,它表明即使图像运行时代码也会运行卡住了,并且程序响应其他功能仍在工作。 你有任何想法如何解决这个问题吗? 提前谢谢你。

我有一张带有卡住手电筒动画的地图 sn-p: Torch Stuck Snippet

编辑:'Point()' 为 20*64,因为火炬大小为 64x64,位于位置 20,地图为 40*40 瓦片。

【问题讨论】:

  • pb.Invalidate();之前,检查pb.InvokeRequired是否为true
  • 问题依旧存在:(
  • 实际上,我删除了执行 'torch_anim[i].maketransparent(Color.FromArgb(255,255,255,255));' 的代码行这似乎解决了卡住的问题,我不知道为什么,但是我仍然需要使动画透明。
  • 您应该这样做:创建具有透明度的 sn-ps,并在 Paint 事件中将它们绘制到控件的表面上。由于它正在拉伸图像,因此您需要 scale 手电筒和位置。你现在的做法是,你的 toch 总是被绘制到图像中并且永远不会从图像中移除,所以在 6 次循环之后,它的所有像素都被设置并且看不到任何变化。..
  • 我不明白为什么你认为拉伸地图会降低分辨率,顺便说一句?也不要连续两次调用 Invalidate!

标签: c# winforms animation bitmap


【解决方案1】:

用photoshop把它转成gif格式,然后用这个类

public class GifImage
{
    private Image gifImage;
    private FrameDimension dimension;
    private int frameCount;
    private int currentFrame = -1;
    private bool reverse;
    private int step = 1;

    public GifImage(string path)
    {
        gifImage = Image.FromFile(path);
        dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
        frameCount = gifImage.GetFrameCount(dimension);
    }

    public bool ReverseAtEnd {
        get { return reverse; }
        set { reverse = value; }
    }

    public Image GetNextFrame()
    {

        currentFrame += step;
        if (currentFrame >= frameCount || currentFrame < 1) {
            if (reverse) {
                step *= -1;
                currentFrame += step;
            }
            else {
                currentFrame = 0;
            }
        }
        return GetFrame(currentFrame);
    }

    public Image GetFrame(int index)
    {
        gifImage.SelectActiveFrame(dimension, index);
        return (Image)gifImage.Clone();
    }
}

在表单加载时初始化它

GifImage gifImage = new GifImage(filePath);

如果你想在最后反转它,请将 Reverse 变量设置为 true

在计时器滴答时使用该代码

pb.Image = gifImage.GetNextFrame();

【讨论】:

    【解决方案2】:

    改变 pb.Invalidate();用 pb.Update();

    【讨论】:

    • 我改变了它,它似乎做同样的事情
    猜你喜欢
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    相关资源
    最近更新 更多