22
None of the answers here are correct and suitable for animation. There are many problems in each solution so I wrote something that actually works with all gif files. For instance, this takes into account the actual width and height of the image instead of taking the width and height of the first frame assuming it will fill the entire canvas, no, unfortunately it's not that simple. Second, this doesn't leave any transparent pickles. Third, this takes into account disposal Methods. Fourth, this gives you delays between frames (* 10 if you want to use it in Thread.sleep()).
private ImageFrame[] readGif(InputStream stream) throws IOException{
ArrayList<ImageFrame> frames = new ArrayList<ImageFrame>(2);
ImageReader reader = (ImageReader) ImageIO.getImageReadersByFormatName("gif").next();
reader.setInput(ImageIO.createImageInputStream(stream));
int lastx = 0;
int lasty = 0;
int width = -1;
int height = -1;
IIOMetadata metadata = reader.getStreamMetadata();
Color backgroundColor = null;
if(metadata != null) {
IIOMetadataNode globalRoot = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
NodeList globalColorTable = globalRoot.getElementsByTagName("GlobalColorTable");
NodeList globalScreeDescriptor = globalRoot.getElementsByTagName("LogicalScreenDescriptor");
if (globalScreeDescriptor != null && globalScreeDescriptor.getLength() > 0){
IIOMetadataNode screenDescriptor = (IIOMetadataNode) globalScreeDescriptor.item(0);
if (screenDescriptor != null){
width = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenWidth"));
height = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenHeight"));
}
}
if (globalColorTable != null && globalColorTable.getLength() > 0){
IIOMetadataNode colorTable = (IIOMetadataNode)