美文网首页
android paint画笔图层混合模式

android paint画笔图层混合模式

作者: GoodWen | 来源:发表于2019-10-08 09:00 被阅读0次

官方Xfermode的实例 里面18中模式详解

public class XfermodesActivity extends AppCompatActivity {

    // create a bitmap with a circle, used for the "dst" image
    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
    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       = 320;
        private static final int H       = W;
        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 Paint mPaint;

        //效果作用于src源图像区域
        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),

                //取两图层全部区域,交集部分饱和度相加
                new PorterDuffXfermode(PorterDuff.Mode.ADD),
                //取两图层全部区域,交集部分叠加
                new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)
        };

        private static final String[] sLabels = {
                "Clear", "Src", "Dst", "SrcOver",
                "DstOver", "SrcIn", "DstIn", "SrcOut",
                "DstOut", "SrcATop", "DstATop", "Xor",
                "Darken", "Lighten", "Multiply", "Screen", "Add","Overlay"
        };

        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);

            mPaint = new Paint();
            mPaint.setStrokeWidth(2);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.GRAY);
        }

        @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.setFilterBitmap(false);

            canvas.translate(15, 15);

            canvas.drawBitmap(mDstB, 0, 0, paint);
            canvas.drawRect(0,0, mDstB.getWidth(), mDstB.getHeight(), mPaint);

            canvas.drawBitmap(mSrcB, mDstB.getWidth() + 15, 0, paint);
            canvas.drawRect(mDstB.getWidth() + 15,0, mDstB.getWidth() + 15 + mSrcB.getWidth(), mSrcB.getHeight(), mPaint);

            canvas.translate(0, mDstB.getHeight() + 15);

            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.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;
                }
            }
        }
    }
}

谷歌官方实例去掉透明区域重新混合

public class XfermodesView extends View {


    private static int W = 250;
    private static int H = 250;

    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

    //其中Sa全称为Source alpha表示源图的Alpha通道;Sc全称为Source color表示源图的颜色;Da全称为Destination alpha表示目标图的Alpha通道;Dc全称为Destination color表示目标图的颜色,[...,..]前半部分计算的是结果图像的Alpha通道值,“,”后半部分计算的是结果图像的颜色值。
    //效果作用于src源图像区域
    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),

            //取两图层全部区域,交集部分饱和度相加
            new PorterDuffXfermode(PorterDuff.Mode.ADD),
            //取两图层全部区域,交集部分叠加
            new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)
    };

    private static final String[] sLabels = {
            "Clear", "Src", "Dst", "SrcOver",
            "DstOver", "SrcIn", "DstIn", "SrcOut",
            "DstOut", "SrcATop", "DstATop", "Xor",
            "Darken", "Lighten", "Multiply", "Screen", "Add","Overlay"
    };

    public XfermodesView(Context context) {
        this(context, null);
    }

    public XfermodesView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XfermodesView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        if (windowManager != null) {
            DisplayMetrics display = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(display);
            W = H = (display.widthPixels - 64) / ROW_MAX; //得到矩形
        }

        //1,API 14之后,有些函数不支持硬件加速,需要禁用
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        mSrcB = makeSrc(W, H);
        mDstB = makeDst(W, H);

        //根据width和height创建空位图,然后用指定的颜色数组colors来从左到右从上至下一次填充颜色
        //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);
    }

//    //google api的画法
//    @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();
//        //设置是否使用双线性过滤来绘制Bitmap,图像在放大绘制的时候,默认使用的是最近邻插值过滤,这种算法简单,但会出现马赛克现象;而如果开启了双线性过滤,就可以让结果图像显得更加平滑
//        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.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
//            labelP.setTextSize(20);
//            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;
//            }
//        }
//    }
//
//    // create a bitmap with a circle, used for the "dst" image
//    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
//    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 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.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);

            // 使用离屏绘制
            int sc = canvas.saveLayer(x, y, x + W, y + H, null);
            canvas.translate(x, y);
            canvas.drawBitmap(makeDst(2 * W / 3, 2 * H / 3), 0, 0, paint);
            paint.setXfermode(sModes[i]);
            canvas.drawBitmap(makeSrc(2 * W / 3, 2 * H / 3), W / 3, H / 3, paint);
            paint.setXfermode(null);
            canvas.restoreToCount(sc);

            // draw the label
            labelP.setTextSize(20);
            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;
            }
        }
    }

    // create a bitmap with a circle, used for the "dst" image
    // 画圆一个完成的圆
    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, h), p);
        return bm;
    }

    // create a bitmap with a rect, used for the "src" image
    // 矩形右下角留有透明间隙
    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(0, 0, w * 19 / 20, h * 19 / 20, p);
        return bm;
    }
}

简单的刮刮卡案例

public class XfermodeEraserView extends View {

    private Paint mPaint;
    private Bitmap mDstBmp, mSrcBmp, mTxtBmp;
    private Path mPath;

    public XfermodeEraserView(Context context) {
        this(context, null);
    }

    public XfermodeEraserView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XfermodeEraserView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //初始化画笔
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(80);

        //禁用硬件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        //初始化图片对象
        mTxtBmp = BitmapFactory.decodeResource(getResources(), R.drawable.result);
        mSrcBmp = BitmapFactory.decodeResource(getResources(), R.drawable.eraser);
        mDstBmp = Bitmap.createBitmap(mSrcBmp.getWidth(), mSrcBmp.getHeight(), Bitmap.Config.ARGB_8888);

        //路径(贝塞尔曲线)
        mPath = new Path();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //绘制刮奖结果
        canvas.drawBitmap(mTxtBmp, 0, 0, mPaint);

        //使用离屏绘制
        int layerID = canvas.saveLayer(0, 0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);

        //先将路径绘制到 bitmap上
        Canvas dstCanvas = new Canvas(mDstBmp);
        dstCanvas.drawPath(mPath, mPaint);

        //绘制 目标图像
        canvas.drawBitmap(mDstBmp, 0, 0, mPaint);
        //设置 模式 为 SRC_OUT, 擦橡皮区域为交集区域需要清掉像素
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
        //绘制源图像
        canvas.drawBitmap(mSrcBmp, 0, 0, mPaint);

        mPaint.setXfermode(null);

        canvas.restoreToCount(layerID);
    }

    private float mEventX, mEventY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mEventX = event.getX();
                mEventY = event.getY();
                mPath.moveTo(mEventX, mEventY);
                break;
            case MotionEvent.ACTION_MOVE:
                float endX = (event.getX() - mEventX) / 2 + mEventX;
                float endY = (event.getY() - mEventY) / 2 + mEventY;
                //画二阶贝塞尔曲线
                mPath.quadTo(mEventX, mEventY, endX, endY);
                mEventX = event.getX();
                mEventY = event.getY();
                break;
        }
        invalidate();
        return true; //消费事件
    }
}

相关文章

  • android paint画笔图层混合模式

    官方Xfermode的实例 里面18中模式详解 谷歌官方实例去掉透明区域重新混合 简单的刮刮卡案例

  • Paint实现滤镜效果

    利用Paint绘制滤镜Xfermode PorterDuff.Mode图层混合模式一共有18种模式。 它将所绘制的...

  • Photoshop教程-色彩范围工具与混合模式制作彩色斑马特效

    通过应用Adobe Photoshop软件的色彩范围工具、图层混合模式、混合颜色带、画笔工具等,制作彩色斑马特效。...

  • 从零开始学视觉-9.溶解

    1. 画出基础图形:新建图层,图层混合模式设置为“溶解”,选画笔工具,柔边圆、硬度1%,画笔笔头设置大一点(700...

  • 李涛 图层效果

    运用图层蒙版减少对素材的破坏。 图层样式——混合选项 1.画笔着色如何不会画出界? 新建图层,画上去以后把图层模式...

  • PS基础课--4月2日作业

    图层蒙版、图层样式及混合模式 打开素材→在图层面板调整自然饱和度为100,饱和度为20→点击图层蒙版‘选择画笔工具...

  • Paint方法总结(三):图层混合模式

    参考扔物线大神博客 离屏绘制 在介绍图层混合模式之前先简单的说一下Android的离屏绘制。离屏绘制就是图层绘制的...

  • UI绘制-Paint(三)图层混合模式

    系列文章传送门:UI绘制-Paint(一)Paint基本属性及方法UI绘制-Paint(二)颜色相关方法UI绘制-...

  • 1.2.2Paint滤镜-XFERMODE

    使用图层混合api的地方(图片与图片图层混合) 1.ComposeShader 组合渲染 2.画笔Pain...

  • 混合模式

    AE混合模式菜单细分为八个类别 术语说明:-源颜色是应用混合模式的图层或画笔的颜色。-基础颜色是“时间轴”面板中图...

网友评论

      本文标题:android paint画笔图层混合模式

      本文链接:https://www.haomeiwen.com/subject/legductx.html