当前位置:   article > 正文

Android setXfermode之ProterXfermode

android setxfermode

ProterDuffXfermode

图片混合模式(18种)
先画的为目标图(DST)
后画的为源图(SRC)

画图与Bitmap的区别

官方示例采用的drawBitmap,是两个大小相同且绘制区域并不会充满整个bitmap
画图例如drawCircle等,使用setXfermode其作用域是第二次绘制的图案的部分,所以部分的DST(目标图)本应该改变但没有

官方API示例源码

MainActivity.java

public class MainActivity extends AppCompatActivity{
    
    static Bitmap makeDst(int w,int h){
        Bitmap bm = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFFFCC44);
        canvas.drawOval(new RecF(0,0,w*3/4,h*3/4),p);
        return bm;
    }
    
    static Bitmap makeSrc(int w,int h){
        Bitmap bm = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFF66AAFF);
        canvas.drawRect(w/3,h/3,w*19/20,h*19/20,p);
        return bm;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));    
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

SampleView.java

private static class SampleView extends View{
    private static final int W = 200;
    private static final int H = 200;
    private static final int ROW_MAX = 4;
    private Bitmap mSrcB;
    private Bitmap mDstB;
    private Shader mBG;
    private static final Xfermode[] sModes = {
        new PorterDuffXfermode(PorterDuff.Mode.CLEAR),
        new PorterDuffXfermode(PorterDuff.Mode.SRC),
        new PorterDuffXfermode(PorterDuff.Mode.DST),
        new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),
        new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),
        new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),
        new PorterDuffXfermode(PorterDuff.Mode.DST_IN),
        new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),
        new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),
        new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),
        new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),
        new PorterDuffXfermode(PorterDuff.Mode.XOR),
        new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
        new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
        new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
        new PorterDuffXfermode(PorterDuff.Mode.SCREEN)
    };
    private static final String[] sLabels = {
        "Clear","Src","Dst","SrcOver",
        "DstOver","SrcIn","DstIn","SrcOut",
        "DstOut","SrcATop","DstATop","Xor",
        "Darken","Lighten","Mutiply","Screen"    
    };
    private SampleView(Context context){
        super(context);
        mSrcB = makeSrc(W,H);
        mDstB = makeDst(W,H);
        // make a ckeckerboard pattern(棋盘图案)
        Bitmap bm = Bitmap.createBitmap(new int[]{0xFFFFFFFF,0xFFCCCCCC,0xFFCCCCCC,0xFFFFFFFF},2,2,Bitmap.Config.RGB_565);
        mBG = new BitmapShader(bm,Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
        Matrix m = new Matrix();
        m.setScale(6,6);
        mBG.setLocalMatrix(m);
    }
    @Override
    protected void onDraw(Canvas canvas){
        canvas.drawColor(Color.WHITE);
        Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG);
        labelP.setTextAlign(Paint.Align.CENTER);
        Paint paint = new Paint();
        paint.setFilterBitmao(false);
        canvas.translate(15,35);
        int x = 0;
        int y = 0;
        for(int i=0;i<sModes.length;i++){
            //draw the border
            paint.setStyle(Paint.Style.STROKE);
            paint.setShader(null);
            canvas.drawRect(x-0.5f,y-0.5f,x+W+0.5f,y+H+0.5f,paint);
            //draw the cheker-board pattern
            paint.setStyle(Paint.Style.FILL);
            paint.setShader(mBG);
            canvas.drawRect(x,y,x+W,y+H,paint);
            //draw the src/dst example into our offscreen bitmap
            int sc = canvas.saveLayer(x,y,x+W,y+H,null,Canvas.ALL_SAVE_FLAG);
            canvas.translate(x,y);
            canvas.drawBitmap(mDstB,0,0,paint);
            paint.setXfermode(sModes[i]);
            canvas.drawBitmap(mSrcB,0,0,paint);
            paint.setXfermode(null);
            canvas.restoreToCount(sc);
            //draw the label
            canvas.drawText(sLabels[i],x+W/2,y-labelP.getTextSize()/2,labelP);
            x+=W+10;
            //wrap around when we've drawn enough for one row
            if((i%ROW_MAX)==ROW_MAX-1){
                x=0;
                y+=H+30;
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

效果图

在这里插入图片描述

原始的画图模式

protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    canvas.drawARGB(255,255,156,161);//设置背景色
    drawDst(canvas,mPaint);
    drawSrc(canvas,mPaint);
}
private void drawDst(Canvas canvas,Paint p){
    p.setColor(0xFFFFCC44);
    int w = canvas.getWidth()/3;
    canvas.drawCircle(w,w,w,p);
}
private void drawSrc(Canvas canvas,Paint paint){
    paint.setColor(0xFF66AAFF);
    int r = canvas.getWidth()/3;
    canvas.drawRect(r,r,r*2.7f,r*2.7f,paint);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

CLEAR

源覆盖的目标图清零

画图

protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    canvas.drawARGB(255,255,156,161);
    drawDst(canvas,mPaint);
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    drawSrc(canvas,mPaint);
    mPaint.setXfermode(null);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述
实现了效果,但是是黑色一块

根据源码实现不加图层渲染的CLEAR模式

使用两个Bitmap进行操作,但是不加canvas.saveLayer()

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(mDstBitmap,0,0,mPaint);
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    canvas.drawBitmap(mSrcBitmap,0,0,mPaint);
    mPaint.setXfermode(null);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

原因:

Activity本身的颜色是黑色,所以CLEAR模式下,两个Bitmap实现了CLEAR效果,所以展示的是Activity的颜色(貌似其余人的都是白色的?

加了图层渲染后

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
    canvas.drawBitmap(mDstBitmap,0,0,mPaint);
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    canvas.drawBitmap(mSrcBitmap,0,0,mPaint);
    mPaint.setXfermode(null);
    canvas.restoreToCount(sc);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现了效果
在这里插入图片描述

按照传统的画图形式呈现CLEAR

先画圆(Dst),画笔设置PorterDuff.Mode.CLEAR后,再绘制矩形(此处加了canvas.saveLayer())
实际上作用域为第二次绘画的大小
在这里插入图片描述

SRC

定义/概念

源像素(SRC)替换目标像素(DST)

传统的画图形式
不加图层渲染
int w = 200;
int h = 200;
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

加图层渲染
int w = 200;
int h = 200;
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里插入图片描述

使用drawBitmap形式

实现官方效果

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

DST

概念

源像素被丢弃,目标像素保留
这种情况下,不论是传统形式还是官方示例操作,或者是加不加图层渲染,呈现的结果都一样

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
//canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST));
mPaint.setColor(Color.GREEN);
//canvas.drawBitmap(mSrcB,0,0,mPaint);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里插入图片描述

SRC_OVER

概念

源像素绘制在目标像素之上
结论同上

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
//canvas.drawCircle(w/3,h/3,h/3,mPaint);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
//canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里插入图片描述

DST_OVER

概念

源像素绘制在目标像素后面

画图形式

不加图层渲染
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

图层渲染
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

drawBitmap

效果对应同上

SRC_IN

概念

保留覆盖目标像素的源像素,丢弃剩余的源像素和目标像素

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

画图形式

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

DST_IN

概念

保留覆盖源像素的目标像素,丢弃剩余的源像素和目标像素

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

画图形式

作用域是第二次绘制的,第二次绘制的是源像素,所以会显示不见,只有目标像素

mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

SRC_OUT

概念

保留不覆盖目标像素的源像素,丢弃覆盖目标像素的源像素,丢弃所有目标像素

画图

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

DST_OUT

概念

保留未被源像素覆盖的目标像素,丢弃被源像素覆盖的目标像素,丢弃所有的源像素

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

画图

同上

SRC_ATOP

概念

丢弃不覆盖目标像素的源像素,在目标像素上绘制剩余的源像素

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

画图

结果同上

DST_ATOP

概念

丢弃未被源像素覆盖的目标像素,在源像素上绘制剩余的目标像素

画图

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

XOR

概念

丢弃源像素覆盖目标像素的源像素和目标像素,,绘制剩余的源像素

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

画图

同上

DARKEN

概念

保留源像素和目标像素的最小分量

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

画图

同上

LIGHTEN

概念

保留源像素和目标像素最大的分量

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

画图

同上

MULTIPLY

概念

源像素和目标像素相乘

画图

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(0xFFFFCC44);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
mPaint.setColor(0xFF66AAFF);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

drawBitmap

int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

SCREEN

概念

先绘制源像素和目标像素,再减去源像素乘以目标

drawBitmap

canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
canvas.drawBitmap(mSrcB,0,0,mPaint);
  • 1
  • 2
  • 3

在这里插入图片描述

画图

同上

ADD

概念

将源像素添加到目标像素并使结果饱和

drawBitmap

canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
canvas.drawBitmap(mSrcB,0,0,mPaint);
  • 1
  • 2
  • 3

在这里插入图片描述

画图

同上

OVERLAY

概念

Multiplies or screens the source and destination depending on the destination color.

画图

mPaint.setColor(0xFFFFCC44);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.OVERLAY));
mPaint.setColor(0xFF66AAFF);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

drawBitmap

同上

整体

MyView.java

private void init(){
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
    }
    
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int sc = canvas.saveLayer(0,0,getWidth(),getHeight(),mPaint);
        XfermodeUtil.drawPattern(canvas,mPaint);
        canvas.restoreToCount(sc);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

XfermodeUtil.java

public static final Xfermode[] sModes = {
            new PorterDuffXfermode(PorterDuff.Mode.ADD),
            new PorterDuffXfermode(PorterDuff.Mode.CLEAR),
            new PorterDuffXfermode(PorterDuff.Mode.DST),
            new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),
            new PorterDuffXfermode(PorterDuff.Mode.DST_IN),
            new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),
            new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
            new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),
            new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
            new PorterDuffXfermode(PorterDuff.Mode.OVERLAY),
            new PorterDuffXfermode(PorterDuff.Mode.SCREEN),
            new PorterDuffXfermode(PorterDuff.Mode.SRC),
            new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),
            new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),
            new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
            new PorterDuffXfermode(PorterDuff.Mode.XOR)
    };

    public static void drawPattern(Canvas canvas, Paint mPaint){
        canvas.drawCircle(100,100,100,mPaint);
        canvas.drawCircle(400,100,100,mPaint);
        canvas.drawCircle(800,100,100,mPaint);

        canvas.drawCircle(100,400,100,mPaint);
        canvas.drawCircle(400,400,100,mPaint);
        canvas.drawCircle(800,400,100,mPaint);

        canvas.drawCircle(100,700,100,mPaint);
        canvas.drawCircle(400,700,100,mPaint);
        canvas.drawCircle(800,700,100,mPaint);

        canvas.drawCircle(100,1000,100,mPaint);
        canvas.drawCircle(400,1000,100,mPaint);
        canvas.drawCircle(800,1000,100,mPaint);

        canvas.drawCircle(100,1300,100,mPaint);
        canvas.drawCircle(400,1300,100,mPaint);
        canvas.drawCircle(800,1300,100,mPaint);

        canvas.drawCircle(100,1600,100,mPaint);
        canvas.drawCircle(400, 1600,100,mPaint);
        canvas.drawCircle(800,1600,100,mPaint);

        mPaint.setColor(Color.GREEN);
        mPaint.setXfermode(sModes[0]);
        canvas.drawRect(100,100,300,300,mPaint);
        mPaint.setXfermode(sModes[1]);
        canvas.drawRect(400,100,600,300,mPaint);
        mPaint.setXfermode(sModes[2]);
        canvas.drawRect(800,100,900,300,mPaint);

        mPaint.setXfermode(sModes[3]);
        canvas.drawRect(100,400,300,600,mPaint);
        mPaint.setXfermode(sModes[4]);
        canvas.drawRect(400,400,600,600,mPaint);
        mPaint.setXfermode(sModes[5]);
        canvas.drawRect(800,400,1000,600,mPaint);

        mPaint.setXfermode(sModes[6]);
        canvas.drawRect(100,700,300,900,mPaint);
        mPaint.setXfermode(sModes[7]);
        canvas.drawRect(400,700,600,900,mPaint);
        mPaint.setXfermode(sModes[8]);
        canvas.drawRect(800,700,1000,900,mPaint);

        mPaint.setXfermode(sModes[9]);
        canvas.drawRect(100,1000,300,1200,mPaint);
        mPaint.setXfermode(sModes[10]);
        canvas.drawRect(400,1000,600,1200,mPaint);
        mPaint.setXfermode(sModes[11]);
        canvas.drawRect(800,1000,1000,1200,mPaint);

        mPaint.setXfermode(sModes[12]);
        canvas.drawRect(100,1300,300,1500,mPaint);
        mPaint.setXfermode(sModes[13]);
        canvas.drawRect(400,1300,600,1500,mPaint);
        mPaint.setXfermode(sModes[14]);
        canvas.drawRect(800,1300,1000,1500,mPaint);

        mPaint.setXfermode(sModes[15]);
        canvas.drawRect(100,1600,300,1800,mPaint);
        mPaint.setXfermode(sModes[16]);
        canvas.drawRect(400,1600,600,1800,mPaint);
        mPaint.setXfermode(sModes[17]);
        canvas.drawRect(800,1600,1000,1800,mPaint);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

输出

在这里插入图片描述

BitmapShader

使用特定的图片来作为纹理来使用

构造函数

//bitmap:作为纹理的图片
//tileX/Y:在X/Y方向纹理的绘制模式
public BitmapShader(@NonNull Bitmap bitmap,TileMode tileX,TileMode tileY)
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/332717
推荐阅读
相关标签
  

闽ICP备14008679号