cesium 直接加载 geotiff 影像图
前言
最近碰到了一个需求,需要通过 cesium 直接加载 geotiff 影像图。
咋一听,这个需求好像蛮奇怪,cesium 本身本来就支持加载 tile 影像图,也就是所谓的切片地图。原理其实就是,通过 geoserver 等工具,按照一定的规则和坐标系规则,切好对应的切片。
而 cesium 里面,加载瓦片地图也很简单,想要显示哪个区域的地图,就根据对应的规则,去 geoserver 里请求对应的切片。这些逻辑在 cesium 里面,也已经封装好了,直接调用就好了。
但是如果不想发布到 geoserver,想直接通过 cesium,加载 geotiff 影像文件,来预览影像图呢?
说实话,刚开始碰到这个需求,内心也是没底的,毕竟翻遍了 cesium 的 api,也没有发现,其能支持这种加载方式。
而且,geotiff 影像图的格式,对于我来说,也是一片未知的领域。要不是去年开始接触 cesium 和 geoserver,我根本不知道它的存在。
当然,碰到问题,还是得发挥一个程序员的 geek 精神,先搜索下,看有没有人碰到同样的烦恼。
虽然这种方式不常见,但是,还是有同道中人的,但是结果多不理想,甚至有人直接回复,说不支持这种加载方式。
就在我一度想要放弃的时候,忽然有了灵感。
几个小问题
既然 geotiff 本质上是一张图片,文件不太大的图,甚至直接用一些常见的看图软件就能打开,那么想要贴在 cesium 的 globe 上,又有何难呢?
现在摆在面前的有几个问题:
- 如果 cesium 支持贴 tif 后缀的图,那么皆大欢喜,只要想方设法解析到 geotiff 的坐标范围信息,然后调用 cesium 提供的加载单张图作为图层的 api,再传入范围信息,即可正常的加载该 geotiff 图。
- 如果很不幸,cesium 不支持贴 tif 后缀的图,那么我们就得先解析 geotiff 文件,想办法获取到相关的地理信息和像素信息,拿到像素信息和地理信息以后,像第一种情形一样处理,无非就是多了一步将像素信息处理成 cesium 可以支持的图像信息而已。
- 我们该如何解析出 geotiff 内部的信息呢?
接下来,就让我们对提出的问题,一个个尝试解决方案,如果能够迎刃而解,那么用 cesium 加载影像图,不是如同探囊取物么!
尝试寻找解决方案
我们先来找找,看能否找到前端解析 geotiff 的解决方案。
我们知道,如果用桌面软件,查看 geotiff 图像,很多常见的软件都能支持,大到像 arcgis,小到像 windows 看图,都能查看。
但是前端,是否有现成的工具,可以用来解析 geotiff 图像呢?
带着这样的疑问,开始了我们的探寻之旅。
经过一番尝试以后,发现前端有个开源的库—— geotiff.js ,可以用来解析 .tif 格式的文件。
具体 geotiff.js 的 api,在这里就不做过多的介绍了,有兴趣了解的,可以去看下官方提供的 readme 文件,上面有用法的详细说明。
原始影像图
假设现在有个 geotiff 文件,用 IrfanView 文件打开,是这个样子的:
解析 geotiff 文件
geotiff.js 提供了几种写入读取 二进制文件的方式,为了方便使用,我们就尝试采用 fromBlob 的方式。
我们先调用 geotiff.js 提供的 api,将文件读取成 js 对象,再通过对象提供的 getImage api,获取到图像的相关信息。
const tiff = await fromBlob(blob);let image = await tiff.getImage();
let [west, south, east, north] = image.getBoundingBox();const code =image.geoKeys.ProjectedCSTypeGeoKey ||image.geoKeys.GeographicTypeGeoKey;
为了准确的把图贴到 cesium 的球面上去,我们必须要先获取到图像的范围,并且要获取到图像采用的是哪种坐标系。
我们测试的这张图,打印出上述信息,发现采用的是 4527 坐标系,范围如图示:
转换坐标的方法
现在问题是,cesium 目前已知的,只支持月球、标准的球体和 WGS84 体系的坐标体系,不支持我们的 CGCS2000 坐标系。
怎么办呢?我们必须能找到一个换算的方式,将我们的坐标换算成 WGS84 坐标体系里的点。
可是,由于本身对 gis 专业相关的基础知识的匮乏,对于坐标体系转换,毫无经验,根本不知道怎么转换该如何是好?
虽然,怎么转化,论文里都有,但是等学会那些,再来解决这个问题,都不知道要等到猴年马月去呀。
不过不要着急,我发现了一个网站支持这种服务,提供了这种转换的接口。
不用自己写转换坐标的算法,岂不是很舒服!
http://epsg.io/
首页长这样:
点击进入这个 transform coordinates 页面:
我们试着输入一个坐标:
返现返回了我们想要的结果,点进去看下位置:
现在问题是,虽然我们能在页面上获取转换结果,但是总不能每次都打开页面,输入地址,来获取转换后的坐标吧?
无妨,我们打开控制台看一下,转换的过程到底经历了写什么。
我们点一下 transform,发现页面发了一个 ajax 请求,里面包含了一些相关的信息
而返回的结果,正是在 4326 体系下,的经纬度坐标信息:
既然有了转换方式,可以转换坐标,那么接下来要做的就很简单了。
通过接口,获取该影像图所表示的地理区域的范围:
let { x: w, y: n } = await (await fetch(`//epsg.io/trans?x=${west}&y=${north}&s_srs=${code}&t_srs=4326`)
).json();
let { x: e, y: s } = await (await fetch(`//epsg.io/trans?x=${east}&y=${south}&s_srs=${code}&t_srs=4326`)
).json();
将 geotiff 像素信息写入 canvas
按理说,走到了这一步后,如果 cesium 支持直接加载 geotiff 图为静态的 图层,是最理想的状态,可惜的是,它并不支持。
既然它不支持,我们就要想办法另辟蹊径了。
// 读取像素信息
const [red = [], green = [], blue = []] = await image.readRasters();// 将像素信息写入canvas
const canvas = document.createElement("canvas");
let width = image.getWidth();
let height = image.getHeight();
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
let imageData = ctx.createImageData(width, height);console.time("写入像素");
for (var i = 0; i < imageData.data.length / 4; i += 1) {imageData.data[i * 4 + 0] = red[i];imageData.data[i * 4 + 1] = green[i] || 0;imageData.data[i * 4 + 2] = blue[i] || 0;imageData.data[i * 4 + 3] = red[i] === 0 ? 0 : 255;
}ctx.putImageData(imageData, 0, 0);console.timeEnd("写入像素");
我们可以通过 image 对象提供的 readRasters 接口,将像素信息读取出来,然后写入 canvas,形成一张前端可以操控的图。
在 cesium 中加载
遗憾的是,cesium 的 SingleTileImageryProvider 接口,并不支持对 canvas 的直接载入,需要转换成图片才能进行操作。
我们可以调用 canvas 自带的 toDataURL 将 canvas 转换成图片,然后传进去即可。
let rectangle = Cesium.Rectangle.fromDegrees(w, s, e, n);
let du = canvas.toDataURL();viewer.imageryLayers.addImageryProvider(new Cesium.SingleTileImageryProvider({url: du,rectangle,})
);viewer.camera.setView({destination: rectangle,
});
这样,我们就成功的将该 geotiff 影像图,直接加载到 cesium 里面去了。
调整颜色
到了这一步,我们要做的差不多就结束了。
但是细心的同学可能会发现,加载到 cesium 里的影像图的颜色跟我们前面用软件打开的时候不太一样。
这是为什么呢?
要理解这个问题,可能需要童鞋们去了解下颜色的构成方式。
这里我们采用的是 rgb 的表示方法。
当我们运行代码的时候,进入调试模式,你会发现,
默认这个影像里面,只存储了 R 的信息,G、B 的信息并没有。
那么怎么处理呢?
其实很简单,只需要改一行代码即可:
const [red = [], green = red, blue = red] = await image.readRasters();
将 green 和 blue 均赋值一个初始值,等于 red 即可。
然后,我们再次尝试运行一下代码,就会得到下图所示的场景了:
此刻,细心的童鞋就会发现,这与我们之前打开的图一般无二了。
后记
当然,有一些情况,我们这里并没有考虑到,有兴趣的同学可以自己研究下:
- 一般情况下,geotiff 影像图都非常的大,我们的示例并未考虑到影像图的大小对系统的影响。
- 我们这里只考虑了单文件的情况,有时候,geotiff 的表示形式,存在多文件的情况。
- 可以尝试对配色进行修改,从而调出不同的风格的影像图,这是个很酷的功能。
cesium 直接加载 geotiff 影像图相关推荐
- cesium离线加载瓦片影像图和DEM高程图
最近准备使用Cesium+WPF来进行项目开发,学习了一下Cesium,由于项目需要离线所以先研究一下如何离线使用吧. 首先展示一下效果图: 离线高德影像瓦片地图的加载方法: 1.我使用的是太乐地图下 ...
- 第四章 Cesium学习入门之加载离线影像图(tif)
从0开始的Cesium 第一章 Cesium学习入门之搭建Vite+Vue3+Cesium开发环境 第二章 Cesium学习入门之搭建Cesium界面预览和小控件隐藏 第三章 Cesium学习入门之地 ...
- cesium首次加载gltf模型成功
接此: https://blog.csdn.net/bcbobo21cn/article/details/111305160 根据资料gltf格式模型可以直接在cesium上加载: 网上搜索gltf, ...
- cesium 3dtiles 加载本地数据_记一次Cesium地形数据生成过程
问题描述 有一小块带高程值的点状数据,需要根据该数据生成Cesium支持的3dtiles数据,在Cesium中显示.经过一周多时间的摸索,终于能够在Cesium中加载成功.现将数据处理流程做个记录,以 ...
- Cesium Primitives加载大量图标点
Cesium Primitives加载大量图标点 前言 效果 关键代码 前言 使用entity的方式加载大量图标点会出现卡顿现象,cesium提供了BillboardCollection可以实现大量图 ...
- Cesium本地加载地形(dem高程)数据
cesium本地加载dem数据,首先需要下载地区的高程数据,一般通常在地理空间数据云里面下载:http://www.gscloud.cn/ 这里一般可以下载到90m和30m精度的数据,当然也可以用自己 ...
- Cesium|xt3d加载中国地形
Cesium|xt3d加载中国地形 效果 代码 预览地址 效果 代码 <!DOCTYPE html> <html lang="zh-CN"><head ...
- Cesium 无法加载出地球
Cesium 无法加载出地球 问题描述 Cesium 无法加载出地球,在控制台中看到这样一条报错信息: 401错误,不可用的token值. 解决方案 1.注册一个免费的账户 网址:https://ce ...
- Cesium Billboard加载Gif图片
Cesium Billboard加载Gif图片 实现效果 关键代码 loadGif(img) {this.superGif = new SuperGif({gif: img});this.superG ...
最新文章
- spark+openfire即时通讯工具二次开发参考文档
- 动态更新 AGS Cache
- 效率提升多倍, 推荐值得收藏40 个命令总结
- 指定ASP .NET Core Web应用端口
- DL之DNN之BP:神经网络算法简介之BP算法/GD算法之不需要额外任何文字,只需要八张图讲清楚BP类神经网络的工作原理
- 文件从头开始读函数_如何从头开始编写自己的Promisify函数
- display:none和visibility:hidden区别
- KubeEdge 1.2.0 部署
- Codeforces Round #342 (Div. 2) D. Finals in arithmetic(想法题/构造题)
- git命令行常用操作及在linux下push到github项目中遇到的问题
- 资金盘FairWin漏洞系统详解:项目方可以撇开“作恶”嫌疑了?
- 场景编辑器开发第五天,设计架构重回flash,很多问题不是出在技术上而是策划上
- 第二章 信息化规划与组织
- Android9设备打开WIFI热点,Android9.0Wifi热点开启流程梳理
- EOSIO流服务Dfuse
- 【SpringBoot】十八、拦截器 interceptor
- 全网最新-扶风视频解析计费系统,2022优化免授权版(赠接口轮询插件)
- 如何组织一场安全、可靠、高效的网络实战攻防演习?
- 任天堂官网在哪里修改服务器,任天堂服务器设置
- ogg转mp3格式转换器