I'm trying to access a animated GIF image with 21 frames and then read the 12th (cause it starts at 0?) frame.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
public class PictureSearch {
public static void search(File file) {
try {
ImageReader reader = (ImageReader) ImageIO.getImageReadersBySuffix("gif").next();
reader.setInput(ImageIO.createImageInputStream(file), false);
BufferedImage caption = reader.read(12);
System.out.println(caption.getHeight());
System.out.println(caption.getWidth());
caption.flush();
} catch (IOException e) {
System.out.println(e);
}
}
public static void main(String[] args) throws IOException {
List<String> suffixes = new ArrayList<String>();
suffixes.add(".jpg");
suffixes.add(".gif");
suffixes.add(".bmp");
suffixes.add(".png");
Iterator<File> files = FileUtils.iterateFiles(new File(
"F:/test/"), (IOFileFilter) new SuffixFileFilter(
suffixes), TrueFileFilter.INSTANCE);
while (files.hasNext()) {
File file = (File) files.next();
PictureSearch.search(file);
}
}
}
The reader should return me a buffered image with height 220 and width 200 (or height 205 and width 188 if it ignores white fields around the image). But what it does is it returns me a image of height 155 and width 174 what is absurd because i triple checked and the frame 12 is height 220 and width 200. Am I doing everything correctly in reading the frames?
The rectangle in your example appears to be a frame representing the changed portion of the image sequence, starting from 1. Open the file in Gimp to see.
Addendum: It looks like a feature intended to optimize rendering. At a guess, I'd say you could rely on the bounds of image number getMinIndex()
; later frames appear to be subsumed in the first.
Addendum:
is there a way to get the full pixel data with the normal image and changes?
Assuming known geometry, you should be able to combine the first image and any later one in a BufferedImage
, as shown here.
Code:
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
public class GifBounds {
/** @see https://stackoverflow.com/questions/5688104 */
public static void main(String[] args) throws IOException {
search(new URL("http://i55.tinypic.com/263veb9.gif"));
}
public static void search(URL url) throws IOException {
try {
ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
reader.setInput(ImageIO.createImageInputStream(url.openStream()));
int i = reader.getMinIndex();
while (true) {
BufferedImage bi = reader.read(i++);
System.out.println(i
+ ": " + bi.getWidth()
+ ", " + bi.getHeight());
}
} catch (IndexOutOfBoundsException e) {
// ignored
}
}
}
Console:
1: 200, 220 2: 79, 95 3: 77, 94 4: 78, 95 5: 79, 95 6: 77, 94 7: 78, 95 8: 79, 95 9: 77, 94 10: 180, 205 11: 97, 111 12: 173, 200 13: 174, 155 14: 174, 155 15: 174, 155 16: 174, 155 17: 174, 155 18: 174, 155 19: 174, 155 20: 167, 200 21: 97, 111