ps中,选区的边界会生成蚂蚁线。下面我们就来视线一下这种效果。
前面已经介绍过魔棒的原理,用来生成一个选区。也介绍了蚂蚁线的生成。我们只需要在计算魔棒的选区的时候,把边界上的点记录下来,单独生成一张图片,然后用这张图片作为生成蚂蚁线时的遮罩。
源码如下:
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.FileFilter;
import flash.net.FileReference;
public class Main extends MovieClip {
private var bmd:BitmapData;
private var bmpCon:Sprite;
public function Main() {
// constructor code
stage ? initStage(null) : addEventListener(Event.ADDED_TO_STAGE, initStage);
}
private function initStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initStage);
bmd = new Yu();
var bmp:Bitmap = new Bitmap(bmd.clone());
addChild(bmp);
bmp.x = bmp.y = 50;
bmpCon = new Sprite();
addChild(bmpCon);
bmpCon.name = "bmpCon";
bmpCon.y = 430;
bmpCon.x = 50;
var bianyuan:Vector.= matting();
var bmd2:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0xffffff);
bmd2.lock();
var len:int = bianyuan.length;
for (var i:int = 0; i < len;i+=2 ) {
bmd2.setPixel(bianyuan[i], bianyuan[i + 1], 0x000000);
}
bmd2.unlock();
bmpCon.addChild(new Bitmap(bmd2));
var con:Sprite = new Sprite();
addChild(con);
con.x = bmp.x;
con.y = bmp.y;
var antLine:AntLine = new AntLine(bmd.width, bmd.height);
con.addChild(antLine);
var bmd3:BitmapData = new BitmapData(bmd.width, bmd.height, true, 0x00000000);
bmd3.lock();
for (i = 0; i < len;i+=2 ) {
bmd3.setPixel32(bianyuan[i], bianyuan[i + 1], 0xff000000);
}
bmd3.unlock();
var maskmc:Bitmap = new Bitmap(bmd3);
con.addChild(maskmc);
antLine.cacheAsBitmap = true;
maskmc.cacheAsBitmap = true;
antLine.mask = maskmc;
}
private var neighbor:Array = [[0, -1], [0, 1], [-1, 0], [1, 0]];
/**
* 抠图,本程序的核心算法
*/
private function matting():Vector.
{
if (!bmd)
return new Vector.();
var bianyuan:Vector.= new Vector.();
//拾取颜色
var pickedColor:uint = 0xffffffff;
var co1:int = rgb2gray(pickedColor);
var thres:int = 32;
var _w:int = bmd.width;
var _h:int = bmd.height;
var t:Number = new Date().getTime();
var rect:Rectangle = new Rectangle(0, 0, _w, _h);
var vec:Vector.= bmd.getVector(rect);
var vec2:Vector.= new Vector.(_w * _h);
check(10,10);
bmd.setVector(rect, vec);
timeTf.text = "用时" + (new Date().getTime() - t) + "ms";
return bianyuan;
function check(_x:int, _y:int):void
{
var stack:Array = [];
stack.push(_x, _y);
while (true)
{
if (stack.length= 0 && _x < _w && _y >= 0 && _y < _h)
{
var index:int = _x + _y * _w;
if (!vec2[index])
{
vec2[index] = true;
var pixel:uint = vec[index];
var co2:int = rgb2gray(pixel);
var cha:int = co1 - co2;
if (cha < 0) cha = -cha;
if (cha<thres)
{
vec[index] = 0x00000000;
for (var i:int = 0; i < 4; i++)
{
var nei:Array = neighbor[i];
stack.push(_x + nei[0], _y + nei[1]);
}
}
else {
bianyuan.push(_x, _y);//边缘提取,关键在于这句。
}
}
}
}
} //end
}
private function rgb2gray(co:uint):int {
var r:int = co >> 16 & 0xff;
var g:int = co >> 8 & 0xff;
var b:int = co & 0xff;
return (r * 313524 + g * 615514 + b * 119538) >> 20;
}
//end
}
}
import flash.display.Sprite;
import flash.events.Event;
class AntLine extends Sprite {
private var _w:int;
private var _h:int;
public function AntLine(w:int,h:int){
setSize(w,h);
}
public function setSize(w:int, h:int):void {
_w = w;
_h = h;
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private var _offset:Number = 0;
private function enterFrameHandler(e:Event):void
{
_offset += 0.5;
update();
}
private function update():void {
graphics.clear();
graphics.lineStyle(2, 0x000000, 1.0);
var len:int = _w + _h;
var x1:Number = i;
var y1:Number = 0;
var x2:Number = 0;
var y2:Number = i;
_offset = _offset % 6;
for (var i:int = _offset; i < len; i += 6 ) {
x1 = y2 = i;
if (i>_w) {
x1 = _w;
y1 = i - _w;
}
if (i>_h) {
y2 = _h;
x2 = i - _h;
}
graphics.moveTo(x1, y1);
graphics.lineTo(x2, y2);
}
}
}效果:
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。