Xfermode

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 定义的,而是为了方便起见被包含在这个类中。

合成模式及其合成方程式

下面给出的所有示例图使用相同的源图像和目标图像:

SRCDST

用于生成每个图表的绘图操作的顺序显示在以下代码段中:

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+(1Asrc)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+(1Asrc)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+(1Adst)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+(1Adst)Csrc
SRC_IN
(5)
保留覆盖目标像素的源像素,
丢弃剩余的源像素和目标像素
A o u t : A s r c ∗ A d s t A_{out} : A_{src} * A_{dst} Aout:AsrcAdst

C o u t : C s r c ∗ A d s t C_{out} : C_{src} * A_{dst} Cout:CsrcAdst
DST_IN
(6)
保留覆盖源像素的目标像素,
丢弃剩余的源像素和目标像素
A o u t : A d s t ∗ A s r c A_{out} : A_{dst} * A_{src} Aout:AdstAsrc

C o u t : C d s t ∗ A s r c C_{out} : C_{dst} * A_{src} Cout:CdstAsrc
SRC_OUT
(7)
保留不覆盖目标像素的源像素。
丢弃覆盖目标像素的源像素。
丢弃所有目标像素。
A o u t : ( 1 − A d s t ) ∗ A s r c A_{out} : (1 - A_{dst}) * A_{src} Aout:(1Adst)Asrc

C o u t : ( 1 − A d s t ) ∗ C s r c C_{out} : (1 - A_{dst}) * C_{src} Cout:(1Adst)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:(1Asrc)Adst

C o u t : ( 1 − A s r c ) ∗ C d s t C_{out} : (1 - A_{src}) * C_{dst} Cout:(1Asrc)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:AdstCsrc+(1Asrc)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:AsrcCdst+(1Adst)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:(1Adst)Asrc+(1Asrc)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:(1Adst)Csrc+(1Asrc)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:AsrcAdst

C o u t : C s r c ∗ C d s t C_{out} : C_{src} * C_{dst} Cout:CsrcCdst
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+AdstAsrcAdst

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+CdstCsrcCdst
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+AdstAsrcAdst

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:{2CsrcCdstAsrcAdst2(AdstCsrc)(AsrcCdst)2Cdst<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+AdstAsrcAdst

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:(1Adst)Csrc+(1Asrc)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+AdstAsrcAdst

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:(1Adst)Csrc+(1Asrc)Cdst+max(Csrc,Cdst)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值