动画 GIF 的帧率似乎低于预期 [英] Animated GIF's framerate seems lower than expected

查看:36
本文介绍了动画 GIF 的帧率似乎低于预期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 winforms 应用程序,它上面有一个 gif,用于让用户了解停止进程.

I have a winforms application, which has a gif on it for letting users know about stalling processes.

问题是它的播放速度比在其他应用程序(chrome、Internet Explorer)上看起来慢得多.

The problem is it plays much slower than it seems on other applications (chrome, internet explorer).

我在 PictureBoxLabel 上尝试过 gif,但结果速度相同.然后经过一些研究,我遇到了 this 问题和传奇@Hans Passant 的回答,但不幸的是,应用他建议的样板代码没有任何区别.

I have tried the gif on PictureBox and Label but resulting speed is same. Then after a little research I've come accross this question and the answer of legendary @Hans Passant, but unfortunately applying the boilerplate code suggested by him didn't make any difference.

下面是简单的复现代码:

Below is the simple reproducing code:

public partial class Form1 : Form
{
    public Form1 ()
    {
        InitializeComponent();
        timeBeginPeriod(timerAccuracy);
    }

    protected override void OnFormClosed ( FormClosedEventArgs e )
    {
        timeEndPeriod(timerAccuracy);
        base.OnFormClosed(e);
    }

    // Pinvoke:
    private const int timerAccuracy = 10;
    [System.Runtime.InteropServices.DllImport("winmm.dll")]
    private static extern int timeBeginPeriod ( int msec );
    [System.Runtime.InteropServices.DllImport("winmm.dll")]
    public static extern int timeEndPeriod ( int msec );
}

如果需要,还有设计器代码:

And the designer code if needed:

partial class Form1
{
    private System.ComponentModel.IContainer components = null;

    protected override void Dispose ( bool disposing )
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    private void InitializeComponent ()
    {
        System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
        this.pictureBox1 = new System.Windows.Forms.PictureBox();
        this.label1 = new System.Windows.Forms.Label();
        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
        this.SuspendLayout();
        //
        // pictureBox1
        //
        this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
        this.pictureBox1.Location = new System.Drawing.Point(8, 9);
        this.pictureBox1.Name = "pictureBox1";
        this.pictureBox1.Size = new System.Drawing.Size(166, 119);
        this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
        this.pictureBox1.TabIndex = 0;
        this.pictureBox1.TabStop = false;
        //
        // label1
        //
        this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        this.label1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.label1.Image = ((System.Drawing.Image)(resources.GetObject("label1.Image")));
        this.label1.Location = new System.Drawing.Point(180, 9);
        this.label1.Name = "label1";
        this.label1.Size = new System.Drawing.Size(158, 119);
        this.label1.TabIndex = 1;
        //
        // Form1
        //
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(346, 134);
        this.Controls.Add(this.label1);
        this.Controls.Add(this.pictureBox1);
        this.Name = "Form1";
        this.Text = "Form1";
        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.PictureBox pictureBox1;
    private System.Windows.Forms.Label label1;
}

两个 gif 的播放速度相同,但比实际 gif 低.在应用此代码时,我还有其他需要注意的地方吗?

Both gifs play at same speed, but lower than the actual gif. Is there any other points that I should be aware of while applying this code?

推荐答案

你只能猜测,我怀疑有人会很幸运得到重现:

You can only get guesses, I doubt anybody will have much luck getting a repro:

  • timeBeginPeriod() 在技术上可能会失败,尽管当您要求 10 毫秒时这是非常不寻常的,请验证它是否返回 0.
  • 如果图像很大,那么它可能无法足够快地更新.或者你的 UI 线程被其他任务占用了太多.gif 的像素格式与现代机器上视频适配器的像素格式不匹配.每次更新帧时都会进行转换.它相当昂贵,特别是如果您还强制重新缩放图像(即 PictureBox.SizeMode != Normal).使用任务管理器验证您的 UI 线程没有消耗 100% 的内核.
  • 您可以通过从提升的命令提示符运行 powercfg/energy 来获得关于有效计时器周期的第二意见.在您的应用程序运行时执行此操作.它将运行一分钟,然后生成一个 HTML 文件,您可以使用浏览器查看该文件.在平台计时器分辨率:计时器请求堆栈"标题下报告,请求周期值应为 10000.请注意其他进程或驱动程序也可能发出请求.
  • timeBeginPeriod() can technically fail, although that is very unusual when you ask for 10 msec, verify that it returns 0.
  • If the image is large then it might just not be able to update fast enough. Or your UI thread is occupied too much with other duties. The pixel format of a gif is a poor match with the pixel format of the video adapter on a modern machine. The conversion is done every time the frame is updated. It is fairly expensive, especially so if you also force the image to be rescaled (i.e. PictureBox.SizeMode != Normal). Use Task Manager to verify that your UI thread is not burning 100% core.
  • You can get a second opinion about the effective timer period by running powercfg /energy from an elevated command prompt. Do so while your app is running. It will trundle for a minute and then generate an HTML file that you can look at with your browser. Reported under the "Platform Timer Resolution:Timer Request Stack" heading, the Requested Period value should be 10000. Beware that other processes or drivers might also have made requests.

这篇关于动画 GIF 的帧率似乎低于预期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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