参考:/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; } } }
效果如下:
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。