« 弾幕時計ブログパーツ | メイン | ハーフトーンカメラ(カラー) »

ハーフトーンカメラ(モノクロ)

Flash上でwebカメラにエフェクトかけて仮想カメラでキャプチャすれば、ustreamに加工映像を流せるようになるのでいろいろ試してみることにしました。

たとえばかまいたちフィルタ(PastClips参照)
http://ustream.tv/channel/munegons-show


他にどんなことができるかなと探していたらハーフトーン処理(ディザ法)なるものがあったので参考に作ってみました。








もちろん全ピクセルをひとつずつ見るようなことはせず、画像処理で一括変換してます。
これでustream配信しても面白そう。
こないだ衝動的に bitmapdata.jp のドメインを取ってしまったのもあるので、この手のエフェクトを集めてみるところから始めてみようかなと考えています。


ソースは以下。

package {
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.display.Shape;
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageQuality;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.filters.ColorMatrixFilter;
  import flash.geom.Matrix;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import flash.media.Camera;
  import flash.media.Video;
  
  
  [SWF(backgroundColor=0x000000, frameRate='30', width='320', height='240')]
  
  public class HalftoneMono extends Sprite {
    private const CAMERA_W:int = 320;
    private const CAMERA_H:int = 240;
    
    private var camera:Camera;
    private var video:Video;
        
    private var effect_bd:BitmapData;
    private var pattern_bd:BitmapData;
    
    private var rect:Rectangle;
    private var zero:Point;
    private var mtx:Matrix;
    private var mono_cmf:ColorMatrixFilter = new ColorMatrixFilter( [
      1/3, 1/3, 1/3, 0, 0,
      1/3, 1/3, 1/3, 0, 0,
      1/3, 1/3, 1/3, 0, 0,
      0, 0, 0, 1, 0 ]
    );    
    private var bayer_arr:Array = [
      0,  8,  2, 10,
      12,  4, 14,  6,
      3, 11,  1,  9,
      15,  7, 13,  5
    ];



public function HalftoneMono() {
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.BEST;
stage.scaleMode = StageScaleMode.NO_SCALE;

stage.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
}

private function mouseUpHandler( e:MouseEvent ):void {
stage.removeEventListener( e.type, arguments.callee );

camera = Camera.getCamera();

if ( camera != null ) {
setupPattern();
setupEffect();
}
}


private function setupPattern():void {
var bayer_bd:BitmapData = new BitmapData( 4, 4, false, 0x000000 );

for ( var y:int = 0; y < 4; ++y ) {
for ( var x:int = 0; x < 4; ++x ) {
var c:int = bayer_arr[ 4*y+x ]*16+8;
bayer_bd.setPixel( x, y, c << 16 | c << 8 | c );
}
}

var temp:Shape = new Shape();
temp.graphics.beginBitmapFill( bayer_bd );
temp.graphics.drawRect( 0, 0, CAMERA_W, CAMERA_H );
temp.graphics.endFill();

pattern_bd = new BitmapData( CAMERA_W, CAMERA_H, false, 0x000000 );
pattern_bd.draw( temp );
bayer_bd.dispose();
temp.graphics.clear();
}


private function setupEffect():void {
video = new Video( CAMERA_W, CAMERA_H );
video.attachCamera( camera );

rect = new Rectangle( 0, 0, CAMERA_W, CAMERA_H );
zero = new Point();
mtx = new Matrix();

effect_bd = new BitmapData( CAMERA_W, CAMERA_H, false, 0x000000 );
addChild( new Bitmap( effect_bd ) );

update();
stage.addEventListener( Event.ENTER_FRAME, update );
}

private function update( e:Event = null ):void {
effect_bd.lock();
effect_bd.draw( video );
effect_bd.applyFilter( effect_bd, rect, zero, mono_cmf );
effect_bd.draw( pattern_bd, mtx, null, "subtract");
effect_bd.threshold( effect_bd, rect, zero, ">", 0x000000, 0xffffffff, 0x0000ff );
effect_bd.unlock();
}
}
}

トラックバック

このエントリーのトラックバックURL:
http://void.heteml.jp/mt/mt-tb.cgi/98

コメントを投稿

あわせて読みたい