• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Encoding Bitmaps and Byte Arrays

Participant ,
Jul 01, 2009 Jul 01, 2009

Copy link to clipboard

Copied

Hello,

I've been banging my head repeatedly on my desk for the last couple of days, trying to get my program to work, with no avail. With no further option, I decided i'd ask the experts.

I am making a program which will ask the user to select an image, then encode it to a binary string and store in an XML file. It will then be able to 'decode' the fil and reconstruct it.

I've followed a few guides online, but I can't seem to get anything to work. My understanding is that I need to break the Bitmap into it's BitmapData components, convert that to a 'byteArray' which is saved, (or optionally encoded) then that same byteArray data is retrieved and made into a movie clip onto the stage. However, no matter what I do, I can't get it to properly recreate the bitmap once i've grabbed the data... It always throws a "end of file

In order to get the basics, i've cut my code down to the bare minimum - which is just to load the image from the local filesystem, grab it's bitmapdata, clone it and place it into a new Bitmap which is added to the stage. However, I only ever get returned a "End of file encountered" error message - which seems to indicate to me it's not properly populating the byteArray. (It certainly looks much too short when traced)

Please help!

Here's my code for the basic loader -

import flash.display.Sprite;
import flash.events.*;
import flash.net.*;

//load image
var loader:Loader = new Loader();
var url = "C:\\Data\\cutcord.jpg";
var urlReq:URLRequest = new URLRequest(url);
configureLoader(loader.contentLoaderInfo);
loader.load(urlReq);

function completeHandler(event:Event):void {

     var imageIn:BitmapData = event.target.content.bitmapData;
     var byteArray:ByteArray = imageIn.getPixels(imageIn.rect);
     var newBitmapData:BitmapData = imageIn.clone();
     
     newBitmapData.setPixels(imageIn.rect, byteArray);
     var newBitmap:Bitmap = new Bitmap(newBitmapData,"auto",true);
     
     this.addChild(newBitmap);
}

function configureLoader(dispatcher:IEventDispatcher):void {
     dispatcher.addEventListener(Event.COMPLETE, completeHandler);
}
TOPICS
ActionScript

Views

8.5K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Engaged , Jul 03, 2009 Jul 03, 2009

Here's one way to do that.

I've broken it up into 2 parts. One part is loading the original image (to create ByteArray from).

Second part (loadImageData()) is using the Base64 encoded ByteArray and convert it back to an image and display it.

import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Bitmap;
import com.dynamicflash.util.Base64;
import flash.display.BitmapData
import flash.geom.Rectangle;

var loader:Loader;
var req:URLRequest;
var orig_mc:MovieClip;
var copy_mc:MovieClip;

v

...

Votes

Translate

Translate
Engaged ,
Jul 02, 2009 Jul 02, 2009

Copy link to clipboard

Copied

Try the following:

import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Bitmap;
import flash.display.BitmapData;

var loader:Loader;
var req:URLRequest;
var orig_mc:MovieClip;
var copy_mc:MovieClip;

function loaderCompleteHandler(evt:Event) {
var ldr:Loader = evt.currentTarget.loader as Loader;
var origImg:Bitmap = (ldr.content as Bitmap);
var origBmd:BitmapData = origImg.bitmapData;
trace(origImg.width);
trace(origImg.height);

var image:Bitmap = new Bitmap(origBmd, "auto", true);
copy_mc.addChild(image);
copy_mc.x = origImg.width;
}

loader = new Loader();
req = new URLRequest("2.jpg");
loader.load(req);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);

// movieclip to display original image
orig_mc = new MovieClip();
orig_mc.addChild(loader);
addChild(orig_mc);

// movieclip to display image copy
copy_mc = new MovieClip();
addChild(copy_mc);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 02, 2009 Jul 02, 2009

Copy link to clipboard

Copied

Thank you so much! You sir, are a gentleman and a saint. That is incredibly helpful.


If you don't mind, I have another question, as I am still stuck. I am now able to reconstruct the data from the bitmap data thanks to Muzak, I now want to convert that bitmap data into a byte array which I can write as a string into a XML File. (Essentially, this is to 'save' images that the user specifies).

I've modified your code and have tried to implement a Base64 encoder - but can't seem to get it to work. No matter what I try,it will always throw a "Error: #2030: End of File was encountered" exception

It doesn't have to be base 64 encoded, or encoded at all - I just would like to be able to write an image out as a string and reimport it. Anyone have any idea how I can accomplish this? For the moment I am just trying to write to a string and decode.

Code

import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Bitmap;
import flash.display.BitmapData;
import com.dynamicflash.util.Base64;


var loader:Loader;
var req:URLRequest;
var orig_mc:MovieClip;
var copy_mc:MovieClip;


function loaderCompleteHandler(evt:Event) {
    //swap data
    var ldr:Loader = evt.currentTarget.loader as Loader;
    var origImg:Bitmap = (ldr.content as Bitmap);
    var origBmd:BitmapData = origImg.bitmapData;
    trace(origImg.bitmapData);
    trace(origImg.width);
    trace(origImg.height);


    //Convert image byteData into Base64 String
    var byteArray:ByteArray = new ByteArray();
    byteArray.writeObject(origBmd);
    var encoded:String = Base64.encodeByteArray(byteArray);
    trace("\nENCODED:\n" + encoded);
    var decoded:ByteArray = Base64.decodeToByteArray(encoded);
    trace("\nDECODED:\n" + decoded.toString());


    // convert base64 string back into movieclip
    var newBmd:BitmapData = new BitmapData(origImg.width,origImg.height,"true",0xFFFFFFFF);
    newBmd.setPixels(origBmd.rect, decoded)
;// THIS THROWS AN " Error #2030: End of file was encountered."
    var image:Bitmap = new Bitmap(newBmd, "auto", true);
    copy_mc.addChild(image);
    copy_mc.x = origImg.width;
}


loader = new Loader();
req = new URLRequest("C:\\Data\\cutcord.jpg");
loader.load(req);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);
// movieclip to display original image
orig_mc = new MovieClip();
orig_mc.addChild(loader);
addChild(orig_mc);
// movieclip to display image copy
copy_mc = new MovieClip();
addChild(copy_mc);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jul 03, 2009 Jul 03, 2009

Copy link to clipboard

Copied

Here's one way to do that.

I've broken it up into 2 parts. One part is loading the original image (to create ByteArray from).

Second part (loadImageData()) is using the Base64 encoded ByteArray and convert it back to an image and display it.

import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Bitmap;
import com.dynamicflash.util.Base64;
import flash.display.BitmapData
import flash.geom.Rectangle;

var loader:Loader;
var req:URLRequest;
var orig_mc:MovieClip;
var copy_mc:MovieClip;

var imgWidth:int;
var imgHeight:int;
var b64Img:String;

function loaderCompleteHandler(evt:Event):void {
trace("Application ::: loaderCompleteHandler");
var ldr:Loader = evt.currentTarget.loader as Loader;
var origImg:Bitmap = (ldr.content as Bitmap);
imgWidth = origImg.width;
imgHeight = origImg.height;
var origBmd:BitmapData = origImg.bitmapData;

var rect:Rectangle = new Rectangle(0,0,origImg.width, origImg.height);
var ba:ByteArray = origBmd.getPixels(rect);
trace("    - bytearray length: ", ba.length);
// Base64 encode - this is what gets stored (in xml or whatever)
b64Img = Base64.encodeByteArray(ba);
//trace("b64Img: ", b64Img);
// now (pretend) to load the data
loadImageData();
}

function loadImageData():void {
trace("Application: loadImageData");
// use b64Img as if it was loaded from xml
// decode Base64 string to ByteArray
var ba:ByteArray = Base64.decodeToByteArray(b64Img);
trace("    - bytearray length: ", ba.length);
// create Rectangle, same size as original
var rect:Rectangle = new Rectangle(0, 0, imgWidth, imgHeight);
// crate BitmapData and throw bytearry at it
var bmd:BitmapData = new BitmapData(imgWidth,imgHeight, false, 0x00000000);
bmd.setPixels(rect, ba);
// create (smooth) bitmap from data
var bm:Bitmap = new Bitmap(bmd, "auto", true);
// display bitmap in movieclip
copy_mc.addChild(bm);
copy_mc.x = imgWidth + 10;
}

loader = new Loader();
req = new URLRequest("2.jpg");
loader.load(req);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);

orig_mc = new MovieClip();
orig_mc.addChild(loader);
addChild(orig_mc);

copy_mc = new MovieClip();
addChild(copy_mc);

Note that for this to work you'll have to save the original image width and height (in your xml) along with the Base64 encoded data.

Another way to do the same would be to use PNGEncoder or JPGEncoder to encode the original bitmapdata.

They're both part of the Flex SDK: http://livedocs.adobe.com/flex/3/langref/mx/graphics/codec/package-detail.html

But also available in the AS3CoreLib: http://code.google.com/p/as3corelib/

http://code.google.com/p/as3corelib/downloads/list

With JPGEncoder/PNGEncoder you'd grab the bitmapdata and convert it to a png or jpg (as ByteArray) and encode that to Base64.

The difference here would be that you'd get *real* image data that other languages can understand as well. So you could display the image using PHP or whatever. The following will encode the original image BitmapData to (jpg) ByteArray.

var jpg:JPGEncoder = new JPGEncoder(80);
var ba:ByteArray = jpg.encode(origBmd);

To display the image you could then use a Loader instance, and call loadBytes()

var loader:Loader = new Loader();
loader.loadBytes(ba);
addChild(loader);

So reconstructing the image is alot easier as well (no need for the original image width or height).

Hope this helps

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jul 03, 2009 Jul 03, 2009

Copy link to clipboard

Copied

Ok, so I went ahead and created a sample using JPGEncoder (from AS3CoreLib).

It's similar to what I posted earlier but requires less code.

import com.adobe.images.JPGEncoder;
import com.dynamicflash.util.Base64;

import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Bitmap;
import flash.display.BitmapData
import flash.geom.Rectangle;

var loader:Loader;
var req:URLRequest;

var b64Img:String;

function loaderCompleteHandler(evt:Event):void {
trace("Application ::: loaderCompleteHandler");
var ldr:Loader = evt.currentTarget.loader as Loader;
var origImg:Bitmap = (ldr.content as Bitmap);
var origBmd:BitmapData = origImg.bitmapData;

var jpg:JPGEncoder = new JPGEncoder(80);
var ba:ByteArray = jpg.encode(origBmd);
trace("    - bytearray length: ", ba.length);
// Base64 encode - this is what gets stored (in xml or whatever)
b64Img = Base64.encodeByteArray(ba);
//trace("b64Img: ", b64Img);
// now (pretend) to load the data
loadImageData();
}

function loadImageData():void {
trace("Application: loadImageData");
// use b64Img as if it was loaded from xml
// decode Base64 string to ByteArray
var ba:ByteArray = Base64.decodeToByteArray(b64Img);
trace("    - bytearray length: ", ba.length);
// use Loader to load image data
var baLoader:Loader = new Loader();
baLoader.loadBytes(ba);
// add loader to display list
addChild(baLoader);
baLoader.x = 210;
}

loader = new Loader();
req = new URLRequest("2.jpg");
loader.load(req);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);

addChild(loader);

So again, the main difference here is that a *real* jpg image (as ByteArray) is stored in the Base64 string, which makes it alot easier to work with, as you can now just use a Loader instance to display it (Loader.loadBytes(ba)).

I'd actually recommend this approach rather than the one I posted earlier.

Grab the AS3CoreLib here: http://code.google.com/p/as3corelib/downloads/list

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 09, 2009 Jul 09, 2009

Copy link to clipboard

Copied

LATEST

Thankyou very much! That was a great help and is much appreciated believe me!

Looks like i was reading in the byteArray the wrong way.

I've got my program all up and running and working fine. The only problem at this point is that it will crash if there are to many JPG strings in the XML (seems random, but about 7 100kb images seems to break it). Any idea how much characters/data the XML string should be able to hold?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines