Test to see if Camera.copyToByteArray() is buggy
package dev.camera
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.media.Camera;
import flash.media.Video;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.ByteArray;
/**
* Test to see if Camera.copyToByteArray() is buggy
*
* Run the file as your main Document, accept the camera prompt, then drag the region with the red outlne.
* Note how the contents of the region are copied to the bitmap using bitmapData.draw()
*
* Now, press any key to toggle to camera.copyToByteArray() mode.
* See how the recatngular region, though using the same coordinate, will not move in Y.
*
* Please submit a code fix if you think this isn't the case!
*
* @author Dave Stewart
*/
public class CopyFrameTest extends Sprite
{
// ---------------------------------------------------------------------------------------------------------------------
// { region: variables
// values
protected var small :int;
// geom
protected var outer :Rectangle;
protected var inner :Rectangle;
protected var inter :Rectangle;
protected var target :Rectangle;
protected var matrix :Matrix;
// elements
protected var status :TextField;
protected var video :Video;
protected var bitmap :Bitmap;
protected var region :Sprite;
protected var overlay :Sprite;
// objects
protected var bitmapData :BitmapData;
protected var camera :Camera;
protected var bytes :ByteArray;
// variables
protected var copyBytes :Boolean;
protected var invalid :Boolean;
// ---------------------------------------------------------------------------------------------------------------------
// { region: instantiation
public function CopyFrameTest()
{
initialize();
build();
start();
}
protected function initialize():void
{
// variables
small = 100;
// bounds
outer = new Rectangle()
inner = new Rectangle();
matrix = new Matrix();
// data
bytes = new ByteArray();
bitmapData = new BitmapData(small, small);
// camera
camera = Camera.getCamera();
camera.setMode(400, 300, 15);
}
protected function build():void
{
// stage
x = y = 10
// video
video = new Video(camera.width, camera.height);
addChild(video);
// bitmap
bitmap = new Bitmap(bitmapData);
bitmap.width = small;
bitmap.height = small;
bitmap.y = video.height + 10;
addChild(bitmap);
// status
status = new TextField();
status.x = status.y = 10;
status.autoSize = 'left';
status.selectable = false;
status.defaultTextFormat = new TextFormat('_sans', 11);
addChild(status);
// region
region = new Sprite();
region.graphics.beginFill(0x000000, 0.2);
region.graphics.drawRect(0.5, 0.5, small - 1, small - 1);
addChild(region);
// overlay
overlay = new Sprite();
addChild(overlay);
}
protected function start():void
{
// status
updateStatus();
status.appendText(' (press any key to change drawing mode)');
// update bounds
updateBounds();
// make region draggable
Draggable.create(region, onDrag);
// event handlers
camera.addEventListener(Event.VIDEO_FRAME, onVideoFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
// attach camera
video.attachCamera(camera);
}
// ---------------------------------------------------------------------------------------------------------------------
// { region: handlers
protected function onDrag(event:MouseEvent):void
{
invalid = true;
}
protected function onKeyDown(event:KeyboardEvent):void
{
copyBytes = ! copyBytes;
updateStatus();
}
protected function onVideoFrame(event:Event):void
{
if (invalid)
{
updateBounds();
invalid = false;
}
draw();
}
// ---------------------------------------------------------------------------------------------------------------------
// { region: protected functions
protected function updateStatus():void
{
status.text = copyBytes ? 'camera.copyToByteArray()' : 'bitmapData.draw()';
}
protected function updateBounds():void
{
// bounds
outer = new Rectangle(video.x, video.y, video.width, video.height);
inner = new Rectangle(region.x, region.y, region.width, region.height);
inter = outer.intersection(inner);
target = new Rectangle(0, 0, inter.width, inter.height);
// matrix
matrix.tx = inner.x > 0 ? -inner.x : 0;
matrix.ty = inner.y > 0 ? -inner.y : 0;
// draw
overlay.graphics.clear();
overlay.graphics.lineStyle(1, 0xFF0000);
overlay.graphics.drawRect(inter.x, inter.y, inter.width, inter.height);
// update size of bitmap
if (target.width > 0 && target.height > 0)
{
bitmapData = new BitmapData(inter.width, inter.height, false, 0xFF0000);
}
}
protected function draw():void
{
// camera.copyToByteArray
if (copyBytes)
{
// copy bytes
bytes = new ByteArray();
camera.copyToByteArray(inter, bytes);
bytes.position = 0;
// set pixels
bitmapData.setPixels(target, bytes)
}
// bitmapData.draw()
else
{
bitmapData.draw(video, matrix);
}
// update bitmap
bitmap.bitmapData = bitmapData;
bitmap.width = inter.width;
bitmap.height = inter.height;
}
// ---------------------------------------------------------------------------------------------------------------------
// { region: protected functions
}
}
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
class Draggable
{
protected var element :DisplayObject;
protected var pt :Point;
protected var onDrag :Function;
public static function create(element:Sprite, onDrag:Function):void
{
new Draggable(element, onDrag);
}
public function Draggable(element:DisplayObject, onDrag:Function)
{
this.element = element;
this.onDrag = onDrag;
element.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
protected function onMouseDown(event:MouseEvent):void
{
pt = new Point(event.stageX - element.x, event.stageY - element.y);
element.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
element.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
protected function onMouseMove(event:MouseEvent):void
{
element.x = event.stageX - pt.x;
element.y = event.stageY - pt.y;
onDrag && onDrag(event);
}
protected function onMouseUp(event:MouseEvent):void
{
element.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
element.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}