.gif
ffmpegを使って画面を録画しました。少し圧縮しましたが、それでもgifsicle
かなり大きいですね。imagemagick
私の目標は、2フレームごとに1フレームを削除して、フレームの総数を半分に減らしてフレームを小さくすることです。
gifsicle
を使用または使用してこれを行う方法を見つけることができませんimagemagick
。man
ページは役に立ちません。
.gif
アニメーションのすべてのフレームからn
1つのフレームを削除する方法は?
答え1
おそらくより良い方法があります。しかし、私はこの方法を使います。
まず、アニメーションをフレームに分割します。
convert animation.gif +adjoin temp_%02d.gif
次に、小さなforループを使用してnフレームの1つを選択し、すべてのフレームを繰り返し2つに分割できることを確認し、次に新しい一時ファイルにコピーします。
j=0; for i in $(ls temp_*gif); do if [ $(( $j%2 )) -eq 0 ]; then cp $i sel_`printf %02d $j`.gif; fi; j=$(echo "$j+1" | bc); done
分割できないすべての数字を保持するには(つまり、n番目のフレームごとに保持せずに削除したい場合)-eq
に置き換えます-ne
。
完了したら、選択したフレームから新しいアニメーションを作成します。
convert -delay 20 $( ls sel_*) new_animation.gif
convert.sh
このような小さなスクリプトを簡単に作成できます
#!/bin/bash
animtoconvert=$1
nframe=$2
fps=$3
# Split in frames
convert $animtoconvert +adjoin temp_%02d.gif
# select the frames for the new animation
j=0
for i in $(ls temp_*gif); do
if [ $(( $j%${nframe} )) -eq 0 ]; then
cp $i sel_`printf %02d $j`.gif;
fi;
j=$(echo "$j+1" | bc);
done
# Create the new animation & clean up everything
convert -delay $fps $( ls sel_*) new_animation.gif
rm temp_* sel_*
その後、たとえば電話してください。
$ convert.sh youranimation.gif 2 20
答え2
代替バージョンがあります膜バイオリアクターbash関数としての答えは次のとおりです。
gif_framecount_reducer () { # args: $gif_path $frames_reduction_factor
local orig_gif="${1?'Missing GIF filename parameter'}"
local reduction_factor=${2?'Missing reduction factor parameter'}
# Extracting the delays between each frames
local orig_delay=$(gifsicle -I "$orig_gif" | sed -ne 's/.*delay \([0-9.]\+\)s/\1/p' | uniq)
# Ensuring this delay is constant
[ $(echo "$orig_delay" | wc -l) -ne 1 ] \
&& echo "Input GIF doesn't have a fixed framerate" >&2 \
&& return 1
# Computing the current and new FPS
local new_fps=$(echo "(1/$orig_delay)/$reduction_factor" | bc)
# Exploding the animation into individual images in /var/tmp
local tmp_frames_prefix="/var/tmp/${orig_gif%.*}_"
convert "$orig_gif" -coalesce +adjoin "$tmp_frames_prefix%05d.gif"
local frames_count=$(ls "$tmp_frames_prefix"*.gif | wc -l)
# Creating a symlink for one frame every $reduction_factor
local sel_frames_prefix="/var/tmp/sel_${orig_gif%.*}_"
for i in $(seq 0 $reduction_factor $((frames_count-1))); do
local suffix=$(printf "%05d.gif" $i)
ln -s "$tmp_frames_prefix$suffix" "$sel_frames_prefix$suffix"
done
# Assembling the new animated GIF from the selected frames
convert -delay $new_fps "$sel_frames_prefix"*.gif "${orig_gif%.*}_reduced_x${reduction_factor}.gif"
# Cleaning up
rm "$tmp_frames_prefix"*.gif "$sel_frames_prefix"*.gif
}
使用法:
gif_framecount_reducer file.gif 2 # reduce its frames count by 2