And here's the cleverer approach by Alexander Hristov under the lesser general public license (which probably means you can use on jPCT but I haven't read it). The first is the tester I wrote (ArrayIndexOutOfBoundsException will be thrown if your gif doesn't have at least 4 frames), and the second is his FrameReader.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
public class FrameReaderTester extends Frame implements WindowListener {
private BufferedImage[] frames;
private int currentFrame = 0;
public FrameReaderTester(String fileName) {
this.setTitle("AGP's");
try {
frames = FrameReader.getAllFrames(new FileInputStream(fileName));
}
catch (IOException e) {System.err.println("Shit happened: "+e.getMessage());}
this.addWindowListener(this);
this.setSize(800, 600);
this.setVisible(true);
}
public void paint(Graphics g) {
g.drawImage(frames[0], 10, 30, null);
g.drawImage(frames[1], 20+frames[0].getWidth(), 30, null);
g.drawImage(frames[2], 10, 40+frames[0].getHeight(), null);
g.drawImage(frames[3], 20+frames[0].getWidth(), 40+frames[1].getHeight(), null);
}
public void windowClosing(WindowEvent e) {
if (e.getWindow().equals(this)) {
this.dispose();
System.exit(0);
}
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public static void main(String[] args) {
if (args == null || args.length == 0)
return;
new FrameReaderTester(args[0]);
}
}
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.ImageInputStream;
class FrameReader {
public static BufferedImage[] getAllFrames(InputStream in) throws IOException {
IIORegistry providers = IIORegistry.getDefaultInstance();
Iterator it = providers.getServiceProviders(ImageInputStreamSpi.class,true);
ImageInputStream imgStream = null;
// Create an ImageInputStream with the first appropriate SPI
while (it.hasNext()) {
ImageInputStreamSpi spi = (ImageInputStreamSpi)it.next();
if (spi.getInputClass().isInstance(in)) {
imgStream = spi.createInputStreamInstance(in);
break;
}
}
if (imgStream == null)
throw new IOException("No appropriate SPI for this input stream ");
it = providers.getServiceProviders(
ImageReaderSpi.class, new CanDecodeFilter(imgStream),true);
if (!it.hasNext())
throw new IOException("No class can read this image format");
ImageReaderSpi readerSpi = (ImageReaderSpi)it.next();
ImageReader reader = readerSpi.createReaderInstance();
ImageReadParam param = reader.getDefaultReadParam();
reader.setInput(imgStream, false, true);
int numFrames = reader.getNumImages(true);
BufferedImage[] frames = new BufferedImage[numFrames];
for (int i = 0; i < numFrames; i++) {
frames[i] = reader.read(i,param);
}
imgStream.close();
reader.dispose();
return frames;
}
static class CanDecodeFilter implements ServiceRegistry.Filter {
ImageInputStream stream;
public CanDecodeFilter(ImageInputStream stream) {
this.stream = stream;
}
public boolean filter(Object element) {
try {
ImageReaderSpi spi = (ImageReaderSpi)element;
boolean canDecode = false;
stream.mark();
canDecode = spi.canDecodeInput(stream);
stream.reset();
return canDecode;
} catch (IOException e) {
return false;
}
}
}
}