ImageIO.read(InputStream)
创建一个ImageInputStream
并打电话read(ImageInputStream)
内部。后一种方法被记录为在读取图像完成后关闭流。
所以,理论上,你可以得到ImageReader
,创建一个ImageInputStream
自己,并拥有ImageReader
读自ImageInputStream
反复。
除此之外,它似乎是一个ImageInputStream
旨在处理一张且仅一张图像(可能包含也可能不包含多个帧)。如果你打电话ImageReader.read(0)
不止一次,它每次都会倒回到(缓存的)流数据的开头,一遍又一遍地为您提供相同的图像。ImageReader.read(1)
会在多帧图像中寻找第二帧,这对于 JPEG 来说当然没有意义。
那么,也许我们可以创建一个 ImageInputStream,让 ImageReader 从中读取,然后创建一个新的 ImageInputStream 来处理流中的后续图像数据,对吗?除外,看来ImageInputStream
进行各种缓存、预读和推回,这使得很难知道包装后的 InputStream 的读取位置。下一个 ImageInputStream 将开始从某处读取数据,但它并不像我们期望的那样位于第一个图像数据的末尾。
确定底层流位置的唯一方法是mark
and reset
。由于图像可能很大,您可能需要BufferedInputStream
以允许大readLimit
.
这对我有用:
private static final int MAX_IMAGE_SIZE = 50 * 1024 * 1024;
static void readImages(InputStream stream)
throws IOException {
stream = new BufferedInputStream(stream);
while (true) {
stream.mark(MAX_IMAGE_SIZE);
ImageInputStream imgStream =
ImageIO.createImageInputStream(stream);
Iterator<ImageReader> i =
ImageIO.getImageReaders(imgStream);
if (!i.hasNext()) {
logger.log(Level.FINE, "No ImageReaders found, exiting.");
break;
}
ImageReader reader = i.next();
reader.setInput(imgStream);
BufferedImage image = reader.read(0);
if (image == null) {
logger.log(Level.FINE, "No more images to read, exiting.");
break;
}
logger.log(Level.INFO,
"Read {0,number}\u00d7{1,number} image",
new Object[] { image.getWidth(), image.getHeight() });
long bytesRead = imgStream.getStreamPosition();
stream.reset();
stream.skip(bytesRead);
}
}