Android: Difference between canvas.drawBitmap and BitmapDrawable.draw? - android

When I want to draw a BitmapDrawable to a Canvas in Android, there are two possibilities that do the same and I don't know which one to prefer:
Using canvas.drawBitmap() and extract the Bitmap from the drawable using getBitmap()
Using drawable.draw(canvas), passing the canvas as an argument to the drawable.
I'm using the first option now, but it seems completely arbitrary as I can't see any difference.
Thanks for your answers

Never do option number 1 the way you do it. Instead of creating a bitmap out of a drawable every time you want to draw it, create a bitmap in the first place. That is, don't create a Drawable if you are going to draw a bitmap. Create a bitmap like this:
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.myImage);
mBitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true);
And this is something you do just once. After that, just draw like you do (canvas.drawbitmap()).
As for option number 2, you are doing it correctly.
Now, there are some differences.
Option 1 is faster to draw and usually good for background images. There is a significant change to FPS depending on if you draw a bitmap or drawable. Bitmaps are faster.
Option 2 is the way to go if you need to things like scaling, moving and other kinds of manipulations of the image. Not as fast but there's no other option if you want to do any of those things just mentioned.
Hope this helps!

Related

Displaying part of a spritesheet in an Android ImageView

In Android, is there a clean way to display only a given part of a bitmap in an ImageView (for example a single sprite of a sprite sheet), without having to :
Manually split the bitmap png into small pngs (=> more drawables embedded in the app, tedious manual operation possibly leading to bugs, or loose the spritesheet).
Have small pngs used in the ImageViews, with the sprite sheet being generated (=> complicated)
Create "dirty" subclasses for ImageView, Drawable, etc (=> the more we use Android API "ASIS" the better)
Programmatically create sub-bitmaps of the big bitmap (=> We have to do all the work programmatically)
For instance I have tried creating an ImageView of width/height of 40dp, and setting its drawable as a ClipDrawable displaying only the part of the bitmap I wanted, but it did not go well :
the clipped part did not fill the parent when using Gravity.CENTER when creating the ClipDrawable.
The whole "big" PNG was displayed when using Gravity.FILL.
Furthermore this solution is feasable with a simple sprite sheet (for example 2*2 sprites), but I do not think it is possible when using something like a 4*4 sprite sheet. I think ClipDrawable is not meant for such a use.
Isn't there something "clean and easy" like in OpenGL where you can set a texture Id, and set the texture coordinates to display only part of the texture? Considering my researchs I think the best solution is to manually split the big bitmap with Bitmap.createBitmap, when I'd rather ask before starting something like that.
PS : I consider using SpriteSheets because of OpenGl, although my "menus" are developed using Android APIs, hence using ImageView.
Are you familiar with Canvas at all? I think that is another way that would work for you.
You create one bitmap in memory, then use drawBitmap to draw just the current chunk you want.
Here is a snippet from the manual:
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
This function ignores the density associated with the bitmap. This is because the source and destination rectangle coordinate spaces are in their respective densities, so must already have the appropriate scaling factor applied.
Parameters
bitmap The bitmap to be drawn
src May be null. The subset of the bitmap to be drawn
dst The rectangle that the bitmap will be scaled/translated to fit into
paint May be null. The paint used to draw the bitmap

Drawing to a new Bitmap and then using that in my onDraw

I would like to display several rings with different coloured sections (see below). The colour of the sections, however, cannot be know in advance, so I will need to draw these dynamically.
I know I could draw directly to the canvas but, once I have them, I would like to animate these rings, rotate them, have them overlap etc. It seemed, therefore, that the easiest and possibly least expensive approach would be to create them in advance, in memory, as transparent pngs and then just draw them in onDraw.
My problem is the only methods I can find to do this are setPixel. Is there not a way I could use drawing tools, like in Canvas, to draw to an empty bitmap, once, then use that bitmap with my canvas in onDraw?
I feel like I am missing a piece in the puzzle. Any help would be greatly appreciated.
You can create a Bitmap that is the size you want the ring to be and then create a Canvas the same size. Call setBitmap() on the Canvas and it will draw on to that for you. Then you can build your circle and have a bitmap to hold onto and use just like any other resource.

Where does Android.Graphics.Camera set its X,Y, and Z axis when canvas is set to a bitmap?

I want to get a bitmap and manipulate it in the following way:
I have created an empty bitmap, on this bitmap, I drew what I needed. Now I need to distorted in a way similar to this because I will then be drawing the whole thing ontop of another bitmap. Think of it as applying a texture to a box. The box simply being a picture of a box. The way that I see myself doing this is creating bitmaps off the main bitmap and drawing them onto the final bitmap through a matrix modified by Graphics.Camera.getMatrix().
I already have this working, but my problem is understanding just exactly how to manipulate the camera. I don't know where the camera creates its X Y and Z axis within the matrix. Or where does the matrix get applied. Or just how it all comes together.
When drawing on canvas set to view, I know I can rotate the canvas and draw from there to create a straight diagonal line, for example in a game engine to draw a projectile acting on two vectors. And I know when working on OpenGL, there is a state machine approach and I can imagine where the matrix is in 3D space. But I just don't understand how Camera, Matrix, and bitmap all relate.
From what I've looked up, I managed to set up the basic solution to this but havent been able to understand just exactly how to tweak this in order to get the right rotations. I have read the documentation but it doesn't really explain the relationship between Camera, Matrix, and canvas beyond the fact that Camera modifies a matrix and then canvas can draw something based on that matrix.
Can anyone explain how I would go about doing what I have in the picture? I already know that I'll be creating a bitmap from region in original bitmap. Then combining the two, to create what is on the right column , and then rotating the canvas/bitmap and getting another bitmap from green section and repeat the whole thing again.
Thanks
Camera is just a utility class that generates a Matrix you can use on Canvas. The generated Matrix contains the appropriate transform. You said it yourself:
it doesn't really explain the relationship between Camera, Matrix, and
canvas beyond the fact that Camera modifies a matrix and then canvas
can draw something based on that matrix.
That's all there is to it really :)

Canvas Dynamically change a bitmap's z-index

I am creating an Android app and in my app I have a canvas which I draw numerous bitmaps to the canvas via the canvas.drawBitmap () function. From my understanding the z-index on these bitmaps are set based on the order in which they are being drawn to the canvas. What I am trying to figure out is after drawing these bitmaps if I can dynamically change the z-index on a bitmap to push it to the top? This seems like a very simple problem, but I have had not luck in finding a solution yet.
Not really possible: after you call drawBitmap the contents of the bitmap are rendered onto the canvas, but the canvas does not store any references to the original bitmap, it only stores the results of applying the bitmap's contents to the canvas. There is no way to dynamically say that bitmap you drew 1st out of 50, I want you to make that the 50th bitmap and automatically redraw every single other bitmap to reflect the change.
So you'll need to order your drawing operations before hand.

drawing part of a bitmap on an Android canvas

How can you blit a non-rectangular (e.g. oval) part of a bitmap into a canvas on Android?
Consider how you'd blit a rectangular part of a bitmap:
canvas.DrawBitmap(src,src_rect,dest_rect,paint). Sadly there is no corresponding methods for non-rectangular regions.
Four approaches present themselves (maybe you know a fifth?):
copy the rectangular bounds you want to blit into an intermediate bitmap, and go setting the pixels you don't want to blit to be transparent, then draw that bitmap
make a mask bitmap - there are ways to blit with a separate mask?
use a BitmapShader with drawArc()/drawCircle(); however, I can't work out how to get the matrix to be properly aligned; how would you initialize the matrix for this operation?
use a very very complicated clipping region
Of these, option 3 is the one that I would most like to work; however, I cannot work out how to do so; can you?
You can use option number #3, it's probably the easiest. Another way is to draw the shape you want to clip with in an intermediate Bitmap (ARGB8888), then draw your original Bitmap using a DstIn or DstOut xfermode.

Categories

Resources