Save Flash frame as JPG with PHP GD library
Post by efox | Date: 2008-07-26
With the "flash.display.BitmapData" class we can build wonderful web based image editing application now. BitmapData has different ways to get pixel color informations:
- getPixel(x:Number, y:Number) : Number
Returns an integer representing an RGB pixel value from a BitmapData object at a specific point (x, y).
- getPixel32(x:Number, y:Number) : Number
Returns an ARGB color value that contains alpha channel data as well as RGB data.
- getColorBoundsRect(mask:Number, color:Number, [findColor:Boolean]) : Rectangle
Determines a rectangular region that fully encloses all pixels of a given color within the bitmap image.
In this article we will focus our attention to the BitmapData.getPixel() method in order to transform a portion of flash movie into a JPEG (created with PHP GD library). In order to recreate a JPEG of a Flash frame, We can send all the pixel color values to an external application (PHP GD library).
Here is the class:
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
class foxarc.PrintScreen {
public var addListener:Function
public var broadcastMessage:Function
private var id: Number;
public var record:LoadVars;
function PrintScreen(){
AsBroadcaster.initialize( this );
}
public function print(mc:MovieClip, x:Number, y:Number, w:Number, h:Number) {
broadcastMessage("onStart", mc);
if(x == undefined) x = 0;
if(y == undefined) y = 0;
if(w == undefined) w = mc._width;
if(h == undefined) h = mc._height;
var bmp:BitmapData = new BitmapData(w, h, false);
record = new LoadVars();
record.width = w
record.height = h
record.cols = 0
record.rows = 0
var matrix = new Matrix();
matrix.translate(-x, -y)
bmp.draw(mc, matrix, new ColorTransform(), 1, new Rectangle(0, 0, w, h));
id = setInterval(copysource, 3, this, mc, bmp);
}
private function copysource(scope, movie, bit){
var pixel:Number
var str_pixel:String
scope.record["px" + scope.record.rows] = new Array();
for(var a = 0; a < bit.width; a++){
pixel = bit.getPixel(a, scope.record.rows)
str_pixel = pixel.toString(16)
if(pixel == 0xFFFFFF) str_pixel = ""; // don't send blank pixel
scope.record["px" + scope.record.rows].push(str_pixel)
}
scope.broadcastMessage("onProgress", movie, scope.record.rows, bit.height)
scope.record.rows += 1
if(scope.record.rows >= bit.height){
clearInterval(scope.id)
scope.broadcastMessage("onComplete", movie, scope.record) // completed!
bit.dispose();
}
}
}
ASBroadcaster class is useful because i will use the addListener() method to receive events (onStart, onComplete and onProgress).
The "print" method accepts params as follows :
- mc: the flash frame to copy
- x: x origin of the frame
- y: y origin of the frame
- w: width
- h: height
then the setInterval will copy all the pixels in one single row of the BitmapData object every 3 ms seconds. Every array of colors (in each row) will be stored in a new array within a LoadVar object. In this way i will have 200 variables to post with the LoadVars object.
Here is the "PrintScreen" class:
import foxarc.movieloaderWindow
import foxarc.PrintScreen
var loader:movieloaderWindow= this.createClassObject(movieloaderWindow, "loader", 10, {_x:-1000, _y:-1000})
loader.setStyle("borderColor", 0xE0E0E0)
// listener which receives the broadcast message
// from the PrintScreen class
var listener:Object = new Object();
// copy in progress...
listener.onProgress = function(target:MovieClip, loaded:Number, total:Number){
var perc = Math.round((loaded/total)*100)
loader.label = "computing... " + perc + "%"
loader.value = perc
}
// copy is complete, send the result LoadVars to PHP
listener.onComplete = function(target:MovieClip, load_var:LoadVars){
loader.label = "sending to php..."
load_var.send("files/getpixels.php", "_blank", "POST")
loader.close()
}
/**
* Print Button has been clicked
*/
function print_out(){
video_mc.pause() // first pause the playing video
pn = new PrintScreen(); // initialize the PrintScreen class
pn.addListener( listener ); // assign a listener
pn.print(_root, 0, 0, 200, 200) // copy the _root
loader.label = "computing... 0%"
loader.open(true, true, true); // open a loader
}
Once the "print" button clicked call the print_out() function.
Stop the playing video, in order to copy the current video frame.
Initialize the PrintScreen class and assign a listener which will receive all the broadcaster messages.
I used pn.print(_root, 0,0, 200, 200) in order to print all the contents in _root.
Once the process is completed send the LoadVars object, which is returned by the onComplete function, to PHP using the POST method )
Here is the code of the "getpixels.php" page
<?php
error_reporting(0);
/**
* Get the width and height of the destination image
* from the POST variables and convert them into
* integer values
*/
$w = (int)$_POST['width'];
$h = (int)$_POST['height'];
// create the image with desired width and height
$img = imagecreatetruecolor($w, $h);
// now fill the image with blank color
// do you remember i wont pass the 0xFFFFFF pixels
// from flash?
imagefill($img, 0, 0, 0xFFFFFF);
$rows = 0;
$cols = 0;
// now process every POST variable which
// contains a pixel color
for($rows = 0; $rows < $h; $rows++){
// convert the string into an array of n elements
$c_row = explode(",", $_POST['px' . $rows]);
for($cols = 0; $cols < $w; $cols++){
// get the single pixel color value
$value = $c_row[$cols];
// if value is not empty (empty values are the blank pixels)
if($value != ""){
// get the hexadecimal string (must be 6 chars length)
// so add the missing chars if needed
$hex = $value;
while(strlen($hex) < 6){
$hex = "0" . $hex;
}
// convert value from HEX to RGB
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
// allocate the new color
// N.B. teorically if a color was already allocated
// we dont need to allocate another time
// but this is only an example
$test = imagecolorallocate($img, $r, $g, $b);
// and paste that color into the image
// at the correct position
imagesetpixel($img, $cols, $rows, $test);
}
}
}
// print out the correct header to the browser
header("Content-type:image/jpeg");
// display the image
imagejpeg($img, "", 90);
?>
]




Previous
Next
Tags: