Ele*_*hoy 14 java memory image awt
我有java程序从硬盘驱动器读取jpeg文件,并将其用作各种其他东西的背景图像.图像本身存储在一个BufferImage对象中,如下所示:
BufferedImage background
background = ImageIO.read(file)
Run Code Online (Sandbox Code Playgroud)
这很有效 - 问题在于BufferedImage对象本身是巨大的.例如,一个215k的jpeg文件成为一个BufferedImag4兆的e对象并进行更改.有问题的应用程序可以加载一些相当大的背景图像,但是jpegs永远不会超过一两或两个,用于存储的内存BufferedImage可以快速超过100兆字节.
我假设这一切都是因为图像作为原始RGB数据存储在ram中,而不是以任何方式压缩或优化.
有没有办法让它以更小的格式将图像存储在ram中?我处在CPU方面比RAM更松弛的情况下,因此将图像对象的大小向下移向jpeg压缩的轻微性能损失将非常值得.
S73*_*17H 11
我的一个项目我只是在动态地从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;
}
Run Code Online (Sandbox Code Playgroud)
要从File获取ImageInputStream,请使用:
ImageIO.createImageInputStream(new File("C:\\image.jpeg"));
Run Code Online (Sandbox Code Playgroud)
如您所见,此实现也尊重图像原始宽高比.您可以选择注册IIOReadProgressListener,以便您可以跟踪到目前为止已读取了多少图像.这对于显示进度条非常有用,例如,如果通过网络读取图像...但不是必需的,您只需指定null即可.
为什么这与您的情况特别相关?它永远不会将整个图像读入内存,就像您需要它一样,以便它可以以所需的分辨率显示.对于巨大的图像非常有效,即使是那些10英寸MB的磁盘也是如此.
小智 1
磁盘上 JPG 文件的大小完全无关。
文件的像素尺寸为。如果您的图像为 15 兆像素,则预计它需要大量 RAM 才能加载原始未压缩版本。
将图像尺寸重新调整为您需要的大小,这是您可以做的最好的事情,而无需使用不太丰富的色彩空间表示。
| 归档时间: |
|
| 查看次数: |
8957 次 |
| 最近记录: |