/**
* Copyright sasa ( http://wonderfl.net/user/sasa )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/eN9I
*/
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
[SWF(width="360", height="320", backgroundColor="#ffffff", frameRate="15")]
public class ChromakeyCamera extends CameraFramework
{
[Embed(source='backGround.jpg')]
private var BackGround:Class; ///< 背景画像
public static const
VIDEO_WIDTH:int = 320, ///< ビデオの幅
VIDEO_HEIGHT:int = 240, ///< ビデオの高さ
SCREEN_WIDTH:int = 360, ///< 画面の幅
SCREEN_HEIGHT:int = 320; ///< 画面の高さ
private var backGround:BitmapData = null; ///< 背景画像
private var chromakeyOn:Boolean = true;
public function ChromakeyCamera()
{
super( SCREEN_WIDTH, SCREEN_HEIGHT, VIDEO_WIDTH, VIDEO_HEIGHT );
var bmp:Bitmap = new BackGround();
backGround = bmp.bitmapData;
label.text = "Chromakey Camera";
drawBgColor(0xD78500);
// ボタン追加
var buttonY:int = 10, buttonW:int = 140;
var chromakeyOnButton:TextButton = new TextButton(buttonW, 20, "ChromaKey ON");
chromakeyOnButton.x = 10;
chromakeyOnButton.y = buttonY;
addChild(chromakeyOnButton);
chromakeyOnButton.addEventListener( MouseEvent.CLICK, chromakeyOnButtonClick );
var chromakeyOffButton:TextButton = new TextButton(buttonW, 20, "ChromaKey OFF");
chromakeyOffButton.x = chromakeyOnButton.x + chromakeyOnButton.width + 10;
chromakeyOffButton.y = buttonY;
addChild(chromakeyOffButton);
chromakeyOffButton.addEventListener( MouseEvent.CLICK, chromakeyOffButtonClick );
}
/// Chromakey ON ボタン処理
private function chromakeyOnButtonClick(event:MouseEvent):void {
chromakeyOn = true;
}
/// Chromakey OFF ボタン処理
private function chromakeyOffButtonClick(event:MouseEvent):void {
chromakeyOn = false;
}
/// 描画処理
public override function draw():void {
/// 画面の真ん中の色を色調整用に出力
trace( "COLOR:" + bdTmp.getPixel32(VIDEO_WIDTH/2,VIDEO_HEIGHT/2).toString(16) );
if( chromakeyOn == false ){
bd.draw(bdTmp);
return;
}
/// マスクの作成
//var maskBitmap:BitmapData = bdTmp.clone(); ///< こっちだとなんかダメ
var MASKFLAG_COLOR:uint = 0xFFFF0000;
var maskBitmap:BitmapData = new BitmapData(bdTmp.width, bdTmp.height);
maskBitmap.draw(bdTmp);
/// 青系の色を透過色にする(ここの色の値を調整するとクロマキーで抜ける色が変わる)
var THRESHOLD_RG_COLOR:uint = 0x444400; ///< 赤、緑がこの値以上だったら透過色ではない
var THRESHOLD_BLUE_COLOR:uint = 0x000060; ///< 青がこの値以上でないと透過色ではない
// まず赤、緑成分が一定値以上のところをMASKFLAG_COLORで塗りつぶす
maskBitmap.threshold(maskBitmap, maskBitmap.rect, new Point(), ">", THRESHOLD_RG_COLOR, MASKFLAG_COLOR, 0x00ffff00 );
// 次に青成分が、一定値以下のところをMASKFLAG_COLORで塗りつぶす
maskBitmap.threshold(maskBitmap, maskBitmap.rect, new Point(), "<", THRESHOLD_BLUE_COLOR, MASKFLAG_COLOR, 0x000000ff );
// MASKFLAG_COLORで塗られてないところをalphaで塗りつぶし(残ったところはかなり青いはず)
maskBitmap.threshold(maskBitmap, maskBitmap.rect, new Point(), "!=", MASKFLAG_COLOR, 0x00000000);
/// 背景描画を描画
bd.draw(backGround);
/// マスキングして、WEBカメラ画像の描画
bd.copyPixels( bdTmp, bdTmp.rect, new Point(), maskBitmap, new Point(), true);
}
}
}
import flash.display.*;
import flash.events.*;
import flash.media.*;
import flash.text.*;
import flash.geom.*
import flash.errors.*;
import flash.filters.*;
import flash.utils.*;
import flash.net.*;
public class CameraFramework extends Sprite
{
private var camera:Camera = null; ///< カメラ
public var video:Video = null; ///< ビデオ
public var bgShape:Shape = new Shape(); ///< 外枠用
public var bd:BitmapData; ///< BMPデータ
public var bdTmp:BitmapData; ///< テンポラリビットマップデータ
public var label:TextField = new TextField(); ///< ラベル
/**
* コンストラクタ
* @param screenWidth SWFの幅
* @param screenHeight SWFの高さ
* @param videoWidth ビデオの幅
* @param videoHeight ビデオの高さ
*/
public function CameraFramework( screenWidth:int, screenHeight:int, videoWidth:int, videoHeight:int )
{
// filterの作成
var filter:Array = new Array;
filter.push( new DropShadowFilter() );
// 背景色用オブジェクト作成
addChild(bgShape);
drawBgColor(0x333333);
// BMPデータの作成
var bmp:Bitmap
bd = new BitmapData( videoWidth, videoHeight, false, 0xffffff);
bmp = new Bitmap(bd);
bmp.filters = filter;
bmp.x = (screenWidth - videoWidth)/2;
bmp.y = (screenHeight - videoHeight)/2;
addChild(bmp);
bdTmp = new BitmapData( videoWidth, videoHeight, false, 0xffffff);
//ラベル
label.autoSize=TextFieldAutoSize.LEFT;
label.text = "WebCamera Framework";
label.filters = filter;
label.textColor = 0xffffff;
label.x = 2;
label.y = screenHeight - label.textHeight - 10;
addChild(label);
//カメラの取得
camera=Camera.getCamera();
if (camera!=null) {
//イベントリスナーの追加
camera.addEventListener(StatusEvent.STATUS,statusHandler);
//ビデオの生成
video = new Video( videoWidth, videoHeight );
video.attachCamera(camera);
} else {
label.text="カメラを利用できません";
}
// メインループ追加
addEventListener(Event.ENTER_FRAME, tick);
}
/// 状態イベントの処理
private function statusHandler(evt:StatusEvent):void {
if (camera.muted){
label.text="カメラを利用できません";
}
}
/// メインループ
private function tick( event:Event ):void
{
if(video == null || camera == null){
return;
}
if( camera.muted == true ){
// カメラがアクセス禁止されている
return;
}
// bdTmpにビデオデータを転送
bdTmp.draw(video);
// 画面描画
draw();
}
/// 背景色の描画
public function drawBgColor(color:uint):void {
bgShape.graphics.lineStyle(0,color);
bgShape.graphics.beginFill(color);
bgShape.graphics.drawRect(0,0,360,320);
bgShape.graphics.endFill();
}
/**
* この関数がoverrideされ、カメラの描画処理を決定する
*/
public function draw():void {
for( var y:int = 0; y < bdTmp.height; ++y ){
for( var x:int = 0; x < bdTmp.width; ++x ){
var color:uint = bdTmp.getPixel(x , y);
bd.setPixel(x, y, color);
}
}
}
/**
* 指定されているURLのウェブサイトを開く
* @param openURL 開くURL
*/
private function openWebsite(openURL:String):void {
var variables:URLVariables = new URLVariables();
var request:URLRequest = new URLRequest(openURL);
try {
navigateToURL(request);
}
catch (e:Error) {
// handle error here
}
}
}
import flash.display.*;
import flash.filters.*;
import flash.text.*;
/// ボタン
public class TextButton extends SimpleButton {
/**
* コンストラクタ
* @param w 幅
* @param h 高さ
* @param text ボタンに表示する文字列
*/
public function TextButton( w:uint, h:uint, text:String ) {
var ew:uint = 15;
downState = makeRoundRect(w, h, ew, 0x006600, text);
overState = makeRoundRect(w, h, ew, 0x00ff00, text);
upState = makeRoundRect(w, h, ew, 0x777777, text);
var filter:Array = new Array;
filter.push( new DropShadowFilter() );
this.filters = filter;
//当たり判定
hitTestState = upState;
//ハンドアイコン
useHandCursor = true;
}
/**
* テキストフォーマットの生成
* @param size サイズ
* @param color 色
*/
public static function makeTextFormat(size:uint,color:uint):TextFormat {
var format:TextFormat=new TextFormat();
format.font ="_等幅";
format.size =size;
format.color=color;
format.bold =true;
return format;
}
/**
* 一定高さ以下にフォントサイズを調整。height以下の高さに
*/
public static function setFontHeight(label:TextField,format:TextFormat,height:uint):void {
var i:uint;
var lastSize:uint = 1;
for(i = lastSize;; i++ ){
format.size=i;
label.setTextFormat(format);
if (label.textHeight >= height){
break;
}
lastSize = i;
}
format.size = lastSize;
label.setTextFormat(format);
}
/**
* 角円矩形の作成
* @param w 幅
* @param h 高さ
* @param ew 角の丸まり
* @param color 色
*/
private function makeRoundRect(w:uint,h:uint,ew:uint,color:uint,text:String):Sprite {
var rrect:Sprite=new Sprite();
rrect.graphics.beginFill(color); //塗り潰し色
rrect.graphics.drawRoundRect(0,0,w,h,ew);//XY座標,幅,高さ,角丸幅
rrect.graphics.endFill(); //塗り潰し終了
rrect.alpha = 0.8;
var textHeight:uint = h/4*3;
var textField:TextField=new TextField();
textField.text = text;
textField.y = (h - textHeight)/2;
textField.width = w;
textField.height = textHeight;
textField.selectable = false;
textField.mouseEnabled = false;
textField.autoSize = TextFieldAutoSize.CENTER;
var format:TextFormat = makeTextFormat(12, 0xffffff);
setFontHeight(textField, format, textHeight);
textField.setTextFormat(format);
rrect.addChild(textField);
return rrect;
}
}