25 Replies Latest reply on Jan 20, 2009 5:39 PM by Olivier C

    Loading pictures from local file system

    Level 1
      Hello air guys,

      I'm currently working on an application to share images and the images are displayed as thumbnails in a Tile list.
      I have a problem when loading the images from the local file system with the Loader object : it is slow with large files, between 0.8 sec and 1 sec., large files meaning more than 3MB.
      I tried using a cache system (resizing images and then saving them to the user's computer) to avoid loading the large file next time the loading of the picture is requested but the problem is still the same since the initial loading is too long.
      I experienced an air application where my 3MB images are loading something like 4 or 5 times faster so there is a way ..

      My question is, is there another way to load images from local file system and display them than using a Loader object or do you have an idea on how I could speed up the loading of these images ?

      Thank you very much.
        • 1. Loading pictures from local file system
          Level 1
          I have searched several hours on the internet for an answer to this "problem" and the only one I found is using the EXIF information from the JPEG image files which may contain a thumbnail of the original file, but unfortunately not for all JPEG files. (however the problem remains the same for image files with other extensions ..)

          Can anyone confirm me that there is not a simpler way to gain speed that I would have missed out ?

          Many thanks.
          • 2. Re: Loading pictures from local file system
            wdfwefewfewfew Level 1
            i've noticed the same thing. any progress?
            • 3. Loading pictures from local file system
              Level 1
              Hello there, no progress for the moment. I noticed something very strange : some pictures (especially vertical ones) are lighter than the others but the loading phase is longer. I wonder why ..

              I only found this post on Ted Patrick's blog (Adobe) which describes how to make a image loading with a progressive effect, the same way a browser would do it naturally ( http://www.onflex.org/ted/2007/12/progressive-image-loading-with.php)

              Everything attempt I did was with the Loader control. I don't think there is another way to extract the bitmap data from a ByteArray image. I also tried with the Image control to be sure that Adobe did not include some special feature for this control but the result was the same.

              Did you try the same kind of things ?
              • 4. Re: Loading pictures from local file system
                wdfwefewfewfew Level 1
                I haven't found any way to speed this up, but I thought maybe it was AIR being slow with local file system access. But then I tried loading large files from the web, and found that was very slow too... so perhaps its the Image class is just insanely slow (very annoying).

                What was the other App that you said was faster? Maybe we can learn something from that.
                • 5. Re: Loading pictures from local file system
                  wdfwefewfewfew Level 1
                  uh oh... the adobe reps answered every question on the front page except this one... :(.
                  • 6. Re: Loading pictures from local file system
                    Level 1
                    The application I experienced is Abelli Photo Books. It's simply amazing :-D
                    I don't know why Oliver Goldman did not answered, he is in general always answering questions.

                    We will find a solution, we're gonna make it mate ! :)
                    • 7. Re: Loading pictures from local file system
                      Level 1
                      I found the following article in the Adobe Developer Center about loading images from Drag and Drop using HTML.
                      When you drag a large file onto the application, the loading phase is very quick. I think this is because this application is using HTML controls, so AIR may be implicitly calling the OS native browser to load the image. What do you think about this point ?

                      I've read that it is possible in an AIR application to mix HTML and Flex controls. So maybe we can perform the loading of the images in HTML and then display them using Flex controls ?
                      • 8. Re: Loading pictures from local file system
                        Oliver Goldman Adobe Employee
                        It's pretty much impossible to answer performance questions without something to measure. If you can put together a *simple* example, we could at least run it to validate its performance.

                        • 9. Re: Loading pictures from local file system
                          wdfwefewfewfew Level 1
                          Thanks for your help Oliver! You can copy this code into a new AIR project, and add a "photos" folder into the app directory containing the swf. I added 11 jpegs (file name ends in '.jpg') of about 3 megs each and got the following results:

                          finished loading one image in: 0.991 seconds
                          finished loading one image in: 7.286 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 7.287 seconds
                          finished loading one image in: 9.206 seconds
                          finished loading one image in: 9.207 seconds

                          <?xml version="1.0" encoding="utf-8"?>
                          <mx:WindowedApplication xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute" width="800" height="600"
                          creationComplete="loadImagesInAppPhotosFolder();">

                          <mx:Script>
                          <![CDATA[
                          import mx.controls.Image;

                          private function loadImagesInAppPhotosFolder():void
                          {
                          // get all the files in app-directory/photos
                          var appDirectory:File = File.applicationDirectory.resolvePath("photos");
                          var files:Array = appDirectory.getDirectoryListing();
                          var startTime:Number = (new Date()).time;
                          var numFiles:int = files.length;
                          var numImages:int = 0;

                          // check each file to see if its a jpeg
                          trace('num files found: ' + numFiles);
                          for (var i:int = 0; i < numFiles; i++)
                          {
                          var file:File = files as File;
                          var fileType:String = file.url.substr(file.url.length - 4).toLowerCase();
                          var image:Image = new Image();

                          // if the file is a jpeg, add it to the display list in a grid format
                          trace('getting file: ' + file.url + ", file type: " + fileType);
                          if (file.isDirectory == false && fileType == ".jpg")
                          {
                          // logic to make thumbnails that fit in a grid format
                          image.width = image.height = 150;
                          image.y = 10 + image.height * Math.floor(numImages / 4);
                          image.x +=10 + (image.width + 10) * (numImages % 4);
                          image.source = file.url;
                          numImages++;

                          // trace when we're done
                          image.addEventListener(Event.COMPLETE, function(e:Event):void
                          {
                          trace('finished loading one image in: ' + (((new Date()).time - startTime) / 1000) + " seconds");
                          });

                          trace('adding image: ' + file.url);
                          this.addChild(image);
                          }
                          }
                          }


                          ]]>
                          </mx:Script>
                          </mx:WindowedApplication>
                          • 10. Re: Loading pictures from local file system
                            Oliver Goldman Adobe Employee
                            OK. Now let's define what we're trying to measure. This code is measuring much more than just the time it takes to read the contents of an image into memory. For example, the timer is started before you've schedule any of the loads, and it's also doing image scaling.

                            Furthermore, it's loading 11 images at the same time, and including all of that in the timing results as well. In general, it's better to load a limited number of images (perhaps 1 or 2) at a time; it prevents contention for shared resources (including disk bandwidth) that can end up slowing everything down.
                            • 11. Loading pictures from local file system
                              Level 1
                              Hello Oliver,

                              Thank you for your help, you'll find below a quick example of the code I'm currently using. I've noticed that using the loadBytes method is quicker than the load method on the Loader object, however is there a more efficient way to load the images ? (with this code you'll get a delay of 500ms to load a 4MB picture ; sorry the delay I wrote in my initial message was wrong, it included other actions)

                              <?xml version="1.0" encoding="utf-8"?>
                              <mx:WindowedApplication xmlns:mx=" http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="_OnCreationComplete(event)">
                              <mx:Script>
                              <![CDATA[
                              import mx.core.UIComponent;
                              private var _loader:Loader = new Loader();
                              private var _startTime:Date;
                              private var _endTime:Date;

                              private function _OnCreationComplete (event:Event):void
                              {
                              _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _OnLoaderComplete)
                              _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _OnLoaderIOError);


                              var path:String;
                              // Set your own path for a picture to load
                              // path = "C:/Users/Oliv/Desktop/P1000154.gif";
                              path = "F:/DONNEES/PHOTOS/2008-07-26 - Mariage Vinz et Gaby/P1000251.JPG";

                              // Example n°1
                              // Call to load method
                              // _startTime = new Date();
                              // _loader.load(new URLRequest(path));

                              // Example n°2
                              // Call to loadBytes method
                              var ba:ByteArray = new ByteArray();
                              var f:File = new File(path);
                              var fs:FileStream = new FileStream();
                              fs.open(f, FileMode.READ);
                              fs.readBytes(ba, 0, fs.bytesAvailable);
                              fs.close();

                              _startTime = new Date();
                              _loader.loadBytes(ba);
                              }

                              private function _OnLoaderIOError (event:IOErrorEvent):void
                              {
                              _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, _OnLoaderComplete)
                              _loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, _OnLoaderIOError);

                              trace ( event.text );
                              }
                              private function _OnLoaderComplete(event:Event) : void
                              {
                              _endTime = new Date();
                              trace ( "Loading time : " + (_endTime.getTime() - _startTime.getTime()) + " ms");

                              _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, _OnLoaderComplete)
                              _loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, _OnLoaderIOError);



                              var somesprite:Sprite = new Sprite();
                              somesprite.addChild( (event.currentTarget as LoaderInfo).loader );
                              var bd:BitmapData=new BitmapData(800,600); // incorrect dimensions, the image will be cropped, it's just for this simple test
                              bd.draw(somesprite);

                              var bitmap:Bitmap = new Bitmap(bd);

                              var uic:UIComponent = new UIComponent();
                              uic.addChild(bitmap);
                              uic.addEventListener(Event.ADDED, _OnImageContainerAdded );

                              // Add image to the stage
                              _startTime = new Date();

                              addChild(uic);
                              }
                              private function _OnImageContainerAdded (event:Event):void
                              {
                              _endTime = new Date();
                              trace ( "Image added to the stage in : " + (_endTime.getTime() - _startTime.getTime()) + " ms" );
                              }

                              ]]>
                              </mx:Script>
                              </mx:WindowedApplication>

                              • 12. Re: Loading pictures from local file system
                                wdfwefewfewfew Level 1
                                i've adjusted my code, and same thing - loader.loadBytes() is the slow part. any way of speeding this up would help immensely. or if there was a way to loadBytes asynchronously or in batches (to load a large jpeg in 10 steps instead of 1) would also be useful if possible? thanks!
                                • 13. Re: Loading pictures from local file system
                                  Oliver Goldman Adobe Employee
                                  @Olivier C: To the best of my knowledge, Loader is the fastest way to load an image for display. The results you're seeing seem to make sense. The loadBytes() call is faster than load() because it works from data already in memory. Loading the image, even from memory, requires decompressing the JPEG image.

                                  There is also some overhead to either call because they operate asynchronously, so scheduling and event dispatch must be done. It's worth noting that these APIs were originally designed for loading images in web pages where the network speed is likely to be the limiting factor, anyway.

                                  Going back to your original question, it may be more likely that the application you saw is hiding (rather than eliminating) this delay. For example, both pre-fetching and caching could be used effectively.

                                  @ wdfwefewfewfew: The loadBytes() method is asynchronous.

                                  • 14. Re: Loading pictures from local file system
                                    wdfwefewfewfew Level 1
                                    Thanks Oliver, this is very helpful!

                                    I see loadBytes() is asynchronous, but I notice that the processing involved is so intensive that the application loses all sense of UI responsiveness for the majority of the time a larger (3000 x 2000) jpeg is loading. Perhaps the async process effectively blocks when it gets to the jpeg decompression part? Whatever it is, any suggestion for improving the responsiveness of the Flash Application? I notice other native applications do not block - perhaps loading a second flash application to handle loading might help keep the UI responsive?
                                    • 15. Re: Loading pictures from local file system
                                      Level 1
                                      Hello Oliver,
                                      Thank you very much for the explanations on the Loader object's behavior. I will work on the way you suggested, pre-fetching / caching images.

                                      wdfwefewfewfew ,
                                      I did not encounter the problem you are describing. How do you load your images ? Are you waiting for each image to be loaded before loading a new one ? Are you manipulating the raw BitmapData after having loaded a larger image (If yes, take a look at this article about the BitmapData object limits : http://www.bit-101.com/blog/?p=1199)

                                      Olivier
                                      • 16. Re: Loading pictures from local file system
                                        Oliver Goldman Adobe Employee
                                        I should also note that you will get faster results if you put the Loader directly on the stage instead of drawing through a Bitmap and putting the Bitmap on the stage. Perhaps there's some particular effect you're achieving via this route, but it forces much more memory to be allocated and data to be copied. (Don't forget that once your image is in memory it's no longer compressed.)

                                        • 17. Re: Loading pictures from local file system
                                          wdfwefewfewfew Level 1
                                          Strange. I open each file, read the bytes, then load the bytes, and find the UI very non-responsive. If you try loading multiple large jpegs (~4 megs) one at a time, and try dragging the title window around, do you find it jerky or silky smooth?

                                          stream.open(file, FileMode.READ);
                                          stream.readBytes(bytes);
                                          loader.loadBytes(bytes);
                                          // load next file after the loader's Event.COMPLETE event is fired
                                          • 18. Re: Loading pictures from local file system
                                            Level 1
                                            Thank you for your knowledge Oliver. In fact I'm using a Bitmap object to resize the images I load and creating cache (only when the image is loaded for the first time of course) ; this is the only way for resizing, right ?

                                            wdfwefewfewfew , can you post your complete code ?
                                            • 19. Re: Loading pictures from local file system
                                              wdfwefewfewfew Level 1
                                              Olivier - you posted code up above and said "with this code you'll get a delay of 500ms to load a 4MB picture".

                                              If you load several 4MB pictures and try dragging the AIR window around the screen, do you notice that the UI only get updated every 500ms?
                                              • 20. Re: Loading pictures from local file system
                                                Oliver Goldman Adobe Employee
                                                @Olivier: using the Bitmap to cache a smaller version of the image is a reasonable approach.

                                                @wdfwefewfewfew: In the code you posted on 9/2, you're doing a synchronous read of 4 MB of data. That's likely the reason for the pause while dragging the window. Passing a URL to the Loader can be a better choice because it operates fully asynchronously.

                                                • 21. Re: Loading pictures from local file system
                                                  Level 1
                                                  wdfwefewfewfew, I have tried to drag the application window while 1 image is loading and I confirm that the UI is less responsive. Meaning that when I drag the window to a direction, the window is actually moved with a delay (this delay corresponding to the time for loading the image). This is happening for large image files but with light files it is of course fully responsive.

                                                  My opinion is that loading large image files requires a lot of resources from the computer (for example my processor use reaches 55% during this phase) that's the reason why this kind of operation should be associated with a modal window informing the user of the action currently processed, as it is implemented in most softwares when processing heavy operations.
                                                  • 22. Re: Loading pictures from local file system
                                                    Milos Roglic Level 1
                                                    I have the same problem like wdfwefewfewfew has. When I'm loading just one large picture (2-3MB) in my custom chrome AIR app, it is sometimes very UI irresponsible so that all chome UI dissapears and shows just blank flex window. I just load image and not show it on screen. The code is simple:

                                                    myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
                                                    myLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, updateProgress); myLoader.load(urlRequest,new LoaderContext(false,new ApplicationDomain()));

                                                    Is there any workaorund to change this behavior of Loader class?
                                                    • 23. Re: Loading pictures from local file system
                                                      kiwi_ziesch Level 1
                                                      I´ve some probs with the loader - see thread "Create thumbnail from selected images"
                                                      I won´t display the images but saving a generated thumbnail. But the loader´s source is always the same for every chosen image.
                                                      Maybe some of you guys can help me out.

                                                      Thanks in advance.
                                                      • 24. Re: Loading pictures from local file system
                                                        Billy888 Level 1
                                                        Hi Oliver Goldman and Olivier C,

                                                        Do you find the solution already ? I encounter the same problem when loading large pictures (2MB each) from local file system is very slow ?
                                                        If you have solution, please share your sample code.

                                                        Thanks.
                                                        Billy
                                                        • 25. Loading pictures from local file system
                                                          Level 1
                                                          Hi Billy,

                                                          Sorry for the late delay I have been quite busy last days. I have not yet find any workaround for this problem, I put the development of my application on standby since last summer.

                                                          However I would be glad that we share our knowledge of the problem to try to find an efficient solution.