Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to distort an image to any quadrangle?

Do any of you have an idea, how to distort an image in any quadrangle? I want to implement an image, which you can pull any corner in any direction, distorting the image. Anyone has an idea how to do that? I use and write stuff in android for a while now, but it does not seem like android has a function for that. I don't really feel like writing a new math library :).

Greetings, Can

like image 339
Geki Avatar asked Dec 18 '12 14:12

Geki


3 Answers

Looks like you need Canvas.drawBitmapMesh . There is a sample in Android SDK showing how to use it.

You need to use Matrix for drawing your bitmap on Canvas. You can easily create such transformation which will fit your bitmap image into any quadrangle with Matrix.polyToPoly method. It will look like this:

matrix.setPolyToPoly(
        new float[] { 
            0, 0, 
            bitmap.getWidth(), 0
            0, bitmap.getHeight(),
            bitmap.getWidth(), bitmap.getHeight() 
        }, 0, 
        new float[] { 
            x0, y0, 
            x1, y1, 
            x2, y2,
            x3, y3
        }, 0, 
        4);

canvas.drawBitmap(bitmap, matrix, paint);

Where x0-x3, y0-y3 are your quadrangle vertex coordinates.

like image 199
Andrei Mankevich Avatar answered Nov 07 '22 07:11

Andrei Mankevich


matrix.setPolyToPoly and canvas.drawBitmap can't solve all matrix transformations. Here I found a solution using canvas.drawBitmapMesh.

Distorting an image to a quadrangle fails in some cases on Android

like image 29
Pep Santacruz Avatar answered Nov 07 '22 06:11

Pep Santacruz


There is an issue with your code. Although it is the correct method, you have inverted the float[] parameters, as appears in Android documentation:

public boolean setPolyToPoly (float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)
WHERE
src: The array of src [x,y] pairs (points)
...
dst: The array of dst [x,y] pairs (points)

So, according with your code, the matrix should be created as:

matrix.setPolyToPoly(
        new float[] {
            x0, y0,
            x1, y1,
            x2, y2,
            x3, y3},
    0,
new float[] { 
        0, 0, 
        bitmap.getWidth(), 0
        0, bitmap.getHeight(),
        bitmap.getWidth(), bitmap.getHeight() 
    }, 0, 
    4);

In this way, the app works fine, as shown in the image:

enter image description here

By the other hand, regarding of what user2498079 says in his comment about the computational problem in low end devices, you can use some easy-to-do techniques to reduce the source image size (and color depth, for example) before matrix conversion calculation. It'd make it easier for the low end phone to realize this task.

like image 32
Anibal Itriago Avatar answered Nov 07 '22 06:11

Anibal Itriago