• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
Locked
0

How to avoid uncompressing bitmapDatas multiple times

New Here ,
Jan 14, 2013 Jan 14, 2013

Copy link to clipboard

Copied

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.

TOPICS
Development

Views

4.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Jan 14, 2013 Jan 14, 2013

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 14, 2013 Jan 14, 2013

Copy link to clipboard

Copied

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 ?).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 15, 2013 Jan 15, 2013

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 15, 2013 Jan 15, 2013

Copy link to clipboard

Copied

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?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 15, 2013 Jan 15, 2013

Copy link to clipboard

Copied

Yes you need it global of course, but keeping the bitmapdata is not enough, the problem is its display decompression you can see with Adobe Scout when it is added (or when you perform a getpixel on it). If you don't have done any of those thing since a while, it will redecompress again the next time it is used (even if the bitmapdata are kept in references). It wont take super long each frame, but even 5ms each if many overlaps can be quite costfull (I sometimes go down 10 fps because of this).

Hope this clears it up.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 08, 2013 Apr 08, 2013

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 08, 2013 Apr 08, 2013

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 09, 2013 Apr 09, 2013

Copy link to clipboard

Copied

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?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 09, 2013 Apr 09, 2013

Copy link to clipboard

Copied

- Didnt try that, but since I'm already working with bitmaps, cacheAsBitmap would nearly double the memory usage no ? If so I can't use it at all (memory is as always already a limit).

Also how would you apply this to swf having hundreds of bmps in library ? Except of course making as many symbols cachedAsBitmap which is not an option for memory as I said. I suppose you work with something like 1swf = 1 animation, or singles png files. So I can't really confirm but you can test this with adobe scout.

- About ContentCache, didnt see it's in spark, which we don't use on iOS. We prefer to rely on basic flash engine and not import this, broken or not

What I would love, and I'm sure Kemsky too, is something where when you do have references on BitmapDatas/Bitmaps (of course they're not collected but that is not the issue), they only decompress once (either when first added or with a method) and then you can set them to either "keep them" as uncompressed or not, even if removed from stage for long period. Colin didn't seem to understand the issue, and it doesn't seem a priority for Adobe

This and the horrible impact of screen touching/"dragging" (even with mouseChildren false and everything) are the 2 worst performance impact on iOS to me. All the rest is fine or nearly (you can always rasterize if needed).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Apr 09, 2013 Apr 09, 2013

Copy link to clipboard

Copied

It's nearly three months since I wrote in this thread, I had to go back and see what it was that I didn't understand!

In that getpixel workaround article, doesn't it say that you have 10 seconds? I've done getpixel things where I had a whole image to read 30 times per second, surely the overhead if reading one pixel per bitmap every ten seconds won't be that high?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 09, 2013 Apr 09, 2013

Copy link to clipboard

Copied

One of the problem is that it is not a fixed-reliable value, so it may be 10 seconds or even 30 if your memory usage is very low (or another reason, I don't have the source code of the player so I'm just guessing here) but it may be 3 seconds, or less in other cases.

Well you see the first issue.

The other issue is that it is fine if you have like 1, 2 or 10 bitmaps that you want to keep this way. I don't dispraise this workaround, it fits some needs for some projects. But suppose you know pretty much how many you have total, and that it fits ok with memory. Then you would want that on every animation of the game that takes a bit too long to decrompress. That can be hundreds of getPixels to do every 3 seconds, with a manager, and you're not even sure if you're setting the timing right (3 secs ? more, less ?). So all in all, you waste really significant perf doing all this (managing the thing, doing getPixels, dispatching it on many different frames as possible, etc). I'm not saying this is not doable, but if you have to loose 3 permanent fps, to avoid the drops... well I suppose this is "better", but clearly not really good. So far we sticked with the drops, just trying to lower their impact (smaller visual effects...), even if we didn't succeed totally, and hope this will be "fixable" someday, with real "locks", not getPixeling everything in the background.

Lastly I'm not sure how this would behave if you have an animation of bitmaps (not exported) in a symbol, instead of blitting. Need to getPixel every frame ? How since it is seen by Flash as "Shapes" (which they are not), and clearly the player gives me better result when NOT exporting the bitmapDatas, with gpu, even if exporting them does lower a lot the decompression time at display (not 0 though), it doesn't compensate the loss. Tried png-8 too but again, doesn't compensate. I know this seems strange but I suppose it's totally internal work. But I disgress here.

Lastly bis : if you have to getPixel a whole image I suppose you used getPixels (with an s), which is of course a LOT faster than doing width*height times a getPixel, so you can't really compare results. Mine with about a hundred of getPixel where not good enough and the worst the device, the worst the impact since you can't mipmap code

Again, it is suitable for some projects, but not for every.

When you think a "lock" method on DisplayObject would both prevent this AND maybe fastened the kind of garbage collector that is behind this (since it could skip those lock in it's schedule), it makes me a bit sad.

Sorry for the long post, which provided 0 new information I admit.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 09, 2013 Apr 09, 2013

Copy link to clipboard

Copied

Yep, cacheAsBitmap will double memory, but i've got only 2 large bitmaps(as background) in my view-based application, that make view transitions sluggish, so i think its ok for me. I was interested if it really worked and i did not miss anything.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jun 28, 2013 Jun 28, 2013

Copy link to clipboard

Copied

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...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 28, 2013 Jun 28, 2013

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Feb 20, 2014 Feb 20, 2014

Copy link to clipboard

Copied

*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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Apr 19, 2014 Apr 19, 2014

Copy link to clipboard

Copied

bump

I just got into this problem... anyone found a solution except the getPixel method?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Apr 20, 2014 Apr 20, 2014

Copy link to clipboard

Copied

It turns out if you copy the pixels of the bitmapdata that you loaded into a new bitmap data, this doesn't happen, and you don't really need to getPixel every few seconds, at least in iOS.

var loadedBitmapData = event.target.content.bitmapData;

var newBitmapData:BitmapData = new BitmapData(loadedBitmapData.width,loadedBitmapData.height);

newBitmapData.copyPixels(loadedBitmapData,new Rectangle(0,0,loadedBitmapData.width, loadedBitmapData.height),new Point(0,0))

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 07, 2014 Oct 07, 2014

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Oct 07, 2014 Oct 07, 2014

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 10, 2014 Oct 10, 2014

Copy link to clipboard

Copied

LATEST

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...

pierBover

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines