参考:/blog/post/%E5%9B%BE%E5%83%8F%E4%B9%8B%E9%AD%94%E6%A3%92%E5%B7%A5%E5%85%B7%E5%AE%9E%E7%8E%B0.html
用as简单做了一下,没有用颜色的灰度值来比较,而是直接使用ARGB分量。
源码:
用到了PNGEncoder和bit01组件库。
package
{
import com.adobe.images.PNGEncoder;
import com.bit101.components.ColorChooser;
import com.bit101.components.ScrollPane;
import com.bit101.components.Slider;
import com.bit101.components.Style;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.SimpleButton;
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;
import flash.text.TextField;
import flash.utils.ByteArray;
public class Main extends MovieClip
{
public var dktpBtn:SimpleButton;
public var ktBtn:SimpleButton;
public var cxBtn:SimpleButton;
public var bcBtn:SimpleButton;
public var tf1:TextField;
public var tf20:TextField;
public var tf21:TextField;
public var tf22:TextField;
public var tf23:TextField;
public var timeTf:TextField;
public var pen:MovieClip;
private var panel:ScrollPane;
private var slider:Slider;
private var bmpCon:Sprite;
private var colorCube:Shape;
private var colorPicker:ColorChooser;
private var fileRefrence:FileReference = new FileReference();
private var fileFilter:FileFilter = new FileFilter("图片文件(*.jpg,*.png,*.gif)", "*.jpg;*.png;*.gif");
private var ld:Loader = new Loader();
private var bmd:BitmapData;
private var pickedColor:uint;
private var fileName:String;
private var arr:Array = [];
private var max_cx:int = 10; //最大撤销次数
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);
Style.fontSize = 11;
Style.embedFonts = false;
Style.fontName = 'Microsoft YaHei';
panel = new ScrollPane(this, 0, 0);
panel.setSize(800, 600);
slider = new Slider(Slider.HORIZONTAL, this, 845, 380, sliderChanged);
slider.maximum = 2;
slider.minimum = 0.3;
bmpCon = new Sprite();
panel.content.addChild(bmpCon);
bmpCon.name = "bmpCon";
colorCube = new Shape();
addChild(colorCube);
colorCube.x = tf1.x + tf1.width;
colorCube.y = tf1.y;
colorPicker = new ColorChooser(this, 890, 440, 0xffffff, bgColorChanged);
colorPicker.usePopup = true;
bgColorChanged(null);
pickedColor = 0x00000000;
updateColor();
slider.value = 1;
pen.mouseEnabled = false;
pen.visible = false;
addChild(pen);
tf20.restrict = "0-9";
tf20.maxChars = 3;
tf21.restrict = "0-9";
tf21.maxChars = 3;
tf22.restrict = "0-9";
tf22.maxChars = 3;
tf23.restrict = "0-9";
tf23.maxChars = 3;
addEventListener(MouseEvent.CLICK, clickHandler);
fileRefrence.addEventListener(Event.SELECT, fileHandler);
fileRefrence.addEventListener(Event.COMPLETE, fileHandler);
ld.contentLoaderInfo.addEventListener(Event.COMPLETE, onImgLoaded);
addEventListener(Event.ENTER_FRAME, enterFramehandler);
}
private function bgColorChanged(e:Event):void
{
panel.color = colorPicker.value;
}
/**
* enterFrame
* @param e
*/
private function enterFramehandler(e:Event):void
{
pen.x = mouseX;
pen.y = mouseY;
}
/**
* 图片加载完成
* @param e
*/
private function onImgLoaded(e:Event):void
{
fileName = fileRefrence.name;
arr = [];
var bmp:Bitmap = ld.content as Bitmap;
bmd = bmp.bitmapData;
updateBmd(true);
}
/**
* 更新图片显示
* @param initFlag 是否更新位置及缩放状态
*/
private function updateBmd(initFlag:Boolean = false):void
{
clear(bmpCon);
bmpCon.addChild(new Bitmap(bmd));
if (initFlag)
{
slider.value = 1;
sliderChanged(null);
}
}
/**
* 清空显示容器
* @param con
*/
private function clear(con:DisplayObjectContainer):void
{
while (con.numChildren)
{
con.removeChildAt(0);
}
}
/**
* 浏览打开图片管理
* @param e
*/
private function fileHandler(e:Event):void
{
switch (e.type)
{
case Event.SELECT:
fileRefrence.load();
break;
case Event.COMPLETE:
ld.loadBytes(fileRefrence.data);
break;
}
}
/**
* 点击管理
* @param e
*/
private function clickHandler(e:MouseEvent):void
{
switch (e.target.name)
{
case "dktpBtn":
fileRefrence.browse([fileFilter]);
break;
case "ktBtn":
pen.visible = !pen.visible;
break;
case "cxBtn":
revoke();
break;
case "bcBtn":
save();
break;
case "bmpCon":
if (pen.visible)
{
matting();
}
break;
default:
break;
}
}
private var neighbor:Array = [[0, -1], [0, 1], [-1, 0], [1, 0]];
/**
* 抠图,本程序的核心算法
*/
private function matting():void
{
if (!bmd)
return;
//拾取颜色
var p:Point = new Point(stage.mouseX, stage.mouseY);
p = bmpCon.globalToLocal(p);
pickedColor = bmd.getPixel32(p.x, p.y);
updateColor();
var obj:Object = colorResolve(pickedColor);
var thresholdObj:Object = {};
thresholdObj.a = int(tf20.text);
thresholdObj.r = int(tf21.text);
thresholdObj.g = int(tf22.text);
thresholdObj.b = int(tf23.text);
var _w:int = bmd.width;
var _h:int = bmd.height;
arr.push(bmd.clone());
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(p.x, p.y);
bmd.setVector(rect, vec);
timeTf.text = "用时" + (new Date().getTime() - t) + "ms";
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 obj2:Object = colorResolve(pixel);
if (comparison(obj2))
{
vec[index] = 0x00000000;
for (var i:int = 0; i < 4; i++)
{
var nei:Array = neighbor[i];
stack.push(_x + nei[0], _y + nei[1]);
}
}
}
}
}
} //end
function comparison(obj2:Object):Boolean
{
var a:int;
a = obj2.a - obj.a;
a = a < 0 ? a * -1 : a;
if (a > thresholdObj.a)
return false;
a = obj2.r - obj.r;
a = a < 0 ? a * -1 : a;
if (a > thresholdObj.r)
return false;
a = obj2.g - obj.g;
a = a < 0 ? a * -1 : a;
if (a > thresholdObj.g)
return false;
a = obj2.b - obj.b;
a = a < 0 ? a * -1 : a;
if (a > thresholdObj.b)
return false;
return true;
}
}
/**
* 撤销
*/
private function revoke():void
{
if (arr.length)
{
bmd = arr.pop();
updateBmd();
}
}
var file4save:FileReference = new FileReference();
/**
* 保存
*/
private function save():void
{
if (bmd)
{
var bytes:ByteArray;
bytes = PNGEncoder.encode(bmd);
file4save.save(bytes, fileName.split(".")[0] + ".png");
}
}
/**
* 拾取颜色
*/
private function pickColor():void
{
var p:Point = new Point(stage.mouseX, stage.mouseY);
p = bmpCon.globalToLocal(p);
pickedColor = bmd.getPixel32(p.x, p.y);
updateColor();
}
/**
* 拖动滑块对图片进行缩放
* @param e
*/
private function sliderChanged(e:Event):void
{
bmpCon.scaleX = bmpCon.scaleY = slider.value;
panel.update();
}
/**
* 更新拾取的颜色值
*/
private function updateColor():void
{
var obj:Object = colorResolve(pickedColor);
tf1.text = pickedColor.toString(16);
colorCube.graphics.clear();
colorCube.graphics.lineStyle(0, 0x000000);
colorCube.graphics.beginFill(obj.c, obj.a / 255);
colorCube.graphics.drawRect(0, 0, 14, 14);
colorCube.graphics.endFill();
}
/**
* 颜色值分解
* @param co
* @return
*/
private function colorResolve(co:uint):Object
{
var obj:Object = {};
obj.a = co >> 24 & 0xff;
obj.r = co >> 16 & 0xff;
obj.g = co >> 8 & 0xff;
obj.b = co & 0xff;
obj.c = co & 0xffffff;
return obj;
}
}
}效果如下:
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。