Tuesday, June 9, 2009

Caching Images to Disk with AIR

In an application I'm currently working on, I create images within the application and want to store them to load later. Because I store the image data in a model object that might be used many places in the running application, I keep the data in memory as a BitmapData object. This turned out to be a problem because you can't write BitmapData objects to disk. Instead you have to write the data to a PNG or JPEG and then save the byte array from that object, and reverse the process to load the data. There may be another way but this is the only solution I could find. Here is my class:

package com.effectiveui.models.widget
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.utils.ByteArray;
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.utils.IExternalizable;

import mx.graphics.codec.PNGEncoder;

[RemoteClass(name="com.effectiveui.models.widget.WidgetCategoryDataModel")]
public class WidgetCategoryDataModel implements IExternalizable
{
public var imageData:BitmapData;

protected var loader:Loader;

public function WidgetCategoryDataModel(){
loader = new Loader();
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE, handleBytesLoaded);
}

public function handleBytesLoaded(event:Event):void{
imageData = Bitmap(loader.content).bitmapData;
}

public function writeExternal(out:IDataOutput):void{
var encoder:PNGEncoder = new PNGEncoder();
var bytes:ByteArray = encoder.encode(imageData);
bytes.position = 0; // may not be necessary
out.writeDouble(bytes.length);
out.writeBytes(bytes);
}

public function readExternal(input:IDataInput):void{
var length:Number = input.readDouble();
var pngData:ByteArray = new ByteArray();
input.readBytes(pngData,0,length);

loader.loadBytes(pngData);
}
}
}

You can download the class here.

0 comments: