Xfermode
Xfermode是对象的基类,在绘制管道中这些对象被调用来实现自定义的“传输模式”。
可以调用静态方法Create(Modes)来返回(在Modes枚举中指定的)任何预定义子类的实例。
当Xfermode指定给Paint时,使用该Paint绘制的对象将应用Xfermode。
public class Xfermode {
static final int DEFAULT = PorterDuff.Mode.SRC_OVER.nativeInt;
int porterDuffMode = DEFAULT;
}
PorterDuffXfermode
Paint.setXfermode(Xfermode)传输模式的专门实现。
请参阅PorterDuff.Mode枚举的文档,以获取有关可用alpha合成和混合模式的更多信息。
public class PorterDuffXfermode extends Xfermode {
/** 创建一个使用指定porter-duff模式的xfermode。参数mode:应用的porter-duff模式 */
public PorterDuffXfermode(PorterDuff.Mode mode) {
porterDuffMode = mode.nativeInt;
}
}
PorterDuff
这个类包含可以传递给PorterDuffXfermode的alpha合成和混合模式列表,这是Paint.setXfermode(Xfermode)中传输模式的一个专门实现。
所有可用的模式都可以在Mode枚举中找到。
public class PorterDuff {
// 这些值必须与其本地等效值匹配。详见SkXfermode.h
public enum Mode {
// alpha合成模式
CLEAR (0),
SRC (1),
DST (2),
SRC_OVER (3),
DST_OVER (4),
SRC_IN (5),
DST_IN (6),
SRC_OUT (7),
DST_OUT (8),
SRC_ATOP (9),
DST_ATOP (10),
XOR (11),
// 混合模式
ADD (12),
MULTIPLY (13),
SCREEN (14),
OVERLAY (15);
ARKEN (16),
LIGHTEN (17),
Mode(int nativeInt) {
this.nativeInt = nativeInt;
}
/** @hide */
public final int nativeInt;
}
/** @hide */
public static int modeToInt(Mode mode) {
return mode.nativeInt;
}
/** 18种模式 @hide */
public static Mode intToMode(int val) {
switch (val) {
default:
// alpha合成模式
case 0: return Mode.CLEAR;
case 1: return Mode.SRC;
case 2: return Mode.DST;
case 3: return Mode.SRC_OVER;
case 4: return Mode.DST_OVER;
case 5: return Mode.SRC_IN;
case 6: return Mode.DST_IN;
case 7: return Mode.SRC_OUT;
case 8: return Mode.DST_OUT;
case 9: return Mode.SRC_ATOP;
case 10: return Mode.DST_ATOP;
case 11: return Mode.XOR;
// 混合模式
case 12: return Mode.ADD;
case 13: return Mode.MULTIPLY;
case 14: return Mode.SCREEN;
case 15: return Mode.OVERLAY;
case 16: return Mode.DARKEN;
case 17: return Mode.LIGHTEN;
}
}
}
PorterDuff类名是对Thomas Porter和Tom Duff的作品的敬意,他们在1984年发表了一篇题为《Compositing Digital Images》的开创性论文。在本文中,作者描述了12个合成运算符,它们控制如何计算源(要渲染的图形对象)和目标(渲染目标的内容)的合成所产生的颜色。
《Compositing Digital Images》发表在Computer Graphics第18卷第3期,日期为1984年7月。
由于Porter和Duff的工作只关注源和目标的alpha通道的影响,因此本文中所描述的12个算子被称为alpha合成模式。
为了方便起见,该类还提供了几种混合模式,类似地定义了合成源和目标的结果,但不受alpha通道的约束。这些混合模式不是由Porter和Duff 定义的,而是为了方便起见被包含在这个类中。
合成模式及其合成方程式
下面给出的所有示例图使用相同的源图像和目标图像:
SRC | DST |
---|---|
用于生成每个图表的绘图操作的顺序显示在以下代码段中:
Paint paint = new Paint();
canvas.drawBitmap(destinationImage, 0, 0, paint);
PorterDuff.Mode mode = // choose a mode
paint.setXfermode(new PorterDuffXfermode(mode));
canvas.drawBitmap(sourceImage, 0, 0, paint);
下面每个单独的alpha合成、混合模式的文档提供了用于计算源和目标合成结果的alpha和颜色值的精确公式。结果(或输出)alpha值被标记为“(A_{out})”。结果(或输出)颜色值被标记为“(C_{out})”。
Alpha合成模式及其合成方程式:
Mode | 图片 | 定义 | 新算法 | 旧算法 |
---|---|---|---|---|
CLEAR (0) | 由源覆盖的目标像素被清除为0 |
A
o
u
t
:
0
A_{out} : 0
Aout:0 C o u t : 0 C_{out} : 0 Cout:0 | ||
SRC (1) | 源像素替换目标像素 |
A
o
u
t
:
A
s
r
c
A_{out} : A_{src}
Aout:Asrc C o u t : C s r c C_{out} : C_{src} Cout:Csrc | ||
DST (2) | 源像素被丢弃,保留目标像素不变 |
A
o
u
t
:
A
d
s
t
A_{out} : A_{dst}
Aout:Adst C o u t : C d s t C_{out} : C_{dst} Cout:Cdst | ||
SRC_OVER (3) | 源像素绘制在目标像素上。 注:over上面 |
A
o
u
t
:
A
s
r
c
+
(
1
−
A
s
r
c
)
∗
A
d
s
t
A_{out} : A_{src}+(1-A_{src})*A_{dst}
Aout:Asrc+(1−Asrc)∗Adst C o u t : C s r c + ( 1 − A s r c ) ∗ C d s t C_{out} : C_{src}+(1-A_{src})*C_{dst} Cout:Csrc+(1−Asrc)∗Cdst | ||
DST_OVER (4) | 源像素被绘制在目标像素后面 |
A
o
u
t
:
A
d
s
t
+
(
1
−
A
d
s
t
)
∗
A
s
r
c
A_{out} : A_{dst} + (1 - A_{dst}) * A_{src}
Aout:Adst+(1−Adst)∗Asrc C o u t : C d s t + ( 1 − A d s t ) ∗ C s r c C_{out} : C_{dst} + (1 - A_{dst}) * C_{src} Cout:Cdst+(1−Adst)∗Csrc | ||
SRC_IN (5) | 保留覆盖目标像素的源像素, 丢弃剩余的源像素和目标像素 |
A
o
u
t
:
A
s
r
c
∗
A
d
s
t
A_{out} : A_{src} * A_{dst}
Aout:Asrc∗Adst C o u t : C s r c ∗ A d s t C_{out} : C_{src} * A_{dst} Cout:Csrc∗Adst | ||
DST_IN (6) | 保留覆盖源像素的目标像素, 丢弃剩余的源像素和目标像素 |
A
o
u
t
:
A
d
s
t
∗
A
s
r
c
A_{out} : A_{dst} * A_{src}
Aout:Adst∗Asrc C o u t : C d s t ∗ A s r c C_{out} : C_{dst} * A_{src} Cout:Cdst∗Asrc | ||
SRC_OUT (7) | 保留不覆盖目标像素的源像素。 丢弃覆盖目标像素的源像素。 丢弃所有目标像素。 |
A
o
u
t
:
(
1
−
A
d
s
t
)
∗
A
s
r
c
A_{out} : (1 - A_{dst}) * A_{src}
Aout:(1−Adst)∗Asrc C o u t : ( 1 − A d s t ) ∗ C s r c C_{out} : (1 - A_{dst}) * C_{src} Cout:(1−Adst)∗Csrc | ||
DST_OUT (8) | 保留源像素未覆盖的目标像素。 丢弃由源像素覆盖的目标像素。 丢弃所有源像素。 |
A
o
u
t
:
(
1
−
A
s
r
c
)
∗
A
d
s
t
A_{out} : (1 - A_{src}) * A_{dst}
Aout:(1−Asrc)∗Adst C o u t : ( 1 − A s r c ) ∗ C d s t C_{out} : (1 - A_{src}) * C_{dst} Cout:(1−Asrc)∗Cdst | ||
SRC_ATOP (9) | 丢弃不覆盖目标像素的源像素。 在目标像素上绘制剩余的源像素。 |
A
o
u
t
:
A
d
s
t
A_{out} : A_{dst}
Aout:Adst C o u t : A d s t ∗ C s r c + ( 1 − A s r c ) ∗ C d s t C_{out} : A_{dst} * C_{src} + (1 - A_{src}) * C_{dst} Cout:Adst∗Csrc+(1−Asrc)∗Cdst | ||
DST_ATOP (10) | 丢弃源像素未覆盖的目标像素。 在源像素上绘制剩余的目标像素。 |
A
o
u
t
:
A
s
r
c
A_{out} : A_{src}
Aout:Asrc C o u t : A s r c ∗ C d s t + ( 1 − A d s t ) ∗ C s r c C_{out} : A_{src} * C_{dst} + (1 - A_{dst}) * C_{src} Cout:Asrc∗Cdst+(1−Adst)∗Csrc | ||
XOR (11) | 丢弃源像素覆盖目标像素的源像素和目标像素。 绘制剩余的源像素。 |
A
o
u
t
:
(
1
−
A
d
s
t
)
∗
A
s
r
c
+
(
1
−
A
s
r
c
)
∗
A
d
s
t
A_{out} : (1 - A_{dst}) * A_{src} + (1 - A_{src}) * A_{dst}
Aout:(1−Adst)∗Asrc+(1−Asrc)∗Adst C o u t : ( 1 − A d s t ) ∗ C s r c + ( 1 − A s r c ) ∗ C d s t C_{out} : (1 - A_{dst}) * C_{src} + (1 - A_{src}) * C_{dst} Cout:(1−Adst)∗Csrc+(1−Asrc)∗Cdst |
混合模式及其合成方程式:
Mode | 图片 | 定义 | 新算法 | 旧算法 |
---|---|---|---|---|
ADD (12) | 将源像素相加到目标像素并使结果饱和。 |
A
o
u
t
:
m
a
x
(
0
,
m
i
n
(
A
s
r
c
+
A
d
s
t
,
1
)
)
A_{out} : max(0, min(A_{src} + A_{dst}, 1))
Aout:max(0,min(Asrc+Adst,1)) C o u t : m a x ( 0 , m i n ( C s r c + C d s t , 1 ) ) C_{out} : max(0, min(C_{src} + C_{dst}, 1)) Cout:max(0,min(Csrc+Cdst,1)) | ||
MULTIPLY (13) | 将源像素和目标像素相乘。 |
A
o
u
t
:
A
s
r
c
∗
A
d
s
t
A_{out} : A_{src} * A_{dst}
Aout:Asrc∗Adst C o u t : C s r c ∗ C d s t C_{out} : C_{src} * C_{dst} Cout:Csrc∗Cdst | ||
SCREEN (14) | 源像素和目标像素相加, 然后减去源像素乘以目标像素。 |
A
o
u
t
:
A
s
r
c
+
A
d
s
t
−
A
s
r
c
∗
A
d
s
t
A_{out} : A_{src} + A_{dst} - A_{src} * A_{dst}
Aout:Asrc+Adst−Asrc∗Adst C o u t : C s r c + C d s t − C s r c ∗ C d s t C_{out} : C_{src} + C_{dst} - C_{src} * C_{dst} Cout:Csrc+Cdst−Csrc∗Cdst | ||
OVERLAY (15) | 根据目标颜色对源和目标 进行乘法或筛选。 |
A
o
u
t
:
A
s
r
c
+
A
d
s
t
−
A
s
r
c
∗
A
d
s
t
A_{out} : A_{src} + A_{dst} - A_{src} * A_{dst}
Aout:Asrc+Adst−Asrc∗Adst C o u t : { 2 ∗ C s r c ∗ C d s t 2 ∗ C d s t < A d s t A s r c ∗ A d s t − 2 ( A d s t − C s r c ) ( A s r c − C d s t ) o t h e r w i s e C_{out} : \begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} \lt A_{dst} \\ A_{src} * A_{dst} - 2(A_{dst} - C_{src})(A_{src} - C_{dst}) & otherwise \end{cases} Cout:{2∗Csrc∗CdstAsrc∗Adst−2(Adst−Csrc)(Asrc−Cdst)2∗Cdst<Adstotherwise | ||
DARKEN (16) | 保留源像素和目标像素的最小分量。 |
A
o
u
t
:
A
s
r
c
+
A
d
s
t
−
A
s
r
c
∗
A
d
s
t
A_{out} : A_{src} + A_{dst} - A_{src} * A_{dst}
Aout:Asrc+Adst−Asrc∗Adst C o u t : ( 1 − A d s t ) ∗ C s r c + ( 1 − A s r c ) ∗ C d s t + m i n ( C s r c , C d s t ) C_{out} : (1 - A_{dst}) * C_{src} + (1 - A_{src}) * C_{dst} + min(C_{src}, C_{dst}) Cout:(1−Adst)∗Csrc+(1−Asrc)∗Cdst+min(Csrc,Cdst) | ||
LIGHTEN (17) | 保留源像素和目标像素的最大分量。 |
A
o
u
t
:
A
s
r
c
+
A
d
s
t
−
A
s
r
c
∗
A
d
s
t
A_{out} : A_{src} + A_{dst} - A_{src} * A_{dst}
Aout:Asrc+Adst−Asrc∗Adst C o u t : ( 1 − A d s t ) ∗ C s r c + ( 1 − A s r c ) ∗ C d s t + m a x ( C s r c , C d s t ) C_{out} : (1 - A_{dst}) * C_{src} + (1 - A_{src}) * C_{dst}+max(C_{src}, C_{dst}) Cout:(1−Adst)∗Csrc+(1−Asrc)∗Cdst+max(Csrc,Cdst) |