HTML5 的 CSS filter 不支持 gamma 校正,因其标准未定义 gamma 函数;需用 Canvas + getImageData + Math.pow 手动实现,对 RGB 归一化后计算 pow(value/255, 1/gamma) 再乘回 255,alpha 保持不变。

HTML5 本身没有 filter: gamma() —— 别白找 CSS 属性了
直接说结论:filter 标准里压根没定义 gamma 函数。你搜到的“CSS 伽马滤镜”基本是混淆了概念:要么是误把 Photoshop 的操作当成了 CSS,要么是把 Canvas 手动计算 gamma 的代码当成滤镜用了。浏览器目前支持的 filter 值(如 brightness、contrast、grayscale)都做不到真正意义上的 gamma 校正——它们是线性调整,而 gamma 是幂函数非线性映射。
真要调 gamma,得用 Canvas + getImageData + Math.pow
这是目前最可靠、可控的前端 gamma 调整方式。核心逻辑就是对每个像素的 R/G/B 值单独做 Math.pow(value / 255, 1 / gamma)(注意:这里是 1 / gamma,不是 gamma!常见翻车点)。
- gamma > 1 → 画面变暗,用
1/gamma 做幂运算才对(例如 gamma=2.2,实际算pow(x, 0.4545)) - gamma 1(例如 gamma=0.5,算
pow(x, 2)) - 必须归一化到 [0,1] 再幂运算,再乘回 255,否则结果溢出或截断
- 别忘了处理 alpha 通道:通常保持不变,避免透明度被意外扭曲
为什么用 1 / gamma 而不是 gamma?
Gamma 校正本质是“补偿显示设备的非线性响应”。显示器输入值为 x,实际亮度 ≈ xγ;所以为了让人眼看到线性亮度,得提前把图像数据“反向压一下”,即应用 x → x1/γ。这也是为什么 PS、Blender、3ds Max 里调 gamma=2.2 是让图变亮(因为做了 1/2.2 映射),而很多人直觉以为“2.2 很大所以变暗”,就在这里栽跟头。
性能和兼容性:Canvas 方案不卡但有代价
每帧读写像素数据是 CPU 密集型操作,图像越大、频率越高,掉帧越明显。1080p 图像单次处理轻松耗时 10–30ms。建议:
立即学习“前端免费学习笔记(深入)”;
- 只在用户主动调节 gamma 时执行一次,而非 requestAnimationFrame 里实时跑
- 用
OffscreenCanvas(现代浏览器支持)把计算移到 worker 线程,避免阻塞主线程 - 如果只是想“让网页图看着更亮”,优先试试
filter: brightness(1.2) contrast(1.1)—— 虽不精准,但零成本、无兼容问题
真正需要 gamma 级别精度的场景(比如医学影像预览、3D 渲染结果校色),绕不开 Canvas 手动计算;其余多数情况,别为“术语正确”牺牲体验。










