我有一些巨大的图像,无法整体加载到内存中。我知道图像是平铺的,并且类ImageReader
中的所有方法都为我提供了合理的非零返回值
getTileGridXOffset(int)
,
getTileGridYOffset(int)
,
getTileWidth(int)
和
getTileHeight(int)
。
我现在的问题是我只想读取一个磁贴,以避免使用ImageReader.readtTile(int, int, int)
方法将整个图像加载到内存中。但是,如何确定切片坐标的有效值是什么?
界面getNumXTiles()
中有getNumYTiles()
和RenderedImage
方法,但所有尝试从源创建渲染图像都会导致out of memory/java heap space
错误。
理论上,瓷砖坐标可以是任何东西,我尝试readtTile(0, -1, -1)
,这也适用于我测试的一些图像。
我还尝试了解这些图片的元数据,但我没有找到有关图片布局的任何有用信息。
是否有人可以告诉我如何获取图块坐标的值而无需将整个图像读入内存?还有另一种方法不需要ImageLayout
的实例吗?
非常感谢您的协助。
答案 0 :(得分:0)
首先,您应该使用ImageReader
检查有问题的isImageTiled(imageIndex)
是否支持给定图像的平铺。如果没有,则不能指望其他方法中的有用值。
然后如果确实如此,给定图像的所有图块的大小必须相等(但是每列中的最后一个图块/最后一行可能会被截断)。对于我所知的所有平铺文件格式(即TIFF)也是如此。因此,使用这些知识,可以计算出两个维度中的图块数量:
// Calculate number of x tiles/y tiles:
int cols = (int) Math.ceil(reader.getWidth(imageIndex) / (double) reader.getTileWidth(imageIndex));
int rows = (int) Math.ceil(reader.getHeight(imageIndex) / (double) reader.getTileHeight(imageIndex));
然后,您可以遍历切片索引(第一个切片始终为0,0):
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
BufferedImage tile = reader.readTile(imageIndex, col, row);
// ...do more processing...
}
}
或者,如果您只想获得一个磁贴,您显然不需要双for
循环。 :-)
注意:对于不支持平铺的ImageReader
s /图像,getTileWidth
和getTileHeight
方法将返回与getWidth
和{{1}相同的方法}, 分别。
此外,getHeight
API文档说:
如果参数超出范围,则抛出
readTile
。如果图像未平铺,则值0,0将返回整个图像;任何其他值都会导致IllegalArgumentException
被抛出。
这意味着您的示例IllegalArgumentException
应始终抛出readtTile(0, -1, -1)
而不管平铺...我怀疑某些实现可能会完全忽略切片坐标,并且无论如何都会为您提供整个图像。
PS:IllegalArgumentException
接口 理论上可以帮助你。但它需要RenderedImage
中的特殊实现。在大多数情况下,您将获得正常ImageReader
(实现BufferedImage
),并且是单个(1x1)磁贴。