1. 引言
本小节是非规范性的。
本文档的第一部分描述用于在 CSS 中控制合成的属性。第二部分将描述 Porter Duff 合成和混合的算法。
2. 阅读本文档
除非另有说明,否则本文档的每个章节都是规范性的。
2.1. 模块交互
本规范定义了一组影响元素视觉渲染的 CSS 属性;这些效果在元素依据 视觉格式化模型([CSS21])完成尺寸和定位之后才会应用。其中一些属性值会导致创建 包含块,以及/或创建层叠上下文。
background-blend-mode 属性同样基于 CSS 背景与边框 模块([CSS3BG])中定义的属性。
本规范还增强了 SVG 1.1 第 14.2 节—简单 Alpha 合成([SVG11])以及 CSS Color Module Level 4 中的简单 Alpha 合成([CSS-COLOR-4])的规则。
此模块同样扩展了 globalCompositeOperation 属性。
2.2. 值
本规范遵循 CSS 属性定义约定([CSS21])。在本规范中未定义的取值类型在 CSS Level 2 Revision 1([CSS21])中有定义。其他 CSS 模块可以扩展这些取值类型的定义:例如,当与本模块结合时,[CSS-COLOR-4] 扩展了本规范中使用的 <color> 取值类型的定义。
除了其定义中列出的属性特定值外,本规范中定义的所有属性也都接受 inherit 关键字作为其属性值。为了可读性,不再重复说明。
3. 在 CSS 中指定混合
3.1. 图形操作的顺序
合成模型必须遵循 SVG 合成模型([SVG11]):先应用任何过滤效果,然后是剪裁、遮罩、混合和合成。
3.2. 特定于 HTML 的行为
CSS 中所有创建 层叠上下文 的东西必须视为“隔离”组。HTML 元素本身不应创建组。
对具有混合效果的元素,必须与其所属 层叠上下文([CSS21])中所有底层内容进行混合。
HTML 文档的根元素是 文档元素。
3.3. 特定于 SVG 的行为
默认情况下,每个元素都必须创建一个非隔离组。
然而,SVG 中的某些操作会创建隔离组。如果使用以下任一特性,所属组必须变为隔离:
- opacity
- 滤镜
- 3D 变换(2D 变换**不**导致隔离)
- 混合
- 遮罩
SVG 文档的根元素是 SVG 元素。
3.4. CSS 属性
3.4.1. The mix-blend-mode 属性
混合模式定义了用于将颜色与背景层混合的公式。此行为在 混合 部分有更详细的描述。
| 名称 | mix-blend-mode |
|---|---|
| 值 | <blend-mode> |
| 初始值 | normal |
| 应用于 | 所有元素均适用。在 SVG 中,它适用于 容器元素、图形元素 以及 图形引用元素。[SVG11] |
| 可继承 | 否 |
| 百分比 | 不适用 |
| 计算值 | 按指定值 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
| 媒体 | 视觉 |
属性 <blend-mode> 的语法如下:
<blend-mode> = normal | darken | multiply | color-burn | lighten | screen | color-dodge | overlay | soft-light | hard-light | difference | exclusion | hue | saturation | color | luminosity
将除 普通 之外的混合模式应用于元素时,必须建立一个新的 层叠上下文([CSS21])。随后,这个组必须与包含该元素的层叠上下文进行混合和合成。
测试
- Blending_in_a_group_with_filter.html(视觉测试) (源代码)
- Blending_in_a_group_with_opacity.html(视觉测试) (源代码)
- Text_with_SVG_background.html(视觉测试) (源代码)
- inheritance.html (实时测试) (源代码)
- line-with-svg-background.html(视觉测试) (源代码)
- mix-blend-mode-in-svg-image.html (实时测试) (源代码)
- mix-blend-mode-svg-rectangle.html (实时测试) (源代码)
- text-with-svg-background.html(视觉测试) (源代码)
- mix-blend-mode-animation.html (实时测试) (源代码)
- mix-blend-mode-blended-element-interposed.html (实时测试) (源代码)
- mix-blend-mode-blended-element-overflow-hidden-and-border-radius.html (实时测试) (源代码)
- mix-blend-mode-blended-element-overflow-scroll.html (实时测试) (源代码)
- mix-blend-mode-blended-element-with-transparent-pixels.html (实时测试) (源代码)
- mix-blend-mode-blended-with-3D-transform.html (实时测试) (源代码)
- mix-blend-mode-blended-with-transform-and-perspective.html (实时测试) (源代码)
- mix-blend-mode-blending-with-sibling.html (实时测试) (源代码)
- mix-blend-mode-border-image.html (实时测试) (源代码)
- mix-blend-mode-both-parent-and-blended-with-3D-transform.html (实时测试) (源代码)
- mix-blend-mode-canvas-parent.html (实时测试) (源代码)
- mix-blend-mode-canvas-sibling.html (实时测试) (源代码)
- mix-blend-mode-creates-stacking-context.html (实时测试) (源代码)
- mix-blend-mode-filter.html (实时测试) (源代码)
- mix-blend-mode-iframe-parent.html (实时测试) (源代码)
- mix-blend-mode-iframe-sibling.html (实时测试) (源代码)
- mix-blend-mode-image.html (实时测试) (源代码)
- mix-blend-mode-intermediate-element-overflow-hidden-and-border-radius.html (实时测试) (源代码)
- mix-blend-mode-mask.html (实时测试) (源代码)
- mix-blend-mode-overflowing-child-of-blended-element.html (实时测试) (源代码)
- mix-blend-mode-overflowing-child.html (实时测试) (源代码)
- mix-blend-mode-paragraph-background-image.html (实时测试) (源代码)
- mix-blend-mode-paragraph.html (实时测试) (源代码)
- mix-blend-mode-parent-element-overflow-hidden-and-border-radius.html (实时测试) (源代码)
- mix-blend-mode-parent-element-overflow-scroll-blended-position-fixed.html (实时测试) (源代码)
- mix-blend-mode-parent-element-overflow-scroll.html (实时测试) (源代码)
- mix-blend-mode-parent-with-3D-transform-and-transition.html(视觉测试) (源代码)
- mix-blend-mode-parent-with-3D-transform.html (实时测试) (源代码)
- mix-blend-mode-parent-with-border-radius.html (实时测试) (源代码)
- mix-blend-mode-parent-with-text.html (实时测试) (源代码)
- mix-blend-mode-parsing.html (实时测试) (源代码)
- mix-blend-mode-plus-lighter-basic.html (实时测试) (源代码)
- mix-blend-mode-plus-lighter-svg-basic.html (实时测试) (源代码)
- mix-blend-mode-plus-lighter-svg.html (实时测试) (源代码)
- mix-blend-mode-plus-lighter.html (实时测试) (源代码)
- mix-blend-mode-root-element-group.html (实时测试) (源代码)
- mix-blend-mode-rotated-clip.html (实时测试) (源代码)
- mix-blend-mode-script.html (实时测试) (源代码)
- mix-blend-mode-sibling-with-3D-transform-and-transition.html(视觉测试) (源代码)
- mix-blend-mode-sibling-with-3D-transform.html (实时测试) (源代码)
- mix-blend-mode-simple.html (实时测试) (源代码)
- mix-blend-mode-stacking-context-001.html (实时测试) (源代码)
- mix-blend-mode-stacking-context-creates-isolation.html (实时测试) (源代码)
- mix-blend-mode-svg.html (实时测试) (源代码)
- mix-blend-mode-video-sibling.html (实时测试) (源代码)
- mix-blend-mode-video.html (实时测试) (源代码)
- mix-blend-mode-with-transform-and-preserve-3D.html (实时测试) (源代码)
- mix-blend-mode-computed.html (实时测试) (源代码)
- mix-blend-mode-invalid.html (实时测试) (源代码)
- mix-blend-mode-valid.html (实时测试) (源代码)
以下是给定的示例标记
<body> <img src="ducky.png"/> </body>
以及以下样式规则
body { background-color: lime; }
... 将产生以下结果
部分透明图像在青柠色背景上
如果我们将样式规则更改为包括混合
body { background-color: lime; }
img { mix-blend-mode: multiply; }
... 输出将是图像与
元素的青柠色背景混合的结果。
在酸橙色背景上混合透明图像。
以下为 svg 代码
<svg> <circle cx="40" cy="40" r="40" fill="red"/> <circle cx="80" cy="40" r="40" fill="lime"/> <circle cx="60" cy="80" r="40" fill="blue"/> </svg>
以及以下样式规则
circle { mix-blend-mode: screen; }
……输出将是 3 个圆的混合。每个圆按照从底部到顶部的顺序渲染。当元素重叠时,混合模式会产生颜色变化。
使用 screen 混合模式的 3 个圆的混合示例
在以下样式表和文档片段中
body { background-color: lime; }
div { background-color: red; width: 200px; opacity: .95}
img { mix-blend-mode: difference; }
<body>
<div>
<img src="ducky.png"/>
</div>
</body>
……<div> 元素上的 opacity 会创建堆叠上下文。这导致创建一个新组,使图像不会与 <body> 的颜色混合。
堆叠上下文内的混合示例。
请注意图像未与酸橙色混合。
以下是给定的示例标记
<body>
<div>
<p>overlay blending on text</p>
</div>
</body>
以及以下样式规则
div { background-image: url('texture.png'); }
@font-face {
font-family: "Mythos Std";
src: url("http://myfontvendor.com/mythos.otf");
}
p {
mix-blend-mode: overlay;
font-family: "Mythos Std"
}
在图像上方带有混合叠加的文字。
3.4.2. isolation 属性
在 SVG 中,这定义了元素是否被隔离。
对于 CSS,将 isolation 设置为 isolate 会将该元素变为堆叠上下文。
默认情况下,元素使用 auto 关键字,暗示它们不被隔离。然而导致创建堆叠上下文的操作[CSS21] 必须使组被隔离。这些操作在 “针对 HTML 的行为” 和 “针对 SVG 的行为” 中有描述。
| 名称 | isolation |
|---|---|
| 值 | <isolation-mode> |
| 初始值 | auto |
| 应用于 | 所有元素均适用。在 SVG 中,它适用于 容器元素、图形元素 以及 图形引用元素。[SVG11] |
| 可继承 | 否 |
| 百分比 | 不适用 |
| 计算值 | 按指定值 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
| 媒体 | 视觉 |
属性 <isolation-mode> 的语法如下:
<isolation-mode> = auto | isolate
测试
在 CSS 中,背景图像或 img 元素的内容必须始终渲染到一个隔离组中。
例如,如果通过 img 标签引用 SVG 文件,则该 SVG 的图形不会与内容的背景混合。
在 SVG 中,mask 总是会创建一个隔离组。
3.4.3. background-blend-mode 属性
定义每个背景层的混合模式。
每个背景层必须与其下方的元素背景层以及元素的背景颜色进行混合。背景层不得与元素后面的内容混合,而应视为渲染到一个隔离组中。
下文是 background-blend-mode 属性的描述:
| 名称 | background-blend-mode |
|---|---|
| 值 | <blend-mode># |
| 初始值 | normal |
| 应用于 | 所有 HTML 元素 |
| 可继承 | 否 |
| 百分比 | 不适用 |
| 计算值 | 按指定值 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
| 媒体 | 视觉 |
测试
- inheritance.html (实时测试) (源代码)
- background-blend-mode-gradient-image.html (live test) (source)
- background-blend-mode-plus-lighter.html (live test) (source)
- background-blend-mode-computed-multiple.html (live test) (source)
- background-blend-mode-computed.html (live test) (source)
- background-blend-mode-invalid.html (live test) (source)
- background-blend-mode-valid.html (live test) (source)
The background-blend-mode 列必须按照 background-image [CSS3BG] 的顺序应用。这意味着列表中的第一个元素对应最上层的背景层。如果属性提供的逗号分隔值不足以匹配所有层数,UA 必须通过重复值列表来产生足够的值。
如果使用 background [CSS3BG] 简写,则该元素的 background-blend-mode 必须重置为其初始值。
以下是给定的示例标记
<body> <div></div> </body>
以及以下样式规则
body { background-color: lime; }
div {
width: 200px;
height: 200px;
background-size: 200px 200px;
background-repeat:no-repeat;
background-image: linear-gradient(to right, #000000 0%,#ffffff 100%), url('ducky.png');
background-blend-mode: difference, normal;
}
两个背景图像的混合。
请注意渐变未与 body 的颜色混合,而是保持其原始颜色。
4. 在 Canvas 2D 中指定合成和混合
canvas 2d 上下文定义了 globalCompositeOperation 属性,用于设置当前的合成和混合操作符。
此属性接受如下值
- ‘globalCompositeOperation’
-
值 <blend-mode> | <composite-mode> 初始值 source-over
属性 <composite-mode> 的语法如下:
<composite-mode> = clear | copy | source-over | destination-over | source-in |
destination-in | source-out | destination-out | source-atop |
destination-atop | xor | lighter
5. 合成简介
合成是将图形元素与其背景进行组合的过程。
在本规范描述的模型中,整体合成操作分为两步——Porter‑Duff 合成和混合。混合步骤决定图形元素颜色与背景颜色的交互方式。
通常,先执行混合步骤,然后再执行 Porter‑Duff 合成步骤。在混合步骤中,先计算图形元素与背景的混合后得到的颜色。图形元素的颜色被此结果颜色取代。随后,图形元素再使用指定的合成算子与背景合成。
注:形状由其数学描述定义。一个特定点要么在形状内部,要么不在形状内部,没有渐变层级。
注:不透明度使用 alpha 值描述,该值与每个点的颜色值一起存储,范围为 0 至 1(包含两端)。alpha 为 0 表示该像素在该点没有覆盖,因而完全透明;即没有任何几何体对该像素有颜色贡献,因为几何体并未覆盖该像素。alpha 为 1 表示像素完全不透明,几何体完全覆盖该像素。
5.1. 简单 alpha 合成
简单 alpha 合成的公式为
co = Cs x αs + Cb x αb x (1 - αs)
其中
注:所有数值均在 0 至 1(含)之间。
合成后像素值(co)通过将源图形元素的贡献 [Cs × αs] 与背景的贡献 [Cb × αb × (1 – αs)] 相加得到。对源图形元素和背景来说,颜色值均乘以 alpha,以确定其颜色贡献量。alpha 为 0 表示颜色不贡献,部分 alpha 表示按该比例贡献。背景的贡献还会受到图形元素不透明度的进一步削减。概念上,背景的 (1 – αs) 份会透过图形元素显示,这意味着若图形元素完全不透明 (αs = 1),则背景完全不可见。
上述简单 alpha 合成公式得到的结果颜色,是背景颜色与图形元素颜色的加权平均,权重由两者的 alpha 决定。合成的最终 alpha 简单地等于各组成元素贡献的 alpha 之和。结果 alpha 的公式为
αo = αs + αb x (1 - αs)
其中
- αo:合成的 alpha 值
- αs:图形元素的 alpha 值
- αb:背景的 alpha 值
通常,为了提高效率,可以存储颜色和不透明度的预乘值。预乘值的计算方式为
cs = Cs x αs
为
- cs:预乘值
- Cs:颜色值
- αs:alpha 值
因此,使用预乘值的简单 alpha 合成公式可写为
co = cs + cb x (1 - αs)
要从预乘值中提取颜色分量,需要对公式进行逆运算。
Co = co / αo
5.1.1. 简单 alpha 合成示例
这是最基本的情况:只有 1 个形状,用实色填充(α = 1),该形状与一个空白背景合成。空白背景对最终合成没有影响。
Cs = RGB(1,0,0) αs = 1 Cb = RGB(0,0,0) αb = 0 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(1,0,0) x 1 + RGB(0,0,0) x 0 x (1 - 1) co = RGB(1,0,0) x 1 co = RGB(1,0,0)
这是更复杂的例子。没有透明度,但两个形状相交。
在交叉区域应用合成公式,可得
Cs = RGB(0,0,1) αs = 1 Cb = RGB(1,0,0) αb = 1 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(0,0,1) x 1 + RGB(1,0,0) x 1 x (1 - 1) co = RGB(0,0,1) x 1 + RGB(1,0,0) x 1 x 0 co = RGB(0,0,1) x 1 co = RGB(0,0,1)
计算结果合成的 alpha
αo = αs + αb x (1 - αs) αo = 1 + 1 x (1 - 1) αo = 1
计算结果合成的颜色分量
Co = co / αo Co = RGB(0, 0, 1) / 1 Co = RGB(0, 0, 1)
此例中形状具有一定透明度,但背景完全不透明。
在交叉区域应用合成公式,可得
Cs = RGB(0,0,1) αs = 0.5 Cb = RGB(1,0,0) αb = 1 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 1 x (1 - 0.5) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 0.5 co = RGB(0.5,0,0.5)
计算结果合成的 alpha
αo = αs + αb x (1 - αs) αo = 0.5 + 1 x (1 - 0.5) αo = 1
计算结果合成的颜色分量
Co = co / αo Co = RGB(0.5, 0, 0.5) / 1 Co = RGB(0.5, 0, 0.5)
图 4 展示了形状和背景均为透明的示例。
在交叉区域应用合成公式,可得
Cs = RGB(0,0,1) αs = 0.5 Cb = RGB(1,0,0) αb = 0.5 co = Cs x αs + Cb x αb x (1 - αs) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 0.5 x (1 - 0.5) co = RGB(0,0,1) x 0.5 + RGB(1,0,0) x 0.25 co = RGB(0.25, 0, 0.5)
计算结果合成的 alpha
αo = αs + αb x (1 - αs) αo = 0.5 + 0.5 x (1 - 0.5) αo = 0.75
计算结果合成的颜色分量
Co = co / αo Co = RGB(0.25, 0, 0.5) / 0.75 Co = RGB(0.33, 0, 0.66)
6. 合成和混合的一般公式
合成和混合的一般公式允许选择合成算子和混合函数,共包含两步。后续章节将详细说明这些函数中使用的术语。
原位应用混合
Cs = (1 - αb) x Cs + αb x B(Cb, Cs)
合成
Co = αs x Fa x Cs + αb x Fb x Cb
其中
- Cs:源颜色
- Cb:背景颜色
- αs:源 alpha
- αb:背景 alpha
- B(Cb, Cs):混合函数
- Fa:由所使用的 Porter‑Duff 运算符定义
- Fb:由所使用的 Porter‑Duff 运算符定义
7. 背景计算
背景 是指元素后面的内容,即元素与之合成的对象。这意味着背景是所有先前元素合成的结果。
7.1. 背景计算示例
8. 合成组
合成组可以更细致地控制合成与背景的交互方式。使用合成组可以指定组内的合成效果如何与场景中已有内容(背景)交互。
合成组可以包含任意数量的元素,也可以包含其他合成组。
合成组的默认属性应当在视觉上与没有组的情况保持一致。参见 组不变性。
渲染合成组的过程是:先将组内元素合成到初始背景上,得到包含颜色和 alpha 信息的单一元素。随后将该元素再合成到组背景上。必须确保组背景只对最终合成贡献一次。
- initial backdrop
- 初始背景是用于合成组中第一个元素的背景。对于非隔离组,这与组背景相同;对于隔离组,则为完全透明的黑色背景。
- group backdrop
- 组背景是指在组的第一个元素之前(不包括该元素)所有元素的合成结果。
8.1. 组不变性
简单 alpha 合成的一个重要属性是其组不变性。这一行为在本规范描述的更复杂模型中得以保留。使用默认属性添加或删除分组不应产生视觉差异。
so: A + B + C = A + (B + C) = (A + B) + C
当向组添加属性(例如 isolate),或使用除 normal 之外的混合模式,或使用除 source-over 之外的 Porter‑Duff 合成算子时,组可能不再保持不变性。
8.2. 隔离组
在隔离组中,初始背景为全黑且完全透明。
此时,初始背景不同于组背景。只有在将组的计算颜色、形状和 alpha 与组背景合成时,才会发生交互。
有关隔离组对合成影响的描述请参见 ‘隔离组与 Porter‑Duff 模式’;有关隔离组对混合影响的描述请参见 ‘组隔离对混合的影响’。
8.3. 根元素组
根元素的隔离组即为根元素组。所有其他元素和组都合成到该组中。根元素的背景(如果已指定)会绘制到根元素组中,随后再应用任何过滤器、clip‑path、遮罩和不透明度,最后合成到根组(如果存在)。
测试
- root-element-background-image-transparency-001.html (live test) (source)
- root-element-background-image-transparency-002.html (live test) (source)
- root-element-background-image-transparency-003.html (live test) (source)
- root-element-background-image-transparency-004.html (live test) (source)
- root-element-background-transparency.html (live test) (source)
- root-element-blend-mode.html (live test) (source)
- root-element-filter-background-clip-text-crash.html (live test) (source)
- root-element-filter.html (live test) (source)
- root-element-opacity-change.html (live test) (source)
- root-element-opacity.html (live test) (source)
8.4. 根组
根组包含整个画布,并位于网页根元素组之下或之中。浏览器常常使用一个无限的 白色、100% 不透明 根组进行最终合成,但这并非必需。
9. 高级合成功能
简单 alpha 合成 使用 source‑over Porter‑Duff 合成算子。
Porter‑Duff 合成基于像素模型,其中两个形状(源和目标)可能对像素的最终颜色产生贡献。像素被划分为 4 个子像素区域,每个区域代表源与目标的可能组合。[PORTERDUFF]
这四个区域是
- 仅源
- 只有源对像素颜色作贡献的情况
- 仅目标
- 只有目标对像素颜色作贡献的情况
- 两者皆有
- 源与目标——两者均可组合决定像素颜色
- 无
- 无源或目标——两者均不对最终像素颜色作贡献
注:目标等同于背景。本节使用 “目标” 这一术语是因为它是 Porter‑Duff 合成的标准称呼。此外,合成算子名称中也使用 destination。
| 两者皆有 | αs × αb |
|---|---|
| 仅源 | αs × (1 – αb) |
| 仅目标 | αb × (1 – αs) |
| 无 | (1 – αs) × (1 – αb) |
上图展示了源和目标均为 0.5 覆盖率的情况。
Both = 0.5 x 0.5 = 0.25 Source Only = 0.5 (1 – 0.5) = 0.25 Destination Only = 0.5(1 – 0.5) = 0.25 None = (1 – 0.5)(1 – 0.5) = 0.25
因此在该示例中每个区域的覆盖率为 0.25。
9.1. Porter‑Duff 合成算子
Thomas Porter 与 Tom Duff(曾在 Lucasfilm 工作)撰写的里程碑论文定义了合成代数,并提出了十二种 “Porter‑Duff” 算子。这些算子控制由具有 alpha 或像素覆盖通道/值的图形对象重叠形成的四个子像素区域的混合结果。算子使用了四个区域的全部实用组合。
共计 12 种基本 Porter‑Duff 算子,覆盖了源与目标的所有可能组合。
从每个算子的几何表示可以看出,各形状的贡献以输出总覆盖率的分数形式表达。例如,在 source‑over 中,源的可能贡献为完整的 1,而目标的可能贡献为剩余的 (1 – αs)。该比例再乘以源和目标的覆盖率,得到像素最终覆盖率的公式。
αo = αs x 1 + αb x (1 – αs)
分数项 Fa(本例为 1)和 Fb(本例为 1 – αs)由每个算子定义,指定了形状对最终像素值可能的贡献比例。覆盖率的一般形式为
αs x Fa + αb x Fb
并在加入颜色后得到通用的 Porter‑Duff 方程
co = αs x Fa x Cs + αb x Fb x Cb
其中
- co 为输出颜色的预乘值,α 范围为 0 ≤ co ≤ 1
- αs 为源的覆盖率;Fa 由算子定义并控制是否包含源;Cs 为源颜色(未乘以 alpha)
- αb 为目标的覆盖率;Fb 由算子定义并控制是否包含目标;Cb 为目标颜色(未乘以 alpha)
9.1.1. Clear
没有任何区域被启用。
Fa = 0; Fb = 0 co = 0 αo = 0
9.1.2. Copy
仅保留源。
Fa = 1; Fb = 0 co = αs x Cs αo = αs
9.1.3. Destination
仅保留目标。
Fa = 0; Fb = 1 co = αb x Cb αo = αb
9.1.4. Source Over
源位于目标之上。
Fa = 1; Fb = 1 – αs co = αs x Cs + αb x Cb x (1 – αs) αo = αs + αb x (1 – αs)
9.1.5. Destination Over
目标位于源之上。
Fa = 1 – αb; Fb = 1 co = αs x Cs x (1 – αb) + αb x Cb αo = αs x (1 – αb) + αb
9.1.6. Source In
源在与目标重叠的部分取代目标。
Fa = αb; Fb = 0 co = αs x Cs x αb αo = αs x αb
9.1.7. Destination In
目标在与源重叠的部分取代源。Fa = 0; Fb = αs co = αb x Cb x αs αo = αb x αs
9.1.8. Source Out
源位于不与目标重叠的区域。
Fa = 1 – αb; Fb = 0 co = αs x Cs x (1 – αb) αo = αs x (1 – αb)
9.1.9. Destination Out
目标位于不与源重叠的区域。
Fa = 0; Fb = 1 – αs co = αb x Cb x (1 – αs) αo = αb x (1 – αs)
9.1.10. Source Atop
源在与目标重叠的部分取代目标,目标则放置在其他位置。
Fa = αb; Fb = 1 – αs co = αs x Cs x αb + αb x Cb x (1 – αs) αo = αs x αb + αb x (1 – αs)
9.1.11. Destination Atop
目标在与源重叠的部分取代源,源则放置在其他位置。
Fa = 1 - αb; Fb = αs co = αs x Cs x (1 - αb) + αb x Cb x αs αo = αs x (1 - αb) + αb x αs
9.1.12. XOR
将源和目标的非重叠区域组合。
Fa = 1 - αb; Fb = 1 – αs co = αs x Cs x (1 - αb) + αb x Cb x (1 – αs) αo = αs x (1 - αb) + αb x (1 – αs)
9.1.13. Lighter
显示源图像与目标图像的和。该算子在 Porter‑Duff 论文中被定义为 plus [PORTERDUFF]。Fa = 1; Fb = 1 co = αs x Cs + αb x Cb; αo = αs + αb
9.2. 使用 Porter‑Duff 模式的组合成行为
在隔离组内对元素进行合成时,元素会在透明的黑色初始背景上合成。如果组中最底层的元素使用了依赖于背景的 Porter‑Duff 合成算子(如 destination、source‑in、destination‑in、destination‑out 或 source‑atop),则第一次合成的结果将为空。组内后续元素将与第一次合成的结果继续合成。
10. 混合
混合是合成的一个方面,用来计算源元素与背景重叠时颜色的混合方式。
概念上,源元素的颜色会在原位与背景混合。混合完成后,修改后的源元素再与背景合成。实际操作中,这通常一步完成。
混合计算不得使用预乘颜色值。
“混合”公式定义为:
Cm = B(Cb, Cs)
为
- Cm:混合后的结果颜色
- B:执行混合的公式
- Cb:背景颜色
- Cs:源颜色
混合公式的结果必须限制在颜色范围的最小值和最大值之间。
混合函数的结果会受到背景 alpha 的调制。完全不透明的背景允许混合函数完整实现;透明背景则会使最终结果成为源颜色与混合后颜色的加权平均,权重由背景 alpha 控制。新颜色的值为:
Cr = (1 - αb) x Cs + αb x B(Cb, Cs)
为
注:以下公式给出源与背景相交区域的颜色值,然后使用指定的 Porter‑Duff 合成公式进行合成。对于简单 alpha 混合,该公式可简化为:
simple alpha compositing:
co = cs + cb x (1 - αs)
written as non-premultiplied:
αo x Co = αs x Cs + (1 - αs) x αb x Cb
now substitute the result of blending for Cs:
αo x Co = αs x ((1 - αb) x Cs + αb x B(Cb, Cs)) + (1 - αs) x αb x Cb
= αs x (1 - αb) x Cs + αs x αb x B(Cb, Cs) + (1 - αs) x αb x Cb
10.1. 可分离混合模式
如果每个结果颜色分量完全由对应的背景和源颜色分量决定,则称该混合模式为可分离的——即混合公式会 分别 应用于每一对对应分量。
下面的每种混合模式都会对每个颜色分量执行混合函数 B(Cb, Cs)。为简化起见,本章所有示例均使用 source‑over 合成。
10.1.1. normal 混合模式
这是默认属性,表示不进行混合。混合公式仅选择源颜色。
B(Cb, Cs) = Cs
10.1.2. multiply 混合模式
源颜色与目标颜色相乘后取代目标颜色。
结果颜色始终不比源或目标颜色更亮。任意颜色与黑色相乘得到黑色;与白色相乘则保持原色。
B(Cb, Cs) = Cb x Cs
10.1.3. screen 混合模式
对背景和源颜色值取补数后相乘,再取结果的补数。
结果颜色始终不比两者中任意一个更暗。任意颜色与白色进行 screen 会得到白色;与黑色进行 screen 则保持原色不变。该效果类似于将多张幻灯片同时投射到同一屏幕上。
B(Cb, Cs) = 1 - [(1 - Cb) x (1 - Cs)]
= Cb + Cs -(Cb x Cs)
10.1.4. overlay 混合模式
根据背景颜色值的不同,对颜色进行乘法或 screen 处理。
源颜色覆盖背景时保留其高光和阴影。背景颜色不被取代,而是与源颜色混合,以反映背景的明暗程度。
B(Cb, Cs) = HardLight(Cs, Cb)
Overlay 是 hard-light 混合模式的反向。请参阅 hard-light 的定义了解公式。
10.1.5. darken 混合模式
从 backdrop 和源颜色中选择较暗的那一个。
当源颜色更暗时,用源颜色替换 backdrop;否则保持不变。
B(Cb, Cs) = min(Cb, Cs)
10.1.6. lighten 混合模式
从 backdrop 和源颜色中选择较亮的那一个。
当源颜色更亮时,用源颜色替换 backdrop;否则保持不变。
B(Cb, Cs) = max(Cb, Cs)
如果结果超出范围,必须向下取整。
10.1.7. color-dodge 混合模式
将 backdrop 颜色变亮,以反映源颜色。使用黑色绘制不会产生任何变化。
if(Cb == 0)
B(Cb, Cs) = 0
else if(Cs == 1)
B(Cb, Cs) = 1
else
B(Cb, Cs) = min(1, Cb / (1 - Cs))
10.1.8. color-burn 混合模式
将 backdrop 颜色变暗,以反映源颜色。使用白色绘制不会产生任何变化。
if(Cb == 1)
B(Cb, Cs) = 1
else if(Cs == 0)
B(Cb, Cs) = 0
else
B(Cb, Cs) = 1 - min(1, (1 - Cb) / Cs)
10.1.9. hard-light 混合模式
根据源颜色值,对颜色执行 multiply(乘算)或 screen(筛选)处理。其效果类似于在 backdrop 上投射强光聚光灯。
if(Cs <= 0.5)
B(Cb, Cs) = Multiply(Cb, 2 x Cs)
else
B(Cb, Cs) = Screen(Cb, 2 x Cs -1)
请参阅 multiply 与 screen 的定义了解它们的公式。
10.1.10. soft-light 混合模式
根据源颜色值,对颜色执行变暗或变亮处理。其效果类似于在 backdrop 上投射柔和的漫射聚光灯。
if(Cs <= 0.5)
B(Cb, Cs) = Cb - (1 - 2 x Cs) x Cb x (1 - Cb)
else
B(Cb, Cs) = Cb + (2 x Cs - 1) x (D(Cb) - Cb)
with
if(Cb <= 0.25)
D(Cb) = ((16 * Cb - 12) x Cb + 4) x Cb
else
D(Cb) = sqrt(Cb)
10.1.11. difference 混合模式
从较亮的颜色中减去两种组成颜色中较暗的那一个。
使用白色绘制会对 backdrop 颜色进行反相;使用黑色绘制则不会产生任何变化。
B(Cb, Cs) = | Cb - Cs |
10.1.12. exclusion 混合模式
产生与 Difference 模式相似但对比度更低的效果。使用白色绘制会对 backdrop 颜色进行反相;使用黑色绘制则不会产生任何变化。
B(Cb, Cs) = Cb + Cs - 2 x Cb x Cs
10.2. 不可分离的混合模式
不可分离的混合模式在组合时会同时考虑所有颜色分量,而可分离的混合模式则逐个分量单独处理。所有这些混合模式在概念上都包括以下步骤:
不可分离混合模式的公式会使用若干辅助函数。
Lum(C) = 0.3 x Cred + 0.59 x Cgreen + 0.11 x Cblue
ClipColor(C)
L = Lum(C)
n = min(Cred, Cgreen, Cblue)
x = max(Cred, Cgreen, Cblue)
if(n < 0)
C = L + (((C - L) × L) / (L - n))
if(x > 1)
C = L + (((C - L) × (1 - L)) / (x - L))
return C
SetLum(C, l)
d = l - Lum(C)
Cred = Cred + d
Cgreen = Cgreen + d
Cblue = Cblue + d
return ClipColor(C)
Sat(C) = max(Cred, Cgreen, Cblue) - min(Cred, Cgreen, Cblue)
The subscripts min, mid, and max in the next function refer to the color
components having the minimum, middle, and maximum values upon entry to the function.
SetSat(C, s)
if(Cmax > Cmin)
Cmid = (((Cmid - Cmin) x s) / (Cmax - Cmin))
Cmax = s
else
Cmid = Cmax = 0
Cmin = 0
return C;
10.2.1. hue 混合模式
创建一种颜色,其色相取自源颜色,而饱和度和亮度取自 backdrop 颜色。
B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
10.2.2. saturation 混合模式
创建一种颜色,其饱和度取自源颜色,而色相和亮度取自 backdrop 颜色。在 backdrop 为纯灰(无饱和度)的区域使用此模式绘制不会产生任何变化。
B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
10.2.3. color 混合模式
创建一种颜色,其色相与饱和度取自源颜色,而亮度取自 backdrop 颜色。这会保留 backdrop 的灰度水平,适用于为单色图像上色或为彩色图像增添色调。
B(Cb, Cs) = SetLum(Cs, Lum(Cb))
10.2.4. luminosity 混合模式
创建一种颜色,其亮度取自源颜色,而色相和饱和度取自 backdrop 颜色。这会产生与 Color 模式相反的效果。
B(Cb, Cs) = SetLum(Cb, Lum(Cs))
10.3. 组隔离对混合的影响
注:在以下示例中,用于构造纸飞机的各个元素都位于同一个组中。这些元素的混合模式均设为 multiply。
在隔离组中,组内元素先合成到一个空的初始 backdrop 上,这避免了它们与原始 backdrop 的相乘操作。相对地,在普通组中,组内元素会合成到包含地面和天空的初始 backdrop 上,因此飞机的元素会与地面和天空相乘。无论哪种情况,组的合成结果随后再使用默认的 normal mix‑blend‑mode(即组的默认混合模式)合成到地面和天空上。
隐私性考虑
本规范未报告任何新的隐私考量。
安全性考虑
必须保证混合和合成操作的耗时不受源像素和目标像素值的影响。实现时应确保无论像素值为何,操作所需时间始终相同。
如果未遵守此规则,攻击者可能通过观察耗时推断信息,从而发起计时攻击。
计时攻击是一种通过研究操作所需时间来获取本应受保护的内容信息的方法。例如,如果绘制红色像素所需时间比绘制绿色像素更长,攻击者或许能够在未直接获取元素内容的情况下,重构出该元素的大致图像。
变更
以下更改相对于 2015 年 1 月 13 日的候选推荐稿进行:
- 添加了“隐私”和“安全”章节。
- 将 Animatable: no 更新为 Animation type: discrete。
- 定义了 HTML 与 SVG 的根元素以及根元素组。
- 明确说明根组不一定是不透明的白色。
- 对根组和隔离组提供了更好的定义。
- 统一使用乘号 × 而不是 x 或 *。
- 修正了示例中本应使用 lime 而误用了 green 的错误,现改为 lime。
- 纠正了 background‑blend‑mode 的初始值。
- 对若干标记和链接进行了修复。
以下更改相对于 2014 年 2 月 20 日的候选推荐稿进行:
- 强制隔离通过
<img>嵌入的 SVG 图像已不再存在风险。 - 从 <composite-mode> 中移除了 destination 选项。
以下更改相对于 2014 年 1 月 7 日的最后通稿进行:
- 移除了不必要的规范性和信息性引用。
以下更改相对于 2013 年 10 月 10 日的最后通稿进行:
- 在非规范性章节中删除了 knockout。
- 在简单 alpha 合成章节中删除了关于 SVG 的段落。
- 更新摘要,以涵盖 CSS 并阐明意图。
- 删除了 clip-to-self 及其相关引用。
- 将第 5‑10 节改为规范性内容,并澄清了这些章节中的注释/示例。
以下更改相对于 2013‑06‑25 工作草案进行:
- 在 SVG 中将 clipping 从创建隔离组的运算符之一中移除。
- 修改 background‑blend‑mode,使其行为与其他 background 语法的重复行为保持一致。
- 移除了 mix‑composite 属性。
- 所有未决问题已得到解决。