Android PorterDuff.Mode圖形混合處理

  PorterDuff.Mode,剛接觸到這個名字的時候,看不懂什麼意思。通過翻譯也沒有查出結果,後來通過一篇博客瞭解到原來PorterDuff是兩個人的名字的組合:Tomas Proter和 Tom Duff.,他們是最早在SIGGRAPH上提出圖形混合概念的大神級人物。通過這一點,其實我們就可以瞭解到,原來PorterDuff原來是處理圖形的混合的,是一種渲染效果。

  在看PorterDuff如何添加效果之前我們首先要先看, Xfermode的概念。

Xfermode

  Xfermode也是凸顯絢爛的方式,可以通過修改Paint的Xfermode來影響在Canvas已有的圖像上面繪製新的顏色的方式 。
  
通過API我們可以查詢到Xfermode包含三個子類:

AvoidXfermode:指定了一個顏色和容差,強制Paint避免在它上面繪圖(或者只在它上面繪圖)。
PixelXorXfermode: 當覆蓋已有的顏色時,應用一個簡單的像素異或操作。
PorterDuffXfermode: 這是一個非常強大的轉換模式,使用它,可以使用圖像合成的16條Porter-Duff規則的任意一條來控制Paint如何與已有的Canvas圖像進行交互。到這我們終於知道爲什麼要介紹Xfermode的了。

PorterDuff.Mode

不免俗套,先貼出16種模式的效果圖:

這裏寫圖片描述

現在再來介紹下16種模式:

1.PorterDuff.Mode.CLEAR
所繪製不會提交到畫布上,也就是不顯示內容。

2.PorterDuff.Mode.SRC
顯示繪製圖片的上層圖片。

3.PorterDuff.Mode.DST
顯示繪製圖片下層圖片。

4.PorterDuff.Mode.SRC_OVER
正常繪製顯示,上下層繪製疊蓋。

5.PorterDuff.Mode.DST_OVER
上下層都顯示,下層居上顯示。

6.PorterDuff.Mode.SRC_IN
取兩層繪製交集。顯示上層。

7.PorterDuff.Mode.DST_IN
取兩層繪製交集。顯示下層。

8.PorterDuff.Mode.SRC_OUT
取上層繪製非交集部分。

9.PorterDuff.Mode.DST_OUT
取下層繪製非交集部分。

10.PorterDuff.Mode.SRC_ATOP
取下層非交集部分與上層交集部分。

11.PorterDuff.Mode.DST_ATOP

取上層非交集部分與下層交集部分。
12.PorterDuff.Mode.XOR
異或:去除兩圖層交集部分。

13.PorterDuff.Mode.DARKEN
取兩圖層全部區域,交集部分顏色加深。

14.PorterDuff.Mode.LIGHTEN
取兩圖層全部,點亮交集部分顏色。

15.PorterDuff.Mode.MULTIPLY
取兩圖層交集部分疊加後顏色。

16.PorterDuff.Mode.SCREEN
取兩圖層全部區域,交集部分變爲透明色。

PorterDuff.Mode的使用 ##

  使用PorterDuff.Mode不能直接在View的畫布上使用,也就是不能在自定義View的onDraw()方法中使用。必須在Bitmap的Canvas上使用,PorterDuff.Mode效果是應用在Paint上的,通過Paint來設置效果。我們來看具體的步驟和代碼。
  
1. 創建一個Bitmap對象。
2. 創建一個Bitmap對象的Canvas畫布。
3. 在Bitmap的Canvas上繪製圖形,在繪製的圖形的Paint上通過setXfermode(Xfermode xfermode)添加圖形混合效果,該方法傳入的是一個Xfermode對象,所以使我們要先創建一個Xfermode 的對象:

PorterDuffXfermode mode  = new PorterDuffXfermode(PorterDuff.Mode.XOR);
  1. 這樣效果就添加成功了。
public class MyBitmapViewAnother extends View {
    private int width;//設置高
    private int height;//設置高
    private Paint mPaint;
    //設置一個Bitmap
    private Bitmap bitmap;
    //創建該Bitmap的畫布
    private Canvas bitmapCanvas;
    private Paint mPaintCirlcle;
    private Paint mPaintRect;

    public MyBitmapViewAnother(Context context) {
        super(context);
    }

    public MyBitmapViewAnother(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();//Bitmap的畫筆

        mPaintCirlcle = new Paint();
        mPaintCirlcle.setAntiAlias(true);
        mPaintCirlcle.setColor(Color.YELLOW);
//        PorterDuffXfermode mode  = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
//        mPaintCirlcle.setXfermode(mode);

        mPaintRect = new Paint();
        mPaintRect.setAntiAlias(true);
        mPaintRect.setColor(Color.GRAY);
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
        mPaintRect.setXfermode(mode);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);//設置寬和高
        //自己創建一個Bitmap
        bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmapCanvas = new Canvas(bitmap);//該畫布爲bitmap的
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //設置該View畫布的背景
        canvas.drawColor(Color.LTGRAY);
        canvas.drawBitmap(bitmap, 0, 0, mPaint);

        bitmapCanvas.drawCircle(width / 2, height / 2, width / 2, mPaintCirlcle);
        bitmapCanvas.drawRect(0, 0, width / 2, height / 2, mPaintRect);
    }
}

  代碼中使用的是PorterDuff.Mode.XOR交集部分不顯示的效果。
  
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章