前言
地图影像一般都为TIF格式的数据,但是直接加载TIF影像的话会存在一些性能问题,想比传统的TIF数据,COG格式的TIF数据对前端渲染来说更加的方便,快捷,因此需要后台对tif文件进行切割为COG 格式的数据。
一、COG是什么?
这里直接引用一些大佬的博文进行解释,https://blog.youkuaiyun.com/Neuromancerr/article/details/123568413;
下面的文章也采用了该博文片段,写出来的目的记录一下并方便以后查阅。
二、Openlayer加载COG文件
1.引入库
用到的是vue3模版,渲染tif文件需要借助geotiff.js库
import { onMounted } from 'vue';
import GeoTIFF, { fromBlob, fromUrl, fromArrayBuffer, Pool } from 'geotiff';
import GeoTIFFSource from 'ol/source/GeoTIFF';
import Map from 'ol/Map';
import WebGLTile from 'ol/layer/WebGLTile';
import View from 'ol/View';
2.渲染COG数据
/**
* 获取tif元信息
* @param url
* @returns noData,波段信息
*/
const getGeoTifMetaData = async url => {
const tiff = await fromUrl(url);
const image = await tiff.getImage();
const bands = [];
// 获取波段数
const samples = image.getSamplesPerPixel();
for (let i = 0; i < samples; i++) {
// 获取该波段信息 如果element都为null 需要后台对波段执行ComputeStatistics,生成GDAL_METADATA
const element = image.getGDALMetadata(i);
console.log('ele', element);
bands.push(element);
}
// 获取nodata值 暂时并不知道这个值有什么用!!!
const noData = image.getGDALNoData();
return { noData, bands };
};
onMounted(async () => {
// 这里在本地进行了代理,真实地址为http://***.**.**
const url = '/cog1/tif/L1C_T51TWJ_A037266_20220811T024318.tif ';
const source = new GeoTIFFSource({
normalize: false,
sources: [
{
url,
// 这里可以手动重设min,max,nodata等属性以覆盖tif原始信息
nodata: 0,
},
],
});
const map = new Map({
target: 'map',
layers: [],
view: source.getView(),
});
const metaData = await getGeoTifMetaData(url);
// 取出元信息里的波段最大最小值
const bands = metaData.bands.map(item => {
console.log('itm', item);
return {
min: parseFloat(item.STATISTICS_MINIMUM),
max: parseFloat(item.STATISTICS_MAXIMUM),
};
});
const style = {
color: [
'array',
// 线性映射字段,把波段里面的最小值映射为0,最大值映射为1(0-1的区间与计算机图形处理相关)
// 最后一位数值代表颜色深浅
['interpolate', ['linear'], ['band', 1], bands[0].min, 0, bands[0].max, 4],
['interpolate', ['linear'], ['band', 2], bands[1].min, 0, bands[1].max, 4],
['interpolate', ['linear'], ['band', 3], bands[2].min, 0, bands[2].max, 4],
1,
],
};
// 加载是异步的
source.getView().then(view => {
const layer = new WebGLTile({
className: 'WebGLTile',
style,
source,
zIndex: 999,
extent: view.extent,
});
map.addLayer(layer);
map.getView().fit(view.extent);
});
});
总结
另外:影像的波段颜色这块代码调试比较麻烦点。