Canvas&Paint 知識梳理(4) 圖像合成 Paint#setXfermode

1、概述

顏色合成文章中的最後一個小結當中,咱們已經見到了PorterDuff.Mode這個枚舉類,在本次的圖像合成中,咱們也須要用到這個類,咱們先看一下最終調用的方法爲:canvas

/**
     * Set or clear the xfermode object.
     * <p />
     * Pass null to clear any previous xfermode.
     * As a convenience, the parameter passed is also returned.
     *
     * @param xfermode May be null. The xfermode to be installed in the paint
     * @return         xfermode
     */
    public Xfermode setXfermode(Xfermode xfermode) {
        long xfermodeNative = 0;
        if (xfermode != null)
            xfermodeNative = xfermode.native_instance;
        native_setXfermode(mNativePaint, xfermodeNative);
        mXfermode = xfermode;
        return xfermode;
    }
複製代碼

當一個Paint被設置了某個Xfermode時,那麼會根據源圖層、畫筆和Mode,來決定畫完以後的圖像究竟是什麼,在使用的時候,咱們通常採用PorterDuffXfermode做爲Xfermode的實現類,它的構造函數的參數就是咱們以前說到的PoterDuff.Mode中的某個類型。bash

2、混合方式

關於混合的方式,網上有張圖是這麼總結的,其中DST表示本來有的圖像,而SRC表示即將繪製上去的圖像: 函數

在某些咱們覺得的狀況下,並不能獲得對應的結果,感謝下面這篇博客的做者: http://blog.csdn.net/u010335298/article/details/51983420 他總結了得到圖中的結果,上面的圖中還有幾個隱含的條件:

  • 關閉硬件加速。
  • 兩個進行疊加的圖層的大小是相同的。
  • 除了有顏色的部分,其它部分都是透明的。

3、示例

下面咱們來看一下,DST_ATOP這種方式ui

3.1 開啓硬件加速

private void drawPorterDuffXferMode(Canvas canvas) {
        Paint paint = new Paint();
        //繪製DST圖像.
        paint.setColor(Color.YELLOW);
        canvas.drawCircle(100, 100, 100, paint);
        //繪製SRC圖像.
        paint.setColor(Color.BLUE);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
        canvas.drawRect(100, 100, 300, 300, paint);
    }
複製代碼

對應的結果爲:spa

和效果圖徹底不符,下面,咱們試一下關閉硬件加速:

3.2 關閉硬件加速

private void init() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }

    private void drawPorterDuffXferMode(Canvas canvas) {
        Paint paint = new Paint();
        //繪製DST圖像.
        paint.setColor(Color.YELLOW);
        canvas.drawCircle(100, 100, 100, paint);
        //繪製SRC圖像.
        paint.setColor(Color.BLUE);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
        canvas.drawRect(100, 100, 300, 300, paint);
    }
複製代碼

結果爲: .net

仍是和理論結果不符合。

3.3 使用兩個大小同樣的Bitmap

private Paint mDstPaint;
    private Paint mSrcPaint;
    private Canvas mDstCanvas;
    private Canvas mSrcCanvas;
    private Bitmap mSrcBitmap;
    private Bitmap mDstBitmap;
    
    private void init() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        mDstPaint = new Paint();
        mSrcPaint = new Paint();
        mDstPaint.setColor(Color.YELLOW);
        mSrcPaint.setColor(Color.BLUE);
        mDstBitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
        mSrcBitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
        mDstCanvas = new Canvas(mDstBitmap);
        mSrcCanvas = new Canvas(mSrcBitmap);
    }

    private void drawPorterDuffXferMode(Canvas canvas) {
        //繪製DST圖像.
        mDstCanvas.drawCircle(100, 100, 100, mDstPaint);
        canvas.drawBitmap(mDstBitmap, 0, 0, mDstPaint);
        //繪製SRC圖像
        mSrcCanvas.drawRect(100, 100, 300, 300, mSrcPaint);
        mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
        canvas.drawBitmap(mSrcBitmap, 0, 0, mSrcPaint);
    }
複製代碼

來看看這個的結果: 3d

爲了獲得這個結果,實例化了一堆的對象,而且須要在 Bitmap的大小同樣的時候才能夠生效,其實這也不能說是坑,由於根據源碼來看,計算的計算原本就是取各像素點的 ARGB進行計算,若是圖層的大小不同,那麼計算的結果天然就和上面不一樣,從圖中來看,它也代表了 DSTSRC的大小是相同的,而且在除了有顏色以外的部分都是透明的。

4、參考文獻

1.http://blog.csdn.net/u010335298/article/details/51983420code

相關文章
相關標籤/搜索