0

I am trying to animate some movements of a person on my device. I have created a sprite sheet, which ends up being 1.23Mb. The image dimensions is 5000 by 1500 pix. The sheet has 8 rows, each is it's own action. (Walk on, bow, jump...). The longest action is 32 images. So the image is basically 32 columns, by 8 rows. So, now I load it:

As soon as I do this:

private Bitmap bmp;
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.myImage);

I get an error:

Thread [<1> main] (Suspended (exception OutOfMemoryError))
BitmapFactory.decodeResource(Resources, int, BitmapFactory$Options) line: 385 BitmapFactory.decodeResource(Resources, int) line: 404
GameView.(Context) line: 25 FightActivity.onCreate(Bundle) line: 13 FightActivity(Activity).performCreate(Bundle) line: 4465
Instrumentation.callActivityOnCreate(Activity, Bundle) line: 1049
ActivityThread.performLaunchActivity(ActivityThread$ActivityClientRecord, Intent) line: 1920
ActivityThread.handleLaunchActivity(ActivityThread$ActivityClientRecord, Intent) line: 1981 ActivityThread.access$600(ActivityThread, ActivityThread$ActivityClientRecord, Intent) line: 123
ActivityThread$H.handleMessage(Message) line: 1147
ActivityThread$H(Handler).dispatchMessage(Message) line: 99 Looper.loop() line: 137 ActivityThread.main(String[]) line: 4424
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] Method.invoke(Object, Object...) line: 511 ZygoteInit$MethodAndArgsCaller.run() line: 784
ZygoteInit.main(String[]) line: 551 NativeStart.main(String[]) line: not available [native method]

Am I limited to a certain file size? Seems strange? And if so, is my only option to split the sprites onto separate 'action' images, as opposed to a sequence of action images per row in one large sprite sheet?

Hope someone can assist a novice.

Craig
  • 18,074
  • 38
  • 147
  • 248
  • Clarification - are you trying to make an image that's 32*5k by 8*1.5k = 1.92Bn pixels? Cause that'll crash a 32 bit process no problems. – NPSF3000 Jul 29 '12 at 03:30
  • No, sorry. The image is 5,000 by 1,500 pixels big, and that comes to 1.23 Megabytes in file size. That image contains 8 rows of 'frames', and that is 32 frames on each row. So, it contains 32x8 images, which I then display. So, it contains 256 small images. – Craig Jul 29 '12 at 03:35
  • 1
    file size is not the issue here your resolution is – Sunny Kumar Aditya Jul 29 '12 at 03:37
  • When I first created the image, it only had 5 rows of 32 images, and the file size was 0.8 Meg. It worked fine. I then added 3 rows of images to the file. Same resolution.. but now, bigger. And now it fails. So, because I have gone to 5000 by 1500 (It was probably 3000 by 1500 when it just had the 5 rows), that is the issue? This is a problem. :( – Craig Jul 29 '12 at 03:43
  • 1
    Thoughts: 1) Check the format - do you need 32 bits or 8. 2) Make the image smaller [either split it up or downsize it]. 3) Why isn't it a power of two resolution? – NPSF3000 Jul 29 '12 at 04:01
  • I think the images could go down to 8bit. But there is bit of shading. I'd lose the smooth shading... but ... maybe worth a bash. At the moment, I create the animation, and then export it into a series of PNGs, 24 frames per second. I then wrote my own .Net app that reads the images, and strings them into a new image, which I then save as BMP. I can look if there is a way to down scale the BMP image in memory, down to 8bit, before I save it to disk.... I'll look into that. As for the Power of 2... I'm new to this... and am not sure about that. – Craig Jul 29 '12 at 04:07

4 Answers4

1

A simple calculation gets you the answer. Assuming 32-bits per pixel, you have ((5000x1500)pixels) * (32 bits per pixel) / (8 bits per byte) / (1024 * 1024 bits per Mb) = 28MB.

I did a Google search and I'm seeing default heap sizes for different versions of Android and different handsets ranging from 16MB - 32MB. I think I see 24MB the most common. So it's very likely that you are simply running out of memory for your image. Check out this post to see what your heap size is: https://stackoverflow.com/a/9428660/1448071.

Edit: There does not appear to be a good way to increase VM heap size for Android. There is a VMRuntime.getRuntime() function with a setMinimumHeapSize function described here Android: how to increase heap size at runtime?. But it appears to be getting deprecated. I would recommend that you split up your sprite.

Community
  • 1
  • 1
Yunchi
  • 5,529
  • 2
  • 17
  • 18
  • Hang on - the filesize is 1.23 Megabytes... not 28 Megabytes. It's a small file. – Craig Jul 29 '12 at 03:40
  • 2
    Is your file a bmp file or a png/jpeg/gif/tiff? If it's the latter ones, your image is greatly compressed, but will be decompressed to full size when you load it as a bitmap. – Yunchi Jul 29 '12 at 03:40
  • 1
    It's a BMP file format. So, you're thinking that maybe in memory, Android is 'uncompressing' the file as you mention above, and it's using 28MB of memory for the image, which on disk, is 1.23Mb? – Craig Jul 29 '12 at 03:43
  • 1
    Yes. Took a quick look at Wikipedia and learned something new :) "Indexed color images may be compressed with 4-bit or 8-bit RLE or Huffman 1D algorithm. OS/2 BITMAPCOREHEADER2 24bpp images may be compressed with the 24-bit RLE algorithm." So it's likely your BMP is compressed. – Yunchi Jul 29 '12 at 03:47
  • Oh, bugger. So, my only option is to separate the rows into separate images, like film strips. I was hoping to have one sprite sheet. I have never done sprite animation (or Java, or Android development, for that matter), so am not sure what is the standard for doing this. Maintaining one file would have been easier and more maintainable. Damn... – Craig Jul 29 '12 at 03:50
  • Sorry but I don't have any experience with sprites either. Your sprites sound amazingly big though. Maybe you should reconsider your approach? – Yunchi Jul 29 '12 at 03:59
1

Have a single spritesheet for every animation in your character, hold a reference to common ones, and load as needed. This is flexible enough that your animation won't lag, except on bitmap change if you need to load it from memory, for example when you change from running to idle or something, (although those two are common enough that you would hold them in memory for a long time).

Increasing VM heap size is only a partial solution, and many devices won't have your needed heap size if you're holding bitmaps so big. Like they say above, image file size on disk is only important for deploying your application on Google Play (users will download less) but on ram the image is completely raw, which means every single pixel counts (example: a completely red 128x128 bitmap takes up the same space as a completely colorful one, having both exact same color depth).

I propose a solution for you, which is using this awesome software (I've no affiliation to it, except that I use it myself and it's great) that'll create your spritesheets in no time and export coordinates in various formats for you to use. TexturePacker.

RedOrav
  • 953
  • 9
  • 21
0

you need to increase the VM heap size. i'd love to grab links for you, but i guess this is the best i can do atm - Increase heap size in Java

Community
  • 1
  • 1
Shark
  • 6,513
  • 3
  • 28
  • 50
0

Depending on the complexity of the images, another answer may be to use vector graphics. There are numerous libraries with varying levels of documentation, and licensing requirements.

Example; http://www.andengine.org/

https://play.google.com/store/apps/details?id=org.anddev.farmtower.eco (AndEngine used on this game)

Raiden
  • 484
  • 2
  • 8