前言

在之前的几次课当中咱们曾经具体理解到整个android程序,从启动再到绘制的整体流程,从这两头咱们又牵扯出了Canvas绘制图形的画板和咱们的Paint管制色调款式的画笔,那么之前根底篇咱们就不进行具体的解释,那些API在之前的根底篇曾经公布出来,我也正文的十分具体,明天我门来理解Paint高级篇真正须要理解的滤镜

  • 公众号:小新聊Android
  • Android根底底层到架构成长笔记github地址

滤镜

1.滤镜成果

从上图咱们能够看到 四张滤镜成果图像,其色调的显示成果各不一样,也就是说所谓滤镜其实只不过是对于本来图像色调进行调整,那么须要对图像的色调进行调整操作,咱们会须要晓得几个概念,那就是咱们的图像形成,色彩通道,色彩模式以及色彩举证

2.图像形成

在具体讲滤镜之前,明天咱们先来系统化真正认识一下在咱们计算机当中咱们的图像到底是什么,咱们都晓得在计算机体系当中咱们的图像有各种各样的格局,比方jpg,png,gif等等...

那么咱们同样也晓得咱们计算机当中的图像文件其实理论也就是一个二进制的字节码文件,那么这个图像实质上来说是一个二进制文件,而后咱们的cpg,gpu对二进制文件进行辨认再显示到咱们的屏幕上,那么咱们当初须要关注的是,这些文件当中他到底保留的是什么?

其实一个图像文件当中,他保留的数据总体分为两块

  1. 图像的信息
  2. 图像的数据

后者好了解,咱们能够了解为图像具体的那些像素点的数据,那么前者其实咱们能够了解为,是一组信息,这组信息的作用是让咱们的cpg,gpu在显示图像的时候,基于我门设定的这组信息的规定不同,那么显示的成果不一样,
以一种格局(PNG)为例,我在网上扒出了对于这个图像的构造的解释(粗略看一下就好)

    PNG的文件构造        对于一个PNG文件来说,其文件头总是由位固定的字节来形容的:    十进制数    137 80 78 71 13 10 26 10    十六进制数    89 50 4E 47 0D 0A 1A 0A    其中第一个字节0x89超出了ASCII字符的范畴,这是为了防止某些软件将                PNG文件当做文本文件来解决。文件中残余的局部由3个以上的PNG的数据块(Chunk)依照特定的程序组成,因而,一个规范的PNG文件构造应该如下:    PNG文件标记    PNG数据块    ……    PNG数据块    PNG数据块(Chunk)    PNG定义了两种类型的数据块,一种是称为要害数据块(critical chunk),这是规范的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。要害数据块定义了4个规范数据块,每个PNG文件都必须蕴含它们,PNG读写软件也都必须要反对这些数据块。尽管PNG文件标准没有要求PNG编译码器对可选数据块进行编码和译码,但标准提倡反对可选数据块。    下表就是PNG中数据块的类别,其中,要害数据块局部咱们应用深色背景加以辨别。
    为了简略起见,咱们假如在咱们应用的PNG文件中,这4个数据块按以上先后顺序进行存储,并且都只呈现一次。    数据块构造    PNG文件中,每个数据块由4个局部组成,如下:    名称    字节数    阐明    Length (长度)    4字节    指定数据块中数据域的长度,其长度不超过(231-1)字节    Chunk Type Code (数据块类型码)    4字节    数据块类型码由ASCII字母(A-Z和a-z)组成    Chunk Data (数据块数据)    可变长度    存储依照Chunk Type Code指定的数据    CRC (循环冗余检测)    4字节    存储用来检测是否有谬误的循环冗余码

从下面这一段解释当中我门能够看出,其实所谓的各个图像格式只不过是公布的规范不一样,那么们cpu解析的规定也不统一,同时一张图片外面蕴含了多个数据块,如下图

这是我关上的一张jpg图的数据,这时我门看到的是16进制的数据,只管咱们不晓得这些数据是什么,那么此时咱们联合上述所说,假设第一行的数据是这个jpg的标记,第2-8行可能记录的是解析规定等等信息相似,前面的为数据,那么这样去对待一张图形,咱们就能大抵明确一个意思, 标记+图像信息+数据--》最终形成一张残缺的图像,图像依据数据和所为的解析规定计算显示进去的。那么对于明天的滤镜,我门须要理解到图像当中比拟重要的两个信息色彩通道,色彩模式

3.色彩通道,色彩模式

色彩通道: 保留图像色彩信息的通道称为色彩通道。这句话是色彩通道的根本定义,我门能够了解为记录色调信息的那一段数据,每个图像都有一个或者多个色彩通道,图像中默认的色彩通道信息取决于色彩模式

色彩模式: 色彩模式我门能够了解为将某种色彩体现为数字模式的模型,或者说是一种记录图像色彩的形式。分为:RGB模式、CMYK模式、HSB模式、Lab色彩模式、位图模式、灰度模式、索引色彩模式、双色调模式和多通道模式等。

其实实际上咱们就认为,当初我要显示的色调这个时候是用数字示意,最经典的RGB模式咱们能够了解为R(255) G(0) B(0)以后这个像素,显示,在辨认的时候为红色,他由红 绿 蓝 三种色调进行混合,显示出咱们要的色彩其水平数值是0-255的范畴

总结: 也就是说,其实图像的显示,每个点都是由模式所决定的色调数值混合造成咱们想要的色彩,那么咱们的滤镜成果实现,其实实际上就是去对于色彩通道进行过滤操作,在其本来的模式数值下面进行操作,达到更改图像色调成果的目标,这就是咱们所为的滤镜

4.色彩矩阵

在android当中,他所采纳的色彩模式是RGBA模式,也就是在红绿蓝的根底上退出了Alpha透明度的概念,那么也就是他当初是一个四通道的模式。在Android当中当android将图像信息获取进去时候,以后图像的色彩通道信息他用的是一个矩阵在进行保留。用一个数组来示意的话就是

下面这里看到的是一个四通道模式的示意形式,我门会发现在

1-1
2-2
3-3
4-4

的地位都是一个1的数值,那么几个数值咱们把他了解为色彩的系数,1为本来数值不动,若0.5那么以后对应的rgba四个选项按比例解决。如果想要更改为半透明的,那么,以后a的值改为0.5就OK了红色翻一倍就改为2。然而如果在这种状况下

这个四介矩阵做不到,在android当中真正的体现形式他利用了一个4*5的矩阵

最初方退出一列,作为所为的亚元坐标,其实也就是重量值,那么上面这个色彩的矩阵如果想要将咱们的色彩值达到上诉成果,第二行的100示意在之前的色彩根底上减少100个绿色数值,那么这种是咱们最为简略的了解,而真正的他当中的实现实际上是采纳矩阵的计算

4.矩阵运算

矩阵的运算规定是矩阵A的一行乘以矩阵C的一列作为矩阵R的一行,C矩阵是图片中蕴含的ARGB信息,R矩阵是用色彩矩阵利用于C之后的新的色彩重量,运算后果如下:

R' = aR + bG + cB + dA + e;

G' = fR + gG + hB + iA + j;

B' = kR + lG + mB + nA + o;

A' = pR + qG + rB + sA + t;

色彩矩阵并不是看上去那么深奥,其实须要应用的参数很少,而且很有法则第一行决定红色第二行决定绿色
第三行决定蓝色,第四行决定了透明度,第五列是色彩的偏移量。上面是一个理论中应用的色彩矩阵。

如果把这个矩阵作用于各色彩重量的话,R=A*C,计算后会发现,各个色彩重量实际上没有任何的扭转(R'=R G'=G B'=B A'=A)。

图1.5所示矩阵计算后会发现红色重量减少100,绿色重量减少100,这样的成果就是图片偏黄,因为红色和绿色混合后失去黄色,黄色减少了100,图片当然就偏黄了。

扭转各色彩重量不仅能够通过批改第5列的色彩偏移量也可如下面矩阵所示将对应的色彩值乘以一个倍数,间接放大。上图1.6是将绿色重量乘以2变为原来的2倍。至此曾经明确了如何通过色彩矩阵来扭转各色彩重量。

5.滤镜实现

那么在对于的实现下面android的应用非常简单,只须要依赖于一个API就好

  // 色彩通道过滤    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{            1, 0,0,0,0,            0,0,0,0,0,            0,0,0,0,0,            0,0,0,1,0,    });  paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));

那么上面是我的demo代码,大家能够去试试成果

 protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    setLayerType(View.LAYER_TYPE_SOFTWARE,null);
    RectF rectF = new RectF(0,100,bitmap.getWidth(),bitmap.getHeight());    paint.reset();    paint.setColor(Color.RED);       canvas.drawBitmap(bitmap,null, rectF,paint);    // 平移运算---加法    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{            1, 0,0,0,0,            0,1,0,0,100,            0,0,1,0,0,            0,0,0,1,0,    });*/    // 反相成果 -- 底片成果   /* ColorMatrix colorMartrix = new ColorMatrix(new float[]{            -1, 0,0,0,255,            0,-1,0,0,255,            0,0,-1,0,255,            0,0,0,1,0,    });*/    // 缩放运算---乘法 -- 色彩加强    /*ColorMatrix colorMartrix = 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,    });*/    // 黑白照片    // 去色原理:只有把R G B 三通道的色调信息设置成一样,那么图像就会变成灰色,    // 同时为了保障图像亮度不变,同一个通道里的R+G+B =1    //    /*ColorMatrix colorMartrix = 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,1,0,    });*/    // 发色成果---(比方红色和绿色替换)    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{            0,1,0,0,0,            1, 0,0,0,0,            0,0,1,0,0,            0,0,0,1,0,    });*/    // 复旧成果    /*ColorMatrix colorMartrix = 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,1,0,    });*/    // 色彩通道过滤   ColorMatrix colorMartrix = new ColorMatrix(new float[]{            1, 0,0,0,0,            0,0,0,0,0,            0,0,0,0,0,            0,0,0,1,0,    });        RectF rectF2 = new RectF(600,100,600 + bitmap.getWidth(),bitmap.getHeight());    paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));        canvas.drawBitmap(bitmap,null, rectF2,paint);    }

那么对于滤镜其余的反转,光影等成果课上讲,大家能够试试这里最根底的一些操作

看完三件事❤️

如果你感觉这篇内容对你还蛮有帮忙,我想邀请你帮我三个小忙: 点赞,转发,有你们的 『点赞和评论』,才是我发明的能源。