2012-05-03 4 views
0

Мне нужно создать флеш-приложение для простой ретуширования морщин. Пользователь должен иметь возможность загружать портретную фотографию, выбирать морщинистые области, а затем на выбранные части будет применен фильтр размытия. Мой вопрос: возможно ли применить фильтр к области свободной формы? Я знаю, что было бы легко сделать выбор прямоугольником, но это не очень полезно, чтобы пометить правильные области. В идеале пользователь должен получить какую-то круглую кисть для обозначения областей, нажмите «ОК», а затем фильтр будет применен. Есть ли способ сделать это? Возможно, у вас есть несколько рекомендаций относительно того, как подойти к этой задаче? У меня очень мало опыта в манипулировании растровыми данными с помощью ActionScript.Применение фильтра размытия для областей свободной формы

Любая помощь приветствуется! Большое спасибо заранее :-)

Example of how what it should look like..

ответ

3

алгоритм выглядит следующим образом:

  1. создать растровую форму выбора с помощью BitmapData.draw() (пусть это будет А)
  2. вырезать прямоугольный кусок исходного изображения, которое покрывается областью выделения, добавьте некоторые поля для размытой области, используя Bitmapdata.copyPixels() (пусть это будет B).
  3. удалите все пиксели из B, которые не покрыты формой A, с BitmapData.threshold() с использованием A в качестве исходного растрового изображения.
  4. размывает полученное изображение
  5. копии размытых пикселей обратно целевым изображение с использованием Bitmapdata.copyPixels()

Вот полный и рабочим пример.
Я все-таки написал код, выясняя решение.
Упование вы считаете полезным.

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); 
     }   
    } 
} 
Смежные вопросы