Comprensión de Android Matrix

prefacio

Lo más importante en el dibujo de Android es la clase Matrix, y no es fácil de entender. Lo he usado antes, pero no lo domino muy bien, así que solo tengo tiempo para resumirlo.

1. Conceptos básicos

1.1 Matriz

Matrix es una matriz, una herramienta muy importante en matemáticas. Se usa para la conversión de coordenadas en Android. Esta publicación de blog registra principalmente el uso de API relacionadas con preXXX y postXXX de imágenes en Matrix en Android. No hace demasiado sobre los principios matemáticos de las matrices llegar al fondo.

La imagen más clásica de Android de Matrix:
Matriz
Entonces, para el resumen de la imagen de arriba:

  • Escala (Scale)
    corresponde a MSCALE_X y MSCALE_Y
  • El desplazamiento (Translate)
    corresponde a MTRANS_X y MTRANS_Y
  • El sesgo
    corresponde a MSKEW_X y MSKEW_Y
  • Girar (Rotar)
    No hay un valor especial para calcular la rotación, Matrix manejará la rotación calculando la escala y el corte erróneo.

1.2 Conocimientos preparatorios para usar Matrix

Es muy importante entender completamente el concepto de origen de coordenadas de la imagen para usar Matrix, para este concepto se resumen los siguientes dos puntos:

  • Todas las operaciones (rotación, traslación, escala, escalonamiento) se basan por defecto en el origen de las coordenadas.
  • El estado del sistema de coordenadas de la operación anterior se conservará y afectará al estado posterior.

Toma una castaña:

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

La imagen se dibujará en la esquina superior izquierda del lienzo, y el origen es la esquina superior izquierda del lienzo, que también es la esquina superior izquierda de la imagen misma.
resultados de demostración
Donde apunta la flecha roja es el origen.
De hecho, el origen de las coordenadas es la esquina superior izquierda de la propia imagen.Puedes hacer un experimento sobre este punto:
Código de prueba:

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);
}

Resultado de la ejecución:
resultados de demostración
a través del resultado de la ejecución, se puede ver que la imagen en el medio está girada 90 grados en el sentido de las agujas del reloj alrededor de su esquina superior izquierda.
Con los conceptos anteriores, puede seguir aprendiendo sobre las API relacionadas con preXXX y postXXX de Matrix .

2. preXXX y postXXX

2.1 Multiplicación por la derecha y multiplicación por la izquierda

Para mí, lo más problemático de aprender Matrix es averiguar la secuencia de ejecución de las API relacionadas, como preTranslate y postTranslate, preRotate y postRotate.

Para conocer esta relación de orden, es necesario conocer las operaciones matemáticas que involucran matrices, la multiplicación por la derecha y la multiplicación por la izquierda de matrices.
Dé directamente esta ley de operación, debe recordar esta regla :
(importante)

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

Sea: T=traducir, R=rotar, S=escala

  1. Todas las API relacionadas con preXXX:
matrix.preTranslate(px, py);
matrix.preRotate(90);
matrix.preScale(0.5f, 0.5f);

De acuerdo con las reglas anteriores, se puede escribir como:
M' = M * T * R * S (multiplicación derecha)

  1. Todas las API relacionadas con postXXX:
matrix.postTranslate(px, py);
matrix.postRotate(90);
matrix.postScale(0.5f, 0.5f);

M' = S * R * T * M (multiplicación izquierda)

  1. Operación híbrida:
matrix.postTranslate(px, py);
matrix.preRotate(90);
matrix.preScale(0.5f, 0.5f);

M' = T * M * R * S
Sin embargo, para escribir código, no se recomienda mezclarlos, debe usar pre-multiplicación o post-multiplicación.

Entonces, ¿de qué sirve saber esto?
Cuando obtenemos resultados como M' = M * T * R * S a través de las reglas anteriores , solo necesitamos eliminar M y luego ejecutar en orden de izquierda a derecha. Este orden de ejecución es el orden de ejecución frontal y posterior del uso de postXXX y API relacionadas con preXXX.

Así que el orden de ejecución:

  • El orden de M' = M * T * R * S es trasladar primero, luego rotar y finalmente escalar.
  • El orden de M' = S * R * T * M es escalar primero, luego rotar y finalmente trasladar.

2.2 Reglas de verificación

Finalmente, verifique esta regla:
la siguiente pieza de código quiere mover la imagen al medio del lienzo y también necesita mostrar la imagen al revés.

		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);

Intuitivamente, el código anterior le da a la gente la sensación de primero rotar y luego traducir. De hecho, de acuerdo con la ley de la multiplicación por la izquierda y la multiplicación por la derecha anterior, debería ser:
M' = T * M * R Primero traslade a la posición de (px, py), y finalmente gire 180 grados de acuerdo con el punto central de la imagen.

Resultado de ejecución:
inserte la descripción de la imagen aquí
centre con éxito la imagen y muéstrela al revés.

3. Origen de coordenadas

Como se mencionó anteriormente, todas las operaciones (rotación, traslación, escalado y cortes erróneos) se basan por defecto en el origen de las coordenadas .
Vamos a verificarlo:

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

Ejecución de resultados:
inserte la descripción de la imagen aquí
cuando se inicializa la matriz, en realidad es una matriz de identidad.
inserte la descripción de la imagen aquí
Puede ver que los valores en las posiciones 2 y 5 son 0, lo que significa que no hay movimiento. Entonces, el lugar de nacimiento de la imagen es la parte superior esquina izquierda del lienzo, es decir, la esquina superior izquierda de la imagen esquina superior izquierda. Al girar, el ángulo de rotación se basa en el punto medio de la imagen.
Entonces, al escribir el código, si la imagen se ha traducido a otras posiciones del lienzo y la imagen debe girarse en un cierto ángulo, simplemente gire la mitad del ancho y la altura de la imagen directamente.
Similar al siguiente código:

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

Finalizar

Después de dominar la multiplicación por la izquierda y la multiplicación por la derecha de la matriz y el origen de las coordenadas, será muy fácil escribir código relacionado con la matriz. ¡Les deseo todo lo mejor en sus estudios y lleguen pronto a tierra!

Supongo que te gusta

Origin blog.csdn.net/RQ997832/article/details/131526376
Recomendado
Clasificación