37

Many of the questions asking how to create an animated gif from a set of png images suggest to use a variant of ImageMagick's convert command:

convert -delay 2 -loop 0 *.png animated.gif

However, I have a few thousand images and thus convert uses up all my memory, swap, and then crashes. What alternative software exists, which is more memory-conscious? I could use another open format if .gif is not supported, and I do prefer a CLI tool.

9
  • 1
    How about dividing the *.png files into manageable chunks? Let's say all filenames start with a digit, then convert -delay 2 -loop 0 0*.png animated.gif will convert only the files that start with a '0'. And so on.
    – Jos
    Jan 14, 2015 at 13:44
  • 2
    So each .png is in the order of 1 Mb? In that case, all I can think of is to first convert the .png files to a lower resolution or color depth, to make them smaller.
    – Jos
    Jan 14, 2015 at 13:51
  • 10
    You say that you could use another open format. It seems to me that gif isn't exactly the best format for thousands of frames. Have you considered encoding a video with Ogg Theora instead?
    – user346339
    Jan 14, 2015 at 15:11
  • 1
    Perhaps take a look at gifsicle, if you really want to use GIF? (Although, as others have said, this isn't what GIF was made for; OGG would be a better choice.)
    – wchargin
    Jan 14, 2015 at 23:32
  • 1
    Re. "where all the memory is going": 65 Kb is the file size of a compressed image. When uncompressed, the image takes roughly 4 x width x height bytes, so a 1024x768 image would take ~3Mb of RAM. Multiply that by "a few thousand" and you'll see where the memory is going...
    – Sergey
    Jan 20, 2015 at 20:49

8 Answers 8

36

It sounds like you're trying to make a video. If that's the case, then I'd use a proper video format.

In this case, I'd use ffmpeg to convert the individual PNG files to a H.264 video. Since ffmpeg is made to work with videos that can be hours long, it should have no problem with your thousands of images. Using H.264 instead of animated gif will result in a vast improvement in image quality.

Something like this should work for you:

 ffmpeg -framerate 1/2 -i img%04d.png -c:v libx264 -r 30 out.mp4
  • -framerate 1/2: This sets the framerate to one-half FPS, or 2 seconds per frame.
  • -i img%04d.png: This tells ffmpeg to read the files img0000.png though img9999.png.
  • -c:v libx264: Use video codec libx264.
    • You can specify video compression parameters here, if you like:
    • -crf <number>: Quality setting. 0 to 51. 23 is the default. 0 is true lossless encoding, which will be quite high bandwidth. 18 is nearly visually lossless.
  • -r 30: Set the output framerate to 30 FPS. Each of the input images will be duplicated to make the output what you specify here. You can leave this parameter off, and the output file will be at the input framerate, but the resulting movie didn't display properly when I tried it just now.
  • out.mp4: Output filename.

References:

2
15

Personally, I would just launch it on limited numbers of files instead of all at once. For example, something like this:

#!/usr/bin/env bash

## Collect all png files in the files array
files=( *png )
## How many should be done at once
batch=50

## Read the array in batches of $batch
for (( i=0; $i<${#files[@]}; i+=$batch ))
do
    ## Convert this batch
    convert -delay 2 -loop 0 "${files[@]:$i:$batch}" animated.$i.gif
done

## Now, merge them into a single file
convert  animated.*.gif all.gif
9

Use -limit memory 1GiB to limit the amount of memory convert uses.

1000s of images would create a huge GIF that most computers will struggle to display. I keep my animated GIFs below 200 images when possible. The fewer the better. If you number your images, this command will delete the odd numbered images rm *[13579].png.

So here is my typical workflow for creating an animated GIF from a movie scene:

avconv -ss 00:26:00 -i someMovie.mpg %5d.png
rm  *[13579].png
convert -limit memory 1GiB -loop 0 -layers optimize -resize 400 *.png output.gif
1
4

If you have thousands of png-s, the anigif format is weird. I would do it in this way, using avconv:

 avconv -i "%d.png" -r 25 -c:v libx264 -crf 20 -pix_fmt yuv420p animated.mov
1
  • This approach has the added benefit that you could later mux in voice-over or music audio which is impossible with the Graphics Interchange Format.
    – Elder Geek
    Jul 5, 2016 at 19:57
4

I could use another open format if .gif is not supported

Perhaps APNG is of use to you. It's supported by some browsers, including Firefox but at the moment excluding Chrome and IE. Since it's just a PNG extension, it's very simple to convert PNGs to APNG. The apngasm tool can do that. But the format is so simple that I recently wrote an APNG assembler myself for Sage. Adapting that code would be an alternative.

3
  • I'd like to also point out that APNG is non-standard and despite having been around for 7 years is still very obscure.
    – Pharap
    Jan 15, 2015 at 7:28
  • For a scientific demonstration, where you might be able to choose the browser used for it, this might still be a simple and robust solution.
    – MvG
    Jan 15, 2015 at 17:17
  • It depends who has to view the demonstration. It wouldn't be very good to hand copies out to the viewers and then two thirds have to go off and download Firefox just to view it. Not the kind of impression I'd like to make if I were making an important scientific demonstration. If it's only intended to be viewed as part of the demonstration then fair enough, but it may not be suitable for other situations.
    – Pharap
    Jan 16, 2015 at 0:10
2

gifsicle is a command-line utility to handle GIF animations. If you are willing to trade memory for speed, you can use its --conserve-memory switch.

2
  • Let me put it this way: gifsicle already has a smaller footprint than ImageMagick - if you find that it still uses too much memory for the task at hand, then you can use --conserve-memory
    – codehead
    Jan 16, 2015 at 10:11
  • Ohh, I think I misread what you were saying, that the switch would use more memory, which doesn't make much sense. never mind. Jan 16, 2015 at 11:30
2

In addition to other answers: since you want to produce a GIF file, I assume you want to display the image on a web page. If so, I would not bother converting your PNGs at all. Just google for "javascript slideshow" and use one of the millions of free scripts. Or write your own, this is really trivial.

The benefits of doing it this way are:

  • only one image is loaded in the browser at any time, the slideshow starts fast and does not consume much RAM on the user's machine.

  • the solution scales to millions of images. Or billions, if you're patient enough to watch them all :)

  • You can add controls to your page to pause, rewind, change the delay or go to a particular frame.

1
  • Thank you Sergey. In fact this is not for display on a webpage. +1 for the idea, though.
    – dotancohen
    Jan 20, 2015 at 21:02
0

You can use apng2gif to achieve the same. From the man page:

Progrmam apng2gif converts APNG into animated GIF format.

   The Animated Portable Network Graphics (APNG) file format is an extension to the Portable
   Network Graphics (PNG) specification. It allows for animated PNG files that work similarly
   to animated GIF files, while retaining backward compatibility with non-animated PNG files
   and adding support for 8-bit transparency and 24-bit images.

   Default run values are /t 128, no background color. A short syntax hlp is provided without
   any command line arguments.

Run the following command to install the package:

sudo apt install apng2gif

Then run the following command to convert all .png files to .gif:

find -type f -name "*.png" -exec apng2gif {} \;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .