Understanding of Android Matrix

foreword

The most important thing in Android drawing is the Matrix class, and it is not easy to understand. I have used it before, but I didn't master it very well, so I just have time to summarize it.

1. Basics

1.1 Matrix

Matrix is ​​a matrix, a very important tool in mathematics. It is used for coordinate conversion in Android. This blog post mainly records the use of APIs related to preXXX and postXXX of images in Matrix in Android. It does not do too much about the mathematical principles of matrices. get to the bottom.

Android's most classic picture of Matrix:
Matrix
So for the summary of the above picture:

  • Scale (Scale)
    corresponds to MSCALE_X and MSCALE_Y
  • The displacement (Translate)
    corresponds to MTRANS_X and MTRANS_Y
  • Skew
    corresponds to MSKEW_X and MSKEW_Y
  • Rotate (Rotate)
    There is no special value to calculate the rotation, Matrix will handle the rotation by calculating scaling and miscutting.

1.2 Preparatory knowledge for using Matrix

It is very important to fully understand the concept of the coordinate origin of the picture for using Matrix. For this concept, the following two points are summarized:

  • All operations (rotation, translation, scaling, stagger) are by default based on the origin of the coordinates.
  • The coordinate system state of the previous operation will be preserved and affect the subsequent state.

Take a chestnut:

canvas.drawBitmap(mBitmap, 0, 0 , null);

The picture will be drawn in the upper left corner of the canvas, and the origin is the upper left corner of the canvas, which is also the upper left corner of the picture itself.
demo results
Where the red arrow points is the origin.
In fact, the origin of the coordinates is the upper left corner of the picture itself. You can do an experiment on this point:
Test code:

private void drawMatrix(Canvas canvas){
    
    
		// 原图
        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        // 从mBitmap中copy出来一张新的bitmap
        Bitmap newBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);
        // 居中位置
        float px = (getWidth() - mBitmap.getWidth()) / 2.0f;
        float py = (getHeight() - mBitmap.getHeight()) / 2.0f;
        // 原图移动位置后再顺时针旋转90度
        mLocationMatrix.preTranslate(px, py);
        mLocationMatrix.preRotate(90);
        // draw原图和新图
        canvas.drawBitmap(mBitmap, mLocationMatrix, null);
        // 新图居中显示
        canvas.drawBitmap(newBitmap, px, py, null);
}

Running result:
demo results
Through running the result, it can be seen that the picture in the middle is indeed rotated 90 degrees clockwise around its upper left corner.
With the above concepts, you can continue to learn about Matrix's preXXX and postXXX related APIs.

Two. preXXX and postXXX

2.1 Right multiplication and left multiplication

For me, the most troublesome thing about learning Matrix is ​​to figure out the execution sequence of related APIs such as preTranslate and postTranslate, preRotate and postRotate.

To know this order relationship, you need to know the mathematical operations involving matrices, right multiplication and left multiplication of matrices.
Directly give this operation law, you need to remember this rule :
(important)

// tips: 这里的M是原始矩阵,A是诸如平移,缩放等矩阵,M'是结果矩阵
preXXX  : 右乘, M' = M*A (右乘是因为A在右边)
postXXX : 左乘, M' = A*M (左乘是因为A在左边)

Let: T=translate, R=rotate, S=scale

  1. All preXXX related APIs:
matrix.preTranslate(px, py);
matrix.preRotate(90);
matrix.preScale(0.5f, 0.5f);

According to the above rules, it can be written as:
M' = M * T * R * S (right multiplication)

  1. All postXXX related APIs:
matrix.postTranslate(px, py);
matrix.postRotate(90);
matrix.postScale(0.5f, 0.5f);

M' = S * R * T * M (left multiplication)

  1. Hybrid operation:
matrix.postTranslate(px, py);
matrix.preRotate(90);
matrix.preScale(0.5f, 0.5f);

M' = T * M * R * S
However, for writing code, it is not recommended to mix them. You should either use pre-multiplication or post-multiplication.

So what's the use of knowing this?
When we get results such as M' = M * T * R * S through the above rules , we only need to remove M and then execute in order from left to right. This execution order is the front and rear execution order of using postXXX and preXXX related APIs .

So the order of execution:

  • The order of M' = M * T * R * S is to translate first, then rotate, and finally scale.
  • The order of M' = S * R * T * M is to scale first, then rotate, and finally translate.

2.2 Verification rules

Finally, verify this rule:
the following piece of code wants to move the picture to the middle of the canvas, and also needs to display the picture upside down.

		mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
       	// 居中显示
        float px = (getWidth() - mBitmap.getWidth()) / 2.0f;
        float py = (getHeight() - mBitmap.getHeight()) / 2.0f;
        // 先preRote
        matrix.preRotate(180,
                mBitmap.getWidth() / 2.0f,
                mBitmap.getHeight() / 2.0f
        );
        // 后postTranslate
        matrix.postTranslate(px, py);
        canvas.drawBitmap(mBitmap, matrix, null);

Intuitively, the above code gives people the feeling of first rotating and then translating. In fact, according to the law of left multiplication and right multiplication above, it should be:
M' = T * M * R First translate to the position of (px, py), and finally rotate 180 degrees according to the center point of the picture.

Running result:
insert image description here
successfully center the picture and display it upside down.

3. Coordinate origin

As mentioned earlier, all operations (rotation, translation, scaling, and miscutting) are by default based on the origin of coordinates .
Let's verify it:

// 相对图片中心点旋转180度
matrix.preRotate(180, mBitmap.getWidth() / 2.0f, mBitmap.getHeight() / 2.0f);

Running results:
insert image description here
When matrix is ​​initialized, it is actually an identity matrix.
insert image description here
You can see that the values ​​at positions 2 and 5 are 0, which means that there is no movement. Then the birthplace of the picture is the upper left corner of the canvas, which is the top left corner of the picture. upper left corner. When rotating, the rotation angle is based on the midpoint of the picture.
So when writing the code, if the picture has been translated to other positions of the canvas, and the picture needs to be rotated by a certain angle, then just rotate half of the width and height of the picture directly.
Similar to the following code:

matrix.preTranslate(px, py);
matrix.preRotate(180, mBitmap.getWidth() / 2.0f, mBitmap.getHeight() / 2.0f
);

Finish

After mastering the left multiplication and right multiplication of the matrix and the origin of the coordinates, it will be very easy to write code related to the matrix. I wish you all the best in your studies and get ashore soon!

Guess you like

Origin blog.csdn.net/RQ997832/article/details/131526376