OpenLayers 加载投影坐标GeoTIFF影像

前言

GeoTIFF是开放地理控件联盟(OGC)实施标准,在TIFF的基础上,嵌入了地理空间元数据,也就是说,GeoTIFF是带有地理空间参考和地理数据的TIFF文件。其中GeoTIFF元数据包括坐标系、地图投影以及特定位置信息等。GeoTIFF格式广泛应用于航空影像、卫星影像以及数字高程模型中。

在上节介绍了OpenLayers加载iis部署的GeoTIFF影像.

本节主要介绍采用Blob的方式加载GeoTIFF影像。OpenLayers加载iis部署的GeoTIFF影像链接:

1. 下载GeoTIFF影像数据

下载GeoTIFF数据,请参考GIS 影像数据源介绍。https://www.yuque.com/u37362584/pg4zca/nmw9pt7fgzkbfx3h#Geag9

2. 添加geotiff.js

OpenLayers中加载GeoTIFF影像之前,需要先引入geotiff.js库。cdn 地址: https://www.jsdelivr.com/package/npm/geotiff

3. IIS部署GeoTIFF文件

在本机测试可以采用windows自带的web服务器iis部署GeoTIFF文件,然后通过http进行访问

4. 加载GeoTIFF影像

查看GeoTIFF元数据信息,明确影像坐标系统。可以通过影像元数据文件进行查看,也可以通过GIS软件如ArcMap查看。

  • 元数据信息

  • ArcMap属性信息

从元数据信息中看到该影像坐标系为WGS 84 / UTM zone 48NEPSG代码为32648。因为OpenLayers默认只支持43263857坐标系,所以需要自定义坐标系。如何自定义坐标系请查看之前的文章插入自定义坐标系的文章

php 复制代码
const def = '+proj=utm +zone=48 +datum=WGS84 +units=m +no_defs +type=crs'
proj4.defs('EPSG:32648', def)
ol.proj.proj4.register(proj4)
const EPSG32648 = new ol.proj.Projection({
    code: "EPSG:32648",
    units: 'm',
    extent: [166021.44, 0.0, 833978.56, 9329005.18], // 投影坐标系范围
    worldExtent: [102.0, 0.0, 108.0, 84.0] // 世界坐标系范围
})

epsg网站中可以看到目标坐标系的详细信息,其中Projected bounds对应extent参数,为投影坐标系范围;WGS84 bounds对应worldExtent参数,为世界坐标系范围。在视图对象中使用自定义坐标系。

php 复制代码
// 方式一:定义view对象
view: new ol.View({
  center: [654900, 2945100],
  zoom: 10,
  projection: EPSG32648
}),
// 方式二:使用source获取view对象
view: source.getView()

5. 完整代码

其中libs文件夹下的包需要更换为自己下载的本地包或者引用在线资源。本示例引用了layui组件,请自行替换。

xml 复制代码
<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>重投影GeoTIFF影像</title>
    <meta charset="utf-8" />

    <script src="../../../libs/proj4.js"></script>
    <script src="../../../js/ol9.2.4.js"></script>
    <script src="../../../libs/layui/layui.js"></script>

    <link rel="stylesheet" href="../../../css/ol9.2.4.css">
    <link rel="stylesheet" href="../../../libs/layui/css/layui.css">

    <script src="https://cdn.jsdelivr.net/npm/geotiff@2.1.3/dist-browser/geotiff.min.js"></script>
    <style>
        * {
            padding: 0;
            margin: 0;
            font-size: 14px;
            font-family: '微软雅黑';
        }

        html,
        body {
            width: 100%;
            height: 100%;
        }

        #map {
            position: absolute;
            top: 50px;
            bottom: 0;
            width: 100%;
        }

        #top-content {
            position: absolute;
            width: 100%;
            height: 50px;
            line-height: 50px;
            background: linear-gradient(135deg, #ff00cc, #ffcc00, #00ffcc, #ff0066);
            color: #fff;
            text-align: center;
            font-size: 32px;
        }

        #top-content span {
            font-size: 32px;
        }

    </style>
</head>

<body>
    <div id="top-content">
        <span>重投影GeoTIFF影像</span>
    </div>
    <div id="map" title="地图显示"></div>
</body>

</html>

<script>
    const source = new ol.source.GeoTIFF({
        sources: [
            {
                // url: "http://localhost/GeoTIFF/tci.tif"
                // url: "http://localhost/GeoTIFF/LC08_B7.tif"
                // url: "http://localhost/GeoTIFF/s1a_clip.tif"
                // url: "http://localhost/GeoTIFF/LC08_B1.tif"
                // url: "http://localhost/GeoTIFF/LE07_clip.tif"
                url: "http://localhost/GeoTIFF/T48RXQ_20230314T032511_TCI_20m.tif"
            }
        ],
        nodata: 0, // 设置无效数据为0
        opaque: true, // 开启透明
        convertToRGB: true // 将色彩系统转换为RGB
    })
    // 加载GeoTIFF影像数据
    const tiffLayer = new ol.layer.WebGLTile({
        source: source
    })

    // 查看元数据信息
    source.getView().then(res => {
        console.log(res)
    })

    const def = '+proj=utm +zone=48 +datum=WGS84 +units=m +no_defs +type=crs'
    proj4.defs('EPSG:32648', def)
    ol.proj.proj4.register(proj4)
    const EPSG32648 = new ol.proj.Projection({
        code: "EPSG:32648",
        units: 'm',
        extent: [166021.44, 0.0, 833978.56, 9329005.18],
        worldExtent: [102.0, 0.0, 108.0, 84.0]
    })

    const map = new ol.Map({
        target: "map",
        loadTilesWhileInteracting: true,
        // view: source.getView(),
        view: new ol.View({
            center: [654900, 2945100],
            zoom: 10,
            projection: EPSG32648
        }),
        // 地图默认控件
        controls: ol.control.defaults.defaults({
            zoom: false,
            attribution: true,
            rotate: true
        })
    })

    map.addLayer(tiffLayer)
</script>
相关推荐
IT_陈寒17 分钟前
被Java的final坑惨了,这些细节你可能也忽略了
前端·人工智能·后端
kyriewen39 分钟前
我带着DeepSeek Harness跑了一周真实需求——这份避坑速查表请收好
前端·ai编程·deepseek
计算机魔术师44 分钟前
OpenAI不单独发o3了,Altman说GPT-5才是终局
前端
一座古城1 小时前
Claude Code 架构源码解析:AI 应用开发的范式跃迁
前端·后端
K哥爬虫1 小时前
【JS 逆向百例】Vaptcha V4 手势验证码逆向分析
前端·后端
用户921080262861 小时前
复盘 AI Coding 工作台的流式链路:从 Sender 输入到 SSE 分流,再到 BubbleList 和右侧预览
前端
了不起的小明1 小时前
SwiftMesh:本地 3D 模型查看器,加密交付 + 转盘录屏一站式搞定,开源免费
前端
默_笙2 小时前
👍 我的代码被 ESLint 抓包了:单引号、var、没分号——全被当场点名
前端·javascript
搞个锤子哟2 小时前
vue项目引入icon的问题
前端
树上有只程序猿2 小时前
当低代码遇上AI,一个开发者的真实感悟
前端