xFermode的原理及使用

xFermode是画笔的一个属性,有点类似于PS中的图层,有一个底层图层,和一个顶层图层,通过两个图层叠放层次的不同,可以做出很多好玩的效果。

谷歌官方的apidemo中生成了两个图层的各种叠放次序效果:

叠放次序效果

是不是有点摸不着头脑,让我们列个表格来解释一下吧:

属性名属性常量属性说明
ClearPorterDuff.Mode.CLEAR所有的图层都不会在画布上展示
SrcPorterDuff.Mode.SRC只显示顶层图层的图像
DSTPorterDuff.Mode.DST只显示底层图层的图像
SrcOverPorterDuff.Mode.SRC_OVER显示所有图层,顶层图层位于底层图层上面(默认效果)
DstOverPorterDuff.Mode.DST_OVER显示所有图层,底层图层位于顶层图层上面
SrcInPorterDuff.Mode.SRC_IN显示两个图层的交集,顶层图层位于底层图层上面
DstInPorterDuff.Mode.DST_IN显示两个图层的交集,底层图层位于顶层图层上面
SrcOutPorterDuff.Mode.SRC_OUT显示两个图层的部分非交集,只显示顶层图层的非交集部分
DstOutPorterDuff.Mode.DST_OUT显示两个图层的部分非交集,只显示底层图层的非交集部分
SrcTopPorterDuff.Mode.SRC_ATOP显示底层图层和两个图层的交集部分,顶层位于底层图层的上面
DstTopPorterDuff.Mode.DST_ATOP显示顶层图层和两个图层的交集部分,底层图层位于顶层图层上面
XorPorterDuff.Mode.XOR显示两个图层的完整非交集
DarkenPorterDuff.Mode.DARKEN显示所有图层,顶层位于底层图层上面,相交部位变暗
LightenPorterDuff.Mode.LIGHTEN显示所有图层,顶层位于底层图层上面,相交部位变暗
MultiplyPorterDuff.Mode.MULTIPLY显示两个图层的交集,颜色变换类似于PS中的“正片叠底”效果
ScreenPorterDuff.Mode.SCREEN显示两个图层的并集,颜色变换类似于PS中的“滤色”效果

Tips:正片叠低效果就是把两个图层中的颜色进行叠加,这样暗的部分会被加强;
滤色效果也是对两个图层中的颜色进行叠加,但亮的部分会被加强。

原理:虽然上面的表格中将XFermode解释成图层的并集交集的叠放,但事实上系统是通过对Sa(Source alpha,Src的透明度)、Da(Destination alpha,Dat的透明度)、Sc(Source Color,Src的颜色)、Dc(Destination Color,Dat的透明度),四个值来进行运算来达到变换的效果。

我们可以在源码中看到相应的运算公式:

    /** [0, 0] */
    CLEAR       (0),
    /** [Sa, Sc] */
    SRC         (1),
    /** [Da, Dc] */
    DST         (2),
    /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
    SRC_OVER    (3),
    /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
    DST_OVER    (4),
    /** [Sa * Da, Sc * Da] */
    SRC_IN      (5),
    /** [Sa * Da, Sa * Dc] */
    DST_IN      (6),
    /** [Sa * (1 - Da), Sc * (1 - Da)] */
    SRC_OUT     (7),
    /** [Da * (1 - Sa), Dc * (1 - Sa)] */
    DST_OUT     (8),
    /** [Da, Sc * Da + (1 - Sa) * Dc] */
    SRC_ATOP    (9),
    /** [Sa, Sa * Dc + Sc * (1 - Da)] */
    DST_ATOP    (10),
    /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
    XOR         (11),
    /** [Sa + Da - Sa*Da,
         Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
    DARKEN      (12),
    /** [Sa + Da - Sa*Da,
         Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
    LIGHTEN     (13),
    /** [Sa * Da, Sc * Dc] */
    MULTIPLY    (14),
    /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
    SCREEN      (15),
    /** Saturate(S + D) */
    ADD         (16),
    OVERLAY     (17);

使用的时候我们需要设置两个图来进行叠加:

    setLayerType(LAYER_TYPE_SOFTWARE, null); //关闭硬件加速
    mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ms);
    mOut = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(mOut);
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    RectF rt = new RectF();
    rt.left = 0; //矩形的左起点
    rt.top = 0; //矩形的顶部起点
    rt.right = mBitmap.getWidth(); //矩形的右终点
    rt.bottom = mBitmap.getHeight(); //矩形的底部终点

    //Dat
    canvas.drawRoundRect(rt, 50, 50, mPaint);

    //设置Xfermode
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    //Src
    canvas.drawBitmap(mBitmap, 0, 0, mPaint);

    //还原Xfermode
    mPaint.setXfermode(null);

圆角矩形效果

通过上面的代码我们就将本来是直角的照片,变成了圆角矩形。

引用声明:慕课网《Android图像处理-变”换”莫测的图像》————eclipse_xu

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值