我的一个项目是,我只是在从ImageStream动态读取图像时对图像进行下采样。下采样将图像的尺寸减小到所需的宽度和高度,同时不需要昂贵的调整大小计算或修改磁盘上的图像。
由于我将图像下采样到较小的尺寸,因此它还显着降低了显示图像所需的处理能力和RAM。为了进行额外的优化,我还在图块中渲染缓冲图像...但这有点超出本次讨论的范围。请尝试以下操作:
public static BufferedImage subsampleImage(
ImageInputStream inputStream,
int x,
int y,
IIOReadProgressListener progressListener) throws IOException {
BufferedImage resampledImage = null;
Iterator<ImageReader> readers = ImageIO.getImageReaders(inputStream);
if(!readers.hasNext()) {
throw new IOException("No reader available for supplied image stream.");
}
ImageReader reader = readers.next();
ImageReadParam imageReaderParams = reader.getDefaultReadParam();
reader.setInput(inputStream);
Dimension d1 = new Dimension(reader.getWidth(0), reader.getHeight(0));
Dimension d2 = new Dimension(x, y);
int subsampling = (int)scaleSubsamplingMaintainAspectRatio(d1, d2);
imageReaderParams.setSourceSubsampling(subsampling, subsampling, 0, 0);
reader.addIIOReadProgressListener(progressListener);
resampledImage = reader.read(0, imageReaderParams);
reader.removeAllIIOReadProgressListeners();
return resampledImage;
}
public static long scaleSubsamplingMaintainAspectRatio(Dimension d1, Dimension d2) {
long subsampling = 1;
if(d1.getWidth() > d2.getWidth()) {
subsampling = Math.round(d1.getWidth() / d2.getWidth());
} else if(d1.getHeight() > d2.getHeight()) {
subsampling = Math.round(d1.getHeight() / d2.getHeight());
}
return subsampling;
}
要从文件中获取图像输入流,请使用:
ImageIO.createImageInputStream(new File("C:\\image.jpeg"));
如您所见,此实现还尊重图像的原始纵横比。您可以选择注册 IIOReadProgressListener,以便可以跟踪到目前为止已读取了多少图像。这对于显示进度条非常有用,例如,如果图像是通过网络读取的...但不是必需的,您可以只指定 null。
为什么这与你的情况特别相关?它永远不会将整个图像读取到内存中,就像您需要的那样多,以便它可以以所需的分辨率显示。对于巨大的图像,即使是那些在磁盘上是10 MB的图像,也非常有效。