js实现HDR
HDR 实现原理
高动态范围(HDR)通过合成多张不同曝光的图像,保留亮部和暗部细节。核心步骤包括曝光序列拍摄、图像对齐、色调映射。
多曝光图像合成
使用 canvas 或 WebGL 合并不同曝光度的图像。以下代码演示通过加权平均合成:
function blendExposures(images) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = images[0].width;
canvas.height = images[0].height;
// 初始化像素数据
const blended = ctx.createImageData(canvas.width, canvas.height);
const data = blended.data;
// 加权混合(示例:简单平均)
for (let i = 0; i < data.length; i += 4) {
let r = 0, g = 0, b = 0;
images.forEach(img => {
const imgData = getImageData(img);
r += imgData[i];
g += imgData[i + 1];
b += imgData[i + 2];
});
data[i] = r / images.length; // R
data[i + 1] = g / images.length; // G
data[i + 2] = b / images.length; // B
data[i + 3] = 255; // Alpha
}
ctx.putImageData(blended, 0, 0);
return canvas.toDataURL();
}
色调映射算法
将高动态范围压缩到显示器可呈现的范围,常用 Reinhard 算子:

[ L{d} = \frac{L}{1 + L} \cdot L{\text{white}}^2 ]
JavaScript 实现:

function reinhardToneMapping(hdrData, whiteLevel) {
const mapped = new Float32Array(hdrData.length);
for (let i = 0; i < hdrData.length; i++) {
const L = hdrData[i];
mapped[i] = (L / (1 + L)) * Math.pow(whiteLevel, 2);
}
return mapped;
}
WebGL 加速方案
使用 Three.js 等库实现高效 GPU 处理:
import * as THREE from 'three';
// 创建HDR渲染器
const renderer = new THREE.WebGLRenderer();
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.toneMappingExposure = 2.5;
// 加载HDR纹理
new THREE.RGBELoader().load('path/to/hdr.hdr', texture => {
const material = new THREE.MeshStandardMaterial({ envMap: texture });
});
浏览器兼容性处理
检测 HDR 显示支持:
const isHDRSupported = window.matchMedia(
'(dynamic-range: high) and (color-gamut: p3)'
).matches;
性能优化建议
- 使用 Worker 线程处理图像合成
- 对移动端设备降级使用低分辨率混合
- 预生成不同曝光度的图像金字塔
完整实现需结合具体场景调整参数,现代浏览器已原生支持 HDR 视频(<video> 标签的 hdr 属性),静态图像处理仍依赖上述技术方案。





