GIF 动图缩放后变成一团乱码
优化过的 GIF 只存局部帧,直接缩放会打乱动画。为什么 -coalesce 是必须的,以及正确的缩放与再优化流程。
你缩放了一个本来正常的 GIF 动图,结果是闪烁的碎片、拖影,或者看起来像原图被撕成条的帧。
为什么
优化过的 GIF 并不保存完整帧。第一帧之后,大部分帧只包含相对上一帧变化的那块矩形,外加一个说明贴在哪里的偏移。这正是 GIF 体积小的原因。
直接缩放这样的文件时,ImageMagick 会分别缩放这些碎片和它们的偏移,取整之后它们就对不齐了,动画随之崩掉。
解决
magick input.gif -coalesce -resize 320x -layers Optimize output.gif
三个部分缺一不可:
-coalesce把每一帧还原成完整图像,这样就没有会错位的局部矩形了。-resize此时作用于完整帧。-layers Optimize之后重新做帧优化。不加的话,文件可能比原来大好几倍。
所有 GIF 操作都适用同一条规则
magick in.gif -coalesce -crop 400x400+0+0 +repage -layers Optimize out.gif
magick in.gif -coalesce -colorspace Gray -layers Optimize out.gif
magick in.gif -coalesce -rotate 90 -layers Optimize out.gif
magick in.gif -coalesce frame_%03d.png
只要你要改动画的像素,先 coalesce。
-layers 的几个选项
| 选项 | 作用 |
|---|---|
-layers Coalesce | 等同 -coalesce,还原成完整帧 |
-layers Optimize | 完整优化:帧、透明和调色板 |
-layers OptimizeFrame | 只把每帧缩到变化区域 |
-layers OptimizeTransparency | 把未变化的像素设为透明 |
-layers RemoveDups | 去掉重复帧并合并它们的延迟 |
帧时间丢失了
如果处理后 GIF 播放速度不对,显式重设延迟。注意 coalesce 之后用 -set delay 是作用于所有帧的:
magick in.gif -coalesce -resize 320x -set delay 8 -layers Optimize out.gif
先看看原来是什么:
magick identify -format '%f[%s] %wx%h %Tcs\n' in.gif
%T 是每帧的延迟(百分之一秒)。变速 GIF 一旦设成单一值就会丢掉原有节奏 —— 如果这个重要,请逐帧处理再重新合成。
帧释放方式
如果帧留下拖影或者背景闪烁,是 dispose 方式不对。它控制画下一帧之前对当前帧做什么:
magick in.gif -coalesce -resize 320x -dispose Background \
-layers Optimize out.gif
None—— 保留当前帧Background—— 清成背景色Previous—— 还原成之前的内容
先 coalesce 再重新优化通常就能解决。只有残影依然存在时才需要手动设置。