Android圖片處理(Matrix,ColorMatrix) - 轉載

Android圖片處理(Matrix,ColorMatrixhtml

轉載自:http://www.cnblogs.com/leon19870907/articles/1978065.htmlandroid

 

在編程中有時候須要對圖片作特殊的處理,好比將圖片作出黑白的,或者老照片的效果,有時候還要對圖片進行變換,以拉伸,扭曲等等。編程

這些效果在android中有很好的支持,經過顏色矩陣(ColorMatrix)和座標變換矩陣(Matrix)能夠完美的作出上面的所說的效果。canvas

下面將分別介紹這兩個矩陣的用法和相關的函數。小程序

顏色矩陣
android
中能夠經過顏色矩陣(ColorMatrix類)方面的操做顏色,顏色矩陣是一個5x4 的矩陣(如圖1.1
數組

能夠用來方面的修改圖片中RGBA各份量的值,顏色矩陣以一維數組的方式存儲以下:
 [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ]
他經過RGBA四個通道來直接操做對應顏色,若是會使用Photoshop就會知道有時處理圖片經過控制RGBA各顏色通道來作出特殊的效果。
ide

這個矩陣對顏色的做用計算方式如1.3示:


矩陣的運算規則是矩陣A的一行乘以矩陣C的一列做爲矩陣R的一行,
函數

C矩陣是圖片中包含的ARGB信息,R矩陣是用顏色矩陣應用於C以後的新的顏色份量,運算結果以下:
 
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;
 
顏色矩陣並非看上去那麼深奧,其實須要使用的參數不多,並且頗有規律第一行決定紅色第二行決定綠色
學習

第三行決定藍色,第四行決定了透明度,第五列是顏色的偏移量。下面是一個實際中使用的顏色矩陣。


若是把這個矩陣做用於各顏色份量的話,R=A*C,計算後會發現,各個顏色份量實際上沒有任何的改變(R'=R G'=G B'=B A'=A)

1.5所示矩陣計算後會發現紅色份量增長100,綠色份量增長100
spa

這樣的效果就是圖片偏黃,由於紅色和綠色混合後獲得黃色,黃色增長了100,圖片固然就偏黃了。

改變各顏色份量不只能夠經過修改第5列的顏色偏移量也可如上面矩陣所示將對應的顏色值乘以一個倍數,直接放大。

上圖1.6是將綠色份量乘以2變爲原來的2倍。相信讀者至此已經明白瞭如何經過顏色矩陣來改變各顏色份量。

下面編寫一段代碼來,經過調整顏色矩陣來得到不一樣的顏色效果,JavaCode以下:
複製到剪貼板  Java代碼

1 CMatrix類: 
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 MyImage
類繼承自View類: 
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 //
顏色濾鏡,將顏色矩陣應用於圖片 
82 paint.setColorFilter(new ColorMatrixColorFilter(cm)); 
83 //
繪圖 
84 canvas.drawBitmap(mBitmap, 0, 0, paint); 
85 Log.i("CMatrix", "--------->onDraw"); 
86 
87 
88 } 
89 
90 }

 

 

CMatrix類主要負責接收顏色矩陣的設置和重繪,沒有要說的。MyImage類中進行繪圖工做,首先設置顏色矩陣cm.set(..)從一維數組中讀取數據20個數據給顏色矩陣賦值,paint.setColorFilter(..)設置顏色濾鏡,而後繪圖,效果就出來了(這個過程和PS差很少)以下:





看到這裏,相信你們對顏色矩陣的做用已經有了一個直觀的感覺,如今也能夠嘗試作一個照片特效的軟件。

可是各類效果並不能讓用戶手動調節顏色矩陣,這裏須要計算公式,因爲本人並非作圖形軟件的也不能提供,能夠參考這個連接:
http://www.adobe.com/devnet/flash/articles/matrix_transformations/ColorMatrixDemo.swf


座標變換矩陣
座標變換矩陣是一個3*3的矩陣如圖2.1,用來對圖形進行座標變化,將原來的座標點轉移到新的座標點,

由於一個圖片是有點陣和每一點上的顏色信息組成的,因此對座標的變換,就是對每一點進行搬移造成新的圖片。

具體的說圖形的放大縮小,移動,旋轉,透視,扭曲這些效果均可以用此矩陣來完成。


這個矩陣的做用是對座標x,y進行變換計算結果以下:
x'=a*x+b*y+c
y'=d*x+e*y+f
一般狀況下g=h=0,這樣使1=0*x+0*y+1恆成立。和顏色矩陣同樣,座標變換矩陣真正使用的參數不多也頗有規律。


上圖就是一個座標變換矩陣的簡單例子,計算後發現x'=x+50,y'=y+50.

可見圖片的每一點都在xy方向上平移到了(5050)點處,這種效果就是平移效果,將圖片轉移到了(5050)處。

計算上面得矩陣x'=2*x,y'=2*y.通過顏色矩陣和上面轉移效果學習,相信讀者能夠明白這個矩陣的做用了,這個矩陣對圖片進行了放大,具體的說是放大了二倍。
下面將介紹幾種經常使用的變換矩陣:
1.      旋轉


繞原點逆時針旋轉θ度角的變換公式是 x' = xcosθ − ysinθ y' = xsinθ +    ycosθ
2.      縮放


變換後長寬分別放大x'=scale*x;y'=scale*y.
3.        
切變


4.        
反射

( , )
單位向量
5.        
正投影

( , )
單位向量
 
上面的各類效果也能夠疊加在一塊兒,既矩陣的組合變換,能夠用矩陣乘法實現之,如:R=B(A*C)=(B*A)C,注意一點就是B*AA*B通常是不等的。

下面將編一個小程序,經過控制座標變換矩陣來達到控制圖形的目的,JavaCode以下:

複製到剪貼板  Java代碼

1

CooMatrix類: 
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
51MyImage
類繼承自View類: 
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//
按照座標變換矩陣的描述繪圖 
83 canvas.drawBitmap(mBitmap, cm, paint); 
84 Log.i("CMatrix", "--------->onDraw"); 
85 
86 
87 } 
88 
89

}



上面的代碼中類CooMatrix用於接收用戶輸入的座標變換矩陣參數,類MyImage接收參數,經過setValues()設置矩陣參數,而後Canvas調用drawBitmap繪圖。效果以下:





上面給出了用座標變換矩陣作出的各類效果,用座標變換矩陣能夠方面的調節圖形的各類效果,

可是咱們看看Matrix類就能夠發現,實際上,matrix類自己已經提供了許多相似的方法,咱們只要調用,就能夠了。
 
setScale(float sx, float sy, float px, float py) 放大 
setSkew(float kx, float ky, float px, float py) 斜切 
setTranslate(float dx, float dy)                       平移 
setRotate(float degrees, float px, float py)    旋轉 
 
上面的函數提供了基本的變換平移,放大,旋轉,斜切。爲了作出更復雜的變換,同時沒必要親手去改動座標變換矩陣,

Matrix類提供了許多Map方法,將原圖形映射到目標點構成新的圖形,

下面簡述setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) 的用法,但願起到觸類旁通的做用。

參數srcdst是分別存儲了原圖像的點和和指定的目標點的一維數組,數組中存儲的座標格式以下:
 [x0, y0, x1, y1, x2,y2,...]
 
這個個函數將src中的座標映射到dst中的座標,實現圖像的變換。

具體的例子能夠參考APIDemos裏的PolyToPoly,我在這裏就再也不貼代碼了,只講一下函數是怎麼變換圖片的。下面是效果:


圖中寫1的是原圖,寫有234的是變換後的圖形。如今分析2是怎麼變換來的,變換的原座標點和目的座標點以下:
src=new float[] { 32, 32, 64, 32 }
dst=new float[] { 32, 32, 64, 48 }

從上圖標示出的座標看出原圖的(3232)映射到原圖的(3232),(6432)映射到原圖(6448)這樣的效果是圖像放大了並且發生了旋轉。這樣的過程至關於(3232)點不動,而後拉住圖形(6432)點並拉到(6448)點處,這樣圖形必然會被拉伸放大而且發生旋轉。最後用一個平移將圖形移動到右邊如今的位置。但願可以好好理解這一過程,下面的34圖是一樣的道理。

相關文章
相關標籤/搜索