BitmapData の練習(なんとなくアウトラインっぽいもの取得)
/**
* Copyright mchang ( http://wonderfl.net/user/mchang )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/wODb
*/
/**
* なんとなくアウトラインを取得するサンプル
*
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.system.LoaderContext;
import flash.net.URLRequest;
import flash.geom.Point;
import flash.geom.Rectangle;
[SWF(width="465", height="465", backgroundColor="#ffffff", frameRate="60")]
public class OutlineSample1 extends Sprite
{
private var _loader:Loader;
public function OutlineSample1()
{
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initialize);
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
_loader.load(new URLRequest('http://wonderfl.minaco.net/Outline.png'), new LoaderContext(true));
}
private function completeHandler(e:Event):void
{
var c:LoaderInfo = _loader.contentLoaderInfo;
var tmpBitmapData:BitmapData = new BitmapData(c.content.width, c.content.height, true, 0x000000);
tmpBitmapData.draw(c.content);
// 不透明の黒(0xff000000) ではない領域を、透明(0x00000000)にします
tmpBitmapData.threshold(tmpBitmapData, tmpBitmapData.rect, new Point(0, 0), '!=', 0xff000000, 0x00000000, 0xffffffff, true);
// 不透明の黒(0xff000000) に一致する矩形領域を判別し、 画像が描画されている領域を取得します
var bounds:Rectangle = tmpBitmapData.getColorBoundsRect(0xffffffff, 0xff000000, true);
// 画像が描画されている領域を取得します
var imageBitmapData:BitmapData = new BitmapData((bounds.right - bounds.x), (bounds.bottom - bounds.y), true, 0x000000);
imageBitmapData.copyPixels(tmpBitmapData, bounds, new Point(0,0));
var bitmap:Bitmap = new Bitmap(imageBitmapData);
addChild(bitmap);
// 破棄します
tmpBitmapData.dispose();
tmpBitmapData = null;
// アウトラインを探します
var points:Array = search(imageBitmapData);
}
protected function search(bd:BitmapData):Array
{
bd.lock();
// アウトラインを取得するための開始座標を取得します
var start:Point = getStartPoint(bd);
if (start == null) {
trace('おかしい');
return null;
}
// 開始座標を青に設定します
var startColor:uint = 0xff0000ff;
bd.setPixel32(start.x, start.y, startColor);
var current:Point = start.clone();
var offsets:Array = [
new Point(1, 0),
new Point(1, 1),
new Point(0, 1),
new Point(-1, 1),
new Point(-1, 0),
new Point(-1, -1),
new Point(0, -1),
new Point(1, -1)
];
// 今の進行方向です
var direction:int = 0;
var points:Array = [current];
for (;;) {
var found:Boolean = false;
// 今の進行方向から時計回りに8方向全て順に調べます
for (var o:int = 0; o < 8; o++) {
var offset:Point = offsets[(direction + o) % 8];
var offset2:Point = offsets[(direction + o + 6) % 8];
var c:uint = bd.getPixel32(current.x + offset.x, current.y + offset.y);
// 一周し開始地点に戻ってきた場合は
if (c == startColor) {
// 終了します
break;
}
// この方向が黒 && この方向-90度の所が白い場合だけ
if (c == 0xff000000 && bd.getPixel32(current.x + offset2.x, current.y + offset2.y) != 0xff000000) {
// そっちに進む
current.x += offset.x;
current.y += offset.y;
// 進行方向がかわったときは
if (direction != o) {
// 座標を取得します
points.push(current.clone());
}
// 方向を覚えておきます
direction = o;
// もし右下(1, 1)の進行方向のときは
if (o == 1) {
// 右からチェックします
direction = 0;
}
// 進行方向が見つかった
found = true;
// 進行方向が見つかったのでぬける
break;
}
}
if (!found) {
break;
}
// アウトラインを緑にします
bd.setPixel32(current.x, current.y, 0xff00ff00);
}
bd.unlock();
return points;
}
protected function getStartPoint(bd:BitmapData):Point
{
var width:int = bd.width;
var start:Point;
for (var x:int = 0; x < width; x++) {
var c:uint = bd.getPixel32(x, 0);
if (c == 0xff000000) {
start = new Point(x, 0);
break;
}
}
return start;
}
}
}