使用方法
- 打开页面先跑一张内置渐变示例:左边是原图,右边是逐像素反相后的结果,可以直接点「下载 PNG」拿走。
- 「选择图片」换成你自己的文件,再点「反相」。支持 PNG、JPEG、GIF、WebP,大小上限 20 MB;选了非图片文件会给出指明类型的提示。
- 「反相模式」二选一:朴素 255−v 是在 sRGB 编码空间直接取反;线性空间反相先按 gamma 线性化、取反、再编码回去。后者物理上更对称,中间灰附近差别最大。
- 「十六进制色值」默认 #315FE8,改一个字符就立刻重算,不用点按钮;结果同时给出朴素与线性空间两个答案。
- 「gamma」默认 2.2,范围 1 到 3,只影响线性空间反相那一栏;sRGB 的实际编码曲线在这个值附近,放大到 3 可以看出差异被拉得更开。
- 结果区上面一行是色值反相的结论,下面一段是逐像素处理的明细:尺寸、像素数、imageData 字节数、处理耗时、平均亮度变化。
- 「下载 PNG」把右边画布导出成文件;本页导出的就是反相后的像素本身,不是叠了一层滤镜的预览。
- 下面那张灰阶对照表默认显示 12 行,点「加载更多」展开全部 52 行,点「导出 CSV」存成带字节序标记的文件;「复制对照表」复制正文那张 gamma 对照表。
- 色值框填了不是 6 位十六进制的值、gamma 超出 1 到 3、图片超过 20 MB,都会给出指明原因的提示。
这个图片颜色反相工具能解决什么问题
第一类是把深色图转成浅底。扫描件、夜间截图、白底黑字的表格截图,反相之后在深色背景的阅读器里更舒服;胶片负片数字化后也要先反相才能看。这里的反相是真的改像素,导出的文件可以直接拿去用。
第二类是做设计对照。想知道某个配色反过来长什么样,把色值输进框里就行:#315FE8 反相成 #CEA017,#000000 与 #FFFFFF 互为反相。批量试色时比在调色盘里手动减 255 快得多。
第三类是排查可读性问题。很多人以为反相后对比度不变,其实不守恒:#333333 与 #C8D0EA 的对比度是 8.22:1,双双反相后 #CCCCCC 与 #372F15 是 8.28:1,不是同一个数。做深色模式时照着反相后的颜色直接上线,完全可能跌破 4.5:1 的可读门槛。
第四类是理解 gamma。直接做 255−v 是在编码空间取反,物理上并不对称;先把通道值线性化再取反,中间灰附近的差别能到 100 以上。这一页把两种结果并列,差别一眼可见。
计算原理与变量说明
整页有三条公式,分别对应色相、对比度与 gamma。
| 变量 | 公式 | 说明 |
|---|---|---|
| 朴素反相 | r' = 255 − r | 三个通道各自取反,a 不变 |
| 线性空间 | L = (v/255)^γ,v' = 255 × (1−L)^(1/γ) | 先线性化、取反、再编码 |
| WCAG 对比度 | (L1 + 0.05) / (L2 + 0.05) | 相对亮度按 sRGB 线性化后加权 |
| alpha | a' = a | 不参与反相 |
反相不是取补色,也不是简单变亮。逐通道取反后色相会变、饱和度不变、亮度取反。RGB(200, 211, 234) 反相成 (55, 44, 21),是冷灰蓝变成暖深褐,而不是它的补色——补色要保持亮度关系,反相把每一条通道都推到对面。
对比度在反相下不守恒,这是本页最反直觉的一条。#333333 与 #C8D0EA 的对比度是 8.22:1;双双反相后 #CCCCCC 与 #372F15 是 8.28:1。反相后「看起来还行」是人眼自适应造成的错觉,深色背景配同色系浅字的组合反相后完全可能跌破 4.5:1 的可读门槛。
gamma 陷阱。sRGB 是 gamma 约等于 2.2 的编码空间,直接做 255−v 是在编码空间取反,物理上并不对称。正确做法是先线性化 L = (v/255)^2.2、取反 1−L、再编码回去:v = 32 时朴素得 223、线性空间得 254,差 31;v = 128 时朴素得 127、线性空间得 228,差 101;v = 223 时朴素得 32、线性空间得 137,差 105。中间灰附近的差异最大,这正是人眼最敏感的区间。
alpha 通道不参与反相。透明保持透明,否则半透明的边缘会突然变成不透明的白边或黑边。灰度图三通道等值反相后仍是灰度;彩色图反相后白底变黑底,打印与投影的耗墨、耗电明显更多,这也是夜间模式不能靠简单反相来做的原因之一。
完整示例(数值仅作演示)
打开页面时的默认色值是 #315FE8。朴素反相得 #CEA017(49→206、95→160、232→23);线性空间反相得 #FCF177。同一枚颜色,两种口径差出一大截,蓝色通道尤其明显:232 取反只有 23,在线性空间里却回到 119。
黑白两端不变:#000000 反相成 #FFFFFF,#FFFFFF 反相成 #000000。256 级灰阶的第 128 级反相成 127——因为取值是 0 到 255,中间那一对是 127 与 128,不是 128 与 128。
内置渐变示例是 320 × 120 的画布,共 38400 个像素、153600 字节的 imageData。逐像素处理时每个像素读 4 个字节,改前三个、留第四个,写回画布后再用 toDataURL 导出 PNG。
换成一张真实照片后,结果区会多出平均亮度一行:原图平均亮度越高,反相后越低,两者之和约为 255(按通道算术平均算)。
图片反相对照表
第一张表是 gamma 陷阱的核心数字,「复制对照表」复制的就是它。
| 原值 v | 朴素 255−v | 线性空间 | 差值 |
|---|---|---|---|
| 0 | 255 | 255 | 0 |
| 32 | 223 | 254 | 31 |
| 64 | 191 | 249 | 58 |
| 128 | 127 | 228 | 101 |
| 200 | 55 | 171 | 116 |
| 211 | 44 | 156 | 112 |
| 223 | 32 | 137 | 105 |
| 234 | 21 | 115 | 94 |
| 255 | 0 | 0 | 0 |
第二张表是色值与对比度:反相前后成对列出,最后一列是 WCAG 对比度。
| 颜色对 | 色值 | 对比度 | 说明 |
|---|---|---|---|
| 深色字 / 浅色底 | #333333 / #C8D0EA | 8.22:1 | 原组合 |
| 双双反相后 | #CCCCCC / #372F15 | 8.28:1 | 不是同一个数 |
| 可读门槛 | AA 级正文 | 4.5:1 | 反相后可能跌破 |
| 示例色反相 | #315FE8 → #CEA017 | — | 朴素口径 |
| 示例色反相 | #315FE8 → #FCF177 | — | 线性空间口径 |
第三张表是几个整块颜色的反相结果,用来快速核对。
| 颜色 | 原色值 | 反相后 | RGB 变化 |
|---|---|---|---|
| 纯黑 | #000000 | #FFFFFF | 0,0,0 → 255,255,255 |
| 纯白 | #FFFFFF | #000000 | 255,255,255 → 0,0,0 |
| 示例蓝 | #315FE8 | #CEA017 | 49,95,232 → 206,160,23 |
| 冷灰蓝 | RGB(200,211,234) | RGB(55,44,21) | 色相变、饱和度不变 |
| 中间灰 | 灰阶第 128 级 | 第 127 级 | 128 → 127 |
读法:第一张看两种口径差在哪,128 附近差 101;第二张看对比度不守恒;第三张看整块颜色。
结果边界、舍入与适用说明
- 色值框填了不是 6 位十六进制的内容时,提示它必须是 # 加 6 位十六进制,例如 #315FE8;带 # 与不带都能认。
- 选择的不是图片文件时提示文件类型不对;超过 20 MB 时提示具体大小并请先压缩。
- gamma 留空、写成非数字或超出 1 到 3 时分别给出对应提示;它只影响线性空间那一栏。
- 线性空间反相的结果四舍五入到 0 到 255 的整数,因此会有 1 的量化误差;两端 0 与 255 严格不变。
- alpha 通道原样保留,透明区域反相后仍是透明;如果原图没有 alpha,导出的 PNG 会是不透明的。
- 带 EXIF 方向标记的照片可能显示成旋转后的样子,本页按浏览器解码后的方向处理,不改写 EXIF。
- 超大图片(比如 8000 × 8000)逐像素处理会占用较多内存与时间,处理耗时会在结果区给出。
- 本页不做锐化、降噪与色彩管理,也不转换色彩空间;CMYK 或 16 位深的图会被浏览器按 8 位 RGBA 解码。
- 整页不联网、不写本地存储,图片只在浏览器里解码与处理,不会上传。
常见问题
反相是不是就是取补色?
不是。反相把每个通道推到对面:RGB(200,211,234) 变成 (55,44,21),色相变了、饱和度不变、亮度取反,和补色不是一回事。
反相后对比度会保持不变吗?
不会。#333333 与 #C8D0EA 是 8.22:1,双双反相后 #CCCCCC 与 #372F15 是 8.28:1。深色底配同色系浅字反相后可能跌破 4.5:1。
为什么中间灰差这么多?
因为 sRGB 是 gamma 约 2.2 的编码空间,直接 255−v 是在编码空间取反。v=128 朴素得 127、线性空间得 228,差 101,正好在人眼最敏感的区间。
透明区域会变成白边吗?
不会。alpha 通道不参与反相,透明保持透明。如果把 alpha 也取反,半透明边缘才会突然变成不透明的白边或黑边。
为什么 128 反相是 127 而不是 128?
取值是 0 到 255 共 256 级,255 − 128 = 127。中间那一对就是 127 与 128,不是两个 128。
导出的文件是真的反相了吗?
是。本页读 imageData 逐像素改前三个通道、写回画布,再用 toDataURL 导出,改的是像素本身,不是叠一层 CSS 滤镜。
反相后的图打印会更费墨吗?
会。大面积白底变黑底,打印与投影的耗墨、耗电明显更多,这也是夜间模式不能靠简单反相来做的原因之一。
图片会上传到服务器吗?
不会。文件只在浏览器里解码、逐像素处理、导出,没有发起任何网络请求,也没有写入本地存储。