Paint、Canvas、Matrix使用讲解(一、Paint)

我正在参加 CSDN 2015博客之星评选 感恩分享活动,如果觉得文章还不错,请投个票鼓励下吧:http://vote.blog.csdn.net/blogstar2015/candidate?username=tianjian4592


好了,前面主要讲了Animation,Animator 的使用,以及桌面火箭效果和水波纹效果,分别使用android框架和自己绘制实现,俗话说,工欲善其事,必先利其器,接下来几篇文章主要讲绘制中我们需要常使用的一些利器;

Paint:画笔

Canvas:画布

Matrix:变换矩阵

绘制动效确实就像拿着笔在画布上面画画一样,而Paint就是我们拿着的笔,Canvas就是使用的画布;


一、Paint(画笔)

根据我们要画的类型,我们可以选择不同的笔,比如大气磅礴的山水画,我们可以选择大头的毛笔;细腻入微的肖像画我们可以选择尖头的铅笔。并且根据我们想要的效果,我们在绘画的时候,还会选择不同的颜料或不同颜色的笔;

那么在程序中,Paint 就足以满足以上所有的需要,我们可以根据我们自己的需要去自行设置我们画笔的属性,首先来看看都能设置哪些属性:


Paint 有三个构造函数,分别是:

Paint()创建一个画笔对象;

Paint(int flags):在构造的时候可以传入一些定义好的属性,eg:Paint.ANTI_ALIAS_FLAG  --用于绘制时抗锯齿

Paint(Paint paint):使用构造函数中Paint的属性生成一个新的Paint

private void initPaint() {
        // 构建Paint时直接加上去锯齿属性
        mColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        // 直接使用mColorPaint的属性构建mBitmapPaint
        mBitmapPaint = new Paint(mColorPaint);
    }


方法常用的主要有以下一些:

setARGB (int a, int r, int g, int b):用于设置画笔颜色,A 代表 alpha(透明度),R 代表Red (红色),G 代表 Green(绿色),B 代表 Blue(蓝色)

色值采用16进制,取值在 0 - 255 之间 ,0(0x00) 即 完全没有 ,255(0xff) 代表满值 ;

setAlpha(int a): 用于设置Paint 的透明度;

setColor(int color):同样设置颜色,如果是常用色,可以使用Color 类中定义好的一些色值 ,eg:Color.WHITE

setColorFilter(ColorFilter filter):设置颜色过滤器,可以通过颜色过滤器过滤掉对应的色值,比如去掉照片颜色,生成老照片效果;

ColorFilter有以下几个子类可用:

ColorMatrixColorFilter

LightingColorFilter

PorterDuffColorFilter


1.ColorMatrixColorFilter:通过颜色矩阵(ColorMatrix)对图像中的色值进行改变

在Android中,图片是以一个个 RGBA 的像素点的形式加载到内存中的,所以如果需要改变图片的颜色,就需要针对这一个个像素点的RGBA的值进行修改,其实主要是RGB,A是透明度;

修改图片 RGBA 的值需要ColorMatrix类的支持,它定义了一个 4*5 的float[]类型的矩阵,矩阵中每一行表示 RGBA 中的一个参数。

颜色矩阵M是以一维数组m=[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]的方式进行存储的;

颜色矩阵


而对于一张图像来说,展示的颜色效果取决于图像的RGBA(红色、绿色、蓝色、透明度)值。而图像的 RGBA 值则存储在一个5*1的颜色分量矩阵C中,由颜色分量矩阵C可以控制图像的颜色效果。颜色分量矩阵如图所示: 

所以为了改变图像的显示效果,只需要改变 4*5 的颜色矩阵ColorMatrix,然后通过

即可得到新的图像显示矩阵;

由此可见,通过颜色矩阵 ColorMatrix 修改了原图像的 RGBA 值,从而达到了改变图片颜色效果的目的。并且,通过如上图所示的运算可知,颜色矩阵 ColorMatrix 的第一行参数abcde决定了图像的红色成分,第二行参数fghij决定了图像的绿色成分,第三行参数klmno决定了图像的蓝色成分,第四行参数pqrst决定了图像的透明度,第五列参数ejot是颜色的偏移量。

  通常,改变颜色分量时可以通过修改第5列的颜色偏移量来实现,如上面所示的颜色矩阵,通过计算后可以得知该颜色矩阵的作用是使图像的红色分量和绿色分量均增加100,这样的效果就是图片泛黄(因为红色与绿色混合后得到黄色):


除此之外,也可以通过直接对颜色值乘以某一系数而达到改变颜色分量的目的。如下图所示的颜色矩阵,将绿色分量放大了2倍,这样的效果就是图片泛绿色:


基于此,我们利用ColorFilter 和 ColorMatrixColorFilter类 和 Paint 的setColorFilter 就可以改变图片的展示效果(颜色,饱和度,对比度等),从而得到类似市面上图像软件中的黑白老照片、泛黄旧照片、羞涩的青春... ...特效;


     

                                  (原图效果)                         (调节效果)


    // 通过外层传入的 A、R、G、B值生成对应的ColorMatrix ,然后重新绘制图像
    public void setArgb(float alpha, float red, float green, float blue) {
        mRedFilter = red;
        mGreenFilter = green;
        mBlueFilter = blue;
        mAlphaFilter = alpha;
        mColorMatrix = new ColorMatrix(new float[] {
                mRedFilter, 0, 0, 0, 0,
                0, mGreenFilter, 0, 0, 0,
                0, 0, mBlueFilter, 0, 0,
                0, 0, 0, mAlphaFilter, 0,
        });
        mPaint.setColorFilter(new ColorMatrixColorFilter(mColorMatrix));

        postInvalidate();
    }


在Activity中拖动seekbar时,动态改变对应的色值参数,然后设置给里面的View:

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        float filter = (float) progress / 100;
        if (seekBar == mRedSeekBar) {
            mRedSeek = filter;
        } else if (seekBar == mGreenSeekBar) {
            mGreenSeek = filter;
        } else if (seekBar == mBlueSeekBar) {
            mBlueSeek = filter;
        } else if (seekBar == mAlphaSeekBar) {
            mAlphaSeek = filter;
        }
        mColorFilterView.setArgb(mAlphaSeek, mRedSeek, mGreenSeek, mBlueSeek);
    }

我们再专门把绿色位置扩大为两倍,看下效果:

    private static final float[] mMatrixFloats = new float[] {
            1, 0, 0, 0, 0,
            0, 2, 0, 0, 0,
            0, 0, 1, 0, 0,
            0, 0, 0, 1, 0
    };

可以看到这个图片绿的敞亮

我们继续修改影响绿色的这一排矩阵值,看会发生什么变化,这次我们只是把2改大一点,改为10看看:

    private static final float[] mMatrixFloats = new float[] {
            1, 0, 0, 0, 0,
            0, 10, 0, 0, 0,
            0, 0, 1, 0, 0,
            0, 0, 0, 1, 0
    };
这次我们已经觉得图片绿的过头了

我们再将影响绿色的矩阵值改小,大家已经可以猜测下图片的效果了,那就是绿色会成倍的减弱,减弱到一定的层度就会显得发灰;
而最后面的颜色增量也是一样,可以根据数值的大小,正负一定程度上增强和减弱对应的色值;

上面的demo只是通过动态的改变上面颜色矩阵里的a、g、s、m 值,进而改变图像对应的色值分量,达到改变图片显示效果的目的,我们还可以通过改变矩阵的其他数据来调节出各种有意思的效果:

修改影响红色的这一排矩阵:

    private static final float[] mMatrixFloats = new float[] {
            2, 0.5f, 0.5f, 0.5f, 20,
            0, 1, 0, 0, 0,
            0, 0, 1, 0, 0,
            0, 0, 0, 1, 0
    };
  • 34
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 27
    评论
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值