64

I need something that can be scripted on windows 7. This image will be used in banners.

Cbox
  • 1,097
  • 1
  • 9
  • 9
  • 1
    does it need to be jpeg? jpeg->anim gif is likely to have unwanted flickery artifacts with worse compression ratio. you should use lossless -> gif, or gif->gif for the best quality results. – tenfour Sep 10 '10 at 23:01
  • 1
    @tenfour - although what you have pointed out is perfectly valid, it's not necessarily a rule of thumb. Much more important is that the frames share similar colors, because if they don't, the palette of maximum 256 colors of a GIF image that is shared between frames will produce crappy results, regardless of the input format and will often leave people wondering "why did it come out grainy ?!" – Valentin Flachsel Sep 10 '10 at 23:12
  • 3
    Using images `IMG-001.jpg`, `IMG-002.jpg`, and so on (with `3` digits), showing `4` images per second, you get the result as a GIF by simply using the following command: `ffmpeg -f image2 -framerate 4 -i "IMG-%03d.jpg" Output.gif` – caw Dec 20 '18 at 23:05

6 Answers6

135

Simon P Stevens' answer almost got me there:

ffmpeg -f image2 -i image%d.jpg video.avi
ffmpeg -i video.avi -pix_fmt rgb24 -loop_output 0 out.gif

Let's see if we can neaten this up.

Going via an avi is unnecessary. A -pix_fmt of rgb24 is invalid, and the -loop_output option prevents looping, which I don't want. We get:

ffmpeg -f image2 -i image%d.jpg out.gif

My input pictures are labeled with a zero-padded 3-digit number and I have 30 of them (image_001.jpg, image_002.jpg, ...), so I need to fix the format specifier

ffmpeg -f image2 -i image_%003d.jpg out.gif

My input pictures are from my phone camera, they are way too big! I need to scale them down.

ffmpeg -f image2 -i image_%003d.jpg -vf scale=531x299 out.gif

I also need to rotate them 90 degrees clockwise

ffmpeg -f image2 -i image_%003d.jpg -vf scale=531x299,transpose=1 out.gif

This gif will play with zero delay between frames, which is probably not what we want. Specify the framerate of the input images

ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1 out.gif

The image is just a tad too big, so I'll crop out 100 pixels of sky. The transpose makes this tricky, I use the post-rotated x and y values:

ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1,crop=299,431,0,100 out.gif

The final result - I get to share my mate's awesome facial expression with the world:

Example of an animated gif created with ffmpeg

Community
  • 1
  • 1
dwurf
  • 12,393
  • 6
  • 30
  • 42
  • %003d ffmpeg replaces this with path - `image_C:/user/...` – user25 Sep 05 '16 at 17:35
  • 1
    Great answer! Too bad it stops short of 2-step palette optimization: https://superuser.com/a/556031/142943 – juanitogan Sep 18 '18 at 00:02
  • 7
    In case your image index do not start at zero, use the `-start_number xxx` option. https://superuser.com/a/666994/999889 – Raf Jul 25 '20 at 07:59
  • My images were synthetic (i.e. plots) and for somes reason unknown to me when I used `ffmpeg` there were some yellow lines in the resulting gif file; though, I didn't encounter this problem when I used ImageMagick `convert` command instead. – today Oct 27 '20 at 15:25
  • 1
    what does image2 represent? – wongz Apr 05 '21 at 20:50
  • 1
    `image2` is the name of the ffmpeg demuxer (the bit that reads the input). `image2` provides the file globbing used in `-i` and knows how to read the files as a video source. See http://manpages.org/ffmpeg – dwurf Apr 06 '21 at 23:14
76

You can do this with ffmpeg

First convert the images to a video:

ffmpeg -f image2 -i image%d.jpg video.avi

(This will convert the images from the current directory (named image1.jpg, image2.jpg...) to a video file named video.avi.)

Then convert the avi to a gif:

ffmpeg -i video.avi -pix_fmt rgb24 -loop_output 0 out.gif

You can get windows binaries for ffmpeg here.


You can also do a similar thing with mplayer. See Encoding from multiple input image files.

I think the command line would be something like:

mplayer mf://*.jpg -mf w=800:h=600:type=jpg -vf scale=160:120 -vo gif89a:fps=3:output=out.gif

(Where 800 & 600 are your source width and height and 160 & 120 are the target width and height.out.gif is your target file name)


I've just tested both of these and they both work fine. However I got much better results from mplayer as I was able to specify the resolution and framerate. Your milage may vary and I'm sure you could find more options for ffmpeg if you looked.

Pang
  • 9,564
  • 146
  • 81
  • 122
Simon P Stevens
  • 27,303
  • 5
  • 81
  • 107
  • Using the recent version of mplayer, it just prints out its manpage. – turbo Jul 09 '15 at 23:28
  • 2
    this has a good google search rating, so if you want to prefix numbers with zeros, use `%04d` (number 4 would use 4 number positions prefixed with 0) – user151496 Mar 07 '16 at 16:55
  • 1
    no file found with name `image1d.jpg` ! trying using cmd – user25 Sep 05 '16 at 17:32
  • 8
    Brilliant answer, just so anyone trying to use it currently is aware the new flag for the .avi to .gif conversion is `-loop`, with an option of 0 for infinite loop. Also I think the rgb profile flag (not that I know anything about colour profiles made my thumbnail have a blue grid of dots over it – Scott Anderson Oct 24 '18 at 12:24
  • You can indeed just use the first command and output to GIF directly by changing the file extension given in the command. Moreover, you may set a frame rate, e.g. `-framerate 1`, `-framerate 20` or `-framerate 1/5`. – caw Dec 20 '18 at 23:08
  • 2
    Doesn't converting to avi degrade quality since avi uses lossy compression? – Nagabhushan S N Jul 17 '19 at 17:42
  • 1
    @caw I tried that. But ffmpeg is introducing some artifacts in the gif. Some dots/blobs on the video. Any idea why? – Nagabhushan S N Jul 17 '19 at 17:43
57

With ImageMagick:

convert *.png a.gif
psycho brm
  • 7,494
  • 1
  • 43
  • 42
  • 1
    also look here: http://stackoverflow.com/questions/5508945/imagemagick-animated-gif-size-optimization – psycho brm Jul 14 '13 at 09:37
  • 1
    I had quality issues from using .png files (because of transparency and layering) which were fixed by using .jpg instead – gatlanticus Dec 13 '16 at 03:15
  • 6
    You can use `-delay` to set the duration each image is shown. Note that the value is given in 1/100 seconds, i.e. `-delay 100` results in a rate of one frame per second. – luator Nov 16 '17 at 10:51
  • Commands like `convert -delay 100 *.jpg Output.gif` work fine, but produce larger file sizes than `ffmpeg` does, it seems, even when using `-layers optimize`. – caw Dec 20 '18 at 23:14
14

The ffmpeg to .avi and .avi to .gif worked, but the only thing to note is that your images must be named in perfect increasing numeric order to work, with no gaps. I cooked up a quick python script to rename all of my images accordingly so that this ffmpeg recipe would work:

import os

files = [ f for f in os.listdir('.') if os.path.isfile(os.path.join('.',f)) and f.endswith('.jpg') ]
for i, file in enumerate(sorted(files)):
    os.rename(file, 'image%03d.jpg' % i)

And then I stumbled upon a much simpler approach than ffmpeg for doing the conversion, which is simply using ImageMagick's command line convert tool like this

convert image%03d.jpg[0-198] animated_gif.gif

Doesn't get much simpler than that folks.

Gist here: https://gist.github.com/3289840

Marko
  • 20,385
  • 13
  • 48
  • 64
  • 5
    _"images must be named in perfect increasing numeric order"_ - I guess you do not know about `-pattern_type glob`, it allows to use files with any names as input, for example, to convert all pngs in current directory to gif: `ffmpeg -framerate 1/10 -pattern_type glob -i '*.png' output.gif` – Lissanro Rayen Dec 13 '14 at 18:36
  • @LissanroRayen, `-pattern_type` would be really great if it could be conjuncted with *.jpg source files somethow, not just *.png. – 1234ru Sep 09 '22 at 21:28
12

Based on the answers of Simon P Stevens and dwurf I came up with this simplified solution:

ffmpeg -f image2 -framerate 1 -i image%d.jpg video.gif

This results in a rate of 1 second per image. Adjust the framerate value according to your needs.

luator
  • 4,769
  • 3
  • 30
  • 51
12

I'd just like to add to dwurf's answer, that this will generate a gif with the standard 256-colors palette, which does not look very visually pleasing.

I've found two blog-posts and adapted them to my needs, in order to improve the visual quality by using a custom palette for your animation:

Generate the color palette:

ffmpeg -f image2 -i image%d.jpg -vf scale=900:-1:sws_dither=ed,palettegen palette.png

Convert images into a regular video with the desired framerate, because the third command only worked with a single input video and not a bunch of images

ffmpeg -f image2 -framerate 1.2 -i image%d.jpg video.flv

Now convert the generated video with the generated palette into a more beautiful gif:

ffmpeg -i video.flv -i palette.png -filter_complex "fps=1.2,scale=900:-1:flags=lanczos[x];[x][1:v]paletteuse" video.gif
Alexander Pacha
  • 9,187
  • 3
  • 68
  • 108