上篇文章介绍了 Matrix基本原理方法 ,这篇文章介绍下Matrix的其他比较常用的方法。

1、mapPoints :计算一组点基于当前Matrix变换后的位置。

其有三个重载方法:

void mapPoints (float[] pts)
void mapPoints (float[] dst, float[] src)
void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount)

<1> void mapPoints(float [ ] pts)  -- 计算结果依然放置pts中,示例如下:

//初始数据为三个点 (0, 0) (80, 100) (400, 300)
float[] pts = new float[] {0, 0, 80, 100, 400, 300};
//构造一个Matrix,并使其x轴坐标缩放0.5
Matrix mMatrix = new Matrix();
mMatrix.setScale(0.5f, 1f);
//输出原有的pts值
Logger.d("before:" + Arrays.toString(pts));
//调用mapPoints方法计算,即将Matrix的值映射至pts中
mMatrix.mapPoints(pts);
//属于计算后的pts值
Logger.d("after:" + Arrays.toString(pts));

<2> void mapPoints(float[ ] dst, float[ ] src) -- 用于存放原始数据与目标数据:

* 原始数据需要保留,用此方法 float[] src = new float[] {0, 0, 80, 100, 400, 300}; float[] dst = new float[] {0, 0, 0, 0, 0, 0}; mMatrix.setScale(0.5f, 1f); Logger.d("before:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst)); mMatrix.mapPoints(dst, src); Logger.d("after:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst));

<3> void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) -- 可以指定只计算一部分数值:

* 将第二个第三个计算后存储在dst最初始位置 float[] src = new float[] {0, 0, 80, 100, 400, 300}; float[] dst = new float[6]; mMatrix.setScale(0.5f,1f); Logger.d("before:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst)); mMatrix.mapPoints(dst,0,src,2,2); Logger.d("before:\n" + "src:" + Arrays.toString(src) + " dst:" + Arrays.toString(dst));

2、mapRadius: 测量半径(由于圆可能会因为画布变换变成椭圆,所以此处测量的是平均半径)。

float mapRadius(float radius) 
float radius = 100;
float result;
mMatrix.setScale(0.5f, 1f);
Logger.d("before:mapRadius " + radius);
result = mMatrix.mapRadius(radius);
Logger.d("after:mapRadius " + result);

3、mapRect: 测量矩阵变换后位置,将结果放置rect中:

其有两个重载方法(第二种与mapPoint同参数方法类似,故不做过多介绍):

boolean mapRect (RectF rect)
boolean mapRect (RectF dst, RectF src)
* 返回值是boolean值,表示矩阵经过变换后是否依然为矩阵(这里使用了斜切,故返回值是false) RectF rectF = new RectF(400, 400, 1000, 800); mMatrix.setScale(0.5f, 1f); mMatrix.postSkew(1, 0); Logger.d("before:mapRect:" + rectF.toString()); boolean result = mMatrix.mapRect(rectF); Logger.d("after:mapRect:" + rectF.toString()); Logger.d("result:" + result);

4、mapVectors: 测量向量,与mapPoints的构造方法及使用基本相同,唯一的区别是测量向量不受位移的影响。

float[] src = new float[]{1000, 800};
float[] dst = new float[2];
// 构造一个matrix
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 1f);
matrix.postTranslate(100,100);
// 计算向量, 不受位移影响
matrix.mapVectors(dst, src);
Log.i(TAG, "mapVectors: "+Arrays.toString(dst));
// 计算点
matrix.mapPoints(dst, src);
Log.i(TAG, "mapPoints: "+Arrays.toString(dst));

5、setPolyToPoly: 根据数组点参数将矩形变换成其他多边形。

* src:原始数组,存储内容为一组点(包含x,y坐标) * srcIndex:原始数组开始位置 * dst:目标数组,存储内容为一组点(包含x,y坐标) * dstIndex:目标数组开始位置 * pointCount:测控点的数量,取值范围(0~4) boolean setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)

下面通过一个具体的实例View,来看一下矩阵的setPolyToPoly方法产生的效果:

public class MatrixSetPolyToPolyView extends View {
    private Matrix mMatrix;
    private Bitmap mBitmap;
    private Paint mPaint;
    public MatrixSetPolyToPolyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initBitmapAndMatrix();
    private void initBitmapAndMatrix() {
        mPaint = new Paint();
        mPaint.setColor(Color.BLUE);
        mMatrix = new Matrix();
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
        float[] src = new float[] {0, 0, mBitmap.getWidth(), 0, mBitmap.getWidth(), mBitmap.getHeight(), 0,
            mBitmap.getHeight()};
        float[] dst = new float[] {0, 0, mBitmap.getWidth(), 100, mBitmap.getWidth(), mBitmap.getHeight() - 100, 0,
            mBitmap.getHeight()};
        //多边形变换
        mMatrix.setPolyToPoly(src, 0, dst, 0, 4);
        mMatrix.postTranslate(0, 200);
    @Override
    protected void onDraw(Canvas conDrawanvas) {
        super.onDraw(conDrawanvas);
        conDrawanvas.drawBitmap(mBitmap, mMatrix, mPaint);

实例效果如下:

6、setRectToRect:将源矩阵的内容添加到目标矩阵中。

* src:源区域 * dst:目标区域 * stf:缩放适配模式 boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf)

其中stf参数类似于ImageView的ScaleType属性,但只有四个参数可供选择:

模式 摘要
CENTER 居中,对src 等比例缩放 ,将其居中放置在dst中。
START 顶部,对src 等比例缩放 ,将其放置在dst的左上角。
END 底部,对src 等比例缩放 ,将其放置在dst的右下角。
FILL 充满, 拉伸 src的宽和高,使其完全填充满dst。

我们使用CENTE来举例说明,初始代码如下:

public class MatrixSetRectToRectView extends View {
    private Matrix mMatrix;
    private Bitmap mBitmap;
    private Paint mPaint;
    public MatrixSetRectToRectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initBitmaAndMatrix();
    private void initBitmaAndMatrix() {
        mMatrix = new Matrix();
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
        mPaint = new Paint();
    @Override
    protected void onDraw(Canvas conDrawanvas) {
        super.onDraw(conDrawanvas);
        conDrawanvas.drawBitmap(mBitmap, mMatrix, mPaint);

代码很简单,我们使用一个自定义View来展示一张图片,效果如下:

下面我们使用setRectToRect方法,stf属性选择CENTER,代码如下:

public class MatrixSetRectToRectView extends View {
    private Matrix mMatrix;
    private Bitmap mBitmap;
    private Paint mPaint;
    private int mViewWidth, mViewHeight;
    public MatrixSetRectToRectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        Logger.d("MatrixSetRectToRectView--执行顺序1");
        initBitmaAndMatrix();
    private void initBitmaAndMatrix() {
        mMatrix = new Matrix();
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
        mPaint = new Paint();
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Logger.d("onSizeChanged--执行顺序2");
        mViewWidth = w;
        mViewHeight = h;
    @Override
    protected void onDraw(Canvas conDrawanvas) {
        super.onDraw(conDrawanvas);
        Logger.d("onDraw--执行顺序3");
        RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
        RectF dst = new RectF(0, 0, mViewWidth, mViewHeight);
        //使用矩阵的setRectToRect方法,stf属性选用CENTER(即等比居中显示)
        mMatrix.setRectToRect(src, dst, ScaleToFit.CENTER);
        //使用画布根据目标区域绘制mBitmap
        conDrawanvas.drawBitmap(mBitmap, mMatrix, mPaint);

这里需要注意的一点是View的关键生命周期为(可自行验证): 
构造View() –> onMeasure() –> onSizeChanged() –> onLayout() –> onDraw()。

故代码中三个方法执行顺序如下:

这样我们在绘制(onDraw)的时候已经获取到ImageView的mViewWidth和mViewHeight,而其均已设置为屏幕的宽高,故修改后的图片展示效果如下:

可以看到,原有的图片在源区域的基础上已经等比缩放居中至目标区域。

7、isIdentity:判断当前矩阵是否是单位矩阵。

boolean isIdentity() 

8、isAffine:判断当前矩阵是否是仿射矩阵(需要API 21及以上)。

boolean isAffine()

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

9、rectStaysRect:判断矩形经过变换后是否仍为矩形。

boolean rectStaysRect()

当矩阵是单位矩阵,或者只进行平移,缩放,以及旋转90度的倍数的时候,返回true。

10、reset:重置矩阵为单位矩阵。

void reset() 

本篇基本讲解了Matrix的一些常用方法,在做图形变换的时候,某些方法还是会经常用到的,建议先阅读下上篇Matrix基本原理方法,理解可能会更深刻一些。

Android开发中,矩阵是一个功能强大并且应用广泛的神器,例如:用它来制作动画效果、改变图片大小、给图片加各类滤镜等。对于矩阵,Android官方SDK为我们提供了一个强大的类Matrix(还有ColorMatrix)是一直困扰着我的问题,虽然大致能够调用相应的API,但却一直get不到其内在的梗。但是出来混总是别想着蒙混过关的,所以最近重新操起一年毕业的线性代数,再本着小事问老婆,大事问Google的心态,终于把多年不解的问题给破了。出于好记性不如烂笔头的原因,便有了本文。读完本文,相信你能够搞明白以下三个问题:1.为什么Matrix是个3X3的矩阵2.Matrix这个3X3的矩阵每个元 Android View 通过平移、旋转、缩放后,顶点映射之前写的这个文章,里面用到的是通过 矩形的4个点来映射出新的4个点。个人以为这就会得到正确的结果。最近呢,就想着,验证一下这个是不是正确的验证想法:“基于 变换后的 ltrb,加一个自定义 view layout;有最外层 view那么大;当 view 变换后,在 layout 上以 ltrb为圆心, 画出一个小圆”最终发现,旋转 用会有问题... 1 概述这里我们会详细讲解matrix的各个方法,以及它的用法。matrix叫做矩阵,在前面讲解 ColorFilter 的文章中,我们讲解了ColorMatrix,他是一个4*5的矩阵。而这里,我们讲解的Matrix不是用于处理颜色的,而是处理图形的。他是一个3*3的矩阵。2 原理先看看matrix的矩阵是什么样子的:这里可以查看Matrix的代码得到。那么这个矩阵分别代表了什么呢,这里通 在android的自定义View中,使用Matrix来转换坐标非常方便,其中有一个方法mapPoints,它的计算方式是怎么样的呢?首先来看看Matrix矩阵长得什么样?它是一个3x3的矩阵。 在编程里,它对应一个长度为9的float[]数组,通过以下变量准确取到数组中相应的值。 现在再来看看,每一位的含意:好了,我们现在来看一下,mapPoints的计算过程: 那么mapPoints的计算方式就如上所示了。... 1、Matrix : mapPoint() mapRect(src,dst)...根据矩阵将src内容转化并存储到dst中; 矩阵操作,preTranslate(dx,dy) = Matrix*t(dx,dy); postTranslate(dx,dy) = t(dx,dy)*Matrux 2、Movie:根据api来看,应该代笔的就是电影,有duration 关于流和文件的操作 最近公司要我做平面识别,完全没头绪,想到AR上有这种功能就去找,最初找到PTAM,可是代码太久远了,没搞好,然后发现ORB_SLAM2,虽然不知道可不可以实现平面识别,不过把ORB_SLAM2给搬到了android studio上了,分享一下本来参考ORB_SLAM2在Android上的移植过程 (Android Studio 2.2+OpenCV 3.2+Cmake) 这篇文章的,可是没成功,就... 1 MatrixAndroid 中的运用 ImageView 缩放模式 setImageMatrix(mMatrix) 方法,可以自定义一个Matrix。 对 Bitmap 做相应的处理,如缩放,位移。 Matrix 可以对 Rect 和 点的集合做变换处理 public void mapPoints(float[] pts) { mapPoints(pts, 0,... 通过前面的分析,我们知道了调整颜色矩阵可以改变一副图像的色彩效果,图像处理很大程度上就是在寻找处理图像的颜色矩阵。不仅仅可以通过Android系统提供的API来进行ColorMatrix的修改,同样可以精确地修改矩阵的值来实现颜色效果的处理。 下面我们就模拟一个4*5的颜色矩阵。通过修改矩阵中的值,一来验证全面所说的改变图像色彩效果的原理是否正确,二来对矩阵变换产生的作用效果有更清晰地认识。程序... 好了,前面主要讲了Animation,Animator 的使用,以及桌面火箭效果和水波纹效果,分别使用android框架和自己绘制实现,俗话说,工欲善其事,必先利其器,接下来几篇文章主要讲绘制中我们需要常使用的一些利器; Paint:画笔 Canvas:画布 Matrix:变换矩阵 绘制动效确实就像拿着笔在画布上面画画一样,而Paint就是我们拿着的笔,Canvas就是使用的画布; 最近在项目中使用到了PhotoView来针对图片进行缩放处理,原本绘制在Bitmap上的内容位置就发生了偏移,在此记录一下解决步骤。在PhotoView缩放操作中,图片本身的大小是不变的,图片的所有平移缩放等操作都是采用Matrix类来操作public void setScale(float scale, float focalX, float focalY,boolean animate) {/... import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matr 在例子Android ApiDemos示例解析(74):Graphics-&gt;PolyToPoly 介绍在已知变换前后的坐标然后根据Matrix.setPolyToPoly 得到对于的变换矩阵。 此外Matrix也支持提供变换前后的两个矩形,通过setRectToRect 取得对应的变换矩阵。来看看setRectToRect 的定义: public boolean setRectToRec...