Skip to content

Instantly share code, notes, and snippets.

@marchbold
Last active April 28, 2016 23:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marchbold/0075bbf8ccf46ac76668 to your computer and use it in GitHub Desktop.
Save marchbold/0075bbf8ccf46ac76668 to your computer and use it in GitHub Desktop.
A Basic Starling Camera UI using the distriqt Camera ANE
/**
* __ __ __
* ____/ /_ ____/ /______ _ ___ / /_
* / __ / / ___/ __/ ___/ / __ `/ __/
* / /_/ / (__ ) / / / / / /_/ / /
* \__,_/_/____/_/ /_/ /_/\__, /_/
* / /
* \/
* http://distriqt.com
*
* @file VideoCameraUI.as
* @brief A Basic Starling Camera UI using the distriqt Camera ANE
* @author "Michael Archbold (ma@distriqt.com)"
* @created 30/03/2015
* @copyright http://distriqt.com/copyright/license.txt
*/
package com.distriqt.camera.starling
{
import com.distriqt.extension.camera.Camera;
import com.distriqt.extension.camera.CameraMode;
import com.distriqt.extension.camera.CameraParameters;
import com.distriqt.extension.camera.CaptureDevice;
import com.distriqt.extension.camera.events.CameraEvent;
import flash.desktop.NativeApplication;
import flash.display.BitmapData;
import flash.display3D.textures.Texture;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
import starling.textures.Texture;
/**
* @author "Michael Archbold (ma@distriqt.com)"
*/
public class VideoCameraUI extends Sprite
{
/**
* Constructor
*/
public function VideoCameraUI()
{
super();
addEventListener( starling.events.Event.ADDED_TO_STAGE, addedToStageHandler );
}
////////////////////////////////////////////////////////
// VARIABLES
//
private var _options : CameraParameters
private var _device : CaptureDevice;
private var _container : Sprite;
private var _preview : Image;
private var _previewTexture : starling.textures.Texture;
private var _previewData : ByteArray;
private var _previewBitmapData : BitmapData;
private var _previewBitmapRect : Rectangle;
private var _lastFrameProcessed : Number = -1;
////////////////////////////////////////////////////////
// FUNCTIONALITY
//
////////////////////////////////////////////////////////
// INTERNALS
//
private function initialiseExtension():void
{
try
{
Camera.init( Config.APP_KEY );
if (Camera.isSupported)
{
var devices:Array = Camera.instance.getAvailableDevices();
for each (var device:CaptureDevice in devices)
{
if (device.position == CaptureDevice.POSITION_FRONT)
{
_device = device;
break;
}
}
_options = new CameraParameters();
_options.enableFrameBuffer = true;
_options.cameraMode = new CameraMode( CameraMode.PRESET_HIGH );
_options.deviceId = _device.id;
_options.frameBufferWidth = 1280;
_options.frameBufferHeight = 720;
Camera.instance.addEventListener( CameraEvent.VIDEO_FRAME, camera_videoFrameHandler );
Camera.instance.initialise( _options );
Camera.instance.setFocusMode( CameraParameters.FOCUS_MODE_CONTINUOUS );
}
}
catch (e:Error)
{
trace( e );
}
}
private function releaseExtension():void
{
try
{
Camera.instance.removeEventListener( CameraEvent.VIDEO_FRAME, camera_videoFrameHandler );
Camera.instance.release();
Camera.instance.dispose();
}
catch (e:Error)
{
trace( e );
}
}
private function DEG2RAD( degrees:Number ):Number
{
return degrees * Math.PI / 180;
}
////////////////////////////////////////////////////////
// EVENT HANDLERS
//
private function addedToStageHandler( event:starling.events.Event ):void
{
_previewData = new ByteArray();
_previewBitmapData = new BitmapData( 1, 1, false );
_previewBitmapRect = new Rectangle(0,0,1,1);
_previewTexture = starling.textures.Texture.fromBitmapData( _previewBitmapData );
_preview = new Image( _previewTexture );
addChild( _preview );
initialiseExtension();
NativeApplication.nativeApplication.addEventListener( flash.events.Event.DEACTIVATE, deactivateHandler );
NativeApplication.nativeApplication.addEventListener( flash.events.Event.ACTIVATE, activateHandler );
}
private function deactivateHandler( event:flash.events.Event ):void
{
releaseExtension();
}
private function activateHandler( event:flash.events.Event ):void
{
initialiseExtension();
}
private function camera_videoFrameHandler( event:CameraEvent ):void
{
var frame:Number = Camera.instance.receivedFrames;
if (frame != _lastFrameProcessed)
{
if (-1 != Camera.instance.getFrameBuffer( _previewData ))
{
try
{
//
// Check we have an appropriately sized bitmapdata and texture
// Recreate if not
if (_previewBitmapData.width != Camera.instance.width || _previewBitmapData.height != Camera.instance.height)
{
trace( "resizing to: (" + Camera.instance.width +", "+ Camera.instance.height +")" );
_previewBitmapData.dispose();
_previewTexture.dispose();
_previewBitmapData = new BitmapData( Camera.instance.width, Camera.instance.height, false );
_previewTexture = starling.textures.Texture.fromBitmapData( _previewBitmapData );
_preview.texture = _previewTexture;
_preview.readjustSize();
_previewBitmapRect = new Rectangle( 0, 0, _previewBitmapData.width, _previewBitmapData.height );
var s:Number = 1.0;
var t:Matrix = new Matrix();
if (_device.orientation == 90 || _device.orientation == 270)
{
s = stage.stageWidth / _previewTexture.height;
t.translate( - _previewTexture.width * 0.5, - _previewTexture.height * 0.5 );
t.rotate( DEG2RAD(_device.orientation) );
t.scale( s, s );
t.translate( _previewTexture.height * s * 0.5, _previewTexture.width * s * 0.5 );
}
else
{
s = stage.stageWidth / _previewTexture.width;
t.translate( - _previewTexture.width * 0.5, - _previewTexture.height * 0.5 );
t.rotate( DEG2RAD(_device.orientation) );
t.scale( s, s );
t.translate( _previewTexture.width * s * 0.5, _previewTexture.height * s * 0.5 );
}
// Something weird happens here with large bitmaps and it turns white? If you comment out this line it works but isn't rotated...
_preview.transformationMatrix = t;
}
//
// Update the bitmapdata and texture
_previewBitmapData.setPixels( _previewBitmapRect, _previewData );
flash.display3D.textures.Texture(_previewTexture.base).uploadFromBitmapData( _previewBitmapData );
}
catch (e:Error)
{
trace( e );
}
finally
{
_previewData.clear();
_lastFrameProcessed = frame;
}
}
}
}
}
}
// com.distriqt.Camera
@berkayk
Copy link

berkayk commented Jul 1, 2015

This example works fine but I think it needs better documentation.

Is there any way to fit the bitmapdata into a square sized area? If not, is there a way to capture the image with square dimensions like 640x640? Changing the size of _previewBitmapRect didn't do the trick.

Thanks.

@marchbold
Copy link
Author

Hi,
You can't just change the rect to setPixels as it's related to the data in the byte array. Instead you should create a second bitmapdata of your target size and copy the region from the preview BitmapData :

var croppedBitmapData:BitmapData = new BitmapData( cropWidth, cropHeight ); 
croppedBitmapData.copyPixels(
    _previewBitmapData, 
    new Rectangle(startPointX, startPointY, cropWidth, cropHeight), new Point(0, 0)
);

Just make sure that the cropped region is contained with in the size of the preview bitmap data.

@berkayk
Copy link

berkayk commented Jul 2, 2015

Thanks marhbold.

By the way, I changed the order of matrices applied to translate, rotate, translate again then scale. This way it's now properly fitting on to the image.

t.translate( - _previewTexture.width * 0.5, - _previewTexture.height * 0.5 );
t.rotate( DEG2RAD(_device.orientation) );
t.translate( _previewTexture.height * s * 0.5, _previewTexture.width * s * 0.5 );
t.scale( s, s );

@piskulicivan
Copy link

Hey marchbold! Can you please help me and tell me how can I make camera full screen? On this screen I show my problem. On lower part of screen there is no camera. How can I stretch it?
screenshot_2015-10-03-20-54-49

@marchbold
Copy link
Author

Please post your support questions in the github repository, we don't get notifications or follow these gists.

@paulornova
Copy link

Great code, thaks very much!
To fix the White problem just need to set the generateMipMap false during the texture creation at line 197.

_previewTexture = starling.textures.Texture.fromBitmapData( _previewBitmapData, false );

I am also saving and applying the transformation matrix on a new bitmap data to return it as it looks.

var bd:BitmapData = new BitmapData(_preview.width, _preview.height, false, 0);
bd.draw(_previewBitmapData, _rotateMatrix);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment