您的位置:首页 > Web前端

PorterDuff及Xfermode详解

2015-09-13 22:18 375 查看

Xfermode有三个子类 :

AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。

PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

要应用转换模式,可以使用setXferMode方法,如下所示:

[java] view
plaincopy

AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. ***OID); borderPen.setXfermode(avoid);


PorterDuff的使用:

参照android apidemo中com.example.android.apis.graphics下的Xfermodes。这里列出已注释的代码:

public class Xfermodes extends GraphicsActivity {

    // create a bitmap with a circle, used for the "dst" image 创建一个圆形的bitmap,用来做dst图像
    static Bitmap makeDst(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        p.setColor(0xFFFFCC44);
        c.drawOval(new RectF(0, 0, w*3/4, h*3/4), p);
        return bm;
    }

    // create a bitmap with a rect, used for the "src" image 创建一个矩形bitmap,用来做src图像
    static Bitmap makeSrc(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        p.setColor(0xFF66AAFF);
        c.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));
    }

    private static class SampleView extends View {
        private static final int W = 64;
        private static final int H = 64;
        private static final int ROW_MAX = 4;   // number of samples per row 每行的数量

        private Bitmap mSrcB;
        private Bitmap mDstB;
        private Shader mBG;     // background checker-board pattern 背景棋盘板模型

        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", "Multiply", "Screen"
        };

        public 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); //整个sampleview为白色

            Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG);
            //Paint.Align.CENTER  文本被画在x,y origin的横向的中心
            //Paint.Align.Left  文本被画在x,y origin的右边
            //Paint.Align.Right  文本被画在x,y origin的左边
            labelP.setTextAlign(Paint.Align.CENTER);

            Paint paint = new Paint();
            paint.setFilterBitmap(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 checker-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.MATRIX_S***E_FLAG |
                                          Canvas.CLIP_S***E_FLAG |
                                          Canvas.HAS_ALPHA_LAYER_S***E_FLAG |
                                          Canvas.FULL_COLOR_LAYER_S***E_FLAG |
                                          Canvas.CLIP_TO_LAYER_S***E_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;
                }
            }
        }
    }
}


效果图:



参考资料/article/1875776.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: