Java ImageIO 读取图像 byte[] 到预分配的 BufferedImage
Java ImageIO read image byte[] into pre-allocated BufferedImage
我正在使用 ImageIO 和 JAI,想将字节数组读入 BufferedImage
。 byte[]
包含 JP2000 编码图像的数据,它相当大,大约 100MB。我目前正在做类似的事情:
byte[] imageDataBytes = ...
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
BufferedImage imageData = ImageIO.read(imageStream);
每次调用 read()
时,ImageIO 似乎都在创建一个 new BufferedImage
。
问题:
有没有办法告诉 ImageIO 读取图像字节数据并将其解码为预分配的可变 BufferedImage
?
我通过 Javadoc 进行了一些搜索,发现 BufferedImage
将其数据存储在 Raster
对象中,而该对象将其数据存储在 DataBuffer
对象中。所以我知道任何存在的解决方案在技术上都不会写入 BufferedImage
,而是直接写入 DataBuffer
.
了解所有图像的大小都相同可能会有所帮助:大约 10,000 x 10,000,因此读取图像与缓冲图像不对齐应该不会有任何问题。最终,我希望有一个缓冲图像、栅格或数据缓冲区的对象池,并在每次使用 ImageIO 读取时从池中借用。像这样的伪代码:
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
WritableRaster raster = ObjectPool.getAvailableRaster();
ImageIO.readToRaster(imageStream, raster);
BufferedImage imageData = new BufferedImage(raster);
我确信有一个简单的解决方案。如有任何帮助,我们将不胜感激!
是的,您可以 set the destination image ImageReadParam 对象。但是,有一个警告:BufferedImage 必须具有与正在加载的图像匹配的 ColorModel 和 SampleModel。
我不确定 JPEG2000 图像,但常规 JPEG 通常是 RGB 图像,因此 TYPE_INT_RGB 的图像应该足够了:
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);
}
}
对于那些发现自己处于这种情况的人,VGR 的答案很有效。我想专门为包含元数据的 JPEG-2000 图像添加,使用
reader.setInput(stream, true, true);
而不是
reader.setInput(stream);
这避免了 NullPointer 异常。你可以在这里读更多关于它的内容:
https://issues.apache.org/jira/browse/PDFBOX-2103
我正在使用 ImageIO 和 JAI,想将字节数组读入 BufferedImage
。 byte[]
包含 JP2000 编码图像的数据,它相当大,大约 100MB。我目前正在做类似的事情:
byte[] imageDataBytes = ...
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
BufferedImage imageData = ImageIO.read(imageStream);
每次调用 read()
时,ImageIO 似乎都在创建一个 new BufferedImage
。
问题:
有没有办法告诉 ImageIO 读取图像字节数据并将其解码为预分配的可变 BufferedImage
?
我通过 Javadoc 进行了一些搜索,发现 BufferedImage
将其数据存储在 Raster
对象中,而该对象将其数据存储在 DataBuffer
对象中。所以我知道任何存在的解决方案在技术上都不会写入 BufferedImage
,而是直接写入 DataBuffer
.
了解所有图像的大小都相同可能会有所帮助:大约 10,000 x 10,000,因此读取图像与缓冲图像不对齐应该不会有任何问题。最终,我希望有一个缓冲图像、栅格或数据缓冲区的对象池,并在每次使用 ImageIO 读取时从池中借用。像这样的伪代码:
InputStream imageStream = new ByteArrayInputStream(imageDataBytes);
WritableRaster raster = ObjectPool.getAvailableRaster();
ImageIO.readToRaster(imageStream, raster);
BufferedImage imageData = new BufferedImage(raster);
我确信有一个简单的解决方案。如有任何帮助,我们将不胜感激!
是的,您可以 set the destination image ImageReadParam 对象。但是,有一个警告:BufferedImage 必须具有与正在加载的图像匹配的 ColorModel 和 SampleModel。
我不确定 JPEG2000 图像,但常规 JPEG 通常是 RGB 图像,因此 TYPE_INT_RGB 的图像应该足够了:
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);
}
}
对于那些发现自己处于这种情况的人,VGR 的答案很有效。我想专门为包含元数据的 JPEG-2000 图像添加,使用
reader.setInput(stream, true, true);
而不是
reader.setInput(stream);
这避免了 NullPointer 异常。你可以在这里读更多关于它的内容: https://issues.apache.org/jira/browse/PDFBOX-2103