一、前期基础知识储备

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精炼详解相关推荐

  1. Android四大组件之——Activity的生命周期(图文详解)

        转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:JohnTsai.Work@gmail.com       [Andro ...

  2. android相册和拍照并裁剪图片大小,Android 拍照并对照片进行裁剪和压缩实例详解...

    Android 拍照并对照片进行裁剪和压缩实例详解 本文主要介绍 Android 调用摄像头拍照并对照片进行裁剪和压缩,文中给出了主要步骤和关键代码. 调用摄像头拍照,对拍摄照片进行裁剪,代码如下. ...

  3. Android基础入门教程——2.3.1 TextView(文本框)详解

    Android基础入门教程--2.3.1 TextView(文本框)详解 标签(空格分隔): Android基础入门教程 本节引言: 学习完Android中的六大布局,从本节开始我们来一个个讲解And ...

  4. Android studio 多渠道(多环境)打包grade配置详解

    Android studio 多渠道(多环境)打包grade配置详解 场景:开发app,我们需要两套环境或者两套环境以上的apk,每套环境的apk分两个版本debug版和release版. 公司有套平 ...

  5. Android Studio CPU profiler性能分析工具介绍和使用详解

    Android Studio CPU profiler性能分析工具介绍和使用详解 CPU profiler介绍 Android Studio CPU 性能剖析器可实时检查应用的 CPU 使用率和线程活 ...

  6. android自定义圆角进度条,Android自定义进度条的圆角横向进度条实例详解

    1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色, ...

  7. Android Studio打不开虚拟机,两种情况详解

    Android Studio打不开虚拟机,两种情况详解 文章目录 Android Studio打不开虚拟机,两种情况详解 1.VT-x is disabled in BIOS 2.Emulator文件 ...

  8. Android中LayoutParams类精炼详解

    一.前期基础知识储备 首先看几个使用LayoutParams的实例: 1.<Android开发艺术探索>第8章,Java代码中动态设置按钮时 通过LayoutParams参数设置按钮位置x ...

  9. 修改图片颜色 色相 饱和度 亮度 ColorMatrix

    Android开发中经常会遇到一些简单的图片处理,比如修改图片的颜色,饱和度,亮度等.今天就给大家介绍一下简单的图片处理. 基础知识 颜色的三要素 色调(色相/颜色):物体的颜色: 饱和度(彩度):色 ...

最新文章

  1. 通过显微镜,人们又看到了一个活生生的但是肉眼看不到的世界。透过成千上万的点击数据,在线世界也就变得更为鲜活,更有意义了。...
  2. 盘点数据科学20个最好的Python库(附链接)
  3. Eclipse使用Maven时出现:Index downloads are disabled, search results may be incomplete.问题解决...
  4. 八数码(康拓展开标记)及类似题
  5. 用mapXtreme Java开发web gis应用 (上)
  6. redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
  7. 【Python】过滤数组中的空值(空字符串''和None)
  8. 免费的数字图书馆_不仅是书籍:您当地图书馆可能提供的所有免费数字资料
  9. Java EE 7发布–反馈和新闻报道
  10. 第五——十三章的作业
  11. 前端学习(2690):重读vue电商网站11之使用树形控件 el-tree
  12. 8天玩转并行开发——第六天 异步编程模型
  13. 【java学习之路】(javaWeb【后端】篇)004.Thymeleaf
  14. 1180魔方阵(每日学习)宁波大学OJ
  15. ng bind html br,使用PrimeNG开发angular web项目
  16. 戴尔Dell笔记本Ins-5510 U盘安装操作系统的方法
  17. 亚控科技笔试面试记录
  18. JDBC userenv('LANG')
  19. 2021年十大开源web应用防火墙
  20. 3D MAX 安装中的一些问题 一直初始化、闪退

热门文章

  1. 一个不错的shell 脚本教程 (国)
  2. 戴尔计算机专业推荐笔记本电脑,戴尔笔记本推荐
  3. 字节跳动面试--二面算法题复盘
  4. 统计学方差,中位数,方差,标准差,协方差等的计算
  5. Windows10系统部分软件出现中文乱码解决方法
  6. win10 可以复制但无法粘贴的问题
  7. (原创)关于中国象棋的
  8. H 小P的数学问题(分块)
  9. 微信小程序仿网易云音乐(使用云开发,提供源码)
  10. iOS 应用内购买(In-App Purchase)之开发