0
votes

I have a canvas which does behave not the way I'd expect it to.

Here's my problem: My two Bitmaps are 700kb and 1.4mb in size.

Here I load my bitmaps

mBitmap = BitmapFactory.decodeResource(mContext.getResources(),
            drawable, mOptions);

Afterwards, I rescale it to the size I need it:

mBitmap = Bitmap.createScaledBitmap(mBitmap, width, height, false);

Then I draw it:

canvas.drawBitmap(mBitmap, x, y, myPaint); 

The performance overall is really bad, I'm not sure why?

And here is the strange behavior: When I load the Bitmaps with low quality (RGB_565), I get around 12(?!) FPS and it's reaally laggy. When I load them with higher quality (ARGB_8888) though, I get around 25 FPS (still too less).

In my manifest I set android:hardwareAccelerated="true", but this does not do any difference either, CPU usage is always the same.

The images are placed in the drawable-nodpi folder.

I thought, maybe my images are too big, I tried to optimize them and made them half the size, and then again the performance drops.

Also, the performance is worse on my tablet, which has higher hardware specs though, so this seems to be a problem with the way I load/scale the images?

What can I do to get better performance?

Thanks in advance!

2
dont use createScaledBitmap, use drawBitmap with Matrix param insteadpskink

2 Answers

1
votes

You're drawing on a Canvas, which may be hardware accelerated if it's part of a custom View, but is never hardware accelerated if you're drawing on a Surface (such as a SurfaceView).

Bitmaps whose color format matches the color format of the underlying Surface may be handled more quickly because no format conversion is required. For example, if you draw your RGB565 Bitmap onto an ARGB8888 Surface, each pixel has to be expanded. If the Bitmap is already in the matching format, the draw call can be a fast blit.

Tablets often have larger display pixel counts than phones, though the trend has been toward absurd pixel counts across all device categories. Displays with lots of pixels take longer to draw, especially when rendering in software. The single-core CPU performance and memory access speeds will be more important than GPU performance.

If you're rendering to a Surface, you can use SurfaceHolder#setFixedSize() to reduce the number of pixels you need to draw (demo here, blog post here).

0
votes

Are you calling createScaledBitmap in your onDraw method? if so, that's the reason for your slow-down. You're basically spinning up all this hardware to resize the image every-single-frame; which, as you've seen, gets worse with a larger image. (in general, you should avoid doing super-heavy work in onDraw, as detailed in Custom Views and Performance) There's a couple solutions:

  1. Resize the image once, during it's inital load, and keep the resized one in memory to use in onDraw method
  2. Use cavnas scaling (update your drawing matrix to draw a smaller image). You'll pass in the larger image to draw, and the GPU will handle scaling for you, rather than you having to do it by hand.

With respect to the 565 performance issue : As talked about in Smaller Pixel Formats the conversion to RGB_565 takes additional compute cycles after the image has been loaded; so it make sense that you'd see a slow-down doing this conversion on top of an image resize.