如何使用浏览器端JavaScript将32位RGB高程PNG转为16位高度图PNG
解决方案
以下是可直接在浏览器环境运行的实现方案,无需依赖Node端生态的库:
实现逻辑
- 解码原始RGB高程PNG获取每个像素的R/G/B通道值
- 代入官方公式计算得到真实高程值
- 将高程值映射到16位无符号整数的取值范围(0~65535)
- 将映射后的灰度值编码为16位灰度PNG,可直接用你提到的
createWritable接口写入本地磁盘
代码示例
// 依赖轻量纯前端PNG编解码库UPNG,无Node环境依赖 async function convertRGBTo16BitHeightmap(rawFile) { // 读取原始PNG文件内容 const fileBuffer = await rawFile.arrayBuffer(); // 解码PNG得到图像尺寸和像素数据 const decodedImg = UPNG.decode(fileBuffer); const { width, height } = decodedImg; const rgbaPixels = new Uint8Array(UPNG.toRGBA8(decodedImg)[0]); // 遍历所有像素计算高程并映射为16位灰度值 const gray16Pixels = new Uint16Array(width * height); for (let i = 0; i < width * height; i++) { const r = rgbaPixels[i * 4]; const g = rgbaPixels[i * 4 + 1]; const b = rgbaPixels[i * 4 + 2]; // 代入Mapbox官方高程计算公式 const realHeight = -10000 + (r * 65536 + g * 256 + b) * 0.1; // 高程值映射到16位无符号整数范围,可根据实际业务调整映射规则 const mappedValue = Math.round(realHeight + 10000); gray16Pixels[i] = Math.max(0, Math.min(65535, mappedValue)); } // 编码为16位灰度PNG const heightmapBuffer = UPNG.encode( [new Uint8Array(gray16Pixels.buffer)], width, height, 16, [0] ); // 保存到本地磁盘,使用你提到的createWritable接口 const saveFileHandle = await window.showSaveFilePicker({ suggestedName: '16bit-heightmap.png', types: [{ description: 'PNG Image', accept: { 'image/png': ['.png'] } }] }); const writableStream = await saveFileHandle.createWritable(); await writableStream.write(new Blob([heightmapBuffer], { type: 'image/png' })); await writableStream.close(); }
适配说明
如果你需要继续使用image-js库,可在遍历像素得到高程数组后,直接调用image-js的构造函数创建16位灰度图像:
const heightmapImg = new Image(width, height, gray16Pixels, { kind: 'GREY', bitDepth: 16 }); // 直接导出为PNG文件即可 heightmapImg.save('16bit-heightmap.png');
注意事项
如果你的使用场景中高程范围超出了-10000米55535米的默认映射范围,可以先遍历所有像素得到最大、最小高程值,再做线性映射把整个高程区间拉伸到065535的16位灰度区间即可。
内容的提问来源于stack exchange,提问作者dan
相关产品推荐
相关产品推荐

