博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 滤镜效果和颜色通道过滤
阅读量:6710 次
发布时间:2019-06-25

本文共 11044 字,大约阅读时间需要 36 分钟。

当今是靠脸吃饭的时代,平时的人像、风景照、美食照等都需要加上一款优美的滤镜,才能让照片更加精致,更加吸引人,这样的照片能够让你在朋友圈更加出众,别具一格。

因此一个智能手机当然少不了一款美颜APP,在商店中有众多的美颜APP,例如我比较喜欢的:Snapseed、InterPhoto、美颜相机和美人相机等等。这些相机都拥有非常美和优秀的滤镜,正因为有这些优秀的滤镜,才能让你的照片变得更美,因此作为开发者的我们需要了解这些滤镜是怎么做出来的,一般都是通过Android自带的滤镜处理、OpenGL处理或者通过颜色RGB的滤镜处理。本文我们不介绍OpenGL,因为OpenGL确实是一个很强大的图像处理技术。

Android的滤镜效果就是对图像进行一定的过滤加工处理,一般的使用Paint设置滤镜效果分为两类:

1、Android自带的滤镜效果,而该滤镜效果可以分为:

1)模糊遮罩滤镜(BlurMaskFilter);

2)浮雕遮罩滤镜(EmbossMaskFilter)。

2、颜色RGB的滤镜处理,可以通过ColorMatrix设置。

通过Android的滤镜效果和颜色通道过滤这两种方式,可以对图像做出很好的滤镜效果,接下来学习下如何处理滤镜。

Android自带的滤镜效果

Android的滤镜处理使用paint.setMaskFilter(maskfilter)方法设置,其中可以设置BlurMaskFilter和EmbossMaskFilter这两款滤镜,而这两款滤镜都是继承MaskFilter这个基类。

BlurMaskFilter

BlurMaskFilter:即模糊遮罩滤镜,通过该滤镜可以使图像呈现模糊效果。

使用:

public class MaskFilterView extends View {    private int progress = 10;    private Paint paint;    public MaskFilterView(Context context) {        super(context);        paint = new Paint(Paint.ANTI_ALIAS_FLAG);    }    public MaskFilterView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        paint = new Paint(Paint.ANTI_ALIAS_FLAG);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //需要关闭硬件加速(没有关闭则没效果)        setLayerType(View.LAYER_TYPE_SOFTWARE, null);        paint.setColor(Color.RED);        RectF r = new RectF(100, 100, 300, 300);        /**模糊遮罩滤镜效果         * BlurMaskFilter.Blur.INNER         * BlurMaskFilter.Blur.NORMAL         * BlurMaskFilter.Blur.OUTER         * BlurMaskFilter.Blur.SOLID         */		paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.NORMAL));        canvas.drawRect(r , paint);    }    public void setProgress(int progress) {        if (progress <= 0){            return;        }        this.progress = progress;        postInvalidate();    }}复制代码

Activity:

public class MaskFilterActivity extends AppCompatActivity {    private SeekBar mSeekBar;    private MaskFilterView mFilterView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_mask_filter);        mSeekBar = (SeekBar)this.findViewById(R.id.seekBar);        mFilterView = (MaskFilterView)this.findViewById(R.id.my_view);        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {            @Override            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {                mFilterView.setProgress(progress);            }            @Override            public void onStartTrackingTouch(SeekBar seekBar) {            }            @Override            public void onStopTrackingTouch(SeekBar seekBar) {            }        });    }}复制代码

效果图:

在MaskFilterView的onDraw方法中,首先需要new一个BlurMaskFilter对象,我们看下其构造方法:

public BlurMaskFilter(float radius, Blur style)

radius:模糊的半径,值越大模糊就越扩散。

style:模糊滤镜使用的类型,总共有四种类型可以选择,它们分别是:

1)INNER:在图像内部产生模糊;

2)NORMAL:将整个图像模糊掉;

3)OUTER:在Alpha边界外产生一层模糊,而且将原本的图像变透明。

4)SOLID:在图像的Alpha外边界产生一层与Paint颜色一致的模糊效果,但不影响图像本身。

注意:这里我们需要需要关闭硬件加速,否则没效果。

上图效果中我们使用了INNER,接下来我们看看其他三种效果。

NORMAL:
paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.NORMAL));canvas.drawRect(r , paint);复制代码

OUTER:
paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.OUTER));canvas.drawRect(r , paint);复制代码

SOLID:
paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.SOLID));canvas.drawRect(r , paint);复制代码

以上便是模糊遮罩滤镜的使用了,下面我们看看浮雕遮罩滤镜的使用效果。

EmbossMaskFilter

EmbossMaskFilter(浮雕遮罩滤镜)让图像呈现一种凹凸不平的面具效果。

使用

paint.setMaskFilter(new EmbossMaskFilter(new float[]{30,30,30}, 0.2f, 20, progress));canvas.drawBitmap(bitmap, 100, 300, paint);复制代码

使用的时候,需要new一个EmbossMaskFilter对象,并通过paint.setMaskFilter方法设置,我们主要看EmbossMaskFilter的构造方法参数。

public EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius)复制代码

direction:指定长度为xxx的数组标量[x,y,z],用来指定光源的位置;

ambient:指定周边背景光源(0~1);

specular:指镜面反射系数;

blurRadius:指定模糊半径。

注意:使用EmbossMaskFilter同样需要关闭硬件加速,否则没效果。

颜色RGB的滤镜处理

颜色RGB的滤镜处理是通过ColorMatrix来实现的,即颜色矩阵,然后将ColorMatrix设置到ColorMatrixColorFilter,通过setColorFilter方法设置ColorMatrixColorFilter,这样就完成了设置颜色过滤器。setColorFilter还可以设置所有ColorFilter的子类,包括LightingColorFilter和PorterDuffColorFilter。

ColorMatrix顾名思义就是颜色矩阵,那么滤镜的所有处理效果都是通过颜色矩阵的变换实现的。所以需要读者能够熟悉基本的矩阵运算方法。如果读者目前还不认识矩阵,怎么办?没关系,接下来我们简单介绍下矩阵,以及基本的运算方法。读者可以自行参考百度百科。

矩阵

定义:

矩阵加法:

矩阵减法:

矩阵乘法:

第一个矩阵A的第一行,与第二个矩阵B的第一列的数字分别相乘,得到的结果相加,最终的值做为结果矩阵的第(1,1)位置的值(即第一行,第一列)。 同样,A矩阵的第一行与B矩阵的第二列的数字分别相乘然后相加,得到的值作为结果矩阵第(1,2)位置的值(即第一行第二列)。

色彩矩阵: 一般的色彩矩阵使用四阶表示,也就是RGBA

半透明的色彩矩阵,如:

Android色彩矩阵使用五阶矩阵

在四阶矩阵的基础上,增加一阶,而第五阶表示偏移量,上图表示红色分量值更改为原来的2倍,绿色分量增加100(1*100+100);

ColorMatrix的使用

调用红色(R),绿色增加两倍。

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //需要关闭硬件加速(没有关闭则没效果)        setLayerType(View.LAYER_TYPE_SOFTWARE, null);        paint.setColor(Color.RED);        ColorMatrix matrix = new ColorMatrix(new float[]{				0,0,0,0,0,				0,1,0,0,200,				0,0,1,0,0,				0,0,0,1,0,		});        paint.setColorFilter(new ColorMatrixColorFilter(matrix ));        canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);    }复制代码

先new一个ColorMatrixColorFilter对象,并把ColorMatrix设置进去,setColorFilter方法把ColorMatrixColorFilter对象设置进去就可以完成设置颜色过滤器。

反相效果
ColorMatrix matrix = new ColorMatrix(new float[]{				-1,0,0,0,255,				0,-1,0,0,255,				0,0,-1,0,255,				0,0,0,1,0,		});paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

颜色增强

颜色增强:可以起到一个变亮的效果,通过矩阵缩放方式。

ColorMatrix matrix = new ColorMatrix(new float[]{				1.2f,0,0,0,0,				0,1.2f,0,0,0,				0,0,1.2f,0,0,				0,0,0,1.2f,0,		});paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

黑白图片

去色原理:只要把RGB三通道的色彩信息设置成一样;即:R=G=B,那么图像就变成了灰色,并且,为了保证图像亮度不变,同一个通道中的R+G+B=1。 如:0.213+0.715+0.072=1;也就是RGB分别为:0.213,0.715,0.072; 三个数字是根据色彩光波频率及色彩心理学计算出来的。

ColorMatrix matrix = new ColorMatrix(new float[]{                0.213f, 0.715f, 0.072f, 0, 0,                0.213f, 0.715f, 0.072f, 0, 0,                0.213f, 0.715f, 0.072f, 0, 0,                0, 0, 0, 1f, 0,        });paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

发色效果

发色效果:如红色和绿色交换——把第一行和第二行交换。

ColorMatrix matrix = new ColorMatrix(new float[]{			0,1f,0,0,0,			1f,0,0,0,0,			0,0,1f,0,0,			0,0,0,1f,0,		});paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

复古风格
ColorMatrix matrix = new ColorMatrix(new float[]{				1/2f,1/2f,1/2f,0,0,				1/3f,1/3f,1/3f,0,0,				1/4f,1/4f,1/4f,0,0,				0,0,0,1f,0,			});paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

色彩运算

ColorMatrix色彩矩阵,除了以上直接设置矩阵的方式,还可以使用ColorMatrix类的方法来设置进行色彩运算:

1)色彩的缩放运算(matrix.setScale):也就是四阶矩阵RGBA对应的乘法运算。

ColorMatrix matrix = new ColorMatrix();//setScale(float rScale, float gScale, float bScale, float aScale)matrix.setScale(2, 2, 2f, 1);paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

上图中RGB都方法原来的两倍。

2)色彩的平移运算,也就是矩阵加法运算。

ColorMatrix的API

通过上面的学习我们知道ColorMatrix其强大之处在于通过矩阵运算可以实现颜色通道过滤,我们有必要学习ColorMatrix的API。

构造方法

三个构造方法,可以不需要参数,可以传一个float数组(矩阵),也可以ColorMatrix对象作为参数。

看下ColorMatrix()方法里面的reset()方法。

/**     * Set this colormatrix to identity:     * 
     * [ 1 0 0 0 0   - red vector     *   0 1 0 0 0   - green vector     *   0 0 1 0 0   - blue vector     *   0 0 0 1 0 ] - alpha vector     * 
*/ public void reset() { final float[] a = mArray; Arrays.fill(a, 0); a[0] = a[6] = a[12] = a[18] = 1; }复制代码

该方法主要是初始化一个矩阵,而且将RGBA都设置为1。

set方法

提供两个set方法,可以设置float数组(矩阵),也可以设置ColorMatrix对象,跟构造方法对应起来。

matrix.set(new float[]{                1/2f,1/2f,1/2f,0,0,                1/3f,1/3f,1/3f,0,0,                1/4f,1/4f,1/4f,0,0,                0,0,0,1f,0,        });paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

setScale方法

设置色彩的缩放函数,上面已经介绍过该方法了.

setRotate

该方法是色彩旋转函数

axis:代表绕哪一个轴旋转,0,1,2 (0红色,1绿色,2蓝色);

degrees:旋转的度数。

该函数已经做好了矩阵的设置和运算了。

matrix.setRotate(0,progress);paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

setSaturation

setSaturation:设置饱和度

方法内部已经运算好的了,我们只需要传一个float类型参数sat。

sat:1表示是原来不变,0表示灰色;如果大于1增加饱和度。

matrix.setSaturation(progress);paint.setColorFilter(new ColorMatrixColorFilter(matrix ));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

setRGB2YUV

RGB转成YUV,对应的还有一个方法setYUV2RGB,也就是YUV转成RGB。

setConcat
setConcat(ColorMatrix matA, ColorMatrix matB):将颜色矩阵matA和matB复合,相当与对图片进行matA矩阵处理再进行矩阵matB处理。matrixA.preConcat(ColorMatrix prematrix):等价于setConcat(matrixA, prematrix)matrixA.postConcat(ColorMatrix postmatrix):等价于setConcat(prematrix,matrixA)复制代码

ColorFilter

ColorFilter作为颜色过滤器,有三个子类来实现颜色过滤: 1)ColorMatrixColorFilter:即色彩矩阵的颜色过滤器,配合ColorMatrix使用。 2)LightingColorFilter:即光照颜色过滤器,能过滤颜色和增强色彩的方法。 3)PorterDuffColorFilter:即图形混合滤镜,该是图形学的一个理论飞跃。

上文中已经使用过了ColorMatrixColorFilter,并且配合ColorMatrix使用。接下来主要介绍LightingColorFilter和PorterDuffColorFilter。

LightingColorFilter

光照颜色过滤器,也就是ColorMatrixColorFilter的简化版本。

public LightingColorFilter(@ColorInt int mul, @ColorInt int add) {        mMul = mul;        mAdd = add;    }复制代码

通过构造方法设置过滤颜色,参数解析:

mul:multiply,也就是乘法 ;

add:加法,也就是颜色偏移量。

paint.setColorFilter(new LightingColorFilter(0x00ff00, 0xff0000));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

PorterDuffColorFilter
public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {        mColor = color;        mMode = mode;    }复制代码

color:源颜色, mode:色彩的混合模式:

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:取两图层全部区域,交集部分变为透明色。

paint.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN));canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);复制代码

转载地址:http://wmalo.baihongyu.com/

你可能感兴趣的文章
表格存储Tablestore权威指南(持续更新)
查看>>
java B2B2C源码电子商城系统-Kafka快速入门
查看>>
Spring Cloud云服务 - HongHu架构common-service 项目构建过程
查看>>
hadoop中hive原理及安装
查看>>
pear默认安装后一个小bug
查看>>
我的友情链接
查看>>
nginx-通过Nginx统计当前每个域名流量
查看>>
家庭电路 功率和负荷
查看>>
SECURITY-Dockerfile写法
查看>>
openGL坐标系
查看>>
vim
查看>>
Intelij idea 不能解析jsp内置对象
查看>>
C中调用C++函数
查看>>
spring boot 1.5.4 之web开发(三)
查看>>
H3CSE之GB0-390广域网安全笔记 之二
查看>>
Redis在新浪的大规模运维经验
查看>>
nginx 源码安装openssl修复Heartbleed漏洞
查看>>
Oracle IO问题解析(四)
查看>>
OSPF与MTU
查看>>
如何处理人际关系
查看>>