所谓的混合模式,也就是颜色的混合。混合模式是从PDF1.4标准开始引进。它决定了上层图形和下层已有内容重叠时该如何显示它们的混合色。
混合模式的写法
混合模式是通过扩展图形状态字典来定义的,刚刚好我们在上一篇文章中介绍了这个概念。它的键名为 /BM 后面跟模式的名称。PDF支持的混合模式类型如下:
| 模式名称 | 中文 | 计算方式 |
|---|---|---|
| Normal | 正常模式 | 默认模式,上层直接覆盖下层(结合透明度时按比例混合) |
| Multiply | 正片叠底 | $C_r = C_s \times C_b$。颜色相乘,结果总是变暗,类似两张半透明彩色胶片重叠 |
| Screen | 滤色 | 互补色相乘,结果总是变亮,类似多盏彩色灯光重叠照射 |
| Overlay | 叠加 | 根据背景暗/亮自动切换 Multiply 或 Screen,保留背景的高光与阴影 |
| Darken | 变暗 | 取两者各通道的最小值 |
| SoftLight | 柔光 | 其核心作用是根据源颜色的明暗来使背景色变暗或变亮,效果类似于在背景上照射一束漫射的柔和聚光灯 |
| HardLight | 强光 | 当顶层源颜色较亮时,效果类似滤色;当较暗时,类似正片叠底,视觉效果如同用强烈的光束照射背景 |
| Difference | 差值 | 取两者 RGB 值的绝对差,常用于色彩反转和对比校验 |
| Exclusion | 排除 | 其效果类似于差值模式但反差更柔和, 计算公式为 $C_r = C_b + C_s - 2 \times C_b \times C_s$ |
示例
下面我们来看具体的例子:
2 0 obj
<< /Type /Page % 这是一个页面
/MediaBox [0 0 700 792] % 纸张尺寸为美国信肖像(612点x792点)
/Contents [3 0 R] % 图形内容在对象4中
/Resources <<
/Font <<
/F1 5 0 R % 注册字体信息
>>
/ExtGState <<
/GS_Normal <</BM /Normal>>
/GS_Multiply <</BM /Multiply>>
/GS_Screen <</BM /Screen>>
/GS_Overlay <</BM /Overlay>>
/GS_Darken <</BM /Darken>>
/GS_SoftLight <</BM /SoftLight>>
/GS_Difference <</BM /Difference>>
/GS_Exclusion <</BM /Exclusion>>
>>
>>
endobj
3 0 obj % 页面内容流
<< >>
stream % 流的开始
0.8 0 0 0 k
100 150 400 400 re f %底色采用青色的矩形
%======= Normal 模式==============
/GS_Normal gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
0 500 Td
(Normal) Tj
ET
%====== Multiply 模式 ==================
/GS_Multiply gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
0 400 Td
(Multiply) Tj
ET
%====== Screen 模式 ==================
/GS_Screen gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
0 300 Td
(Screen) Tj
ET
%====== Overlay 模式 ==================
/GS_Overlay gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
0 200 Td
(Overlay) Tj
ET
%======= Darken 模式==============
/GS_Darkens gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
350 500 Td
(Darken) Tj
ET
%====== SoftLight 模式 ==================
/GS_SoftLight gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
350 400 Td
(SoftLight) Tj
ET
%====== Difference 模式 ==================
/GS_Difference gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
350 300 Td
(Difference) Tj
ET
%====== Exclusion 模式 ==================
/GS_Exclusion gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
350 200 Td
(Exclusion) Tj
ET
endstream % 流结束
endobj
5 0 obj
<<
/Type /Font
/Subtype /Type1 % 标准 Type1 字体字典定义
/BaseFont /Helvetica %内置 Helvetica 字体,无需嵌入字体文件
>>
endobj上面的例子我们往Page对象中注册了资源,里面有:字体资源、混合模式资源。字体资源我们引用了5这个对象,而混合模式的资源我们注册在 ExtGState 里面,它的注册与上一篇中注册图形状态字典类似。我们注册了8种混合模式的字典。
接着我们在页面中绘制了一个大的青色矩形作为底色,然后在适当的位置绘制了各种字符,通过字符颜色和底色进行混合来测试不同混合模式的显示效果,最终的效果如下:
关于字体相关的部分,我们将在后面进行介绍。这里我们看到定义颜色时使用的操作符是k,而不是我们以前使用的rg操作符。这是因为这里使用的是 CMYK (Cyan、Magenta、Yellow、Key) 颜色空间,而rg是用来定义rgb颜色空间的。而 CMYK 需要四个颜色值。关于颜色空间的内容我们将在后面讲解。
透明度
关于透明度,我觉得这里不需要特别解释它的概念。
不透明度使用 /CA(填充不透明度) 或者 /ca(描边不透明度) 。需要注意的是PDF渲染引擎在计算最终的颜色时,先计算混合模式的值,之后根据透明度再计算一个最终的颜色。假设不透明度是 $\alpha$ , 混合模式计算的值是 $C_blend$ ,最终的颜色可以使用下列公式计算
$C_final = \alpha \times C_blend + (1-\alpha) \times C_blackground$
我们仍然采用上面的例子,只不过这一次新增一个不透明度,我们将不透明度定为 0.5
2 0 obj
<< /Type /Page % 这是一个页面
/MediaBox [0 0 700 792] % 纸张尺寸为美国信肖像(612点x792点)
/Contents [3 0 R] % 图形内容在对象4中
/Resources <<
/Font <<
/F1 5 0 R % 注册字体信息
>>
/ExtGState <<
/GS_Alpha50 <</CA 0.5 /ca 0.5>>
/GS_Normal <</BM /Normal>>
/GS_Multiply <</BM /Multiply>>
/GS_Screen <</BM /Screen>>
/GS_Overlay <</BM /Overlay>>
/GS_Darken <</BM /Darken>>
/GS_SoftLight <</BM /SoftLight>>
/GS_Difference <</BM /Difference>>
/GS_Exclusion <</BM /Exclusion>>
>>
>>
endobj我们这里定义了一个不透明度,可以在适当的时候调用。实际上我们调用字典中定义的属性本质上就是在使用图形状态操作符,一旦设置了后面如果没有手动变更,那么整个流中都会采用这个状态。
3 0 obj % 页面内容流
<< >>
stream % 流的开始
0.8 0 0 0 k
100 150 400 400 re f %底色采用青色的矩形
/GS_Alpha50 gs %设置全局的不透明度
%======= Normal 模式==============
/GS_Normal gs
0 0.9 0 0 k %字体颜色为洋红色
BT
/F1 72 Tf
0 500 Td
(Normal) Tj
ET
%====== Multiply 模式 ==================
% ...... 按照上面的例子依次往下列举各个混合模式
endstream % 流结束
endobj这里我将它放到定义矩形之后、开始混合模式之前。最终得到的结果如下:
放到其他位置显示的效果又不太一样,这个读者可以自行去尝试
总结
本节到此就结束了。本节中的不透明度和混合模式理解起来不难。虽然每种混合模式标准中都定义了详细的计算方式,但是我们并不是要开发PDF渲染引擎,本文只用来作为扫盲,只涉及一些大概的概念即可。关于混合模式的详细信息可以在PDF标准中的 关于 blend mode 模块中找到
评论 (0)