Search code examples
actionscript-3flashjpegbitmapdata

How to save BitmapData to Bitmap *.bmp file, or much faster JPE Encoding method


I have a Flash / Actionscript 3 based desktop app wrapped in an *.exe using Zinc 4.0. I am using Flash Pro CS5.

I need to start saving very large image files locally. I have messed around with JPG Encoding these images before saving them to a local file via Zinc. I solved the actionscirpt timeout issue using This "asyncronous like" method. Encoding a 1.5 MP image takes about 5 seconds which is alright, but encoding an 8 MP image file takes about 40 seconds, which is not acceptable.

One idea I had is to save the BitmapData locally to a temporary Bitmap file (*.bmp), without having the end user to wait for JPG Encoding in Flash, and then use my already existing image processor (written in C#) to read the bitmap file and encode it without waiting on Flash to do it, effectively offloading the task away from the user.

I have used BitmapData.getPixels() to try and write the byte array directly to the file, using the same Zinc method as I do successfully with encoded JPGs, but the *.bmp file is unreadable. Are there some file headers that would need to be included in addition to the BitmapData getPixel()'s byte array to successfully save a bitmap image? If so how could I successfully add them to the byte array before writing to file?

Any guidance, clarification or other solutions much appreciated.


Solution

  • I've found a solution for my needs, and just in case others have similar needs:

    To save an actual Bitmap (*.bmp) file, Engineer's suggested Btimap encoder class was awesome. Very fast on the actual encoding; however, since my file writing call in Zinc is synchronous and bitmap files are a lot larger than JPGs it really just moved my bottle neck from encoding to the file saving, so I decided to look elsewhere. If Zinc had an asynchronous binary file writing method that would not lock up the GUI I would have been happy, but until then this is not the solution for me.

    I stumbled across a Flash Alchemy solution, with great results. Instead of waitint abour 40 seconds to encode an 8 MP image, it now only takes a few seconds. This is what I did:

    1. Downloaded the jpegencoder.swc from this page and saved it in my project directory
    2. Added the swc: Publish Settings > Flash (tab) > Script: Actionscript 3.0 "Settings..." button > Library path (tab)> and added that .swc with Link Type = "Merged into code"
    3. Then used it :

    (below is my modified code with just the basics)

    import flash.utils.ByteArray;
    import flash.display.BitmapData;
    import cmodule.aircall.CLibInit; //Important: This namespace changed from previous versions
    
    var byteArrayResults:ByteArray; //Holds the encoded byte array results
    
    public static function startEncoding(bitmapData:BitmapData):void {
    
        var jpeginit:CLibInit = new CLibInit();     // get library
        var jpeglib:Object = jpeginit.init();       // initialize library exported class to an object
    
        var imageBA:ByteArray = bitmapData.getPixels(bitmapData.rect);  //Getpixels of bitmapData
        byteArrayResults = new ByteArray();
        imageBA.position = 0;
        jpeglib.encodeAsync(encodeComplete, imageBA, byteArrayResults, bitmapData.width, bitmapData.height, 80);
    }
    
    private static function encodeComplete(thing:*):void
    {
        // Do stuff with byteArrayResults
    }
    

    You may find this link useful as well: http://last.instinct.se/graphics-and-effects/using-the-fast-asynchronous-alchemy-jpeg-encoder-in-flash/640