openlayers+geotiff.js实现tiff格式图片导出

OpenLayers.js + geotiff.js实现tiff格式图片导出

引言

OpenLayers是一个开源的JavaScript库,用于在Web浏览器中呈现交互式地图。它本身并不提供导出地图为TIFF图片的功能,但可以结合其他库或服务来实现这个功能。一种可能的解决方案是使用Canvas和FileSaver.js库。Canvas可以将网页上的内容渲染为图像,而FileSaver.js库可以将生成的图像保存到本地。在生成TIFF文件上我选择geotiff.js这个库,GeoTIFF.js可以在TIFF图像中嵌入地理元数据,并且支持多种地图投影坐标系。

步骤

  1. 下载所需要的库

    npm install geotiff
    npm install file-saver
    
  2. 获取canvas信息

    这一步可以参考openlayers导出PNG的官方示例:https://openlayers.org/en/v6.15.1/examples/export-map.html

    具体思路就是获取地图所在的元素,转化为画布绘制,这里主要提供思路,所以只针对整个显示区域做导出,需要自定义导出范围的朋友可以私信或者评论,我再补充对应的例子,这里以tiff制做为主。

    • 创建地图

      let map = new Map({
          target: 'olMap',
          layers: [layers],
          controls: defaults({
              attributionOptions: {
                  collapsible: false,
              }
          }),
          view: new View({
              center: fromLonLat([0,0]),
              zoom: 15
          })
      })
      
    • 获取地图范围

      // 获取地图范围信息
      let extent = map.getView().calculateExtent(this.map.getSize())
      let bottomLeft = [extent[0], extent[1]]
      let topRight = [extent[2], extent[3]]
      let bbox = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]
      
    • 获取投影和分辨率

      let resolution = map.getView().getResolution()
      let projection = map.getView().getProjection().getCode()
      
    • 将地图转换为canvas

      map.once('postcompose', function (event) {
          let canvas = event.context.canvas;
          let imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data
          })
      

​ 至此,我们得到了需要导出范围的地图canvas及图像数据,接下来,我们需要将数据写入tiff文件中,即需要用到geotiff中的writeArrayBuffer方法。

  1. 创建tiff文件实例

    • 导入所需方法

      import {writeArrayBuffer} from 'geotiff'
      
    • 编写元数据

      // 将图像数据写入GeoTIFF文件
      let tifImage = writeArrayBuffer(imageData, {
          width: canvas.width,
          height: canvas.height,
          GeographicTypeGeoKey: projection,
          ModelTiepoint: [0, 0, 0, bbox[0], bbox[3], 0],
          ModelPixelScale: [resolution, resolution, 0],
          GTModelTypeGeoKey: 2,
      })
      

      这里将步骤3中得到的地图元素写入tiff文件,{}中为元数据,这里我依次定义了图片的长宽、投影类型、模型点配准(这里我理解为canvas坐标和地理坐标的配准)、模型像素比例尺、模型类型(0表示未定义或未知;1表示2D投影坐标参考系;2表示地理二维坐标参考系;3表示3D坐标参考系;32767表示自定义)。

      这些参数可以查询GEOTIFF文件规范,根据需要添加,我这里只需要图片能导入ArcGIS能显示具体坐标信息即可。

    • geotiff.js源代码展示的属性信息

      [
          'Compression',
          'ExtraSamples',
          'GeographicTypeGeoKey',
          'GTModelTypeGeoKey',
          'GTRasterTypeGeoKey',
          'ImageLength', // synonym of ImageHeight
          'ImageWidth',
          'Orientation',
          'PhotometricInterpretation',
          'ProjectedCSTypeGeoKey',
          'PlanarConfiguration',
          'ResolutionUnit',
          'SamplesPerPixel',
          'XPosition',
          'YPosition',
        ]
      
  2. 导出图片

    • 导入方法

      import { saveAs } from 'file-saver'
      
    • 转blob格式

      let tiffBlob = new Blob([tifImage])
      
    • 导出

      saveAs(tiffBlob, 'map.tiff')
      
  3. 全部代码

    import {writeArrayBuffer} from 'geotiff'
    import { saveAs } from 'file-saver'
    
    let map = new Map({
        target: 'olMap',
        layers: [layers],
        controls: defaults({
            attributionOptions: {
                collapsible: false,
            }
        }),
        view: new View({
            center: fromLonLat([0,0]),
            zoom: 15
        })
    })
    
    // 获取地图范围信息
    let extent = map.getView().calculateExtent(this.map.getSize())
    let bottomLeft = [extent[0], extent[1]]
    let topRight = [extent[2], extent[3]]
    let bbox = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]
    
    let resolution = map.getView().getResolution()
    let projection = map.getView().getProjection().getCode()
    
    map.once('postcompose', function (event) {
        let canvas = event.context.canvas;
        let imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data
        
        // 将图像数据写入GeoTIFF文件
        let tifImage = writeArrayBuffer(imageData, {
            width: canvas.width,
            height: canvas.height,
            GeographicTypeGeoKey: projection,
            ModelTiepoint: [0, 0, 0, bbox[0], bbox[3], 0],
            ModelPixelScale: [resolution, resolution, 0],
            GTModelTypeGeoKey: 2,
        })
        
        let tiffBlob = new Blob([tifImage])
        saveAs(tiffBlob, 'map.tiff')
    })
    

参考资料

  • GeoTiff格式说明:

    • https://blog.csdn.net/oYinHeZhiGuang/article/details/121904325
    • https://www.mathworks.com/help/map/ref/geotiffwrite.html
    • https://blog.csdn.net/DLW__/article/details/124024718
  • geotiff的github链接:https://github.com/geotiffjs/geotiff.js/

    官方文档:https://geotiffjs.github.io/geotiff.js/module-geotiff.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值