从大的jp2图像读取像素,而不将整个图像加载到内存中

时间:2015-01-02 15:20:05

标签: java image

我试图从java中的大图片中读取部件。我的图片大小超过700 MB。我已经使用了这个代码,它通常读取像素而不将整个图像加载到内存中:

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

然而,我收到了错误:

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)

请帮忙阅读这张大图中的部分内容?

1 个答案:

答案 0 :(得分:0)

有不同的方法可以将部分图像加载到内存中,然后再处理它。您可以尝试以下方法来读取片段:

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;
}

并且这样称呼它:

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主题中标记为正确答案。

如果需要,可以使用此技术最终将整个图像读入内存。

修改
您尝试处理的图像的分辨率大于阵列可以具有的分辨率(95168x154832)。所以基本上你将无法读取图像,因为ImageIO.createImageInputStream()试图将整个图像加载到阵列AFAIK中。

可以做的是使用名为ImgLib2的库。 Here你可以找到一些例子。 ImgLib2使用多维数组来读取(大)图像数据,因此它大于ImageIO可以处理的数据。