将模糊滤镜应用于自由形状区域

时间:2012-05-03 10:48:52

标签: actionscript-3 flash

我必须为简单的皱纹修饰构建一个flash应用程序。用户应该能够上传肖像照片,选择褶皱区域,然后将模糊滤镜应用于所选部分。我的问题是 - 是否可以将过滤器应用于自由形式区域?我知道选择矩形会很容易,但这对于真正标记正确的区域并不是很有用。理想情况下,用户应该使用某种圆形笔刷来标记区域,按“确定”然后应用过滤器。 有没有办法做到这一点?您是否可以获得有关如何处理此任务的进一步建议?我对使用ActionScript操作位图数据的经验很少。

任何帮助表示赞赏!非常感谢提前: - )

Example of how what it should look like..

1 个答案:

答案 0 :(得分:3)

算法如下:

  1. 使用BitmapData.draw()创建一个选择形状的BitmapData(让它成为A)
  2. 剪切由选区覆盖的矩形原始图像,使用Bitmapdata.copyPixels()为模糊区域添加一些边距(让它为B)。
  3. 使用A作为源位图,删除B中未被形状A覆盖的所有像素BitmapData.threshold()
  4. 模糊生成的图像
  5. 使用Bitmapdata.copyPixels()
  6. 将模糊像素复制回目标图像

    这是一个完整而有效的例子 在找出解决方案时,我还是编写了代码 希望你发现它很有用。

    package
    {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Loader;
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.filters.BlurFilter;
        import flash.geom.Matrix;
        import flash.geom.Point;
        import flash.geom.Rectangle;
        import flash.net.URLRequest;
        import flash.system.LoaderContext;
    
        [SWF(width="800", height="600",backgroundColor="#FFFFFF")]    
        public class TestBlur extends Sprite
        {
            private const loader:Loader = new Loader();
    
            public function TestBlur()
            {
                stage.align = StageAlign.TOP_LEFT;
                stage.scaleMode = StageScaleMode.NO_SCALE;
    
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
                loader.load(new URLRequest("http://i.stack.imgur.com/u3iEv.png"), new LoaderContext(true));
            }
    
            protected function onLoadComplete(event:Event):void
            {
                trace(event);
                var bmp:Bitmap = loader.content as Bitmap;
                addChild(bmp);
    
                // create some test selection area
                var selection:Shape = new Shape();
                selection.graphics.lineStyle(30, 0xFF0000, .5);
                selection.graphics.curveTo(75, -50, 200, 10);
                selection.x = 40;
                selection.y = 60;
                addChild(selection);
    
                // create a duplicate of the original image
                var target:BitmapData = bmp.bitmapData.clone();
                var targetBmp:Bitmap = new Bitmap(target);
                targetBmp.x = bmp.x + bmp.width;
                addChild(targetBmp);
    
                //
                // *** main work starts here ***
                // by now we have selection shape and a bitmap to blur
    
                const destPoint:Point = new Point();
                const drawMatrix:Matrix = new Matrix();
                const blurMargin:uint = 10;
                const blur:BlurFilter = new BlurFilter(2, 2, 3);
                var rect:Rectangle;
    
                // 0: prepare an image of selection area
                // we'll need it at step 3
                rect = selection.getBounds(selection);
                rect.x -= blurMargin;
                rect.y -= blurMargin;
                rect.width += blurMargin*2;
                rect.height += blurMargin*2;            
                var selectionImage:BitmapData = new BitmapData(rect.width, rect.height, true, 0);
                drawMatrix.identity();
                drawMatrix.translate(-rect.x, -rect.y);
                selectionImage.draw(selection, drawMatrix);
    
                        // just some testing
                        var test0:Bitmap = new Bitmap(selectionImage.clone());
                        test0.y = bmp.y + bmp.height;
                        addChild(test0);
    
                // 1: cut a rectangular piece of original image that is covered by selection area
                rect = selection.getBounds(selection.parent);
                rect.x -= blurMargin;
                rect.y -= blurMargin;
                rect.width += blurMargin*2;
                rect.height += blurMargin*2;
                var area:BitmapData = new BitmapData(rect.width, rect.height, true, 0);
                area.copyPixels(bmp.bitmapData, rect, destPoint);
    
                        // just some testing
                        var test1:Bitmap = new Bitmap(area.clone());
                        test1.y = bmp.y + bmp.height;
                        test1.x = test0.x + test0.width;
                        addChild(test1);
    
                // 2: remove all pixels that are not covered by selection
                area.threshold(selectionImage, area.rect, destPoint, "==", 0, 0, 0xFF000000);
    
                        // just some testing
                        var test2:Bitmap = new Bitmap(area.clone());
                        test2.y = test0.y + test0.height;
                        test2.x = test0.x;
                        addChild(test2);
    
                // 3: blur copied area
                area.applyFilter(area, area.rect, destPoint, blur);
    
                        // just some testing
                        var test3:Bitmap = new Bitmap(area.clone());
                        test3.y = test0.y + test0.height;
                        test3.x = test2.x + test2.width;
                        addChild(test3);
    
                // 4: copy blurred pixels back to target image
                destPoint.x = rect.x;
                destPoint.y = rect.y;
                target.copyPixels(area, area.rect, destPoint);
            }        
        }
    }