Android色彩特效处理之色调、饱和度、亮度、ColorMatrix精炼详解
一、前期基础知识储备
Bitmap(位图文件),扩展名可以是.bmp或者.dib。位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2、4、8、16、24和32位色彩。想象一下你以前测红绿色盲的时候,王医生拿给你看的那张红红绿绿小动物数字交通工具的图,那就是一个位图图片,由一个个像素组成。
一个位图图像的一个像素点,用RGBA四个值来描述,具体控制是通过一个4*5的矩阵来控制,每个像素点的RGBA又共同组成了位图的展现形式,这就意味着只要我们能控制像素点的RGBA值,就可以改变位图展示的效果。
基于此,Android中常用的对于图像色彩处理的常用方式有两种:
①使用ColorMatrix类来改变RGBA;
②使用专业的像素点算法来定点来改变RGBA。
二、上代码,具体实现通过ColorMatrix类进行色彩处理
我们需要知道在通常的色彩处理中,我们使用以下的专业词汇来描述一个图像:
色调——物体传播的颜色;
饱和度——颜色的纯度,从0(灰)到100%(饱和)来进行描述;
亮度——颜色的相对明暗程度;
在Android中,系统使用一个颜色矩阵——ColorMatrix,来处理图像的这些色彩效果。Android中的颜色矩阵是一个4×5的数字矩阵,它用来对图片的色彩进行处理。而对于每个像素点,都有一个颜色分量矩阵用来保存颜色的RGBA值,如下图所示:
在这个4×5的颜色矩阵中按以下方式划分:
第一行的abcde值用来决定新的颜色值中的R——红色
第二行的fghij值用来决定新的颜色值中的G——绿色
第三行的klmno值用来决定新的颜色值中的B——蓝色
第四行的pqrst值用来决定新的颜色值中的A——透明度
矩阵A中的第五列——ejot值分别用来决定每个分量重的offset,即偏移量。
1)色彩矩阵变化举例:
①改变偏移量
在这个矩阵中修改了R,G所对应的颜色偏移量,那么最后的处理结果就是图像的红色,绿色分量增加了100。而我们知道,红色混合绿色会得到黄色,所以使得整个图像的色调偏黄色。
②改变颜色系数
在这个矩阵中,改变了G分量所对应的系数g,这样的矩阵运算后G分量会变成以前的两倍,最终效果就是图像的色调更加偏绿。
2)使用ColorMatrix类来实现色彩处理:
图像的色调,饱和度,亮度这三个属性在图像处理中的使用非常多,因此颜色矩阵中,也封装了一些API来快速调用这些参数,而不用每次都去计算矩阵的值。
在Android中,系统封装了一个类——ColorMatrix,也就是说前面的颜色矩阵。通过这个类,可以很方便地改变矩阵值来处理颜色效果。官方文档中给出了三种ColorMatrix的构造方法:
ColorMatrix()
Create a new colormatrix initialized to identity (as if reset() had been called).
ColorMatrix(float[] src)
Create a new colormatrix initialized with the specified array of values.
ColorMatrix(ColorMatrix src)
Create a new colormatrix initialized with the specified colormatrix.
//通常情况下使用第一种即可,即ColorMatrix colorMatrix = new ColorMatrix();
①对于色调的处理,色调是传播出的颜色,所以RGB三个值都可以进行处理,Android系统提供了setRotate(int axis, float degree)来帮助我们设置颜色的色调。第一个参数,系统分别使用0、1、2来代表Red、Green、Blue三种颜色的处理;而第二个参数,就是需要处理的值,代码如下:
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix .setRotate(0,hue0);
hueMatrix .setRotate(1,hue1);
hueMatrix .setRotate(2,hue2);
②对于饱和度的处理,Android系统提供了setSaturation(float sat)方法来设置颜色的饱和度,参数代表设置颜色饱和度的值,当饱和度为0时,图像就变成灰度图像了,代码如下:
ColorMatrix saturationMatrix=new ColorMatrix();
saturationMatrix.setSaturation(saturation);
③对于亮度的处理,当三原色以相同的比例进行混合的时候,就会显示出白色,系统正式使用这个原理来改变一个图像的亮度的,代码如下,当亮度为0时,图像就变成全黑了,处理的代码如下:
ColorMatrix lumMatrix=new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);
④色彩的混合处理,除了单独使用上面三种方式来进行颜色效果的处理之外,Android系统还封装了矩阵的乘法运算。它提供了postConcat()方法来将矩阵的作用效果混合,从而叠加处理效果,代码如下:
//将矩阵的作用效果混合,从而叠加处理效果
ColorMatrix imageMatrix=new ColorMatrix();
imageMatrix.posConcat(hueMatrix);
imageMatrix.posConcat(saturationMatrix);
imageMatrix.posConcat(lumMatrix);paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(bitmap,0,0,paint);
最后通过paint.setColorFilter(newColorMatrixColorFilter(imageMatrix))设置给paint,并使用这个画笔来绘制原来的图像,从而将颜色矩阵作用到原图上,代码如下:
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(bitmap,0,0,paint);
下面给出《Android群英传》中通过SeekBar调整色彩的经典代码段:
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener{private static final int MAX_VALUE = 255;private static final int MID_VALUE = 127;private ImageView mImageView;private float mHue, mSaturation, mLum;private Bitmap mBitmap;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.shuicai);mImageView = (ImageView) findViewById(R.id.imageview);SeekBar seekBarHue = (SeekBar) findViewById(R.id.seekbarHue);SeekBar seekBarSaturation = (SeekBar) findViewById(R.id.seekbarSaturation);SeekBar seekBarLum = (SeekBar) findViewById(R.id.seekbarLum);seekBarHue.setOnSeekBarChangeListener(this);seekBarSaturation.setOnSeekBarChangeListener(this);seekBarLum.setOnSeekBarChangeListener(this);//设置最大值seekBarHue.setMax(MAX_VALUE);seekBarSaturation.setMax(MAX_VALUE);seekBarLum.setMax(MAX_VALUE);//设置进度seekBarHue.setProgress(MID_VALUE);seekBarSaturation.setProgress(MID_VALUE);seekBarLum.setProgress(MID_VALUE);mImageView.setImageBitmap(mBitmap);}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {switch (seekBar.getId()) {case R.id.seekbarHue://色调mHue = (progress - MID_VALUE) * 1.0f / MID_VALUE * 180;break;case R.id.seekbarSaturation://饱和度mSaturation = progress * 1.0f / MID_VALUE;break;case R.id.seekbarLum://亮度mLum = progress * 1.0f / MID_VALUE;break;}mImageView.setImageBitmap(ImageHelper.handleImageEffect(mBitmap, mHue, mSaturation, mLum));}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}
}
public class ImageHelper {public static Bitmap handleImageEffect(Bitmap bm, float hue, float saturation, float lum) {//设置颜色的色调ColorMatrix hueMatrix = new ColorMatrix();//第一个参数,系统分别使用0、1、2来代表Red、Green、Blue三种颜色的处理;而第二个参数,就是需要处理的值hueMatrix.setRotate(0, hue);hueMatrix.setRotate(1, hue);hueMatrix.setRotate(2, hue);//设置颜色的饱和度ColorMatrix saturationMatrix = new ColorMatrix();//saturation参数即代表设置颜色的饱和度的值,当饱和度为0时,图像就变成灰度图像了saturationMatrix.setSaturation(saturation);//设置颜色的亮度ColorMatrix lumMatrix = new ColorMatrix();lumMatrix.setScale(lum, lum, lum, 1);//将矩阵的作用效果混合,从而叠加处理效果ColorMatrix imageMatrix = new ColorMatrix();imageMatrix.postConcat(hueMatrix);imageMatrix.postConcat(saturationMatrix);imageMatrix.postConcat(lumMatrix);/*** 设置好处理的颜色矩阵后,通过使用Paint类的setColorFilter()方法,将通过imageMatrix构造的* ColorMatrixColorFilter对象传递进去,并使用这个画笔来绘制原来的图像,从而将颜色矩阵作用到原图中*/Paint paint = new Paint();paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));/*** Android系统也不允许直接修改原图,类似Photoshop中的锁定,必须通过原图创建一个同样大小的Bitmap,并将* 原图绘制到该Bitmap中,以一个副本的形式来修改图像。*/Bitmap bitmap = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);canvas.drawBitmap(bm, 0, 0 ,paint);return bitmap;}
}
三、上代码,具体实现通过像素点算法进行色彩处理
作为更加精确的图像处理方式,可以通过改变每个像素点的具体RGBA值,来达到处理一张图像效果的目的。这里要注意的是传递进来的原始图片是不能修改的,一般根据原始图片生成一张新的图片来进行修改。
在Android中,系统提供了Bitmap.getPixels()方法来帮我们提取整个Bitmap中的像素点,并保存到一个数组中:
bitmap.getPixels(pixels,offset,stride,x,y,width,height);
这几个参数的含义如下:
pixels——接收位图颜色值的数组
offset——写入到pixels[]中的第一个像素索引值
stride——pixels[]中的行间距
x——从位图中读取的第一个像素的x坐标值
y——从位图中读取的第一个像素的y坐标值
width——从每一行中读取的像素宽度
height——读取的行数
通常情况下,可以使用如下代码:
bitmap.getPixels(oldPx,0,bm.getWidth(),0,0,width,height);
接下来就可以获取每个像素具体的ARGB了,如下:
color=oldPx[i];
r=Color.red(color);
g=Color.green(color);
b=Color.blue(color);
a=Color.alpha(color);
当获取到具体的颜色值后,就可以通过相应的算法来修改它的ARGB值。如下老照片效果效果:
r1=(int)(0.393*r+0.769*g+0.189*b);
g1=(int)(0.349*r+0.686*g+0.168*b);
b1=(int)(0.272*r+0.534*g+0.131*b);
再通过如下代码将新的RGBA值合成像素点:
newPx[i]=Color.argb(a,r1,g1,b1);
最后通过如下代码,将处理后的像素点数组重新set给我们的Bitmap,从而达到图像处理的目的:
bitmap.setPixels(newPx,0,width,0,0,width,height);
下面以《Android群英传》中底片效果为例,具体实现:
public static Bitmap handleImageNegative(Bitmap bm){int width = bm.getWidth();int height - bm.getHeight();int color;int r,g,b,a;Bitmap bmp=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);int[]oldPx=new int[width * height];int[]newPx=new int[width * height];bm.getPixels(oldPx,0,width,0,0,width,height);for(int i=0;i<width * height;i++){color=oldPx[i];r=Color.red(color);g=Color.green(color);b=Color.blue(color);a=Color.alpha(color);//r=255-r;g=255-g;b=255-b;if(r>255){r=255;}else if(r<0){r=0;} if(g>255){g=255;}else if(g<0){g=0;}if(b>255){b=255;}else if(b<0){b=0;}newPx[i]=Color.argb(a,r,g,b);}bmp.setPixels(newPx,0,width,0,0,widht,height);return bmp;
}
Android色彩特效处理之色调、饱和度、亮度、ColorMatrix精炼详解相关推荐
- Android四大组件之——Activity的生命周期(图文详解)
转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai 联系方式:JohnTsai.Work@gmail.com [Andro ...
- android相册和拍照并裁剪图片大小,Android 拍照并对照片进行裁剪和压缩实例详解...
Android 拍照并对照片进行裁剪和压缩实例详解 本文主要介绍 Android 调用摄像头拍照并对照片进行裁剪和压缩,文中给出了主要步骤和关键代码. 调用摄像头拍照,对拍摄照片进行裁剪,代码如下. ...
- Android基础入门教程——2.3.1 TextView(文本框)详解
Android基础入门教程--2.3.1 TextView(文本框)详解 标签(空格分隔): Android基础入门教程 本节引言: 学习完Android中的六大布局,从本节开始我们来一个个讲解And ...
- Android studio 多渠道(多环境)打包grade配置详解
Android studio 多渠道(多环境)打包grade配置详解 场景:开发app,我们需要两套环境或者两套环境以上的apk,每套环境的apk分两个版本debug版和release版. 公司有套平 ...
- Android Studio CPU profiler性能分析工具介绍和使用详解
Android Studio CPU profiler性能分析工具介绍和使用详解 CPU profiler介绍 Android Studio CPU 性能剖析器可实时检查应用的 CPU 使用率和线程活 ...
- android自定义圆角进度条,Android自定义进度条的圆角横向进度条实例详解
1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色, ...
- Android Studio打不开虚拟机,两种情况详解
Android Studio打不开虚拟机,两种情况详解 文章目录 Android Studio打不开虚拟机,两种情况详解 1.VT-x is disabled in BIOS 2.Emulator文件 ...
- Android中LayoutParams类精炼详解
一.前期基础知识储备 首先看几个使用LayoutParams的实例: 1.<Android开发艺术探索>第8章,Java代码中动态设置按钮时 通过LayoutParams参数设置按钮位置x ...
- 修改图片颜色 色相 饱和度 亮度 ColorMatrix
Android开发中经常会遇到一些简单的图片处理,比如修改图片的颜色,饱和度,亮度等.今天就给大家介绍一下简单的图片处理. 基础知识 颜色的三要素 色调(色相/颜色):物体的颜色: 饱和度(彩度):色 ...
最新文章
- 通过显微镜,人们又看到了一个活生生的但是肉眼看不到的世界。透过成千上万的点击数据,在线世界也就变得更为鲜活,更有意义了。...
- 盘点数据科学20个最好的Python库(附链接)
- Eclipse使用Maven时出现:Index downloads are disabled, search results may be incomplete.问题解决...
- 八数码(康拓展开标记)及类似题
- 用mapXtreme Java开发web gis应用 (上)
- redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
- 【Python】过滤数组中的空值(空字符串''和None)
- 免费的数字图书馆_不仅是书籍:您当地图书馆可能提供的所有免费数字资料
- Java EE 7发布–反馈和新闻报道
- 第五——十三章的作业
- 前端学习(2690):重读vue电商网站11之使用树形控件 el-tree
- 8天玩转并行开发——第六天 异步编程模型
- 【java学习之路】(javaWeb【后端】篇)004.Thymeleaf
- 1180魔方阵(每日学习)宁波大学OJ
- ng bind html br,使用PrimeNG开发angular web项目
- 戴尔Dell笔记本Ins-5510 U盘安装操作系统的方法
- 亚控科技笔试面试记录
- JDBC userenv('LANG')
- 2021年十大开源web应用防火墙
- 3D MAX 安装中的一些问题 一直初始化、闪退