Julia
Julia

Reputation: 65

Applying blur filter to freeform areas

I have to build a flash application for simple wrinkle retouching. The user should be able to upload a portrait photo, select the wrinkled areas and then a blur filter will be applied to the selected parts. My question is - is it somehow possible to apply the filter to a freeform area? I know it would be easy to make the selection rectangular, but that would not be very useful to really mark the correct areas. Ideally the user should get some kind of round brush to use for marking the areas, press "OK" and then the filter will be applied. Is there any way to do this? And do you maybe have some further recommendations on how to approach this task? I have very little experience with manipulating bitmap data with ActionScript.

Any help is appreciated! Thanks very much in advance :-)

Example of how what it should look like..

Upvotes: 0

Views: 652

Answers (1)

Michael Antipin
Michael Antipin

Reputation: 3532

The algorithm is as follows:

  1. create a BitmapData of selection shape using BitmapData.draw() (let it be A)
  2. cut a rectangular piece of original image that is covered by selection area, add some margins for blurred area using Bitmapdata.copyPixels() (let it be B).
  3. remove all pixels from B, that are not covered by shape A with BitmapData.threshold() using A as source bitmap.
  4. blur the resulting image
  5. copy blurred pixels back to target image using Bitmapdata.copyPixels()

Here's a complete and working example.
I've written the code anyway while figuring out the solution.
Hope you find it usefull.

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("https://i.sstatic.net/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);
        }        
    }
}

Upvotes: 3

Related Questions