I'm looking for any information anyone may have on ActionScript 3.0 and capturing the area of the stage. I'm not interested in taking a picture of someones desktop, just the stage.
Thanks
Printable View
I'm looking for any information anyone may have on ActionScript 3.0 and capturing the area of the stage. I'm not interested in taking a picture of someones desktop, just the stage.
Thanks
What is the problem?
Hmm, not sure if you can do that only with actionscript.
Taking a screenshot only of your stage might be tricky if not impossible. Think of it as if you were trying to tell flash to print the stage but instead, try to somehow render it... No idea how to do it actually, as I know, flash can't export .jpg files or anything else via code, but I might be wrong... Can't help you with too much, sorry.
Ah, ok understand. You can convert a Sprite or MovieClip to a Bitmap and store as a jpg, but you can't do that with the stage as far as I know.
^ Maybe he could do a work around by building his whole project in one movie clip ( like a main container ) and that way he could store that movie clip ( essentially that movie clip is "the stage" since it holds everything else ).
Could be she :)
^ Ahh, true, could be. :)
uh, why not just:
Code:var bd:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight);
bd.draw(stage);
var screenshot:Bitmap = new Bitmap(bd);
oh, if it's to send out, you'd do something like:
after the bitmapdata is drawn...and then send that ByteArray in POST data or through AMF or however you want to PHP, where you can use GD to draw it into a jpeg. The only problem you'll have is that you'll get errors unless all loaded objects are in the same application domain and used loader context files that explicitly allow the domain the flash is being served from... because otherwise you won't have access to the bitmap-level data.Code:var ba:ByteArray = bd.getPixels(new Rectangle(0,0,stage.stageWidth,stage.stageHeight));
Good thing you don't want to take a screenshot of their desktop, that would be impossible anyway.
thanks for the post, joshstrike, your info has helped me as well with my project. I'm wondering if you may have some incite into how I can take this a step further. I've been a Flash user for a couple of years but have yet to fully grasp AS3, but am doing my best. Currently, what I'm trying to do is allow the user to capture a specific region (set size displayed as the cursor) of the stage and then be able to save that pixel data into memory. For now I'd just like to repost it to a blank portion of the stage. Using the code you posted I've been able to capture the whole stage and I've setup the moving cursor and set the capture size to the size of the cursor, but when I capture (onClick) it only grabs the region from the origin (top left corner). I'm wondering how I can get flash to allow me to capture the region of the stage based on the current cursor position. Here is what I have so far:
Logically, I'm thinking that if I record the current cursor position and subtract its distance in x and y from the origin when I run the function, I should be able to locate the area of the stage, but I'm not sure how to say that in AS3. Any push in the right direction is much appreciated.Code:stop();
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,follow);
function follow(evt:MouseEvent){
cursor.x = mouseX;
cursor.y = mouseY;
}
stage.addEventListener(MouseEvent.CLICK,onClick);
function onClick(evt:MouseEvent){
grabStage();
trace("picSnapped");
}
function grabStage()
{
var bd:BitmapData = new BitmapData(cursor.width,cursor.height);
bd.draw(stage);
var screenshot:Bitmap = new Bitmap(bd);
screenshot.x = 550;
screenshot.y = 100;
addChild(screenshot);
}
My Stage is 800 by 800 and I want a jpg snapshot of a particular region.
I still don't know why I have to give the translate command negetive numbers, but I think it's subtracting x and y from the center of the rectangle as centered on the stage. I then use the jpegencoder from as3corelib (free on the net) to do the encoding. Next I send it to php using this code.Code:var stage_snapshot:BitmapData = new BitmapData(600, 120);
var myRectangle:Rectangle = new Rectangle(0, 0, 600, 120);
var myMatrix:Matrix = new Matrix();
var translateMatrix:Matrix = new Matrix();
translateMatrix.translate(-100, -225);
myMatrix.concat(translateMatrix);
stage_snapshot.draw(stage,myMatrix,null,null,myRectangle);
var encoded_jpg:JPGEncoder = new JPGEncoder(100);
var jpg_binary:ByteArray = new ByteArray();
jpg_binary = encoded_jpg.encode(stage_snapshot);
Keep in mind you are using urlvariables in this case, so you cannot send variable pairs with this or retreive them from php. I worked around this by adding the extra information I needed to the end of the picture stream then chopping it off using php. Cryptosalt is optional and is another free library online to encrypt passwords or other data going to php and back. It returns an encrypted string of 24 characters in length which will decrypt in php into the word "parameter". Write multibyte takes the jpg string and tacks on the 24 characters to the end of it.Code:var header:URLRequestHeader = new URLRequestHeader ("Content-type", "application/octet-stream");
var request:URLRequest = new URLRequest("savejpg.php);
request.requestHeaders.push(header);
request.method = URLRequestMethod.POST;
request.data = jpg_binary;
var loader:URLLoader = new URLLoader();
trace ("sending pic to php");
loader.load(request);
loader.addEventListener(Event.COMPLETE,finishSave);
if you know the length ahead of time and it doesn't change, no problem. BUt if you have a variable length of data at the end of the picture, you opened to tell php how many bytes to strip off. I put that in there by modifying the url to include get variables.Code:var helperMode = cryptoSalt.encrypt("parameter");
jpg_binary.writeMultiByte(helperMode,"us-ascii");
var request:URLRequest = new URLRequest("savejpg.php?params=24,24,2);
So now to php to grab the header byte stream and the get variables.
//this part takes substrings of the last 50 bytes of the picture and decrypts parts of them based on the params array numbers. It then strips off 50 bytes from the end of the picture and write it to a jpg file.Code:$crypto = new Crypt;
$result = $crypto->init("SaltStrg"); //salt string for the decryption. Must be 8 characters for this particular decryption utility.
$params = explode(",",$_GET['params']); //divide paramter into a 3 row array by commas.
Code:$jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
$pw = $crypto->decrypt(utf8_decode(substr($jpg, - (int)($params[0] + $params[1] + $params[2]),(int)$params[0])));
$mode = $crypto->decrypt(utf8_decode(substr($jpg, - (int)($params[1] + $params[2]),$params[1])));
$petid = substr($jpg, -(int)$params[2]);
if ($pw != "password") die ("error=Not Authorized");
$jpg = substr($jpg,0,strlen($jpg) - ($params[0] + $params[1] + $params[2]));
if ($mode == "Banner")
{
$filename = "banners/pic.jpg";
file_put_contents($filename, $jpg);
echo "&error=none";
}
I recommend using the UILoader control to display your screenshot. Otherwise you'll be stuck removing each bitmap when next you click. If you don't, you'll keep eating up memory with bitmaps that overlap each other. Don't forget that you have to drag the UILoader component to the stage so that it goes to your library if you want to use it. You can then delete it from the stage as long as it reamins in the library.
Also, you'll need to put someting on your stage to capture. The draw method does not capture the stage bacground color. I drew a random shape to capture. The draw method fills the background with red if there is nothing to capture to help with diagnostics).
Code:import fl.containers.UILoader;
stage.addEventListener(MouseEvent.CLICK, mouseClick);
stage.addEventListener("mouseMove",moveCursor);
var ui = new UILoader();
with (ui) {x=300,y=100,width=200,height=200};
addChild(ui);
var copyArea = new Sprite();
copyArea.graphics.lineStyle(2,0x000000);
copyArea.graphics.drawRect(0,0,202,202);
copyArea.x = mouseX;
copyArea.y = mouseY;
addChild(copyArea);
function moveCursor(e):void
{
copyArea.x = (mouseX - 1);
copyArea.y = (mouseY - 1);
}
function mouseClick(e):void {
var rect:Rectangle = new Rectangle(mouseX, mouseY, 200, 200);
var matrix:Matrix = new Matrix();
matrix.translate(-rect.x, -rect.y);
var bmp:BitmapData = new BitmapData(rect.width, rect.height, false, 0xFFFF0000);
bmp.draw(stage, matrix);
var copied = new Bitmap(bmp);
ui.source = copied;
}
where do you got your cursor?
The box that I use as the cursor is titled "copyArea" and is a sprite in which a rectangle is drawn. It's initially set to the x,y cordinates that the mouse cursor is at. Then the stage listens for the mouse to move and updates the location of the "copyArea" cursor to match that of the mouse. Making dotted lines in AS3 is a pain and wasn't the primary goal of this post. I found at least 2 dotted line classes that you can use if you want that.
Otherwise I'm not sure what you are asking.