Adobe Flex: Export As A PNG Image
DiggBlinkRedditDeliciousTechnorati
article by Srirangan
So this week I had this task, to add a "Save As Image" component to an existing Flex based application. I figure this is the sort of feature many will find useful, so I take the opportunity to share the code samples with all.
This is a tutorial which assumes you understand the basics of Flex, XML and DOMs. Below are the bare code samples, hope you can make sense of them and implement productively.
public function writeChunk(png:ByteArray, type:uint, data:ByteArray):void
{
if (!crcTableComputed)
{
crcTableComputed = true;
crcTable = [];
var c:uint;
for (var n:uint = 0; n < 256; n++)
{
c = n;
for (var k:uint = 0; k < 8; k++)
{
if (c & 1)
{
c = uint(uint(0xedb88320) ^
uint(c >>> 1));
} else
{
c = uint(c >>> 1);
}
}
crcTable[n] = c;
}
}
var len:uint = 0;
if (data != null)
{
len = data.length;
}
png.writeUnsignedInt(len);
var p:uint = png.position;
png.writeUnsignedInt(type);
if ( data != null )
{
png.writeBytes(data);
}
var e:uint = png.position;
png.position = p;
c = 0xffffffff;
for (var i:int = 0; i < (e-p); i++)
{
c = uint(crcTable[
(c ^ png.readUnsignedByte()) &
uint(0xff)] ^ uint(c >>> 8));
}
c = uint(c^uint(0xffffffff));
png.position = e;
png.writeUnsignedInt(c);
}
public function encode(img:BitmapData):ByteArray
{
// Create output byte array
var png:ByteArray = new ByteArray();
// Write PNG signature
png.writeUnsignedInt(0x89504e47);
png.writeUnsignedInt(0x0D0A1A0A);
// Build IHDR chunk
var IHDR:ByteArray = new ByteArray();
IHDR.writeInt(img.width);
IHDR.writeInt(img.height + 20);
IHDR.writeUnsignedInt(0x08060000);
// 32bit RGBA
IHDR.writeByte(0);
writeChunk(png,0x49484452,IHDR);
// Build IDAT chunk
var IDAT:ByteArray= new ByteArray();
for(var i:int=0;i < img.height;i++)
{
// no filter
IDAT.writeByte(0);
var p:uint;
var j:int;
if ( !img.transparent )
{
for(j=0;j < img.width;j++)
{
p = img.getPixel(j,i);
IDAT.writeUnsignedInt(uint(((p&0xFFFFFF) << 8)|0xFF));
}
} else
{
for(j=0;j < img.width;j++)
{
p = img.getPixel32(j,i);
IDAT.writeUnsignedInt(uint(((p&0xFFFFFF) << 8)|(p>>>24)));
}
}
}
IDAT.compress();
writeChunk(png,0x49444154,IDAT);
// Build IEND chunk
writeChunk(png,0x49454E44,null);
// return PNG
return png;
}
public function downloadChart():void
{
var bd:BitmapData = new BitmapData(OBJECT_ID.width, OBJECT_ID.height);
bd.draw(OBJECT_ID);
var png:ByteArray = encode( bd );
var variables:URLVariables = new URLVariables();
variables.uid = "156";
variables.item_name = "Chart";
var request:URLRequest = new URLRequest( "DownloadImage.php" );
request.data = png;
request.method = URLRequestMethod.POST;
navigateToURL( request );
}
DownloadImage.php
<?php
header('Content-disposition: attachment; filename=myImage.png');
header("Content-type: application/png");
readfile('php://input');
?>
Set the paths and IDs right and the code should work intuitively. No real documentation required - we use Bitmap Arrays and chunk it down into PNG ByteStreams. Using a PHP server side script to make download available.
Some of the code borrowed from open sources.