🦀 Rust + WASM 实战系列 第 11 篇 阅读时间:约 5 分钟 | 实战可运行
📌 写在前面
最后一篇邻域卷积 ,也是唯一一个不用卷积核 的------靠像素坐标重映射就能实现"赛博朋克"风格。
原理极其简单:把 R、G、B 三个通道分别从不同位置取,自然就"错位"了。
🚀 TL;DR
css
原图: 故障风:
┌──────────┐ ┌──────────┐
│ R G B │ │ R G B │
│ │ │ ↑ ↑ │ ← R 向左偏移
│ RGB 像素 │ → │ ↑ ↑ │ ← B 向右偏移
│ │ │ RGB 像素│
└──────────┘ └──────────┘
边缘出现"红/蓝重影"
两种模式:
| 模式 | 效果 | 适用 |
|---|---|---|
horizontal |
整张图统一偏移 | 轻微故障 |
random |
每行随机偏移(更乱) | 强故障 |
📖 目录
- [什么是 RGB 通道偏移?](#什么是 RGB 通道偏移? "#%E4%B8%80%E4%BB%80%E4%B9%88%E6%98%AF-rgb-%E9%80%9A%E9%81%93%E5%81%8F%E7%A7%BB")
- [核心算法:3 通道分别取不同位置](#核心算法:3 通道分别取不同位置 "#%E4%BA%8C%E6%A0%B8%E5%BF%83%E7%AE%97%E6%B3%953-%E9%80%9A%E9%81%93%E5%88%86%E5%88%AB%E5%8F%96%E4%B8%8D%E5%90%8C%E4%BD%8D%E7%BD%AE")
- 关键代码
- 前端效果展示
- [两种模式:uniform vs random](#两种模式:uniform vs random "#%E4%BA%94%E4%B8%A4%E7%A7%8D%E6%A8%A1%E5%BC%8Funiform-vs-random")
- [进阶:垂直偏移 / 颜色错位](#进阶:垂直偏移 / 颜色错位 "#%E5%85%AD%E8%BF%9B%E9%98%B6%E5%9E%82%E7%9B%B4%E5%81%8F%E7%A7%BB--%E9%A2%9C%E8%89%B2%E9%94%99%E4%BD%8D")
- 应用场景
一、什么是 RGB 通道偏移?
一张图片 = 3 张灰度图叠在一起(R、G、B 各一张)。
正常情况:3 张叠得很准 → 一张彩色图。
arduino
R 通道: ████ ████ ████ (红色位置)
G 通道: ████ ████ ████ (绿色位置)← 对齐
B 通道: ████ ████ ████ (蓝色位置)
结果: 彩色对齐 → "白衬衫"
RGB 偏移 = 把其中一两张错位:
arduino
R 通道: ████ ████ (向左移 2 格)
G 通道: ████ ████ ████ (不动)
B 通道: ████ ████ (向右移 2 格)
结果: 三层错位 → "红/蓝重影的赛博风"
视觉 :边缘出现红边 + 蓝边,中间正常。
二、核心算法:3 通道分别取不同位置
rust
// 原来:3 个通道都从 (x, y) 取
result[i] = pixels[i] // R
result[i + 1] = pixels[i + 1] // G
result[i + 2] = pixels[i + 2] // B
// 现在:R、B 从不同位置取
result[i] = pixels[(y * w + (x - off)) * 4] // R 从左边 off 像素取
result[i + 1] = pixels[i + 1] // G 保持
result[i + 2] = pixels[(y * w + (x + off)) * 4 + 2] // B 从右边 off 像素取
就这么简单 ------没有卷积核,没有梯度,纯坐标重映射。
三、关键代码
rust
for y in 0..h {
let row_off = if kind == "random" {
// 每行用伪随机偏移
(pseudo_rand(y as u32, 0, 42) as i32 % (off * 2 + 1)) - off
} else {
off
};
for x in 0..w {
let out = ((y * w + x) * 4) as usize;
// R:向左偏 row_off
let r_x = (x - row_off).clamp(0, w - 1);
let r_idx = ((y * w + r_x) * 4) as usize;
result[out] = pixels[r_idx];
// G:保持
result[out + 1] = pixels[out + 1];
// B:向右偏 row_off
let b_x = (x + row_off).clamp(0, w - 1);
let b_idx = ((y * w + b_x) * 4) as usize;
result[out + 2] = pixels[b_idx + 2];
// A:保持
result[out + 3] = pixels[out + 3];
}
}
四、前端效果展示
五、两种模式:uniform vs random
uniform 模式
rust
let row_off = off; // 每行都用同一个偏移
效果:整张图"红蓝"整齐地错位,比较"克制"。
random 模式(更故障)
rust
let row_off = pseudo_rand(y, 0, 42) % (off * 2 + 1) - off;
// ↑ ↑
// 0~255 映射到 -off ~ +off
效果:每行错位量不同,看起来像"真·信号故障"。
| 模式 | 视觉效果 |
|---|---|
horizontal |
整齐错位(轻微) |
random |
撕裂错位(强烈) |
六、进阶:垂直偏移 / 颜色错位
垂直偏移
把 x ± off 改成 y ± off,整张图变成"上下错位":
rust
// R 从上面取
let r_y = (y - off).clamp(0, h - 1);
let r_idx = ((r_y * w + x) * 4) as usize;
result[out] = pixels[r_idx];
// B 从下面取
let b_y = (y + off).clamp(0, h - 1);
let b_idx = ((b_y * w + x) * 4 + 2) as usize;
result[out + 2] = pixels[b_idx + 2];
三通道独立偏移
不只偏 R 和 B,三个通道各偏不同方向:
rust
result[out] = pixels[((y * w + (x - off)) * 4)]; // R 左
result[out + 1] = pixels[((y * w + (x + off / 2)) * 4 + 1)]; // G 轻微右
result[out + 2] = pixels[((y * w + (x + off)) * 4 + 2)]; // B 右
效果更"乱",故障感更强。
七、应用场景
| 场景 | 说明 |
|---|---|
| 赛博朋克风格 | 黑客帝国 / 银翼杀手 |
| 音乐 MV | 80s / Synthwave 风格 |
| 故障艺术(Glitch Art) | 当代艺术常用手法 |
| 复古游戏 UI | 老电视 / 录像带质感 |
| 恐怖游戏 | "信号被干扰" 的诡异效果 |
| VHS 滤镜 | 模拟老录像带 |
| 品牌 Logo 设计 | 抖音 / TikTok 音符图标的视觉签名 |
🎵 抖音 / TikTok 图标:克制的 RGB 偏移
最经典也最被忽视的例子 ------ 抖音 / TikTok 的音符图标:
┌─────────────────┐
│ │
│ ╱╲ │
│ ╱ ╲ │ ← 音符主体(白色)
│ ╱ ╲ │
│ ╱ ● │ ← 音符头(白色)
│ ╱ │
│ │
└─────────────────┘
仔细看音符边缘,会发现有轻微的红 / 青(cyan)色"重影"------这就是 RGB 通道偏移的视觉签名:
| 抖音图标边缘 | RGB 通道偏移效果 |
|---|---|
| 红色重影在一侧 | R 通道偏移 |
| 青色(= 缺 R)重影在另一侧 | B 通道偏移 |
| 中心正常 | G 通道保持 |
本质上就是同一个算法 ------只是抖音用得很"克制"(偏移 1
2 像素,作为品牌识别的微妙细节),而故障风用得很"放肆"(偏移 1030 像素,做强烈的赛博朋克风格)。
为什么 TikTok 选这个风格?
- 辨识度:RGB 分离让人一眼就能"看见"图像边界,比纯白色音符更有视觉张力
- 时代感:呼应短视频时代的"快、躁、潮"调性
- 年轻化:红 / 青撞色是赛博朋克、Synthwave 文化的标志色
- 普适性:在手机小图标(48×48)和大 banner 上都能保持识别度
💡 设计圈的小秘密 :很多设计师做故障风时先做"大偏移"找灵感 ,再缩到"小偏移"做成品牌 logo------同一个数学公式,只是参数不同。理解了这个,你也能复刻任何"赛博朋克 logo"。
🎁 写在最后
第二部分"邻域卷积"全完结 🎉
| 任务 | 核数 | 输出 |
|---|---|---|
| 6 模糊 | 1 | 平滑 |
| 7 马赛克 | 0 | 块状 |
| 8 暗角 | 0 | 四周变暗 |
| 9 Sobel | 2 | 边缘 |
| 10 浮雕 | 1 | 立体感 |
| 11 RGB 偏移 | 0 | 错位重影 |
所有 6 个都用到了 nalgebra 或类似工具 ------你已经彻底掌握邻域操作了。
下部分预告:第三部分 图像几何变换 ------用 2D 矩阵做旋转、缩放、翻转 。线代工具箱正式登场!
📦 项目地址 :pixel-math-wasm 🦀 Rust + WebAssembly 实战系列
🏷️ 标签 :#Rust #WebAssembly #图像处理 #RGB偏移 #故障风 #赛博朋克 #算法
