I've got the following code.
this.getGame().getGraphics().drawBitmap(Assets.playScreen_LaserBeamAnimation, new Rect(0, 0, 100, 750), new Rect(0, 0, 100, 750), null);
this.getGame().getGraphics().drawBitmap(Assets.playScreen_LaserBeamAnimation, new Rect(0, 200, 10, 800), new Rect(0, 0, 200, 600), null);
The first render statement takes around 0.6 - 1 second
to render.
The second one around 1 millisecond
.
The Bitmap is large: 968 KB
and is loaded with the following code:
public Bitmap readAssetsBitmap(String filename) throws IOException {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeStream(assets.open(filename), null, options);
if(bitmap == null) {
WSLog.d(Game.GAME_ENGINE_TAG, this,"File cannot be opened: It's value is null");
throw new IOException("File cannot be opened: It's value is null");
}
else {
WSLog.d(Game.GAME_ENGINE_TAG, this,"File successfully read: " + filename);
return bitmap;
}
}
catch (IOException e) {
WSLog.d(Game.GAME_ENGINE_TAG, this,"File cannot be opened: " + e.getMessage());
throw new IOException("File cannot be opened: " + e.getMessage());
}
}
I expect the reading of the image and setting the Bitmap to take some time, however rendering a small region of it should not take so long (and mysteriously it is only the first render call).
How do I avoid the first render to take so long?
NB: It does not have to do anything with the scaling (I believe).
TL;DR Loading and rendering graphics is actually a relatively expensive set of (internal) operations, first loading into memory then into the graphics module of the ARM CPU when it is first rendered to screen. Further, the animated GIF is expanded into a set of images, one for each animation frame making it quite a bit larger than you may think. To improve speed, you might consider decreasing the animation size (pixels and number of frames), or forcing the GIF onto the graphics memory earlier to avoid the first-frame pause.
There is one heck of a lot of things Android has to do internally to render game graphics, especially if you have a GIF animation:
Now we have an image (actually a set of frames) in the CPUs memory. Note that a very small GIF with a lot of frames can become a very large in memory - Android has to have a full-sized image for each frame in your GIF. Also the 256 bit colour model is expanded into RGBA internally, so you have 4 bytes per pixel.
Take for example a GIF (128x128 pixels) with a small shape animated on it (32x32 pixels). Let's further suppose you have 100 steps in the animation - this might be 10k or so depending on how simple the background is. However, expanded in memory, each frame in the animation is 4x128x128 = 64kB. You have 100 frames, so your in-memory size is 6MB.
Next:
Once the image (which is actually a bunch of frames) is loaded into the graphics module, then things get fast.
OK, so what can you do about it? Here are some suggestions:
Reducing the size of the GIF could reduce the memory usage significantly, and that will reduce the time Android takes to push the frames into the graphics module and the cost to compile into textures. The downside to that is you might not have the authority to modify the graphics.
Pre-loading pushes the image into the graphics module earlier by forcing a render during the game loading phase. The image might be off-screen (setting the window as hidden) or behind a top-layer by setting a low Z-order or in a 1 pixel region.
Tiling is discussed in my answer to a similar question). Take Google Earth as the most extreme example - this uses tiles (at any given resolution) for every area on earth. To render just the bit you are interested in, Google Earth has to load only the tiles that are to be shown. Because the tiles are small, they load fast. However, in your case you may have a GIF animation, so that's not going to work. Tiling an animation might not be practical or might lead to artefacts or delays in rendering portions of the image.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With