Android Matrix类以及ColorMatri
引自:http://www.chinabaike.com/t/37396/2014/0624/2556217.html
Android Matrix类以及ColorMatrix类详解
最近在系统学习了android的图像处理(在网上搜集了一些资料并自己编写了测试程序,做了整理),现在这里做一总结:
一、ColorMatrix类
ColorMatrix是一个5x4阶的矩阵 在下面表示为A,第一行表示R红色分量,第二行表示G绿色分量,第三行表示B蓝色分量,第四行表示透明度:
用一维数组的存储方式如下: [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ],
颜色矩阵和颜色分量相乘之后得到新的颜色如下:
R‘ = a*R + b*G + c*B + d*A + e; //红色分量 G' = f*R + g*G + h*B + i*A + j; //绿色分量 B' = k*R + l*G + m*B + n*A + o; //蓝色分量 A' = p*R + q*G + r*B + s*A + t; //透明度 颜色矩阵的第五列表示各个颜色的偏移量。
下面了解下ColorMatrix的常用API:
public void set(float[] src) 将src数组的值赋给颜色矩阵A public final float[] getArray() 返回颜色矩阵A的具体数值,以一阶数组形式表示 public void setConcat(ColorMatrix matA,ColorMatrix matB) 将颜色矩阵matA和matB复合,相当与对图片进行matA矩阵处理再进行矩阵matB处理。 public void postConcat (ColorMatrix postmatrix) 若matA.postConcat(postmatrix)等价与 setConcat(postmatrix,matA)。 public void preConcat (ColorMatrix prematrix) 若matA.preConcat(prematrix)等价与 setConcat(matA,prematrix)。 public void setRotate (int axis, float degrees) 设置颜色分量旋转:axis==0旋转红色;axis==1对应绿色;axis==2对应蓝色,
源码如下:
/** * Set the rotation on a color axis by the specified values. * axis=0 correspond to a rotation around the RED color * axis=1 correspond to a rotation around the GREEN color * axis=2 correspond to a rotation around the BLUE color */ public void setRotate(int axis, float degrees) { reset(); float radians = degrees * (float)Math.PI / 180; float cosine = FloatMath.cos(radians); float sine = FloatMath.sin(radians); switch (axis) { // Rotation around the red color case 0: mArray[6] = mArray[12] = cosine; mArray[7] = sine; mArray[11] = -sine; break; // Rotation around the green color case 1: mArray[0] = mArray[12] = cosine; mArray[2] = -sine; mArray[10] = sine; break; // Rotation around the blue color case 2: mArray[0] = mArray[6] = cosine; mArray[1] = sine; mArray[5] = -sine; break; default: throw new RuntimeException(); } }
public void setSaturation (float sat) 通过改变矩阵的值设置图像的饱和度 参数0对应灰色图像,1对应没改变
public void setScale (float rScale, float gScale, float bScale, float aScale) 设置矩阵的R,G,B,A等变量到对应的倍数。
对应的api为setScale(1,2,1,1);这个函数实际对应设置的是颜色矩阵对角线上的值。
下面的例子作出了对图像的一些处理,比较简单:
private void useColorMatrix(Canvas canvas,Paint paint) { // TODO Auto-generated method stub //清除画笔的颜色过滤 paint.setColorFilter(null); cmatrix = new ColorMatrix(); cmatrix.set(carrycolor); //cmatrix.reset(); //cmatrix.setSaturation(0F); //cmatrix.setRotate(0, 100); //cmatrix.setScale(2, 2, 2, 2); //设置颜色矩阵过滤器 paint.setColorFilter(new ColorMatrixColorFilter(cmatrix)); canvas.drawBitmap(bitmap, 0,0, paint); }
二、Matrix类详解
Matrix类是一个3x3的位置坐标矩阵,该类对矩阵进行初始化必须通过reset函数或者set...等方法,
图形的放大缩小,移动,旋转,透视,扭曲这些效果都可以用该此矩阵来完成。位置矩阵A的第一行控制X坐标,第二行控制y坐标第三行控制Z坐标。
这个矩阵的作用是对坐标x,y进行变换计算结果如下:
x'=a*x+b*y+c
y'=d*x+e*y+f
由上面的公式可以看出c,f分别控制x,和y位置的偏移量,a和e控制X,与y坐标倍数的变化,所以
x放大a倍,y放大b倍,
矩阵就是:,
x方向的平移量为△x,y方向的平移量为△y,那么,点P(x,y)的坐标为:
x = x0 + △x
y = y0 + △y
采用矩阵表达上述如下:
先移动再放大用的是矩阵的乘法如A*B。
图像的旋转稍微复杂:现设点P0(x0, y0)绕原点旋转θ角后的对应点为P(x, y)。通过使用向量,我们得到如下,r为旋转半径:
x0 = r cosα
y0 = r sinα
x = r cos(α+θ) = x0 cosθ - y0 sinθ (三角函数展开然后变量替换)
y = r sin(α+θ) = x0 sinθ + y0 cosθ
于是我们得到矩阵:
图像的镜像,分为2种:水平镜像、垂直镜像。先介绍如何实现垂直镜像,什么是垂直镜像就不详细说明。图像的垂直镜像变化也可以用矩阵变化的表示,
设点P0(x0 ,y0 )进行镜像后的对应点为P(x ,y ),图像的高度为fHeight,宽度为fWidth,原图像中的P0(x0 ,y0 )经过垂直镜像后的坐标变为(x0 ,2*fHeight- y0);
x = x0 垂直镜像后x坐标不变
y = fHeight – y0 垂直镜像后相当与先将图像绕x轴旋转180度,再将图像向下平移两个图像的高度,所以先y=-y0;然后再加2倍高度
推导出相应的矩阵是:
final float f[] = {1.0F,0.0F,0.0F,0.0F,-1.0F,120.0F,0.0F,0.0F,1.0F};
Matrix matrix = new Matrix();
matrix.setValues(f);
代码如下:
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = mPaint;
//useColorMatrix(canvas,paint);
matrix = new Matrix();
matrix.setValues(carrypos);
paint.setColorFilter(null);
canvas.drawBitmap(bitmap,matrix,paint);// you can setColorFilter(null);
carrypos[5] = 2*bitmap.getHeight();//设置y坐标移动
carrypos[4] = -1;//设置绕x轴转180度
matrix.setValues(carrypos);
canvas.drawBitmap(bitmap, matrix, paint);
}
按照上述方法运行后的结果:
实际上,使用下面的方式也可以实现垂直镜像:
Matrix matrix = new Matrix();
matrix.setScale (1.0,-1.0);
matrix.postTraslate(0,2* fHeight);
Matrix学习——图像的复合变化
如果图像围绕着某个点P(a,b)旋转,则先要将坐标系平移到该点,再进行旋转,然后将旋转后的图像平移回到原来的坐标原点。
我们需要3步:
1. 平移——将坐标系平移到点P(a,b);
2. 旋转——以原点为中心旋转图像;
3. 平移——将旋转后的图像平移回到原来的坐标原点;
相比较前面说的图像的几何变化(基本的图像几何变化),这里需要平移——旋转——平移,这种需要多种图像的几何变化就叫做图像的复合变化。
设对给定的图像依次进行了基本变化F1、F2、F3…..、Fn,它们的变化矩阵分别为T1、T2、T3…..、Tn,图像复合变化的矩阵T可以表示为:T = TnTn-1…T1。
按照上面的原则,围绕着某个点(a,b)旋转θ的变化矩阵序列是:
按照上面的公式,我们列举一个简单的例子:围绕(100,100)旋转30度(sin 30 = 0.5 ,cos 30 = 0.866)
float f[]= { 0.866F, -0.5F, 63.4F,0.5F, 0.866F,-36.6F,0.0F, 0.0F, 1.0F };
matrix = new Matrix();
matrix.setValues(f);
旋转后的图像如下:
Android为我们提供了更加简单的方法,如下:
Matrix matrix = new Matrix();
matrix.setRotate(30,100,100);
矩阵运行后的实际结果:
与我们前面通过公式获取得到的矩阵完全一样。
在这里我们提供另外一种方法,也可以达到同样的效果:
float a = 100.0F,b = 100.0F;
matrix = new Matrix();
matrix.setTranslate(a,b);
matrix.preRotate(30);
matrix.preTranslate(-a,-b); //等价与matrix=matrix*T(移动相应距离的矩阵) post...(把pre的乘积因子相交换)
Matrix学习——错切变换
什么是图像的错切变换(Shear transformation)?我们还是直接看图片错切变换后是的效果:
上图是设置了x向量的第二个参数为0.5F 即x=x0+0.5y0 所以x随y的增大而成斜率为0.5的线性变化。
代码如下:
private float[]carrypos2 ={1,0,100,
0,1,100,
0,0,1};//z no change
float[] test01 = carrypos2;
test01[1] = 0.5F;
matrix.setValues(test01);
canvas.drawBitmap(bitmap, matrix, paint);
也可以這樣寫:
对图像的错切变换做个总结:
x = x0 + b*y0;
y = d*x0 + y0;
这里再次给大家介绍一个需要注意的地方:
通过以上,我们发现Matrix的setXXXX()函数,在调用时调用了一次reset(),这个在复合变换时需要注意。
Matrix学习——对称变换(反射)
什么是对称变换?具体的理论就不详细说明了,图像的镜像就是对称变换中的一种。
利用上面的总结做个具体的例子,产生与直线y= – x对称的反射图形,代码片段如下:
当前矩阵输出是:
图像变换的效果如下:
附:三角函数公式
两角和公式
sin(a+b)=sinacosb+cosasinb
sin(a-b)=sinacosb-sinbcosa
cos(a+b)=cosacosb-sinasinb
cos(a-b)=cosacosb+sinasinb
tan(a+b)=(tana+tanb)/(1-tanatanb)
tan(a-b)=(tana-tanb)/(1+tanatanb)
cot(a+b)=(cotacotb-1)/(cotb+cota)
cot(a-b)=(cotacotb+1)/(cotb-cota)
倍角公式
tan2a=2tana/[1-(tana)^2]
cos2a=(cosa)^2-(sina)^2=2(cosa)^2 -1=1-2(sina)^2
sin2a=2sina*cosa
半角公式
sin(a/2)=√((1-cosa)/2) sin(a/2)=-√((1-cosa)/2)
cos(a/2)=√((1+cosa)/2) cos(a/2)=-√((1+cosa)/2)
tan(a/2)=√((1-cosa)/((1+cosa)) tan(a/2)=-√((1-cosa)/((1+cosa))
cot(a/2)=√((1+cosa)/((1-cosa)) cot(a/2)=-√((1+cosa)/((1-cosa))
tan(a/2)=(1-cosa)/sina=sina/(1+cosa)
和差化积
2sinacosb=sin(a+b)+sin(a-b)
2cosasinb=sin(a+b)-sin(a-b) )
2cosacosb=cos(a+b)-sin(a-b)
-2sinasinb=cos(a+b)-cos(a-b)
sina+sinb=2sin((a+b)/2)cos((a-b)/2
cosa+cosb=2cos((a+b)/2)sin((a-b)/2)
tana+tanb=sin(a+b)/cosacosb
积化和差公式
sin(a)sin(b)=-1/2*[cos(a+b)-cos(a-b)]
cos(a)cos(b)=1/2*[cos(a+b)+cos(a-b)]
sin(a)cos(b)=1/2*[sin(a+b)+sin(a-b)]
诱导公式
sin(-a)=-sin(a)
cos(-a)=cos(a)
sin(pi/2-a)=cos(a)
cos(pi/2-a)=sin(a)
sin(pi/2+a)=cos(a)
cos(pi/2+a)=-sin(a)
sin(pi-a)=sin(a)
cos(pi-a)=-cos(a)
sin(pi+a)=-sin(a)
cos(pi+a)=-cos(a)
tga=tana=sina/cosa
万能公式
sin(a)= (2tan(a/2))/(1+tan^2(a/2))
cos(a)= (1-tan^2(a/2))/(1+tan^2(a/2))
tan(a)= (2tan(a/2))/(1-tan^2(a/2))
其它公式
a*sin(a)+b*cos(a)=sqrt(a^2+b^2)sin(a+c) [其中,tan(c)=b/a]
a*sin(a)-b*cos(a)=sqrt(a^2+b^2)cos(a-c) [其中,tan(c)=a/b]
1+sin(a)=(sin(a/2)+cos(a/2))^2
1-sin(a)=(sin(a/2)-cos(a/2))^2
其他非重点三角函数
csc(a)=1/sin(a)
sec(a)=1/cos(a)
双曲函数
sinh(a)=(e^a-e^(-a))/2
cosh(a)=(e^a+e^(-a))/2
tgh(a)=sinh(a)/cosh(a)
Android Matrix类以及ColorMatri的更多相关文章
- [转载]Matrix类的使用
2013-12-18 11:31:00 转载自: http://www.cnblogs.com/mmy0925/archive/2013/01/22/2871009.html 在Android中,对图 ...
- Bitmap、BitmapDrawable、BitmapFactory、Matrix类之间的关系
1.BitmapFactory是一个工具类 Bitmap实现在android.graphics包中.但是Bitmap类的构造函数是私有的,外面并不能实例化,只能是通过JNI实例化.这必然是 某个辅助类 ...
- Android Matrix(坐标矩阵)
Android Matrix 2016-02-26 14:38:10 介绍 中文名:坐标矩阵 高等数学里有介绍,在图像处理方面,主要是用于平面的缩放.平移.旋转等操作. 在Android里面,Matr ...
- android Activity类中的finish()、onDestory()和System.exit(0) 三者的区别
android Activity类中的finish().onDestory()和System.exit(0) 三者的区别 Activity.finish() Call this when your a ...
- Android图像格式类及图像转换方法
Android图像格式类及图像转换方法介绍 一款软件的开发和图像密切相关,特别是移动应用程序,在视觉效果等方面是至关重要的,因为这直接关系到用户的体验效果.在Android程序开发的过程中,了解存在哪 ...
- Android 服务类Service 的详细学习
http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建 目录(?)[+] 什么是服务 服务有 ...
- 项目源码--Android答题类游戏源码
下载源码 技术要点: 1. 精致的答题UI 2. Android的Http通信技术 3. Android数据库QLITE与其他数据存储技术 4. Android在线音乐背景技术 5. Android答 ...
- android application类的用法
android application类的用法 Application是android系统Framework提供的一个组件,它是单例模式(singleton),即每个应用只有一个实例,用来存储系统的一 ...
- [C#绘图]Matrix类
想要从入门到精通一门语言,最好的学习文档就是官方提供的文档,比如说OpenCV的学习,最权威的学习资料还是其官方的学习文档,C#和.net的最好的学习入门文档还是MSDN.但是好多人一开始真的不会用, ...
随机推荐
- txt文件的读取
两个函数:textread或importdata [textread函数] 格式:I=textread('文件名.txt','列',读取的行数,'headerlines',跳过的头行数); 返回值I ...
- ElasticSearch(5)-Mapping
一.Mapping概述 映射 为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成全文本(Full-text)或精确的字符串值,Elasticsearch需要知道每个字段里面都包含了 ...
- 如何自定义JSR-303标准的validator
在web应用中为了保证数据的有效性而对用户提交的表单数据是必需的,而前台客户端的验证例如javascript并不总是那么安全和可靠,这样我们就需要一个健壮的后台验证框架来处理这个问题.好在java发布 ...
- 转delphi中 formclose的事件 action:=cafree form:=nil分别是什么意思?
转自:http://www.cnblogs.com/jshchg/articles/1929894.html MDI子窗体关闭时用到的(以下摘自Delphi的帮助)caNone The form i ...
- php 积少成多!
- 多线程---其他方法 停止线程、守护线程、join方法
第三方停止线程: 原来是stop(),因为该方法有些问题,所以被interrupt()方法取代,它的用途跟机制是 当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除,强制让线程恢复到 ...
- hdu 5584 gcd/lcm/数学公式
input T 1<=T<=1000 x y output 有多少个起点可以走n(n>=0)步走到(x,y),只能从(x,y)走到(x,y+lcm(x,y))/(x+lcm(x,y) ...
- 关于个人网站选择虚拟主机还是VPS服务器的讨论
还记得当初才开始学习建站的时候,选择的第一款虚拟主机是全HTML的主机,那时候的虚拟主机还分为HTML或者是ASP,PHP的都很少,在国内接触的学习较多还是以ASP为主,PHP是最近几年才开始流行.如 ...
- 2016年7款最流行的Java框架
虽然Java一直被唱衰,但是直到现在Java也坚持霸主地位不动摇,毫无疑问,Java是目前最热门的编程语言之一,所以我们为大家搜集了一些目前比较受欢迎的Java框架的消息. 根据RebelLabs对在 ...
- H5的新应用-获取用户当前的地理坐标
------------------------------ <script type="text/javascript"> ...