Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
177 changes: 177 additions & 0 deletions
177
_posts/2012-04-10-Making-Your-Own-GIF-Image-Macros.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.