如何估计GIF文件的大小?

时间:2014-05-28 19:17:56

标签: image performance compression gif animated-gif

我们正在建立一个在线视频编辑服务。其中一项功能允许用户将视频中的短段导出为动画gif。 Imgur每个上传的动画gif都有file size limit 2Mb。

Gif文件大小取决于帧数,颜色深度和图像内容本身:坚固的平面颜色导致非常轻量级的gif,而一些随机颜色的电视噪声动画会非常沉重。

首先,我将每个视频帧导出为最终GIF帧大小的PNG(固定,384x216)。

然后,为了最大化gif质量,我进行了几次gif渲染尝试,参数略有不同 - 不同的帧数和gif调色板中的颜色数。在保持文件大小限制的情况下具有最佳质量的渲染会上传到Imgur。

每个渲染需要时间和CPU资源 - 我希望优化。

问题:根据实际图片估算最佳渲染设置的智能方法,尽可能接近文件大小限制,并至少最小化渲染尝试次数到2-3?

2 个答案:

答案 0 :(得分:7)

GIF图像格式使用LZW压缩。臭名昭着的算法专利Unisys的所有者,正如图像格式受欢迎一样积极地追求版税支付。结果很好,我们得到PNG感谢。

LZW压缩图像的数量非常不确定,并且很大程度上取决于图像内容。您最多可以为用户提供估计最终图像文件大小的启发式方法。例如,使用彩色条显示成功预测。只需转换第一帧,您就可以很快地为它着色。这不会花费很长时间在384x216图像上,这个图像在人类时间运行,只需几分之一秒。

然后将第一个图像的有效压缩率外推到后续帧。哪个应该只编码与原始帧的小差异,因此应具有可比较的压缩率。

在编码整个序列之前,您无法真正知道它是否超出了网站的大小限制。所以一定要在你的UI设计中强调你的预测只是一个估计,所以你的用户不会太失望。当然,为他提供了降低尺寸的工具,例如最近邻插值,使图像中的像素更大。专注于使后面的帧变得更小可以获得丰厚的回报,GIF编码器通常不会自己做得很好。 YMMV。

答案 1 :(得分:4)

对此没有简单的答案。单帧GIF大小主要取决于量化后的图像熵,您可以尝试使用stddev作为估计器,例如使用ImageMagick的:

identify -format "%[fx:standard_deviation]" imagename.png

通过在图像上运行平滑内核可以获得更好的结果,以消除一些不太可能是信息性的高频噪声,并且很可能会破坏压缩性能。无论如何,使用JPEG比使用GIF要好得多。

然后,一般来说,你想要运行大量样本以便提出类似的东西(假设你有一个压缩参数Q)

STDDEV   SIZE W/Q=1   SIZE W/Q=2    SIZE W/Q=3 ...
value1   v1,1         v1,2          v1,3

经过几十次测试后(但你只需一次,而不是"在运行时"),你会得到估计的,比方说,和测量其误差。然后你会看到当Q = 1时stddev 0.45压缩到108 Kb的图像,当Q = 2时压缩到91 Kb加或减5,当Q = 3时压缩到88 Kb加或减3,等等上。

此时你得到一个未知图像,得到它的stddev和压缩@ Q = 1,你可以在Q等于4时插入可能的大小,而不实际运行编码。

当您的服务处于活动状态时,您可以存储统计数据(即,真正进行编码后,存储实际结果)以进一步改进估算;毕竟,您只存储了一些数字,而不是视频中可能存在的任何潜在敏感或个人信息。获取和存储这些数字几乎是免费的。

背景

识别具有固定背景的图像可能是值得的;在这种情况下,您可以运行一些调整以使某些区域中的所有帧都相同,并且GIF动画算法不会存储该信息。这个如果你得到这样一个视频(例如一个说话的头),可能会带来巨大的节省(但是会完全抛弃参数估计的东西,除非你能做到估计背景区域的实际范围。在这种情况下,让这个区域为B,让框架区域为A,压缩的"图像"五帧的大小为A +(AB)*(5) -1)而不是A * 5,您可以将此修正系数应用于估算值。

压缩优化

然后有一些优化技术可以稍微修改图像并使其适应更好的压缩,但我们偏离了手头的主题。我有几种算法在调色板PNG上运行得非常好,在许多方面与GIF类似,但我需要检查是否以及哪些可以自由使用。

一些想法:LZW算法在中继续。因此,每当N个像素的序列是"小于X%"从已经遇到的序列中不同(感知或算术),重写序列:

     018298765676523456789876543456787654
     987678656755234292837683929836567273

这里第一行中的656765234序列几乎与第二行中的656755234序列匹配。通过将不匹配的5更改为6,LZW算法可能会拾取整个序列并将其存储为一个符号而不是三个(6567,5,5234)或更多。

此外,LZW使用,而不是字节。这意味着,非常粗略地说,0和1和1的平衡越多,压缩就越差。他们的序列越不可预测,结果越差。

因此,如果我们能找到一种方法使分配更加**对称,我们就赢了。

我们可以做到,我们可以无损地(同样适用于PNG)。一旦我们对其进行量化,我们就会选择图像中最常见的颜色。让那个颜色为颜色指数0.那就是00000000,八个零点。现在我们选择最常见的颜色,或者第二种最常见的颜色;我们给它索引1,即00000001.另一个零和一个。接下来的颜色将被索引为2,4,8,16,32,64和128;每个都只有一个位1,所有其他都是零。

由于颜色很可能遵循幂律分布,因此可以合理地假设大约20%的像素将使用前九种最常见的颜色进行涂漆;并且可以使20%的数据流至少为87.5%的零。其中大多数都是连续的零,这是LZW永远不会感激的东西。

最重要的是,这种干预是完全没有损失的;重新编制索引的像素仍然是相同的颜色,它只是相应移动的调色板。几年前我为PNG开发了这样一个编解码器,在我的用例场景(PNG街道地图)中,它产生了非常好的结果,压缩增加了约20%。使用更多不同的调色板和LZW算法,结果可能不太好,但处理速度快且不太难实现。