davestewart
8/24/2015 - 10:07 PM

Test to see if Camera.copyToByteArray() is buggy

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);
	}
	
}