Wednesday 16 July 2008

Streaming raw image data into Flash

As an alternative to using flv video in Flash, it is possible to stream raw image data across a socket to be used to fill a BitmapData object provided that each pixel is transferred as a 32-bit ARGB value.
By streaming from a socket (running in an external application) on the localhost, this displays about 9fps (820x640 pixels). Of course, there is no audio.



package
{
import flash.display.*;
import flash.geom.Rectangle;
import flash.net.*;
import flash.events.*;
import flash.utils.ByteArray;
import flash.errors.EOFError;


/**
* ...
*
*
* Open a socket
* read an image
* display
* repeat
*/
public class Main extends Sprite
{

private var imageSocket:Socket;
private var response:String;
private var imageBytes:ByteArray;
private var byteArrayOffset:Number;
private var myBitmap:Bitmap;
private var myBitmapData:BitmapData;

public function Main()
{

response = new String("");
imageBytes = new ByteArray();
byteArrayOffset = new Number();
byteArrayOffset = 0;

stage.stageWidth = 820;
stage.stageHeight = 640;

myBitmapData = new BitmapData(820, 640, true, 0xFFFFFF00);
myBitmap = new Bitmap(myBitmapData);

stage.addChild(myBitmap);



imageSocket = new Socket("localhost", 4242);

imageSocket.addEventListener(Event.CLOSE, closeHandler);
imageSocket.addEventListener(Event.CONNECT, connectHandler);
imageSocket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imageSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
imageSocket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);




}

private function closeHandler(event:Event):void
{
imageSocket.flush();
trace("closeHandler: " + event);
trace(response.toString());
}

private function connectHandler(event:Event):void
{
trace("connectHandler: " + event);
}

private function ioErrorHandler(event:IOErrorEvent):void
{
trace("ioErrorHandler: " + event);
}

private function securityErrorHandler(event:SecurityErrorEvent):void
{
trace("securityErrorHandler: " + event);
}

private function socketDataHandler(event:ProgressEvent):void
{

//trace("socketDataHandler: " + event);
//this bit reads the stuff in the socket into a ByteArray object,
//note that it comes in chunks, so you need to add up the bytesloaded
//property each time the event is called until your message is the size
//you expect.

imageSocket.readBytes(imageBytes, byteArrayOffset, event.bytesLoaded);

byteArrayOffset = byteArrayOffset + event.bytesLoaded;


if (byteArrayOffset >= 820*640*4) //image is loaded
{
//do stuff with image

byteArrayOffset = 0;

//need to reset the position pointer in the ByteArray so that
//subsequent functions read from the start of the array

imageBytes.position = 0;


this.drawImage();

}

}

private function drawImage():void
{
try
{
var rect:Rectangle = new Rectangle(0, 0, 820, 640);

//this bit sets the pixel values in the BitmapData object to the values in the ByteArray

myBitmapData.setPixels(rect, imageBytes);
}
catch (e:EOFError)
{
trace(e);
}
}
}
}

No comments: