颜色矩阵 滤镜 ColorMatrix
颜色矩阵原理
色彩的三要素1、色相。色相通俗的说就是“颜色”,色相的改变就是颜色的改变,色相的调节伴随着红橙黄绿蓝紫的变化。2、亮度。明度通俗的说就是“光照度”,明度的改变就是光照在物体上带来的改变,明度的调节伴随着越高,光越强,越泛白(就像过曝一样,往白色上偏离);越低,光越弱,越往黑里偏3、饱和度。饱和度通俗的说就是“色彩的纯度”,饱和度的改变会影响颜色的鲜艳程度,以红色为例子,越高,越接近红色,越低则越接近灰色(黑白)在编程中有时候需要对图片做特殊的处理,比如将图片做出黑白的,或者老照片的效果,有时候还要对图片进行变换,以拉伸,扭曲等等。
这些效果在android中有很好的支持,通过颜色矩阵 ColorMatrix 和坐标变换矩阵 Matrix 可以完美的做出上面的所说的效果。android中可以通过颜色矩阵 ColorMatrix 方便的操作颜色,颜色矩阵是一个5x4 的矩阵
第一行决定红色、第二行决定绿色、第三行决定蓝色、第四行决定了透明度。第五列是颜色的偏移量。
颜色矩阵以一维数组的方式存储如下:
[ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ]
他通过RGBA四个通道来直接操作对应颜色,如果会使用Photoshop就会知道有时处理图片通过控制RGBA各颜色通道来做出特殊的效果。而图像的RGBA值则存储在一个5*1的颜色分量矩阵C中,由颜色分量矩阵C可以控制图像的颜色效果![]()
要想改变一张图片的颜色效果,只需要改变图像的颜色分量矩阵即可。通过颜色矩阵可以很方便的修改图像的颜色分量矩阵。假设修改后的图像颜色分量矩阵为C1,则有如下图所示的颜色分量矩阵计算公式。矩阵的运算规则是:矩阵M的一行乘以矩阵C的一列作为矩阵R的一行。
M是颜色矩阵,C矩阵是图片中包含的RGBA信息,R矩阵是用M应用于C之后的新的颜色分量。由此可见,通过颜色矩阵修改了原图像的RGBA值,从而达到了改变图片颜色效果的目的。并且,通过上图所示的运算可知,颜色矩阵M的第一行参数abcde决定了图像的红色成分,第二行参数fghij决定了图像的绿色成分,第三行参数klmno决定了图像的蓝色成分,第四行参数pqrst决定了图像的透明度,第五列参数ejot是颜色的偏移量。通常,改变颜色分量时可以通过修改第5列的颜色偏移量来实现,如下图所示的颜色矩阵M1,通过计算后可以得知该颜色矩阵的作用是使图像的红色分量和绿色分量均增加100,这样的效果就是图片泛黄(因为红色与绿色混合后得到黄色)。除此之外,也可以通过直接对颜色值乘以某一系数而达到改变颜色分量的目的。如下图所示的颜色矩阵M2,将绿色分量放大了2倍,这样的效果就是图片泛绿色。
![]()
效果演示
调色器代码
public class MainActivity extends Activity implements OnSeekBarChangeListener, OnClickListener {private ImageView imageView;private SeekBar sb_red, sb_green, sb_blue, sb_brightness, sb_saturation;private Bitmap preBitmap, afterBitmap;private Canvas canvas;private ColorMatrix colorMatrix, rgbMatrix, huduMatrix;private Paint paint;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);imageView = (ImageView) findViewById(R.id.iv);findViewById(R.id.btn_select).setOnClickListener(this);findViewById(R.id.btn_save).setOnClickListener(this);sb_red = (SeekBar) findViewById(R.id.sb_red);sb_green = (SeekBar) findViewById(R.id.sb_green);sb_blue = (SeekBar) findViewById(R.id.sb_blue);sb_brightness = (SeekBar) findViewById(R.id.sb_brightness);sb_saturation = (SeekBar) findViewById(R.id.sb_saturation);sb_red.setOnSeekBarChangeListener(this);sb_green.setOnSeekBarChangeListener(this);sb_blue.setOnSeekBarChangeListener(this);sb_brightness.setOnSeekBarChangeListener(this);sb_saturation.setOnSeekBarChangeListener(this);paint = new Paint();colorMatrix = new ColorMatrix();//5*4的颜色矩阵rgbMatrix = new ColorMatrix();//RGB颜色及亮度huduMatrix = new ColorMatrix();//饱和度或灰度}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//进度改变时调用if (preBitmap != null) {float progressR = sb_red.getProgress() / 128f;//这里处理后值的范围为[0,2],初始值是1,也即初始时不做任何改变。float progressG = sb_green.getProgress() / 128f;float progressB = sb_blue.getProgress() / 128f;float progressA = sb_brightness.getProgress() / 128f;float progressS = sb_saturation.getProgress() / 128f;float[] values = new float[] { progressR, 0, 0, 0, 0,//0, progressG, 0, 0, 0,//0, 0, progressB, 0, 0,//0, 0, 0, progressA, 0 };////1、改变色相及亮度rgbMatrix.set(values);//2、改变饱和度、透明度、灰度。当饱和度=0时,会变成黑白图片(有灰度的黑白照片)。huduMatrix.setSaturation(progressS);//3、要想将色彩三元素综合运用到一张图片上,需要通过颜色矩阵的postConcat方法将三元素进行连接。colorMatrix.reset();//要重置一下才可以,不然等于是在之前的基础上进行的更改colorMatrix.postConcat(rgbMatrix);//这里其实是将两个矩阵进行了运算,熟悉矩阵运算的应该知道,先后顺序是有重大影响的colorMatrix.postConcat(huduMatrix);//4、通过颜色滤镜将颜色矩阵应用于图片上paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));canvas.drawBitmap(preBitmap, new Matrix(), paint);imageView.setImageBitmap(afterBitmap);} else Toast.makeText(getApplicationContext(), "清先选择一张图片再调整颜色", 0).show();}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {//开始拖动时调用}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {//结束拖动时调用}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_select: // 激活系统图库,选择一张图片Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);intent.setType("image/*");startActivityForResult(intent, 0);break;case R.id.btn_save: //保存bitmap为图片File file = new File(Environment.getExternalStorageDirectory(), new SimpleDateFormat("yyyy.MM.dd HH-mm-ss", Locale.getDefault()).format(new Date()) + ".png");try {FileOutputStream out = new FileOutputStream(file);afterBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);out.close();} catch (Exception e) {Toast.makeText(this, "保存出现异常", Toast.LENGTH_SHORT).show();e.printStackTrace();}break;}}//返回一张照片后初始化afterBitmap@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (data != null && data.getData() != null) {try {Uri uri = data.getData();// 得到图片的全路径。相机目录下的某个文件的路径为:content://media/external/images/media/12718Log.i("bqt", "路径为:" + uri);//SD卡根目录下的文某个文件的件路径为:content://media/external/images/media/12758InputStream is = getContentResolver().openInputStream(uri);//获取文件的流preBitmap = BitmapFactory.decodeStream(is); //通过流加载图片} catch (FileNotFoundException e) {}// 创建一张可以被修改的空白图片afterBitmap = Bitmap.createBitmap(preBitmap.getWidth(), preBitmap.getHeight(), preBitmap.getConfig());canvas = new Canvas(afterBitmap);canvas.drawBitmap(preBitmap, new Matrix(), paint);//先把原图绘制上去,目的仅仅是让你预览一下imageView.setImageBitmap(afterBitmap);//注意imageView上显示的不是我们本地的图片,而是我们内存中刚刚new的Bitmap}super.onActivityResult(requestCode, resultCode, data);}}
调色器布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><SeekBarandroid:id="@+id/sb_red"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="255"android:progress="128" /><SeekBarandroid:id="@+id/sb_green"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="255"android:progress="128" /><SeekBarandroid:id="@+id/sb_blue"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="255"android:progress="128" /><SeekBarandroid:id="@+id/sb_brightness"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="255"android:progress="128" /><SeekBarandroid:id="@+id/sb_saturation"android:layout_width="match_parent"android:layout_height="wrap_content"android:max="255"android:progress="128" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><Buttonandroid:id="@+id/btn_select"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="选择一张照片" /><Buttonandroid:id="@+id/btn_save"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="保存图片到SD卡" /></LinearLayout><ImageViewandroid:id="@+id/iv"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>
颜色矩阵演示
颜色矩阵代码
public class MainActivity extends Activity implements OnClickListener {private Paint myPaint;private Bitmap bitmap, alterBitmap;private Canvas canvas;private ColorMatrix myColorMatrix;private ImageView iv;private EditText[] editTextArray = new EditText[20];private float[] colorArray = new float[20];private int[] EditTextID = { R.id.Edit1, R.id.Edit2, R.id.Edit3, R.id.Edit4, R.id.Edit5, R.id.Edit6, R.id.Edit7, R.id.Edit8,R.id.Edit9, R.id.Edit10, R.id.Edit11, R.id.Edit12, R.id.Edit13, R.id.Edit14, R.id.Edit15, R.id.Edit16, R.id.Edit17,R.id.Edit18, R.id.Edit19, R.id.Edit20 };@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.Button).setOnClickListener(this);iv = (ImageView) findViewById(R.id.iv);for (int i = 0; i < 20; i++) {editTextArray[i] = (EditText) findViewById(EditTextID[i]);}myPaint = new Paint();myColorMatrix = new ColorMatrix();bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a);iv.setImageBitmap(bitmap);//先用旧图装饰一下门面}@Overridepublic void onClick(View v) {for (int i = 0; i < 20; i++) {String num = editTextArray[i].getText().toString().trim();if (TextUtils.isEmpty(num)) colorArray[i] = 0;else colorArray[i] = Float.valueOf(num);}//每提交一次都要重新设置以下alterBitmap,不然等于是在上次的基础上修改了alterBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());canvas = new Canvas(alterBitmap);//必须先把原图画上去,然后才能通过颜色矩阵修改图片的颜色canvas.drawBitmap(bitmap, new Matrix(), new Paint());//注意这里的Paint不能直接使用myPaint,否则会重复绘制颜色滤镜。当然使用之前重置一下就可以用了。//设置颜色矩阵myColorMatrix.set(colorArray);myPaint.setColorFilter(new ColorMatrixColorFilter(myColorMatrix));canvas.drawBitmap(alterBitmap, 0, 0, myPaint);iv.setImageBitmap(alterBitmap);}}
颜色矩阵布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><ImageViewandroid:id="@+id/iv"android:layout_width="match_parent"android:layout_height="200dp"android:layout_gravity="center" /><Buttonandroid:id="@+id/Button"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="提交" /><LinearLayoutandroid:id="@+id/colorlayout1"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditTextandroid:id="@+id/Edit1"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal"android:text="1" /><EditTextandroid:id="@+id/Edit2"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit3"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit4"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit5"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /></LinearLayout><LinearLayoutandroid:id="@+id/colorlayout2"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditTextandroid:id="@+id/Edit6"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit7"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal"android:text="1" /><EditTextandroid:id="@+id/Edit8"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit9"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit10"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /></LinearLayout><LinearLayoutandroid:id="@+id/colorlayout3"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditTextandroid:id="@+id/Edit11"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit12"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit13"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal"android:text="1" /><EditTextandroid:id="@+id/Edit14"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit15"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /></LinearLayout><LinearLayoutandroid:id="@+id/colorlayout4"android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditTextandroid:id="@+id/Edit16"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit17"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit18"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /><EditTextandroid:id="@+id/Edit19"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal"android:text="1" /><EditTextandroid:id="@+id/Edit20"android:layout_width="50dp"android:layout_height="40dp"android:layout_weight="1"android:numeric="decimal" /></LinearLayout></LinearLayout>
颜色矩阵 滤镜 ColorMatrix的更多相关文章
- (转)android中颜色矩阵colormatrix
原文地址:http://www.cnblogs.com/menlsh/archive/2013/02/03/2890888.html 在Android中,对图像进行颜色方面的处理,如黑白老照片.泛黄旧 ...
- ColorMatrixFilter色彩矩阵滤镜;
包 flash.filters 类 public final class ColorMatrixFilter 继承 ColorMatrixFilter BitmapFilter Object 使用 ...
- Android学习笔记之图像颜色处理(ColorMatrix)
对图像进行颜色方面的处理,通过使用颜色矩阵(ColorMatrix)来实现.从而可以达到很多特效如黑白老照片.泛黄旧照片等等. 1.颜色矩阵(ColorMatrix) 这里有详细的介绍:http:// ...
- Egret中图片颜色的改变,颜色矩阵
参考: 图片处理:颜色矩阵和坐标变换矩阵 Egret-滤镜 之前面试有问到如何改变图片的颜色.貌似之前做Flash的时候做过,做Egret后没有此类需求,所以一直没有研究过. 现在来弄一弄如何改变图片 ...
- ColorMatrixFilter色彩矩阵滤镜
ColorMatrixFilter色彩矩阵滤镜: /** * * *----------------------------------------* * | *** ColorMatrixFilte ...
- ColorMatrixFilter色彩矩阵滤镜(as3)
matrix是一个长度为4*5=20的数组,其构成如下所示: R ,G, B, A, offset [1, 0, 0, 0, 0]); // red [0, 1, 0, 0, 0 ...
- AS3 滤镜相关
<ignore_js_op> package { import flash.display.Sprite; import flash.filters.BlurF ...
- Android ColorMatrix类图像颜色处理-黑白老照片、泛黄旧照片、高对比度等效果
在Android中,对图像进行颜色方面的处理,如黑白老照片.泛黄旧照片.高对比度.低饱和度等效果,都可以通过使用颜色矩阵(ColorMatrix)来实现. 1.颜色矩阵(ColorMatrix)介绍 ...
- Android图片处理(Matrix,ColorMatrix)
转发说明:原文链接http://www.cnblogs.com/leon19870907/articles/1978065.html 在编程中有时候需要对图片做特殊的处理,比如将图片做出黑白的,或者老 ...
随机推荐
- 如何修改TextField的Label和EmptyText
在需求中常常有修改form表单的标签和空文本提示,在渲染后组件有些字符固定下来 除非使用document进行原始修改,通过查询stackflow,我介绍更方便方法 模拟场景:点击ChangeLabel ...
- MyEclipse内存不足的问题
今早打开MyEclipse莫名其妙弹出提示框,然后我各种搜索,用了网上能查到的各种办法去试图解决问题,方法包括但不限于 修改eclipse.ini .设置Default VM Arguments . ...
- 1、CentOS6.5系统安装及学习
1. CentOS6.5系统安装及学习 1.需要的工具,Vmware workstation12虚拟机,CentOS6.5 ISO镜像,选择的是32位系统. 2.下载CentOS6.5地址:htt ...
- jQuery自学笔记(二):jQuery选择器
一.简单选择器 ID选择器:$('#box') 元素标签名:$('div') 类选择器:$('.box') jQuery提供了length和size()两种方法查看返回的元素,可验证ID在页面只出现一 ...
- 监听<input/>标签行为的方法总结
一.内容改变 1.<input onchange="javascript:function()"/>方法 onchange可以替换为下面几种:oninput,onpro ...
- js获取上传的文件名
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- delphi2010 开发及调试WebService 实例
使用delphi已经10多年了,一直搞桌面程序开发,对Webservice一直很陌生,近来因工作需要,学习delphi开发WebService,担心遗忘,作此笔记. 特别感谢 中塑在线技术总监 大犇 ...
- Hibernate对象的状态和映射
一. Hibernate对象的状态 实体对象的三种状态: 1) 暂态(瞬时态)(Transient)---实体在内存中的自由存在,它与数据库的记录无关. po在DB中无记录(无副本),po和sessi ...
- C语言杂记 -- 简陋的<深入理解计算机系统>笔记
程序的表示 l 32位64位操作系统是由CPU寄存器的位数决定,即虚拟寻址的范围为2^32.2^64. l 字节的大端小端法是以字节为基本单位的:比如十进制的7在十六位机器上表示 · 地址 100 1 ...
- 【学习笔记】【Foundation】字典
字典NSDictionary: 用于保存具有映射关系的数据:key-value: 创建NSDictionary的常用方法: dictionary: dictionaryWithContentsOfFi ...


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



