Matrix ,中文里叫矩陣,高等數(shù)學(xué)里有介紹,在圖像處理方面,主要是用于平面的縮放、平移、旋轉(zhuǎn)等操作。
首先介紹一下矩陣運(yùn)算。加法和減法就不用說(shuō)了,對(duì)應(yīng)位相加就好。圖像處理,主要用到的是乘法 。下面是一個(gè)乘法的公式:
在 Android 里面, Matrix 由 9 個(gè) float 值構(gòu)成,是一個(gè) 3*3 的矩陣。如下圖:
解釋一下,上面的sinX 和cosX ,表示旋轉(zhuǎn)角度的cos 值和sin值,注意,旋轉(zhuǎn)角度是按順時(shí)針?lè)较蛴?jì)算的。 translateX 和 translateY 表示 x 和 y 的平移量。 scale 是縮放的比例, 1 是不變, 2 是表示縮放 1/2 。
Matrix的操作,總共分為translate(平移),rotate(旋轉(zhuǎn)),scale(縮放)和skew(傾斜)四種,每一種變換在Android的API里都提供了set, post和pre三種操作方式,除了translate,其他三種操作都可以指定中心點(diǎn)。
set是直接設(shè)置Matrix的值,每次set一次,整個(gè)Matrix的數(shù)組都會(huì)變掉。
post是后乘,當(dāng)前的矩陣乘以參數(shù)給出的矩陣??梢赃B續(xù)多次使用post,來(lái)完成所需的整個(gè)變換。例如,要將一個(gè)圖片旋轉(zhuǎn)30度,然后平移到(100,100)的地方,那么可以這樣做:Matrix m = new Matrix(); m.postRotate(30 ); m.postTranslate(100 , 100 ); 這樣就達(dá)到了想要的效果。
pre是前乘,參數(shù)給出的矩陣乘以當(dāng)前的矩陣。所以操作是在當(dāng)前矩陣的最前面發(fā)生的。例如上面的例子,如果用pre的話(huà),就要這樣:Matrix m = new Matrix(); m.setTranslate(100 , 100 ); m.preRotate(30 );
旋轉(zhuǎn)、縮放和傾斜都可以圍繞一個(gè)中心點(diǎn)來(lái)進(jìn)行,如果不指定,默認(rèn)情況下,是圍繞(0,0)點(diǎn)來(lái)進(jìn)行。
特別注意:
Matrix的操作,總共分為translate(平移),rotate(旋轉(zhuǎn)),scale(縮放)和skew(傾斜)四種,每一種變換在
Android的API里都提供了set, post和pre三種操作方式,除了translate,其他三種操作都可以指定中心點(diǎn)。
set是直接設(shè)置Matrix的值,每次set一次,整個(gè)Matrix的數(shù)組都會(huì)變掉。
post是后乘,當(dāng)前的矩陣乘以參數(shù)給出的矩陣??梢赃B續(xù)多次使用post,來(lái)完成所需的整個(gè)變換。
鏡面效果:
倒影效果:
圖片的合成(水印):
不多說(shuō)了,直接上代碼了。
MainActivity.java里的主要代碼如下:
- package net.loonggg.testmatrix;
-
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Matrix;
- import android.graphics.Paint;
- import android.graphics.PorterDuff.Mode;
- import android.graphics.PorterDuffXfermode;
- import android.os.Bundle;
- import android.view.Window;
- import android.widget.ImageView;
-
- public class MainActivity extends Activity {
- private ImageView iv1, iv2;
- private Canvas canvas;
- private Paint paint;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- iv1 = (ImageView) findViewById(R.id.iv1);
- iv2 = (ImageView) findViewById(R.id.iv2);
- Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(),
- R.drawable.weibo);
- Bitmap updateBitmap = Bitmap.createBitmap(bitmap1.getWidth() * 2,
- bitmap1.getHeight() * 2, bitmap1.getConfig());
- canvas = new Canvas(updateBitmap);
- paint = new Paint();
- paint.setColor(Color.BLACK);
- Matrix matrix = new Matrix();
- // setMirrorOne(bitmap1, matrix);
- // setInvertedImage(bitmap1, matrix);
- // setBaseChange(matrix);
- canvas.drawBitmap(bitmap1, matrix, paint);
- setImageSynthesis(matrix);
- iv1.setImageBitmap(bitmap1);
- iv2.setImageBitmap(updateBitmap);
-
- }
-
- /**
- * 還有一些基本變化
- */
- private void setBaseChange(Matrix matrix) {
- // matrix.setRotate(60);// 這是旋轉(zhuǎn)多少度
- // matrix.setRotate(degrees, px, py);//這個(gè)方法是以哪個(gè)點(diǎn)為中心進(jìn)行旋轉(zhuǎn)多少度
- // matrix.setSkew(kx, ky);//設(shè)置傾斜,以x軸傾斜,還是y軸
- // 傾斜x和y軸,以(100,100)為中心。
- // matrix.postSkew(0 .2f, 0 .2f, 100 , 100 );
- // matrix.setScale(0.5f, 1);//縮放寬度變?yōu)樵瓉?lái)的一半,高度不變
- }
-
- /**
- * 設(shè)置倒影效果
- *
- * @param bitmap1
- * @param matrix
- */
- private void setInvertedImage(Bitmap bitmap1, Matrix matrix) {
- matrix.setScale(1, -1);
- matrix.postTranslate(0, bitmap1.getHeight());
- }
-
- /**
- * 設(shè)置鏡面效果方法一
- *
- * @param bitmap1
- * @param matrix
- */
- private void setMirrorOne(Bitmap bitmap1, Matrix matrix) {
- matrix.setTranslate(bitmap1.getWidth(), 0);// 這個(gè)是移動(dòng)
- matrix.preScale(-1, 1);
- }
-
- // ---------------------------------------------------------
- /**
- * 解釋?zhuān)虹R面效果方法一和二的區(qū)別:
- * 不知道大家看沒(méi)看出來(lái),其實(shí)這兩種方法的效果是一樣的,只不過(guò)是設(shè)置步驟不一樣,post是后乘,當(dāng)前的矩陣乘以參數(shù)給出的矩陣
- * ??梢赃B續(xù)多次使用post,來(lái)完成所需的整個(gè)變換。 pre是前乘,參數(shù)給出的矩陣乘以當(dāng)前的矩陣。所以操作是在當(dāng)前矩陣的最前面發(fā)生的。
- * 可以連續(xù)多次使用post
- * ,來(lái)完成所需的整個(gè)變換,但是不可以連續(xù)使用set來(lái)完成矩陣的整個(gè)變換,為什么呢?set是直接設(shè)置Matrix的值,每次set一次
- * ,整個(gè)Matrix的數(shù)組都會(huì)變掉,第一次可以使用set,之后的變換必須換成post或者pre,也可以一直用post也行
- */
- // ---------------------------------------------------------
-
- /**
- * 設(shè)置鏡面效果方法二
- *
- * @param bitmap1
- * @param matrix
- */
- private void setMirrorTwo(Bitmap bitmap1, Matrix matrix) {
- matrix.setScale(-1, 1);
- matrix.postTranslate(bitmap1.getWidth(), 0);
- }
-
- /**
- * 設(shè)置圖片的合成
- *
- * @param matrix
- */
- private void setImageSynthesis(Matrix matrix) {
- Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(),
- R.drawable.ic_launcher);
- // 設(shè)置圖片合成時(shí)的各種模式
- paint.setXfermode(new PorterDuffXfermode(Mode.DARKEN));
- // 圖片的合成很簡(jiǎn)單,就是再以bitmap2為基圖往目標(biāo)圖片上畫(huà)一次
- canvas.drawBitmap(bitmap2, matrix, paint);
- }
-
- }
布局文件的代碼如下:
- <LinearLayout xmlns:android="http://schemas./apk/res/android"
- xmlns:tools="http://schemas./tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context=".MainActivity" >
-
- <ImageView
- android:id="@+id/iv1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <ImageView
- android:id="@+id/iv2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/loongggdroid/article/details/18706999
|