24

Has anybody managed to convince ImageIO to write an animated GIF, and in particular setting the correct metadata? My first attempt is roughly as follows (where b1 and b2 are BufferedImages):

ImageTypeSpecifier spec = new ImageTypeSpecifier(b1);
ImageWriter wr = ImageIO.getImageWriters(spec, "GIF").next();
wr.setOutput(ImageIO.createImageOutputStream(new File("C:\\Flashing.gif")));
ImageWriteParam param = wr.getDefaultWriteParam();
IIOMetadata meta = wr.getDefaultImageMetadata(spec, param);
wr.prepareWriteSequence(meta);
wr.writeToSequence(new IIOImage(b1, null, null), param);
wr.writeToSequence(new IIOImage(b2, null, null), param);

This appears to almost work, but:

  • I clearly need to somehow set "proper" metadata to set the time between the images and ideally make them loop (I was naively hoping the default would do something sensible, but hey...)
  • whatever metadata it is writing by default is obviously not quite right: the GIMP gives a couple of error messages when loading the file, although embedding the image in a test web page in Firefox does display the two images in very quick succession, which is tantilisingly close to what I want...

If anyone has got writing animated GIFs from ImageIO to work and can share a snippet of working code or how to fix the above problems, it would be greatly appreciated!

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
Neil Coffey
  • 21,615
  • 7
  • 62
  • 83

1 Answers1

31

I ran across this question, and decided to try it out; It took a small but non-trivial amount create a usable class (thanks ax) -- so I thought I might share the code around: here is a small class for creating an animated gif image from a number of other images. Archived version

resueman
  • 10,572
  • 10
  • 31
  • 45
Elliot Kroo
  • 4,463
  • 3
  • 23
  • 15
  • 1
    There is an error in the example provided within main() function. Comments say: `// a gif sequence with the type of the first image, 1 second between frames, which loops continuously`, that would be `new GifSequenceWriter(output, firstImage.getType(), 1000, true)` instead of `new GifSequenceWriter(output, firstImage.getType(), 1, false)` – gvlasov Aug 14 '13 at 07:44
  • 3
    Also, if you find out that transparent colors are not handled properly (when you write a transparent color, a pixel from previous frame retains itself), you need to do this: find a line with `graphicsControlExtensionNode.setAttribute("disposalMethod", "none");` and change `"none"` to `"restoreToBackgroundColor"` – gvlasov Aug 14 '13 at 08:15
  • Your code is still referenced on stackoverflow [4 years later](http://stackoverflow.com/questions/16649620/is-there-a-way-to-create-one-gif-image-from-multiple-images-in-java) and I plan to use it 7 years later :) – Aaron Jan 05 '16 at 23:10
  • 1
    This is just fantastic! I embedded a copy in my Wayang library for drawing graphical interfaces on the Ableton Push 2. To make it work, I had to add a variant constructor that would take a RenderedImage, because the custom BufferedImage I use to accommodate the bit layout on the Push 2 display was not compatible with the existing constructor. You can see the source of my version (along with an example GIF captured from my UI) here: https://github.com/brunchboy/wayang#wayang – James Elliott Mar 25 '16 at 03:25
  • 11 years later and your GifWriter is still relevant! Appreciate the work –  May 04 '20 at 17:53
  • If there is anyone still following this post, how can I adjust the compression level? –  May 04 '20 at 22:32