V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
maninfog
V2EX  ›  Android

我企图用 PorterDuffXfermode 来裁切一个圆,但是失败了,有人帮忙看下问题出在哪里吗?

  •  1
     
  •   maninfog · 2019-02-27 22:48:39 +08:00 · 10023 次点击
    这是一个创建于 2125 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下:

       
       // 初始一下
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
        mRectF.left = 0;
        mRectF.top = 0;
        mRectF.right = getWidth();
        mRectF.bottom = getHeight();
        
        // 先做了离屏缓存
        int count = canvas.saveLayer(mRectF,null,Canvas.ALL_SAVE_FLAG);
        
        canvas.drawRect(mRectF,mPaint); // 画了红色一个正方形
        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        mPaint.setXfermode(mXfermode); // 设置 xfermode 为 DST_IN
        canvas.drawCircle(dp2Px(100),dp2Px(100),dp2Px(100),mPaint);//画了一个圆形与正方形相切
        
        canvas.restoreToCount(count); // 恢复画布的状态
    

    预想的结果: 因为使用了 DST_IN 的模式进行裁切,所以应该显示下层交集,于是应该显示一个红色的圆。 实际显示:红色正方形。

    尝试将 MODE 改为:PorterDuff.Mode.DST_OUT,显示效果与预期是一致的,显示的是去除了中心圆的正方形。

    我去 github 看了很多前辈的实现思路,发现也是类似的代码,但是我写出来却不能达到预期的效果,很是苦恼,烦请各位大佬帮我看一下。

    同时:对于这种实现方式,我还有一个疑问,PorterDuffXfermode 原理是将颜色混合,那么如果我们画了一个圆,paint 应该只能对这个圆范围内的颜色进行处理?为什么还能处理圆以外的像素呢?

    第 1 条附言  ·  2019-02-28 16:21:32 +08:00
    我已经出离的懵逼了:
    当我把 drawCircle 的代码改成这样时:

    ```
    mPath.reset();
    mPath.addCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, Path.Direction.CW);
    canvas.drawPath(mPath, mPaint);
    ```
    也就是通过 path 来添加时,效果符合预期,但是,使用 path 添加其他图形确还是不符合预期,比如圆角矩形。
    第 2 条附言  ·  2019-03-04 03:48:07 +08:00

    今天无意中发现是关闭了硬件加速导致的,也就是调用了:

    setLayerType(LAYER_TYPE_SOFTWARE,null);
    

    这句代码导致的效果不如意,去除之后,能正常达到预期效果了。至于原因,目前还不清楚。

    20 条回复    2019-03-04 03:50:07 +08:00
    Cabana
        1
    Cabana  
       2019-02-28 11:12:05 +08:00
    mPaint 在每次用完后有 把 Xfermode 置 null 吗?
    maninfog
        2
    maninfog  
    OP
       2019-02-28 11:20:07 +08:00
    @Cabana #1 这里 onDraw 只执行了一次,没有重绘,所以应该不是 paint 的问题,并且试了一下置空,还是异常
    enkechan
        3
    enkechan  
       2019-02-28 12:50:38 +08:00
    哪有人说自己“企图”做某件事的,听起来像要干坏事哈哈
    maninfog
        4
    maninfog  
    OP
       2019-02-28 13:04:45 +08:00 via iPhone
    @enkechan 主要是想将自己的意图明显表达出来,这里用这个词的确不太合适,应该用意图
    Cabana
        5
    Cabana  
       2019-02-28 14:25:51 +08:00 via Android
    @maninfog
    mRectF 大小对吗?
    Cabana
        6
    Cabana  
       2019-02-28 14:27:26 +08:00 via Android
    是不是 dp2px 最后的值已经大于 mRectF 的范围了?
    jamessky
        7
    jamessky  
       2019-02-28 15:22:32 +08:00 via iPhone
    问问
    maninfog
        8
    maninfog  
    OP
       2019-02-28 15:37:56 +08:00
    @Cabana #5 mRect 的大小是对的,就是取的宽高;然后 dp2px 这个值也是对的,不然 DST_OUT 的效果也会是错的。硬件加速也关闭了。
    NaiveSimpleYoung
        9
    NaiveSimpleYoung  
       2019-02-28 17:07:24 +08:00
    “试图”比较合适
    Cabana
        10
    Cabana  
       2019-02-28 18:31:43 +08:00
    @maninfog 貌似,最后被 Draw 下来的那一方,不管是 SRC 还是 DST 必须是 Bitmap 才可以。
    SRC_开头的 需要 SRC 是 Bitmap,DST 开头的需要 DST 是 Bitmap
    Cabana
        11
    Cabana  
       2019-02-28 18:34:31 +08:00
    @Cabana 直接在 canvas 上 draw SRC_的一系列 Xfermode,会生效是应为 canvas 本身自带一个 Bitmap
    Cabana
        12
    Cabana  
       2019-02-28 18:40:55 +08:00
    另外,裁剪难道不应该用 SRC_IN 吗?为啥会用 DST_IN ? SRC_才是保留原图,DST_是保留后贴上去的图形呀
    maninfog
        13
    maninfog  
    OP
       2019-02-28 18:43:52 +08:00
    @Cabana #12 1.应该用 DST_IN , 你应该是理解反了。因为 dst 才是先放上去的。2.你看我 append 的代码,使用 drawPath 就能行。
    Cabana
        14
    Cabana  
       2019-02-28 18:45:49 +08:00
    pps:PorterDuffXfermode 并不是简单的将颜色混合而已,如果将 SRC 和 DST 看做集合的话,在合成模式下它能够做交集,并集,差集;在混合模式下,才是你说的颜色混合

    https://developer.android.com/reference/android/graphics/PorterDuff.Mode
    Cabana
        15
    Cabana  
       2019-02-28 18:47:54 +08:00
    @maninfog
    SRC--->Source
    DST--->Destination
    Cabana
        16
    Cabana  
       2019-02-28 19:12:09 +08:00
    傻逼了,再去看了下 google 的文档,是又记反了🥶
    maninfog
        17
    maninfog  
    OP
       2019-02-28 20:32:55 +08:00
    @Cabana #14 也没有设置模式的 API 啊
    fyyz
        18
    fyyz  
       2019-02-28 21:28:14 +08:00 via Android
    还好没有用“妄图”
    wsxyeah
        19
    wsxyeah  
       2019-03-02 18:20:54 +08:00 via iPhone
    至少贴下对应的实际效果截图吧
    maninfog
        20
    maninfog  
    OP
       2019-03-04 03:50:07 +08:00
    @Cabana #15 感谢帮忙分析,目前已经能达到预期效果了,具体请看我最新的 append。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   955 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 19:16 · PVG 03:16 · LAX 11:16 · JFK 14:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.