js实现HDR
HDR 实现原理
高动态范围(HDR)通过合成多张不同曝光的照片来扩展图像的动态范围,保留更多亮部和暗部细节。JavaScript 实现的核心是通过 Web API 获取图像数据,进行像素级运算。
获取多曝光图像数据
使用 FileReader 或 fetch 加载不同曝光的图像资源,将图像绘制到 canvas 上获取像素数据:

async function loadImageData(url) {
const img = new Image();
img.src = url;
await img.decode();
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return ctx.getImageData(0, 0, canvas.width, canvas.height);
}
像素融合算法
采用权重融合法合并多张图像,对每个像素的 RGB 通道进行加权平均:
function mergeHDR(imagesData, weights) {
const merged = new ImageData(imagesData[0].width, imagesData[0].height);
for (let i = 0; i < merged.data.length; i += 4) {
let r = 0, g = 0, b = 0;
imagesData.forEach((imgData, idx) => {
r += imgData.data[i] * weights[idx];
g += imgData.data[i+1] * weights[idx];
b += imgData.data[i+2] * weights[idx];
});
merged.data[i] = Math.min(255, r);
merged.data[i+1] = Math.min(255, g);
merged.data[i+2] = Math.min(255, b);
merged.data[i+3] = 255; // Alpha通道
}
return merged;
}
色调映射处理
使用 Reinhard 算子将 HDR 数据压缩到标准动态范围:

$$ L{display} = \frac{L{hdr}}{1 + L_{hdr}} \times 255 $$
function toneMapping(hdrData) {
const result = new ImageData(hdrData.width, hdrData.height);
for (let i = 0; i < hdrData.data.length; i += 4) {
const r = hdrData.data[i] / 255;
const g = hdrData.data[i+1] / 255;
const b = hdrData.data[i+2] / 255;
result.data[i] = (r / (1 + r)) * 255;
result.data[i+1] = (g / (1 + g)) * 255;
result.data[i+2] = (b / (1 + b)) * 255;
result.data[i+3] = 255;
}
return result;
}
完整处理流程
- 准备 3-5 张不同曝光的源图像(建议 EV 间隔 2档)
- 为每张图像分配权重(通常中间曝光权重最高)
- 执行像素融合生成 HDR 图像数据
- 应用色调映射转换为可显示的图像
- 输出到 Canvas 显示或保存为文件
性能优化建议
使用 Web Workers 分离计算密集型任务:
// 主线程
const worker = new Worker('hdr-worker.js');
worker.postMessage({ imagesData, weights });
worker.onmessage = (e) => updateCanvas(e.data);
// Worker线程
self.onmessage = ({data}) => {
const result = processHDR(data.imagesData, data.weights);
self.postMessage(result);
};
注意事项
- 源图像需严格对齐(建议使用三脚架拍摄)
- 权重分配影响最终效果,需根据场景调整
- 移动端需注意内存限制,建议降低分辨率处理
- 支持 WebGL 的设备可使用 GLSL 加速计算






