Matrix in Android: what it is, matrix types and working with transformations

Author: IT Sectr Published: 2026-07-22 Reading time: 9 min

Matrix — a class from the Android SDK (android.graphics.Matrix) representing an affine transformation through a 3×3 matrix. It is used for transforming graphic objects — moving, scaling, rotating and skewing. According to the Android Developers Documentation (2026), Matrix is the primary tool for working with transformations in Canvas, Bitmap and Drawable, providing precise coordinate control in custom drawing.

Key Takeaways

  • Matrix — Android class for affine and perspective transformations with a 3×3 matrix
  • Affine operations: translate, scale, rotate and skew
  • Matrix supports projective transformations via setPolyToPoly
  • Order of operations matters — Matrix.concat performs sequential multiplication
  • Matrix is applied to Canvas, Bitmap, RectF, PointF and Path in Android graphics

What is Matrix in Android?

Matrix (android.graphics.Matrix) — an Android SDK class representing a mathematical 3×3 matrix used for transforming two-dimensional coordinates. Matrix is the fundamental building block for all graphic transformations in Android — from Canvas movement and scaling to complex perspective distortions of Bitmap.

Unlike iOS, which uses separate CGAffineTransform (affine) and CATransform3D (3D) structures, Android combines affine and perspective transformations in a single Matrix class. The 3×3 matrix allows representing both standard affine operations (last row [0, 0, 1]) and perspective distortions where the last row contains arbitrary values. This provides more flexibility but requires understanding of matrix mathematics.

Matrix is tightly integrated with the Canvas API. When a developer calls canvas.translate(), canvas.scale() or canvas.rotate(), these methods internally modify the graphic context’s matrix. You can get the current Canvas matrix via canvas.getMatrix() and manually apply a custom one via canvas.setMatrix() or canvas.concat().

Matrix Transformation Types

Matrix supports four basic types of affine transformations: translate, scale, rotate, skew. Each type has methods for pre-multiplication (pre), post-multiplication (post) and setting (set). The difference between preTranslate and postTranslate lies in the order of matrix multiplication, which affects the final transformation when combining operations.

OperationMethodParametersDescription
TranslatesetTranslate / preTranslate / postTranslatedx, dyShift along X and Y axes
ScalesetScale / preScale / postScalesx, sy, px, pyScaling with pivot point
RotatesetRotate / preRotate / postRotatedegrees, px, pyRotation around pivot point
SkewsetSkew / preSkew / postSkewkx, kyTilt (shear) along axes

Translate — movement

Translate changes the position of all points by a given offset dx, dy. Positive dx shifts right, dy — down (in the Android screen coordinate system, the Y axis points down). Translate does not change the shape of the object — only its position. This is the simplest and most commonly used operation for positioning elements.

Scale — scaling

Scale changes the size of an object with factors sx (along X) and sy (along Y). The parameters px, py specify the pivot point for scaling. If px, py are not specified, scaling is performed relative to the origin (0, 0). When sx = sy, the object scales uniformly. Negative values create a reflection.

Rotate — rotation

Rotate rotates an object by a given angle (in degrees) around a pivot point (px, py). Positive degrees correspond to clockwise rotation (unlike iOS/macOS, where a positive angle is counterclockwise). If px, py are not set, rotation is performed around the origin.

Skew — skewing

Skew (shear) deforms an object by tilting it along the X axis (kx) or Y axis (ky). A value of 1.0 tilts by 45 degrees. Skew is used to create tilt effects, pseudo-3D appearances, and perspective distortion.

Structure of a 3×3 Matrix

Matrix stores its 3×3 elements in an internal array of 9 floating-point values (float[9]). The storage order is column-major, consistent with standard mathematical representation. Access to individual elements is done through constants: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X and so on.

Matrix elements

The matrix is organized as follows: the first two columns (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) handle scaling, rotation and skew. The third column (MTRANS_X, MTRANS_Y, MPERSP_2) handles translation and perspective. For affine transformations, MPERSP_0 and MPERSP_1 are 0, and MPERSP_2 is 1.

To get matrix values, use getValues(float[] values), which fills an array of 9 elements. To set them, use setValues(float[] values). This allows direct manipulation of the matrix for complex custom transformations beyond the standard translate, scale, rotate and skew methods.

Matrix type checking

Matrix provides several methods for classifying the current state. isIdentity() checks whether the matrix is an identity matrix. isAffine() checks whether it contains only affine transformations (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). These checks are useful for optimization: if the matrix is identity, the transformation can be skipped.

Basic Matrix Operations

Matrix supports several categories of operations: set, pre-multiplication (pre), post-multiplication (post), concatenation (concat), inversion (invert) and mapping (map). Each category serves its purpose when building complex transformations.

Pre and Post operations

preTranslate multiplies the current matrix on the left by the translation matrix: result = translate × current. postTranslate multiplies on the right: result = current × translate. The difference is in the order of application: pre-operations are applied before current transformations, post-operations after. The same applies to preScale, postScale, preRotate, postRotate and preSkew, postSkew.

Inversion and concatenation

invert(Matrix inverse) computes the inverse matrix. If the original matrix is singular (determinant is zero), it returns false. concat(Matrix other) multiplies the current matrix by the given one: set = set × other. For reverse order, use setConcat(other, this).

Map — applying to points and rectangles

mapRect(RectF rect) transforms a rectangle and returns the result in a new RectF. mapPoints(float[] dst, float[] src) transforms an array of points. mapVectors(float[] dst, float[] src) transforms vectors — without accounting for translation. mapRect is useful for computing bounding boxes after transformation.

Application in Canvas and Bitmap

Matrix is actively used in two key Android graphics scenarios: Canvas transformation and Bitmap transformation. In both cases, Matrix determines how the graphic output will be modified.

Canvas transformation via Matrix

Canvas provides canvas.setMatrix(matrix) for full replacement of the current matrix and canvas.concat(matrix) for multiplying the current transformation by the given one. After applying Matrix, all subsequent drawing — drawBitmap, drawRect, drawPath calls — is performed in the transformed coordinate system. Canvas also maintains its own saved state stack via save() and restore().

Bitmap transformation via Matrix

Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) creates a new Bitmap with the given transformation applied. This is a powerful tool for creating scaled, rotated or distorted image copies without losing the original Bitmap. The filter parameter controls anti-aliasing during pixel interpolation.

setPolyToPoly — perspective transformations

setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — a unique capability of Matrix with no direct equivalent in CGAffineTransform. It computes a matrix that transforms given points from one polygon to another. With pointCount = 4, a full perspective (projective) transformation is created, allowing Bitmap overlay with perspective distortion.

Kotlin Code Examples

Let’s look at practical examples of using Matrix for graphics transformation in an Android application with Kotlin.

Basic affine transformations

The example creates a Matrix for a combined transformation: translation by (100, 50), scaling by 1.5x and rotation by 45 degrees. Using postTranslate after preRotate and preScale changes the order of operation application.

kotlin
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)

// Applying to points
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)

// Applying to rectangle
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)

Canvas transformation with save and restore

The example demonstrates applying Matrix to Canvas in onDraw to rotate and scale a circle around its center. Saving and restoring the Canvas state ensures that the transformation does not affect subsequent drawing elements.

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    val cx = width / 2f
    val cy = height / 2f
    val radius = 100f

    canvas.save()
    val matrix = Matrix()
    matrix.postTranslate(cx, cy)
    matrix.postRotate(30f)
    matrix.postScale(1.2f, 1.2f)
    canvas.concat(matrix)

    val paint = Paint().apply {
        color = Color.BLUE
        style = Paint.Style.FILL
    }
    canvas.drawCircle(0f, 0f, radius, paint)
    canvas.restore()
}

Perspective distortion via setPolyToPoly

The example uses setPolyToPoly to create a perspective distortion of a Bitmap. Four source points (corners of the original rectangle) are mapped to four target points forming a trapezoid. The result is a tilted-in-space image effect.

kotlin
fun applyPerspective(
    bitmap: Bitmap,
    skew: Float
): Bitmap {
    val w = bitmap.width.toFloat()
    val h = bitmap.height.toFloat()

    val src = floatArrayOf(0f, 0f, w, 0f,
                         0f, h, w, h)
    val dst = floatArrayOf(skew, 0f, w - skew, 0f,
                         0f, h, w, h)

    val matrix = Matrix()
    matrix.setPolyToPoly(src, 0, dst, 0, 4)

    return Bitmap.createBitmap(
        bitmap, 0, 0,
        w.toInt(), h.toInt(),
        matrix, true
    )
}

Frequently Asked Questions

How is Matrix different from Camera in Android?

Matrix works with two-dimensional affine and perspective transformations through a single 3×3 matrix. Camera (android.graphics.Camera) is a higher-level class that simulates a three-dimensional camera: it creates 3D rotation and then projects the result into a 2D Matrix. Camera uses Matrix internally.

How to rotate a Bitmap by 90 degrees?

Create a Matrix with postRotate(90f) and pass it to Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Note that when rotating by 90 degrees, the width and height of the result swap places. For rotation by an arbitrary angle, cropping may be required to avoid empty areas.

How to get the inverse Matrix transformation?

Use matrix.invert(resultMatrix). The method returns true if inversion is successful and writes the inverse matrix to resultMatrix. Inversion may be impossible if the matrix is singular (e.g., at zero scale). Always check the return value.

What is the difference between pre and post operations?

pre multiplies the new transformation on the left: result = operation × current — the operation is applied before current ones. post multiplies on the right: result = current × operation — the operation is applied after. For a preRotate + postTranslate sequence: first rotation, then translation.

Can Matrix be used in Compose?

Yes, Matrix is used in Jetpack Compose through the android.graphics.Matrix class in interaction with Canvas Compose. In Compose, graphicsLayer is available for transformations (scale, rotationX, translationX and others), but for complex Bitmap transformations, Matrix is used in drawWithContent or drawBehind code.

Summary

  • Matrix — Android class for affine and perspective transformations with a 3×3 matrix
  • Four basic types: translate, scale, rotate, skew
  • pre/post operations control application order: pre — before current, post — after current transformations
  • setPolyToPoly — unique function for computing perspective transformation from 4 point pairs
  • Matrix is applied to Canvas via concat, to Bitmap via createBitmap with Matrix, to points via mapPoints
  • invert computes the inverse transformation, returning false for singular matrices
  • isAffine and isIdentity help classify matrix state for optimization

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also