16种图形混合模式示例

首先绘制Dst(黄色的),然后绘制Src(蓝色的)
问题来了:为何还会有部分黄色?不应该是把src和dst都清除了吗?


图形混合模式简介

ProterDuff的含义
ProterDuff是两个人名的组合:Tomas Proter和 Tom Duff,他们是最早在SIGGRAPH(Special Interest Group for Computer GRAPHICS,计算机图形图像特别兴趣小组)上提出图形混合概念的大神级人物。
利用ProterBuff.Mode我们可以完成任意2D图像测操作

模式使用简介
首先绘制Dst(黄色的),然后绘制Src(蓝色的)
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    上下层都显示

画出这几种模式的效果

public class XfermodesView extends View {
    private Context context;
    /**每个item的大小*/
    private int itemLength;
    /**每行的数量*/
    private static final int ROW_MAX = 4;
    /**首先绘制的黄色的Bitmap*/
    private Bitmap mDstBitmap;
    /**然后绘制的蓝色的Bitmap*/
    private Bitmap mSrcBitmap;
    /**灰白相间的背景图渲染器*/
    private Shader bitmapShader;
    private Paint textPaint;
    private Paint bitmapPaint;
    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 XfermodesView(Context context) {
        super(context);
        this.context = context;
        itemLength = dp2px(70);
        mSrcBitmap = makeSrcBitmap(itemLength, itemLength);
        mDstBitmap = makeDstBitmap(itemLength, itemLength);
        //根据width和height创建空位图,然后用指定的颜色数组colors来从左到右从上至下依次填充颜色
        Bitmap bitmap = Bitmap.createBitmap(new int[] { 0xFFFFFFFF, 0xFFCCCCCC, 0xFFCCCCCC, 0xFFFFFFFF }, 2, 2, Bitmap.Config.RGB_565);
        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        Matrix matrix = new Matrix();
        matrix.setScale(dp2px(2), dp2px(2));//本来背景是一个白像素一个会像素,太密集了,此操作目的是放大背景
        bitmapShader.setLocalMatrix(matrix);
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(dp2px(10));
        bitmapPaint = new Paint();
        bitmapPaint.setFilterBitmap(false);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        canvas.translate(dp2px(5), dp2px(20));
        int x = 0;
        int y = 0;
        for (int i = 0; i < sModes.length; i++) {
            // 画正方形边框
            bitmapPaint.setStyle(Paint.Style.STROKE);
            bitmapPaint.setShader(null);//不去渲染
            canvas.drawRect(x - 0.5f, y - 0.5f, x + itemLength + 0.5f, y + itemLength + 0.5f, bitmapPaint);//+-0.5f只是为了精确
            //画灰白相间的背景
            bitmapPaint.setStyle(Paint.Style.FILL);
            bitmapPaint.setShader(bitmapShader);//用上面指定的渲染器渲染
            canvas.drawRect(x, y, x + itemLength, y + itemLength, bitmapPaint);
            // 根据不同的模式画两个图
            int sc = canvas.saveLayer(x, y, x + itemLength, y + itemLength, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG //1|2|4|8|16
                    | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
            canvas.translate(x, y);
            // 以下是最核心的三行代码
            canvas.drawBitmap(mDstBitmap, 0, 0, bitmapPaint);
            bitmapPaint.setXfermode(sModes[i]);
            canvas.drawBitmap(mSrcBitmap, 0, 0, bitmapPaint);
            bitmapPaint.setXfermode(null);
            canvas.restoreToCount(sc);
            // 画标题
            canvas.drawText(sLabels[i], x + itemLength / 2, y - textPaint.getTextSize() / 2, textPaint);
            x += itemLength + dp2px(5);
            //画完一行后移到下一行
            if ((i % ROW_MAX) == ROW_MAX - 1) {
                x = 0;
                y += itemLength + dp2px(20);
            }
        }
    }

    private Bitmap makeDstBitmap(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;
    }
    private Bitmap makeSrcBitmap(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;
    }
    private int dp2px(float dpValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

图形混合模式 PorterDuff Xfermodes的更多相关文章

  1. Android Paint Xfermode 学习小结

    一.setXfermode(Xfermode xfermode) Xfermode国外有大神称之为过渡模式,这种翻译比较贴切但恐怕不易理解,大家也可以直接称之为图像混合模式,因为所谓的"过渡 ...

  2. 详解Paint的setXfermode(Xfermode xfermode)

    一.setXfermode(Xfermode xfermode) Xfermode国外有大神称之为过渡模式,这种翻译比较贴切但恐怕不易理解,大家也可以直接称之为图像混合模式,因为所谓的“过渡”其实就是 ...

  3. Android之圆形头像裁切

    PS:今天项目测试组发现,百度地图定位的数据坐标位置是正确的,但是显示的数据是错误的.最后查来查去发现,那个商厦在百度地图上根本就没有那条数据,这让我如何显示,当初就推崇使用高德地图定位,上面的数据量 ...

  4. 【腾讯bugly干货分享】Android自绘动画实现与优化实战——以Tencent OS录音机波形动

    前言 本文为腾讯bugly的原创内容,非经过本文作者同意禁止转载,原文地址为:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1180 ...

  5. 转载爱哥自定义View系列--Paint详解

    上图是paint中的各种set方法 这些属性大多我们都可以见名知意,很好理解,即便如此,哥还是带大家过一遍逐个剖析其用法,其中会不定穿插各种绘图类比如Canvas.Xfermode.ColorFilt ...

  6. Android Paint以及ColorFilter等

    我们可以通过Paint中大量的setter方法来为画笔设置属性: 这些属性大多我们都可以见名知意,很好理解,即便如此,哥还是带大家过一遍逐个剖析其用法,其中会不定穿插各种绘图类比如Canvas.Xfe ...

  7. Android 画笔Paint

    转自 http://wuxiaolong.me/2016/08/20/Paint/ 了解Android Paint,一篇就够.引用Aige<自定义控件其实很简单>系列博客的话“很多时候你压 ...

  8. 自己定义控件事实上非常easy1/6

    尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 上一节我们粗略地讲了下怎样去实现我 ...

  9. Canvas与Paint的0基础使用

    看了非常多android自己定义方面的资料,了解了非常多原理,遇到人家自己定义的东西也可以看得懂,可是.当自己去自己定义的时候.发现脑袋一片空白,所以就先从认识Canvas和Paint開始吧! Can ...

随机推荐

  1. Java学习笔记——SequenceInputStream类合并文件的综合举例分析

    SequenceInputStream 介绍 SequenceInputStream 类表示其他输入流的逻辑串联,即文件的合并. 它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾, ...

  2. mysql中的JOIN用法总结

    join是mysql中一个基础的关键词,一般在多表连接查询中使用,这里做一下总结 1.JOIN的语法格式 table_references: table_reference [, table_refe ...

  3. 在windows下搭建linux-c学习环境

    下载virtualbox并安装: https://www.virtualbox.org/wiki/Downloads 现在vagrant并安装: https://www.vagrantup.com/d ...

  4. cocos2d(粒子效果编辑器)

    ParticleDesigner  for  Mac下载地址:http://www.cocoachina.com/bbs/read.php?tid=108339 最近在做一款粒子编辑器 其实就是在co ...

  5. Dom4j修改xml文档

    1. 写出内容到xml文档 XMLWriter writer = new XMLWriter(OutputStream, OutputForamt) wirter.write(Document); 2 ...

  6. 转:CFile::Seek

    CFile::Seek virtual LONG Seek(LONG lOff,UINT nFrom);  throw(CFileException); 返回值:如果要求的位置合法,则Seek返回从文 ...

  7. The 500 Most Commonly Used Words in the English Language

    Based on the combined results of British English, American English and Australian English surveys of ...

  8. angular2 学习笔记 ( ngModule 模块 )

    2016-08-25, 当前版本是 RC 5. 参考 : https://angular.cn/docs/ts/latest/guide/ngmodule.html 提醒 : 这系列笔记的 " ...

  9. Qt入门(5)——用Qt控件创建一个电话本界面

    具体实现步骤: 一.首先用 Qt Designer 创建一个两张图的对话框,分别保存为listdialog.ui和editdialog.ui文件 要注意其中各个空间对应的名称修改好 二.新建一个Qt应 ...

  10. 【转】Java中 List的遍历

    原文网址:http://blog.csdn.net/player26/article/details/3955906 import java.util.ArrayList; import java.u ...