在編程中有時候需要對圖片做特殊的處理,比如將圖片做出黑白的,或者老照片的效果,有時候還要對圖片進行變換,以拉伸,扭曲等等。這些效果在android中有很好的支持,通過顏色矩陣(ColorMatrix)和坐標變換矩陣(Matrix)可以完美的做出上面的所說的效果。下面將分別介紹這兩個矩陣的用法和相關(guān)的函數(shù)。顏色矩陣 可以用來方面的修改圖片中RGBA各分量的值,顏色矩陣以一維數(shù)組的方式存儲如下: 這個矩陣對顏色的作用計算方式如1.3示: C矩陣是圖片中包含的ARGB信息,R矩陣是用顏色矩陣應(yīng)用于C之后的新的顏色分量,運算結(jié)果如下: 第三行決定藍色,第四行決定了透明度,第五列是顏色的偏移量。下面是一個實際中使用的顏色矩陣。 這樣的效果就是圖片偏黃,因為紅色和綠色混合后得到黃色,黃色增加了100,圖片當然就偏黃了。 上圖1.6是將綠色分量乘以2變?yōu)樵瓉淼?倍。相信讀者至此已經(jīng)明白了如何通過顏色矩陣來改變各顏色分量。 下面編寫一段代碼來,通過調(diào)整顏色矩陣來獲得不同的顏色效果,JavaCode如下: 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 //設(shè)置顏色矩陣 80 cm.set(array); 81 //顏色濾鏡,將顏色矩陣應(yīng)用于圖片 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類主要負責接收顏色矩陣的設(shè)置和重繪,沒有要說的。MyImage類中進行繪圖工作,首先設(shè)置顏色矩陣cm.set(..)從一維數(shù)組中讀取數(shù)據(jù)20個數(shù)據(jù)給顏色矩陣賦值,paint.setColorFilter(..)設(shè)置顏色濾鏡,然后繪圖,效果就出來了(這個過程和PS差不多)如下: 但是各種效果并不能讓用戶手動調(diào)節(jié)顏色矩陣,這里需要計算公式,由于本人并不是做圖形軟件的也不能提供,可以參考這個鏈接:
因為一個圖片是有點陣和每一點上的顏色信息組成的,所以對坐標的變換,就是對每一點進行搬移形成新的圖片。 具體的說圖形的放大縮小,移動,旋轉(zhuǎn),透視,扭曲這些效果都可以用此矩陣來完成。 可見圖片的每一點都在x和y方向上平移到了(50,50)點處,這種效果就是平移效果,將圖片轉(zhuǎn)移到了(50,50)處。
下面將編一個小程序,通過控制坐標變換矩陣來達到控制圖形的目的,JavaCode如下: 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//為坐標變換矩陣設(shè)置響應(yīng)的值 81 cm.setValues(array); 82//按照坐標變換矩陣的描述繪圖 83 canvas.drawBitmap(mBitmap, cm, paint); 84 Log.i("CMatrix", "--------->onDraw"); 85 86 87 } 88 89 }
但是我們看看Matrix類就可以發(fā)現(xiàn),實際上,matrix類本身已經(jīng)提供了許多類似的方法,我們只要調(diào)用,就可以了。 Matrix類提供了許多Map方法,將原圖形映射到目標點構(gòu)成新的圖形, 下面簡述setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) 的用法,希望起到舉一反三的作用。 參數(shù)src和dst是分別存儲了原圖像的點和和指定的目標點的一維數(shù)組,數(shù)組中存儲的坐標格式如下: 具體的例子可以參考APIDemos里的PolyToPoly,我在這里就不再貼代碼了,只講一下函數(shù)是怎么變換圖片的。下面是效果: |
|