调整电影图谱(动画GIF)的问题

Jon*_*Ong 6 graphics image imagemagick image-processing graphicsmagick

我正在调整电影图谱的大小.如果您不知道,它们是GIF,其中只有一部分图像是动画的,而普通的GIF则是整个图像的动画.这是一个node.js示例:

// ![http://i.imgur.com/Qb1m0.gif][1]

var gm = require('gm')

var file = 'Qb1m0.gif',
    frags = file.split('.')

gm(file)
  //.noProfile()
  //.quality(80)
  .resize(200, 200)
  .write(frags[0] + '_200.' + frags[1], function(err) {
    if (err) console.error(err)
  })

// Result:
// ![http://i.imgur.com/eFqak.gif][2]
Run Code Online (Sandbox Code Playgroud)

等效的cmd行代码是:

gm convert Qb1m0.gif -resize 200x200 cinema_200.gif
Run Code Online (Sandbox Code Playgroud)

知道发生了什么事吗?

原创动画GIF:

原版的

调整大小的动画GIF:

调整大小

Kur*_*fle 19

我比ImageMagick更了解ImageMagick.对于ImageMagick,以下声明适用:

  • 如果GIF包含透明度,则几乎不可能使用简单的命令行(例如您给出的命令行)直接调整动画 GIF的大小.

  • 如果动画GIF不包含透明度,则甚至很难做到这一点.

我认为这对于GraphicsMagick来说是相同的.

背景说明

如果您查看原始GIF identify,您会发现并非每个框架都具有相同的尺寸:

identify Qb1m0.gif
 Qb1m0.gif[1]  GIF 720x416 720x416+0+0    8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[1]  GIF 471x122 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[2]  GIF 471x121 720x416+160+76 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[3]  GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[4]  GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[5]  GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[6]  GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[7]  GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[8]  GIF 471x122 720x416+160+76 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[9]  GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.009
 Qb1m0.gif[10] GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.000
 Qb1m0.gif[11] GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.000
 Qb1m0.gif[12] GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.000
 Qb1m0.gif[13] GIF 471x122 720x416+160+76 8-bit PseudoClass 256c 920KB 0.000u 0:00.000
 Qb1m0.gif[14] GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.000
 Qb1m0.gif[15] GIF 471x123 720x416+160+75 8-bit PseudoClass 256c 920KB 0.000u 0:00.000

尺寸的这些变化是对动画GIF 进行优化以减小文件大小的结果.

还有其他优化方法,它们确实减少了使用的颜色数量.这两种类型的优化都不能与-resize操作完美结合.

-resize专为单个图像而设计,并使得到的单个图像看起来尽可能好.这通常会为图像添加新的颜色值.这与GIF的设计相矛盾:使用严格限制的颜色表(最多256种颜色).在动画序列中,下一个图像/帧-resize可能会产生与前一个产生的颜色表完全不同的颜色表 - 但是对于运行良好的动画,您需要跨所有帧的共同颜色表.

-resize 处理每个帧图像与其他图像完全分开,并没有考虑"帧优化"(它们倾向于为每个放置在具有自己的偏移的公共画布上的帧创建不同的宽度+高度).

因此,调整大小的图像远非理想,不能保存单个图像的有限GIF文件格式,更不用说动画GIF的多个帧.结果是调整大小的图像中的重色减少.

然后是透明度问题:大多数动画GIF确实大量使用透明度.透明度经常用于甚至实现压缩优化,通常图像的外观根本不需要透明度.

在这种情况下会发生这种情况:-resize在叠加图像中创建半透明像素.当图像保存回GIF文件格式时,这些像素将转换为完全透明度或完全不透明度:两者都会对生成的动画产生严重的颜色失真,远离原始颜色.

一般程序

通常,调整动画GIF大小的最佳步骤是:

  1. 合并(去优化)动画.这将为动画的所有帧创建相同大小的单个图像.

  2. 为动画提供完整的GIF优化序列:不仅用于优化,还用于颜色优化.

'简单'命令

要运行'简单'调整大小命令仍然试试运气,你可以试试这个:

convert                        \
  http://i.imgur.com/Qb1m0.gif \
 -coalesce                     \
 -resize 200x200               \
  cinema_200.gif
Run Code Online (Sandbox Code Playgroud)

结果:

 结果

此命令将解决帧优化问题.它会纠正由此产生的问题,但会增加文件大小.

但是,当涉及到边缘时,它仍然可能会显示"阶梯"伪影,因为调整大小的帧会出现可怕的混淆.这是因为抗锯齿需要边缘周围的半透明颜色,但GIF无法保存-resize操作员生成的半透明颜色.