所谓的混合模式,也就是颜色的混合。混合模式是从PDF1.4标准开始引进。它决定了上层图形和下层已有内容重叠时该如何显示它们的混合色。
混合模式的写法
混合模式是通过扩展图形状态字典来定义的,刚刚好我们在上一篇文章中介绍了这个概念。它的键名为 /BM 后面跟模式的名称。PDF支持的混合模式类型如下:
![]() | ||
![]() |
示例
下面我们来看具体的例子:
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>>>>>>endobj3 0 obj % 页面内容流<< >>stream % 流的开始0.8 0 0 0 k100 150 400 400 re f %底色采用青色的矩形%======= Normal 模式==============/GS_Normal gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf0 500 Td(Normal) TjET%====== Multiply 模式 ==================/GS_Multiply gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf0 400 Td(Multiply) TjET%====== Screen 模式 ==================/GS_Screen gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf0 300 Td(Screen) TjET%====== Overlay 模式 ==================/GS_Overlay gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf0 200 Td(Overlay) TjET%======= Darken 模式==============/GS_Darkens gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf350 500 Td(Darken) TjET%====== SoftLight 模式 ==================/GS_SoftLight gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf350 400 Td(SoftLight) TjET%====== Difference 模式 ==================/GS_Difference gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf350 300 Td(Difference) TjET%====== Exclusion 模式 ==================/GS_Exclusion gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf350 200 Td(Exclusion) TjETendstream % 流结束endobj5 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渲染引擎在计算最终的颜色时,先计算混合模式的值,之后根据透明度再计算一个最终的颜色。假设不透明度是
, 混合模式计算的值是
,最终的颜色可以使用下列公式计算

我们仍然采用上面的例子,只不过这一次新增一个不透明度,我们将不透明度定为 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 k100 150 400 400 re f %底色采用青色的矩形/GS_Alpha50 gs %设置全局的不透明度%======= Normal 模式==============/GS_Normal gs0 0.9 0 0 k %字体颜色为洋红色BT/F1 72 Tf0 500 Td(Normal) TjET%====== Multiply 模式 ==================% ...... 按照上面的例子依次往下列举各个混合模式endstream % 流结束endobj
这里我将它放到定义矩形之后、开始混合模式之前。最终得到的结果如下:

放到其他位置显示的效果又不太一样,这个读者可以自行去尝试
总结
本节到此就结束了。本节中的不透明度和混合模式理解起来不难。虽然每种混合模式标准中都定义了详细的计算方式,但是我们并不是要开发PDF渲染引擎,本文只用来作为扫盲,只涉及一些大概的概念即可。关于混合模式的详细信息可以在PDF标准中的 关于 blend mode 模块中找到
夜雨聆风
