選択範囲の境界線を描くまで
- 2010 年 8月 12 日
Photoshopで選択範囲を取ったときの点線の輪郭線を描きたくて試した方法。
輪郭線を描きたい対象を透明なBitmapDataにdrawする。
輪郭を得るために一旦このBitmapDataを透明と黒100%で二値化する。
var rect:Rectangle = new Rectangle( 0, 0, 200, 200 ); var master:BitmapData = new BitmapData( rect.width, rect.height, true, 0x00000000 ); var pt:Point = new Point(); master.draw( container ); master.threshold( master, rect, pt,">",0x00000000, 0xFF000000, 0xFFFFFFFF, false ); |
エッジ部分のアンチエイリアスも含めて輪郭としたかったんで、ここでは透明以外のピクセルはすべて黒100%にしているけど0x00000000を変更すれば、輪郭に含むアンチエイリアスの許容値を調整できる。
元の文字と二値化した文字。
二値化したBitmapDataを複製しておく。元のBitmapDataにConvolutionFilterを適用。
以下のマトリックスで適用すると境界の内側、外側に1ピクセルずつ不透明ピクセルが出来て滲んだ画像になる。ConvolutionFilterって前にエントリー書いたけど、なるほどこんなケースで使えるんだなぁと思いました。
var convolution:ConvolutionFilter = new ConvolutionFilter( 3,3, [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ], 9, 0, false ); var clone:BitmapData = master.clone(); master.applyFilter( master, rect, pt, convolution ); master.draw( clone ); |
次に滲んだBitmapDataに複製しておいたBitmapDataをdrawする。これで輪郭の外側1ピクセルが滲んだ状態になる。
輪郭の内側・外側が滲んだ文字と、輪郭の外側が滲んだ文字。
輪郭の外側の滲んだ部分が選択範囲の境界線として使いたい部分なのでこれを取り出す。
BitmapDataに対し今度は黒100%の部分を透明に置き換えた後、再度、透明と黒100%で二値化する。
master.threshold( master, rect, pt,"==",0xFF000000, 0x00000000, 0xFFFFFFFF, false ); master.threshold( master, rect, pt,">" ,0x00000000, 0xFF000000, 0xFFFFFFFF, false ); |
これで選択範囲の境界線が出来た。
続いてチカチカ流れる部分。これ一時悩んだのですが(輪郭を時計回りに回っているものだと思った)よく見ると水平線は左から右へ、垂直線は上から下へ流れているだけ。難しく考え過ぎてた。斜めの線動かせばいんじゃない?ってYさんの一言で気づいた。
斜め線のパターンを作ってBitmapDataのサイズ同じサイズでShapeを塗りつぶす。
var b:uint = 0xFF000000; var pattern:BitmapData = new BitmapData( 6,6, true, 0x00000000 ); pattern.setVector( new Rectangle( 0,0,6,6 ), Vector.<uint>([ 0,0,0,b,b,b, 0,0,b,b,b,0, 0,b,b,b,0,0, b,b,b,0,0,0, b,b,0,0,0,b, b,0,0,0,b,b ]) ); var shape:Shape = new Shape(); var g:Graphics = shape.graphics; g.beginBitmapFill( pattern ); g.drawRect( 0,0, rect.width, rect.height ); |
選択範囲の境界線と斜め線のパターン。
あとは斜め線のパターンを1ピクセルずつ動かしながら選択範囲の境界線に合成すれば、Photoshop風の点線境界線の完成です。
var matrix:Matrix = new Matrix(); addEventListener( Event.ENTER_FRAME, function(e:Event):void{ matrix.tx = ( matrix.tx + 1 ) % 6; g.clear(); g.beginBitmapFill( pattern, matrix ); g.drawRect( 0,0, rect.width, rect.height ); outline.fillRect( rect, 0 ); outline.draw( master ); outline.draw( shape, null, null, BlendMode.ALPHA ); }); |