webgis —— geoserver 更优秀的瓦片格式

前言

刚进目前所在的这家公司之前,其实我没有做过 webgis 方面的开发工作的,所以对于 gis 开发,我算是个完完全全的新手。

那时候,我甚至连 wmts、wms 服务都不太能分得清。更不要说什么 openlayers、cesium、geoserver 这些了,统统都没怎么用过。

想想,人对于未知的东西,就会产生恐惧。

而客服恐惧的最好方式,就是不停的学习。

很多时候,有了好的学习资料,有了好的学习方式,甚至于有了好的老师,完全可以让你事半功倍。

相反,如果这些都没有,也只能让你事倍功半了。

回过头来想想,对于 webgis 方面的学习,真可谓是一路坎坷,甚至于比自学前端的经历更让人难忘。

虽然很多人都说前端简单,但是如果你只是写写 html、css,而且只满足于应付日常的工作,确实简单。

但是,在众多的前端领域中,如果你选择的是我之前做过的数据可视化方向,以及现在做的 webgis 方向,你会真真切切的感受到,那些口口声声说简单的人简直是睁着眼睛说瞎话。

对于前端数据可视化工程师和 webgis 工程师来说,首先,你得是个优秀的前端工程师,也就是说,大部分前端的会的东西,你都要会,并且需要你掌握的游刃有余,这样才能不至于与前端这个岗位脱节。

除了这些以外,你还要学习掌握一些 canvas、webgl 等知识,如果你是做 webgis 方向,你还要了解 gis 方面的一些专业知识。

这几个方面的知识,除了 canvas 稍微简单好啃点,其他都是一些难啃的硬骨头。

初识 webgis

很多东西,你只有接触了,思考了,并在实际的工作中运用了,才会开始慢慢掌握,了解其应用场景,否则,即使是学习了,也很难融会贯通。

就比如我今天要讲的这个话题,就让我深切的感受到了这一点。

通常情况下,在 web 端,加载影像图都是通过影像切片的方式进行的。

在这里,我不想引用一大段专业的术语,来枯燥的讲述什么是影像切片,因为这毫无意义。

我写并非科普文,只是想从一个外行的从业者,谈谈自己对 webgis 的理解,如果完全“照本宣科”,就背离了我写这篇文章的初衷了。

当然以下的内容,完全是我一家之言,如果有讲的不对的地方,希望更专业的童鞋能像我提出自己的意见,大家一起讨论讨论。

个人理解,之所以出现影像切片,纯粹是由于,对于 web 端来说,需要一个更加合适的方式,来展示影像图。

那么为什么不能直接展示影像图呢?原因显而易见,数据量太大,没法直接在 web 端展示。

一般按照我们通俗的理解来说,一张照片要想越清晰,分辨率就得越高,分辨率越高同时也意味照片越大。

这个道理放在影像图,也就是 geotiff 上,同样适用。

通常情况下,一景数据(也就是卫星拍摄的一张影像),所包含的面积,少则几千平方公里,多则上万平方公里。

试想想,范围这么大,又想看得清晰,geotiff 文件大也可以了理解了。

更别说,我们通常用的影像图,都是用好多景的数据拼凑而成,形成某个区域或地方的某一时期的影像图。

这么大的文件,不可能通过网络直接传输,进而显示到用户的浏览器上的。

那么就有了一些别的方法,可以帮助我们,实现直接远程通过浏览器来查看影像图的目的。

其中 OSGeo 制定的 Web地图服务(WMS) — OGC e-Learning 2.0.0 文档、Web地图平铺服务(WMTS) — OGC e-Learning 2.0.0 文档 等地图可视化服务标准,就是通过一定的分层规则和投影方式,对影像进行分层切割。

使用的时候再按照对应的规则,根据层级请求瓦片资源,进行地图还原。

详细的定义和使用方式,在这里,我就不想过多的赘述了。我想能阅读这篇文章的人,多半对这些知识有过一些了解。

当然,据我了解,也还有一些别的影像使用方式,比如谷歌的 xyz 方式、bing 地图的 QuadTree 方式,甚至于还有不切片的 Cloud Optimized GeoTIFF 的方案。

这些不在我们这里的讨论范围之内,有兴趣的童鞋,可以自行了解下相关知识。

geoserver

谈到了 wmts、wms 以后,一个不能避开的一个话题就是 GeoServer 了。

geoserver 是一款开源的地图服务软件,允许用户共享和编辑地理空间数据。

对 geoserver 不了解的童鞋,可以去官网看下介绍:GeoServer Documentation。要是觉得英文阅读存在障碍的童鞋,还有对应的中文文档:GeoServer用户手册 — GeoServer 2.19.x User Manual。

一般情况下,我们会用 geoserver 发布矢量和栅格图,然后通过调用其提供的 wmts 或者 wms 服务接口来加载地图。

具体如何发布以及如何使用发布的影像,可以查看相关文档进行了解。

最近在使用 geoserver 的时候,突然发现它支持一种很奇怪的 format:

20220706145136.png

当然,之前也并不是没发现,可以选择很多不同的格式来查看发布的数据,只不过以前没去探究原因而已。

这次,刚好需要对项目做一些优化工作,所以就开始注意到这个地方了。

我们知道,png 格式支持 alpha 通道,所以一般情况下,我们会用 png 格式来存储可能会存在透明区域的图。当然,还有 webp 等图片格式,支持 alpha 通道,但是由于 geoserver 默认不支持,就不再这里讨论了。

当改用 image/vnd.jpeg-png 这个方式的时候,wms 请求里,参数发生了一些变化:

20220706150752.png

为了了解清楚其作用,在官方文档 WMS output formats — GeoServer 2.21.x User Manual 找到如下描述。

20220706151325.png

简而言之,这个格式的作用的就是,如果影像中存在透明的区域,就会返回 png 图像;如果不存在,则返回 jpg 格式的图像。

可以说,这种方案,一举解决了,之前项目中的种种弊端。

  1. 影像图不能用 jpeg 格式,因为会存在透明区域,叠加在底图上效果会很难看。所以,以前默认情况下,都是用 png 格式的瓦片。
  2. 但是 png 由于编码的原因,单张瓦片占用内存太大,浪费存储空间。
  3. 一般我们都会用 gwc 的方式来访问影像切片,为了加速访问,我们一般会提前预切好到一定层级的影像瓦片。
  4. 正常情况下,一帮 256 * 256 大小的瓦片,如果内容丰富,jpeg 格式和 png 格式,所占存储空间大小相差十倍之多,导致如果全用 png 格式,对服务器来说,带宽压力很大;对客户端来说,表现的性能也要差的多。
  5. 改用 webp,默认 geosever 不支持该格式; openlayers、cesium 等前端 gis 框架的支持度也有待考证;某些系统的浏览器,默认对 webp 的支持度不高。

基于以上种种因素,这种自动决定使用 jpeg 或者 png 的瓦片方案,简直就是太优秀了。

实际应用

稍微研究了下,改改之前的加载方式,就能很平滑的应用到实际的项目中去了:

// 在 openlayers 中使用
new WMTS({
  name: option.name,
  url: `${config.wmtsPrefix}?transparent=TRUE`,
  layer: option.layerName,
  style: '',
  matrixSet: 'EPSG:4326',
  format: 'image/vnd.jpeg-png',
  wrapX: true,
  tileGrid: new WMTSTileGrid({
    tileSize: [tileSize, tileSize],
    extent: option.extent || [-180.0, -90.0, 180.0, 90.0], // 范围
    origin,
    resolutions,
    matrixIds,
  }),
})

//在 cesium 中使用
new WebMapTileServiceImageryProvider({
    url: `${url}?transparent=TRUE`,
    layer,
    style,
    format: 'image/vnd.jpeg-png',
    rectangle: Rectangle.fromDegrees(
      ...rectangle,
    ),
    tilingScheme: new GeographicTilingScheme({
      numberOfLevelZeroTilesX: 2,
      numberOfLevelZeroTilesY: 1,
    }),
    tileMatrixSetID: 'EPSG:4326',
    tileMatrixLabels: [...Array(zoomMax - zoomMin + 1)].map((_, index) => `EPSG:4326:${zoomMin + index}`),
    minimumLevel: zoomMin,
    maximumLevel: zoomMax,
});

当然,以上两段代码,都是没法正常运行的,需要结合实际的情况,补齐对应的变量方能正常的将 wmts 服务请求的瓦片格式设置为 image/vnd.jpeg-png

当然,如果你不是用 geoserver 作为地图服务器,就不能直接这么用了,这是 geoserver 特有的功能。

如果你也像我们一样,用 gwc 对瓦片做缓存,那么你需要开启对 vnd.jpeg-png 格式的支持,默认 gwc 是没开启对该格式的支持的。

20220706154406.png

结语

老实说,这篇文章,前前后后写了很多次,每次想一鼓作气地写完,却每每半途而废。

本想不落窠臼,却无奈对于 webgis 了解的并不是太透彻,最后难免还是落入了俗套。

不过好歹也是写完了,对自己也算是有了一个交代吧。

世上无难事,只怕有心人。

这句谚语,你越是品味,越是觉得其中蕴涵了丰富的人生经验。

现在回过头去看看,不知不觉,在很多以前看来是未知的领域,已经探索了很久了。

从陌生到熟悉,从畏惧到从容,从一知半解到现在的渐入佳境,这又何尝不是一种美妙的体验呢。

越是深入研究,就越是明白一个道理,其实技术不分高低贵贱,更不分对错,什么场景使用什么技术,也只不过是一种取舍而已。

你可能感兴趣的:(webgis —— geoserver 更优秀的瓦片格式)