Reputation: 469
I am trying to extract all the frames of an animated gif to an array of bufferedimages. I have been reading Convert each animated GIF frame to a separate BufferedImage and it was fairly easy to write each frame to a seperate file. But my problem comes up when I try to fill an ArrayList with the frames instead of writing them. Every image in the ArrayList is just the last frame of the gif.
To make it more clear, this code will write each frame to seperate files perfectly:
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for (int i = 0; i < ir.getNumImages(true); i++)
{
master.getGraphics().drawImage(ir.read(i), 0, 0, null);
ImageIO.write(master, "gif", new File(dirGifs + "/frames" + i + ".gif"));
}
However, this code will only gives me an ArrayList full of the same frame (being the last frame of the gif)
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for (int i = 0; i < ir.getNumImages(true); i++)
{
master.getGraphics().drawImage(ir.read(i), 0, 0, null);
frames.add(master);
}
I thought that it was because I wasnt disposing of the graphics afterwards, but I tried creating a graphics object and disposing it and nothing changed. Need help!
Upvotes: 0
Views: 2794
Reputation: 469
Colouredmirrorball pointed out that I could solve this problem by creating a new instance of the bufferedimage. So I created a new instance for each array element first and then set the element's data to the same as the master image. The following piece of code gives me an array of frames extracted from an animated gif file.
public ArrayList<BufferedImage> getFrames(File gif) throws IOException {
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for (int i = 0; i < ir.getNumImages(true); i++) {
frames.add(new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB));
master.getGraphics().drawImage(ir.read(i), 0, 0, null);
frames.get(i).setData(master.getData());
}
return frames;
}
Upvotes: 0
Reputation: 331
It's because the BufferedImage master
is being stored in the ArrayList as a reference and not as a copy. So each element of the ArrayList points to the same BufferedImage. I think the easiest way to solve this is just to put the line BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
inside the for loop, so a new instance of BufferedImage is created on each iteration.
Upvotes: 2