某些 GIF 查看器的 Delphi TGIFImage 动画问题 [英] Delphi TGIFImage animation issue with some GIF viewers

查看:50
本文介绍了某些 GIF 查看器的 Delphi TGIFImage 动画问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现使用 Delphi 2009 的 TGIFImage 创建的动画 GIF 有时无法在 某些 GIF 查看器中正确播放.问题是动画过早重启.

I have discovered that animated GIFs created using Delphi 2009's TGIFImage sometimes doesn't play correctly in some GIF viewers. The problem is that the animation is restarted prematurely.

考虑以下示例:

program GIFAnomaly;

{$APPTYPE CONSOLE}

uses
  Windows, Types, Classes, SysUtils, Graphics, GIFImg;

var
  g: TGIFImage;
  bm: TBitmap;

procedure MakeFrame(n: integer);
var
  x: Integer;
  y: Integer;
begin
  for x := 0 to 256 - 1 do
    for y := 0 to 256 - 1 do
      bm.Canvas.Pixels[x, y] := RGB((x + n) mod 255,
        (x + y - 2*n) mod 255, (x*y*n div 500) mod 255);
end;

var
  i: integer;

begin

  bm := TBitmap.Create;
  bm.SetSize(256, 256);

  g := TGIFImage.Create;
  g.Animate := true;
  for i := 0 to 499 do
  begin
    MakeFrame(i);
    TGIFGraphicControlExtension.Create(g.Add(bm)).Delay := 3;
    Writeln('Creating frame ', i+1, ' of 500.');
  end;
  TGIFAppExtNSLoop.Create(g.Images.Frames[0]).Loops := 0;

  g.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\test.gif');


end.

(这是我能找到的显示问题的最简单的例子.)

(This is the simplest example I could find that exhibits the problem.)

输出是一个相当大的动画 GIF.在 Internet Explorer 11 中,整个 15 秒的电影"都可以正常播放,但在 Google Chrome 中,电影"仅在大约 4 秒后就过早地重新启动.

The output is a rather large animated GIF. In Internet Explorer 11, the entire 15-second 'movie' is played properly, but in Google Chrome the 'movie' is prematurely restarted after only about four seconds.

这是为什么?

  1. 输出的 GIF 文件有问题吗?
  2. 如果是这样,我上面的代码是否有问题,或者 GIFImg 是否有问题?
  3. 如果不是,查看器中问题的性质是什么?有多少可用观众有这个问题?有没有办法在 GIF 创建过程中避免"这个问题?

为了 SO 用户的利益,上面的代码是一个最小的工作示例.当然,当我发现这个问题时,我并不是在创造这些迷幻图案.相反,我正在研究 Lorenz 系统模拟器,并制作了这个 GIF 动画,它可以在 IE 中播放,但不能在 Chrome 中播放:

For the benefit of the SO user, the above code is a minimal working example. Of course, I wasn't creating these psychedelic patterns when I discovered the issue. Instead, I was working on a Lorenz system simulator, and produced this GIF animation which does play in IE but not in Chrome:

在 Internet Explorer 11 中,模型会在动画重新启动之前旋转 360 度.在 Google Chrome 中,动画仅在大约 20 度后过早重新启动.

In Internet Explorer 11, the model is rotated 360 degrees before the animation is restarted. In Google Chrome, the animation is restarted prematurely after only some 20 degrees.

  • 洛伦兹图像在 Internet Explorer 11.0.9600.17239、GIMP 2.8.0、Opera 12.16 中工作
  • 洛伦兹图像在 Google Chrome 36.0.1985.143 m、Firefox 26.0、27.0.1、31.0 中不起作用.

如果我在 The GIMP 中打开一个有问题"的 GIF 并让 GIMP(重新)将其保存为动画 GIF,则结果适用于每个查看器.以下是洛伦兹动画的GIMPed版本:

If I open a 'problematic' GIF in The GIMP and let GIMP (re)save it as an animated GIF, the result works in every viewer. The following is the GIMPed version of the Lorenz animation:

使用十六进制编辑器比较两个文件,并使用维基百科文章作为例如,一个参考似乎就像'NETSCAPE'字符串在原始(unGIMPed)版本中的错误位置.有点奇怪,即使我设置了GIF图片的widthheight,逻辑屏幕描述符中对应的值也没有.

Comparing the two files using a hex editor, and using the Wikipedia article as a reference, it seems, for instance, like the 'NETSCAPE' string is at the wrong place in the original (unGIMPed) version. It is somewhat strange, that even if I set the width and height of the GIF image, the corresponding values in the Logical Screen Descriptor are not there.

推荐答案

这是 TGIFImage 的 LZW 编码器中的一个错误.

It's a bug in TGIFImage's LZW encoder.

在一些非常罕见的情况下,LZW 编码器会在 LZW 流的末尾输出一个额外的零字节.由于 LZW 结束块标记也是一个零字节,严格的 GIF 阅读器可能会对此感到窒息或将其解释为 GIF 的结束(尽管文件结束标记是 $3B).

In some very rare circumstances the LZW encoder will output an extra zero byte at the end of the LZW steam. Since the LZW end block marker is also a zero byte, a strict GIF reader might choke on this or interpret it as the end of the GIF (although the end of file marker is $3B).

一些 GIF 阅读器可以处理这个问题的原因可能是,有这个问题的 GIF 在多年前很常见.显然,TGIFImage 并不是唯一犯这种错误的库.

The reason some GIF readers can handle this is probably that GIFs with this problem was common many years ago. Apparently TGIFImage wasn't the only library to make that particular mistake.

为了解决这个问题,对gifimg.pas进行如下修改(标记为*):

To fix the problem make the following modification to gifimg.pas (change marked with *):

procedure TGIFWriter.FlushBuffer;
begin
  if (FNeedsFlush) then
  begin
    FBuffer[0] := Byte(FBufferCount-1); // Block size excluding the count
    Stream.WriteBuffer(FBuffer, FBufferCount);
    FBufferCount := 1; // Reserve first byte of buffer for length
    FNeedsFlush := False; // *** Add this ***
  end;
end;

这篇关于某些 GIF 查看器的 Delphi TGIFImage 动画问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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