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

ToddBFisher picture ToddBFisher · Apr 3, 2012 · Viewed 7.2k times · Source

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.

Answer

ToddBFisher picture ToddBFisher · Apr 4, 2012

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