我企图用 PorterDuffXfermode 来裁切一个圆,但是失败了,有人帮忙看下问题出在哪里吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
maninfog
V2EX    Android

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

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

    代码如下:

     // 初始一下 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setCoor(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     Solana     5453 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 07:29 PVG 15:29 LAX 00:29 JFK 03:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86