BitmapDataの境界線指定による2値化
/**
* Copyright okoi ( http://wonderfl.net/user/okoi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/nuUQ
*/
//
// BitmapData画像のある色を境界にして2値化する処理
// 今回は白色と透明で区切りたかったためByteArrayとSetPixelsを利用してpaletteMapと同じような処理を再現している
// スライダーを動かすと境界の位置を変更
// CheckBoxをクリックすると paletteMapモードとByteArrayモードの切り替えが可能
//
// ※画像が読み込まれるまでしばらくお待ちください
//
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Shape;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Point;
import flash.system.Security;
import flash.geom.Matrix;
import flash.utils.ByteArray;
import com.bit101.components.HSlider;
import com.bit101.components.Label;
import com.bit101.components.CheckBox;
[SWF(width = "465", height = "465", frameRate="60")]
/**
* ...
* @author
*/
public class Main extends Sprite
{
public static const WIDTH:int = 465;
public static const HEIGHT:int = 465;
private var imagewaku:Shape;
private var image:Image;
private var canvas:BitmapData = null;
private var bmp:Bitmap;
private var step:Number;
private var slider:HSlider;
private var label:Label;
private var check:CheckBox;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
graphics.beginFill(0xa9a9a9);
graphics.drawRect(0, 0, WIDTH, HEIGHT);
graphics.endFill();
for ( var y:int = 0; y < 5; y++ )
{
for ( var x:int = 0; x < 5; x++ )
{
if ( (5 * y + x) % 2 != 0 ) continue;
graphics.beginFill(0xc0c0c0);
graphics.drawRect(x * (WIDTH / 5), y * (HEIGHT / 5), (WIDTH / 5), (HEIGHT / 5));
graphics.endFill();
}
}
Security.allowDomain("assets.wonderfl.net");
Security.loadPolicyFile("http://assets.wonderfl.net/crossdomain.xml");
image = new Image("http://assets.wonderfl.net/images/related_images/6/6d/6dff/6dff50d5157b019ea6c42bb4b046a7419557277d", CreateCanvas );
imagewaku = new Shape();
addChild( imagewaku );
bmp = new Bitmap();
addChild( bmp );
step = 0;
// スライダー
slider = new HSlider( this, 0, 0, MoveSliderHandler );
slider.width = 300;
slider.height = 20;
slider.x = 25;
slider.y = HEIGHT - 80;
slider.setSliderParams( 0, 256, 0 );
// ラベル
label = new Label( this, 0, 0, slider.value + "" );
label.autoSize = true;
label.scaleX = 2;
label.scaleY = 2;
label.x = 335;
label.y = HEIGHT - 90;
// チェックボックス
check = new CheckBox(this, 0, 0, "ByteArrayMode", CheckBoxHandler);
check.scaleX = 2;
check.scaleY = 2;
check.x = 25;
check.y = HEIGHT - 40;
}
private function MoveSliderHandler( e:Event ) : void
{
if ( e.currentTarget != null && label != null )
{
label.text = e.currentTarget.value + "";
if ( check.selected ) DrawImage2();
else DrawImage();
}
}
private function CheckBoxHandler( e:Event ) : void
{
if ( check.selected ) DrawImage2();
else DrawImage();
}
private function CreateCanvas() : void
{
canvas = new BitmapData( image.image.width, image.image.height, true, 0 );
bmp.bitmapData = canvas;
bmp.x = WIDTH / 2 - canvas.width / 2;
bmp.y = HEIGHT / 2 - canvas.height / 2 - 40;
imagewaku.graphics.lineStyle(1);
imagewaku.graphics.drawRect(bmp.x, bmp.y, canvas.width+1, canvas.height+1);
imagewaku.graphics.endFill();
if ( check.selected ) DrawImage2();
else DrawImage();
}
/**
* 現在のスライダーの値からパレットマップを作成する
* 白色と透明で分断する
* @return
*/
private function CreatePaletteMap() : PaletteMapColorData
{
var map:PaletteMapColorData = new PaletteMapColorData();
for ( var i:int = 0; i < 256; i++ )
{
if ( i >= slider.value )
{
map.r.push( 255 << 24 | 0xFF << 16 | 0xFF << 8 | 0xFF );
map.g.push( 255 << 24 | 0xFF << 16 | 0xFF << 8 | 0xFF );
map.b.push( 255 << 24 | 0xFF << 16 | 0xFF << 8 | 0xFF );
map.a.push( 255 << 24 | 0 | 0 | 0 );
}else
{
map.r.push( 0 | 0 | 0 | 0 );
map.g.push( 0 | 0 | 0 | 0 );
map.b.push( 0 | 0 | 0 | 0 );
map.a.push( 0 | 0 | 0 | 0 );
}
}
return map;
}
/**
* 現在のスライダーの値から絵を変換して描画する
*/
private function DrawImage() : void
{
if ( image.image == null || canvas == null ) return;
canvas.lock();
canvas.fillRect( canvas.rect, 0 );
var map:PaletteMapColorData = CreatePaletteMap();
canvas.paletteMap( image.image, canvas.rect, new Point(), map.r, map.g, map.b, map.a );
canvas.unlock();
}
/**
* 現在のスライダーの値からByteArrayを使ってpaletteMapと同等の処理を行う
*/
private function DrawImage2() : void
{
if ( image.image == null || canvas == null ) return;
var bytes:ByteArray;
var newbytes:ByteArray = new ByteArray();
canvas.lock();
canvas.fillRect( canvas.rect, 0 );
canvas.draw( image.image );
bytes = canvas.getPixels( canvas.rect );
var map:PaletteMapColorData = CreatePaletteMap();
var pixelnum:uint = bytes.length / 4;
bytes.position = 0;
for ( var p:uint = 0; p < pixelnum; p++ )
{
var color:uint = bytes.readUnsignedInt();
var a:uint = (color >> 24) & 0xFF;
var r:uint = (color >> 16) & 0xFF;
var g:uint = (color >> 8) & 0xFF;
var b:uint = (color) & 0xFF;
var alpha:uint = map.a[int((r+g+b)/3)]; // 今回は透明と白で分割したいのでこう表現
var red:uint = map.r[r];
var green:uint = map.g[g];
var blue:uint = map.b[b];
a = (((alpha >> 24) & 0xFF) + ((red >> 24) & 0xFF) + ((green >> 24) & 0xFF) + ((blue >> 24) & 0xFF)) % 256;
r = (((alpha >> 16) & 0xFF) + ((red >> 16) & 0xFF) + ((green >> 16) & 0xFF) + ((blue >> 16) & 0xFF)) % 256;
g = (((alpha >> 8) & 0xFF) + ((red >> 8) & 0xFF) + ((green >> 8) & 0xFF) + ((blue >> 8) & 0xFF)) % 256;
b = (((alpha >> 0) & 0xFF) + ((red >> 0) & 0xFF) + ((green >> 0) & 0xFF) + ((blue >> 0) & 0xFF)) % 256;
color = (a << 24) | (r << 16) | (g << 8) | b;
newbytes.writeUnsignedInt( color );
}
newbytes.position = 0;
canvas.setPixels( canvas.rect, newbytes );
canvas.unlock();
}
}
}
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
/**
* イメージ格納クラス
* @author
*/
class Image
{
public static const MAX_W:int = 400; // 基本サイズ
public static const MAX_H:int = 300; // 基本サイズ
public var width:Number = MAX_W;
public var height:Number = MAX_H;
public var view:Sprite;
protected var baseimg:BitmapData; //元画像データ
private var loader:Loader = null;
private var loaderinfo:LoaderInfo = null;
private var _loadcallback:Function;
public function Image( path:String, loadcallback:Function = null )
{
view = new Sprite();
loader = new Loader();
loaderinfo = loader.contentLoaderInfo;
loaderinfo.addEventListener( Event.COMPLETE, LoadedImageHandler );
loader.load( new URLRequest( path ) );
_loadcallback = loadcallback;
}
protected function LoadedImageHandler( e:Event ) : void
{
loaderinfo.removeEventListener( Event.COMPLETE, LoadedImageHandler );
var scaleX:Number = Math.min( width / loader.width, 1 );
var scaleY:Number = Math.min( height / loader.height, 1 );
var scale:Number = ( scaleX < scaleY ) ? scaleX : scaleY;
width = loader.width * scale;
height = loader.height * scale;
baseimg = new BitmapData( width, height, true, 0 );
baseimg.draw( loader, new Matrix(scale, 0, 0, scale, 0, 0) );
loaderinfo = null;
loader = null;
if ( _loadcallback != null ) _loadcallback();
}
public function get image():BitmapData { return baseimg; }
}
/**
* ...
* @author
*/
class PaletteMapColorData
{
public var r:Array = new Array(); // 赤チャンネル
public var g:Array = new Array(); // 緑チャンネル
public var b:Array = new Array(); // 青チャンネル
public var a:Array = new Array(); // アルファチャンネル
}