寻找像 djpeg 这样的东西,它使用 O(1) RAM 通过子采样来调整大小,但是在 java 中并且能够处理 jpg、png、gif、bmp 等。也许已经存在一些实现。如何调整流中的图像大小(使用最少的 RAM)?
问问题
2421 次
2 回答
6
对FileImageInputStream
特定的图像格式一无所知,它只是方便从文件支持的输入中读取整数、短裤、字节、字节数组等。文件格式支持由各种ImageReader
实现处理。
对您的问题的简短回答是:您无法在不加载图像的情况下真正调整图像大小。
从 djpeg 的描述:
djpeg 解压缩命名的 JPEG 文件 [...]
(重点是我的)
但是,您可以对图像进行二次采样,这非常快(对于大多数格式),并且会使用更少的内存。看看ImageReadParam.setSourceSubSampling
方法和ImageReader.read(int, ImageReadParam)
方法。这将创建一个调整大小的图像,非常类似于“最近邻”或“点采样”算法(即,结果不一定看起来很好)。
可以先组合二次采样,然后再调整质量,以节省内存,并可能获得可接受的结果。这完全取决于您期望/需要的质量。
如果您真的非常想调整图像大小而不将它们加载到堆内存中(也许您的图像很大),我已经编写了一些使用内存映射文件的类,您可以查看它们,但是它们非常慢。
于 2013-06-27T09:18:46.677 回答
2
- 十二猴罐子可以读取非 RGB jpeg
setSourceSubSampling
并setSourceRegion
允许在流中调整图像大小。- 不支持渐进式 jpeg
- 不支持大输出文件
例子:
File javaStreamSubsample(File inFile, int s, Rectangle sourceRegion) throws IOException {
File outFile = File.createTempFile("img", null);;
ImageInputStream input = ImageIO.createImageInputStream(inFile);
try {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
ImageReader reader = readers.next();
try {
reader.setInput(input);
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceSubsampling(s, s, 0, 0);
if(sourceRegion!=null){
param.setSourceRegion(sourceRegion);
}
BufferedImage image = reader.read(0, param);
ImageIO.write(image, "jpg", outFile);
}finally {
reader.dispose();
}
} finally {
input.close();
}
return outFile;
}
于 2015-06-09T21:21:41.223 回答