I'm working with ImageIO and JAI and want to read a byte array into a BufferedImage
. The byte[]
contains data for a JP2000 encoded image, and it's fairly large, around 100MB. I'm currently doing something like:
byte[] imageDataBytes = ...
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
BufferedImage imageData = ImageIO.read(imageStream);
It seems that ImageIO is creating a new BufferedImage
each time read()
is called.
Question:
Is there a way to tell ImageIO to read and decode the image byte data into a pre-allocated mutable BufferedImage
?
I did some searching through the Javadocs and found that the BufferedImage
stores its data in a Raster
object, which stores its data in a DataBuffer
object. So I'm aware any solution that exists will technically not be writing to the BufferedImage
, but instead will be directly writing to the DataBuffer
.
It may help to know that all images are the same size: roughly 10,000 x 10,000, so there shouldn't be any problems with the read image not aligning with the buffered image. Ultimately, I would like to have an object pool of buffered images, or rasters, or data buffers, and borrow from the pool every time I read using ImageIO. Something like this pseudocode:
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
WritableRaster raster = ObjectPool.getAvailableRaster();
ImageIO.readToRaster(imageStream, raster);
BufferedImage imageData = new BufferedImage(raster);
I'm sure there's a simple solution out there. Any help would be appreciated!
Yes, you can set the destination image of an ImageReadParam object. However, there is a caveat: the BufferedImage must have a ColorModel and SampleModel that match the image being loaded.
I’m not sure about JPEG2000 images, but regular JPEGs are usually RGB images, so an image of TYPE_INT_RGB should suffice:
BufferedImage image = new BufferedImage(10000, 10000,
BufferedImage.TYPE_INT_RGB);
while (bytesAvailable) {
byte[] imageDataBytes = getImageBytes();
try (InputStream in = new ByteArrayInputStream(imageDataBytes);
ImageInputStream stream = ImageIO.createImageInputStream(in)) {
ImageReader reader = ImageIO.getImageReaders(stream).next();
reader.setInput(stream);
ImageReadParam param = reader.getDefaultReadParam();
param.setDestination(image);
reader.read(0, param);
}
}