Read pixel from a big jp2 image without loading the whole image into memory

匿名 (未验证) 提交于 2019-12-03 08:59:04

问题:

I'm trying to read parts from a big image in java. My image size is more than 700 MB. I have used this code which normally reads pixels without loading the whole image into memory:

Rectangle sourceRegion = new Rectangle(0, 0, 512, 512); // The region you want to extract  ImageInputStream stream = ImageIO.createImageInputStream( new File("/home/dhoha/Downloads/BreastCancer.jp2")); // File or input stream final Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);  if (readers.hasNext()) { ImageReader reader = (ImageReader)readers.next();  reader.setInput(stream, true);  ImageReadParam param = reader.getDefaultReadParam(); param.setSourceRegion(sourceRegion); // Set region  BufferedImage image = reader.read(0, param); // Will read only the region specified 

However, I got the error:

Exception in thread "main" java.lang.IllegalArgumentException: Dimensions (width=95168 height=154832) are too large     at java.awt.image.SampleModel.<init>(SampleModel.java:130)     at java.awt.image.ComponentSampleModel.<init>(ComponentSampleModel.java:146)     at java.awt.image.PixelInterleavedSampleModel.<init>(PixelInterleavedSampleModel.java:87)     at com.sun.media.imageioimpl.plugins.jpeg2000.J2KRenderedImageCodecLib.createSampleModel(J2KRenderedImageCodecLib.java:741)     at com.sun.media.imageioimpl.plugins.jpeg2000.J2KRenderedImageCodecLib.createOriginalSampleModel(J2KRenderedImageCodecLib.java:729)     at com.sun.media.imageioimpl.plugins.jpeg2000.J2KRenderedImageCodecLib.<init>(J2KRenderedImageCodecLib.java:261)     at com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLib.read(J2KImageReaderCodecLib.java:364)     at testJai2.test3.main(test3.java:21) 

Any help please to read parts from this big image?

回答1:

There are different ways to load parts of image to memory and then process it afterwards. You can try out the following method to read fragments:

public static BufferedImage readFragment(InputStream stream, Rectangle rect)             throws IOException {         ImageInputStream imageStream = ImageIO.createImageInputStream(stream);         ImageReader reader = ImageIO.getImageReaders(imageStream).next();         ImageReadParam param = reader.getDefaultReadParam();          param.setSourceRegion(rect);         reader.setInput(imageStream, true, true);         BufferedImage image = reader.read(0, param);          reader.dispose();         imageStream.close();          return image; } 

And calling it like this:

URL url = new URL("..."); // You can use your own stream instead of URL Image chunk = readFragment(url.openStream(), new Rectangle(150, 150, 300, 250)); 

This is marked as a correct answer in this thread.

You can use this technique to finally read the whole image into the memory if you need by doing some simple calculations.

EDIT:
The resolution of the image you are trying to process is larger than an array can have (95168x154832). So basically you will not be able to read the image, since ImageIO.createImageInputStream() tries to load the whole image into an array AFAIK.

What you can do is use a library called ImgLib2. Here you can find some examples. ImgLib2 uses multidimensional arrays to read the (big) image data and so it's larger than ImageIO can handle.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!