码迷,mamicode.com
首页 > 移动开发 > 详细

Android进阶之Matrix完全解析

时间:2015-08-13 17:59:35      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:android   matrix   图形变换   缩放   平移   

官方文档镇楼
https://developer.android.com/reference/android/graphics/Matrix.html

The Matrix class holds a 3x3 matrix for transforming coordinates.
Matrix是一个用于坐标变换的3*3矩阵

矩阵乘法变换基础

矩阵乘法公式

若一矩阵的列数与另一矩阵的行数相等,则可定义这两个矩阵的乘积。如 A 是 m×n 矩阵和 B 是 n×p矩阵,它们是乘积 AB 是一个 m×p 矩阵,其中
(AB)[i, j] = A[i, 1] * B[1, j] + A[i, 2] * B[2, j] + … + A[i, n] * B[n, j] 对所有 i 及 j。

矩阵左乘

矩阵左乘相当于行变换,例如对于矩阵A:

???147258369???

如果想让第一行和第二行进行交换,则只需为其左乘一个矩阵B:
???010100001???

矩阵右乘

矩阵右乘相当于列变换,例如对于矩阵A,如果想让其第一列和第二列进行变换,则只需为其右乘一个矩阵C:

???010100001???

Android中的Matrix

介绍

在Android中Matrix由9个float值构成,是一个3*3的矩阵,如下图:

???cosXsinX0?sinXcosX0translateXtranslateYscale???

其中,cosX,-sinX,sinX,cosX对应于旋转角度的三角函数值,例如:顺时针旋转90°,即分别为0,-1,1,0。translateX,translateY分别对应于x轴,y轴方向上的平移量。scale对应于缩放的比例,1为不变,2表示缩放为原先的1/2。

代码验证

旋转

由上文可知,如果我们将matrix矩阵的值设置为:

???010?100001???

图片将会顺时针旋转90°,那么到底是不是这样呢,直接上代码:

public void rotate1(){
        ImageView iv_image1 = (ImageView) findViewById(R.id.iv_rotate1);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.filter_0, new BitmapFactory.Options());
        iv_image1.setImageBitmap(bitmap);
        iv_image1.setScaleType(ScaleType.MATRIX);
        Matrix matrix_rotate1 = new Matrix();
        float[] rotate1s = new float[]{0.0f,-1.0f,0.0f,
                                      1.0f,0.0f,0.0f,
                                      0.0f,0.0f,1.0f};
        matrix_rotate1.setValues(rotate1s);
        iv_image1.setImageMatrix(matrix_rotate1);
    }

运行结果:
技术分享

我们并没有看到旋转90°后的图片,这是因为,图片在以(0,0)为中心顺时针旋转90°后已经出了空间的范围,因此,我们已经看不到旋转后的图片。

那么如何以图片中心进行旋转呢,我们可以这样想,图片以(0,0)为中心顺时针旋转90°后再沿x轴正方向平移一段距离即可。这里需要注意的是平移的距离,答案应该是图片的高度减1(这个应该不难想到)。代码如下:

public void rotate2(){
        ImageView iv_image2 = (ImageView)findViewById(R.id.iv_rotate2);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.filter_0, new BitmapFactory.Options());
        iv_image2.setImageBitmap(bitmap);
        iv_image2.setScaleType(ScaleType.MATRIX);
        Matrix matrix_rotate2 = new Matrix();
        float[] rotates2 = new float[]{0.0f,-1.0f,bitmap.getHeight()-1.0f,
                                      1.0f,0.0f,0.0f,
                                      0.0f,0.0f,1.0f};
        matrix_rotate2.setValues(rotates2);
        iv_image2.setImageMatrix(matrix_rotate2);
    }

运行结果:
技术分享

平移

其实旋转中已经涉及到了平移变换,只需对translateX,translateY进行赋值即可,需要注意的是这两个值代表的是平移量而非平移的坐标。另外平移是不可以设置中心点的。

public void translate(){
        ImageView iv_translate = (ImageView)findViewById(R.id.iv_translate);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.filter_0, new BitmapFactory.Options());
        iv_translate.setImageBitmap(bitmap);
        iv_translate.setScaleType(ScaleType.MATRIX);
        Matrix matrix_translate = new Matrix();
        float[] translates = new float[]{1.0f,0.0f,200.0f,
                                        0.0f,1.0f,0.0f,
                                        0.0f,0.0f,1.0f};
        matrix_translate.setValues(translates);
        iv_translate.setImageMatrix(matrix_translate);;
    }

运行结果:
技术分享

缩放

看到这里我们应该很清楚了,要想实现缩放效果,只需对scale值进行赋值即可,1代表不缩放,2代表缩放为原先的1/2,以此类推,默认(0,0)为中心点。注意:(0,0)表示图片的左上角坐标而非屏幕原点。

public void scale(){
        ImageView iv_scale = (ImageView)findViewById(R.id.iv_scale);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.filter_0, new BitmapFactory.Options());
        iv_scale.setImageBitmap(bitmap);
        iv_scale.setScaleType(ScaleType.MATRIX);
        Matrix matrix_scale = new Matrix();
        float[] scales = new float[]{1.0f,0.0f,0.0f,
                                    0.0f,1.0f,0.0f,
                                    0.0f,0.0f,2.0f};
        matrix_scale.setValues(scales);
        iv_scale.setImageMatrix(matrix_scale);
    }

运行结果:
技术分享

当然也可以设置按照某一中心点坐标进行缩放。这个下文会讲到。

Matrix相关API

上文我们从矩阵变换的角度讲解了,图片的坐标变换。其实安卓一已经为我们封装好了相关运算,我们只需调用相应的api即可。接下来会讲解这些api的用法和注意事项。

Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。

set

包括:
- setRotate(float degrees) degrees为旋转的度数,正为顺时针,默认以(0,0)为旋转中心
- setRotate(float degrees, float px, float py) px,py为旋转中心坐标
- setScale(float sx, float sy) sx,sy分别为图片在x,y轴方向上的缩放比例
- setScale(float sx, float sy, float px, float py) px,py为缩放的中心点坐标,即缩放过程中保持不变的点
- setTranslate(float dx, float dy) dx,dy分别为图片在x,y轴方向上的偏移量,注意平移无中心点
- setSkew(float kx, float ky) kx,ky为图片相对于x,y轴的倾斜量
- setSkew(float kx, float ky, float px, float py) px,py为图片倾斜的中心点坐标

注意:set是直接设置matrix的值,每次set一次,整个matrix的值都会变掉。所以如果进行组合变换的话,只能在第一次使用set,以后要使用post和pre,也可以只是用post。

pre

以preRotate()为例:
技术分享

可以看到pre操作是拿参数给出的矩阵右乘当前矩阵M,即pre执行的是一个右乘的操作。而在图形操作中,越靠近右边的矩阵就越先执行。所以,pre操作是在当前矩阵的最前面执行的。

post

技术分享

post是拿参数给出的矩阵左乘当前矩阵M,即post执行的是一个左乘的操作。所以,post操作是在当前矩阵的最后面执行的。所以完全可以只使用post操作来完成所需的变换。

相关api请参看官方文档,这里不再一一解释。

本文代码下载:
http://download.csdn.net/detail/u012483425/9001425

参考博客:
http://blog.csdn.net/zzhou910/article/details/26379795
http://blog.csdn.net/loongggdroid/article/details/18706999

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android进阶之Matrix完全解析

标签:android   matrix   图形变换   缩放   平移   

原文地址:http://blog.csdn.net/u012483425/article/details/47609655

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!