如何调整流中的图像大小(使用最小的RAM)?

时间:2013-06-26 18:01:10

标签: java image image-resizing

寻找类似djpeg的东西,它使用O(1)RAM通过子采样调整大小,但在java中能够处理jpg,png,gif,bmp等等。也许某些实现已经存在。 如何调整流中的图像大小(使用最小的RAM)?

2 个答案:

答案 0 :(得分:4)

FileImageInputStream对特定图像格式一无所知,它只是方便从文件支持的输入读取整数,短路,字节,字节数组等。文件格式支持由各种ImageReader实现处理。

您的问题的简短回答是:如果不加载图像,则无法真正调整图像大小。

来自djpeg的描述:

  

djpeg 解压缩指定的JPEG文件[...]

(重点是我的)

但是,您可以对图像进行二次采样,对于大多数格式来说非常快(并且会使用更少的内存)。查看ImageReadParam.setSourceSubSampling方法和ImageReader.read(int, ImageReadParam)方法。这将创建一个调整大小的图像,非常类似于“最近邻居”或“点采样”算法(即,结果不一定非常好)。

可以先将子采样结合起来,然后再调整质量,以节省内存,并可能获得可接受的结果。这一切都取决于您期望/需要的质量。

如果你真的,真的想要调整图像大小而不将它们加载到堆内存中(也许你的图像很大),我写了一些使用memory mapped files的类,你可以看一下,但它们很慢。

答案 1 :(得分:0)

  • twelvemonkeys罐子可以读取非RGB jpeg
  • setSourceSubSamplingsetSourceRegion允许在流中调整图片大小。
  • 不支持渐进式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;
}