Why does ImageReader return incorrect BufferedImage?
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.ArrayL开发者_如何学运维ist;
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
Code 1
import java.net.URL;
import java.awt.Image;
import javax.imageio.ImageIO;
class GetGifSize {
public static void main(String[] args) throws Exception {
URL urlToImage = new URL("http://i55.tinypic.com/263veb9.gif");
Image image = ImageIO.read(urlToImage);
System.out.println( "Image size is " +
image.getWidth(null) +
"x" +
image.getHeight(null) );
}
}
Output
Image size is 200x220
Code 2
A variant of the code posted by trashgod.
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 http://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 {
ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
reader.setInput(ImageIO.createImageInputStream(url.openStream()));
int i = reader.getMinIndex();
int offset = i-0;
int count = reader.getNumImages(true);
System.out.println("Image count: " + count);
for (int ii=i; ii<(count-i); ii++) {
BufferedImage bi = reader.read(ii);
System.out.println(ii
+ offset
+ ": " + bi.getWidth()
+ ", " + bi.getHeight());
}
}
}
As an aside, I think you should mark trashgod's answer correct of the two answers.
It was first to get to the real core of the problem. And you gotta' love an answer with screen-shots. That's going 'the whole 9 yards'.
精彩评论