【问题标题】:Read region from very large image file in Java从Java中的非常大的图像文件中读取区域
【发布时间】:2013-08-30 06:20:24
【问题描述】:

是否有一个 Java 库可以读取非常大的图像(例如 JPEG)文件(> 10,000 x 10,000 像素)的区域,而无需将整个图像保存在内存中。

或者,哪个 Java 库能够以最少的开销处理非常大的图像文件。

【问题讨论】:

  • 您想从整个图像中读取字节偏移量和长度还是几个像素的区域?
  • 以像素为单位的区域。
  • 好吧,试试我下面贴的答案。

标签: java image-processing jai


【解决方案1】:

标准 ImageIO 允许您读取(大)图像的区域,而无需先将整个图像读入内存。

Rectangle sourceRegion = new Rectangle(x, y, w, h); // The region you want to extract

ImageInputStream stream = ImageIO.createImageInputStream(input); // File or input stream
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);

if (readers.hasNext()) {
    ImageReader reader = readers.next();
    reader.setInput(stream);

    ImageReadParam param = reader.getDefaultReadParam();
    param.setSourceRegion(sourceRegion); // Set region

    BufferedImage image = reader.read(0, param); // Will read only the region specified
}

【讨论】:

  • 嗨!感谢您剪掉了非常好的代码。实际上是否可以在不读取整个图像的情况下将区域写入图像?我的区域只有 100px 的正方形,我喜欢将它存储在一个巨大的 Jpeg 中的某个位置。
  • @Durin 是的,在某些文件格式中可能是可能的。 ImageIO API 支持它。但是请提出一个新问题! :-)
【解决方案2】:

例如,您可以使用 RandomAccessFile 从文件中间读取: 但问题是整个 jpeg 图像在 DCT 量化后被压缩(http://www.fileformat.info/mirror/egff/ch09_06.htm),所以我认为不读取整个文件到内存就不可能读取片段。

【讨论】:

  • 我对JPEG和DCT量化只有肤浅的了解,但我相信DCT适用于8x8像素块,应该可以避免解码所有块以获得区域。当然有必要从图像的其他部分获取一些系数/信息,但这并不意味着我必须将所有数据读入内存......但我可能是错的。
【解决方案3】:

您可以使用BufferedImage 来做您需要的事情。

// Set these variables according to your requirements
int regionX, regionY, regionWidth, regionHeight;    

BufferedImage image = ImageIO.read(new File("/path/to/image.jpg"));
BufferedImage region = image.getSubimage(regionX, regionY, regionWidth, regionHeight);

然后您可以随意处理区域子图像。

【讨论】:

  • @Raman:您描述了适用于中等大小图像的标准方法。您将 整个 图像读入 BufferedImage,然后提取该区域。我的问题是这需要大量内存和非常大的图像,因为所有像素都被解码并保存在内存中。对于大小为 20,000x30,000 的图像,这将需要近 2GB 的内存;另外,解码器花时间解码从未使用过的像素......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
相关资源
最近更新 更多