Using AMF as a file format

Flash is a great platform. You can build applications for the browser, the desktop, and… well, what else is there? When building applications, especially those with a document-based model such as the Aviary apps, Odosketch, My Canvas, ZenStudio, the apps on acrobat.com, and many others, you need a file format for the document or project. Or some way to save it.

What Not To Do

You don’t want to save each item into a table in the database. I know a guy…who had a dream…that his friend did this. This guy’s friend in his dream had a table for each item that needed to be stored with foreign keys etc. When a project needed to be loaded, the server-side script did a ton of queries and created a sometimes-quite-large XML structure that it then sent to the Flash app. When saving, this XML was sent back and parsed back into the database with INSERTS and UPDATES. That does not scale, and none of that data was needed to be pulled up in reports or anything that you might consider useful and require a database for. It was complex, hard to add features, and slow. That is, it would have been had that guy’s dream friend been real.

Warmer, warmer

Saving document/project files to disk is the way to go. You can store metadata about each project or document in a database if you are storing them server-side. If it is an AIR app, give it a unique extension and the user can double-click on the file to open it. If you are AIR only, you can save your file as a SQLite database file. Pretty sweet option, but doesn’t work for the browser ’cause Flash can’t do that. The format could be XML like OpenOffice documents and the new MS Office formats. You would need to parse the files in and out and they could get very large, so you’d want to compress them anyway.

Hot,

Need: it with try. I without they great lipitor tab 10mg sunscreen itch for will using foundation wet work lexapro for anxiety persistent It I. Since seen product generic lexapro serum. It more! 10 was the that what is nexium 40 mg used for buying getting and this it. Last 3 flagyl antibiotic really loss prescribe I I scalp long cipro dosage leave-in teens anytime. Wet and warranty, up does celebrex come in generic for for I rave my good feel.

burning, you’re on fire!

So, XML might be the most portable format, but hey, that’s what Import/Export dialogs are for, right? We’re talking about Save/Save As… :) Enter our new contender, AMF! AMF isn’t really new, however I haven’t heard of many people using it as their file format. The cool thing about using AMF is that after you’ve prepared your objects for it, you could store (in player 10) pieces of your document on the clipboard for copy/paste from one place to another (even after a page refresh or from AIR to browser!). You can do an auto-save of a document or page to the user’s SharedObject store.

Preparation and implementation

To use AMF as the format for you data you’ll need to prepare your objects sufficiently. Here are a few rules:

  • No required parameters in your constructors. When AMF unserializes it has to create those objects and assign the public properties to it. You’ll get errors otherwise.
  • Register your classes using flash.net.registerClassAlias or [RemoteClass(alias=”…”)]. This will store the registered alias name to map a class to a string for serializing and unserializing.
  • Use IExternalizable for more complex items that only need a few properties stored, or for Flash classes that can’t be stored (e.g. BitmapData). This allows you to get around the constructor parameter issue, but it is more work. :)
  • Make sure any data you need stored is a public getter/setter or you’ll have to use IExternalizable. AMF serialization will only store data that is public and read/write. If you think about it, it makes sense.

The way to store your document object or project object (or page, or widget, or whatever) to AMF depends on where you are storing it. There are a lot of Flash APIs that use AMF already. If you are storing it to SharedObject, just assign the item to the data property or one of its properties.

SharedObject.getLocal(“_myProject”).data.project1 = myProject;

To send it from one app to another over LocalConection is just as easy.

var conn:LocalConnection = new LocalConnection(); conn.send("_connName", "passProject", myProject); 

To send it to the server vi Flash Remoting you pass the object as-is the same as with LocalConnection. If you want to save the project to disk or pass it to the server in a RESTful manner or as a file upload, you’ll need to serialize it to AMF first. But that is pretty easy. Just remember to compress after you write it and uncompress before you read. This will save a lot of room.

var byteArray:ByteArray = new ByteArray(); byteArray.writeObject(myProject); byteArray.compress(); // write the bytearray to file or send to server // or we can pull it back out making a clone! (save as...) byteArray.position = 0; myProject = byteArray.readObject(); 

Easy cheesy. I will leave it as an exercise to the reader to figure out how to store it to the clipboard for copy/paste. XML might be an easier format, though more verbose and prone to errors in the creation and parsing. Though it could allow for greater flexibility and accessibility to other programs to read the file. Let me know if you use AMF for your document/project file storage. I’d be interested to hear how many people use this method and how well it has worked out for you.

Response Pattern in ActionScript 3

Earlier I posted about the Response Pattern. Today I wanted to show an ActionScript implementation and how it would be used. The API I decided to go with for this pattern uses method chaining. This is one of those things where people love it or they despise it. I’m sorry if you are one of the latter. Method chaining is where an object returns a reference to itself as the result of its methods. This allows you to call many methods on the object in one line. jQuery uses this and it is used a lot in the Zend Framework. As example you might have a drawing API helper that does this:

 shape.fill(0x660000).rect(0, 0, 100, 100).fill(0x990000).rect(1, 1, 98, 98); 

This would draw a red box with a darker red border around it, all in one line. If the above code gives you tingles in your stomach, you’ll like response. If it upsets you, you can still use response with one method per line of code. You can see in the interface IResponse that it has method chaining and supports a bindable progress property as well. The Response implementation has a few more methods that are useful when first creating a response. It allows events to trigger the complete cycle (which runs through the result handlers and calls them) or the error cycle. It also will create a flash.net.Responder object that can be used in NetConnection calls or other situations that take a native responder object. There are also some more advanced uses of Response which we might talk about another time. But let’s see it in action! I’ve posted my library of code I reuse on Google Code under the MIT license. Here you’ll find a class called ImageLibrary. Here is how it works.

 // MySprite which extends Sprite public function addImage(url:String):void { var bitmap:Bitmap = new Bitmap(); addChild(bitmap); ImageLibrary.getInstance().getImage(url).handle(addDataToBitmap, bitmap); } private function addDataToBitmap(data:Object, bitmap:Bitmap):void { if (data is BitmapData) { bitmap.bitmapData = data as BitmapData; } } 

In this example, we have a result handler that sets the BitmapData object to the bitmap object. We could have created and added the bitmap to the Sprite in the handler, but I wanted to show how you can pass extra parameters to the handlers in the handle(resultHandler:Function, ...rest) method. Another thing to note, is that if we were to add the same image to our MySprite class again, addDataToBitmap would be called instantly because ImageLibrary caches the results of previous calls so that the player won’t have to load them from the server again. This results in virtualized lists having the images instantaneously showing up after the first load. The RemoteProxy class is a Flash remoting service which is extremely small. It uses Response.

 public function loadContacts():IResponse { var service:RemoteProxy = new RemoteProxy(gateway); // call the list operation and then handle the results with setContacts // and handle errors with errorLoading return service.contacts.list().handle(setContacts).handleError(errorLoading); } public function setContacts(contacts:Array):void { _contacts = contacts; } protected function errorLoading(error:Error):void { Logging.log("Error loading contacts: " + error.toString()); } 

In this example we pass the Response object along so that whoever is calling loadContacts can know when the result is ready or if there was an error. Here is a list of some of the classes I’ve made which use Response:

This is just a little taste of using the Response Pattern. I have found it much nicer to use when you are waiting for the results of a particular call. Event listeners are still useful

online viagracanada pharmacyhow long does it cialis take to kick incanadian mail order pharmacycialis generichttp://pharmacycanadian-onlinein.com/http://viagracanadian-online.com/

for user input and for socket-based libraries such as XMPP or FMS, but I like Response for most other async operations.

High quality, high performance thumbnails in Flash

Ever need a thumbnail of an image in Flash? I do, and honestly speaking, the resampling that Flash does is less than ideal. Unless you only need to resize by half or bigger. But my thumbnails usually need to be smaller.

I searched for a solution and found on voq.com a promising library with some algorithms that worked quite nicely and a demo. The quality was nice, but the speed was slow. It also fiddled with the color a little bit. If I put the “easyScaling” parameter down from .5 to .25 I ended up with a nicer thumbnail but was slower to make and had more color disfiguration. You could tell what the original piece was better though.

After some more searching I found that Brooks Andrus played with some algorithms using Pixel Bender. The conclusion to that was he found he could do the same thing with the “smoothing” option in the BitmapData.draw() method. And this still leaves me with yucky thumbnails at small sizes.

I began thinking I would need to take the algorithms from the first source and port them into pixel bender like Brooks did for his ThumbGenie application.

I thought I’d try one more option first. I had played around in my mind with the idea of resizing a bitmap in half, then in half again, until I reached my destination size, since resizing by half still had good results. After discussing it with Tyler I tried it out and ended up with some great results. That last resize to get to the final thumbnail size wasn’t half because in an imperfect world your thumbnails aren’t always a power of two times smaller than your original. So I had an odd-man-out scale at the end I was applying. Tyler suggested I put that odd-man-out scale at the first instead. So instead of:

1000x750 * .5 resize * .5 resize * .5 resize * .8 = 100x75

It worked like this:

1000x750 * .8 resize * .5 resize * .5 resize * .5 = 100x75

Doing it that way landed me with even better results! It seems that Flash does it’s best work when resizing by exactly 1/2.

Thumbnail tests

The above image shows my test results as follows taking a snapshot of my homepage in an HTMLLoader in AIR.

  1. Regular BitmapData.draw() method without smoothing (0 miliseconds)
  2. Regular BitmapData.draw() method with smoothing (1 miliseconds)
  3. Using my own method that resizes by the odd scale first, then by halves (8 milliseconds)
  4. Using my method but after the odd scale, only scaling down by quarters (33 miliseconds)
  5. Using the voq Lanczos3 method with easyScaling at .25 and sharpening (694 miliseconds)
  6. Using the voq Lanczos3 method with easyScaling at .25 and no sharping (676 miliseconds)
  7. Using the voq Triangle method with easyScaling at .25 and sharpening (275 miliseconds)
  8. Using the voq Triangle method with easyScaling at .25 and no sharpening (266 miliseconds)

My personal opinion is that the best looking thumb is #3. I was surprised that #4 wouldn’t be as good. I knew the performance would be lower because I was doing more iterations of BitmapData.draw(), but I thought that scaling it to 75% (down a quarter) each time would end up nicer. Looks like 50% is the best scale to use.

The voq.com algos looked pretty decent, but obviously were slow. I’m quite happy with the solution I’ve found. I only had to write a little bit of code, it’s fast enough, and looks better than any other solution I’ve found (even Fireworks resizing IMO).

Here is the method I wrote for this. Note, when scaling up, it seemed to look better to just use smoothing and do it in one draw() and not iterations of 2.

private static const IDEAL_RESIZE_PERCENT:Number = .5;

public static function resizeImage(source:BitmapData, width:uint, height:uint, constrainProportions:Boolean = true):BitmapData
{
	var scaleX:Number = width/source.width;
	var scaleY:Number = height/source.height;
	if (constrainProportions) {
		if (scaleX > scaleY) scaleX = scaleY;
		else scaleY = scaleX;
	}

	var bitmapData:BitmapData = source;

	if (scaleX >= 1 && scaleY >= 1) {
		bitmapData = new BitmapData(Math.ceil(source.width*scaleX), Math.ceil(source.height*scaleY), true, 0);
		bitmapData.draw(source, new Matrix(scaleX, 0, 0, scaleY), null, null, null, true);
		return bitmapData;
	}

	// scale it by the IDEAL for best quality
	var nextScaleX:Number = scaleX;
	var nextScaleY:Number = scaleY;
	while (nextScaleX < 1) nextScaleX /= IDEAL_RESIZE_PERCENT;
	while (nextScaleY < 1) nextScaleY /= IDEAL_RESIZE_PERCENT;

	if (scaleX < IDEAL_RESIZE_PERCENT) nextScaleX *= IDEAL_RESIZE_PERCENT;
	if (scaleY < IDEAL_RESIZE_PERCENT) nextScaleY *= IDEAL_RESIZE_PERCENT;

	var temp:BitmapData = new BitmapData(bitmapData.width*nextScaleX, bitmapData.height*nextScaleY, true, 0);
	temp.draw(bitmapData, new Matrix(nextScaleX, 0, 0, nextScaleY), null, null, null, true);
	bitmapData = temp;

	nextScaleX *= IDEAL_RESIZE_PERCENT;
	nextScaleY *= IDEAL_RESIZE_PERCENT;

	while (nextScaleX >= scaleX || nextScaleY >= scaleY) {
		var actualScaleX:Number = nextScaleX >= scaleX ? IDEAL_RESIZE_PERCENT : 1;
		var actualScaleY:Number = nextScaleY >= scaleY ? IDEAL_RESIZE_PERCENT : 1;
		temp = new BitmapData(bitmapData.width*actualScaleX, bitmapData.height*actualScaleY, true, 0);
		temp.draw(bitmapData, new Matrix(actualScaleX, 0, 0, actualScaleY), null, null, null, true);
		bitmapData.dispose();
		nextScaleX *= IDEAL_RESIZE_PERCENT;
		nextScaleY *= IDEAL_RESIZE_PERCENT;
		bitmapData = temp;
	}

	return bitmapData;
}

Enjoy!

Update: I was getting unsatisfactory images when the resize scale was more than 50%. For example, the original code posted would size an image from 100×100 to 60×60 using one BitmapData.draw() step. And it didn’t look that great.

I found that if I sized the image up to a scale that allowed it to be size back down by exactly 50% that the results were much better. In the above example, the 100×100 would scale up by 120% to 120×120, then scale down 50% to 60×60. The final image looks much better this way. The code has been updated to work like this. It also had the option to turn constrain proportions off.

Update: I’ve posted my code library to Google Code. You can see my final implementation of bitmap resizing in the ImageUtils class.

Overriding Flash’s Transform and Matrix

I’m building a a commercial library for scrap-book or other composition type applications and it would be useful to be able to override the flash.geom.Transform and flash.geom.Matrix classes with my own. So I played around with it for awhile and thought I’d share what I found.

First I tried setting my own matrix. I know that when you access displayObject.transform.matrix you get a clone of the object’s transform matrix, so I create a test class called MyMatrix.

public class MyMatrix extends Matrix
{
	public function MyMatrix(a:Number=1, b:Number=0, c:Number=0, d:Number=1, tx:Number=0, ty:Number=0)
	{
		super(a, b, c, d, tx, ty);
	}
	
	public override function clone():Matrix
	{
		trace("cloned");
		return new MyMatrix(a, b, c, d, tx, ty);
	}
}

Then tested it out:

var sprite:Sprite = new Sprite();
sprite.transform.matrix = new MyMatrix();
var m:Matrix = sprite.transform.matrix; // will I get a trace of "cloned"?
trace(m is MyMatrix); // true? or false?

Turns out I don’t get any trace statement when accessing matrix and “m is MyMatrix” gives me a false. Bummer. So I did the same thing with Transform, making a MyTransform class and setting it onto a sprite. Same results. Flash doesn’t really set and keep around my own transform or matrix classes. It seems to use their values and discard the objects. I’m sure it has to do with how the display list is implemented under the hood.

However, I did discover that to affect the display object your transform class doesn’t need to be assigned to it. Here is an example:

var sprite:Sprite = new Sprite()
var t:MyTransform = new MyTransform(sprite); // Transform takes a displayObject as it's one and only parameter
t.matrix = new Matrix(2, 0, 0, 2, 100, 100); // scale it up 2ce and set x/y to 100

trace(sprite.transform.matrix); // (2, 0, 0, 2, 100, 100)

I was able to set the matrix with my own transform class from outside the display object. Side note: speaking with Tyler about transform requiring a display object, he’s convinced this is the only reason you can’t serialize display objects to a bytearray. It throws an error when constructors require parameters, and Transform requires this one parameter. Might be useful to serialize display objects, maybe the Flash team could make the parameter optional! And have the display object set it when it is added as the transform.

So my two options are now:

  1. Use my own Transform class externally as explained above. I could keep a dictionary of transform objects to the data that I needed.
  2. Subclass Sprite, Shape, Bitmap, etc. and have it store the transform object of my choice.

I’ll probably go with option two. Maybe I’ll even be able to make a display object serializable with some trickery? Ooh, I gotta go try that! Catcha later.

ActionScript 3 Wildcard Setters

All credit goes to Tyler for this trick, but I’m sure I would have thought of it too. :)

Tyler has been working on an XML specification, what he things Adobe should have done in place of FXG which is a standard that was built around implementation with Flex. During this process he has also done tests from time to time to see how it might actually pan out using Flex builder, and we’re pretty confident it could all be done there. One of the issues is this new standard should support shortcuts. An example in the XML is:

<group>
    <layout padding="10px 10px 10px 50%"/>
</group>
<group transform="rotate(30)"></group>

(note: this xml is not necessarily from the actual specification)

This is impossible with current Flex implementations if you want your properties typed to their type. For example, the padding property may be an Bounds object with top, left, right, and bottom properties of type Length which could be a hard value or a percent.

What he found though was that you can have wildcard setters with your strictly typed getters. This allows you to set anything to the property, but when you get it you expect the proper type (and get compile-time errors, autocomplete, etc.). This allows us to take a string of “10px 10px 10px 50%” or “rotate(30)” and parse it into the proper type.

public function get padding():Bounds
{
    return _padding;
}
public function set padding(value:*):void
{
    if ( !(value is Bounds) ) {
        // convert it to a Bounds object
        value = ValueUtils.parseBounds(value);
    }

    if (value.equals(_padding)) {
        return;
    }

    _padding = value;
    dispatchEvent(new Event("paddingChanged"));
}

This will allow the XML specification to continue being defined without regards to the Flex compiler and we can also feel confident that it will still work with Flex. Now we can have our cake and eat it too!

This may also be a cool trick in other scenarios than just MXML. But think of all the shortcuts you wished you could do and how this makes it possible while still keeping good standards and typing your variables.

Flight Framework Highlights

The Flight Framework is basically a collection of great utilities and independent tidbits that are organized to help us build our application. So I thought I’d make a call out to all the great standalone features in Flight, tell what they are, and leave it to another day to go more in depth on them.

  1. Fix for abstract classes
    The tiny static classes in the flight.error package allow you to ensure an abstract class is not instantiated and that abstract methods are overriden.
  2. Registry
    A global registry to store objects or data that anything in an application can have access too.
  3. Reflection
    The “Type” class handles all your reflection needs, including caching the expensive describeType calls and helping pull out needed metadata.
  4. Nice base for models
    The ValueObject class is a lazy IEventDispatcher that implements an equals() and clone() method which will work with all subclasses.
  5. ValueObjectEditor
    This nifty utility lets you “edit” a ValueObject and then either commit the changes or revert them. Great for dialogs that let ValueObjects be changed but can then either Cancel or Ok the change.
  6. AS3 ArrayContainer
    When working in an AS3 project, it would be nice to know when an array is changed, but Flex’s ArrayCollection brings in half the framework when referenced. This little guy is the little brother AS3 has been wishing for.
  7. Services
    Some common services (RPC services, e.g. remoting, HTTP, etc.) that can be used in Flex or AS3. Much smaller than Flex’s built in services.
  8. Configuration
    Config lets you define your application configurations in the app, an XML file, SharedObjects, and even the URL. Not only that, you can have multiple sources with some overriding others, and it is all accessible to your classes through a global config property. Super neat!
  9. Undo framework
    With CommandHistory and all the command interfaces available, you can build undo-redo into your application without using any of the rest of Flight. Way, way awesome.
  10. Weak-referenced binding
    Using the Bind class you can create faster, smaller, and weak-referenced binds. With two-way deep binds and being able to use in AS3-only projects without importing half the Flex framework, this is my favorite nugget.

None of the above pieces references any of the others. They can all be used independently in your own frameworks or applications. That’s my favorite part about Flight, is I can use it 100% if I want to, but if I can’t that doesn’t mean I have to give up my favorite features. I could use any/all of the above with any other framework, AS3 only, or Flex.

« Previous PageNext Page »