1

I am writing an application that should batch resize images in a folder. My problem is that my code works for directories that has small images or directories that has small number of images, but when I run my code on directories where there are many large images that requires more processing, the application crashes without reporting any errors. Here is my code:

function BatchResizeDirectory(){
        var dir : File = new File;

        dir.addEventListener(Event.SELECT,function(){
            var files = dir.getDirectoryListing();

            for each (var file:File in files) 
            {
                if(["png","jpg","bmp","jpeg"].indexOf(file.extension.toLocaleLowerCase()) != -1){

                    file.addEventListener(Event.COMPLETE,function(e:Event){
                        var f:File = File(e.target);    
                        var loader:Loader = new Loader();
                        loader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event){

                            //init bmp data
                            var bmpd:BitmapData = new BitmapData(loader.content.width,loader.content.height);
                            bmpd.draw(loader);

                            //resize
                            var result:BitmapData = ImageResizer.bilinearIterative(bmpd, 64,64,
                                ResizeMath.METHOD_PAN_AND_SCAN);

                            //write to disk
                            var pnge:JPEGEncoder = new JPEGEncoder();
                            var bytes:ByteArray = pnge.encode(result);

                            var name = f.name.replace("."+f.extension,"");
                            var outputFilename = dir.nativePath+"/"+ name + "_resized." + f.extension;
                            var outputFile:File = dir.resolvePath(outputFilename);
                            var fs:FileStream = new FileStream();
                            try{
                                //open file in write mode
                                fs.open(outputFile,FileMode.WRITE);
                                //write bytes from the byte array
                                fs.writeBytes(bytes);
                                //close the file
                                fs.close();
                            }catch(e:Error){
                                trace(e.message);
                            }

                        });
                        loader.loadBytes(f.data);

                    });

                    file.load();

                }

            }
        });

        dir.browseForDirectory("Choose the input folder");

    }

My question is. Why is my application crashing on heavy processing? Does it have anything to do with anonymous declaration of event handlers? I am confused.

Thank you!

dlock
  • 9,447
  • 9
  • 47
  • 67

1 Answers1

3

Check your memory usage, also you can call bitmapData.dispose once you are done with resizing an image to free the memory.

I would also move those anonymous functions out to make it easier to read and less prone to error due to the for loop.

Edit : I believe the problem was that the files array had no other refence so you were losing the references to the files. Try the following code and see if it helps.

package 
{
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.filesystem.File;
    import flash.filesystem.FileStream;

    public class Main extends Sprite 
    {
        private var _files:Array;

        public function Main():void 
        {
            BatchResizeDirectory();
        }

        private function BatchResizeDirectory():void{
            var dir : File = new File;

            dir.addEventListener(Event.SELECT,function():void{
                _files = dir.getDirectoryListing();

                for each (var file:File in _files) 
                {
                    loadFile(file);

                }
            });

            dir.browseForDirectory("Choose the input folder");

        }

        private function loadFile(file:File):void 
        {
            if(file.extension && ["png","jpg","bmp","jpeg"].indexOf(file.extension.toLocaleLowerCase()) != -1){

                file.addEventListener(Event.COMPLETE, onComplete);

                file.load();
            }
        }

        private function onComplete(e:Event):void 
        {
            var f:File = File(e.target);    
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.INIT,function(e:Event):void{

                trace(f.name);
            });
            loader.loadBytes(f.data);

        }
    }
}
Barış Uşaklı
  • 13,440
  • 7
  • 40
  • 66
  • The memory usage seems fine. The program crashes before resizing a single image. It takes a period of around 10 seconds then it freezes and stops responding. The memory usage was reported to be 80mb which is not much. What do you suggest? – dlock Mar 15 '13 at 16:44
  • How big is the image it starts to work on? And, depending on IDE, 15s may be the standard script timeout. – Josh Mar 15 '13 at 16:45
  • The images are around 4mb each. Also, I just realized that `Event.COMPLETE` is not firing at all when the directory has many images and the images are large in size. – dlock Mar 15 '13 at 16:47
  • Make the functions standalone and debug to see where it crashes. – Barış Uşaklı Mar 15 '13 at 16:51
  • 1
    And you said the file is 4mb is that a jpg? What are the dimensions of the image that is crashing maybe you are hitting a limit. – Barış Uşaklı Mar 15 '13 at 16:53
  • @BarışUşaklı I commented out the lines for resizing/bmp loading. I also made the handlers standalone, the problem is still happening and the app doesn't fire `Event.Complete` for any `File`. – dlock Mar 15 '13 at 16:59
  • Try the `INIT` event instead of `COMPLETE`. See : http://stackoverflow.com/questions/11541730/bytearray-to-bitmapdata-as3/11542166#11542166 – Barış Uşaklı Mar 15 '13 at 17:00
  • @BarışUşaklı tried it, still the same. Maybe its happening because it tries to `.load()` MANY files at once? – dlock Mar 15 '13 at 17:01
  • @BarışUşaklı It's happening for the `File` object not the `Loader`. The `Event.Complete` for for each file does not fire. – dlock Mar 15 '13 at 17:03
  • `The FileReference.load() and FileReference.save() functions are nonblocking. These functions return after they are called, before the file transmission is complete. In addition, if the FileReference object goes out of scope, any transaction that is not yet completed on that object is canceled upon leaving the scope. Be sure that your FileReference object remains in scope for as long as the upload, download, load or save is expected to continue.` From http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#load() – Barış Uşaklı Mar 15 '13 at 17:06
  • Not sure if that's your problem but worth a shot, though I guess the files array is keeping the references alive. – Barış Uşaklı Mar 15 '13 at 17:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/26258/discussion-between-deadlock-and-baris-usakli) – dlock Mar 15 '13 at 17:09