当前位置:首页 > JavaScript

js实现HDR

2026-02-02 00:21:57JavaScript

HDR 实现原理

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

获取多曝光图像数据

使用 FileReaderfetch 加载不同曝光的图像资源,将图像绘制到 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;
}

完整处理流程

  1. 准备 3-5 张不同曝光的源图像(建议 EV 间隔 2档)
  2. 为每张图像分配权重(通常中间曝光权重最高)
  3. 执行像素融合生成 HDR 图像数据
  4. 应用色调映射转换为可显示的图像
  5. 输出到 Canvas 显示或保存为文件

性能优化建议

使用 Web Workers 分离计算密集型任务:

js实现HDR

// 主线程
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图片轮播的实现

基础图片轮播实现 使用HTML、CSS和JavaScript实现一个简单的图片轮播效果。HTML部分定义轮播容器和图片,CSS负责样式和过渡效果,JavaScript处理逻辑。 <div cl…

用js实现vue

用js实现vue

用 JavaScript 实现 Vue 核心功能 Vue.js 是一个渐进式框架,其核心功能包括响应式数据绑定、虚拟 DOM 和组件系统。以下是一个简化版的实现,展示如何用原生 JavaScript…

vue.js实现scrollTop

vue.js实现scrollTop

Vue.js 实现 scrollTop 的方法 使用原生 JavaScript 实现 通过 window.scrollTo 或 Element.scrollTop 实现滚动到指定位置。在 Vue 中可…

js原生实现vue路由

js原生实现vue路由

使用 History API 实现路由切换 通过 window.history.pushState 和 popstate 事件可以实现前端路由的无刷新跳转。创建一个路由对象管理路径与组件的映射关系。…

react.js如何打包发布

react.js如何打包发布

安装依赖 确保项目已安装必要的依赖包,包括 react、react-dom 和构建工具(如 webpack 或 vite)。若使用 webpack,需安装 webpack、webpack-cli 及相…

js实现无缝滚动

js实现无缝滚动

实现无缝滚动的思路 无缝滚动的核心是通过动态调整内容位置或克隆元素,使内容在视觉上形成无限循环的效果。常见方法包括利用CSS动画、JavaScript动态计算或结合两者实现。 水平无缝滚动实现 通过…