Menu:

Sponsor

Discover Master of Alchemy, our first iPad/iPhone and iPod touch game!

 

Forum's topics

Latest Files

Archives

Top Rated

Categories

Photo Gallery


Export JPEG with Flash/PHP

As you can see in the previous example, once "print" button is pressed a loader window appears counting the percent progress.

This is because i used a setInterval function to copy all the pixels. This won't stress your cpu so much..

Here the class i use:


import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;
import flash.geom.Matrix;

/**
 * Little and simple print flash screen class
 */
class it.sephiroth.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, 5, 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)  // send back the progress status
        scope.record.rows += 1
        if(scope.record.rows >= bit.height){
            clearInterval(scope.id)
            scope.broadcastMessage("onComplete", movie, scope.record)   // completed!
            bit.dispose();
        }
    }
}

 

The ASBroadcaster class will be useful because i will use the addListener() method in order to receive events (onStart, onComplete and onProgress).

the main method is "print", which accepts there params:

  1. mc: the movieclip to copy
  2. x: x origin of the copy
  3. y: y origin of the copy
  4. w: width
  5. h: height

then the setInterval will copy all the pixel in one single row in the BitmapData object, every 5 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 210 variables to post with the LoadVars object.

Please note that 0xFFFFFF pixels won't be added in the arrays, this beacuse the image i will create in PHP will have a blank background color, and for this reason blank pixels wont be created every time...

 

3. The .fla source

Now let's take a look at the flash file will use this "PrintScreen" class:

import it.sephiroth.mloaderWindow
import it.sephiroth.PrintScreen


var loader:mloaderWindow = this.createClassObject(mloaderWindow, "loader", 10, {_x:-1000, _y:-1000})
loader.setStyle("borderColor", 0x006699)

// 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/pixels.php", "_blank", "POST")
    loader.close()
}

/**
 * Print Button has been clicked
 */
function print_me(){
    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, 500, 210) // copy the _root
    loader.label = "computing... 0%"
    loader.open(true, true, true);  // open a loader
}

 

there's nothing particular to say here..
Once the "print" button is clicked call the print_me() 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, 500, 210) 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 ( the posted Content-length is: 563024 )

 

4. Generate the image in PHP

Here the code of the "pixels.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($img000xFFFFFF);

$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($hex02));
            
$g hexdec(substr($hex22));
            
$b hexdec(substr($hex42));
            
// 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);
?>

 

 

That's all.
This is only a demonstration, because this method require a lot of memory to be used from PHP in order to generate the image (ImageMagik should be a better solution in this case indeed), and also because the POST headers are very very big!

You can use for example the Live HTTP headers FireFox extension to see exactly what we're passing to the pixels.php page.

 

In the same way you can read pixels informations from a BitmapData many other things can be done, for example parsing an image and find streets

 

6. Download file source

Download files used in this tutorial