I am writing an android app, which needs to draw a huge amount of pictures aligned in a grid. The plan is to draw about 2000 pictures (building up a mosaic). Each of these pictures has a size of 1024x1024. Of course I ran there into heavy efficiency problems.
Right now I am using OpenGL ES 2.0 for drawing. I have one thread loading the images from resources into bitmap objects and passing them to a central pool. The rendering thread of OpenGL then takes an image from this pool, loads the image data from the bitmap to the GPU and draws it at the right cell of a built up grid.
This is horribly slow. I measured some times on this procedure using the android emulator. I got about 60ms for loading a resource into a bitmap object. Loading bitmap into GPU + drawing it takes about 15ms.
I don't have a clear idea on how to speed this up and do this with at least like 30 FPS. My ideas at this moment are to use an external library for loading bitmaps and maybe use the NDK to speed things up. Also I know about texture atlas and batching up my draws. I could implement this, but as my problems are with loading images from resources on runtime I didn't try it for now.
Maybe someone can give me an advice on how to do this efficiently.
Thank you everyone.
First of all, I just want to make it clear, since I think your title is a but misleading - your real problem is not drawing but loading, according to your description. You did not really say if you have a drawing problem (you mentioned the fps for loading and drawing).
You did not mention all the requirements, for example - how soon do you need to draw all of them? Maybe you can, for example, load the first X as part of the app loading, so when the app loads the textures are already created and can be drawn, and in the meantime in the dedicated thread load another X, and so on...
Another approach would be to have low resolution images and high resolution images, load the low resolution first and replace later (on-demand, for example). I'm not sure if this is reasonable memory-wise for 2000 images, but you can check that.
Also, I would suggest taking a look at Rajawali - it is a nice framework, with good examples including for multiple textures (there's also examples app in Google Play). Perhaps it could help.
Related
I'm a 17 year old trying to start developing some android games. I've used LibGDX once before and found it a pretty effective tool, so I'm using it again now.
The game I'm making is a choice based, interactive game where you make a choice and then the next scenario happens based on your choice, and it goes on and on until your character dies or you win. I'm expected to have around 200 scenarios by the time I'm done, and currently have around 160.
The problem I'm having is that each of these scenarios is basically a "card," with a picture, scenario description and 2 options below it. Each of these images is pretty big, and if I scale the card images down they start looking pixelated on the phone screen. I'm worried that in just images, my game will reach 100mb, and then with sound effects and everything else it might be like 200mb. This seems pretty inefficient and I don't want potential players to shy away from the game just because of it's size, if they don't have enough room on their phone...
Am I doing something wrong? I apologize for this inexperienced question, I'm really new to Android development.
That isn't too big for modern games but you will need to not include the assets in the apk and either download that when needed or use what Google already thought of for this problem.
https://developer.android.com/google/play/expansion-files.html
These are some steps that can help you reduce your apk size:
Use only specific drawable
Add only specific image size for each drawable directory for drawable-mdpi, drawable-xhdpi, drawable-xxhdpi, etc. You can try removing a drawable directory that could potentially unused by the user, like drawable-mdpi and drawable-xhdpi, and use only the hi-res one like drawable-xxhdpi. Or, you can try using only drawable directory for all the images, so your app will only use one image for all devices type.
Resize your images
Compress your images
If your images are PNG files, You can compress the images without a noticeable change using pngquant. In fact, it can reduce your images sizes significantly (often as much as 70%) and preserves full alpha transparency. Or you can try using pngcrush (I'm rarely using this)
So I've tried going about animating a button through the example given in this example: Android Developers
and have made a huge (95 pictures) anim-list with Pngs. When trying to run the app and pressing the button, I promptly receive an error about memory not being sufficient. The file sizes are about 170k (12mb in total) . Is this too much for an animation? I realize the serious lack of regard for eventual users' storage space with this approach, but it's mostly for my own use anyway and won't matter.
The images are pretty big and need to be downscaled by the graphics engine however, and this might have to do with it?
Or is 95 pictures too much ? I can make the pictures smaller, right now they're at a whopping 4K resolution, which in hindsight is pretty dumb.
However, I can compress the pictures and make them smaller from the beginning anyway so that's not a problem. I just need to know how to fix this issue, if there's a treshold for how much can be loaded into RAM at a specific time so i can match the image sizes or if there's a way to override the default RAM settings or overcome this?
Don't look at the file size. Image has to be uncompressed so Android can use it. The image size is more or less equal to width*height*4. 4K image takes ~35MB of memory.
Modern devices can allocate 64MB of memory per app. It means that you can load only one such image. Maybe more if your phone has higher heap limit.
AnimationDrawable is for small animations (like 100x100px). If you wish to play such a large animation, you should encode it to mp4. If you can make the images smaller or make the animation procedural - go for it.
To override the memory limit use 'largeHeap' flag or change the setting in the ROM configuration (you have to flash your device with a custom ROM).
I started my first game 6 months ago and everything was fine and dandy. Now I've started added a lot of details into the game with some problems.
Problems.
1. Out of memory on older devices (Android 2.3) with high res screen. VM memory is only small on these. Don't have this problem with newer devices.
Getting a little lag which is bad on the super high-res devices.
Drawing large bitmaps is slow.
Currently I have:
canvas.drawBitmap(mBitmap, Pos.x, Pos.y, null);
Is there an easy way of converting this to OpenGL, as I now have hundreds of bitmaps using the above.
Ie.
GLView.drawBitmap(mBitmap, Pos.x, Pos.y, null);
Can anyone recommend something, I'm fairly new to OpenGL.
I have working on a large project which requires to support low performance devices for nearly a month. For your problem, I have few suggestions:
Consider whether you use jpg, png and bmp. According to my experience, jpg can improve the performance of old devices. However, there is a huge issue with jpg: it does not support transparency image. Think about it.
By using png (in case you wanna use it), try with 8 bit img. It will reduce the quality of the image a little bit. I mean, you can not easily recognise it, but it definitely improve lots of performance.
A tip is that, you can reload and draw all the images before starting the app. I do not have a chance to look at your code, but when I did it, my app changes from 35 fps to 55-60 fps.
Using sprite instead of titled background. Also, only use title where it is absolutely necessary.
Cheers.
Is there a good method to create HD like graphics for regular 480x800 devices as well as tablets? So far I can create HD like graphics for only 480x800 devices. And since i'm using OpenGL i place all of my graphics in the assets folder. My images are in the 480x800 format. I have thought of multiple ways and they are listed below.
I tried using 480x800 graphics and using OpenGL to stretch it to a tablet with GL_LINEAR. As expected, the graphics were great on the 480x800 devices and average if not poor on the tablet.
I have not tried this but I believe this to be a good method (need clarification). Using seamless textures and creating my background from those. (problem with this is that my character would become non-HD like).
(Soon to be tried) Using the res folder instead of the assets folder. Seperating tablet graphics and phone graphics. However, i have not come up with a good method to place these graphics in identical places with OpenGL. [need clarification on this :)]
What are some of your good methods to create HD games for both 480x800, 480x854 and tablets?
The answer is the one you probably expected - for the best results you should create images of different sizes and use the most appropriate set.
Hopefully not making this too vague... but I have been dealing with a lot of image scaling and manipulating with an app I'm working on and wanted to know:
Is it possible/feasible to warp images using java code and if so, is it possible? I have read up on JAI but can't seem to grasp it very well. Is there any form of built in implementation that would work with Android 2.3 or higher?
Any tutorials or examples that someone may have come across would be a great help as I have been researching for a while and can't seem to gain any ground.
End goal: to be able to warp an image (point to point by pixels) in multiple places and then saving the bitmap. This would be processed behind the scenes and show the user the end result.
do you have an example of the kind of warping that you want to do? It's certainly feasible but you'll probably end up doing pixel-by-pixel manipulation to generate the warped image.
there is a previous discussion here:
android image processing tutorial?