Delphi TGIFImage 与某些 GIF 查看器的动画问题

2023-11-24

我发现使用 Delphi 2009 创建的动画 GIFTGIFImage有时无法正确播放someGIF 观众。问题是动画过早地重新启动。

考虑以下示例:

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.

(这是我能找到的最简单的例子来说明这个问题。)

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

为什么是这样?

  1. 输出的 GIF 文件有问题吗?
  2. 如果是的话,是我上面的代码有问题,还是有问题GIFImg?
  3. 如果不是,查看器中问题的本质是什么?有多少观众有这个问题?有没有办法在 GIF 创建过程中“避免”这个问题?

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

Sample GIF animation displaying the issue

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

  • 洛伦兹图像works在 Internet Explorer 11.0.9600.17239、GIMP 2.8.0、Opera 12.16 中
  • 洛伦兹图像不起作用在谷歌浏览器 36.0.1985.143 m、火狐浏览器 26.0、27.0.1、31.0 中。

如果我在 GIMP 中打开一个“有问题”的 GIF 并让 GIMP(重新)将其另存为动画 GIF,则结果在每个查看器中都有效。以下是洛伦兹动画的 GIMPed 版本:

Sample GIF animation that has been GIMPed

使用十六进制编辑器比较两个文件,并使用维基百科文章作为参考,例如,“NETSCAPE”字符串似乎位于原始(未GIMPed)版本中的错误位置。有点奇怪的是,即使我设置了width and height对于 GIF 图像,逻辑屏幕描述符中的相应值不存在。


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

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

一些 GIF 阅读器能够处理这个问题的原因可能是很多年前就有这个问题的 GIF 很常见。显然 TGIF Image 并不是唯一犯这个错误的库。

要解决该问题,请进行以下修改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;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Delphi TGIFImage 与某些 GIF 查看器的动画问题 的相关文章

  • Indy 的 TIdHTTPProxyServer:如何过滤请求?

    我正在使用 TIdHTTPProxyServer 来实现一个简单的 HTTP 代理 但我现在想阻止一些与某些 URL 匹配的连接 哪个事件和 或组件最适合实现这一目标 Indy 文档并没有太多解释 Thanks 作为基本过滤器 您可以使用
  • 在项目后对本机动画平面列表项目做出反应

    我正在寻找一种方法来制作一个又一个的动画平面列表项目 当一个项目完成他的动画时 下一个项目 来自平面列表 将出现在屏幕上 class AnimatedFlatList extends React PureComponent state se
  • CSS动画比JS动画快吗?

    前段时间读到一篇文章说CSS动画比JS动画快 使用 jQuery 做了一些动画后 我可以理解为什么有些人会这么说 因为 jQuery 动画有时会出现错误并且速度很慢 但我想知道的是 这个论点是否有任何核心事实 有一种常见的误解 认为 CSS
  • Async InputQuery 不处理“取消”按钮

    我正在使用一个简单的调用TDialogServiceAsync InputQuery 使用单个输入 它只是忽略了Cancel按钮和窗口的X关闭按钮 But the Ok按钮工作正常 这是我的代码 uses FMX DialogService
  • requestAnimationFrame 报告的帧速率有时高于显示器的刷新速率

    我使用以下内容来记录应用程序的帧速率 let lastCalledTime let fps let frame 0 let csv Frame Timestamp FPS const refreshLoop gt window reques
  • 我如何在Delphi中处理事件?

    例如 我有一个程序 在单击 Button1 后执行某些操作 如果没有 Button1Click 中的代码 如何处理按钮的 onclick 事件 我需要为 Button1 动态添加事件 unit Unit1 interface uses Wi
  • 如何在Delphi中下载一个非常简单的HTTPS页面?

    我尝试了在这里看到的代码 但它不适用于 HTTPS 我需要将此页面作为字符串下载 并在其上添加一些换行符 以便将信息按顺序放入 TMemo 中 怎么做 我尝试使用 Indy 但由于 SSL 问题而失败 我尝试了此页面的解决方案 如何将网页下
  • TDictionary 上的 GetItem 由链接器消除

    我正在使用一个TDictionary of
  • 处理 TShellListView 后代中的文件放置

    我正在尝试创建 TShellListView 的后代 它接受从 Windows 资源管理器中删除的文件 我想在组件定义中处理拖 放操作 而不必在任何使用该组件的应用程序中实现它 我找到了接受从 Windows 资源管理器中拖放的文件的示例
  • 单击按钮重复动画

    我想每次单击按钮时都重复动画 我尝试做某事像这样 https jsfiddle net 91raod7e const dist document querySelector dist document querySelector butto
  • overridePendingTransition 显示第二个活动的速度太快

    我有 2 个活动 我想在两个活动之间创建一个动画过渡 以便两个活动的视图向上滑动 就好像第二个活动正在向上推动第一个活动一样 在我的第一个活动中我使用 Intent iSecondActivity new Intent FirstActiv
  • Cocos2d 变色精灵

    我需要我的精灵从一种颜色过渡到另一种颜色 然后不断地 比如蓝色 然后绿色 然后紫色 但我找不到任何好的动作 我想知道 我应该使用动画吗 或者是否有为此采取的联合行动 您可以使用 CCTintTo 操作来更改精灵的颜色 sprite runA
  • 使用完成处理程序在 Swift 中调用连续动画

    我正在制作一个可以显示化学反应动画的应用程序 每个原子都是一个 SCNSphere 并通过 SCNActions 进行动画处理 我尝试使用 runAction 中的完成处理程序在当前操作完成后调用下一个动画 因为每个原子必须做出很多不同的运
  • 每次 TDbGrid 的选定位置更改时都会触发什么事件?

    我的项目中有一个 TDbGrid 每次更改所选行时我都试图触发一个事件 行中的任何更改都已经更新了链接到同一数据源的所有数据感知控件 但还需要进行其他更改 我需要一个事件处理程序 我认为 OnColEnter 会起作用 根据帮助文件 它在以
  • 使用velocity.js制作可拖动元素的动画

    我正在使用velocity js 为用户拖动的可拖动 SVG 元素设置动画 然而 velocity js 将先前的 mousemove 坐标排队并通过所有后续的 mousemove 坐标进行动画处理 我想要的是velocity js 不要对
  • delphi中如何实现多重继承?

    我正在对一个旧库进行完全重写 我不确定如何处理这种情况 为了便于理解 大家都欢呼自行车类比 我有以下课程 TBike 自行车本身 TBikeWheel 自行车的一个轮子 TBikeWheelFront and TBikeWheelBack
  • 为什么 {$ifopt FINITEFLOAT ON} 无法编译?

    我有这样的构造 ifopt FINITEFLOAT ON message FINITEFLOAT option ON else message FINITEFLOAT option OFF endif 在我的源代码中 它不会编译 这一定是一
  • 如何在运行时(Delphi/Windows)程序中添加代码?

    我正在Windows XP Delphi 7上工作 我需要在正在运行的程序中添加一些过程 或函数 并且我不想在完成后再次重新编译它 我只有一个具有 5 个功能的主机应用程序来发送不同类型的警报 但是还有其他新的警报类型 所以我必须执行新的功
  • 如何更改 TPageControl 上标签的方向?

    我是 Delphi 的新手 再次强调 我在 1994 年就使用过 Delphi 我现在有 Delphi 2009 Pro 来自Java 我发现对象继承非常晦涩 我的用户想要选项卡位于左侧的选项卡式页面 但是 TPageControl 不允许
  • 如何调试仅在应用程序关闭时发生的崩溃? (德尔福)

    因此 经过最近的一些更改 我们发现我们最古老的应用程序之一有时会在关闭时崩溃 这会以 运行时错误 216 消息的形式或来自 Windows 错误报告的消息的形式表明应用程序已停止工作 该应用程序已经发出OutputDebugString 每

随机推荐

  • C# 中的 HttpWebRequest 不适用于 .net 4.5

    我正在开发一个 C 项目 该项目将 xml 发送到服务器并接收 xml 作为响应 安装 Net Framework 4 0 后 可以正常工作 安装 Net Framework 4 5 后 它会抛出此异常 System NullReferen
  • 是否可以在 Rails 中创建两个日期之间的月份列表

    我正在尝试创建一个页面来显示每个月的链接列表 按年份分组 月份必须位于 今天 和 首次输入的日期 这两个日期之间 我在砖墙上 我不知道如何创建它 任何帮助将不胜感激 问候 亚当 只需将您想要的内容放入范围循环中并使用 Date MONTHN
  • Flutter:将 Widget 的边缘与第二个 Widget 重叠

    我想将一个小部件的底部边缘与另一个小部件重叠 使其看起来像这样 我正在使用堆栈将箭头按钮放置在卡片上 目前我只是设置了位置 上面有一个看不见的框 问题是这种方法仅适用于确切的分辨率 它应该与屏幕尺寸无关 小部件的必要代码 Stack chi
  • 增加 catalina.bat 文件中堆大小的最佳方法

    我在 windows xp 上有 tomcat 6 服务器 并且我通过控制台启动 tomcat 即使用startup bat AFAIK catalina bat文件适用于 Windows 因此我正在更改 bat 文件以进行内存管理 我没有
  • 如何调用Web服务方法进行测试,例如从浏览器

    有一个 dll webservice 用 Delphi 制作 有一个名为List它返回字符串列表 宽字符串 是否有任何方法可以调用该服务而无需编写客户端应用程序来使用它 Ex http misitio com 8080 miwebservi
  • Emacs 24内置cedet功能亮点

    我想去掉上面的下划线功能 例如 如上面 void 的屏幕截图所示 http cedet sourceforge net img gen semantic ia complete menu png 我在文档中找不到任何明显的内容 但哎呀 我什
  • 将行替换为空格,将反斜杠替换为包含空格的字符串

    我想替换以下行 memory 20g with memory 100g 实际上它应该替换之后的任何数字 memory 以下是我所拥有的 但无法获得预期的结果 sed i E s b memory memroy 100g g a txt 您不
  • 如何在代码外部(即 XML 文件中)定义 AutoMapper 映射,或使用不同的方法来实现完全可配置的对象映射?

    EDIT 最初我打算使用 AutoMapper 来实现我的目标 但我必须知道 AutoMapper 并不是这样工作的 它使您可以创建配置文件 但在我的情况下 完全可配置 我需要为每个参数组合一个配置文件 所以我想出了一种自己的方法 请参阅答
  • AngularJS - jQuery UI - 绑定问题

    我目前正在将一个大型应用程序移植到一个基于 HTML5 的 Web 应用程序 我已经开始在 AngularJS 中构建该应用程序并享受 AngularJS 框架的强大功能 目前我遇到一个问题 我有一个指令为我提供了 jQuery Datep
  • 如何让 Python / PostgreSQL 更快?

    现在我有一个日志解析器读取 515mb 的纯文本文件 过去 4 年里每天的一个文件 我的代码目前是这样的 http gist github com 12978 我已经使用了 psyco 如代码中所示 并且我也在编译它并使用编译后的版本 它每
  • 如何将 tail -f 通过管道传输到 awk 中

    我正在尝试设置一个脚本 当日志文件中出现某个字符串时 会生成警报 已有的解决方案每分钟一次 grep 整个日志文件 并计算字符串出现的频率 使用日志行的时间戳仅计算前一分钟的出现次数 我认为用尾巴来做这件事会更有效 所以我尝试了以下方法作为
  • ASP.NET中如何在Web表单之间传递信息

    如何在asp net中将一些信息从一个Web表单发送到另一个Web表单 第一个网页表单是HumanList aspx显示a中的人类列表GridView成分 当用户单击编辑链接时 我想传递 humanID 人类记录 ID 的值 HumanLi
  • Google 自动完成教程为 swift 放置 api

    我想要一个自动完成文本字段 可以像 Android 一样自动完成位置 https developers google com places training autocomplete android 有谁知道我在哪里可以找到这方面的教程或示
  • 使用 youtube 播放器 api 在后台播放 Youtube 视频

    我已经使用成功播放了 YouTube 视频youtube player api 但我需要在按下后退按钮时在后台运行它 我用谷歌搜索了很多 但没有找到任何结果请帮助我实现这一目标 提前致谢 这是我的代码 public class Fullsc
  • 传递 null 时选择哪个构造函数?

    在下面的示例中 我有 2 个构造函数 一个采用 String 另一个采用自定义对象 在此自定义对象上存在一个方法 getId 该方法返回一个字符串 public class ConstructorTest private String pr
  • Ruby 中什么时候需要 do 关键字?

    例如 是否存在do下面的代码对程序的行为有什么影响 while true do puts Hi break end while true puts Hi break end 根据Ruby 编程语言本书第 5 2 1 节 The do中的关键
  • 如何在 SQL Server 中使用前导通配符全文搜索?

    Note I am使用 SQL 的全文搜索功能 CONTAINS 子句和所有 是全文中的通配符 仅适用于 LIKE 子句 我现在在几个地方读到 MS SQL 不支持 前导通配符 搜索 例如使用 overflow 来匹配 stackoverf
  • MongoDB v2.4.9 按布尔字段排序

    如何根据布尔字段对查询结果进行排序 考虑以下集合 id ObjectId name John isFoo true id ObjectId name Jim isFoo false id ObjectId name Joel isFoo f
  • 兼容 Nexus 的存储库,用于获取节点和 npm 安装程序

    我正在寻找一个符合 nexus 标准的存储库 我可以在其中获取节点安装程序 一个符合 nexus 标准的替代品 http nodejs org dist 语境 在java环境中 我们的构建是由maven处理的 最近我们添加了一个 javas
  • Delphi TGIFImage 与某些 GIF 查看器的动画问题

    我发现使用 Delphi 2009 创建的动画 GIFTGIFImage有时无法正确播放someGIF 观众 问题是动画过早地重新启动 考虑以下示例 program GIFAnomaly APPTYPE CONSOLE uses Windo