Looking for something like djpeg which uses O(1) RAM to resize by sub sampling, but in java and able to handle jpg, png, gif, bmp, etc. Maybe some implementation already exists. How to resize an image in a stream (using minimal RAM)?
Resizing in Preview To start, select the image you want to resize by clicking Open With > Preview. Once you have your image opened, go to Tools in your menu bar and select Adjust Size.
In the Preview app on your Mac, open the file you want to change. Choose Tools > Adjust Size, then select “Resample image.” Enter a smaller value in the Resolution field. The new size is shown at the bottom.
The FileImageInputStream
doesn't know anything about specific image formats, it's just convenience for reading ints, shorts, bytes, byte arrays, etc, from a file-backed input. File format support is handled by the various ImageReader
implementations.
The short answer to your question is: You can't really resize an image without loading it.
From the description of djpeg:
djpeg decompresses the named JPEG file [...]
(Emphasis is mine)
However, you can subsample images, wich is really fast (for most formats), and will uses less memory. Have a look at the ImageReadParam.setSourceSubSampling
method and the ImageReader.read(int, ImageReadParam)
method. This will create a resized image, quite similar to the "nearest neighbour" or "point sampling" algorithms (ie. the results won't necessary look good).
It's possible to combine subsampling first, with better quality resizing afterwards, to save memory, and possibly get acceptable results. It all depends on what quality you expect/need.
If you really, really want to resize images without loading them into heap memory (perhaps your images are huge), I've written some classes that use memory mapped files you can look at, but they are painfully slow.
setSourceSubSampling
and setSourceRegion
permit resizing images in a stream.Example:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With