图案裂变的底色衰减:alpha通道、亮度对比与白墨分色的量化拆解
"深色底上图案会掉"是现象,不是原因。要能修,得先知道掉的是哪个量。
这篇只拆四个能算的东西:半透明像素被合成成了什么值、亮度差降到多少开始不可辨、最细笔画与布纹的尺度比、白墨通道为什么绕不开。
一、合成公式:半透明像素被底色拉走了多少
电子预览里的"叠在深色衣服上",本质是一次 alpha 合成。每个像素的输出值等于透明度乘前景,加上剩余比例乘背景:
C_out = α · F + (1 − α) · B
F 是图案自身颜色,B 是成衣底色,α 是这一像素的不透明度。白底预览里 B 接近 0.96,深色布上 B 通常落在 0.04 到 0.08 之间。
拿一条典型的水彩过渡带验算。前景是一层浅奶油色,F = 0.92,边缘的不透明度 α = 0.35。
白底上:0.35 × 0.92 + 0.65 × 0.96 = 0.944。它和背景的差值只有 0.016,肉眼完全看不出来,你会以为那里是干净收边。
黑布上:0.35 × 0.92 + 0.65 × 0.05 = 0.354。从 0.944 掉到 0.354,中间没有经过任何"消失",它变成了一个脏灰值。这就是大家口中"发灰"的物理来源------前景没有被削弱,是被常量 B 拽到了中间调。
再看一层更淡的 fringe,α = 0.06。白底上算出 0.958,与背景差 0.002,等于不存在;黑底上 0.102,与黑布差 0.052,看得见,但已经是脏边。
这两个例子说明一件事:衰减幅度近似等于 (1 − α)(B_白 − B_深)。α 越小,衰减越大;底色跨度越大,衰减越大。白底之所以"没问题",不是因为图案干净,是因为 B_白 恰好和浅色过渡带同值,差值被掩盖了。
要压住这个量,只有两条路:动 α(设计端把软过渡做成硬边),或者动 B(工艺端把布的颜色挡掉)。后者就是白墨。
二、亮度对比:算 Y,不要算 HSL 的 L
判断"还能不能看清",用的量是相对亮度,不是色相,也不是饱和度。
sRGB 值先线性化,再按人眼敏感度加权:
Y = 0.2126 · R_lin + 0.7152 · G_lin + 0.0722 · B_lin
线性化对单通道做一次幂运算,分量大于 0.04045 时按 ((v + 0.055) / 1.055) ^ 2.4 展开,小于等于时直接除以 12.92。
得到的 Y 再折算成对比率:CR = (Y_亮 + 0.05) / (Y_暗 + 0.05)。那个 0.05 是环境光补偿项,不是随手写的常数。
我们内部用的阈值分三档。大色块之间,CR 低于 3.0 就开始在深底上发闷;细线、小字、镂空这类结构,CR 要到 4.5 才稳;跌破 1.8,基本等于消失,剩下只是轮廓位置上的轻微明度抖动。还有一条更严的:96 像素缩略图上,边界两侧的 Y 差低于 0.06,无论 CR 多少都判不可辨------抗锯齿会把边缘抹平,全尺寸下的达标值不作数。

用那张金色狮子头算一遍会很有意思。主体金黄色,sRGB 取 (212, 175, 55)。线性化后三通道约为 0.646、0.428、0.036,加权得 Y ≈ 0.446。
压在黑布上(Y ≈ 0.006):CR = 0.496 / 0.056 ≈ 8.9,非常稳。
压在米杏色布上(Y ≈ 0.72):CR = 0.77 / 0.50 ≈ 1.54,不合格。
也就是说,这张图真正的风险不在深色,在浅暖色。金色和米杏的亮度几乎贴在一起,色相还相近,两个变量同时归零。裂变那一版鬃毛更蓬松、瞳孔换成金黄,看着更抓人,可深色线条一多,Y 反而略降------在米杏布上比原版还危险,在黑布上则更立得住。
这也就解释了"整体调亮一档"为什么是错的方向。把 Y = 0.45 的金色推到 0.60,黑布上 CR 从 8.9 升到 12,收益很小;米杏布上前景离背景更近,反而更糊。方向错的调整,做多少都是负收益。
顺带说清 HSL 的 L 为什么不能当判据。L 取最大通道与最小通道的算术中值,纯几何量。金色 (212,175,55) 的 L = 0.52,Y 只有 0.446;纯黄 (255,255,0) 的 L = 0.5,Y 高达 0.93。高饱和色在 L 上被严重低估,拿它判对比,橙、黄、青会系统性误判。
三、线宽与布纹:0.25mm 这条线怎么来的
颜色之外还有尺度问题。
180g 平纹棉的经纬纱间距在 0.35 到 0.5 毫米之间。丝网印刷的感光胶能稳定出 0.2 到 0.3 毫米的线,但油墨落到布上要跨过纱线起伏,线宽一旦与纱距同量级,就会被纤维打断成断续的颗粒。数码直喷能打到 0.1 毫米,热压后纤维回弹,细线还是断点。
换算一下。一张 28 厘米宽的稿件,300dpi 输出,横向约 3307 像素,单像素折合 0.085 毫米。
两像素的线,等于 0.17 毫米,比最密的那档纱距还窄。它落在两根纱之间,被纤维直接吞掉。
四像素的线,等于 0.34 毫米,和纱距持平,才连得起来。再粗就稳定了,但风格也已从线稿变成粗描。
这条换算解释了白底预览里最常被误判的一件事:2 像素的线在屏幕上非常清楚,因为显示器没有纤维。清楚,不等于能印。

简约笑脸那张就是单一线宽的极端案例。两个圆眼、一条弯眉、一道大弧微笑,全是同一种笔宽,没有任何色块托底。裂变后线条加粗、比例收得更协调,更适合印花------加粗在这类图上不是修饰,是能不能印出来的分界线。这也顺带说明了线稿类图案深底版难做的原因:整张图的信息全压在那一档线宽上,加粗换风格,不加粗印不出。
四、白墨分色:为什么它是必选项而不是优化项
彩色油墨是减色的,本身半透明。布面颜色会参与反射,等于在每个色版下面又垫了一层未知的底。写进公式还是那个 alpha 合成,只是 B 从软件预览层换成了真实布料------同一份分色文件落在黑布、藏青布、米杏布上,C_out 完全不同,设计端的可控性在这一步丢失。
白墨通道的作用,是把 α 强行变成 1。
做法是取图案的 alpha 掩膜,二值化之后做一次膨胀,膨胀量按工艺定,通常 0.2 到 0.3 毫米。铺了白墨之后,合成式退化成 C_out = F,底色不再进入计算。深底版能成立,靠的就是这个退化。
边缘处理有两个方向。白墨比彩版小 0.2 毫米,叫收,收多了边缘会露一圈布色;大 0.2 毫米,叫放,放多了彩墨压不住白边,边缘发毛发亮。这两个值跟克重、网目、烘干温度都相关,得跟印花厂对齐。
代价也要写清楚。白墨厚,手感偏硬,透气性下降;大面积白墨印在薄布上,穿着几次之后会沿折痕开裂。所以白墨不是越多越好,是只在需要挡底的地方铺。
一段够用的判定脚本
不需要专业色彩库,Pillow 加标准库的 colorsys 就够跑完上面全部四项。下面这个函数取图案中心区域的平均色,算色相、相对亮度差和对比率,再把最小笔画折算成毫米。
bash
from PIL import Image
from colorsys import rgb_to_hls
def check_ink_floor(p, min_stroke=2, bg_luma=0.05):
im = Image.open(p).convert("RGB")
w, h = im.size
px = im.load()
# 只采中心六成区域,避开出血边和透明留白
step = max(1, w // 24)
r = g = b = n = 0
for y in range(h // 5, h * 4 // 5, step):
for x in range(w // 5, w * 4 // 5, step):
pr, pg, pb = px[x, y]
r += pr
g += pg
b += pb
n += 1
r, g, b = r / n, g / n, b / n
hue, light, sat = rgb_to_hls(r / 255, g / 255, b / 255)
# light 只留作调试,判据用线性的 y_fg
y_fg = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255
delta_y = abs(y_fg - bg_luma)
ratio = (max(y_fg, bg_luma) + 0.05) / (min(y_fg, bg_luma) + 0.05)
# 28cm 成图宽 300dpi 时单像素约 0.085mm,min_stroke 直接折成线宽
line_mm = min_stroke * 300.0 / w
ok = ratio >= 3.0 and delta_y >= 0.06 and line_mm >= 0.25
return f"{'PASS' if ok else 'REVIEW'} hue={hue:.2f} sat={sat:.2f} dY={delta_y:.3f} CR={ratio:.2f} line={line_mm:.2f}mm"
五、反相与反白:色相被转动 180 度的代价
这几个词常被混用,它们在色相环上做的事却完全不同。
反相的运算是对每个通道取补,等价于色相转 180 度:H' = (H + 0.5) mod 1.0。原来的橙色猫,H 约 0.08(29 度),反相后变成 0.58(209 度),青蓝。红蝴蝶结 H 约 0.97,反相后 0.47,青绿。整张图的关系保住了,颜色全反了。
反白只推亮度,H 不动。同一只橙猫反白后仍是 29 度的橙,只是 L 从 0.42 抬到 0.85 附近,S 略降,看起来是"同一个颜色的浅版本"。
结论很干脆:无彩的图(黑白线稿、单色剪影)可以反相;有任何色相信息的图必须反白。反相之后的肤色、木色、金属色会一起毁掉,而且不可逆------你已经不知道原始饱和度是多少了。

斑马纹那张是个好例子。原版边缘压了一圈红蓝绿的彩色描边。这圈描边在浅色底上是设计元素,在白底预览里撑起了潮流感;落到深色布上,它却成了图案和布之间唯一的分界线------黑白条纹本身没有明度差,全靠这圈彩边续命。裂变那版把彩边去掉,改成纯黑白配米色底,纹理更自然,条纹走向也更流畅。
但要提醒一句:换成米色底之后,米色和白色条纹的 Y 值非常接近(都在 0.75 以上),白条纹会先丢,只剩黑条纹浮着,读起来是一组粗细不均的墨条。它没有变差,只是把风险从"边界"挪到了"内部两色的明度差"。
三组容易混的说法一起讲清。深底说的是承印物的颜色,深色图案说的是油墨的颜色,两件事分别落在公式的 B 和 F 上,别当成一回事。反白只动 L,反相动 H,这是两条完全不同的路径。描边是等宽外扩,宽度恒定为 W + 2d;投影是带偏移和模糊核的复制,参数是 (dx, dy, σ),放在深底上只会让边缘更脏,起不到分隔作用。
六、验收:四个能算的指标
不用靠感觉,四个数够了。
缩略到 96 像素后,边界两侧的 Y 差仍需大于 0.06,同时 CR 不低于 3.0。这一条筛掉绝大多数"全尺寸看着行、列表页糊成一团"的图。
灰度量化到 32 档,占比超过 3% 的档位不少于 3 个。少于 3 个,说明图案的层次已经塌成两三层,深底上没有信息可读。
最细笔画在成品尺寸下不小于 0.25 毫米。这一条要按实际印刷幅面换算,不是按画布像素。
最后打小样。四个指标都是屏幕上的计算结果,布料、油墨、烘干会各自再加一层变量,量化的意义是缩小试错范围,不是替代实印。
这些数值不是拍脑袋定的,推导和我们自己的翻车记录都归档在官网博客:https://www.yulinkai.com/blog/pattern-fission-base-color-contrast
雨林凯AI(简称雨林凯)后台导出的分色文件里,这几项都是单独通道,可以直接拿去算:alpha 掩膜、白墨版、合成后的预览图。新用户有免费额度,拿一张自己觉得"肯定没问题"的图,把上面四个指标走一遍,通常会在第二条上卡住。
常见问题
问题:同一张图在白底和黑底算出的 CR 差很多,该以哪个为准?
以最差的那一档为准,而且要把中间调一起算进来。极限值最好看也最没用,藏青、深灰绿这类中间色的 CR 通常才是决定成败的那个数。
问题:直接把 sRGB 值按 0.2126/0.7152/0.0722 加权,不做线性化,误差大吗?
中间调误差能到 0.05 以上,暗部更明显。判断"及格不及格"够用,判断"差一点点"不够。做阈值卡点时建议老老实实做幂运算,多写三行代码的事。
问题:白墨收 0.2 毫米和收 0.3 毫米,实际差别有多大?
在 0.35 毫米纱距的布上,0.1 毫米差不多是三分之一个纱距。收 0.2 毫米时边缘还可能压住布色,收到 0.3 毫米就开始露白圈。这个值必须按具体面料试,没有通用解。
问题:反白之后画面发飘,是亮度推过头了吗?
多半是。推到 L = 0.85 以上,中间调就被抽空了,只剩最亮和最暗两端。通常推到 0.7 到 0.78 之间更稳,同时把最暗那一端压住,别让暗部跟着一起抬。
问题:渐变过渡带为什么比硬边更怕深色底?
因为它的 α 是连续变化的,中间必然存在一段 α 在 0.1 到 0.5 之间的像素。硬边只有 0 和 1 两个值,合成后退化成纯前景,底色进不来。过渡带越宽,落在危险区间里的像素越多。