ColorFilter初探一

MaskFilter是对一个Paint的alpha通道的转换,而ColorFilter则是对每一个RGB通道应用转换 。所有由ColorFilter所派生的类在执行它们的转换时,都会忽略alpha通道。

Android包含三个ColorFilter:

ColorMatrixColorFilter  可以指定一个4×5的ColorMatrix并将其应用到一个Paint中。ColorMatrixes通常在程序中用于对图像进行处理 ,而且由于它们支持使用矩阵相乘的方法来执行链接转换,所以它们很有用。

LightingColorFilter  乘以第一个颜色的RGB通道,然后加上第二个颜色。每一次转换的结果都限制在0到255之间。

PorterDuffColorFilter  可以使用数字图像合成的16条Porter-Duff 规则中的任意一条来向Paint应用一个指定的颜色。

ColorMatrixColorFilter:

ColorMatrix mColorMatrix = new ColorMatrix(new float[]{
                        .5f, 0, 0, 0, 0,
                        0, .5f, 0, 0, 0,
                        0, 0, .5f, 0, 0,
                        0, 0, 0, 1, 0,
                });
                drawable.setColorFilter(new ColorMatrixColorFilter(mColorMatrix));
LightingColorFilter:

drawable.setColorFilter(new LightingColorFilter(0xffff0000, 0xff00ff00));
PorterDuffCOlorFilter

drawable.setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.ADD));
接下来重点讲解PorterDuffColorFilter

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 Xfermodes extends AppCompatActivity {
    private static final Xfermode[] sModes = {
            new PorterDuffXfermode(PorterDuff.Mode.CLEAR),/** [0, 0] */
            new PorterDuffXfermode(PorterDuff.Mode.SRC),/** [Sa, Sc] */ //原图
            new PorterDuffXfermode(PorterDuff.Mode.DST),/** [Da, Dc] */ //目标图
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */ //原图在上面
            new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),/** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */ //目标图在上面
            new PorterDuffXfermode(PorterDuff.Mode.DST_IN),/** [Sa * Da, Sc * Da] */ //绘制交集部分,绘制的是目标图
            new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), /** [Sa * Da, Sc * Da] */ //绘制交集部分,绘制的是原图
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),/** [Sa * (1 - Da), Sc * (1 - Da)] */ //绘制原图(不包括相交部分)
            new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),/** [Da * (1 - Sa), Dc * (1 - Sa)] */ //绘制目标图(不包括相交部分)
            new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),/** [Da, Sc * Da + (1 - Sa) * Dc] */ //相交的部分绘制原图,不想交的部分绘制目标图
            new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), /** [Sa, Sa * Dc + Sc * (1 - Da)] */ //相交的部分绘制目标图,不想交的部分绘制原图
            new PorterDuffXfermode(PorterDuff.Mode.XOR),/** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */ //取两个图形绘制的非交集
            new PorterDuffXfermode(PorterDuff.Mode.DARKEN),/** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */ //都显示,相交部分是黑色
            new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), /** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */ //都显示,相交部分是白色
            new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),/** [Sa * Da, Sc * Dc] */ //去两层绘制的交集
            new PorterDuffXfermode(PorterDuff.Mode.SCREEN), /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */ //都显示,交集部分显示透明颜色
            new PorterDuffXfermode(PorterDuff.Mode.ADD), /** Saturate(S + D) */ //按饱和度增加来显示
            new PorterDuffXfermode(PorterDuff.Mode.OVERLAY) /** Saturate(S + D) */ //叠加,
    };

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
    }

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

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

    class SampleView extends View {
        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 int W = 64;
        private static final int H = 64;

        public SampleView(Context context) {
            super(context);
            mSrcB = makeSrc(W, H);
            mDstB = makeDst(W, H);

            //这里只是创建一个2*2像素的Bitmap,并为每一个像素设置颜色,tips:数组的长度要和width*height的值保持一致
            /*
                extend:
                      Bitmap.Config.ALPHA_8就是Alpha由8位组成
                      Bitmap.Config.ARGB_4444就是由4个4位组成即16位
                      Bitmap.Config.ARGB_8888就是由4个8位组成即32位
                      Bitmap.Config.RGB_565就是R为5位,G为6位,B位5位共16位
                位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真
             */
            Bitmap bm = Bitmap.createBitmap(new int[]{0xFFFFFFFF, 0xFFCCCCCC,
                            0xFFCCCCCC, 0xFFFFFFFF}, 2, 2,
                    Bitmap.Config.RGB_565);

            //定义色彩渲染器,模式为x、y轴重复显示
            mBG = new BitmapShader(bm,
                    Shader.TileMode.REPEAT,
                    Shader.TileMode.REPEAT);
            Matrix m = new Matrix();
            //进行缩放,放大为原来的6倍
            m.setScale(6, 6);
            mBG.setLocalMatrix(m);//设置BitmapShader的本地矩阵
        }


        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.GREEN);
            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++) {
                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.MATRIX_SAVE_FLAG |
                                Canvas.CLIP_SAVE_FLAG |
                                Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                                Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
                                Canvas.CLIP_TO_LAYER_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);

                //书写文字
                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;
                }
            }
        }
    }
}
以上为APIDemo中的代码,在很多情况都不会使用自定义View

iv = (ImageView) findViewById(R.id.iv);
iv.getDrawable().setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.ADD));
在API21及以上可以使用

iv.getDrawable().setTint(0xffff0000);
iv.getDrawable().setTintMode(PorterDuff.Mode.MULTIPLY);








你可能感兴趣的:(android)