GIF规范中“背景色指数”的解读

Posted

技术标签:

【中文标题】GIF规范中“背景色指数”的解读【英文标题】:Interpretation of "background colour index" in GIF specification 【发布时间】:2018-06-09 12:06:43 【问题描述】:

如果您查看GIF specification 并搜索“背景颜色索引”,您会看到以下描述:

vii) 背景颜色索引 - 全局颜色表中的索引 背景颜色。背景颜色是用于那些 屏幕上未被图像覆盖的像素。如果全球 颜色表标志设置为(零),该字段应为零并且 应该忽略。

这里有一个歧义,如果“全局颜色表标志”设置为零并且忽略此字段,那么如果图像数据本身没有,则不确定 GIF 的实际背景颜色应该是什么覆盖整个图像区域。这是可能的,因为每个图像数据块都独立指定左/右/宽/高,并且不要求每个像素都必须由图像数据编码。

我误解了吗?如果不是,那么在这种模棱两可的情况下,当今 GIF 实现的实际行为是什么?

【问题讨论】:

【参考方案1】:

例如,Safari 使用黑色作为背景。使用 Win10 照片查看器很难分辨,因为它无论如何都使用黑色背景。 Chrome、IE 和 Edge 使用白色。 当没有背景颜色并且您需要背景颜色时,规范没有定义行为,所以我想您会得到任意选择,尽管我投票赞成透明是最明智的。

【讨论】:

(这篇文章似乎没有为问题提供quality answer。请编辑您的答案,或者将其作为对问题的评论发布)。【参考方案2】:

解码器(包括一些现代浏览器)经常忽略背景颜色索引,而 GDI+(例如 Windows Paint 或 .NET WinForms 控件)尊重它。 GDI+ 是这样处理的:

如果没有全局调色板,OR第一帧是透明的(在图形控件扩展中设置了透明颜色标志),那么背景是透明的 如果有全局调色板并且第一帧没有透明度(第一帧没有图形控制扩展,或者没有为它设置透明颜色标志),那么这意味着来自全局调色板的颜色索引,仅当第一个图像未覆盖整个虚拟屏幕区域时,或者为帧设置“恢复为背景颜色”处理方法时才有意义。在后一种情况下,可能存在的本地调色板是否不包含背景颜色并不重要。

为了演示它的效果,我用my encoder 创建了一个简单的两帧动画,然后使用一些设置进行播放(请随意下载图像并在文件查看器中查看它们的内容,因为我在文件中添加了一些文本提示)。您可以使用this app 在使用 GDI+ 渲染的 Win32 应用程序中查看动画。

常用属性:

所有图像都有一个全局调色板,因此可以设置背景颜色。 背景颜色设置为绿色。 虚拟屏幕尺寸为 64x64 像素 第一帧为 48x48 像素 第二帧是 32x32 像素
The animation rendered by your browser The 2nd frame by GDI+ Description
None of the frames are transparent, there is no clear.
Both frames are transparent, there is no clear.
Only the 2nd frame is transparent, there is a clear after the first frame.

【讨论】:

AFAICS 微软再次参与其中,打破了事实标准。 我不会比其他人更尊重规范(顺便说一句,这是模糊的)的“破坏”。与现代浏览器不同,它可以区分动画和多层静止图像。我认为这个故事的寓意是,在当今的应用程序或网络使用中,不应依赖背景颜色索引。 以防万一:我完全同意将 0ms 延迟视为单个帧的一部分。然而,绝大多数 GIF 解码器并非如此。问题是,即使对标准的某些解释感觉比共识解释更正确,通常也不鼓励实施前者而不是后者,除非用户混淆是期望的结果。 其实它也有点复杂(因为一切都具有事实上的标准)。有 examples 应该设置 0 个延迟。 GDI+(或者更准确地说,WIC GIF 解码器)处理它非常有效:如果没有NETSCAPE 应用程序扩展,那么 0 延迟确实意味着没有延迟;否则,使用默认的 100 毫秒。无论如何,浏览器倾向于将零解释为 100 毫秒的延迟。【参考方案3】:

是的,确实存在歧义。背景颜色在很大程度上是 GIF87a 的遗弃,目前仅用于“恢复背景”帧混合模式。

到目前为止,我见过的所有解码器都将不属于任何帧的像素视为透明的,即使所有帧中的透明度标志都为零。

考虑这个 GIF,例如:

看看您的浏览器是如何解释它的?整个背景是透明的。

P.S.:如果没有循环,请使用 Ctrl+F5 重新加载页面。

【讨论】:

“整个背景都是透明的” - 不,这张图片不使用透明度。所有帧都使用GCE_DISPOSAL_INPLACE 处理控制代码来防止清除帧之间的图像。 “万一它不循环” - 它不能循环,因为它甚至不包含NETSCAPE2.0 扩展。实际上它根本不应该被动画化(所有帧都有 0 延迟,大多数浏览器将其解释为 100 毫秒,但没有重复信息,这些应该被解释为图层而不是动画帧)。 Paint 可以正确处理它,一次显示整个高彩色图像。 @GyörgyKőszeg 1. 好的,所以图像不使用透明度,但是如何在渲染时通过它看到背景?一定是奇迹。 2. 错误,所有动画 GIF 默认无限循环,早在 Netscape 引入其自定义扩展之前就是这种情况。 3. 声明的标准和事实上的标准有区别——例如: GIF 图形控件扩展标头包含一个特殊标志,允许 GIF 要求用户输入以继续下一帧,但现在没有人尊重该标志。 不用客气,我也没有失礼。这是一个众所周知的高彩色 GIF 示例,与透明度无关。 GDI+ 正确处理它,因此如果您在 Paint 中打开它,整个图像会立即显示(但尝试打开动画 GIF,您将只看到第一帧)。如果浏览器对其进行动画处理,您会看到一个透明的背景,直到整个虚拟屏幕区域都被填满,因为没有全局调色板。但问题是关于背景颜色索引,而不是透明度(有关详细信息,另请参阅我的答案)。 @GyörgyKőszeg 如果您不认为 Microsoft 所做的任何事情(包括 GIF)的实现都是可行的,我永远不会“粗鲁”。自成立以来,MS 因不断推动其他实现“过时”而打破事实标准而臭名昭著。拥抱、扩展、消灭。

以上是关于GIF规范中“背景色指数”的解读的主要内容,如果未能解决你的问题,请参考以下文章

css 背景色如何平铺

纯CSS实现四种方式文本反差色效果

Android开发怎么让自己的APP UI漂亮大方(配色篇二)

初学c# -- 学习笔记

canvas一段背景色鼠标移入后

怎么把图片背景变成透明