Problem Summary
Saving images from AIR application in SWF format.
Solution Summary
Encode BitmapData to PNG or JPEG file, and load it to Loader using loadBytes method. After loading is completed you can pull out SWF data using bytes property of LoaderInfo class. This method works only in AIR applications.
Explanation
In AIR applications images loaded with Loader class are internally stored as a single frame, not compressed SWF file. As far as I know, this isn't documented anywhere, but it seems to work this way. This also fast way to convert local image file (png, jpg or gif) to swf format. We will use this method to create save local swf file from any image that is stored in BitmapData class instance.
/* create bitmap to be saved as an swf file */ var bd:BitmapData = new BitmapData(320,240); /* capture application snapshot, this can be any other object */ bd.draw( Application.application as IBitmapDrawable );
When we have already created bitmap image we need to encode it to PNG or JPEG virtual file. Virtual means it will be stored in memory using ByteArray class. In example below we use mx.graphics.codec.PNGEncoder, to create virtual png file.
/* create virtual png file */ var png:ByteArray = ( new PNGEncoder() ).encode( bd );
Last step is to use Loader class to load image. To load virtual png image stored in as instance of ByteArray class we must use loadBytes method. Listener function saveContentToSWF will be executed when load completes.
/* load virtual png image */ var l:Loader = new Loader(); l.contentLoaderInfo.addEventListener( Event.COMPLETE, saveContentToSWF ); l.loadBytes( png );
When event is dispatched, our image is already converted to SWF file. Bytes stored in Loader class can be accessed with contentLoaderInfo.bytes property. To create and save local file we use File and FileStream classes. Lets put this all together now.
function saveContentToSWF( event : Event ):void { /* create output file on desktop */ var file:File = File.desktopDirectory.resolvePath('out.swf'); var fs:FileStream = new FileStream(); fs.open( file, FileMode.WRITE ); /* pull out SWF bytes from Loader */ fs.writeBytes( (evt.target as LoaderInfo).bytes ); fs.close(); }
This method we will create local uncompressed SWF file. To decrease size we can also create compressed SWF file. To do this we must copy 8 byte header from uncompressed one. To indicate that file is compressed we must set first byte to value 0x43 (ascii code of letter 'C'). Entire file after first 8 bytes can be then compressed using compress method of ByteArray class. Puting this together we get new listener function, that creates compressed SWF files.
function saveContentToSWF_compress( event : Event ):void { var file:File = File.desktopDirectory.resolvePath('out_c.swf'); var fs:FileStream = new FileStream(); fs.open( file, FileMode.WRITE ); /* compressed file header */ var swf_head : ByteArray = new ByteArray(); swf_head.endian = Endian.LITTLE_ENDIAN; swf_head.writeBytes( (evt.target as LoaderInfo).bytes, 0, 8 ); swf_head[0] = 0x43; // 'C' letter, indicates that file is compressed swf_head.position = 0; /* compressed file body */ var swf_body : ByteArray = new ByteArray(); swf_body.endian = Endian.LITTLE_ENDIAN; swf_body.writeBytes( (evt.target as LoaderInfo).bytes, 8 ); swf_body.position = 0; swf_body.compress(); swf_body.position = 0; /* write it down to file */ fs.writeBytes( swf_head ); fs.writeBytes( swf_body ); fs.close(); };
Example code using this technique is attached. Example application saves two SWF files compressed and uncompressed on users desktop.
Related files for download
save file, save image, save swf, swf, AIR, jpg, png
save_swf.zip