添加云优化地理TIFF (COG)
向地图添加云优化地理TIFF (COG);
<!DOCTYPE html>
<html lang="en">
<head>
<title>添加云优化地理TIFF (COG)</title>
<meta property="og:description" content="向地图添加云优化地理TIFF (COG)" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.js'></script>
<script src="https://cdn.jsdelivr.net/npm/geotiff"></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<style>
#button-container {
position: absolute;
top: 10px;
right: 10px;
border-radius: 10px;
padding: 10px;
background-color: #fff;
overflow: auto;
display: flex;
flex-direction: column;
align-items: flex-start;
}
</style>
<div id="map"></div>
<div id="button-container">
<div>
<input type="checkbox" id="toggle-cog" name="toggle-cog">
<label for="toggle-cog">CloudOptimizedGeoTIFF</label>
</div>
</div>
<script>
// 用MapLibre初始化地图
const map = new maplibregl.Map({
container: 'map',
style:
'https://demotiles.maplibre.org/styles/osm-bright-gl-style/style.json',
center: [35.5, 28],
zoom: 1.6
});
let tiff;
let canvas;
let context;
let rasters;
let tiepoint;
let scale;
const checkShadow = document.getElementById('toggle-cog');
function createCanvasFromTIFF() {
const {width, height} = tiff;
canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
context = canvas.getContext('2d');
const imageData = context.createImageData(width, height);
const rgba = imageData.data;
for (let i = 0, j = 0; i < rasters[0].length; ++i, j += 4) {
rgba[j] = rasters[0][i];
rgba[j + 1] = rasters[0][i];
rgba[j + 2] = rasters[0][i];
rgba[j + 3] = 255;
}
context.putImageData(imageData, 0, 0);
}
// 从GeoTIFF读取坐标转换为世界坐标
function getWorldCoordinate(tiffX, tiffY) {
const worldX = tiepoint[0] + tiffX * scale[0];
const worldY = tiepoint[1] + tiffY * -scale[1]; // 注意:Y反转
return [worldX, worldY];
}
// 异步加载CloudOptimizedGeoTIFF
async function loadCOG() {
// 示例COG来自CBERS-4 (http://cbers.stac.cloud)
// 数据归功于:INPE - Brazilian National Institute for Space Research
// 使用的特定图像:
// http://www.dgi.inpe.br/catalogo/explore/isimagerd.html?id=CB4OLITPAN20170517ABC20181023
// 生成的缩略图和视图服务器:
// 来源:https://github.com/radiantearth/stac-browser
tiff = await GeoTIFF.fromUrl(
'https://cbers-stac-0-6.s3.amazonaws.com/CBERS4/PAN10M/217/102/CBERS_4_PAN10M_20170517_217_102_L2/CBERS_4_PAN10M_20170517_217_102.tif'
);
// 获取宽度、高度等所需信息...
const image = await tiff.getImage();
tiff.width = image.getWidth();
tiff.height = image.getHeight();
rasters = await image.readRasters();
// 获取坐标到经纬度变换的信息
const fileDirectory = image.getFileDirectory();
tiepoint = fileDirectory.ModelTiepoint;
scale = fileDirectory.ModelPixelScale;
// 从像素创建图像
createCanvasFromTIFF();
loadCogSource();
}
function loadCogSource() {
// 得到图像边界的经纬度
const bounds = [
getWorldCoordinate(0, 0),
getWorldCoordinate(tiff.width, tiff.height)
];
// 设置新图片源
const mapCanvas = map.getCanvas();
const tiffImage = new Image(tiff.width, tiff.height);
tiffImage.src = canvas.toDataURL('image/png');
tiffImage.onload = () => {
if (map.hasImage('cogImage')) map.removeImage('cogImage');
map.addImage('cogImage', tiffImage);
if (map.getSource('cog')) map.removeSource('cog');
map.addSource('cog', {
type: 'image',
url: 'cogImage',
coordinates: [
[bounds[0][0], bounds[0][1]],
[bounds[1][0], bounds[0][1]],
[bounds[1][0], bounds[1][1]],
[bounds[0][0], bounds[1][1]]
]
});
if (map.getLayer('image-cog')) map.removeLayer('image-cog');
map.addLayer({
id: 'image-cog',
type: 'raster',
source: 'cog',
paint: {
'raster-opacity': 0.85
},
layout: {
visibility: 'none'
}
});
};
}
map.on('load', async () => {
// 加载COG层
loadCOG();
// 事件监听器和初始化
checkShadow.addEventListener('change', () => {
if (checkShadow.checked) {
map.setLayoutProperty('image-cog', 'visibility', 'visible');
} else {
map.setLayoutProperty('image-cog', 'visibility', 'none');
}
});
});
</script>
</body>
</html>