当前位置:首页 > JavaScript

js实现HDR

2026-02-02 00:21:57JavaScript

HDR 实现原理

高动态范围(HDR)通过合成多张不同曝光的照片来扩展图像的动态范围,保留更多亮部和暗部细节。JavaScript 实现的核心是通过 Web API 获取图像数据,进行像素级运算。

获取多曝光图像数据

使用 FileReaderfetch 加载不同曝光的图像资源,将图像绘制到 canvas 上获取像素数据:

js实现HDR

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 数据压缩到标准动态范围:

js实现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;
}

完整处理流程

  1. 准备 3-5 张不同曝光的源图像(建议 EV 间隔 2档)
  2. 为每张图像分配权重(通常中间曝光权重最高)
  3. 执行像素融合生成 HDR 图像数据
  4. 应用色调映射转换为可显示的图像
  5. 输出到 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 加速计算

标签: jsHDR
分享给朋友:

相关文章

vue.js实现轮播

vue.js实现轮播

Vue.js 实现轮播功能 使用第三方库(推荐) Vue.js 生态中有许多成熟的轮播组件库,例如 vue-awesome-swiper 或 swiper,它们功能丰富且易于集成。 安装 swipe…

js实现全选

js实现全选

实现全选功能的方法 在JavaScript中实现全选功能通常涉及监听全选复选框的点击事件,并根据其状态控制其他复选框的选中状态。以下是几种常见的实现方式: 基础DOM操作实现 通过获取所有目标复选框…

js实现驼峰

js实现驼峰

实现驼峰命名的几种方法 使用正则表达式和字符串替换 通过正则表达式匹配字符串中的特定模式(如下划线或短横线),并将其后的字母转换为大写,同时移除分隔符。 function toCamelCase(s…

js实现目录

js实现目录

实现目录的基本思路 在JavaScript中实现目录功能通常涉及以下几个核心步骤:解析文档中的标题元素(如h1-h6),动态生成目录结构,并添加交互逻辑(如点击跳转)。以下是具体实现方法: 解析标题…

js实现图片

js实现图片

图片加载与显示 在JavaScript中,可以通过Image对象动态加载图片。创建实例后设置src属性触发加载,通过onload回调处理加载完成后的操作: const img = new Ima…

js实现文字滚动

js实现文字滚动

实现文字滚动的几种方法 使用CSS动画实现滚动 通过CSS的@keyframes和transform属性可以实现平滑的文字滚动效果。 <style> .scroll-text { w…