http://www.cnblogs.com/leon19870907/archive/2011/03/09/1978065.html
在编E中有时候需要对囄做特D的处理Q比如将囄做出黑白的,或者老照片的效果Q有时候还要对囄q行变换Q以拉Q扭曲等{?/span>
q些效果在android中有很好的支持,通过颜色矩阵QColorMatrixQ和坐标变换矩阵QMatrixQ可以完的做出上面的所说的效果?/span>
下面分别介l这两个矩阵的用法和相关的函数?/span>
颜色矩阵
android中可以通过颜色矩阵QColorMatrixc)斚w的操作颜Ԍ颜色矩阵是一?x4 的矩阵(如图1.1Q?/p>
可以用来斚w的修改图片中RGBA各分量的|颜色矩阵以一l数l的方式存储如下Q?br /> [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ]
他通过RGBA四个通道来直接操作对应颜Ԍ如果会用Photoshop׃知道有时处理囄通过控制RGBA各颜色通道来做出特D的效果?/p>
q个矩阵寚w色的作用计算方式?.3C:

矩阵的运规则是矩阵A的一行乘以矩阵C的一列作为矩阵R的一行,
C矩阵是图片中包含的ARGB信息QR矩阵是用颜色矩阵应用于C之后的新的颜色分量,q算l果如下Q?br />
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;
颜色矩阵q不是看上去那么深奥Q其实需要用的参数很少Q而且很有规律W一行决定红色第二行军_l色
W三行决定蓝ԌW四行决定了透明度,W五列是颜色的偏U量。下面是一个实际中使用的颜色矩c?br />

如果把这个矩阵作用于各颜色分量的话,R=A*CQ计后会发玎ͼ各个颜色分量实际上没有Q何的改变(R'=R G'=G B'=B A'=A)?br />
?.5所C矩阵计后会发现红色分量增?00Q绿色分量增?00Q?/p>
q样的效果就是图片偏黄,因ؓU色和绿色合后得到黄色Q黄色增加了100Q图片当然就偏黄了?br />
改变各颜色分量不仅可以通过修改W?列的颜色偏移量也可如上面矩阵所C将对应的颜色g以一个倍数Q直接放大?/p>
上图1.6是将l色分量乘以2变ؓ原来?倍。相信读者至此已l明白了如何通过颜色矩阵来改变各颜色分量?/p>
下面~写一D代码来Q通过调整颜色矩阵来获得不同的颜色效果QJavaCode如下Q?br />复制到剪贴板 Java代码
1 CMatrixc:
2 public class CMatrix extends Activity {
3
4 private Button change;
5 private EditText [] et=new EditText[20];
6 private float []carray=new float[20];
7 private MyImage sv;
8 @Override
9 public void onCreate(Bundle savedInstanceState) {
10 super.onCreate(savedInstanceState);
11 setContentView(R.layout.main);
12
13 change=(Button)findViewById(R.id.set);
14 sv=(MyImage)findViewById(R.id.MyImage);
15
16 for(int i=0;i<20;i++){
17
18 et[i]=(EditText)findViewById(R.id.indexa+i);
19 carray[i]=Float.valueOf(et[i].getText().toString());
20 }
21
22 change.setOnClickListener(l);
23 }
24
25 private Button.OnClickListener l=new Button.OnClickListener(){
26
27 @Override
28 public void onClick(View arg0) {
29 // TODO Auto-generated method stub
30 getValues();
31 sv.setValues(carray);
32 sv.invalidate();
33 }
34
35 };
36 public void getValues(){
37 for(int i=0;i<20;i++){
38
39 carray[i]=Float.valueOf(et[i].getText().toString());
40 }
41
42 }
43
44
45 }
46 MyImagecȝ承自Viewc:
47 public class MyImage extends View {
48 private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
49 private Bitmap mBitmap;
50 private float [] array=new float[20];
51
52 private float mAngle;
53
54 public MyImage(Context context,AttributeSet attrs) {
55 super(context,attrs);
56
57 mBitmap = BitmapFactory.decodeResource(context.getResources(),
58 R.drawable.test);
59 invalidate();
60 }
61
62
63 public void setValues(float [] a){
64 for(int i=0;i<20;i++){
65 array[i]=a[i];
66 }
67
68 }
69
70 @Override protected void onDraw(Canvas canvas) {
71 Paint paint = mPaint;
72
73
74
75 paint.setColorFilter(null);
76 canvas.drawBitmap(mBitmap, 0, 0, paint);
77
78 ColorMatrix cm = new ColorMatrix();
79 //讄颜色矩阵
80 cm.set(array);
81 //颜色滤镜Q将颜色矩阵应用于图?
82 paint.setColorFilter(new ColorMatrixColorFilter(cm));
83 //l图
84 canvas.drawBitmap(mBitmap, 0, 0, paint);
85 Log.i("CMatrix", "--------->onDraw");
86
87
88 }
89
90 }
CMatrixcM要负?接收颜色矩阵的设|和重绘Q没有要说的。MyImagecMq行l图工作Q首先设|颜色矩阵cm.set(..)从一l数l中d数据20个数据给颜色?阵赋|paint.setColorFilter(..)讄颜色滤镜Q然后绘图,效果出来了Q这个过E和PS差不多)如下Q?/span>




看到q里Q相信大家对颜色矩阵的作用已l有了一个直观的感受Q现在也可以试做一个照片特效的软g?/span>
但是各种效果q不能让用户手动调节颜色矩阵Q这里需要计公式,׃本hq不是做囑Ş软g的也不能提供Q可以参考这个链接:
http://www.adobe.com/devnet/flash/articles/matrix_transformations/ColorMatrixDemo.swf
坐标变换矩阵
坐标变换矩阵是一?*3的矩阵如?.1Q用来对囑Şq行坐标变化Q将原来的坐标点转移到新的坐标点Q?/span>
因ؓ一个图片是有点阵和每一点上的颜色信息组成的Q所以对坐标的变换,是Ҏ一点进行搬UdŞ成新的图片?/span>
具体的说囑Ş的放大羃,UdQ旋转,透视Q扭曲这些效果都可以用此矩阵来完成?/span>

q个矩阵的作用是对坐标x,yq行变换计算l果如下Q?/span>
x'=a*x+b*y+c
y'=d*x+e*y+f
通常情况下g=h=0,q样?=0*x+0*y+1恒成立。和颜色矩阵一P坐标变换矩阵真正使用的参数很也很有规律?/span>

上图是一个坐标变换矩늚单例子,计算后发现x'=x+50,y'=y+50.
可见囄的每一炚w在x和y方向上^Ud了(50Q?0Q点处,q种效果是q移效果Q将囄转移CQ?0Q?0Q处?/span>

计算上面得矩阵x'=2*x,y‘=2*y.l过颜色矩阵和上面{UL果学习,怿读者可以明白这个矩늚作用了,q个矩阵对图片进行了攑֤Q具体的说是攑֤了二倍?/span>
下面介l几U常用的变换矩阵Q?/span>
1. 旋{

l原炚w时针旋?#952;度角的变换公式是 x' = xcosθ − ysinθ ?y? = xsinθ + ycosθ
2. ~放

变换后长宽分别放大x'=scale*x;y'=scale*y.
3. 切变

4. 反射

( , )单位向量
5. 正投?br />
( , )单位向量
上面的各U效果也可以叠加在一P既矩늚l合变换Q可以用矩阵乘法实现之,如:R=B(A*C)=(B*A)C,注意一点就是B*A和A*B一般是不等的?/p>
下面编一个小E序Q通过控制坐标变换矩阵来达到控制图形的目的QJavaCode如下Q?br />
复制到剪贴板 Java代码
CooMatrixc:
2
3public class CooMatrix extends Activity {
4
5 private Button change;
6 private EditText [] et=new EditText[9];
7 private float []carray=new float[9];
8 private MyImage sv;
9 /** Called when the activity is first created. */
10 @Override
11 public void onCreate(Bundle savedInstanceState) {
12 super.onCreate(savedInstanceState);
13 setContentView(R.layout.main);
14
15 change=(Button)findViewById(R.id.set);
16 sv=(MyImage)findViewById(R.id.MyImage);
17
18 for(int i=0;i<9;i++){
19
20 et[i]=(EditText)findViewById(R.id.indexa+i);
21 carray[i]=Float.valueOf(et[i].getText().toString());
22
23 }
24
25 change.setOnClickListener(l);
26
27
28 }
29
30 private Button.OnClickListener l=new Button.OnClickListener(){
31
32 @Override
33 public void onClick(View arg0) {
34 // TODO Auto-generated method stub
35 getValues();
36 sv.setValues(carray);
37 sv.invalidate();
38 }
39
40 };
41 public void getValues(){
42 for(int i=0;i<9;i++){
43
44 carray[i]=Float.valueOf(et[i].getText().toString());
45 }
46
47 }
48
49
50}
51MyImagecȝ承自Viewc:
52public class MyImage extends View {
53 private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
54 private Bitmap mBitmap;
55 private float [] array=new float[9];
56
57
58
59 public MyImage(Context context,AttributeSet attrs) {
60 super(context,attrs);
61
62 mBitmap = BitmapFactory.decodeResource(context.getResources(),
63 R.drawable.ic_launcher_android);
64 invalidate();
65 }
66
67
68 public void setValues(float [] a){
69 for(int i=0;i<9;i++){
70 array[i]=a[i];
71 }
72
73 }
74
75 @Override protected void onDraw(Canvas canvas) {
76 Paint paint = mPaint;
77 canvas.drawBitmap(mBitmap, 0, 0, paint);
78 //new 一个坐标变换矩?
79 Matrix cm = new Matrix();
80//为坐标变换矩阵设|响应的?
81 cm.setValues(array);
82//按照坐标变换矩阵的描q绘?
83 canvas.drawBitmap(mBitmap, cm, paint);
84 Log.i("CMatrix", "--------->onDraw");
85
86
87 }
88
89
上面的代码中cCooMatrix用于接收用户输入的坐标变换矩阵参敎ͼcMyImage接收参数Q通过setValues()讄矩阵参数Q然后Canvas调用drawBitmapl图。效果如下:



上面l出了用坐标变换矩阵做出的各U效果,用坐标变换矩阵可以方面的调节囑Ş的各U效果,
但是我们看看Matrixcd可以发现Q实际上QmatrixcLw已l提供了许多cM的方法,我们只要调用Q就可以了?/span>
setScale(float sx, float sy, float px, float py) 攑֤
setSkew(float kx, float ky, float px, float py) 斜切
setTranslate(float dx, float dy) q移
setRotate(float degrees, float px, float py) 旋{
上面的函数提供了基本的变换^U,攑֤Q旋转,斜切。ؓ了做出更复杂的变换,同时不必亲手L动坐标变换矩阵,
MatrixcL供了许多MapҎQ将原图形映到目标Ҏ成新的图形,
下面qsetPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) 的用法,希望起到举一反三的作用?/span>
参数src和dst是分别存储了原图像的点和和指定的目标点的一l数l,数组中存储的坐标格式如下Q?/span>
[x0, y0, x1, y1, x2,y2,...]
q个个函数将src中的坐标映射到dst中的坐标Q实现图像的变换?/span>
具体的例子可以参考APIDemos里的PolyToPolyQ我在这里就不再贴代码了Q只讲一下函数是怎么变换囄的。下面是效果Q?/span>

图中?的是原图Q写?Q?Q?的是变换后的囑Ş。现在分?是怎么变换来的Q变换的原坐标点和目的坐标点如下Q?/span>
src=new float[] { 32, 32, 64, 32 }
dst=new float[] { 32, 32, 64, 48 }

?上图标示出的坐标看出原图的(32Q?2Q映到原图的(32Q?2Q,Q?4Q?2Q映到原图Q?4Q?8Q这L效果是图像放大了而且发生了旋转?q样的过E相当于Q?2Q?2Q点不动Q然后拉住图形(64Q?2Q点q拉刎ͼ64Q?8Q点处,q样囑Ş必然会被拉攑֤q且发生旋{。最后用一个^U?图形移动到双现在的位|。希望能够好好理解这一q程Q下面的3Q?图是同样的道理?/span>