The previous article “Anatomy of Matrix Principle” introduced the basic principle of Matrix, and this paper introduced some common methods and specific application scenarios of Matrix

Matrix method in detail

The parts and pictures reference since: blog.csdn.net/gb702250823…

Method category The relevant API Abstract
Numerical operations Set, reset, setValues, getValues Set, reset, set values, get values
Numerical calculation MapPoints, mapRadius, mapRect, mapVectors Compute the transformed value
Set up the SetConcat, setRotates, setScale, setSkew, setTranslate Set the transform
Before take PreConcat, preRotate, preScale, preSkew, preTranslate By transformation before
After a PostConcat, postRotate, postScale, postSkew, and postTranslate After take the transform
Special methods SetPolyToPoly, setRectToRect Some special operations

Numerical operations

void set(Matrix src)

A deep copy of SRC data into the current Matrix. If SRC is null, it is reset

void reset()

Resets the current Matrix to an identity Matrix

void setValues(float[] values)

Copies the first nine bits of a set of floating-point values into the Matrix. Calling this method throws an exception if the array length is less than nine

void getValues(float[] values)

Copy data from Matrix to values float array

Numerical calculation

MapXXX has many signature versions, specific differences can refer to the source notes, here according to one of the commonly used signature methods as an illustration, the same as below

void mapPoints(float[] dst, float[] src)

Apply the current Matrix to all coordinates indicated by SRC, and then copy the transformed coordinates to the DST array

Each two adjacent points in the array represent a coordinate (x,y), so the array length is usually even, otherwise the last value is not counted

float mapRadius(float radius)

Apply the current Matrix to the circle whose radius is indicated by RADIUS, and then return the radius of the transformed circle. Since the circle may be transformed into an ellipse due to the canvas, the average radius is measured here

boolean mapRect(RectF dst, RectF src)

Similar to mapPoints, apply the current Matrix to the four vertices indicated by SRC, and then write the values of the four transformed vertices into DST. The return value is to determine whether the rectangle is still a rectangle after transformation

void mapVectors(float[] dst, float[] src)

Similar to mapPoinst and mapRect, this test computes vectors and is not detailed

Set up the

SetRotates, setScale, setSkew, setTranslate

These methods are easy to understand, that is, to set the transformation to the current Matrix and get a transformed Matrix

boolean setConcat(Matrix a, Matrix b)

Equivalent to computing two matrices multiplied by a × b and assigning the result to the current matrix, i.e. c. setconcat (a, b) means c = a × b

Before take after take

These two kinds of calculation are also easier to understand, that is, corresponding to the matrix multiplication and multiplication in mathematics

Special methods

boolean setPolyToPoly

boolean setPolyToPoly (
        float[] SRC, // original vertex array SRC [x, y]intSrcIndex, // Start of the original vertex arrayfloat[] DST, // Destination vertex array DST [x, y]intDstIndex, // Start position of target vertex arrayint pointCount)	// The number of vertices ranges from 0 to 4
Copy the code

Poly stands for Polygon.

This method computes the transformation from the original vertex to the destination vertex (meaning SRC and DST are one-to-one) and stores the transformation information in the current Matrix. By applying the Matrix obtained to any graph, the graph can be transformed into the shape represented by Matrix. The effect is shown in the figure below

The most commonly used pointCount is 4,0, and 3, which can be implemented in simpler ways

pointCount Abstract
0 The equivalent ofreset
1 The equivalent ofTranslate
2 You can scale, rotate, and translate
3 It can perform scaling, rotation, translation, and tangent transformation
4 You can scale, rotate, translate, misshear, and any deformation

Selection of measurement and control points

You can choose any location you think convenient, as long as SRC corresponds to DST one by one. However, for convenience, special points are usually selected: the four corners of the figure, the center of the edges, and the center of the figure. But one thing to note, it is not repeated measurement and control point selection should be (SRC and DST is so), if choose the repeat points will directly lead to measure failure, this also means that you are not allowed to be a square (4 points) mapped to triangle (four points, but the two position overlap), but it can be close to the triangle.

scope

Scope is the entire area of the Matrix. If you assign the Matrix to the Canvas, its scope is the entire Canvas. If you assign the Matrix to the Bitmap, its scope is the entire image

boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf)

In most cases, the length ratio of the source rectangle to the target rectangle is inconsistent. How to fill the source rectangle is determined by the third parameter STF

ScaleToFit is an enumerated type that contains four modes:

model The effect
CENTER In the middle,srcScale and fill the transformed rectangle to the maximum and center it indst
START At the top ofsrcEqual scale and maximize fill transform the rectangle after placing it indstTop left corner of the, top left aligned
END At the bottom,srcEqual scale and maximize fill transform the rectangle after placing it indstThe bottom right corner of the
FILL Fill, stretchsrcThe width and height make it completely filleddst

A picture is worth a thousand words:

Matrix usage scenarios in Android

In fact, we have more or less come into contact with Matrix in daily development, but most of us are not aware of it. For example, the ScaleType of ImageView we use is actually internally implemented through Matrix

In addition, Matrix has a wide range of applications, which cannot be listed here. After learning basic principles and common apis, people can imagine and practice by themselves. There are also many interesting examples of Matrix application on the Internet.

Here I would like to share with you the example of Matrix used in actual development — camera scanning to identify two-dimensional code

When I was developing this function, I encountered a tricky problem: when the camera recognized the TWO-DIMENSIONAL code in real-time preview, it needed to intercept the current frame as a static background image, and then display a small yellow dot on the position of the two-dimensional code recognized, similar to the effect of wechat code scanning:

First of all, we need to introduce the general process of camera recognition of two-dimensional code

Real-time view taking of camera viewfinder frame -> image frame preprocessing (including clipping and grayscale, etc.) -> Scan code SDK to analyze the preprocessed frame image -> identify the TWO-DIMENSIONAL code and return the two-dimensional code information (including the position in the picture, etc.) -> set the original frame of the current image as the background picture -> draw the yellow dot at the position of the two-dimensional code on the picture

Since the SDK analyzes the image after graying, the location information of the TWO-DIMENSIONAL code returned is also based on the coordinate system after cutting. If we draw this coordinate directly on the screen, we will inevitably find the incorrect location of the two-dimensional code

This is where coordinate mapping comes in: we need to map the cropped coordinates back to the screen coordinates of the phone

Let’s take a look at what we currently have:

  1. Cropped image
  2. Two-dimensional code location information is a group of vertices (up, down, left and right points x, Y)
  3. Viewfinder size

We can analyze that what has changed here are two rectangles: the viewfinder and the cropped image

Based on what we learned, we can use setPolyToPoly or setRectToRect to describe this transformation. Here we use setPolyToPoly as an example, pseudo code is as follows:

// Instantiate a primitive matrix (identity matrix)
val matrix = Matrix()

// cropRect is the rectangle of the cropped image
val source = floatArrayOf(
    cropRect.left.toFloat(),
    cropRect.top.toFloat(),
    cropRect.right.toFloat(),
    cropRect.top.toFloat(),
    cropRect.right.toFloat(),
    cropRect.bottom.toFloat(),
    cropRect.left.toFloat(),
    cropRect.bottom.toFloat()
)

// previewView is the viewfinder view
val destination = floatArrayOf(
    0f.0f,
    previewView.width.toFloat(),
    0f,
    previewView.width.toFloat(),
    previewView.height.toFloat(),
    0f,
    previewView.height.toFloat()
)

// Use setPolyToPoly to describe this transformation and get a Matrix Matrix
// By default, the clipped image is not rotated, otherwise it needs to be rotated
matrix.setPolyToPoly(source, 0, destination, 0.4)
Copy the code

After obtaining the Matrix, mapPointsToPoints can be used to calculate the position coordinates of the TWO-DIMENSIONAL code with the Matrix transformation

val srcArray = it.position.toFloatArray() // Represents the original coordinate data of the TWO-DIMENSIONAL code
val destArray = FloatArray(srcArray.size) // Represents the calculated two-dimensional code coordinate data, that is, the position on the camera viewfinder
matrix.mapPoints(destArray, srcArray)
Copy the code

In this way, we can accurately mark the location of the QR code on the camera screen

My blog is synchronized to tencent cloud + community, invite everyone to come together: cloud.tencent.com/developer/s…