As we know, we can rotate a bitmap through 2 ways.
The 1st way is:
Matrix mt = new Matrix();
mt.postRotate(degree);
Bitmap bitmap = CreateBitmap(src, 0, 0, w, h, mt, true);
canvs.drawBitmap(bitmap, 0, 0, paint);
In this way, we always need create new bitmap for every rotation, it is not good way for high performance game or app.
The 2nd way is:
canvas.save();
canvas.rotate(degree);
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
In this way, we avoid creating new bitmap frequently, but the rotation bitmap is distortion, the bitmap quality is worse than first way.
So, Is there 3rd way to rotate bitmap with high performance and good quality?
Your any comments are really appreciated!
Make sure that you providing Paint to canvas.drawBitmap(bitmap, 0, 0, paint).
And don't forget to use anti-alias and bitmap filtering:
paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
If you really want high speed graphical applications (even 2D) you should use OpenGL on Android.
I believe Replica Island uses OpenGL and VBO's (where available) for rendering it's 2D scene. But I can't find a reference.
this method should use the GPU to rotate the bitmap
Canvas.drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint)
Related
I'm creating a app in android for mugs like this
I know how to do everything except wrapping an image around an object. It would be a simple task to do if I would only have to stack an image on top of the other, if they were flat, but if it is a round object, as this mug is, it's kinda tricky.
I thought of creating a obj object file in blender and render the image on it in OpenGL or Unity. The obj file size goes to 5MB. And i cannot use this much big file in my app.
Is there any alternate good approach for it? If there please share a reference or example for it
Use in this manner
the work around of it by doing a masking over the image
ImageView mImageView= (ImageView)findViewById(R.id.imageview_id);
Bitmap original = BitmapFactory.decodeResource(getResources(),R.drawable.content_image);
Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.mask);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(original, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint); paint.setXfermode(null);
mImageView.setImageBitmap(result);
mImageView.setScaleType(ScaleType.CENTER);
mImageView.setBackgroundResource(R.drawable.background_frame);
As mentioned here Masking(crop) image in frame
I suppose that this is the right way, but using pure OpenGL is difficult. I used LibGDX for simple 3d modeling.
I need to do something which exactly the opposite of Bitmap.extractAlpha: Apply an alpha map (which loaded from a file) onto a RGB bitmap (which also loaded from a file).
Yes! Just like "CGImageCreateWithMask" in iOS!
The Square blog had a tutorial about this just last week: http://corner.squareup.com/2013/01/transparent-jpegs.html :).
I dont know what exactly CGImageCreateWithMask does, but if you want another picture to serve as the alpha channel for your Bitmap, you can create one as described in this question, which combines four images. I haven't tried it now, but I think for two colors it would look something like this:
Paint colorPaint = new Paint();
redPaint.setShader(new BitmapShader(redChanImg, TileMode.CLAMP, TileMode.CLAMP));
Paint alphaPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
alphaPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
c.setBitmap(resultImage);
c.drawRect(0, 0, width, height, colorPaint);
c.drawBitmap(alphaImg, 0, 0, alphaPaint);
// save result somewhere
You can also always just work on the raw pixel data of a bitmap using Bitmap.getPixels
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);
What is the relation between Canvas and Bitmap?
Bitmap drawingBitmap = Bitmap.createBitmap(bmp1.getWidth(),
bmp1.getHeight(), bmp1.getConfig());
canvas = new Canvas(drawingBitmap);
paint = new Paint();
canvas.drawBitmap(bmp1, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.SCREEN));
canvas.drawBitmap(bmp2, 0, 0, paint);
compositeImageView.setImageBitmap(drawingBitmap);
I don't understand this code.Why the drawingBitmap is the composition of bmp1 and bmp2?
Basically, the Canvas is backed by a Bitmap, so when you draw anything using the canvas, the canvas will draw into the Bitmap it was created with. So, when you draw those two bitmaps using the canvas, it's going to composite the bitmaps together and the result will be stored in drawingBitmap, as it's backing the canvas.
Anh's analogy is correct-ish, though probably confusing (and over-simplifying, which I'm also doing above) – as I mentioned in a comment, you can think of the Canvas as the pen, the Paint as a configuration of that pen (e.g., replaceable ink or something - whatever you can fit into the idea of a configurable pen), and the Bitmap as the paper you draw onto. The analogy becomes confusing if you focus too much on the accepted meaning of the words.
Let's think canvas as a pen, and drawingBitmap as a paper. You use your pen to draw something on your paper, and you get what you draw.
Technically, you can construct Canvas object from Bitmap to draw others bitmaps on it.
Canvas is the place or medium where perfroms/executes the operation of drawing, and Bitmap is responsible for storing the pixel of the picture you draw.
While rotating a bitmap using matrix, vertex is not stable..
Matrix matrix = new Matrix();
matrix.postRotate(mDegree,100,100);
mCompasstemp = Bitmap.createBitmap(mCompPic, 0, 0, mCompPic.getWidth(), mCompPic.getHeight(), matrix, true);
mCompassHud.setImageBitmap(mCompasstemp);
Output of my code is like
-bitmap will rotate.
-vertex of my bitmap is not stable.
-Bitmap is resizing
I need disable image resizing and make the rotation stable.Can you please suggest a solution for this?
Rather than creating your new Bitmap directly from the original, another (more straight-forward, imho) option is to create the resultant Bitmap, create a Canvas with that Bitmap, then do your rotation/translation/scaling on the Canvas and draw the original Bitmap onto the new Bitmap via the Canvas.
Basically, you're looking, then, at:
scaledImage = Bitmap.createBitmap (croppedWidth, croppedHeight, Bitmap.Config.ARGB_8888);
Canvas offscreenCanvas = new Canvas (scaledImage);
Matrix matrix = new Matrix();
matrix.setRotate (rotations, centreX, centreY);
matrix.postScale(scaleX, scaleY);
offscreenCanvas.setMatrix (matrix);
offscreenCanvas.drawBitmap (pickedImage, 0, 0, new Paint(Paint.DITHER_FLAG));
Not sure if this is what your looking for but it might help.
Android uses its built in compatibility features to scale and render a bitmap appropriately for screens with different pixel densities. There are two methods of scaling, pre-scaling and auto-scaling.
It will pre-scale bitmaps' from resources and auto-scales when the bitmap is being drawn internally (which is what your doing be using createBitmap).
Go to http://developer.android.com/guide/practices/screens_support.html and check under:
4.Use density and/or size-specific resources:
Pre-scaling and auto-scaling of bitmaps and nine-patches
I have tried this code, and the rotate is stable at the center of the bitmap
matrix.reset();
matrix.setRotate(degree, Xpos+bitmap.getWidth()/2, Ypos+bitmap.getHeight()/2);
and then in canvas doDraw()
canvas.setMatrix(matrix);
canvas.drawBitmap(bitmap, Xpos, Ypos, null);
canvas.setMatrix(null);
The Xpos and Ypos is the X and Y position of the bitmap
The setMatrix(null), set the matrix to null, so that the rotate didn't affect the after bitmap
And it didn't always create new bitmap, so it's great for performance
I hope that help
I know its an old question but, all answers with code imply a canvas, so heres a solution without a canvas that worked for me :
Matrix matrix = new Matrix();
matrix.postRotate(mDegree,100,100);
mCompasstemp = Bitmap.createBitmap(mCompPic, 0, 0, mCompPic.getWidth(),
mCompPic.getHeight(), matrix, true);
mCompasstemp = Bitmap.createScaledBitmap(mCompassTemp, mCompPic.getWidth(),
mCompic.getHeight(), false);
mCompassHud.setImageBitmap(mCompasstemp);
So basically after rotating your bitmap you rescale it to the desired size. Might not be best practice, but at least you dont have to create an extra canvas if you dont want/need to, since the involving Paint() Object is not an inexpensive operation either.