当前位置:首页 > 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
分享给朋友:

相关文章

js实现图片放大缩小

js实现图片放大缩小

实现图片放大缩小的基础方法 使用CSS的transform: scale()属性可以快速实现图片的放大缩小效果。通过JavaScript动态修改该属性值: const img = document.…

js防抖和节流实现

js防抖和节流实现

防抖(Debounce)的实现 防抖的核心思想是在事件被触发后,延迟执行回调函数。如果在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口大小调整等场景。 function debounce…

js 实现分页

js 实现分页

实现分页的基本逻辑 分页功能通常需要后端返回数据总量或总页数,前端根据当前页码和每页条数截取对应数据。以下是一个基于JavaScript的简单分页实现方案: 前端分页实现 假设已有从后端获取的完整数…

js实现变形

js实现变形

使用 CSS 和 JavaScript 实现元素变形 在 JavaScript 中实现变形效果通常结合 CSS 的 transform 属性,通过动态修改该属性实现元素的旋转、缩放、倾斜或平移。 基…

js实现祖玛

js实现祖玛

实现祖玛游戏的核心思路 祖玛游戏的核心玩法是发射彩色珠子,形成三个或以上相同颜色的珠子即可消除。以下是使用JavaScript实现的基本框架。 游戏初始化 创建画布并初始化游戏状态: const…

js实现目录

js实现目录

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