Android-Matrix矩阵
来源:互联网 发布:windows视频截gif 编辑:程序博客网 时间:2024/06/05 22:56
一直很忙,也年底了,想了很多新一年的规划,也不知道能完成几个。。。年前发完版本,趁着空隙时间,看看Matrix相关的内容,顺便做做总结。
- Matrix 原理
- Matrix 的应用 - 压缩图像
- Matrix 的应用 - 实现多点触控,控制图像缩放
Matrix
Matrix意思是矩阵,作为Android源码中的一个常用类,它的作用是持有一个3*3的矩阵数组,用于坐标的转换。Matrix作为Android开发中常用的数学工具,它的主要作用领域,主要作用于图像大小变换。
Matrix图片操作
我们可以看到Matrix矩阵如下
字面上理解,它们分别代表什么?
MSCALE 控制图像的缩放变换
MSKEW 控制图像的错切变换
MTRANS 控制图像的平移变换
MPSERSP 控制图像的透视
当然实际貌似并不是完全按照字面的意思去操作,在实际Android开发中,根据矩阵乘法的影响,我们知道实际上:
MSCALE_X, MSCALE_Y , MSKEW_X , MSKEW_Y 处理图像的旋转变换,
MTRANS_X, MTRANS_Y 处理图像的位移变换,
MSCALE_X, MSCALE_Y, MPERSP_2处理图像的缩放变换,
MSKEW_X, MSKEW_Y处理图像的错切变换。
Matrix的矩阵运算
Matrix有上述几种变换,包括位移、缩放、错切、透视,每一种变换都是对每一个像素点的操作,对于每一个像素点,我们可以用一个3行1列的数组矩阵来描述它
x代表像素点在屏幕上X轴的坐标,y代表像素点在屏幕上Y轴的坐标,1是像素点在屏幕上Z轴的坐标,Z轴数值为1代表默认值,如果Z轴值变大,相当于屏幕画布拉近,图像变大。
而当我们对一个像素点做变换操作,其实就是对像素点对应的矩阵做矩阵乘法运算,通过上面规定的三阶矩阵各个数值代表的变换,相乘之后来改变像素点的矩阵值,而改变像素点的位置。
这里复习一下矩阵的乘法
设A为m * p的矩阵,B为p n的矩阵,那么称m*n的矩阵C为矩阵A与B的乘积,记作 C = A B ,其中矩阵C中的第i行第j列元素可以表示为:
这是一个矩阵相乘的例子:
位移变换
位移变化其实也就是图像的每个像素点都实现了位移运算,以单独一个像素点来说,P(x0,y0)是起始点,P(x,y)是终点。
所做的矩阵运算
这里看到我们做的是后乘的矩阵运算,由一开始我们分析可知MSCALE_X, MSCALE_Y 控制图像的缩放变换,这两个值应该设置为△x和△y;MSCALE_X, MSCALE_Y控制图像旋转变换,由于此时大小不变,因为均为1;MPERSP_2控制图像的缩放,因此这个值也为1。
旋转变换
旋转变换,如果旋转的中心为原点,根据矩阵乘法的运算逆推,我们得出
MSCALE_X, MSCALE_Y , MSKEW_X , MSKEW_Y的值
缩放变换,错切变换
缩放变换,我们只需要控制的MSCALE_X, MSCALE_Y的值
如下图,k1,k2即为我们对图像的缩放比例,如果我们希望图像横纵比例都缩小一倍,那么k1,k2的值则为0.5,0.5。
错切变换,就是让每个像素点的横坐标(或者纵坐标)保持不变,而纵坐标(或者横坐标按比例变换)。
水平错切:
每一个像素点的坐标,纵坐标不变,横坐标则按比例发生了变化
垂直错切:
每一个像素点的坐标,横坐标不变,纵坐标则按比例发生了变化
如下图,k1的值控制水平错切,k2的值控制垂直错切
Matrix的前乘和后乘作用以及区别
对于上述的每种变换,Android提供了三种操作方式,分别是pre,set,post。例如位移变换,Matrix为我们提供了几个不同的API方法,分别是setTranslate,preTranslate,postTranslate,setTranslate代表直接设置三阶矩阵数值(直接覆盖原先已有的三阶矩阵),preTranslate代表让原来的三阶矩阵前乘另一个三阶矩阵,postTranslate代表让原来的三阶矩阵后乘另一个三阶矩阵。
为什么要这样区分呢?
这是为了让几种不同的变换操作同时起作用,比如我们有位移和缩放两个效果,如果我们只是调用setTranslate,那么之前设置的变换效果会被覆盖。为了让多种变换效果复合,我们需要采用前乘或者后乘的设置方式。
我们来看例子,
测试案例1
这是什么操作都不做的情况,直接显示位图:
测试案例2
我们调用set方法,给位图加上位移和缩放的效果:
Matrix matrix = new Matrix(); matrix.setTranslate(150, 150); matrix.setScale(0.5f, 0.5f); Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap .ic_launcher); canvas.drawBitmap(bitmap, matrix, paint);
效果图:
我们看到我们设置了两个效果,但是位移效果最后会被缩放效果覆盖。
测试案例3
现在我们使用pre方法,也还是给位图加上位移和缩放的效果:
Matrix matrix = new Matrix(); matrix.setScale(0.5f, 0.5f); matrix.preTranslate(150, 150); Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap .ic_launcher); canvas.drawBitmap(bitmap, matrix, paint);
效果图:
测试案例4
然后我们再尝试post方法,也还是给位图加上位移和缩放效果:
Matrix matrix = new Matrix(); matrix.setScale(0.5f, 0.5f); matrix.preTranslate(150, 150); Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap .ic_launcher); canvas.drawBitmap(bitmap, matrix, paint);
效果图
从上面我们可以看到,通过调用preXXX或者postXXX能够实现图像变换效果的复合,但是我们可以发现,调用preXXX和调用postXXX的结果是不一样的,原因就是矩阵乘法中前乘和后乘得到的结果是不一样的。
以上的例子来计算:
我们调用
matrix.setScale(0.5f, 0.5f);matrix.preTranslate(150, 150);
Matrix会通过前乘来计算出最后的结果:
而我们调用
matrix.setScale(0.5f, 0.5f);
matrix.preTranslate(150, 150);
Matrix会调用后乘来计算得出最后的结果:
通过上面分析我们知道,前乘和后乘能够带来两种不同效果。此时,通过后乘达到的效果与我们预期的不相符。
1)如果我们希望变换效果按照代码的执行顺序,那么我们可以调用postXXX;比如我们希望先缩小0.5倍,再位移150个单位,这时候调用preXXX。
2)如果我们希望后添加的变换效果也会被之前变换效果影响,那么我们调用postXXX;比如我们先设置了缩小效果,但是我们后续添加位移的效果,那么此时位移效果会被缩小效果影响,就像我们设置了0.5f的缩放值,后面通过postTranlate位移100单位,最后却只会位移50个单位。
Matrix应用 - 压缩图像
首先,我们可以用它来对图像进行压缩处理
private Bitmap scaleBitmap(Bitmap bitmap, int targetWidth, int targetHeight) { Matrix matrix = new Matrix(); matrix.setScale(targetWidth / bitmap.getWidth(), targetHeight / bitmap.getHeight()); return Bitmap.createBitmap(bitmap, 0, 0, targetWidth, targetHeight, matrix, true); }
Matrix应用 - 实现图片的多点触控
先来说我们的目标,是实现一个能够使图片感应手指多点触控放大缩小的功能,通过上面Matrix的铺垫,我们知道Matrix可以操作图像的缩放,这里还有一个点,就是多点触控。
多点触控
思路一,直接处理onTouchEvent()
MotionEvent.ACTION_DOWN:在第一个点被按下时触发
MotionEvent.ACTION_UP:当屏幕上唯一的点被放开时触发
MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有一个点被按住,此时再按下其他点时触发。
MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)。
MotionEvent.ACTION_MOVE:当有点在屏幕上移动时触发。
通过event.getX(index)和event.getY(index)可以获取到指定index点的坐标
/** * Returns the X coordinate of this event for the given pointer * <em>index</em> (use {@link #getPointerId(int)} to find the pointer * identifier for this index). * Whole numbers are pixels; the * value may have a fraction for input devices that are sub-pixel precise. * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 * (the first pointer that is down) to {@link #getPointerCount()}-1. * * @see #AXIS_X */ public final float getX(int pointerIndex) { return nativeGetAxisValue(mNativePtr, AXIS_X, pointerIndex, HISTORY_CURRENT); }
相对的,evetn.getX()就是获取第一个按下的手指的坐标
/** * {@link #getX(int)} for the first pointer index (may be an * arbitrary pointer identifier). * * @see #AXIS_X */ public final float getX() { return nativeGetAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT); }
思路二,通过GestureDetector辅助完成
我们知道Android为我们提供了GestureDetector,通过将触摸事件托管给它,能够为我们实现滑动,双击等操作的响应方法,为了方便多点触摸放大缩小的监听,我们也可以用辅助类ScaleGestureDetector。
交付触摸事件给ScaleGestureDetector处理
@Override public boolean onTouchEvent(MotionEvent event) { return mScaleGestureDetector.onTouchEvent(event); }
简单地实现从屏幕中心放大缩小的效果
private class MatrixScaleGestureDetector implements android.view.ScaleGestureDetector .OnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { Matrix matrix = getImageMatrix(); matrix.postScale(detector.getScaleFactor(), detector.getScaleFactor(), getWidth() / 2, getHeight() / 2); setImageMatrix(matrix); invalidate(); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } }
当然还有一些更加酷的效果,类似魅族手机的相册功能,相册图像能够根据手势进行旋转。
demo地址:https://github.com/82367825/MatrixMaster
更加高级的功能实现,我们能看到像这样的折叠菜单效果:
http://blog.csdn.net/lmj623565791/article/details/44283093
类似Matrix这样的数学矩阵在Android中不止用于操作图像大小和变换,更有ColorMatrix用于操作图像色彩,实现各种滤镜效果:
http://www.it165.net/pro/html/201505/40131.html
参考内容:
http://www.cnblogs.com/qiengo/archive/2012/06/30/2570874.html
http://blog.csdn.net/cquwentao/article/details/51445269
- Android Matrix矩阵详解
- Android-Matrix矩阵
- Android的Matrix(矩阵)
- Android Matrix(变形矩阵)
- Android矩阵原理详解(Matrix,ColorMatrix)
- Android矩阵原理详解(Matrix,ColorMatrix)
- Android矩阵原理详解(Matrix,ColorMatrix)
- Android矩阵原理详解(Matrix,ColorMatrix)
- Android矩阵原理详解(Matrix,ColorMatrix)
- Android中的矩阵转换 (Matrix转换)
- Android OpenGL_ES2.0 理解矩阵Matrix
- Android变形矩阵——Matrix
- 矩阵Matrix
- Matrix 矩阵
- 矩阵(Matrix)
- Matrix矩阵
- 矩阵(Matrix)
- Android学习笔记进阶八之Matrix矩阵
- CSS_背景
- DP-编辑距离问题
- 简单计算 (sdut oj)
- 求1+2+3+...+n(逻辑题)
- (五)play之yabe项目【评论】
- Android-Matrix矩阵
- Unity简单触屏判断
- SDWebImage源码解读 之SDWebImageDownloaderOperation
- python 界面编程 并执行sh命令
- 存储过程与触发器的区别
- codeforces 760E or 759C 【线段树维护后缀和】
- 三 . css语法、样式表
- PAT甲级1032
- 重载与重写