The Alphabet of Nations

How to create an animated GIF from a sequence of scanned JPG images in the Linux Terminal

Elizabeth Wotawa

@PenguinPhoenixE

Before we get into the technical details of this article, I need to tell you one thing: I am a They Might be Giants fan.

A t-shirt wearing, concert-going, lyric-memorizing, cubicle-dance-party-throwing fan. Jumping around to The Guitar is a great way to blow off steam after a few hours of overtime. Be careful not to scare the cleaning crew, though.

So, naturally, when KMSU 89.7 FM announced their annual They Might be Playing They Might be Giants marathon, I got excited. Even better, there was a coloring contest:

WITH PRIZES:

As I looked at the two templates, I worked my way through the TMBG songbook for inspiration. John Linnell came out with a great album called State Songs when I was in college, but I couldn't quite figure out how to get the melodies to fit with the map of the United States. I then thought of another TMBG song from Here Come the ABCs: The Alphabet of Nations.


I hope you like the song. If you're anything like me, you'll be singing it to yourself for the next month.

Now this song had potential. I had the option of a world map template. I started to identify the countries and to incorporate their names into the design. As I was going, I realized that the design would be a lot more fun for the viewer if he or she could follow along with the melody. Hence the purpose of this article: how to use ImageMagick and Gifsicle on the Linux command line to create an animated GIF from scanned JPG images.

The Setup

I really did want to color the template for the contest, but I also wanted to honor the tech theme of my Twitter handle. I settled on a hybrid approach:

  • Color the image by hand.
  • Scan the document as I complete each colored component.
  • Animate the series of scans as an animated GIF.

I started with JPG images due to a hardware limitation: my scanner can only save to PDF or to JPG.

Image Reformatting

The first step is to convert the images into a GIF format so that they can be consolidated into the animation. I decided to use ImageMagick, an open-source software suite for working with image files, to convert my JPG scans into the GIF format. I recently purchased a new computer and thus was working with a fresh install of ImageMagick. You can follow along with my install process in the TecMint article, How to Install ImageMagick 7 on Debian and Ubuntu.

After opening a new terminal, I used the cd command to navigate into the folder where I stored my images.

I used the ls command to confirm that I was working in the correct folder.

            ~/Documents/alphabet$ ls
            00_the.JPG          13_japan.JPG        26_w_xylophone.JPG
            01_alphabet.JPG     14_kazakhstan.JPG   27_yemen.JPG
            02_of.JPG           15_libya.JPG        28_zimbabwe.JPG
            03_nations.JPG      16_mongolia.JPG     29_tmbp_outline.JPG
            04_algeria.JPG      17_norway.JPG       30_tmbg_outline.JPG
            05_bulgaria.JPG     18_oman.JPG         31_kmsu.JPG
            06_cambodia.JPG     19_pakistan.JPG     32_spirals.JPG
            07_dominica.JPG     20_qatar.JPG        33_tmbp_fill.JPG
            08_egypt.JPG        21_russia.JPG       34_tmbg_fill.JPG
            09_france.JPG       22_suriname.JPG     35_final.JPG
            10_the_gambia.JPG   23_turkey.JPG
            11_hungary.JPG      24_uruguay.JPG
            12_iran.JPG         25_vietnam.JPG

I then entered ImageMagick's convert command to iterate through each JPG image in the folder and create a copy in GIF format:

~/Documents/alphabet$ convert *.jpg %d.gif

* is a wildcard that will read all files with the JPG extension in the path referenced on the command line. %d is a wildcard that will assign a unique name to each new GIF file.

The Error

Unfortunately, there was a small wrinkle in my process. Rather than returning a series of GIF files, my terminal returned the following error message:

            convert: unable to open image '*.jpg': No such file or directory @ error/blob.c/OpenBlob/3497.
            convert: no decode delegate for this image format `JPG' @ error/constitute.c/ReadImage/561.
            convert: no images defined `*.gif' @ error/convert.c/ConvertImageCommand/3273.

After some digging, Googling, and sifting through Stack Overflow, I stumbled upon the following command:

~/Documents/alphabet$ convert -list format

The command returns a list of the file formats that ImageMagick supports. I have included a copy of the table at the end of the article for reference.

I was impressed at how thorough the list was. However, when I scrolled down to the J section, I realized why ImageMagick was throwing the error. ImageMagick does not support JPG file formats out of the box. Their supported formats page offered some insight. To use files in a JPG format, I would need to install an additional package, jpegsrc.v8c.tar.gz, then reinstall ImageMagick.

The format of the tarball for JPG format support looked very similar to the one I had just used to install ImageMagick. I decided to try the same install method for JPG image support as I had for ImageMagick itself.

JPG Format Support Package for ImageMagick

I used the following process to install JPG format support for ImageMagick on my machine. More information about the package is available on its Web site.

Get to the correct directory location

I had been working in the folder with my images when I encountered the error, so I needed to get back to base directory before I could continue with the install. cd .. is a common terminal command for this task, and one I use when I don't want to open a new terminal window.

Install updates

I next executed the following steps to ensure that my version of build-essential was up-to-date:

            $ sudo apt update
            $ sudo apt-get install build-essential

Download and decompress the tarball

I downloaded a copy of the tarball to my machine:

$ wget http://www.ijg.org/files/jpegsrc.v8c.tar.gz

A tarball is a compressed file format, similar to a ZIP file. I therefore needed to decompress the tarball before installing the package:

$ tar xvzf jpegsrc.v8c.tar.gz

Configure the package

The ls command on my working directory showed a new folder, jpeg-8c. I used the cd command to move into this directory:

$ cd jpeg-8c

I then ran the configure, make, and install commands shown below:

            ~/jpeg-8c$ ./configure
            ~/jpeg-8c$ make
            ~/jpeg-8c$ sudo make install
            ~/jpeg-8c$ sudo ldconfig /usr/local/lib  

Reinstall ImageMagick

Now that I had JPG format support, I needed to re-install ImageMagick so that the program would recognize the new package. Again, I'd recommend the TecMint article I referenced above.

I can haz JPG?

Before I went any further, I wanted to make sure that ImageMagick would now understand the JPG file format. I ran the ImageMagick command again to show the supported format list.

$ convert -list format

I found a few updates.

            Format              Mode  Description
            -------------------------------------------------------------------------------
            JNX*                r--   Garmin tile format
            JPE*                rw-   Joint Photographic Experts Group JFIF format (libjpeg 80)
            JPEG*               rw-   Joint Photographic Experts Group JFIF format (libjpeg 80)
            JPG*                rw-   Joint Photographic Experts Group JFIF format (libjpeg 80)
            JPS*                rw-   Joint Photographic Experts Group JFIF format (libjpeg 80)
            JSON                -w+   The image format and characteristics

Now I could continue with my image format conversion exercise.

Image Reformatting, Take 2

I navigated back to the folder where I had stored my JPG scans, and I attempted to run the convert command again.

~/Documents/alphabet$ convert *.jpg %d.gif

This time the command ran without error. A quick look at the directory revealed twice as many files as I had previously: the original list of JPG files and an enumerated list of GIF files. I moved each file type into its own directory before continuing forward. For the next step of the process, I'd be working with just the GIF images.

            ~/Documents/alphabet/gif$ ls
            0.gif   13.gif  17.gif  20.gif  24.gif  28.gif  31.gif  35.gif  6.gif
            10.gif  14.gif  18.gif  21.gif  25.gif  29.gif  32.gif  3.gif   7.gif
            11.gif  15.gif  19.gif  22.gif  26.gif  2.gif   33.gif  4.gif   8.gif
            12.gif  16.gif  1.gif   23.gif  27.gif  30.gif  34.gif  5.gif   9.gif

Animate the GIF

Now that I had a sequence of GIF files, I could use the Gifsicle application to merge them into an animated GIF.

GIF Animation in ImageMagick

I realized by accident that ImageMagick also can create animated GIFs. If you want a quick preview of how the animated GIF will look, you can use the convert command to merge the images into a single file:

~/Documents/alphabet$ convert *.jpg animation.gif

However, I wanted more control over several details in the animation. I found an article by Himanshu Arora, How to Create and Edit Animated GIFs from the Command Line in Ubuntu. I will walk you through the steps relevant to my project below, but I recommend Arora's work for a more comprehensive introduction.

Getting Started with Gifsicle

Gifsicle is a command-line tool for creating, editing, and getting information about GIF images and animations.

I returned to my root directory using the cd .. command. I entered the following command to install the program:

$ sudo apt-get install gifsicle

Prep the GIF files

I navigated to the directory where I had stored my GIF images. I made a few final edits before I began working with Gifsicle:

  • Ordered my images. I prefixed all of the ordinal numbers so that they were the same length: represent 1 as 01 if your largest number is 99 or lower, 001 if your largest number is 100 or higher, e.g.
  • Duplicated a few images. If you listen to The Alphabet of Nations, some of the country names receive two beats while others receive one. I wanted folks to be able to sing along to the rhythm of the GIF, so I made copies of the appropriate country images to match the rhythm of the song.

Create the Animated GIF

I used the command below to generate my first animated GIF file.

~/Documents/alphabet/gif$ gifsicle --delay=100 loopcount=forever *.gif>alphabet_of_nations.gif

The command breaks down into a few components:

  • gifsicle initiates the command.
  • --delay tells Gifsicle how many hundredths of a second each image in the animated GIF should appear.
  • loopcount=forever tells Gifsicle that I want the images to loop continuously rather than stopping at the end of one or more sequences.
  • *.gif tells Gifsicle that I want to include all files with the .gif extension in my working directory in the animated GIF.
  • alphabet_of_nations.gif is the name of the animated GIF file.

You can read more about these options on Gifsicle's man (manual) page. You can access the man pages one of two ways:

  • On the web. The author of Gifsicle included the man pages on Gifsicle's Web page.
  • In the terminal. Enter the command man gifsicle to return the same information in the terminal.

Fine-Tune the Animated GIF

The first refinement I made to the animated GIF involved the --delay option: I wanted the pace of the GIF to approximate the tempo of the song. I settled on a delay of 80.

Satisfied with the outcome, I tried to upload the file to Twitter to submit my image for the #TheyMightBeColoring competition. That's when I found out that Twitter has a file size limit. Animated GIFs can be up to 5MB on mobile and up to 15MB on web. Yeah, that animated GIF was HUGE since I had started with so many scanned images.

Fortnuately, Gifsicle has a few options that facilitate file compression. I chose to work with scale, optimize, and colors.

  • scale adjusts the size of the image. I decided to reduce mine by half.
  • optimize optimizes the animated GIF for space.
  • colors reduces the number of colors in the output GIF to no more than the number specified in the command. Because I had scaled down the image, I had space for 256 colors.

After these adjustments, my final Gifsicle command looked as follows:

~/Documents/alphabet/gif$ gifsicle --delay=80 --colors 256 --scale 0.5 --optimize *.gif > alphabet_of_nations_opt_256.gif

The final file size was 5.8MB, which meant that I could upload it to Twitter.

I Might be Coloring

The last step was to submit my animated GIF to the coloring contest.

You're singing along, aren't you? So am I.

Additional Resources

Below are a few additional resources you can consult if you'd like to make your own animated GIF.


ImageMagick Supported Image Formats

            Format              Mode  Description
            -------------------------------------------------------------------------------
            3FR                 r--   Hasselblad CFV/H3D39II
            3G2                 r--   Media Container
            3GP                 r--   Media Container
            A*                  rw+   Raw alpha samples
            AAI*                rw+   AAI Dune image
            AI                  rw-   Adobe Illustrator CS2
            ART*                rw-   PFS: 1st Publisher Clip Art
            ARW                 r--   Sony Alpha Raw Image Format
            AVI                 r--   Microsoft Audio/Visual Interleaved
            AVS*                rw+   AVS X image
            B*                  rw+   Raw blue samples
            BGR*                rw+   Raw blue, green, and red samples
            BGRA*               rw+   Raw blue, green, red, and alpha samples
            BGRO*               rw+   Raw blue, green, red, and opacity samples
            BMP*                rw-   Microsoft Windows bitmap image
            BMP2*               rw-   Microsoft Windows bitmap image (V2)
            BMP3*               rw-   Microsoft Windows bitmap image (V3)
            BRF*                -w-   BRF ASCII Braille format
            C*                  rw+   Raw cyan samples
            CAL*                r--   Continuous Acquisition and Life-cycle Support Type 1
                Specified in MIL-R-28002 and MIL-PRF-28002
            CALS*               r--   Continuous Acquisition and Life-cycle Support Type 1
                Specified in MIL-R-28002 and MIL-PRF-28002
            CANVAS*             r--   Constant image uniform color
            CAPTION*            r--   Caption
            CIN*                rw-   Cineon Image File
            CIP*                -w-   Cisco IP phone image format
            CLIP*               rw+   Image Clip Mask
            CMYK*               rw+   Raw cyan, magenta, yellow, and black samples
            CMYKA*              rw+   Raw cyan, magenta, yellow, black, and alpha samples
            CR2                 r--   Canon Digital Camera Raw Image Format
            CRW                 r--   Canon Digital Camera Raw Image Format
            CUBE*               r--   Cube LUT
            CUR*                rw-   Microsoft icon
            CUT*                r--   DR Halo
            DATA*               rw+   Base64-encoded inline images
            DCM*                r--   Digital Imaging and Communications in Medicine image
                DICOM is used by the medical community for images like X-rays.  The
                specification, "Digital Imaging and Communications in Medicine
                (DICOM)", is available at http://medical.nema.org/.  In particular,
                see part 5 which describes the image encoding (RLE, JPEG, JPEG-LS),
                and supplement 61 which adds JPEG-2000 encoding.
            DCR                 r--   Kodak Digital Camera Raw Image File
            DCRAW               r--   Raw Photo Decoder (dcraw)
            DCX*                rw+   ZSoft IBM PC multi-page Paintbrush
            DDS*                rw+   Microsoft DirectDraw Surface
            DNG                 r--   Digital Negative
            DPX*                rw-   SMPTE 268M-2003 (DPX 2.0)
                Digital Moving Picture Exchange Bitmap, Version 2.0.
                See SMPTE 268M-2003 specification at http://www.smtpe.org

            DXT1*               rw+   Microsoft DirectDraw Surface
            DXT5*               rw+   Microsoft DirectDraw Surface
            EPDF                rw-   Encapsulated Portable Document Format
            EPI                 rw-   Encapsulated PostScript Interchange format
            EPS                 rw-   Encapsulated PostScript
            EPS2                -w-   Level II Encapsulated PostScript
            EPS3                -w+   Level III Encapsulated PostScript
            EPSF                rw-   Encapsulated PostScript
            EPSI                rw-   Encapsulated PostScript Interchange format
            ERF                 r--   Epson RAW Format
            FAX*                rw+   Group 3 FAX
                FAX machines use non-square pixels which are 1.5 times wider than
                they are tall but computer displays use square pixels, therefore
                FAX images may appear to be narrow unless they are explicitly
                resized using a geometry of "150x100%".

            FILE*               r--   Uniform Resource Locator (file://)
            FITS*               rw-   Flexible Image Transport System
            FLV                 rw+   Flash Video Stream
            FRACTAL*            r--   Plasma fractal image
            FTP*                ---   Uniform Resource Locator (ftp://)
            FTS*                rw-   Flexible Image Transport System
            G*                  rw+   Raw green samples
            G3*                 rw-   Group 3 FAX
            G4*                 rw-   Group 4 FAX
            GIF*                rw+   CompuServe graphics interchange format
            GIF87*              rw-   CompuServe graphics interchange format (version 87a)
            GRADIENT*           r--   Gradual linear passing from one shade to another
            GRAY*               rw+   Raw gray samples
            GRAYA*              rw+   Raw gray and alpha samples
            HALD*               r--   Identity Hald color lookup table image
            HDR*                rw+   Radiance RGBE image format
            HISTOGRAM*          -w-   Histogram of the image
            HRZ*                rw-   Slow Scan TeleVision
            HTM*                -w-   Hypertext Markup Language and a client-side image map
            HTML*               -w-   Hypertext Markup Language and a client-side image map
            HTTP*               ---   Uniform Resource Locator (http://)
            HTTPS*              r--   Uniform Resource Locator (https://)
            ICB*                rw-   Truevision Targa image
            ICO*                rw+   Microsoft icon
            ICON*               rw-   Microsoft icon
            IIQ                 r--   Phase One Raw Image Format
            INFO                -w+   The image format and characteristics
            INLINE*             rw+   Base64-encoded inline images
            IPL*                rw+   IPL Image Sequence
            ISOBRL*             -w-   ISO/TR 11548-1 format
            ISOBRL6*            -w-   ISO/TR 11548-1 format 6dot
            JNX*                r--   Garmin tile format
            JSON                -w+   The image format and characteristics
            K*                  rw+   Raw black samples
            K25                 r--   Kodak Digital Camera Raw Image Format
            KDC                 r--   Kodak Digital Camera Raw Image Format
            LABEL*              r--   Image label
            M*                  rw+   Raw magenta samples
            M2V                 rw+   MPEG Video Stream
            M4V                 rw+   Raw MPEG-4 Video
            MAC*                r--   MAC Paint
            MAP*                rw-   Colormap intensities and indices
            MASK*               rw+   Image Clip Mask
            MAT                 rw+   MATLAB level 5 image format
            MATTE*              -w+   MATTE format
            MEF                 r--   Mamiya Raw Image File
            MIFF*               rw+   Magick Image File Format
            MKV                 rw+   Multimedia Container
            MONO*               rw-   Raw bi-level bitmap
            MOV                 rw+   MPEG Video Stream
            MP4                 rw+   MPEG-4 Video Stream
            MPC*                rw+   Magick Persistent Cache image format
            MPEG                rw+   MPEG Video Stream
            MPG                 rw+   MPEG Video Stream
            MRW                 r--   Sony (Minolta) Raw Image File
            MSL*                ---   Magick Scripting Language
            MSVG                -w+   ImageMagick's own SVG internal renderer
            MTV*                rw+   MTV Raytracing image format
            MVG*                rw-   Magick Vector Graphics
            NEF                 r--   Nikon Digital SLR Camera Raw Image File
            NRW                 r--   Nikon Digital SLR Camera Raw Image File
            NULL*               rw-   Constant image of uniform color
            O*                  rw+   Raw opacity samples
            ORF                 r--   Olympus Digital Camera Raw Image File
            OTB*                rw-   On-the-air bitmap
            PAL*                rw-   16bit/pixel interleaved YUV
            PALM*               rw+   Palm pixmap
            PAM*                rw+   Common 2-dimensional bitmap format
            PANGO*              ---   Pango Markup Language
            PATTERN*            r--   Predefined pattern
            PBM*                rw+   Portable bitmap format (black and white)
            PCD*                rw-   Photo CD
            PCDS*               rw-   Photo CD
            PCL                 rw+   Printer Control Language
            PCT*                rw-   Apple Macintosh QuickDraw/PICT
            PCX*                rw-   ZSoft IBM PC Paintbrush
            PDB*                rw+   Palm Database ImageViewer Format
            PDF                 rw+   Portable Document Format
            PDFA                rw+   Portable Document Archive Format
            PEF                 r--   Pentax Electronic File
            PES*                r--   Embrid Embroidery Format
            PFM*                rw+   Portable float format
            PGM*                rw+   Portable graymap format (gray scale)
            PGX*                rw-   JPEG 2000 uncompressed format
            PICON*              rw-   Personal Icon
            PICT*               rw-   Apple Macintosh QuickDraw/PICT
            PIX*                r--   Alias/Wavefront RLE image format
            PLASMA*             r--   Plasma fractal image
            PNM*                rw+   Portable anymap
            PPM*                rw+   Portable pixmap format (color)
            PS                  rw+   PostScript
            PS2                 -w+   Level II PostScript
            PS3                 -w+   Level III PostScript
            PSB*                rw+   Adobe Large Document Format
            PSD*                rw+   Adobe Photoshop bitmap
            PWP*                r--   Seattle Film Works
            R*                  rw+   Raw red samples
            RADIAL-GRADIENT*    r--   Gradual radial passing from one shade to another
            RAF                 r--   Fuji CCD-RAW Graphic File
            RAS*                rw+   SUN Rasterfile
            RAW                 r--   Raw
            RGB*                rw+   Raw red, green, and blue samples
            RGB565*             r--   Raw red, green, blue samples in 565 format
            RGBA*               rw+   Raw red, green, blue, and alpha samples
            RGBO*               rw+   Raw red, green, blue, and opacity samples
            RGF*                rw-   LEGO Mindstorms EV3 Robot Graphic Format (black and white)
            RLA*                r--   Alias/Wavefront image
            RLE*                r--   Utah Run length encoded image
            RMF                 r--   Raw Media Format
            RW2                 r--   Panasonic Lumix Raw Image
            SCR*                r--   ZX-Spectrum SCREEN$
            SCREENSHOT*         r--   Screen shot
            SCT*                r--   Scitex HandShake
            SFW*                r--   Seattle Film Works
            SGI*                rw+   Irix RGB image
            SHTML*              -w-   Hypertext Markup Language and a client-side image map
            SIX*                rw-   DEC SIXEL Graphics Format
            SIXEL*              rw-   DEC SIXEL Graphics Format
            SPARSE-COLOR*       -w+   Sparse Color
            SR2                 r--   Sony Raw Format 2
            SRF                 r--   Sony Raw Format
            STEGANO*            r--   Steganographic image
            SUN*                rw+   SUN Rasterfile
            SVG                 rw+   Scalable Vector Graphics
            SVGZ                -w+   Compressed Scalable Vector Graphics
            TEXT*               r--   Text
            TGA*                rw-   Truevision Targa image
            THUMBNAIL*          -w+   EXIF Profile Thumbnail
            TILE*               r--   Tile image with a texture
            TIM*                r--   PSX TIM
            TM2*                r--   PS2 TIM2
            TXT*                rw+   Text
            UBRL*               -w-   Unicode Text format
            UBRL6*              -w-   Unicode Text format 6dot
            UIL*                -w-   X-Motif UIL table
            UYVY*               rw-   16bit/pixel interleaved YUV
            VDA*                rw-   Truevision Targa image
            VICAR*              rw-   VICAR rasterfile format
            VID*                rw+   Visual Image Directory
            VIFF*               rw+   Khoros Visualization image
            VIPS*               rw+   VIPS image
            VST*                rw-   Truevision Targa image
            WBMP*               rw-   Wireless Bitmap (level 0) image
            WMV                 rw+   Windows Media Video
            WPG*                r--   Word Perfect Graphics
            X3F                 r--   Sigma Camera RAW Picture File
            XBM*                rw-   X Windows system bitmap (black and white)
            XC*                 r--   Constant image uniform color
            XCF*                r--   GIMP image
            XPM*                rw-   X Windows system pixmap (color)
            XPS                 r--   Microsoft XML Paper Specification
            XV*                 rw+   Khoros Visualization image
            Y*                  rw+   Raw yellow samples
            YCbCr*              rw+   Raw Y, Cb, and Cr samples
            YCbCrA*             rw+   Raw Y, Cb, Cr, and alpha samples
            YUV*                rw-   CCIR 601 4:1:1 or 4:2:2

            * native blob support
            r read support
            w write support
            + support for multiple images