Games Loading a lot of images

Informatix

Expert
Licensed User
Longtime User
I'm trying to use the new framework for games (XUI2D+BitmapCreator). What's the recommended method to load a lot of big images into memory? Is there any option to lower/optimize the memory usage?
It's for a card game with illustrations on cards (there are more than one hundred 400x900 images to load and you may have to browse through them during the game, so it's better if they are all already loaded and ready to be drawn).
 

ilan

Expert
Licensed User
Longtime User
i think the best way to load graphics into memory in xui2d is by using the x2utils library like this.

B4X:
x2.GraphicCache.PutGraphic2("mystery", Array(x2.LoadBmp(File.DirAssets, "mystery.png", 1, 0.5, True)), True, 2)

and then you can get it back with the name and the index by using:

B4X:
x2.GraphicCache.GetGraphic(...)

i am not sure about the performance but this is how you load images into the cache memory.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The angle interval can have a large impact on the memory used, assuming that the image will be rotated. If the image will never be rotated then set it to 360. If they do rotate and you want to lower the used memory then increase it to 5.
Note that rotated images are only created when needed (or when you call X2.GraphicCache.WarmGraphic).
 

Informatix

Expert
Licensed User
Longtime User
i think the best way to load graphics into memory in xui2d is by using the x2utils library like this.

B4X:
x2.GraphicCache.PutGraphic2("mystery", Array(x2.LoadBmp(File.DirAssets, "mystery.png", 1, 0.5, True)), True, 2)

and then you can get it back with the name and the index by using:

B4X:
x2.GraphicCache.GetGraphic(...)

i am not sure about the performance but this is how you load images into the cache memory.
I get very quickly a OutOfMemory error on different devices so this doesn't help me.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Loading hundreds of non-small images is likely to require too much memory.
Assuming that each image is loaded with a size of 900x400 then each image needs at least 1.5mb. You will reach the process memory limit.

You can downscale everything by initializing X2Utils with a smaller ImageView and then resizing the ImageView after this call.
 

Informatix

Expert
Licensed User
Longtime User
Loading hundreds of non-small images is likely to require too much memory.
Assuming that each image is loaded with a size of 900x400 then each image needs at least 1.5mb. You will reach the process memory limit.
This is not a problem with libGDX since resources are stored outside the Java heap. In a non-game application, I avoid this kind of problem quite simply:
- I increase the size of the Java heap in the manifest (but here, this is not enough);
- I reduce the number of colors of opaque images (ARGB8888 -> RGB565, but this format is not supported by BitmapCreator);
- I use an LRU cache to avoid cluttering up the memory with little-used images (but here, the result is not satisfactory when it comes to scrolling through the entire deck of cards).

You can downscale everything by initializing X2Utils with a smaller ImageView and then resizing the ImageView after this call.
Everything is resized to obtain the required quality on the device. The solution will not come from there.
The compressed format of BitmapCreator will not help me either because 99% of my images are opaque.
In the end, it seems there is nothing in your classes to help me with my card game and I will have to use libGDX to finish my project under Android, which is a problem, because it is supposed to work also under Windows. I would like to share the code between B4A and B4J.
 

ilan

Expert
Licensed User
Longtime User
This is not a problem with libGDX since resources are stored outside the Java heap. In a non-game application, I avoid this kind of problem quite simply:
- I increase the size of the Java heap in the manifest (but here, this is not enough);
- I reduce the number of colors of opaque images (ARGB8888 -> RGB565, but this format is not supported by BitmapCreator);
- I use an LRU cache to avoid cluttering up the memory with little-used images (but here, the result is not satisfactory when it comes to scrolling through the entire deck of cards).


Everything is resized to obtain the required quality on the device. The solution will not come from there.
The compressed format of BitmapCreator will not help me either because 99% of my images are opaque.
In the end, it seems there is nothing in your classes to help me with my card game and I will have to use libGDX to finish my project under Android, which is a problem, because it is supposed to work also under Windows. I would like to share the code between B4A and B4J.

is it not possible to load only the amount of cards that are needed in that specific play? like load about 50 cards and when you play the game load the other cards for the next play so always hold 2 sets in advanced. i have no idea what kind of game it is but loading 100s of images is maybe also not a very good approach even if using libgdx or am i wrong? even if you dont have any memory issues why holding 100s of cards in memory?

another solution would be wrapping libgdx for b4j :D

i really would like to know how spritekit handle such an amount of images in memory? maybe i should make some tests :rolleyes:

i had an idea to create a library using libgdx but put all commands as in ispritekit because i like a lot the logic how it works and like this i could share the same code for my ios and android games. i think it could be easily possible since spritekit has much less commands then libgdx. and using a class that use the same commands only with libgdx engine could really be an awesome solution for game making in b4x (b4a + b4i)
 

Informatix

Expert
Licensed User
Longtime User
is it not possible to load only the amount of cards that are needed in that specific play? like load about 50 cards and when you play the game load the other cards for the next play so always hold 2 sets in advanced. i have no idea what kind of game it is but loading 100s of images is maybe also not a very good approach even if using libgdx or am i wrong? even if you dont have any memory issues why holding 100s of cards in memory?

another solution would be wrapping libgdx for b4j :D

i really would like to know how spritekit handle such an amount of images in memory? maybe i should make some tests :rolleyes:

i had an idea to create a library using libgdx but put all commands as in ispritekit because i like a lot the logic how it works and like this i could share the same code for my ios and android games. i think it could be easily possible since spritekit has much less commands then libgdx. and using a class that use the same commands only with libgdx engine could really be an awesome solution for game making in b4x (b4a + b4i)
Imagine a deck of 100 cards that a player can scroll through to select any card. This player may want to choose the card in the final position and go there by scrolling the cards very quickly. You cannot display all 20 cards: "Wait, we'll load the next 20 images", especially if this operation has to be repeated several times during a match. Nor can you display a placeholder as we usually do in an image gallery when the images are being loaded.
The original image size is 400x900, but depending on the screen resolution, the actual bitmap size can be much smaller or slightly larger (e. g. on a Samsung 9).
 

ilan

Expert
Licensed User
Longtime User
Imagine a deck of 100 cards that a player can scroll through to select any card. This player may want to choose the card in the final position and go there by scrolling the cards very quickly. You cannot display all 20 cards: "Wait, we'll load the next 20 images", especially if this operation has to be repeated several times during a match. Nor can you display a placeholder as we usually do in an image gallery when the images are being loaded.
The original image size is 400x900, but depending on the screen resolution, the actual bitmap size can be much smaller or slightly larger (e. g. on a Samsung 9).

i understand but when we are using ULV even if we have 1000 items we dont load all 1000 items. and it does scroll very smooth or smooth enough so why not use the same approach? you can see it in a lot of games that if they have a big list and you scroll very fast the lower items are loaded in real time and it doesnot bother anyone to much as long as it takes less then a second or two i think it is ok.

do you have something to show? a short video of the card game?
 

Informatix

Expert
Licensed User
Longtime User
i understand but when we are using ULV even if we have 1000 items we dont load all 1000 items. and it does scroll very smooth or smooth enough so why not use the same approach? you can see it in a lot of games that if they have a big list and you scroll very fast the lower items are loaded in real time and it doesnot bother anyone to much as long as it takes less then a second or two i think it is ok.
If I could use the same method, I would use it. In fact, I tried and it was not what I expected (images are really big so reading them back from the disk is not fast enough on some devices and I don't want to put a placeholder; the card would be unrecognizable).

you can see it in a lot of games that if they have a big list and you scroll very fast the lower items are loaded in real time and it doesnot bother anyone to much as long as it takes less then a second or two i think it is ok.
Why should I accept an unsatisfactory situation (lack of fluidity or very low resolution) when I can get exactly what I want with libGDX? I already created such a game with libGDX (Dark Continent) so I know it's possible. If only BitmapCreator would support RGB565, that would help a lot (the bitmap size is strongly reduced with this format and the difference is not really noticeable).

do you have something to show? a short video of the card game?
This game uses temporary illustrations so there's nothing exciting to show. Moreover I'm not allowed to publish anything at this time.
 

advansis

Active Member
Licensed User
Longtime User
Do not know if I understood well... What about pre-scaling the entire game-desktop in memory (canvas) and load dinamically the zoomed part?
 

wonder

Expert
Licensed User
Longtime User
I'm trying to use the new framework for games (XUI2D+BitmapCreator). What's the recommended method to load a lot of big images into memory? Is there any option to lower/optimize the memory usage?
It's for a card game with illustrations on cards (there are more than one hundred 400x900 images to load and you may have to browse through them during the game, so it's better if they are all already loaded and ready to be drawn).

Hi! :)

I've been dealing with a similar situation, as I'm writing a comic book reader, using good old LibGDX as the backend.
My solution is loading the images into Pixmaps on a background thread (using lgAsyncTask) and loading the Pixmaps into Textures in a continuous update loop.

Holding more than 40 (~2 megapixel) textures in memory results in crash, so I'm loading no more than 5 pages (textures) at the same time (the user can only see 3 pages on screen). The Java memory consumption is up to 24mb and Native heap sits around 170mb.

Pixmap to Texture takes 60 milliseconds to complete, so I'm masking it behind the user TouchUp gesture. The Pixmap loader itself, which runs on the background, doesn't affect performance at all, even under heavy load.


upload_2019-5-7_0-13-29.png


Note that I cannot load the Textures on the background thread, because the openGL context is lost (undefined behavior) and the AssetManager doesn't work with external files.
https://www.badlogicgames.com/forum/viewtopic.php?f=11&t=1565
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
Hi! :)

I've been dealing with a similar situation, as I'm writing a comic book reader, using good old LibGDX as the backend.
My solution is loading the images into Pixmaps on a background thread (using lgAsyncTask) and loading the Pixmaps into Textures in a continuous update loop.

Holding more than 40 (~2 megapixel) textures in memory results in crash, so I'm loading no more than 5 pages (textures) at the same time (the user can only see 3 pages on screen). The Java memory consumption is up to 24mb and Native heap sits around 170mb.

Pixmap to Texture takes 60 milliseconds to complete, so I'm masking it behind the user TouchUp gesture. The Pixmap loader itself, which runs on the background, doesn't affect performance at all, even under heavy load.


View attachment 80160

Note that I cannot load the Textures on the background thread, because the openGL context is lost (undefined behavior) and the AssetManager doesn't work with external files.
https://www.badlogicgames.com/forum/viewtopic.php?f=11&t=1565
I have no problem with libGDX, only with the new game framework, which is cross platform. I have to create a game running on two platforms and I thought that BitmapCreator would help, but I face a memory issue with it that I can't solve.
 

Informatix

Expert
Licensed User
Longtime User
Hi! :)

I've been dealing with a similar situation, as I'm writing a comic book reader, using good old LibGDX as the backend.
My solution is loading the images into Pixmaps on a background thread (using lgAsyncTask) and loading the Pixmaps into Textures in a continuous update loop.

Holding more than 40 (~2 megapixel) textures in memory results in crash, so I'm loading no more than 5 pages (textures) at the same time (the user can only see 3 pages on screen). The Java memory consumption is up to 24mb and Native heap sits around 170mb.

Pixmap to Texture takes 60 milliseconds to complete, so I'm masking it behind the user TouchUp gesture. The Pixmap loader itself, which runs on the background, doesn't affect performance at all, even under heavy load.


View attachment 80160

Note that I cannot load the Textures on the background thread, because the openGL context is lost (undefined behavior) and the AssetManager doesn't work with external files.
https://www.badlogicgames.com/forum/viewtopic.php?f=11&t=1565
Note that's the way UltimateListView works with items.
 
Top