寻找类似djpeg的东西,它使用O(1)RAM通过子采样调整大小,但在java中能够处理jpg,png,gif,bmp等等。也许某些实现已经存在。 如何调整流中的图像大小(使用最小的RAM)?
答案 0 :(得分:4)
FileImageInputStream
对特定图像格式一无所知,它只是方便从文件支持的输入读取整数,短路,字节,字节数组等。文件格式支持由各种ImageReader
实现处理。
您的问题的简短回答是:如果不加载图像,则无法真正调整图像大小。
来自djpeg的描述:
djpeg 解压缩指定的JPEG文件[...]
(重点是我的)
但是,您可以对图像进行二次采样,对于大多数格式来说非常快(并且会使用更少的内存)。查看ImageReadParam.setSourceSubSampling
方法和ImageReader.read(int, ImageReadParam)
方法。这将创建一个调整大小的图像,非常类似于“最近邻居”或“点采样”算法(即,结果不一定非常好)。
可以先将子采样结合起来,然后再调整质量,以节省内存,并可能获得可接受的结果。这一切都取决于您期望/需要的质量。
如果你真的,真的想要调整图像大小而不将它们加载到堆内存中(也许你的图像很大),我写了一些使用memory mapped files的类,你可以看一下,但它们很慢。
答案 1 :(得分:0)
setSourceSubSampling
和setSourceRegion
允许在流中调整图片大小。示例:
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;
}