Search code examples
androidmathandroid-bitmap

Clearly understand matrix calculation


I have this code snippet. I don't understand the Matrix.preScale and the Bitmap.createBitmap with the matrix passed. What does it mean? Is there any simulation website to understand matrix calculation? Could you give me some websites about mathematics used for graphics? I'm sorry I'm not good at mathematics. :)

public Bitmap createReflectedImages(final Bitmap originalImage) {
    final int width = originalImage.getWidth();
    final int height = originalImage.getHeight();
    final Matrix matrix = new Matrix();
    matrix.preScale(1, -1);
    final Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, (int) (height * imageReflectionRatio),
            width, (int) (height - height * imageReflectionRatio), matrix, false);
    final Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (int) (height + height * imageReflectionRatio + 400),
            Config.ARGB_8888);
    final Canvas canvas = new Canvas(bitmapWithReflection);
    canvas.drawBitmap(originalImage, 0, 0, null);
    final Paint deafaultPaint = new Paint();
    deafaultPaint.setColor(color.transparent);
    canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
    final Paint paint = new Paint();
    final LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
            bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
    paint.setShader(shader);
    paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
    canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
    return bitmapWithReflection;
}

Solution

  • Don't think about it too hard, at least not at the early stages.

    Just think of a matrix as an array of numbers. In this case, an Android Matrix has 3 rows of 3 numbers. Each number tells an Android graphics function what to do to scale (bigger/smaller), translate (move), rotate (turn) or skew (distort in a 2D plane) the "thing" which the matrix is applied to.

    The matrix looks like this (see the docs here).

    {Scale X, Skew X, Transform X
    Skew Y, Scale Y, Transform Y
    Perspective 0, Perspective 1, Perspective 2}
    

    The good news is that you don't need to know any matrix maths, indeed almost no maths, to use matrices in Android. That's what methods like preScale() do for you. To understand the maths behind is not that hard, for most things you only need add, multiply and SOHCAHTOA.

    matrix-transform-for-the-mathematically-challenged/

    When you read the Matrix documentation, you will see methods for rotate, translate etc with prefixes of 'set', 'post' or 'pre'.

    Imagine that you create a new matrix. You then use setRotate() to setup the matrix to do a rotation. You then use preTranslate() to do a translation. Because you used 'pre', the translation happens before the rotation. Had you used 'post', the rotation would happen first. 'set' clears whatever is in the matrix and starts again.

    To answer your specific question, new Matrix() creates the 'identity matrix'

    {1, 0, 0
     0, 1, 0
     0, 0, 1}
    

    which scales by 1 (therefore same size) and does no translation, rotation or skew. Therefore, applying the identity matrix will do nothing. The next method is preScale() which is applied to this identity matrix and in the case you've shown, results in a matrix that scales, and does nothing else so could also be done using setScale() or postScale().