如何从静态图像创建动态GIF(最好使用命令行)?

我想从一组给定的.jpg图片中制作一个.gif动画图片。
最好能够通过命令行完成,所以命令行工具将非常受欢迎。

3工作,但非常占用内存。然而,有很多潜在的重复问题:http://askubuntu.com/questions/648244/how-to-create-gif-from-command-line http://askubuntu.com/questions/457351/are-there-softwares-available-on-ubuntu-for-the-conversion-of-a-series-of-image http://askubuntu.com/q/573712/178596 http://askubuntu.com/questions/566476/how-can-i-create-a-gif-out-of-a-sequence-of-png-files-without-the-previous-image http://askubuntu.com/questions/380875/loop-terminal-command-for-combining-png-to-gif-animation http://askubuntu.com/q/636149/178596 - Wilf
9个回答

你可以使用ImageMagick软件包。使用以下命令进行安装:
sudo apt-get install imagemagick

现在你可以使用以下方法从多张图片(jpg)创建一个gif:
convert -delay 20 -loop 0 *.jpg myimage.gif

11请在此处说明如何将 GIF 动画调整大小等,将其缩小 50%。例如:-resize 50% - Léo Léopold Hertz 준영
3Ubuntu 18.10在这些图片上出现“缓存资源耗尽”的错误:https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.zip?raw=true 相关链接:https://superuser.com/questions/1178666/imagemagick-convert-quits-after-some-pages - Ciro Santilli OurBigBook.com
ImageMagick的用户可能还需要使用-deconstruct选项。我还发现ImageMagick非常占用内存,可以参考这些基准测试:https://askubuntu.com/a/1102183/52975 - Ciro Santilli OurBigBook.com
convert -delay 0 -loop 0 *.tif myanimated.gif 运行得很好,处理了720个tif文件。 - ron
厉害,你可以根据需要调整延迟时间。 - sh6210

为了补充@Maythux的回答:
为了避免生成一个非常大的文件,你可以使用“-resize”选项:
在我的情况下,我有4608x3456像素的图片,生成的gif文件超过了300M,包含32张图片。
convert -resize 20% -delay 20 -loop 0 *.jpg myimage.gif

或者

convert -resize 768x576 -delay 20 -loop 0 *.jpg myimage.gif

处理 *.jpg 的注意事项

*.jpg 在处理数值时有些不太理想,你可以生成一个包含未排序图片的 gif。

$ ls|cat
21-33-26_1.jpg
21-33-26_10.jpg   // <--- this one
21-33-26_2.jpg
21-33-26_3.jpg
21-33-26_4.jpg
21-33-26_5.jpg
21-33-26_6.jpg
21-33-26_7.jpg
21-33-26_8.jpg
21-33-26_9.jpg
21-33-28_1.jpg    // <--- should be here    
21-33-28_2.jpg
21-33-28_3.jpg
...

由于快速拍摄(每秒10张),所有照片的修改时间都相同,因此无法使用“ls -t”等方法进行欺骗。在Ubuntu上,您可以使用“ls -v”代替,类似于:
convert -resize 768x576 -delay 20 -loop 0 `ls -v` myimage.gif

在Mac OS X上进行数字排序是相当棘手的,我猜你需要编写一个自定义脚本。

8你可以通过在数字前面填充零来避免你的*.jpg问题。例如,使用"01.jpg"而不是"1.jpg",以此类推。如果你达到三位数,那么使用"001.jpg"、"010.jpg"等。 - bigreddmachine
2解决文件名序列问题有几种方法。包括使用findsort、花括号扩展等等。ls工具在这种情况下并不适用。请使用find命令。虽然需要一些学习曲线,但是它是值得的。 - voices
一些用户可能对使用massren来编辑文件名感兴趣:https://github.com/laurent22/massren - Graham P Heath
完成需要很长时间。有没有详细选项? - ouranos
如果输入具有透明背景,我还建议使用-dispose Background选项。(我意识到OP的帖子是关于不能具有透明背景的JPEG图像,但以防万一有人通过谷歌找到这个答案,就像我一样)。顺便说一下,关于ls排序,你可以在内联中进行一些bash脚本的操作,例如:$(for f in \seq 0 10`; do printf "21-33-26_$f.jpg\n"; done)`。 - Daniel

ffmeg解决方案 + 测试数据

从Ubuntu 18.10开始,ffpmeg 4.0.2-2,ImageMagick 6.9.10-8,我发现ffmpeg比ImageMagick快得多,并且使用的内存要少得多

最简单的转换命令是:

ffmpeg \
  -framerate 60 \
  -pattern_type glob \
  -i '*.png' \
  -r 15 \
  -vf scale=512:-1 \
  out.gif \
;

您可以通过以下方式获取我的测试数据:
wget -O opengl-rotating-triangle.zip https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.zip?raw=true
unzip opengl-rotating-triangle.zip
cd opengl-rotating-triangle

测试数据是使用以下链接生成的:https://stackoverflow.com/questions/3191978/how-to-use-glut-opengl-to-render-to-a-file/14324292#14324292,包含256个1024x1024的PNG图像。
这里还有另一组测试数据,您可以直接在浏览器中生成!https://stackoverflow.com/questions/19235286/convert-html5-canvas-sequence-to-a-video-file/57153718#57153718

enter image description here

我要强调的ffmpeg重要选项是:

  • -pattern_type glob:方便地选择图像

  • -framerate 60:假定输入图像为60 FPS,并输出相同的FPS。

    ffmpeg无法知道否则,因为图像中没有像视频格式中那样的FPS数据。

    256个输入帧需要约4秒钟才能完成。

    -r 15:可选。每4个图像中挑选一个以缩小大小(4 == 60 / 15)。

    使用它,identify out.gif表明GIF仅包含64帧。

    仍然需要4秒才能播放,因此延迟被改变以使事物匹配。

  • -vf scale=512:-1:可选。设置宽度,按比例缩放高度,通常是为了减小大小并节省空间。

另请参阅:

ImageMagick与ffmpeg性能对比

为了让ImageMagick正常工作,我首先需要修改其在/etc/ImageMagick-6/policy.xml中的磁盘和内存限制,具体方法请参考:https://superuser.com/questions/1178666/imagemagick-convert-quits-after-some-pages

我进行了以下命令的比较:

/usr/bin/time -v convert *.png -deconstruct -delay 1.6 out-convert.gif
/usr/bin/time -v ffmpeg \
  -framerate 60 \
  -pattern_type glob \
  -i '*.png' \
  out-ffmpeg.gif \
;

命令的构建旨在产生尽可能接近的输出,以使比较有效。
  • /usr/bin/time -v:用于查找最大内存使用量,如https://stackoverflow.com/questions/774556/peak-memory-usage-of-a-linux-unix-process所述。

  • -deconstruct:GIF图像可以只包含前一帧的最小修改矩形,以使GIF文件更小。

    ffmpeg默认计算这些差异,但ImageMagick不会,除非使用-deconstruct选项。

    您基本上希望每次在ImageMagick中使用该选项。

    我们可以通过以下方式观察到差异:

    identify out.gif
    

    在压缩版本中,所有帧的大小都小于初始帧,例如:

    out.gif[0] GIF 1024x1024 1024x1024+0+0 8-bit sRGB 256c 16.7865MiB 0.010u 0:00.010
    out.gif[1] GIF 516x516 1024x1024+252+257 8-bit sRGB 256c 16.7865MiB 0.010u 0:00.010
    out.gif[2] GIF 515x520 1024x1024+248+257 8-bit sRGB 256c 16.7865MiB 0.010u 0:00.010
    

    在此示例中,第二帧仅为516x516,而不是完整的1024x1024,并且位于偏移量252+257处。因此,它只包含中间的三角形。

    另请参阅:how can I resize an animated GIF file using ImageMagick?

  • -delay:与ffmpeg的60FPS相匹配的值。对于转换性能来说应该没有影响,但我不想冒险。

输出的GIF文件大小大致相同,并且在视觉上看起来完全一样。
我们使用ImageMagick获得的结果是:
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:56.16
Maximum resident set size (kbytes): 2676856

并且对于ffmpeg:
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:04.41
Maximum resident set size (kbytes): 97172

从中我们可以看到:
- ImageMagick使用了2.6GB的内存,耗时约1分钟 - ffmpeg使用了100MB的内存,耗时4秒
测试硬件:联想ThinkPad P51笔记本电脑,Intel Core i7-7820HQ处理器,32GB(16+16) DDR4 2400MHz SODIMM内存,512GB SSD PCIe TLC OPAL2。

2点赞和喜欢!很棒的回答,我有一个小问题要追问。我的图片质量不是很高,而且我没有使用-r-v命令,但生成的gif文件质量比原始的png文件低得多。如何保持gif与给定的png文件相同的质量? - BhishanPoudel
嗨 @astro123,质量为什么会降低呢?图片的尺寸变小了吗,还是帧数减少了,或者有其他原因(GIF 使用无损压缩,所以压缩应该不会更差)?试试使用 -framerate 60 -r 60。使用 ImageMagick 工具像 identify 来检查生成的 GIF 和输入图像,看看到底发生了什么问题。 - Ciro Santilli OurBigBook.com
1我强烈推荐使用palettegenpaletteuse以获得更好的质量和更小的文件大小,例如使用-filter_complex "[0:v] split [a][b];[a] palettegen [p];[b][p] paletteuse"。参见:giphy engineering。另外,请注意FFmpeg不支持透明背景,这对于制作动画表情等非常重要。 - Daniel

不必修改文件名,你可以使用通配符来让你的shell自动展开文件名。
convert -resize 50% -delay 10 -loop 0 image_{0..99}.jpg output.gif

GIMP

你可以轻松地使用GIMP来完成这个任务。如果尚未安装,请先安装它。

sudo apt-get install gimp

制作gif动画

从GIMP中选择文件 -> 作为图层打开,将所有的png文件分别打开到各自的图层上。

Open as Layer

从这里您可以对图层进行编辑,完成后转到文件 -> 导出为。在对话框中确保将文件类型设置为GIF。

Set file type to GIF

从那里,您将进入GIF导出选项。勾选“作为动画”选项,并根据需要设置参数。

GIF export options

更改帧之间的延迟
修改图层名称,并在括号中包含以毫秒为单位的延迟时间,例如:(1500ms)

enter image description here

在导出之前预览动画

点击“滤镜”菜单,然后选择“动画”,再选择“动画播放”。


命令行优先。 - Gathide

你可以使用一个叫做convert的程序,它包含在imagemagick软件包中。它是命令行驱动的,但非常易于使用。你可以通过软件中心安装它,或者打开命令提示符并输入相应命令来安装。
sudo apt-get install imagemagick

现在开始创建 .gif 文件。
convert -delay 100  -size 100x100 xc:SkyBlue \
          -page +5+10  balloon.gif   -page +35+30 medical.gif  \
          -page +62+50 present.gif   -page +10+55 shading.gif  \
          -loop 0  animation.gif

*请注意,上述示例直接来自Image Magick Examples

1如何将一个文件夹中的40个PNG图像制作成循环GIF?文件夹路径为/home/fusion809/Documents/Images。 - Josh Pinto
3@BH2017:convert -delay 20 -loop 0 *.png out.gif 可以制作一个循环播放的 GIF。 - unutbu

补充一点,你可能会得到一个巨大的GIF文件,使用提供的“convert”变体。
正如StackOverflow上的this回答所述,最好使用以下方法对生成的GIF进行优化。
mogrify -layers 'optimize' -fuzz 7% mygif.gif

通过这个方法,我得到的大小只有原始大小的1/50。

我在使用分配给ImageMagick的资源时遇到了一些问题。如果是这种情况,这篇帖子可能会有所帮助。


我建议您使用相同的转换命令,但是在添加下一帧之前,请确保包含-dispose Background以清除画布。具体如下所示:
convert -delay 100 -dispose Background -loop 0 *.jpg animation.gif

只需在命令行上使用ffmpeg,它已经预装在Ubuntu、Kubuntu、Debian和其他Linux系统上。
ffmpeg -f concat -i list.txt output.gif

你的list.txt文件应该按照以下方式排列:
image001.jpg
duration 5
image002.jpg
duration 12
image003.jpg
duration 7
image004.jpg
duration 2