The ultimate tutorial to make your own GIF on GNU/Linux

Intro

There are already a lot of GIF available on the internet but often it's hard to get the one we're looking for or we find some with bad quality. So here a complete tutorial to see how we can make our own GIF on Linux.

Install tools

root@host:~# apt install imagemagick ffmpeg

Make a GIF

Extract a video to png files

user@host:~$ ffmpeg -ss 2:14 -t 6 -i /movies/1988.Rambo.III.MULTI.x264.1080p.mkv -vf fps=10,scale=320:-1 $filename%05d.png

Remove unwanted frames

Convert png files to one GIF file

user@host:~$ convert -loop 0 *.png myimage.gif

Enjoy the result

Sylvester Stallone in Rambo III movie putting his red ruban

Remove black bars

Some movies have black bars that you may want to remove.

Extract a video to png files

user@host:~$ ffmpeg -ss 8:26 -t 9 -i /movies/2000.American.Psycho.MULTI.AC3.1080p.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png

Crop files

user@host:~$ identify 00039.png
00039.png PNG 320x180 320x180+0+0 8-bit sRGB 79528B 0.000u 0:00.000
user@host:~$ convert -crop 320x130+0+25 00039.png +repage Cropped_00039.png
user@host:~$ for i in 000*; do convert -crop 320x130+0+25 "$i" +repage Cropped_"$i"; done

Make your GIF

user@host:~$ convert -loop 0 Cropped*.png myimage.gif

Enjoy the result

Christian Bale in American Psycho movie smiling

Add text to your GIF

Extract a video to png files

user@host:~$ ffmpeg -ss 19:24 -t 5 -i /movies/1998.The.Big.Lebowski.MULTI.1080p.Bluray.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png

Add text to a frame

user@host:~$ convert 00016.png -font Cantarell-Extra-Bold -gravity south -pointsize 30 -stroke black -fill white -strokewidth 1 -annotate +0+0 'YOU'\''RE\nAN ASSHOLE!!!' Text_00016.png
Jeff Bridges in The Big Lebowski movie, you're an asshole!

Add text to multiple frames

user@host:~$ for i in 000*; do cp "$i" Text_"$i"; done
user@host:~$ for i in 0001[6-9]*; do convert "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 30 -stroke black -fill white -strokewidth 1 -annotate +0+0 'YOU'\''RE\nAN ASSHOLE!!!' Text_"$i"; done
user@host:~$ for i in 0002[0-7]*; do convert "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 30 -stroke black -fill white -strokewidth 1 -annotate +0+0 'YOU'\''RE\nAN ASSHOLE!!!' Text_"$i"; done

Make your GIF

user@host:~$ convert -loop 0 Text_*.png myimage.gif

Enjoy the result

Jeff Bridges in The Big Lebowski movie, you're an asshole!

Play with text

We can also simulate text motion

Extract a video to png files

user@host:~$ ffmpeg -ss 16:43 -t 1 -i /movies/1993.groundhog.day.MULTI.1080p.bluray.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png

Add text

user@host:~$ a=-250;for i in 000*; do convert "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 35 -stroke black -fill white -strokewidth 1 -annotate -"$a"+0 'I'\''M THINKING...' Texted_${i}; ((a+=60)); echo "$a"; done
a=-250
for i in 000*
do 
	convert "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 35 -stroke black -fill white -strokewidth 1 -annotate -"$a"+0 'I'\''M THINKING...' Texted_${i}
	a=$((a+60))
	echo "$a"
done

Make your GIF

user@host:~$ convert -loop 0 Texted_*.png myimage.gif

Enjoy the result

Bill Murray in Groundhog Day movie, I'm thinking

Reduce GIF size

Depending on where you want to publish your GIF, size could matter. For example if I want to share GIF via MMS and keep source quality, size should be lower than 600Ko.

Let's see differents way to reduce our GIF.

With normal parameters

user@host:~$ ffmpeg -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1 $filename%05d.png
user@host:~$ convert -loop 0 00* myimage.gif
user@host:~$ du -sh myimage.gif
2,3M    myimage.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda

Use palettegen

user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
user@host:~$ du -sh output.gif
1,7M    output.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda http://blog.pkh.me/

Compress with fuzz parameter

It will reduce GIF size and output quality. Pretty good results with limited motions.

user@host:~$ convert myimage.gif -fuzz 2% -layers Optimize result.gif; du -sh result.gif
user@host:~$ du -sh result.gif
1,5M    result.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda
user@host:~$ convert myimage.gif -fuzz 5% -layers Optimize result.gif
user@host:~$ du -sh result.gif
720K    result.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda

Fuzz + palettegen

user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" out%05d.png
user@host:~$ convert -loop 0 out000* myimage.gif; du -sh myimage.gif
user@host:~$ convert myimage.gif -fuzz 2% -layers Optimize result.gif; du -sh result.gif
1,1M    result.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda
user@host:~$ convert myimage.gif -fuzz 5% -layers Optimize result.gif; du -sh result.gif
536K    result.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda

Reducing scale

We could also scale down our GIF

user@host:~$ for i in 00*; do convert "$i" -resize 240x Scalled_$i; done
user@host:~$ convert -loop 0 Scalled_000* myimage.gif; du -sh myimage.gif
1,3M	myimage.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda

Drop frames + Fuzz

user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" out%05d.png
user@host:~$ convert -delay 22 -loop 0 $(ls out000* | grep -E "*[02468].png") myimage.gif; du -sh myimage.gif
1,1M	myimage.gif
user@host:~$ convert myimage.gif -fuzz 5% -layers Optimize result.gif; du -sh result.gif
340K	result.gif
Samuel L. Jackson in Pulp Fiction movie, drinking soda
Licence Creative Commons
This website http://shebangthedolphins.net is licensed to the public under a licence Creative Commons Attribution licence.
Contact :