Rust图像处理第8节-暗角 & 复古胶片特效:四周衰减中心高亮

暗角 & 复古胶片特效:四周衰减中心高亮

🦀 Rust + WASM 实战系列 第 8 篇 阅读时间:约 5 分钟 | 实战可运行

📌 写在前面

有没有觉得,专业相机拍的照片四周总有一圈暗影 ?这不是镜头脏了,这是"暗角(Vignette)"------艺术效果,不是缺陷。

这一篇实现两种:

  • 暗角:四周变暗,中心高亮
  • 复古胶片:暗角 + 暖色调 + 颗粒(老电影味道)

🚀 TL;DR

复制代码
原图:               暗角后:              复古胶片:
┌──────────┐        ┌──────────┐         ┌──────────┐
│  200 200 │        │  200 200 │         │  220 220 │
│ 200 200  │   →    │ 200 180  │    →    │ 200 180  │ + 颗粒
│          │        │   ▓▓▓▓   │         │  ▓  ▓ ▓▓ │
└──────────┘        └──────────┘         └──────────┘
(均匀)             (中心亮,四角暗)    (+ 暖色 + 噪点)
模式 公式 额外效果
暗角 factor = 1 - strength × t²
复古胶片 在暗角基础上:暖色调 + 颗粒噪点 R 增强、B 减弱、随机 ±5

📖 目录

  1. 暗角的物理原理
  2. [核心算法:3 个数学概念](#核心算法:3 个数学概念 "#%E4%BA%8C%E6%A0%B8%E5%BF%83%E7%AE%97%E6%B3%953-%E4%B8%AA%E6%95%B0%E5%AD%A6%E6%A6%82%E5%BF%B5")
  3. 关键代码
  4. 前端效果展示
  5. 进阶:衰减函数选型
  6. [复古胶片:暖色 + 颗粒](#复古胶片:暖色 + 颗粒 "#%E5%85%AD%E5%A4%8D%E5%8F%A4%E8%83%B6%E7%89%87%E6%9A%96%E8%89%B2--%E9%A2%97%E7%B2%92")
  7. 应用场景
  8. 参考资料

一、暗角的物理原理

真实相机的暗角来自镜头边缘光线衰减

复制代码
镜头中心  ←─── 光圈最大,光线最足
镜头边缘  ←─── 光线被遮挡,亮度下降

照片平面上看:

erlang 复制代码
   ┌─────────────────┐
   │  ▓▓▓▓▓▓▓▓▓▓▓▓▓  │
   │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │  中心:满亮度 1.0
   │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│  边缘:~0.6(变暗 40%)
   │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
   │  ▓▓▓▓▓▓▓▓▓▓▓▓▓  │  对角:~0.4(最暗)
   └─────────────────┘

算法本质离中心越远,越暗


二、核心算法:3 个数学概念

1. 到中心的距离

rust 复制代码
let dx = x as f32 - cx;          // 水平距离
let dy = y as f32 - cy;          // 垂直距离
let dist = (dx * dx + dy * dy).sqrt();  // 欧氏距离

2. 归一化到 0~1

rust 复制代码
let t = dist / max_dist;
// t = 0  →  正在中心
// t = 1  →  在对角

3. 二次衰减函数

rust 复制代码
let factor = 1.0 - strength * t * t;
// factor = 1.0  → 不变(中心)
// factor = 0.0  → 全黑(对角,strength=1 时)

三、关键代码

rust 复制代码
for y in 0..height {
    for x in 0..width {
        // 1. 算距中心比
        let dx = x as f32 - cx;
        let dy = y as f32 - cy;
        let dist = (dx * dx + dy * dy).sqrt();
        let t = dist / max_dist;

        // 2. 衰减因子
        let factor = 1.0 - strength * t * t;

        // 3. 应用到 RGB(alpha 保留)
        let i = ((y * width + x) * 4) as usize;
        result[i]     = (pixels[i]     as f32 * factor) as u8;
        result[i + 1] = (pixels[i + 1] as f32 * factor) as u8;
        result[i + 2] = (pixels[i + 2] as f32 * factor) as u8;
        result[i + 3] = pixels[i + 3];
    }
}

四、前端效果展示

五、进阶:衰减函数选型

不同函数 → 不同暗角效果:

函数 效果 公式
二次(本文) 边缘渐暗,自然 1 - t²
线性 太硬,像切角 1 - t
平方根 太亮 1 - √t
三次方 边缘更暗 1 - t³
指数 可调衰减快慢 1 - e^(-kt)

实际工程中二次最常用,效果最自然。


六、复古胶片:暖色 + 颗粒

vintage 模式在暗角基础上额外做 3 件事

1. 暖色调(Sepia-like)

rust 复制代码
r *= 1.1;   // 红色增强
b *= 0.9;   // 蓝色减弱
g *= 1.0;   // 绿色不变

效果:偏黄、偏红 → 老电影味道。

2. 颗粒噪点(Grain)

rust 复制代码
let noise = pseudo_rand(x, y, 42) as f32 - 128.0;  // -128 ~ 127
let grain = noise * 0.15;                          // 缩到 ±19
r = (r + grain).clamp(0.0, 255.0);

为什么用伪随机? 不用引入 rand 库,编译更快、WASM 更小 ,且相同 (x, y) 永远返回相同值(保证多次调用结果一致)。

3. 暗角照常应用

复古胶片 = 暖色 + 颗粒 + 暗角,三者叠加。


七、应用场景

场景 推荐参数
人像特写(聚焦主体) 强度 0.6~0.8,纯暗角
风景(聚焦中央景物) 强度 0.3~0.5,纯暗角
怀旧照片 强度 0.5,复古胶片
电影感 强度 0.7,复古胶片
抽象艺术 强度 1.0,复古胶片

八、参考资料

  • Wikipedia - Vignetting:暗角的物理原理
  • Photoshop 文档:Filter → Lens Correction → Vignette
  • Lightroom 文档:Effects → Vignette
  • GIMP 文档:Filters → Light and Shadow → Vignette

🎁 写在最后

暗角是"廉价"但有效的艺术手段

  • 实现简单(10 行代码)
  • 效果立竿见影
  • 任何照片加了都有"专业感"

下篇预告:《Sobel 边缘检测:3×3 卷积核提取图像轮廓 》------ 第一个真正用卷积的算法,敬请期待。


📦 项目地址pixel-math-wasm 🦀 Rust + WebAssembly 实战系列


🏷️ 标签#Rust #WebAssembly #图像处理 #暗角 #复古胶片 #Vignette #算法

相关推荐
SmalBox15 小时前
【节点】[CirclePupilAnimation节点]原理解析与实际应用
unity3d·游戏开发·图形学
独孤留白16 小时前
从C到Rust:Rust 的 Trait 不是Interface,那是什么?
rust
花褪残红青杏小1 天前
Rust图像处理第7节-马赛克像素化:分块取平均色实现打码风格
rust·webassembly·图形学
用户298698530142 天前
在 React 中使用 JavaScript 将 Excel 转换为 PDF
javascript·react.js·webassembly
SmalBox2 天前
【节点】[Zigzag节点]原理解析与实际应用
unity3d·游戏开发·图形学
doiito2 天前
【Agent Harness】Gliding Horse 设计细节 -- 不跟风开发自己的AI Agent
架构·rust·agent
doiito2 天前
【Agent Harness】Gliding Horse 核心设计理念,不跟风开发自己的AI Agent
ai·rust·架构设计·系统设计·ai agent
花褪残红青杏小2 天前
Rust图像处理第6节- 均值模糊 & 中值模糊:3×3 邻域的两种经典玩法
rust·webassembly·图形学
子兮曰2 天前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust