Convert Android Matrix values to View transform properties - android

I have a View which is rotated around the X and Y axis using View.setRotationX and View.setRotationY. I have used View.getMatrix() and modified the values of the Matrix. I would now like to apply the Matrix back to the View but I have not found a good way of doing this without using the legacy Animation API in Android.
Basically what i need is to convert the Matrix values to View transformation values.
Example:
float[] src = new float[]{0, 0, view.getWidth(), 0, 0, view.getHeight(), view.getWidth(), view.getHeight()};
float[] dst = new float[8];
Matrix matrix = view.getMatrix();
matrix.mapPoints(dst, src);
dst[7] = NEW_Y_COORD_OF_CORNER;
matrix.setPolyToPoly(src, 0, dst, 0, dst.length >> 1);
//The matrix is now changed but the View is not.
So i would like to get rotation and translation of the Matrix to apply it back to the View:
float newRotationX = convertMatrixRotationToViewRotationX(matrix); //method i need
float newRotationY = convertMatrixRotationToViewRotationY(matrix); //method i need
float newTranslationX = convertMatrixRotationToViewTranslationX(matrix); //method i need
float newTranslationY = convertMatrixRotationToViewTranslationY(matrix); //method i need
view.setRotationY(newRotationX);
view.setRotationX(newRotationY);
view.setX(newTranslationX);
view.setY(newTranslationY);
This might seem like a far to complex way of transforming the View but I need to do it this way in order to be able to set x,y corner coordinates of the View. For more info of getting the corner coordinates of a way see my previous post here: https://stackoverflow.com/questions/24330073/how-to-get-all-4-corner-coordinates-of-a-view-in-android?noredirect=1#comment37672700_24330073

Related

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

Perspective correction of imageview

I'm working on an app that needs to apply perspective distortion correction to a photo taken with the phone's camera.
Once the photo is taken, the idea is to show it on an imageview and let the user mark the four corners of the document (a card, a sheet of paper, etc.) and then apply the correction based on those points.
This is an example of what im trying to achieve:
http://1.bp.blogspot.com/-ro9hniPj52E/TkoM0kTlEnI/AAAAAAAAAbQ/c2R5VrgmC_w/s640/s4.jpg
Any ideas on how to do this on android?
You don't have to use a library for this.
You can just as well use one of the drawBitmap functions of the Canvas class with a matrix that's initialized using the setPolyToPoly function of the Matrix class.
public static Bitmap cornerPin(Bitmap b, float[] srcPoints, float[] dstPoints) {
int w = b.getWidth(), h = b.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c = new Canvas(result);
Matrix m = new Matrix();
m.setPolyToPoly(srcPoints, 0, dstPoints, 0, 4);
c.drawBitmap(b, m, p);
return result;
}
(The Paint object is only needed to enable anti-aliasing.)
Usage:
int w = bitmap.getWidth(), h = bitmap.getHeight();
float[] src = {
0, 0, // Coordinate of top left point
0, h, // Coordinate of bottom left point
w, h, // Coordinate of bottom right point
w, 0 // Coordinate of top right point
};
float[] dst = {
0, 0, // Desired coordinate of top left point
0, h, // Desired coordinate of bottom left point
w, 0.8f * h, // Desired coordinate of bottom right point
w, 0.2f * h // Desired coordinate of top right point
};
Bitmap transformed = cornerPin(bitmap, src, dst);
Where src are the coordinates of the source points, dst are the coordinates of the destination points. Result:
What you want to do goes under various names of art, "corner-pin" being the one commonly used in the visual effects industry. You need to proceed in two steps:
Compute the mapping from the the desired, rectified image, to the original, distorted, image
Actually warp the original image according to the mapping computed in (1).
The 4 (non-collinear, perspective-distorted) corners of the original image, and the 4 corners of the target (undistorted) image, define the mapping. This mapping is called a "homography" - read the pointed wikipedia page for details. Once the mapping is known, the warping at step (2) can be computed by interpolation: for every pixel in the target image, find the corresponding pixel in the original image. As this will typically not be at integer coordinates, you interpolate its color from the neighbors. Various interpolation schemes are used, the common ones being nearest-neighbor, bilinear and bicubic (in increasing order of smoothness in the results).
For Android, I'd recommend installing the OpenCV SDK , and then use the geometry transformation routines (getPerspectiveTransform and warpPerspective for the two steps above).

Rotate icons/views along a circular path, on scroll - Android

I'm basically trying to implement something similar to this. Sadly, it's an iOS tutorial.
I have googled in most possible keywords to move something in circular manner, but couldn't find any to start off. Can any one atleast provide any hints on how this can be hacked on android? Please.
Thanks.
i used rotate animation to rotate an image about a point.
double r = Math.atan2(evt.getX() - turntable.getWidth() / 2, turntable.getHeight() / 2 - evt.getY());
rotation = (int) Math.toDegrees(r);
if (evt.getAction() == MotionEvent.ACTION_MOVE)
{
x= (int)evt.getX();
y = (int)evt.getY();
rotateAnim = new RotateAnimation(angle,rotation-50,200,100);
rotateAnim.setFillAfter(true);
ImageView.setanimation(rotateAnim );
ImageView.startAnimation(rotateAnim);
}
you can also use matrix
float newRot = new Float(rot);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.disc);
Matrix matrix = new Matrix();
matrix.postRotate(newRot - 50);
Bitmap redrawnBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
turntable.setImageBitmap(redrawnBitmap);
This would be pretty easy to do in a custom control. Just create a class that extends View and override the draw() method. Then you can listen for touches and calculate how far the user has rotated the control. Then you just need to use that data to rotate the canvas and draw the numbers on it.
-= Update =-
When you override the draw method you get a Canvas object. That object lets you draw to it what ever you want. It would look something like this:
#Override
public void draw(Canvas c)
{
c.rotate(amount);
c.drawBitmap(myImage);
}
This is a link to the full Canvas Documentation.

Android Bitmap Transformation Math

I need to combine 2 images into one. Basically all i need to do is to overlay one of them on top of the other in the center of the image. This needs to work on all major android devices.
I have tried a number of things, but here is my code snippet as of right now (and yes I know it's messed up, we need to figure out delx and dely):
/* Rotate our original photo */
// final float scale = getResources().getDisplayMetrics().density;
canvas.drawBitmap(bmp, 0f, 0f, null);
final float overlay_scale_factor = .5f;
final int overlaywidth = (int)(overlay.getWidth() * overlay_scale_factor);
final int overlayheight = (int)(overlay.getHeight() * overlay_scale_factor);
final int delx = overlaywidth;
final int dely = overlayheight;
Matrix mat = new Matrix();
mat.postRotate(270);
mat.postScale(overlay_scale_factor, overlay_scale_factor);
//mat.postTranslate(-delx, -dely);
canvas.drawBitmap(overlay, mat, null);
/* Bottom image 'composite' is now a composite of the two. */
Any help is appreciated. I know this is just math, but I'm not good at this kind of stuff.
The first image, 'bmp' is 100% the size of the canvas.
The second image, 'overlay' is the overlay that needs to be centered after it's rotated 270 degrees.
Totally untested, but I'd expect something like this to work:
// Set the origin (0,0) in the middle of the view
canvas.translate(width/2, height/2);
// Draw the first bitmap so it is centered at (0,0)
canvas.drawBitmap(bmp, -bmp.getWidth()/2, -bmp.getHeight()/2, null);
// Rotate & scale
canvas.save();
canvas.rotate(270);
canvas.scale(.5f);
// Draw the overlay
canvas.drawBitmap(overlay, -overlay.getWidth()/2, -overlay.getHeight()/2, null);
canvas.restore();

Rotating a bitmap on an axis in Android

I have a bitmap flush with the bottom of my screen. When the user clicks a button I want it to rotate to the right by one degree. I am able to accomplish this but the problem is that the bottom of the item is no longer flush with the screen. I need it to appear to rotate on its bottom axis. I could use some hack to increment the x and y when its rotated (using trial and error I suppose) but is there a formula or something more elegant I can use?
public void rotate(int degrees)
{
Matrix mat = new Matrix();
mat.postRotate(degrees);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mat, true);
}
Could you not instead use the following method that Matrix also has:
postRotate (float degrees, float px, float py)
It enables rotation on the specified point.

Categories

Resources