ImageMagick - 使用 IM 转换将 2 个 GIF 变成并排的 GIF

问题描述 投票:0回答:2

我有 2 个长度相同的 GIF。

我想将 GIF 放在一起,以获得 1 个 GIF,同时播放。我尝试使用

convert
工具:

convert +append 1.gif1 2.gif output.gif

但是,这似乎将所有图像混合在一起并将尺寸更改为非常小。

我想我可以将每个图像附加在一起,然后用这些已经组合的图像创建一个 GIF。然而,当我尝试时它不起作用:

convert -delay 15 -loop 0 1*.png 2*.png +append output.gif

我有很多名称很长的图像,我不想单独浏览并为每个图形附加新的命名约定。

image unix imagemagick imagemagick-convert
2个回答
29
投票

我没有 2 个相同长度的动画 GIF,所以我只使用这个的两个副本:

enter image description here

让我们看看里面的框架,如下:

identify 1.gif
1.gif[0] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[1] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[2] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[3] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[4] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[5] GIF 449x339 500x339+51+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[6] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[7] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[8] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[9] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[10] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[11] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[12] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[13] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[14] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[15] GIF 448x339 500x339+52+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[16] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000
1.gif[17] GIF 500x339 500x339+0+0 8-bit sRGB 32c 508KB 0.000u 0:00.000

嗯,18个不同大小的帧,这意味着我们需要使用

-coalesce
将部分帧重建为完整的帧。

让我们复制它并制作

2.gif

cp 1.gif 2.gif

现在我们可以将两个 gif 分割成它们的组件框架,如下所示:

convert 1.gif -coalesce a-%04d.gif     # split frames of 1.gif into a-0001.gif, a-0002.gif etc
convert 2.gif -coalesce b-%04d.gif     # split frames of 2.gif into b-0001.gif, b-0002.gif etc

现在让我们并排连接各个框架:

for f in a-*.gif; do convert $f ${f/a/b} +append $f; done

注意

${f/a/b}
是一个 bash-ism,意思是 “取 f 的值并将字母 'a' 替换为 'b'”

然后将它们再次放回一起:

convert -loop 0 -delay 20 a-*.gif result.gif

这看起来更长,更难,因为我试图解释这一切,但它看起来真的是这样的:

convert 1.gif -coalesce a-%04d.gif                         # separate frames of 1.gif
convert 2.gif -coalesce b-%04d.gif                         # separate frames of 2.gif
for f in a-*.gif; do convert $f ${f/a/b} +append $f; done  # append frames side-by-side
convert -loop 0 -delay 20 a-*.gif result.gif               # rejoin frames

enter image description here

请注意,这是概念性代码,而不是生产质量。它不会删除它创建的临时文件,也不会从原始 GIF 中向前移动帧间时间。如果您想获得原始帧速率,您可以像这样获取它们并将它们保存到数组中,然后将延迟反馈到最后的重新动画命令中:

identify -format "%f[%s] %T\n" 1.gif
1.gif[0] 8
1.gif[1] 8
1.gif[2] 8
1.gif[3] 8
1.gif[4] 8
1.gif[5] 8
1.gif[6] 8
1.gif[7] 8
1.gif[8] 8
1.gif[9] 8
1.gif[10] 11
1.gif[11] 11
1.gif[12] 11
1.gif[13] 11
1.gif[14] 11
1.gif[15] 11
1.gif[16] 11
1.gif[17] 26

此外,您可能需要在两个动画之间有一个间隔,例如 10 个像素,您可以通过将

convert
循环内的
for
命令替换为以下命令来实现:

convert $f -size 10x xc:none ${f/a/b} +append $f

enter image description here


0
投票

ffmpeg 单行,无需中间文件

ffmpeg 现在也可以处理 GIF,他按照以下命令并排连接两个 GIF,每个 GIF 的高度固定为 300 px:

ffmpeg \
  -i 1.gif \
  -i 2.gif \
  -filter_complex '
  [0]scale=-1:300[a];
  [1]scale=-1:300[b];
  [a][b]hstack
  ' \
  12.gif

我创建了测试输入 1.gif(480x,蓝色背景,2 秒)和 2.gif(640x,绿色背景,3 秒):

ffmpeg -y -f lavfi -i "
color=blue:480x480:d=2,
drawtext=
  fontcolor=black:
  fontsize=600:
  text='%{eif\:t\:d}':
  x=(w-text_w)/2:
  y=(h-text_h)/2
" 1.gif
ffmpeg -y -f lavfi -i "
color=green:640x640:d=3,
drawtext=
  fontcolor=black:
  fontsize=800:
  text='%{eif\:t\:d}':
  x=(w-text_w)/2:
  y=(h-text_h)/2
" 2.gif

该命令创建以下处理图:

1.gif --> [0] --> scale --> [a] --+
                                  |
                                  v
                                  hstack --> 12.gif
                                  ^
                                  |
2.gif --> [1] --> scale --> [b] --+
  • 首先,
    scale
    过滤器
    修改视频以将它们设置为相同的高度
  • 然后
    hstack
    过滤器
    获取那些缩放的中间视频并“水平堆叠”它们

正如我们所见,如果一个 GIF 比另一个长,该命令会在最后一帧停止最短的 GIF。

要改为将视频截断到最短视频的运行时间,我们可以添加

shortest=1
hstack
选项,如下所示:

ffmpeg -y -i 1.gif -i 2.gif -filter_complex '[0]scale=-1:300[a];[1]scale=-1:300[b];
  [a][b]hstack=shortest=1' 12-short.gif

或者,要垂直堆叠,我们可以使用

vstack
过滤器,并修复视频宽度而不是高度:

ffmpeg -y -i 1.gif -i 2.gif -filter_complex '[0]scale=300:-1[a];[1]scale=300:-1[b];
  [a][b]vstack' 12-vert.gif

© www.soinside.com 2019 - 2024. All rights reserved.