Android绘图之Matrix
一、概述
1. 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类。Android中的Matrix是一个3 x 3的矩阵,其内容如下
2.Matrix的对图像的处理可分为四类基本变换:
Translate 平移变换
Rotate 旋转变换
Scale 缩放变换
Skew 错切变换
针对每种变换,Android提供了pre、set和post三种操作方式。其中
set用于设置Matrix中的值。
pre是先乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。先乘相当于矩阵运算中的右乘。
post是后乘,因为矩阵的乘法不满足交换律,因此先乘、后乘必须要严格区分。后乘相当于矩阵运算中的左乘。
除平移变换(Translate)外,旋转变换(Rotate)、缩放变换(Scale)和错切变换(Skew)都可以围绕一个中心点来进行,如果不指定,在默认情况下是围绕(0, 0)来进行相应的变换的。
二、常用操作
1.平移
matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());
2.缩放
matrix.setScale(2f, 2f);
3.旋转
//第一种方式 //旋转 围绕图片中心 matrix.setRotate(45f,view.getImageBitmap().getWidth()/2f,view.getImageBitmap().getHeight()/2f); //平移 matrix.postTranslate(view.getImageBitmap().getWidth()*1.5f,0f); //第二种方式 //旋转 中心点(0,0) matrix.setRotate(45f); //先将图片中心移到(0,0),旋转后再移到原位置 matrix.preTranslate(-view.getImageBitmap().getWidth()/2f,-view.getImageBitmap().getHeight()/2f); matrix.postTranslate(view.getImageBitmap().getWidth()*2f,view.getImageBitmap().getHeight()/2f);
4.错切
matrix.setSkew(0.5f,0f);//水平 matrix.setSkew(0f,0.5f);//竖直 matrix.setSkew(0.5f,0.5f);//水平和数值
5.对称
1)x轴对称
float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
2)Y轴对称
float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
3)y=x对称
float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};
matrix.setValues(matrix_values);
三、代码
1.xml文件
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/rl" > <com.example.dhj.bitmapdemo.TransformMatrixView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/view" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="visible" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginBottom="135dp" android:onClick="click" android:text="平移" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/button" android:layout_alignBottom="@+id/button" android:layout_marginLeft="17dp" android:layout_marginStart="17dp" android:layout_toEndOf="@+id/button" android:layout_toRightOf="@+id/button" android:onClick="click" android:text="旋转" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/button2" android:layout_marginLeft="35dp" android:layout_marginStart="35dp" android:layout_toEndOf="@+id/button2" android:layout_toRightOf="@+id/button2" android:onClick="click" android:text="水平倾斜" /> <Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/button5" android:layout_alignBottom="@+id/button5" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:onClick="click" android:text="竖直倾斜" /> <Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/button2" android:layout_alignStart="@+id/button2" android:layout_below="@+id/button2" android:onClick="click" android:text="水平竖直倾斜" /> <Button android:id="@+id/button6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/button3" android:layout_alignStart="@+id/button3" android:layout_below="@+id/button3" android:onClick="click" android:text="x轴对称" /> <Button android:id="@+id/button7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/button4" android:layout_marginTop="15dp" android:onClick="click" android:text="y轴对称" /> <Button android:id="@+id/button8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/button7" android:layout_alignLeft="@+id/button5" android:layout_alignStart="@+id/button5" android:onClick="click" android:text="y=x对称" /> <Button android:id="@+id/button11" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/button6" android:layout_alignStart="@+id/button6" android:layout_alignTop="@+id/button8" android:onClick="click" android:text="缩放" /> </RelativeLayout> </FrameLayout>
2.自定义view
class TransformMatrixView extends ImageView { private Bitmap bitmap; private Matrix matrix; public TransformMatrixView(Context context) { super(context); Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.p1); bitmap=resizeBitmap(b,162,251); matrix = new Matrix(); setBackgroundColor(Color.parseColor("#3f51b5")); } public TransformMatrixView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.p1); bitmap=resizeBitmap(b,162,251); matrix = new Matrix(); // setBackgroundColor(Color.parseColor("#3f51b5")); } @Override protected void onDraw(Canvas canvas) { // 画出原图像 canvas.drawBitmap(bitmap, 0, 0, null); // 画出变换后的图像 canvas.drawBitmap(bitmap, matrix, null); super.onDraw(canvas); } @Override public void setImageMatrix(Matrix matrix) { this.matrix.set(matrix); super.setImageMatrix(matrix); } public Bitmap getImageBitmap() { return bitmap; } /** * 使用Matrix将Bitmap压缩到指定大小 * @param bitmap * @param w * @param h * @return */ public static Bitmap resizeBitmap(Bitmap bitmap, int w, int h) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scaleWidth = ((float) w) / width; float scaleHeight = ((float) h) / height; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true); return resizedBitmap; } }
3.activity
public class MainActivity extends Activity { private TransformMatrixView view; Matrix matrix= new Matrix(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); view= (TransformMatrixView) findViewById(R.id.view); } public void click(View v){ switch (v.getId()){ case R.id.button: tranlate(); break; case R.id.button2: rorate(); break; case R.id.button3: skewhorizontal(); break; case R.id.button4: skewVertical(); break; case R.id.button5: skew(); break; case R.id.button6: symmetryHorizontal(); break; case R.id.button7: symmetryVertical(); break; case R.id.button8: symmetry(); break; case R.id.button11: scale(); break; } view.setImageMatrix(matrix); // view.invalidate(); } //平移 private void tranlate(){ // 输出图像的宽度和高度(162 x 251) // Log.e("TestTransformMatrixActivity", "image size: width x height = " + view.getImageBitmap().getWidth() + " x " + view.getImageBitmap().getHeight()); // 1. 平移 matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight()); // 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight() } //旋转 private void rorate(){ //第一种方式 //旋转 围绕图片中心 matrix.setRotate(45f,view.getImageBitmap().getWidth()/2f,view.getImageBitmap().getHeight()/2f); //平移 matrix.postTranslate(view.getImageBitmap().getWidth()*1.5f,0f); //第二种方式 //旋转 中心点(0,0) matrix.setRotate(45f); //先将图片中心移到(0,0),旋转后再移到原位置 matrix.preTranslate(-view.getImageBitmap().getWidth()/2f,-view.getImageBitmap().getHeight()/2f); matrix.postTranslate(view.getImageBitmap().getWidth()*2f,view.getImageBitmap().getHeight()/2f); } //缩放 private void scale(){ matrix.setScale(2f, 2f); matrix.postTranslate(view.getImageBitmap().getWidth(),view.getImageBitmap().getHeight()); } //水平 倾斜 private void skewhorizontal(){ // matrix.setSkew(0.5f, 0f); // matrix.postTranslate(view.getImageBitmap().getWidth(), 0f); matrix.setSkew(0.5f,0f); matrix.postTranslate(view.getImageBitmap().getWidth(),0f); } //竖直 倾斜 private void skewVertical(){ matrix.setSkew(0f,0.5f); matrix.postTranslate(view.getImageBitmap().getWidth(),0f); } //倾斜 水平和竖直 private void skew(){ matrix.setSkew(0.5f,0.5f); matrix.postTranslate(view.getImageBitmap().getWidth(),0f); } //x轴对称 private void symmetryHorizontal(){ float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f}; matrix.setValues(matrix_values); matrix.postTranslate(0f,view.getImageBitmap().getHeight()*2); } //y轴对称 private void symmetryVertical(){ float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f}; matrix.setValues(matrix_values); matrix.postTranslate(view.getImageBitmap().getWidth()*2,0f); } //对称 y=x private void symmetry(){ float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f}; matrix.setValues(matrix_values); matrix.postTranslate(view.getImageBitmap().getWidth()+view.getImageBitmap().getHeight(), view.getImageBitmap().getHeight()+view.getImageBitmap().getWidth()); } }
四、效果
参考:
Android中图像变换Matrix的原理、代码验证和应用