And*_*and 10 delphi animation gif animated-gif tgifimage
我发现使用Delphi 2009创建的动画GIF TGIFImage有时在某些 GIF查看器中无法正常播放.问题是动画过早地重新启动.
请考虑以下示例:
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.
Run Code Online (Sandbox Code Playgroud)
(这是我能找到的解决问题的最简单的例子.)
输出是一个相当大的动画GIF.在Internet Explorer 11中,整个15秒的"电影"可以正常播放,但在谷歌浏览器中,"电影"仅在大约四秒后过早重启.
为什么是这样?
GIFImg?为了SO用户的利益,上面的代码是一个最小的工作示例.当然,当我发现这个问题时,我并没有创造出这些迷幻图案.相反,我正在研究一个Lorenz系统模拟器,并制作了这个GIF动画,它可以在IE中播放,但不能在Chrome中播放:
显示问题的样本GIF动画http://privat.rejbrand.se/lorenz50.gif
在Internet Explorer 11中,模型在重新启动动画之前旋转360度.在谷歌浏览器中,动画仅在大约20度后过早重启.
如果我在GIMP中打开'有问题'的GIF并让GIMP(重新)将其保存为动画GIF,则结果可以在每个观看者中使用.以下是Lorenz动画的GIMPed版本:
已经GIMPed的示例GIF动画http://privat.rejbrand.se/lorenz50_GIMPed.gif
比较两个文件使用十六进制编辑器,并使用维基百科文章作为参考,例如,似乎'NETSCAPE'字符串在原始(unGIMPed)版本中的位置错误.这是有点怪,即使我设置width和heightGIF图像,在逻辑屏幕描述符对应的值是不存在的.
这是TGIFImage的LZW编码器中的一个错误.
在一些非常罕见的情况下,LZW编码器将在LZW蒸汽结束时输出额外的零字节.由于LZW结束块标记也是零字节,严格的GIF阅读器可能会对此进行阻塞或将其解释为GIF的结尾(尽管文件结束标记为$ 3B).
一些GIF读者可以解决这个问题的原因可能是多年前这个问题的GIF很常见.显然,TGIFImage并不是唯一能够犯这个错误的库.
要解决此问题,请进行以下修改gifimg.pas(更改标记为*):
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;
Run Code Online (Sandbox Code Playgroud)