1. 程式人生 > >關於Xfermode的介紹和用處(遮罩圖層,圓形圖片)

關於Xfermode的介紹和用處(遮罩圖層,圓形圖片)

1.關於Xfermode類


從上面看出Xfermode有三個子類:AvoidXfermode,PixelXorXfermode,PoterDuffXfermode。它們分別表示:

AvoidXfermode:在繪圖時,要麼繪製在最頂層,要麼繪製在除最頂層以外的地方。

PixelXorXfermode:這種轉換不遵循自左乘的約定,因此這種模式總返回不透明的顏色(alpha=255),由此,對於混合顏色操作是沒有用的。

PoterDuffXfermode:可以使用影象合成的任何一條PoterDuff模式。

注意:只有當一個Xfermode被分配給一個Paint時,使用Paint繪製Xfermode才有效。

2.PoterDuffXfemode

關於PoterDuff的所有Mode的效果圖如下:


16種模式表示的意思分別是:

PoterDuff.Mode.CLEAR:繪製的圖不會提交到畫布上

PoterDuff.Mode.SRC:只顯示繪製的上層圖

PoterDuff.Mode.DST:只顯示繪製的下層圖

PoterDuff.Mode.SRC_OVER:繪製的上層圖和下層圖都顯示,但上層圖會覆蓋下層圖

PoterDuff.Mode.DST_OVER:繪製的上層圖和下層圖都顯示,但下層圖會覆蓋上層圖

PoterDuff.Mode.SRC_IN:取繪製的圖的交集部分,顯示上層

PoterDuff.Mode.DST_IN:取繪製的圖的交集部分,顯示下層

PoterDuff.Mode.SRC_OUT:取繪製的圖的非交集部分,顯示上層

PoterDuff.Mode.DST_OUT:取繪製的圖的非交集部分,顯示下層

PoterDuff.Mode.SRC_ATOP:取繪製的圖的下層部分,和上層與下層的交集部分

PoterDuff.Mode.DST_ATOP:取繪製的圖的上層部分,和下層與上層的交集部分

PoterDuff.Mode.XOR:取繪製的圖的上層和下層的非交集部分

PoterDuff.Mode.DARKEN:取繪製的圖的全集,上層和下層交集部分加深

PoterDuff.Mode.LIGHTEN:取繪製的圖的全集,上層和下層交集部分點亮

PoterDuff.Mode.MULTIPLY:取繪製的圖的交集部分並且交集部分顏色加深

PoterDuff.Mode.SCREEN:取繪製的圖的全集,上層和下層的交集部分透明

附加:關於圖的示例來自於SDK中的Sample,在我電腦上的路勁為:\sdk\samples\android-16\ApiDemos\src\com\example\android\apis\graphics\Xfermode.java

3.運用示例:

 3.1 拍照遮罩  

         先看效果圖:


總體為一個FramLayout,遮罩層在相機預覽的上面,為了實現這個效果,最核心的就是在畫遮罩層的時候,讓中間矩形這塊區域不可見。那麼從上面分析的PoterDuff.Mode中,很明顯CLEAR模式下,可以實現上面的效果。

因此,只需要兩步,第一步畫一個整體的遮罩圖(下層圖),第二步畫一個不顯示的矩形圖(上層圖):

設定畫矩形區域的畫筆: mRectPaint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));

在onDraw()方法中,先畫下層圖: canvas.drawRect(0, 0, mScreenWidth, mScreenHeight, mAreaPaint);,再畫上層圖:canvas.drawRect(mVisibleRect, mRectPaint);

因此,這樣就可以實現上面的顯示效果。

   3.2 圓形圖片

         先看效果圖:

         思路:在PoterDuff.Mode的SRC_IN下,畫一個圓形的下層圖,再把目標圖片畫在上面,那麼這樣最後的結果就是圓形圖片(取繪製的圖的交集部分,顯示上層)。

程式碼示例:

 public static Bitmap getRoundedCornerBitmap(Bitmap srcBitmap) {

        int width = srcBitmap.getWidth();
        int height = srcBitmap.getHeight();

        int radius = 0;
        if (width <= height) {
            radius = width / 2;
        } else {
            radius = height / 2;
        }

        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setColor(Color.WHITE);

        Rect rect = new Rect(0, 0, 2 * radius, 2 * radius);
        RectF rectF = new RectF(rect);
        Bitmap desBitmap = Bitmap.createBitmap(2 * radius, 2 * radius, Bitmap.Config.ARGB_4444);
        Canvas canvas = new Canvas(desBitmap);
        //除去抗鋸齒
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
        canvas.drawARGB(0, 0, 0, 0);
        //繪製下層圖
        canvas.drawRoundRect(rectF, radius, radius, paint);
        // 設定PorterDuffXfermode模式,取繪製的圖的交集部分,顯示上層
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        //繪製上層圖
        canvas.drawBitmap(srcBitmap, rect, rect, paint);

        return desBitmap;
    }

總結:關於Xfermode的運用還很多,上面遮罩圖層和圓形圖片只是兩種比較常見的運用,從中也可以看出其影象合成的強大所在。另外關於PorterDuff的由來是有兩個人名的組合:Thomas Porter 和 Tom Duff。