Skip to main content
Known Participant
January 14, 2013
Question

How to avoid uncompressing bitmapDatas multiple times

  • January 14, 2013
  • 6 replies
  • 5241 views

Hi,

Not sure if this should go here (performance) or IOS section, since I mainly have this issue on iOS but I think its on all air players.

When a bitmap (for exemple a bitmap in a fla) is added, you can see with Adobe SCOUT (great tool btw!) that it is uncompressed when added. Allright.

The bad thing is, if it is removed from stage, even if you keep it in memory for reuse, it is very often re-uncompressed when redisplayed. I mean 'often' because it seems erratic. If it stay removed for just a second, most of the time it won't be uncompressed again, but after 3 or more seconds, most of the time it will be (some kind of garbage collector in the "video" memory ?)

Setting its quality to lossless in the fla helps the decompression goes a bit faster (30-40 % I would say), on the detriment of swf size, but does not solve the main question : how can I force an animation (made of bitmaps for example) to never be uncompressed again as long as I dont tell it to to be "disposed" from wherever this is stored ?

Having it permanently on screen hidden somewhere is just too much a performance killer to be considered a solution when you have many. CacheAsBitmapMatrix could be usefull for vector data  on this issue (not sure), but drawing a bitmap seems a bit stupid if you do already have bitmaps.

It might not seem a big issue but in a game with effects etc. most of those will only show up once every 2 to 10 seconds, but if you loose 5ms/frame for 40 frames each time one does, and you have many, it really impact performance on devices like ios etc, whereas memory doesnt seem to be the problem here, it happens with low or high memory usage both.

If anyone knows a tip, thanks a lot!

EDIT : Tests made with gpu mode, flash builder 4.7, air 3.5, iPad3 (or other), release build.

This topic has been closed for replies.

6 replies

bethsierra1977
Known Participant
October 10, 2014

I am sad to report that I am also still somewhat having these decompression problems. The only thing that worked in any form of quasi-satisfactory way, were the solutions (2,3 and 6) listed here: actionscript 3 - How to reduce lag or performance problems due to images decompression on AIR, flash apps - Stack Overfl…

pierBover

bethsierra1977
Known Participant
October 8, 2014

In my experience, the second solution here: actionscript 3 - Bitmaps Being Cached As Bitmaps - Stack Overflow is the one that gave me best results thus far, even when loading a swf (as opposed to a bitmap) which contains bitmaps inside. To avoid this decompressing on the run (on demand) you can instead request flash to decompress it on load. This will increase the load time but improve the perceived performance of the app since a separate thread takes care of the decompressing. This of course means no jitter or skip when the image hits the screen:

var fileLocation:URLRequest = new URLRequest(levelToLoad);

levelToLoad = "testLevel.swf";

var levelLoader:Loader = new Loader();

var loaderContext:LoaderContext = new LoaderContext();

loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;

levelLoader.load(fileLocation, loaderContext);

Embedded images (via code) are not supposed to be compressed, so this problem shouldn't occur with applications that do so. However, if you are like me, and you use the Flash Pro IDE to import PNGs or other bitmap assets, Flash Pro compresses them as JPG by default, using the setting provided by the image itself.

To fix this and avoid these decompression issues, simply go to your Flash Pro asset library, right click on the image you want to change, click on properties and select "lossless / PNG/GIF" as compression. This will increase largely the load time but you will have the much better perceived performance discussed here. This should be done in addition to implementing the code above, or it will make no difference.

In my experience the frame rate average dropped only by one frame per second, but it's much more consistent without any skips or lags which is essential for games.

See: http://help.adobe.com/en_US/as3/dev/WS52621785137562065a8e668112d98c8c4df-8000.html

And

http://www.bytearray.org/?p=2931

Known Participant
October 8, 2014

Hey Beth

Sure ON_LOAD can increase performance, but even when decoding on a separate thread, you can get stuttering when adding big images to the stage because the runtime has to calculate dirty regions. I have experienced this many times when loading retina images on an iPad 3.

Another problem is that when a decoded image is not displayed on screen for a certain time (I think it's 10 seconds) the runtime will erase the decoded image from memory. So when you need to display that picture it will be decoded again on the main thread. The way to avoid this is using the getPixel trick mentioned earlier.

Known Participant
June 29, 2013

What about using ImageDecodingPolicy.ON_LOAD ?

I'm using it on iOS and images that are decoded, keep decoded.

I still haven't checked memory though...

Known Participant
June 29, 2013

Interesting, didn't know that it this existed. It seems to me it affects only Loader though, like if you load a .png. It doesn't affect the bitmaps contained in a swf, or those you create at runtime, does it ?

I would say 90% chance it doesn't solve the issue, but still worth having a deeper look.

Participant
February 20, 2014

*bump*

Any progress on this?  I am also having a hard time delivering a smooth frame-rate when my app is liable to suddenly spike 10-20ms in a single frame from image (re)decompression.  It makes things look amateur.

As a serious platform for games/multimedia, we really need control over when the runtime is going to do this (we are already all going to great lengths preallocating everything to prevent the GC from doing this).

I am worried that the getPixel() method might incur other unseen penalties, such as perhaps forcing an unswizzling of GPU texture.

Best regards

Participating Frequently
April 8, 2013

Have you find a solution yet? I have tried ContentCache, but it seems to be useless in this case.

Known Participant
April 9, 2013

Unfortunately no. And I have too many of them to just do getPixel on each every 50 or so frames. Didn't try contentCache but I believe you. One thing I didn't try is Starling, if you wan't to give it a try.

So I just live with it, but it is definitely a perf-killer when added to stage again in a real time environment

If you find more info, or less costfull ideas, please let me know.

Participating Frequently
April 9, 2013

Well, cacheAsBitmap seems to fix this, but it also does not come for free.

I have patched ContentCache version with "loaderInfo.content.cacheAsBitmap = true;" and i don't see "Image Decompressing" any more. Can you confirm?

Known Participant
January 15, 2013

I forgot to specify, maybe I wanted to avoid a too long post^^ :

- unfortunately storing all the BitmapDatas or Bitmap (or MovieClips...) doesn't change anything since it is a decompression made for display, nothing else. Tested this and didn't help.

- using sprite sheets and some kind of scrollrect (or another technique) shouldn't help either because same thing : it will just decompress the whole sheet when it is back and haven't been displayed for a while (not tested but since the issue is not animation-related that's my guess, should be the same with just 1 large bitmap like a sprite sheet).

This seems to have to do with only flash rendering, what is kept and what is not for next renderings (video memory ?).

Known Participant
January 15, 2013

Found a workaround using getPixel but it is not very good : http://jacksondunstan.com/articles/2080

Not much good because in order to be sure the uncompression is never done again, you have to do those getPixel frequently, and this hurts performances. It is still a positive effect on my project, but it could be way more positive if the getPixel and all weren't needed (a direct way to tell air to keep it uncompress for further use).

Not sure if starling could help here, but since I'm not sure about the performances impact, it is too costfull to switch all the project to starling for only a supposition.

Colin Holgate
Inspiring
January 15, 2013

In that example code the bmd variable is just local to the onLoaded function. Surely if a bitmapData is stored in a more global variable its data will be kept around, until you null the variable?

chris.campbell
Community Manager
Community Manager
January 14, 2013

Moved to Mobile Development and gave our iOS team a heads up.