Webカメラの映像をアスキーアート化するAS3習作
http://n00dle.web.fc2.com/webcamasciify.html
任意のキーを入力すると表示モードが変わります。もちろんMac版Firefoxでは効かない。マウスイベントで処理すればよかった。
荒いなあ。Adobeのサンプルコードぐらいの精度にしたいんだが…。実態は、各ピクセルの明るさを文字列の長さで等分して、ドット数順に並んだAscii文字をそれぞれに割り振ってるだけだからか。一度Ascii文字をビットマップデータに描写してドット数を判定する箇所がプログラムに組み込むとうまく動かなくてめんどくさくなったから、Adobeのサンプルからドット数順に並んだ文字列を拝借した。素っ裸でコード書いてたんだけど、体も壁も白くてスクショ撮っても何がなんだか分からなかったから、しょうがなく黒いTシャツを着た。HMDに映して遊んでみる。
参考
- Example: ASCII art -- Flash CS3
- Oaxoa Blog » 2008 » March » 04 / Asciify - Actionscript 3 (as3) Ascii Art class
http://blog.oaxoa.com/2008/03/04/asciify-actionscript-3-as3-ascii-art-class/
http://shin-ishimaru.cocolog-nifty.com/blog/2007/09/webflash_9c21.html
ソースは以下
WebcamAsciify.as
package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.media.*; import flash.text.*; [SWF(backgroundColor = "0x000000", frameRate = "30")] public class WebcamAsciify extends Sprite { private var video:Video; private var textField:TextField; private var textFormat:TextFormat; private var bd:BitmapData; private var picW:uint; private var picH:uint; private var matrix:Matrix; private var pixels:Array; private var asciiArray:Array; private var swit:Boolean; public static const videoWidth:int = 320, videoHeight:int = 240, pixelSize:Number =5; public function WebcamAsciify() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; swit = new Boolean (false); //描写モードのスイッチ textFormat = new TextFormat(); textFormat.size = 6; textFormat.color = 0x00ff00; textFormat.font = "Courier New" sampleChars(); //Ascii文字テーブル生成 //Webカメラのビデオサイズを縮小して処理するための変数設定 picW = videoWidth / pixelSize; picH = videoHeight / pixelSize; matrix = new Matrix(); matrix.scale(1/pixelSize, 1/pixelSize); var camera : Camera = Camera.getCamera(); video = new Video(videoWidth, videoHeight); video.attachCamera(camera); textField = new TextField(); textField.autoSize = "left"; textField.selectable = false; textField.defaultTextFormat = textFormat; textField.antiAliasType=AntiAliasType.ADVANCED; addChild(textField); stage.addEventListener(KeyboardEvent.KEY_DOWN, entKey); addEventListener(Event.ENTER_FRAME, tick); } private function entKey(event:KeyboardEvent):void { swit = !(swit); } //メインループ private function tick(event:Event):void { textField.text = ""; var output:String = ""; bd = new BitmapData(picW, picH); bd.draw(video, matrix); pixels = new Array(); for (var y:uint = 0; y < picH; y++) { var row:Array=new Array(); for (var x:uint = 0; x < picW; x++) { var sampledColor:Number=bd.getPixel(x, y); row.push(sampledColor); } pixels.push(row); } for (var y:uint = 0; y < picH; y++) { for (var x:uint = 0; x < picW; x++) { var color:Number=pixels[y][x]; var rgb:Object=makeRgb(color); var avg:Number=(rgb.r + rgb.g + rgb.b)/3; var s:String = getCharFromColor(avg); output += s + s + s + s; } output+="\n\n"; } textField.appendText(output); } private function sampleChars():void { asciiArray = new Array(); var list:String = " .,;-~_+<>i!lI?/|)(1}{][rcvunxzjftLCJUYXZO0Qoahkbdpqwm*WMB8&%$#@"; asciiArray = list.split(""); } private function makeRgb(hex:Number):Object { var r:Number; var g:Number; var b:Number; r = (0xFF0000 & hex) >> 16; g = (0x00FF00 & hex) >> 8; b = (0x0000FF & hex); return {r:r,g:g,b:b}; } private function getCharFromColor(arg:uint):String { var i:uint=0; var _char:String; //"A"か" "で表現 if (swit == false) { if ( arg < Math.floor(256/3) ) { _char = "A"; } else { _char = " "; } } //複数のAscii文字で表現 if (swit == true) { for (var col:Number = 0; col < 256; col += Math.floor(256/asciiArray.length) ) { if (arg<=col) { _char = asciiArray[i]; } else { i++; } } } return _char; } } }