We are building a scrollable background, and currently have one large background image that we split up into 512x512 tiles, and want to load these tiles as they are needed, instead of all at once, when calling GLUtils.texImage2D within onDrawFrame, we have noticeable lag we think because of having to load the texture onto the hardware, is there a better way to do this?
Thanks.
Use texSubImage2D() to reload existing texture objects instead of creating entirely new ones.
G'day buddy,
I think the sheer amount of image data you're trying to transfer within a frame time is a tad much: if you are using a 24bpp format, 512x512 amounts to 1 MB of data. I can think of two ways to minimize it:
Change to a bitmap format that has less bpp. If you are using ARGB8888 you might want to try switching to RGB565 (as it is a background) to halve the data.
Consider splitting up the 512x512 into e.g. 4 chunks of 512x128 (since you are scrolling vertically). This way you distribute the loading over more frame intervals.
Cheers, Aert.
Related
Right now I am working in developing live wallpaper.
I have around 75 animation images for my main character and in one spot I can't able to load it into memory.
It throws an OutOfMomory exception.
Basically I have to continuously change frame of my main character from first to last. So I write algorithm for loading required image and unload other image. But it calls garbage collector program continuously so as a result animation can't run smoothly as per expectation.
So how to manage that much images for live wallpaper?? Please provide some guidance here.
Maybe the tips Nicolas posted here will help you.
Short version:
Reduce texture sizes.
Reduce texture switches (aka try to use spritesheets, so that the texture needs to be changed as few as possible)
Use lower quality textures (RGBA4444 or RGB565 instead of RGBA8888)..
Call setIgnoreUpdate where the entity doesn't need updates.
Use SpriteBatches if possible.
You can also add "android:largeHeap=true" in your application tag along with the tips LordRaydenMK has suggested.
I am stuck showing frame animation in android. My problem is that I have to animate 36 images. The smallest image is 69 kb in size and the biggest(last frame) is 526kb. A total of 11mb. I know its insane but I need to do it. See images below. The app is already made for iphone and I have to port it to android.
Requirements:
smooth animation
no frame loss
consistent with iphone
The solutions I tried are:
AnimationDrawable by providing in xml files. Problems: the start time is almost 6 -12 seconds. Images lose frames so jaggy experience.
Change imageview bitmap inside a handler. Problems: Frame loss and Out of memory
Create a custom imageview class. Define a method showAnimation() and inside it update bitmap and invalidate() the view unitl the last frame. Problems: Not fitting my requirement. This by far gave the best result but not half as required.
I am a noob in opengl and gamedevelopment. I am unable to find any alternative to my problem. Please help.
Smallest image:
Last image:
I can visualize the effect you are aiming at.I guess doing this will require pushing in different images onto the same imageView, with incremental frame rate.|
The accuracy will depend on the number of images you have. Greater the number of images finer will be the precision.
Also you need to implement incremental frame rate. So that it gives a smoother feel.
Doing this should be possible using a simple loop to change the image resource of the imageView Controller. There must be lag between two iterations, this lag will actually be the frame rate.
I think this can give satisfactory results.
Going for openGL, however, you will not need all these images. It will just require one image of the card that will be animated and duplicated to create the final image. This however is a complex piece of task(I think) so if you are catching some dead lines, you must go for a non-openGL solution like the 1st one, I have suggested.
I'm currently trying to create a game for a tablet device for Android using a SurfaceView. I have sprites and what not, but I'm struggling if I should use a whole spritesheet (With every animation in it), or just seperate the sprites on image files.
For example, my spritesheet is named bear.png, which contains 16 images inside. I can animate them beautifully using Rect (Thanks to mybringback for this):
canvas.drawBitmap(bitmap, rectSrc, rectDest, null);
But, I fear doing so would grow to larger than the heap size eventually.
However, there is another method. By seperating each image (bear1.png, bear2.png until bear16.png), I will also be able to create an animation with these sprites via:
Bitmap bitmap = Bitmap.decodeResource(context.getResources(), context.getResources().getIdentifier("bear" + index, "drawable", "com.example.game"));
then calling that to the canvas:
canvas.drawBitmap(bitmap, bitmapX, bitmapY, null);
Which also works fine for now. And of course, it greatly reduces my heap size since I'm only using 1 image at a time. But, because well.. Because, I'd be recalling Bitmap.decodeResource() at almost all times, I fear that when putting many animations together at one time, it may cause a significant lag.
So in short:
- Spritesheets: Increased heap size (which may eventually lead to an OutOfMemory error), but better performance
- Sprites on different image files: Decreased heap size, but may hinder performance
I'm not entirely sure which approach to use. Would it actually be okay if I go with the second method (Sprites on different image files)? Or would it be better with just spritesheets?
Never mind, I just answered my own question. It appears that rendering Bitmap.decodeResource() on every iteration lags the whole canvas, rather than rendering actual spritesheets and using Rect. Performance-wise, if experiencing too much lag on the canvas, there's no other way other than to shrink images using inSampleSize or using GLSurfaceView.
My app is loading a large image (a house floorplan), then drawing touch-reactive objects (furniture, lamps etc.) on the image. I have a base image file included with my app but the objects come from coords in my database.
I've successfully deployed the app in multiple iterations, but now I need to use larger base images and BitmapFactory is causing an OutOfMemory exception on many devices (both old and new devices; anything with < 32MB heap seems to crash). I've read the 157 OOM questions on SO, but I'm afraid the link they all seem to point to won't help me since resolution / zooming is critical to the app's function.
I've tried to test the device's available memory before loading, but the results are spotty at best (some devices like the galaxy S3 report plenty of heap but still crash). I've also tried decreasing resolution but the image became unusable when reduced to a safe size based on the above test.
Is there another way to implement this design without ever using bitmaps?
I need to:
Load large base image
Create clickable shapes on top of the base image, maintaining their position / scale relative to the base image
BONUS: in the iOS version of my app, I can do SVG-style text scaling so a long label on a small object will stay inside the object
instead of running across the map(and will be invisible until the
image is zoomed). Replicating this in android would make me a happy
code monkey.
I can post code if needed, but you've all seen it before (almost all of it came from SO).
Thanks in advance for reading, and for any help you can give.
you have a few options:
break your large image into tiles, load these tiles into an array, and move a camera object around and only load tiles that need to be drawn, as the comments suggest.
make your image small and scale it up using 'android:scaletype`
Draw lines and curves on a Canvas object at runtime.
Use OpenGL
The appropriate solution really depends on how you want it to look. Tiling will take more dev effort but will look better, just be careful that you are properly cleaning up any tiles that aren't being drawn...
dynamically scaling will be easier, but you cannot guarantee the image won't be blurry.
Drawing on a Canvas object at runtime could work well-- just use Lines of different width and circles and Rects etc.
Using OpenGL will have the steepest learning curve, and might be overkill. This depends on your purpose.
You might like to look into using a "largeHeap"
http://developer.android.com/reference/android/R.styleable.html#AndroidManifestApplication_largeHeap
Here are some options:
1) Use tiles. Use tiles and dynamically load your data. Honestly, this is the best solution. With this solution you can load arbitrarily large images.
I've successfully used this approach for an endless paint canvas and it works quite well. You really only need to draw what is directly visible to the user. Tiles is a way to cast away pieces you don't need. A pyramid of tiles (where you pre-downsample your images and create more tiles), allows you to do this in a clean and fast way.
2) Use native code. The memory restrictions on native code are not the same as Java code. You can get away with allocating more memory.
3) Use OpenGL. Once again, the memory restriction for OpenGL are not the same as Java code.
4) Convert your original plan to an SVG and use an SVG library like this one.
5) Use "largeHeap". I strongly discourage this, as I think a largeHeap is rarely the solution, there are generally cleaner ways to approach the problem.
if the image is static , you might wish to use this nice library:
https://github.com/ManuelPeinado/ImageLayout
if the library doesn't support auto-downsampling of the image, you should do it by yourself, in order to use the best image for the current device (so that you won't get OOM).
for auto-sizing text , you might have some luch with the next post:
Auto-fit TextView for Android
To what extend do color depth and compression level of the original jpg and/or png images used as drawables have an effect on the app's UI performance, given the fact that all images are converted to bitmaps internally anyway.
Especially considering i.e. images in list views for example.
Same question goes for png vs. xml shapes as drawables.
Edit: I found a similar question which addresses memory usage, but my focus is more on UI performance (i.e. scrolling long list views, etc.).
Is decreasing size of .png files have some effect to resulted Bitmap in memory
Larger images probably take longer for decompressing, but when they're cached properly (and i.e. asynchronous lazy loading), after initial loading, it shouldn't matter anymore.
If the images are indeed all are converted to bitmaps internally anyway, then I think you're right, the compression level of the original file makes no difference once the image is loaded.
Color depth of the image, on the other hand, would still be a preserved difference, right? I.e. image files of different color depth on disk can be loaded to in-memory images of different color depth. So I would expect "deeper" images to have an adverse effect on performance eventually.
But as always, you never know for sure about performance till you run tests.