我想写一个地图查看器,我必须处理大地图图像文件的小图块,并且需要平铺大图,现在的问题是将大图平铺到小图块(250 * 250 像素或类似大小)所以上,我使用 ImageMagic 程序来做,但现在有问题是任何其他编程方法或应用程序做平铺?我可以用 Java 中的 JAI 来做吗?如何?
6 回答
对于像您这样的大图像尺寸,您最好使用 JPEG 文件的无损编辑。这不仅更快,因为不需要渲染图像,而且还保持质量,因为图像没有重新压缩。
无损编辑适用于块,通常为 16px 正方形。虽然对某些应用程序有限制,但这似乎很适合映射。您可以通过首先将图像无损裁剪为大小块来实现不同缩放级别的平铺。(这是快速有效的,因为图像没有被渲染。)这为您提供了全缩放的平铺。要创建较低级别的缩放,请组合 2x2 块并将它们缩小到 1 个块的大小。下一个级别使用 4x4 瓷砖和 8x8 等等,每次都缩小到一个瓷砖。在某些时候,当图块数量太大时,您可以选择使用缩放图块作为基础资源。例如,在缩放级别 8 下,这将需要 256x256 的图块。这可能难以处理,因此您可以使用缩放级别 4 的 16x16 平铺。
维基百科有更多关于无损编辑的内容,以及一些实现库的链接。
你有没有试过自己用java做?我用 (WARNING, big image, can crash your browser, use "save as...") this image试过了。虽然需要使用额外的内存来运行 ( -Xmx400M
)。
public class ImageTile {
public static void main(String[] args) throws IOException {
Dimension tileDim = new Dimension(250, 250);
BufferedImage image = ImageIO.read(new File(args[0]));
Dimension imageDim = new Dimension(image.getWidth(), image.getHeight());
for(int y = 0; y < imageDim.height; y += tileDim.height) {
for(int x = 0; x < imageDim.width; x += tileDim.width) {
int w = Math.min(x + tileDim.width, imageDim.width) - x;
int h = Math.min(y + tileDim.height, imageDim.height) - y;
BufferedImage tile = image.getSubimage(x, y, w, h);
ImageIO.write(tile, "JPG", new File("tile-"+x+"-"+y+".jpg"));
}
}
}
}
imagemagick 使用-tile进行平铺。它更像是对图像的重复,但可能很有用,尤其是。因为你已经在使用它了。但是,如果您的意思是生成的无缝平铺,我不确定 imagemagick 是否可以做到这一点。
GDAL附带一个名为 gdal2tiles.py 的脚本,它可以完全按照您的要求进行操作,包括格式化用于 Google 地图、OpenLayers 等的图块。
似乎也有更新版本的GDAL2Tiles。
使用 r-tree 进行高效访问的巨型纹理怎么样?显然它可以使用 128000x128000 像素的图像。
JAI 依赖于平台,现在看起来像是一个死项目。
我建议使用开源程序imagemagick。尽管它依赖于平台,但它可用于与 JAI 相同的平台,但具有完整的社区支持。
关于 imagemagick 的大图像的技巧是使用它的“流”命令而不是转换命令。Stream 仅读取图像的相关部分并将提取的部分保存为原始数据。然后,您需要“转换”以将小的原始数据保存为 jpeg。
将大小为 800x600 的块从位置 0x0 保存到 tile.jpeg 的示例:
stream -extract 800x600+0+0 large.jpeg tile.rgb
convert -depth 8 -size 800x600 rgb:tile.rgb tile.jpeg
(在windows上运行时,一定要使用ImageMagick的convert.exe,因为windows有一个名为“convert”的命令。)
仅使用 TIFF 图像时,apache Sanselan可能是正确的选择——它是一个纯 Java 图像库。此外,JAI 似乎包含一个独立于平台的 TIFF 编解码器。