Skip to content

Commit

Permalink
GIF tutorial post.
Browse files Browse the repository at this point in the history
  • Loading branch information
skeeto committed Apr 11, 2012
1 parent 50b39c3 commit 71344f1
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 0 deletions.
177 changes: 177 additions & 0 deletions _posts/2012-04-10-Making-Your-Own-GIF-Image-Macros.html
@@ -0,0 +1,177 @@
---
title: Making Your Own GIF Image Macros
layout: post
tags: [media, video, tutorial]
---

<p class="abstract">
This tutorial is very similar to my <a href="/blog/2011/11/28/">video
editing tutorial</a>. That's because the process is the same up until
the encoding stage, where I encode to GIF rather than WebM.
</p>
<p>
So you want to make your own animated GIFs from a video clip? Well,
it's a pretty easy process that can be done almost entirely from the
command line. I'm going to show you how to turn the clip into a GIF
and add an image macro overlay. Like this,
</p>
<p>
<img src="https://s3.amazonaws.com/nullprogram/calvin/calvin-macro.gif"
alt=""/>
</p>
<p>
The key tool here is going to be
<a href="http://www.lcdf.org/gifsicle/">Gifsicle</a>, a very excellent
command-line tool for creating and manipulating GIF images. So, the
full list of tools is,
</p>
<ul>
<li><a href="http://www.mplayerhq.hu/">MPlayer</a></li>
<li><a href="http://www.imagemagick.org/">ImageMagick</a></li>
<li><a href="http://www.gimp.org/">GIMP</a></li>
<li><a href="http://www.lcdf.org/gifsicle/">Gifsicle</a></li>
</ul>
<p>
Here's the source video for the tutorial. It's an awkward video my
wife took of our confused cats, Calvin and Rocc.
</p>
<p class="center">
<video src="https://s3.amazonaws.com/nullprogram/calvin/calvin-dummy.webm"
width="480" height="360" controls/>
</p>
<p>
My goal is to cut after Calvin looks at the camera, before he looks
away. From roughly 3 seconds to 23 seconds. I'll
have <code>mplayer</code> give me the frames as JPEG images.
</p>
<pre>
mplayer -vo jpeg -ss 3 -endpos 23 -benchmark calvin-dummy.webm
</pre>
<p>
This tells <code>mplayer</code> to output JPEG frames between 3 and 23
seconds, doing it as fast as it can (<code>-benchmark</code>). This
output almost 800 images. Next I look through the frames and delete
the extra images at the beginning and end that I don't want to
keep. I'm also going to throw away the even numbered frames, since
GIFs can't have such a high framerate in practice.
</p>
<pre>
rm *[0,2,4,6,8].jpg
</pre>
<p>
There's also dead space around the cats in the image that I want to
crop. Looking at one of the frames in GIMP, I've determined this is a
450 by 340 box, with the top-left corner at (136, 70). We'll need
this information for ImageMagick.
</p>
<p>
Gifsicle only knows how to work with GIFs, so we need to batch convert
these frames with ImageMagick's <code>convert</code>. This is where we
need the crop dimensions from above, which is given in ImageMagick's
notation.
</p>
<pre>
ls *.jpg | xargs -I{} -P4 \
convert {} -crop 450x340+136+70 +repage -resize 300 {}.gif
</pre>
<p>
This will do four images at a time in parallel. The
<code>+repage</code> is necessary because ImageMagick keeps track of
the original image "canvas", and it will simply drop the section of
the image we don't want rather than completely crop it away. The
repage forces it to resize the canvas as well. I'm also scaling it
down slightly to save on the final file size.
</p>
<p>
We have our GIF frames, so we're almost there! Next, we ask Gifsicle
to compile an animated GIF.
</p>
<pre>
gifsicle --loop --delay 5 --dither --colors 32 -O2 *.gif > ../out.gif
</pre>
<p>
I've found that using 32 colors and dithering the image gives very
nice results at a reasonable file size. Dithering adds noise to the
image to remove the banding that occurs with small color
palettes. I've also instructed it to optimize the GIF as fully as it
can (<code>-O2</code>). If you're just experimenting and want Gifsicle
to go faster, turning off dithering goes a long way, followed by
disabling optimization.
</p>
<p>
The delay of 5 gives us the 15-ish frames-per-second we want -- since
we cut half the frames from a 30 frames-per-second source video. We
also want to loop indefinitely.
</p>
<p class="center">
<img src="https://s3.amazonaws.com/nullprogram/calvin/calvin-dummy.gif"
alt=""/>
</p>
<p>
The result is this 6.7 MB GIF. A little large, but good enough. It's
basically what I was going for. Next we add some macro text.
</p>
<p>
In GIMP, make a new image with the same dimensions of the GIF frames,
with a transparent background.
</p>
<p class="center">
<img src="/img/gif-tutorial/blank.png" alt=""/>
</p>
<p>
Add your macro text in white, in the Impact Condensed font.
</p>
<p class="center">
<img src="/img/gif-tutorial/text1.png" alt=""/>
</p>
<p>
Right click the text layer and select "Alpha to Selection," then under
Select, grow the selection by a few pixels -- 3 in this case.
</p>
<p class="center">
<img src="/img/gif-tutorial/text2.png" alt=""/>
</p>
<p>
Select the background layer and fill the selection with black, giving
a black border to the text.
</p>
<p class="center">
<img src="/img/gif-tutorial/text3.png" alt=""/>
</p>
<p>
Save this image as text.png, for our text overlay.
</p>
<p>
<img src="/img/gif-tutorial/text.png" alt=""/>
</p>
<p>
Time to go back and redo the frames, overlaying the text this
time. This is called compositing and ImageMagick can do it without
breaking a sweat. To composite two images is simple.
</p>
<pre>
convert base.png top.png -composite out.png
</pre>
<p>
List the image to go on top, then use the <code>-composite</code>
flag, and it's placed over top of the base image. In my case, I
actually don't want the text to appear until Calvin, the orange cat,
faces the camera. This happens quite conveniently at just about frame
500, so I'm only going to redo those frames.
</p>
<pre>
ls 000005*.jpg | xargs -I{} -P4 \
convert {} -crop 450x340+136+70 +repage \
-resize 300 text.png -composite {}.gif
</pre>
<p>
Run Gifsicle again and this 6.2 MB image is the result. The text
overlay compresses better, so it's a tiny bit smaller.
</p>
<p>
<img src="https://s3.amazonaws.com/nullprogram/calvin/calvin-macro.gif"
alt=""/>
</p>
<p>
Now it's time to post it on reddit and reap that tasty, tasty karma.
</p>
Binary file added img/gif-tutorial/blank.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/gif-tutorial/text.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/gif-tutorial/text1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/gif-tutorial/text2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/gif-tutorial/text3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 71344f1

Please sign in to comment.