Android开发 之 Matrix的使用

来源:互联网 发布:jdbcutils.java工具类 编辑:程序博客网 时间:2024/05/19 19:39

Matrix

这里我们会详细讲解matrix的各个方法,以及它的用法。matrix叫做矩阵,这里讲的是处理图形的。他是一个3*3的矩阵。

基本方法解析
讲解完了matrix作用于像素点的原理之后,我们逐个讲解它的方法。
(1) 构造函数
public Matrix()
public Matrix(Matrix src)
构造函数有两个,第一个是直接创建一个单位矩阵,第二个是根据提供的矩阵创建一个新的矩阵(采用deep copy)

(2) isIdentity与isAffine
public boolean isIdentity()//判断是否是单位矩阵
public boolean isAffine()//判断是否是仿射矩阵
是否是单位矩阵很简单,就不做讲解了,这里是否是仿射矩阵可能大家不好理解。

首先来看看什么是仿射变换。仿射变换其实就是二维坐标到二维坐标的线性变换,保持二维图形的“平直性”(即变换后直线还是直线不会打弯,圆弧还是圆弧)和“平行性”(指保持二维图形间的相对位置关系不变,平行线还是平行线,而直线上点的位置顺序不变),可以通过一系列的原子变换的复合来实现,原子变换就包括:平移、缩放、翻转、旋转和错切。这里除了透视可以改变z轴以外,其他的变换基本都是上述的原子变换,所以,只要最后一行是0,0,1则是仿射矩阵。

(3) rectStaysRect
public boolean rectStaysRect()
判断该矩阵是否可以将一个矩形依然变换为一个矩形。当矩阵是单位矩阵,或者只进行平移,缩放,以及旋转90度的倍数的时候,返回true。

(4) reset
public void reset()
重置矩阵为单位矩阵。

(5) setTranslate
public void setTranslate(float dx, float dy)
设置平移效果,参数分别是x,y上的平移量。 

(6) setScale
public void setScale(float sx, float sy, float px, float py)
public void setScale(float sx, float sy)
两个方法都是设置缩放到matrix中,sx,sy代表了缩放的倍数,px,py代表缩放的中心。这里跟上面比较类似不做讲解了。

(7) setRotate
 public void setRotate(float degrees, float px, float py)
 public void setRotate(float degrees)
和上面类似,不再讲解。


上面的基本方法中,有关于变换的set方法都可以带来不同的效果,但是每个set都会把上个效果清除掉,例如依次调用了setSkew,setTranslate,那么最终只有setTranslate会起作用,那么如何才和将两种效果复合呢。Matrix给我们提供了很多方法。但是主要都是2类:
preXXXX:以pre开头,例如preTranslate 
postXXXX:以post开头,例如postScale

他们分别代表了前乘,和后乘。看一段代码:
Matrix matrix = new Matrix();
matrix.setTranslate(100, 1000);
matrix.preScale(0.5f, 0.5f);
这里matrix前乘了一个scale矩阵,换算成数学式如下:
这里写图片描述
这里写图片描述
从上面可以看出,最终得出的matrix既包含了缩放信息也有平移信息。 
后乘自然就是matrix在后面,而缩放矩阵在前面,由于矩阵前后乘并不等价,也就导致了他们的效果不同。我们来看看后乘的结果:
这里写图片描述
可以看到,结果跟上面不同,并且这也不是我们想要的结果,这里缩放没有更改,但是平移被减半了,换句话说,平移的距离也被缩放了。所以需要注意前后乘法的关系。


(8) setSinCos
public void setSinCos(float sinValue, float cosValue, float px, float py)
public void setSinCos(float sinValue, float cosValue)
这个方法乍一看可能有点蒙,其实在前面的原理中,我们讲解了一个旋转的例子,他最终的矩阵效果是这样的:
其实旋转,就是使用了这样的matrix,显而易见,这里的参数就清晰了。 
sinValue:对应图中的sin值 
cosValue:对应cos值 
px:中心的x坐标 
py:中心的y坐标

看一个示例,我们把图像旋转90度,那么90度对应的sin和cos分别是1和0。
Matrixmatrix = new Matrix();matrix.setSinCos(1, 0, bitmap.getWidth() / 2, bitmap.getHeight() / 2);canvas.drawBitmap(bitmap, matrix, paint);

(9) setSkew
public void setSkew(float kx, float ky, float px, float py)
public void setSkew(float kx, float ky)
错切,这里kx,ky分别代表了x,y上的错切因子,px,py代表了错切的中心。

(10) setConcat
public boolean setConcat(Matrix a,Matrix b)
将当前matrix的值变为a和b的乘积,它的意义在下面的 进阶方法中来探讨。

(11)setPolyToPoly
public boolean setPolyToPoly(float[] src, int srcIndex,float[] dst, int dstIndex,int pointCount)
通过指定的0-4个点,原始坐标以及变化后的坐标,来得到一个变换矩阵。如果指定0个点则没有效果。
            InputStream inputStream = getResources().openRawResource(R.drawable.tp03);//            bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.tp03);//这种方式默认把图片尺寸放大一倍            bitmap = BitmapFactory.decodeStream(inputStream);            try {                inputStream.close();            } catch (IOException e) {                e.printStackTrace();            }            matrix = new Matrix();


//            //1个点setPolyToPoly平移//            float[] src={0,0};//            float[] dst={0+30,0+200};//            matrix.setPolyToPoly(src, 0, dst, 0, 1);//            //两个点setPolyToPoly平移,点的平移可能不规则,但是图片不会变形,可能会缩放。//            int bw = bitmap.getWidth();//            int bh = bitmap.getHeight();//            float[] src = {bw / 2, bh / 2, bw, 0};//            float[] dst = {bw / 2+200, bh / 2+200, bw / 2 + bh / 2+200, bw / 2 + bh / 2};//            matrix.setPolyToPoly(src, 0, dst, 0, 2);//            //三个点setPolyToPoly,1点不动,2点动,图片在矩形和菱形之间变化。//              int bw = bitmap.getWidth();//              int bh = bitmap.getHeight();//              float[] src={0,bh,100,bh-50,bw,bh};//              float[] dst={0,bh+100,100,bh-50,bw-100,bh};//              matrix.setPolyToPoly(src, 0, dst, 0, 3);//              //四个点setPolyToPoly,图形发生巨大变化。//              int bw = bitmap.getWidth();//              int bh = bitmap.getHeight();//              float[] src={0,bh,bw,bh,bw,0,0,0};//              float[] dst={0,bh,bw,bh,bw-50,500,50,500};//              matrix.setPolyToPoly(src, 0, dst, 0, 4);
  @Override        protected void onDraw(Canvas canvas) {            super.onDraw(canvas);            canvas.drawColor(Color.WHITE);            canvas.drawBitmap(bitmap,0,0,null);            canvas.drawBitmap(bitmap,matrix,null);        }
(12)setRectToRect
public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf)
将rect变换成rect,上面的rectStaysRect已经说过,要保持rect只能做缩放平移和选择90度的倍数,那么这里其实也是一样,只是这几种变化,这里通过stf参数来控制。

ScaleToFit 有如下四个值:

FILL: 可能会变换矩形的长宽比,保证变换和目标矩阵长宽一致。 
START:保持坐标变换前矩形的长宽比,并最大限度的填充变换后的矩形。至少有一边和目标矩形重叠。左上对齐。 
CENTER: 保持坐标变换前矩形的长宽比,并最大限度的填充变换后的矩形。至少有一边和目标矩形重叠。 
END:保持坐标变换前矩形的长宽比,并最大限度的填充变换后的矩形。至少有一边和目标矩形重叠。右下对齐。
这里使用谷歌的api demo的图片作为例子:


这里写图片描述


(13) invert
public boolean invert(Matrix inverse)
反转当前矩阵,如果能反转就返回true并将反转后的值写入inverse,否则返回false。当前矩阵*inverse=单位矩阵。
//             Matrix matrix00=new Matrix();//            //反转当前矩阵,如果能反转就返回true并将反转后的值写入inverse,否则返回false。当前矩阵*inverse=单位矩阵。//            boolean invert = matrix.invert(matrix00);//            if(invert)//            {//                matrix=matrix00;//            }


(14) mapPoints
public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,int pointCount)
public void mapPoints(float[] dst, float[] src)
public void mapPoints(float[] pts)
映射点的值到指定的数组中,这个方法可以在矩阵变换以后,给出指定点的值。 
dst:指定写入的数组 
dstIndex:写入的起始索引,x,y两个坐标算作一对,索引的单位是对,也就是经过两个值才加1 
src:指定要计算的点 
srcIndex:要计算的点的索引 
pointCount:需要计算的点的个数,每个点有两个值,x和y。

(15) mapVectors
public void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex,int vectorCount)
public void mapVectors(float[] dst, float[] src)
public void mapVectors(float[] vecs)
与上面的mapPoionts基本类似,这里是将一个矩阵作用于一个向量,由于向量的平移前后是相等的,所以这个方法不会对translate相关的方法产生反应,如果只是调用了translate相关的方法,那么得到的值和原本的一致。

(16) mapRect
public boolean mapRect(RectF dst, RectF src)
public boolean mapRect(RectF rect)
返回值即是调用的rectStaysRect(),这个方法前面有讲过,这里把src中指定的矩形的左上角和右下角的两个点的坐标,写入dst中。

(17) mapRadius
public float mapRadius(float radius)
返回一个圆圈半径的平均值,将matrix作用于一个指定radius半径的圆,随后返回的平均半径。

还有一些效果代码:
//           //  对称 (竖直对称)//            matrix.setScale(1, -1);//            matrix.postTranslate(0, bitmap.getHeight()*2);            //水平对称//            matrix.setScale(-1, 1);//            matrix.postTranslate(bitmap.getWidth()*2, 0);// 这个是移动            //y=x对称//             matrix.setScale(-1, -1);//             matrix.postTranslate(bitmap.getWidth()*2,bitmap.getHeight()*2);// 这个是移动

常用的功能就是以上这些了

这里写图片描述
原创粉丝点击