深入理解 Android 中的Matrix

在 Android 开发中,矩阵可以是一个功能强大并且应用广泛的神器!

原文链接:http://geek.csdn.net/news/detail/89873

作者:D_clock

 

在 Android 开发中,矩阵是一个功能强大并且应用广泛的神器,例如:用它来制作动画效果、改变图片大小、给图片加各类滤镜等。对于矩阵,Android 官方 SDK 为我们提供了一个强大的类 Matrix (还有 ColorMatrix )是一直困扰着我的问题,虽然大致能够调用相应的 API ,但却一直 get 不到其内在的梗。但是出来混总是别想着蒙混过关的,所以最近重新操起一年毕业的线性代数,再本着小事问老婆,大事问Google的心态,终于把多年不解的问题给破了。出于好记性不如烂笔头的原因,便有了本文。在此先感谢下面两篇令我茅舍顿开的文章:

读完本文,相信你能够搞明白以下三个问题:

  • 为什么 Matrix 是个 3 X 3 的矩阵
  • Matrix 这个 3 X 3 的矩阵每个元素的作用
  • Matrix 的 setXXX、preXXX、postXXX API 方法的工作原理

Matrix 的结构

Matrix 是 Android SDK 提供的一个矩阵类,它代表一个 3 X 3 的矩阵(不懂矩阵为何物的童鞋就要自行 Google 了)。 Matrix 提供了让我们获得 Matrix 值的 API —— getValues

利用此 API 传入一个长度为 9 的 float 数组,即可获得矩阵中每个元素的值。那么这 9 个浮点数的作用和意义是什么呢,从 Android 官方文档上看,它为这个数组中的每一个元素都定义了一个下标常量

这个 9 个常量取值分别是 0 - 8

如果我们将这个 float 排成直观的矩阵格式,那它将是下面这样子的

实际上我们平常利用 Matrix 来进行 Translate(平移)、Scale(缩放)、Rotate(旋转)的操作,就是在操作着这个矩阵中元素的数值来达到我们想要的效果。但是现在问题来了,上面提到的平移、缩放、旋转操作中,旋转和缩放可以用乘法表示,而平移就只能用加法表示,而且 Matrix 是一个 3 X 3 的矩阵,实际上表示这些操作 2 X 2 的矩阵足矣!

如上,可以依次看到平移、缩放、旋转的矩阵,其中

  • (x’,y’)表示执行操作后的点的坐标,(x,y)表示执行操作前的点的坐标
  • tx、ty 分别表示x轴、y轴上平移的距离,Sx、Sy 分别表示x轴、y轴上的缩放比例
  • θ 则表示旋转角度

至于上面矩阵的推导过程,网络上很多,这里就不去赘述了。以前到了这里,我就会很纳闷,为什么 2 X 2 矩阵能干的事情,偏偏要用 3 X 3 矩阵去做,直到遇到前面提到的两篇文章才有所领悟。

其实在计算机图形应用涉及到几何变换,主要包括平移、旋转、缩放。以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘。那些数学大神们为了方便计算,所以引入了一样神器叫做齐次坐标(不懂的童鞋,老规矩自行搜索),将平移的加法合并用乘法表示。所以,2 X 2 的矩阵经过一番变换后,成了下面这样的。

至此,我们可以得知为什么 Matrix 是一个 3 X 3 的矩阵,其实 2 X 2 的矩阵是足以表示的,不过是为了方便计算而合并写成了 3 X 3 的格式。

Matrix 元素的作用

一个 Matrix 共有 9 个元素,那么它每个元素的值发生改变会起到什么作用呢?按照前面所示的齐次坐标转换得到 3 X 3 的矩阵和 Android 文档提供的官方结构相对应,我们不难看出下面的对应关系(其实从 Matrix 中每个位置的常量命名也可以看出来):

从这我们可以看出这个 Matrix 结构中的每个参数发挥着如下作用:

  • MTRANS_X、MTRANS_Y 同时控制着 Translate
  • MSCALE_X、MSCALE_Y 同时控制着 Scale
  • MSCALE_X、MSKEW_X、MSCALE_Y、MSKEW_Y 同时控制着 Rotate
  • 从名称上看,我们可以顺带看出 MSKEW_X、MSKEW_Y 同时控制着 Skew

如果要进行代码验证的话,也非常简单,例如直接只对 Matrix 做 Translate 的 API 调用操作,再将 Matrix 的信息打印到控制台,你会发现整个 Matrix 确实只有 MTRANS_X、MTRANS_Y 两个位置的数字在发生变化。其他 Scale、Rotate、Skew 操作也是一样,感兴趣的童鞋可以自行代码验证一番。

至此,我们可以大致弄清矩阵每个元素的作用。至于 MPERSP_0、MPERSP_1、MPERSP_2 这三个参数,目前暂时不得而知,网上有文章说这三个参数控制着透视变换,但是文档和 API 上都没怎么提及,所以还是有待验证研究的,有明白的童鞋不妨留言赐教一下,不胜感激。

理解 Matrix API 调用

按照第一小节里面通过齐次坐标转换而来的矩阵方程可以知道,假设一根线执行了平移操作,相当于线上每个点的坐标被下方的矩阵左乘。(缩放和旋转操作也是同理)

如果要进行同时缩放、平移之类的符合变化操作,也无非就是选取相应的矩阵做左乘操作。为了加深矩阵变换对应 Matrix API 调用的理解,直接通过下面的一个自定义的动画效果和代码来讲解好了。


public class SimpleCustomAnimation extends Animation {

    private int mWidth, mHeight;

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        this.mWidth = width;
        this.mHeight = height;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        Matrix matrix = t.getMatrix();
        matrix.preScale(interpolatedTime, interpolatedTime);//缩放
        matrix.preRotate(interpolatedTime * 360);//旋转
        //下面的Translate组合是为了将缩放和旋转的基点移动到整个View的中心,不然系统默认是以View的左上角作为基点
        matrix.preTranslate(-mWidth / 2, -mHeight / 2);
        matrix.postTranslate(mWidth / 2, mHeight / 2);
    }
}

熟悉动画这块的童鞋肯定知道,Animation 就是通过不断改变 applyTransformation 函数传入的 Matrix 来实现各种各样的动画效果的,通过上面 applyTransformation 寥寥的几行 Matrix 的复合变换操作可以得到如下效果

实际上这几行代码用矩阵来表示就相当于如下所示:

关于代码的作用上边已经给出了注释,这里就不多写了。主要还是要弄明白 Matrix 复合变换中 pre 、 post 等操作与其对应的矩阵发生的左乘、右乘变化。

总结

到此,整篇文章已经完结,相信已经能够让你明白开头提到的三个问题。其实我们也可以发现,Google 封装了 Matrix 已经是很完美了,几乎屏蔽了所有的数学细节,使得我这种数学水平一般的开发者也能够去调用相应的 API 实现一些简单的效果。虽然被封装得很完美,但掌握相应的一些原理,依旧可以帮你更好的理解一些技术实现,此次加深了对 Matrix 一些操作的理解,帮我自己解决了以前不少的困惑,不知道有没有帮你 get 到一些什么呢?

上面给的示例代码很简单,复制黏贴即可运行玩耍,实在需要直接运行源码的童鞋就到 https://github.com/D-clock/AndroidStudyCode 找吧!

最新文章
1客户案例研究:专家安全扫描,守护金融银行小程序安全和私密性 WeTest私有化部署的定制扫描平台让金融银行客户能无成本接入扫描系统并迅速上手使用。客户能方便快捷地根据定制手册进行自助扫描,根据生成的扫描报告,详细洞察漏洞,快速识别并准确定位问题根源。
2客户案例研究:专家渗透测试,洞察电子商务小程序重大交易漏洞 通过WeTest渗透测试服务,某知名零售公司旗下的在线购物类小程序中发现了8处安全风险,我们的安全专家为客户提供了详细的漏洞报告,提供了较为清晰完整的安全加固方案。在回归测试中,中危以上风险均被解决。
3自查小程序4大安全隐患!文末免费赠送小程序安全扫描专业版! 腾讯WeTest现面向小程序开发者开放免费申请使用小程序安全扫描专业版,助您提前发现全面的安全漏洞。扫描文中问卷二维码或点击问卷链接,即可报名参与免费领取活动。
4浅谈渗透测试服务在泛互行业带来的价值 在泛互联网行业中,渗透测试服务对于保障企业的网络安全至关重要。
5云手机卡顿/无特定设备/商店登录受限怎么办?WeTest专有云帮您解决! 公有云满足了大量小微企业、个人的测试需求;随着客户深入使用,也遇到了一系列新问题。本篇将对几个常见问题予以解答
购买
客服
反馈