17 Replies Latest reply on Mar 6, 2007 7:28 AM by buabco

    Load Images

    odenys
      Hello

      Could you please assist me with such issue

      I am using a Canvas object like a container for images (Image class). My application loads 500-1000 images (tiles) dynamically and then displays them. Everything works fine but the memory grows up to 300Mb.

      Here is a code:


      private function GetLoop(layer:String):void {
      var canvas:Canvas = new Canvas();
      for(var i:Number = 0; i < curFrames; i++) {
      var img:Image = new Image();
      img.addEventListener(Event.COMPLETE, OnImageLoaded); img.load(urlReq);
      canvas.addChild(img);
      }

      }
        • 1. Re: Load Images
          buabco Level 1
          HI!

          you used up so much memory beacuse you have all 1000 images in memory at a time. You must load them as you need them in order to optimize this.

          Fortunatelly the TileList container is designed to do this and you should use it. If you combine it with a custom itemRenderer you'll need no code to achieve what you are looking for.
          • 2. Re: Load Images
            odenys Level 1
            Hi, buabco

            Thank You for your quick answer

            The main idea of my application is to show animation of some layers ( Canvas which contains set of images). So, I have a set of canvases (each of them contains set of images/tiles). To do animation at first I have to load all images into the appropriate canvases (containers) an then show necessary canvas (animate).
            • 3. Re: Load Images
              buabco Level 1
              In that case I guess you are in trouble, my recomendation is that you consider optimizing your code. If what you are trying to achieve is a transition between canvases then you only need 2 canvases at a time, I guess you can make your code add canvases dynamically as needed instead of all at one time.

              You can still preload all the images so you'll be able to display them quickly, to do this you can use 2 or 3 image containers to download all the images, even if you destroy the image immediately after download it will stay in the browser cache, so next time you load the image in a image container it should load pretty fast. Since you are handling 90 MB of data though this can take some time.
              • 4. Re: Load Images
                odenys Level 1
                Thanks

                I am just trying to understand why there is so much memory being used. All 1000 tiles are ~10Mb. At the beginning the application (browser) uses ~40Mb, and after tiles loading it increases to ~300Mb. The reason is that for each image the new object is stored into the memory?

                Is it possible to use any advantages of Bitmap object? I mean to draw one bitmap (which will contain all tiles) for each canvas.
                • 5. Re: Load Images
                  buabco Level 1
                  I suppose you can, but remember that when you see the file size you are looking at JPG compressed images, when flash access them it has to decompress them into memory. I guess that's the reason your memory size goes all the way to 300 MB.

                  If you come to think of this having all images in one Bitmap should use more or less the same amount of memory. Still I'm not sure how flash manages its internal memory.
                  • 6. Re: Load Images
                    jpwrunyan Level 1
                    I can't help you with your application as it is currently constructed but I may be able to shed some light as to why so much memory is being used. Flash cannot display .jpg images as such. It converts every image loaded into a bitmap. So even if you have a miniscule 15x15 gif file (approx 370 bytes) loaded into the FlashPlayer (for example, via the Image class) it gets displayed as a 15x15 bitmap with 3 or 4 bytes per pixel (depending on whether it uses the alpha channel). So now FlashPlayer is using 900 bytes of memory for your image.

                    And as I think you guessed, if you use the same .gif in 4 Image class instances, each one gets loaded into its own memory location for 900 x 4 = 3,600 bytes of memory used.

                    Just to give you a heads up, if you try removing the Image class after you are done with it, the bitmap data will still stay in memory causing a very serious memory leak. Although this is beyond the scope of your current application (as I understand it) it will need to be addressed by accessing the Image.content as a BitMap and then calling dispose() on the BitMap.bitmapData. I only say this now because in my experience, anytime someone is loading images dynamically in their application, they inevitably end up wanting to unload them later. So again, for future prosperity, remember to dispose your bitmap data before you remove your Image classes:

                    BitMap(ImageLoader_inst.content).bitmapData.dispose();

                    likewise, if you are smart(er than me) you might be able to create a bitmapData instance for shared images and pass a reference to that to Bitmaps that are being displayed in your application. Again, this will only theoretically help you if you are using the same image multiple times.

                    Sorry but these are the only suggestions I can make to help cut down memory usage when dynamically loading external images--and these tips might not even apply to your current goal.
                    • 7. Re: Load Images
                      odenys Level 1
                      Thank you

                      Now I better understand how the Image's object is stored into the memory.

                      Thanks for the valuable advice concerning bitmap data disposing. It really helped in case of unnecessary images removing.
                      • 8. Re: Load Images
                        buabco Level 1
                        Hi jpwrunyan,

                        From reading to your explanation I ended up a little confused; are you saying that garbage collector wont destroy the image data once you dispose of the object?, lets say I have a sprite with 4 Loader classes that each loaded an image, if I remove every reference to the Sprite, and the garbage collector take care of it, and later of the loader classes since they ended up with no reference, the image data will still be eating up memory?
                        • 9. Re: Load Images
                          jpwrunyan Level 1
                          quote:

                          Originally posted by: buabco
                          are you saying that garbage collector wont destroy the image data once you dispose of the object?, lets say I have a sprite with 4 Loader classes that each loaded an image, if I remove every reference to the Sprite, and the garbage collector take care of it, and later of the loader classes since they ended up with no reference, the image data will still be eating up memory?


                          In essence, yes, that is what I am saying. However, I must add the caveat that I am not privy to the inner workings of the garbage collection system. What minimal knowledge I do have I picked up from gskinner.com (www.gskinner.com/blog/). Last year another forum user was having the same trouble and he ended up posting on gskinner's blog and he was able to figure out that the bitmap data had to be disposed. And he also provided some explanation as to why.

                          In my case I had a component that used an Image class to load external bitmaps. I tried many different implemenations varying the following two themes:

                          1) Single Image class that dynamically loaded different .jpgs
                          2) Single parent class that dynamically loaded different Image classes for each .jpg

                          whether changing the content of the Image, or removing the Image class entirely and creating/adding a new Image, I found that flash was holding onto the bitmap data. Since my images were 2000x1500 pixels I rapidly ran out of memory.

                          However, I was not able to crash my computer the way a true memory leak should. What I found is that when I got to about 90% of my RAM, then Flash player started recycling data. My only guess is that the player decided on its own "well, I gotta get rid of something or I'm gonna crash" and therefore finally started disposing (I assume) bitmap data. However, like I said, I have no way of knowing for certain--it's just my speculation. The player could easily have been disposing of other information as well, although the sheer volume of bitmap data in memory means that, if data was chosen at random by the garbage collector, the bitmap data was most likely removed.

                          This is one of those things where I really wish someone at Adobe or a Flash player engineer would enlighten the community.
                          • 10. Re: Load Images
                            buabco Level 1
                            Me too I wish I could have some recomendation form Adobe on the right way of preparing data for disposing. All I know now is that you should remove every reference to an object in order to for the garbage collector to kill it. This is kind of tricky when you are using events since you need to remove event listeners from an object so it will be disposed, I wonder why there is no deletion command on the flash framework.

                            I'm not sure ether how or when the player performs the garbage collection, there is no command to force it, so you should relly on it. For what I can read on your own experience it seems that the Player tends to use garbage collection as the only last resort when it's running out of memory which doesn't look very good.

                            Still, I'm writting an application that should end up using lots of images, I'm not using the IMAGE class but a sinple Loader, I haven't check on the memory usage yet, but I'll write here what I found.
                            • 11. Re: Load Images
                              jpwrunyan Level 1
                              Just to let you know, the Image class actually contains a Loader inside of it. The Loader's property name is "content".
                              Also, garbage collection does occur periodically. You can see this if you watch your resource manager. What I was trying to say is that when the player is running extremely low on resources, it seems to force garbage collection on resources it might not consider true garbage as a safety precaution. Presumably, if it had endless resources, it would not do so. Anyway, just wanted to clarify, garbage collection definately does work, just not for bitmap data.
                              • 12. Re: Load Images
                                Matlus Level 1
                                jpwrunyan,

                                I'm interested in the sharing aspect you mention. Have you tried this? Any help would be appreciated.
                                • 13. Re: Load Images
                                  jpwrunyan Level 1
                                  Matlus,

                                  I have not tried sharing with bitmaps or bitmapData objects yet. I have done sharing with simple XML data, URLLoader data, and DisplayObjects. The concept should basically be the same, though. My only hesitation is that bitmaps are terra incognito for me.

                                  However, if I were to try it, I would make a static bitmap data variable for some custom AS class that is similar to the SWFLoader or Image class (or even extends from them). Anyway, I will assume I have a class that displays a bitmap. I may have more than one of these classes on the screen at a time. The class will extend from a regular UIComponent and contain a Bitmap instance. However, the class will have one globally accessable (static) BitmapData class instance. Use a class initialization technique similar to that used when making custom styles to call a method the first time any instance of this class in instantiated. In that method set up your BitmapData class instance. In the regular instance constructor (or createChildren method or wherever), set the Bitmap instance's bitmapData reference to the static class reference. That should do it. You can set filters independently and show the same image on screen multiple times (hopefully) without getting tons of redundant bitmap data instances the way (I suspect) you do if you try the same thing with Image or SWFLoader.

                                  Like I said, I do this with ComboBox dataProviders where the dataProvider is taken from an external XML but I have multiple instances of the same ComboBox/dataProvider in one application (although I have the added incentive because the XML is furthermore taken from the server and I don't want to call the server EVERY time a combobox appears--but that's neither here nor there). Anyway, though, like I said, the same priniciple should apply here as well.

                                  And if you want to dynamically apply the same technique for any number of bitmap data (such that any one bitmap data is only loaded once and then never again), it shouldn't be too big a leap to set up a Dictionary (or just a regular array if you like) and then load the images from there to the appropriate instances based on some key value.

                                  I'm sorry I don't have any code worked out. But if you 're interested (and what I described above makes sense), then give it a whirl. If you have problems, post them.
                                  • 14. Re: Load Images
                                    odenys Level 1
                                    Hi, jpwrunyan

                                    Could you give any idea about such approach. I am going to load all necessary images using URLLoader and store them into the ByteArray. When the animation starts I will show necessary images from ByteArray ( using Loader.loadBytes() ). How to represent loader's content as UIComponent (e.g. to put it into canvas container) and then how to dispose this bitmap from UIComponent?
                                    • 15. Re: Load Images
                                      buabco Level 1
                                      I think I actually did this, even though I thought I was copying the bitmap, since it was more than one copy of the image on the stage.

                                      What I did is something like this:

                                      var ldr:Loader; //Lets asume this is the loader you used to load the image and the image is already loaded, I'll not add the code to actually load the image here.

                                      var bmp:BitmapData = new BitmapData(ldr.width, ldr.height); //Try use the real width and height here
                                      bmp.draw(ldr.content);

                                      var copy:Bitmap= new Bitmap();
                                      copy.bitmapData = bmp;
                                      • 16. Re: Load Images
                                        odenys Level 1
                                        Thanks, buabco

                                        Do you know what the significant difference between Loader and URLLoader classes is?.. and what is better to use for PNG images/tiles loading?
                                        • 17. Re: Load Images
                                          buabco Level 1
                                          odenys,

                                          They are totally different, and they are used for totally diferent things as well. The URLLoader is meant to server side script communication, you can get a PNG from it but you'll just get the PNG data, not sure how you go from there to a display object, I don't think you can any ways, since what URLLoader provide is RAW data.

                                          The Loader class on the other hand is a DISPLAYOBJECT and is meant to load IMAGES and SWF files you'll use on your stage. This class does all the uncompressing of Images for you and just gives you a display object in it's "content" parameter.

                                          I totally recommend you the Loader class for image loading.