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. NetBeans使用技巧记录

    1.窗体字体大小设置: 在etc文件夹下的netbeans.conf中添加,12表示字体大小,12正合适. netbeans_default_options="--fontsize 12 - ...

  2. android WIFI的一些属性

    package com.example.wifitest; import java.util.List; import android.content.Context; import android. ...

  3. 多线程12-CyclicBarrier、CountDownLatch、Exchanger

    1.CyclicBarrier 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面 package org.lkl.thead.foo; import java.util.con ...

  4. 解决secureCRT数据库里没有找到防火墙 '无'问题,转自:http://jingyan.baidu.com/article/9989c74601274bf649ecfe74.html

    中文版的secureCRT由于汉化的问题(把null翻译成无了),导致每次打开都会有个防火墙的错误提示:数据库里没有找到防火墙 '无' 此会话将尝试不通过防火墙进行连接.出现这个错误的原因是在secu ...

  5. Ubuntu下MySQL配置为外网访问

    Ububtu安装MySQL后默认外网无法连接,但是很多时候我们想要在外网访问方便管理.在这里,简单叙述一下自己在配置过程中的操作,步骤如下: 以root身份登入mysql mysql -u root ...

  6. ubuntu 14.0 下github 配置

    一:创建Repositories 1:首先在github下创建一个帐号.这个不用多说,然后创建一个Repositories. 2:然后在ubuntu下安装git相关的东东: 1 sudo apt-ge ...

  7. 采访:Go语言编程

    Go语言是由Google在2009年11月份公布的,它的目标是要应对软件开发所面临的最新挑战.Go语言特别被设计为快速(包括在编译时).支持多核的语言,并且兼顾了动态语言的简单性和静态类型语言的安全性 ...

  8. Ionic 测试针对Andorid平台

    环境准备: (1)nodejs环境以及配置完成: y@y:~$ node -v v0.12.2 (2)Android SDK 环境变量已经配置完毕: export ANDROID_SDK=/home/ ...

  9. 标签 Attribute

    在一个类上面放一个标签,可以用来表示一些特定规则,比如某个对象的某个属性不想被json化,那么我们在它头上放个标签就行了,或是做ORM时指定某个Class对应的table名字等. 最后标签是通过反射来 ...

  10. Qt自定义带游标的slider,在滑块正上方显示当前值(类似于进度条,用一个额外的QLabel冒充QSilder的一部分,然后move就行了)

    首先自定义QSlider的子类MyCustomSlider,如下所示. mycustomslider.h #ifndef MYCUSTOMSLIDER_H #define MYCUSTOMSLIDER ...