如何从非地理来源为传单制作平铺的图像金字塔

时间:2018-07-14 20:18:13

标签: javascript d3.js leaflet dc.leaflet.js

假设我有一个非地理图像,而不是普通的地图。举例来说,例如X射线,MRI扫描或显微镜图像,我想使用传单,以便可以放大,缩小并在一些预定点上放置一些标记。

我已经阅读了Non-geographical maps中的示例,但此例演示了使用单个图像而不是平铺图像。我宁愿使用图块,因为我的图像会很大。还有其他适合我上述情况的情况吗?我正在研究rastercoords,但尚未确定该方法是否适用于其中的任何栅格文件,仅适用于纯地图。

2 个答案:

答案 0 :(得分:6)

我的经验是如何根据PDFs或高分辨率图像或non-slippy maps等源创建平滑地图。无论如何,我都想写一篇文章,所以让这个答案成为尚未撰写的文章的草稿。

举个例子,这里是PDF map of European inland waterways,上面有矢量图形,这里是slippy map

基本上,最合理的方法是制作一个标准的图块集,然后让Leaflet显示它。即为每个缩放级别生成大小为256x256的图块。
您不希望将大图像作为图层,因为这对于浏览器来说会很沉重。您也不想在浏览器中调整大小,这会导致质量下降。

幸运的是,使用ImageMagick创建图块非常容易。这就是我的方法。

确定所需的缩放比例

首先,确定所需的缩放级别。这取决于地图,根据我的经验,您最多需要5-7缩放级别。让我们以5个缩放级别为例。生产的级别越多,对硬件的要求就越高。下面的方法可能不适用于超过7-8的缩放级别。

渲染或调整源图像大小

接下来,为每个缩放级别渲染或调整图像大小。您必须生成尺寸等于以下之一的图像:

  • 256像素,位于级别0
  • 512像素在第1级上
  • 1024像素在第2级上
  • 2048像素,位于第3级
  • 4096像素,位于第4级
  • 等等。

注意:此步骤的结果是巨大的图像。级别5约为10 MB,级别6约为20 MB,级别7约为40 MB。小心尝试在“常规”工具中打开这些图像。

调整普通高分辨率图像的大小

如果您的来源是高分辨率图像,只需将convert -resizex*256**256*x一起使用:

convert images\source.jpg -resize   x256 images\0.jpg
convert images\source.jpg -resize   x512 images\1.jpg
convert images\source.jpg -resize  x1024 images\2.jpg
convert images\source.jpg -resize  x2048 images\3.jpg
convert images\source.jpg -resize  x4096 images\4.jpg
convert images\source.jpg -resize  x8192 images\5.jpg

如果您有多个缩放级别不同的缩放图像(我想这是MRI扫描的情况),请选择缩放最近的源图像。

使用已平铺的图像

在某些情况下,源图像已被切成小块。这在您想滑动的“旧”地图客户端中很典型。 This is an example,图块称为vk-X-Y.jpg,并经过重叠切割。在这种情况下,您首先必须裁剪图像:

magick data\vk-0-0.jpg  -crop 522x373+0x0 images\t-0-0.jpg
magick data\vk-1-0.jpg  -crop 522x373+0x0 images\t-1-0.jpg
magick data\vk-2-0.jpg  -crop 522x373+0x0 images\t-2-0.jpg
magick data\vk-3-0.jpg  -crop 522x373+0x0 images\t-3-0.jpg
magick data\vk-4-0.jpg  -crop 522x373+0x0 images\t-4-0.jpg
magick data\vk-5-0.jpg  -crop 650x373+0x0 images\t-5-0.jpg
...

要弄清楚作物参数将垂直和水平方向相邻的图块加载到图形编辑器中,请尝试将它们匹配并检查偏移坐标。

然后,在裁剪图块时,将它们附加到大图像上:

magick images\t-0-0.jpg images\t-1-0.jpg images\t-2-0.jpg images\t-3-0.jpg images\t-4-0.jpg images\t-5-0.jpg +append images\t-0.jpg
...
magick images\t-0.jpg images\t-1.jpg images\t-2.jpg images\t-3.jpg images\t-4.jpg images\t-5.jpg images\t-6.jpg images\t-7.jpg images\t-8.jpg images\t-9.jpg images\t-10.jpg -append images\t.jpg

此裁剪和追加操作的结果是地图的高分辨率图像。按如上所述将其调整为每个级别。

调整PDF大小

渲染PDF时,我更喜欢使用density调整大小。要计算每个缩放级别的密度(这是Windows命令,请针对Linux进行相应修改):

identify -precision 16 -format "%%[fx:((256/max(w,h))*72)]\n%%[fx:((512/max(w,h))*72)]\n%%[fx:((1024/max(w,h))*72)]\n%%[fx:((2048/max(w,h))*72)]\n%%[fx:((4096/max(w,h))*72)]" source.pdf

这给你类似的东西

21.89073634204276
43.78147268408551
87.56294536817103
175.1258907363421
350.2517814726841

(4096/max(w,h))*72表达式的神奇之处很简单:(目标大小/源大小)*标准DPI。

具有密度渲染图像:

convert -verbose -density 21.89073634204276 source.pdf        images\0.png
convert -verbose -density 43.78147268408551 source.pdf        images\1.png
convert -verbose -density 87.56294536817103 source.pdf        images\2.png
convert -verbose -density 175.1258907363421 source.pdf        images\3.png
convert -verbose -density 350.2517814726841 source.pdf        images\4.png

在更高级别上,这可能会花费很多时间。

在图块中剪切水平图像

这时您应该每层有一张图像。现在我们可以将它们切成小块:

convert -verbose images\0.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\0_%%[filename:tile].png"
convert -verbose images\1.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\1_%%[filename:tile].png"
convert -verbose images\2.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\2_%%[filename:tile].png"
convert -verbose images\3.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\3_%%[filename:tile].png"
convert -verbose images\4.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\4_%%[filename:tile].png"
convert -verbose images\5.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\5_%%[filename:tile].png"

这将产生如下文件:

  • tiles/0_0_0.png
  • tiles/1_0_0.png
  • tiles/1_0_1.png
  • tiles/1_1_0.png
  • tiles/1_1_1.png

这是256x256大小的静态预渲染图块。

配置传单

现在,您只需要配置Leaflet。假设磁贴文件相对于HTML文件位于../tiles目录中,只需:

L.tileLayer('../tiles/{z}_{x}_{y}.png', {
    maxZoom: 5,
    noWrap: true,                     
    attribution: 'Some Attribution'
}).addTo(map);

如果要设置适当的初始视点,请缩放/移动到所需位置,在开发工具中打开JavaScript控制台,然后输入:

map.getCenter();
map.getZoom();

然后在初始化地图时使用打印的参数:

var map = L.map('map').setView([-26.3525, -65.0390], 3);

要添加标记:

L.marker([-26.3525, -65.0390], {title: "Hi there!"}).addTo(map);

即使平移或缩放,标记也将保持在同一位置。


以下是其中一个项目:

答案 1 :(得分:3)

libvips的一项操作可以在一个命令中制作用于活页的草绘地图图块。

例如,使用此PDF map of European inland waterways(谢谢@lexicore!),您可以输入:

vips dzsave European_inland_waterways_-_2012.pdf[dpi=600] xxx --layout google

,它将创建一个名为xxx的目录,其中包含您所有的图块,可以随时将其上载到服务器。大约需要15秒(无论如何在这台笔记本电脑上)。

速度快,几乎不需要内存。具体细节随文件格式的不同而有所不同,但是对于许多格式,它可以并行解码输入,构造所有金字塔层,并写入输出图块,而无需将整个输入图像加载到其中。记忆。我经常在一台普通的笔记本电脑上渲染超过300,000 x 300,000像素的金字塔。

它可以执行一些有用的文件类型,以及通常的tiff,PNG,JPG等,包括SVG,FITS,DICOM和OpenSlide之类的文件。它也可以使金字塔成为Deepzoom和zoomify。

Windows主机的一个不错的功能是能够将图块集写入zip文件而不是文件系统中。 Windows创建文件的速度相当慢-使用大型金字塔和小图块,仅在创建文件时就可以花费将近75%的CPU时间。改为写入zip文件,您可能会看到3倍的加速:

vips dzsave huge.tif xxx.zip --layout google

当然,zip更容易上传到服务器。

有一个chapter in the libvips manual introducing dzsave并显示所有选项。