Save Flash frame as JPG with PHP GD library

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 :

  1. mc: the flash frame to copy
  2. x: x origin of the frame
  3. y: y origin of the frame
  4. w: width
  5. 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);
?>

 




Comment: 2 | Read times: -
unnamed[2011-01-21 09:37 AM | del]
pls help me find some sample tutotial video on how to save flash frame as jpeg in php...tnx a lot!.... :-)
unnamed[2011-01-21 09:08 AM | del]
this would help me a lot.. but maybe i'll check some sample video on how to use it..thanks x)...
Announce commentary
Your name
Content
Validation code Code