I have a Canvas and a Bitmap.I have to draw bitmap twice on canvas and rotate them.This is my code:
Bitmap bitmap = ... ;
Matrix matrix = new Matrix();
Camera camera = new Camera();
camera.save();
// First drawing:
camera.rotateX(x_rotate_angle);
camera.rotateY(y_rotate_angle);
camera.getMatrix(matrix);
matrix.postTranslate(0, 0);
matrix.postScale(3, 3);
canvas.drawBitmap(bitmap, matrix, null);
camera.restore();
// Second drawing:
camera.rotateX(x_rotate_angle);
camera.rotateY(y_rotate_angle);
camera.getMatrix(matrix);
matrix.postTranslate(10, 10 + bitmap.getHeight());
matrix.postScale(3, 3);
canvas.drawBitmap(bitmap, matrix, null);
Result before rotation:
When bitmaps rotate only axis X,all things are fine.In this case result looks like this:
In both above images you can see that all edges are parallel.But when bitmaps rotate axis Y,edges will not be parallel(bottom edge of top bitmap crosses top edge of bottom bitmap):
Did I do any thing wrong?
You're not doing anything wrong, it's just that you haven't understood the results you were going to get from your code. The camera you're using is a 3D camera and you're seeing the results of moving the camera in 3D space. When you rotate a camera, parallel lines do not in general remain parallel. You noticed the artifact when rotating about the y-axis, but it's also present in your illustration for the x-axis rotation. Notice that for the x-axis, the left and right sides are not parallel; the left side is closer to vertical than the right.
The Android canvas object has scale, skew, translate, and rotate operations. If it's 2D operations that you need, you can ditch the camera object entirely.
Related
I'm using the matrix.rotate(deg, fx,fy) method to rotate an image.
The image has an alpha channel and only has something visual in the right-hand corner. I want to rotate the canvas, create the new image with that matrix and have the visual part be the only part that is rotating.
At the moment the image rotates but doesn't rotate around the desired axis. It always rotates around the original width of the object.
Here is the code I use:
Matrix matrix = new Matrix();
matrix.setRotate(rotation, xPivot, yPivot);
Bitmap pic1a = Bitmap.createBitmap(pic1, 0, 0, pic1.getWidth(), pic1.getHeight(), matrix, true);
This rotates the image correctly but only seems to rotate within the same location of the original canvas.
What I want is for the point that the image rotates around (xPivot, yPivot) becoming the centre location on the display.
I am attempting to rotate, scale, and translate an image for drawing on a Canvas. However, the order is proving to be troublesome and I am having trouble getting everything to line up correctly.
Matrix matrix = new Matrix();
//matrix.postRotate(90f);
matrix.postScale(scaleFactor, scaleFactor);
matrix.postTranslate(screenCoords.x - scaleWidth/2, screenCoords.y
- scaleHeight/2);
c.drawBitmap(blackJackBM, matrix, this.mPaint);
The scaling and translate works correctly in this instance, however un-commenting the rotation code will cause the image to be offset, in this case, to the left of where it should be drawing. Any ideas?
postRotate(float) rotates the matrix from its upper left point. Use postRotate(float, centerX, centerY) instead.
How can I rotate an image around it's center point? This rotates it but also moves it:
Matrix mat = new Matrix();
mat.postRotate(45);
Bitmap bMapRotate = Bitmap.createBitmap(dialBM, 0, 0, dialBM.getWidth(),dialBM.getHeight(), mat, true);
dial.setImageBitmap(bMapRotate);
I've checked other examples on this site, but they either fail to work or use canvas, I do not wish to use canvas.
The second and third arguments to postRotate is the x and y pivot point.
mat.postRotate(45, dialBM.getWidth()/2, dialBM.getHeight()/2);
Probably because your matrix rotates around (0,0), and not the middle of your bitmap. You should declare two additional matrices - one for moving the bitmap's center to (0,0) (shift by -getWidth()/2, -getHeight(2)) and one to move the bitmap's center back to (0,0). Multiply the three matrices, and then the result.
I'm trying to learn how to make an animated sprite in android and couldn't figure out how to go about organising my bitmaps. I have a sprite sheet of my character walking to the Right: a bitmap of five copies of a character, equally spaced (every 45px), in a walk cycle.
I planned to draw each frame by drawing a tiny section of my sprite sheet bitmap at a time by going:
Rect sourceRect = new Rect(0, 0, 45, 75);
canvas.drawBitmap(spriteSheetBitmap, sourceRect, new Rect(0, 0, 45, 75), null);
Then for the next frames, increment "sourceRect.x" by 45, then redraw and so forth.
However, I'm now not sure how to go about making my sprite walk to the Left. I had initially thought I could just mirror my rectangle that I am drawing from to get a flipped picture. Something like:
sourceRect = new Rect(45, 0, 0, 75);
which doesn't seem to work (not sure what actually happens here, but nothing gets drawn to my surface).
Searching online, it seems I should make a copy of my original bitmap, mirror it with a transform matrix, then use that bitmap for drawing when walking to the left. However I've also found implementations where many smaller bitmap objects get created out of the original sprite sheet, stored (and transformed for the mirrored motion), then used as needed.
So I'm wondering what would be the best in this case or if there is really any difference (performance/memory):
Method 1: Load in my original sprite sheet, make a new bitmap instance, mirror it,, then calculate all the rectangles and use those + two entire sheets to draw from (admittedly there is some extra bitmap space where the sprite sheet is unused).
Method 2: Load in my original sprite sheet, for every frame create a new two bitmap objects (1 mirrored, 1 normal) and store those to draw from.
Method 3: Other better ways?
Method 2 would be way too expensive, and you don't need a canvas to flip a bitmap. Simply create another bitmap with a Matrix applied, like so:
BitmapDrawable flip(BitmapDrawable d)
{
Matrix m = new Matrix();
m.preScale(-1, 1);
Bitmap src = d.getBitmap();
Bitmap dst = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m, false);
dst.setDensity(DisplayMetrics.DENSITY_DEFAULT);
return new BitmapDrawable(dst);
}
To mirror your sprite simply apply the following transform on the Canvas: scale(-1, 1). You will have to offset the sprite by its width too.
To draw a vertical mirrored bitmap bmp on a canvas:
Matrix m = new Matrix();
// Mirror is basically a rotation
m.setScale( -1 , 1 );
// so you got to move your bitmap back to it's place. otherwise you will not see it
m.postTranslate(canvas.getWidth(), 0);
canvas.drawBitmap(bmp, m, p);
In my Android project, I have a matrix that I use to draw a bitmap on a canvas. During my drawFrame method, I translate the matrix in the Y direction so it looks like the bitmap is moving up. It does move up, but it is also drawn in the previous position leaving multiples of itself behind. Here is my drawFrame code:
Canvas canvas = null;
canvas = holder.lockCanvas();
Matrix moveMatrix = new Matrix ();
moveMatrix.postTranslate(0, 10);
matrix.preConcat(moveMatrix);
canvas.drawBitmap(bitmap, matrix, null);
holder.unlockCanvasAndPost(canvas);
"matrix" is a global Matrix member.
Does anyone know why this leaves a "streaking" trail of bitmaps across the screen?
Thanks!
I forgot to mention that each previous bitmap position seems to shift up and down in the y direction every time the bitmap moves. So it ends up with a string of bitmaps that look like they are jittering up and down. This would mean that every bitmap would have to be redrawn every frame otherwise they would all be standing still.
You need to clear the Canvas at the previous position of the bitmap :)