Transform BitmapData into JPEGs (AS3, JPGEncoder, Rails, Rmagick)
By Cary Dunn / October 13, 2008
Do you ever have nightmares where you are back in the Actionscript 2 days and trying to save BitmapData to a JPEG? ... ok, so maybe its just me, but who cares because it's easy now!
Old news...
ByteArray rocks! If you aren't familiar, it was introduced in AS3 for playing with binary data and has endless uses. Compression being the most obvious, but speed, custom protocols, and streaming data are no less important. zlib and deflate support are built in as well.
Capturing BitmapData, encoding it as a JPG, and saving it through Rails...
Step 1. We need to download the as3corelib. The library we will be using from this package is com.adobe.images.JPGEncoder (a port of this C algorithm), but look around! There are some awesome libraries in here.
Some imports...
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.ByteArray;
import com.adobe.images.JPGEncoder;
import flash.events.*;
import flash.net.*;
Capture BitmapData, encode as a JPG, convert to ByteArray, send to Rails
// Capture the BitmapData of the stage for example
var stage_snapshot:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
stage_snapshot.draw(stage);
// Setup the JPGEncoder, run the algorithm on the BitmapData, and retrieve the ByteArray
var encoded_jpg:JPGEncoder = new JPGEncoder(100);
var jpg_binary:ByteArray = encoded_jpg.encode(stage_snapshot);
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "application/octet-stream");
var request:URLRequest = new URLRequest("/generate_jpg");
request.requestHeaders.push(header);
request.method = URLRequestMethod.POST;
request.data = jpg_binary;
var loader:URLLoader = new URLLoader();
loader.load(request);
Rails n' RMagick...
// Example RMagick usage...
image = Magick::Image.from_blob(request.body.read).first
image.write("#{RAILS_ROOT}/public/jpgs_from_as/test.jpg")
Why it rocks...
Well, just think about what you would have to do without it?
Data transfer- 800x600 sized image...480000 pixels...*~4 (RGBA)...~2Megs? For a ~80kb compressed jpg? No dice.
Data processing - calculating this per pixel color array makes your machine sound like a lawnmower...
I suppose I'll miss dealing with color palettes and encoding pixel data...NOT!
Comments
What language were you thinking of using to output the JPG?
You could make the request to a PHP script with somethink like the following...
$jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
header('Content-Type: image/jpeg');
header("Content-Disposition: attachment; filename=".$_GET['filename']);
echo $jpg;
Where $_GET['filename'] comes from the get paramters of the request.
Does that help?
The PHP code that Cary Dunn provides above works fine, with some modification for saving it to a file.
<?
/*
*** THIS CODE IS UNSAFE FOR PRODUCTION ***
This code does absolutely no error checking on the validity of the
expected jpg file coming through. It should be checking that the data
coming in is in fact a valid JPEG file of appropriate dimensions.
*/
$jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
$filename = 'uploads/'.date('r').'.jpg';
file_put_contents($filename, $jpg);
echo "saved to ".$filename;
?>
SORRY, I'M A BIT OF A NEWBIE WHEN IT COMES TO THIS STUFF. YOU WOULD NEED TO CHANGE THE URLREQUEST IN THE FLASH FILE TO RUN THIS PHP SCRIPT, WOULDN'T YOU? AND, IS USING A "LOADER" THE BEST METHOD? OR, WOULD YOU JUST USE "SENDTOURL?"


GREAT TUTORIAL!! i wanted to say thank you for that. i have another problem. how can i specify where to store the encoded JPG without using rails