0

So I've tried a number of times, and I just can't get it to work. I have a program out there that converts animated GIFs into a sequence of PNGs with a bunch of configurable settings.

The problem is, the only ways I could find to be able to read frames of the GIF as BufferedImages and reuse the ImageReader involved making an array or some type of list that stores all the frames. This is very convenient, but for long, high resolution files, this eats up a lot of ram. Ideally I'd like to read them one at a time, and dispose of them when I am done with the frame. I have tried to study how compressed GIFs work, but the way disposal works is proving to be a bit over my head. The two essential methods I have tried and failed miserably to code are

public BufferedImage getNextFrame() 

to return the uncompressed, full next frame, and

public void reset()

to reset the index at 0. I have realized it is impossible to efficiently jump to an arbitrary frame without storing every one as an index of an array or list.

Can someone give me some pointers on how to manage GIFs in a resource efficient way when I intend to do more with the frames than simply display them? I'm not asking you to write the entire thing, but just give me an idea of how one would do this.

user3236716
  • 189
  • 1
  • 11
  • "Ideally I'd like to read them one at a time, and dispose of them when I am done with the frame." Why is this a problem? I would assume this is as easy as removing the reference to the `BufferedImage` (ie. assigning it `null`). (Note: It probably isn't that easy, but it's just not clear to me, why it isn't. It would help if you clarify and add some more detail to the question. :-) ) – Harald K Mar 26 '15 at 09:52
  • Compressed GIFs use information from previous frames to make the image for the next frame. I am struggling to find a way to keep track of what past frames I need, and I am really not used to working with files so directly like this. I built my original class based on the third answer to [this question](http://stackoverflow.com/questions/8933893/convert-animated-gif-frames-to-separate-bufferedimages-java). I tried to take the part in the for loop out and turn it into a method (obviously with a few structural changes) and it's just not going well. – user3236716 Mar 26 '15 at 19:14

2 Answers2

0

I couldn't figure it out on my own, but I did find this to do the trick. Looking at the code I wasn't even close to figuring it out on my own.

user3236716
  • 189
  • 1
  • 11
0

If you don't mind using third party code, here is a Java image library I made which could do much more than just grab each frames of an animated GIF.

That's said, there is a specific class called FrameReader and it is intended to do exactly what you want: grab GIF frames one at a time. The following example shows how to use it:

import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.InputStream;

import com.icafe4j.image.gif.FrameReader;
import com.icafe4j.image.gif.GIFFrame;


public class GrabFrame {

    public static void main(String[] args) throws Exception {
        InputStream is = new FileInputStream(args[0]);
        FrameReader reader = new FrameReader();
        BufferedImage curFrame = null;

        GIFFrame gifFrame = reader.getGIFFrameEx(is);

        while(gifFrame != null) {
            curFrame = gifFrame.getFrame();
            // Do something with curFrame
            gifFrame = reader.getGIFFrameEx(is);
        }       
    }
}

the method getGIFFrameEx(is) returns a GIFFrame instance which wraps among other frame control parameters a BufferedImage which takes into account different disposal methods used by the animated GIF graphic control block. If you don't care about the disposal methods, you can call getGIFFrame(is) which also wraps a BufferedImage which however doesn't take into account the relationship between different frames. This may create strange-looking frames as talked about here.

Community
  • 1
  • 1
dragon66
  • 2,645
  • 2
  • 21
  • 43