I work on a lot of charting and data visualization applications. Flex is great for these projects, but what happens when a client wants to use a chart (or any DisplayObject) from the application in a document, presentation, website or email? I needed a way to let users save jpeg and png files to their computers without storing any images on the server. The following solution works with PHP but it should be very simple to duplicate the process for other environments. Continue reading to try it out and view code.
(Right click to view source)
Note: The image is displayed in a new browser window so you may need to allow pop-ups for this to work correctly.
How it works
-
ImageSnapshot.captureImage([DisplayObject], [resolution], [IImageEncoder])
- Encode the a DisplayObject as an image using an image encoder. Flex ships with JPEGEncoder and PNGEncoder.
-
ImageSnapshot.encodeImageAsBase64([encoded image])
- Encode the image as a Base64 string which will be posted to a script on the server.
- There's only slightly more to it, but that's the gist. Encode as Base64 in Flex, post to the server and decode to render an image.
This solution will work best with smaller images. The larger the image, the larger the string, the longer the wait. I favor this approach for its simplicity - not its efficiency.
PHP Receives the Data & Generates an Image
-
<?php
-
# Posted variables
-
#
-
$string = $_POST['encoded'];
-
$type = $_POST['type'];
-
-
# Fix for IE which does not handle variables
-
# posted from Flash very well.
-
#
-
if (!$string) {
-
-
$string = $post_vars['encoded'];
-
$type = $post_vars['type'];
-
}
-
-
# If we got a string, decode it
-
#
-
if ($string) {
-
$im = imagecreatefromstring($data);
-
-
# If it decodes, display it
-
#
-
if ($im !== false) {
-
if ($type == 'jpeg') {
-
imagejpeg($im);
-
}
-
if ($type == 'png') {
-
imagepng($im);
-
}
-
else {
-
echo 'Unknown image type.';
-
}
-
}
-
else {
-
echo 'There was an error processing the image.';
-
}
-
} else {
-
echo 'No data was received to generate an image.';
-
}
-
?>
(Written for readability. This script could be much more condensed.)
Friendly Filenames
Notice that the URLRequest in the Flex application posts the data to a .jpeg or .png file instead of a .php file as might be expected. That file doesn't exist. I am using a RewriteRule in an .htaccess file which points requests for chart.jpeg or chart.png to the .php script above. This provides very friendly filenames like chart.jpeg which users will naturally expect.
Thanks for reading. I hope you have found this useful. If so, please let me know with a comment. Also, if you have any improvements or additional resources to add to this post please leave them below.
Hey Scot,
Another method for doing this is to encode the jpg as a ByteArray and send it to an AMF interface like AMFPHP. With that in place you can just do a file_put_contents on the server end and you're good to go. However, like you said, if simplicity on the server is what you're after, your method has legs simply because you don't need to install AMFPHP.
@Ben - That's the more efficient way of doing this. I'm actually considering trying out the method that AlivePDF uses for sending a ByteArray in POST data without using AMF. Check out their code on the PHP side:
<?php $method = $_GET['method']; $name = $_GET['name']; if ( isset ( $GLOBALS["HTTP_RAW_POST_DATA"] )) { // get bytearray $pdf = $GLOBALS["HTTP_RAW_POST_DATA"]; // add headers for download dialog-box header('Content-Type: application/pdf'); header('Content-Length: '.strlen($pdf)); header('Content-disposition:'.$method.'; filename="'.$name.'"'); echo $pdf; } else echo 'An error occured.'; ?>^ Hows that for simple? I have read of people having problems with this method when sending image data, but it may be worth a shot as well. (And check out AlivePDF if you haven't - very young but very cool). Encoding images as Base64 really just comes in handy when images need to be stored in a database. I'll update this post when I get a moment.
JPEG version worked wheras all other methods which I have been looking for the last 6 hours didnt!!! IE friendly (sort of) as well as firefox....Many Thanks!