2011-03-05 115 views
3

我在as3中構建繪圖應用程序,並且在畫筆上出現羽化或模糊邊緣問題。我使用bitmapData.draw()繪製筆刷,但在繪製速度緩慢時,邊緣周圍會看到較深的彩色區域。AS3 - bitmapData邊緣alpha透明問題

我試過很多選項,包括設置所有涉及到cacheAsBitmap = true的顯示對象,使用copyPixels而不是繪製,模糊濾鏡與漸變填充... 都無濟於事。

以下課程說明了我的問題。我已經包含了一個可以正常工作但沒有羽化邊緣的solid()方法,一個顯示相同問題的gradient()方法和一個filter()方法,並且onMove2使用copyPixels()並且同樣存在問題。

有什麼我可以做的,以解決這個問題?我真的不希望進入使用pixelbender着色器這麼簡單的東西...

package test { 
    import flash.display.*; 
    import flash.events.*; 
    import flash.filters.*; 
    import flash.geom.*; 

    public class Sucks extends Sprite { 

     private var brush:Sprite; 
     private var brushMap:BitmapData; 
     private var bmd:BitmapData; 
     private var radius:Number = 50; 
     private var color:uint = 0x990000; 


     public function Sucks() { 
      brush = new Sprite(); 
      brushMap = new BitmapData(radius*2, radius*2, true, 0x00ffffff); 
      bmd = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x0); 
      var bmp:Bitmap = new Bitmap(bmd, PixelSnapping.ALWAYS, true); 
      addChild(bmp); 

      //solid();   
      gradient(); 
      //filter(); 
      brushMap.draw(brush, new Matrix(1, 0, 0, 1, radius, radius)); 

      stage.addEventListener(Event.ENTER_FRAME, onMove); 
     } 

     private function solid():void { 
      brush.graphics.beginFill(color, 1); 
      brush.graphics.drawCircle(0, 0, radius); 
      brush.graphics.endFill(); 
     } 

     private function gradient():void { 
      var m:Matrix = new Matrix(); 
      m.createGradientBox(radius*2, radius*2, 0, -radius, -radius); 
      brush.graphics.beginGradientFill(GradientType.RADIAL, [color, color], [1, 0], [0, 250], m); 
      brush.graphics.drawCircle(0, 0, radius); 
      brush.graphics.endFill(); 
     } 

     private function filter():void { 
      solid(); 
      brush.filters = [new BlurFilter(8, 8, 3)]; 
     } 

     private function onMove(e:Event):void { 
      var mp:Matrix = new Matrix(); 
      mp.tx = mouseX; 
      mp.ty = mouseY; 
      bmd.draw(brush, mp); 
      //bmd.applyFilter(bmd, new Rectangle(0, 0, stage.stageWidth, stage.stageHeight), new Point(), new BlurFilter(2, 2, 3)); 
     } 

     private function onMove2(e:Event):void { 
      bmd.copyPixels(brushMap, new Rectangle(0, 0, radius*2, radius*2), new Point(mouseX-radius, mouseY-radius), null, null, true); 
     } 

    } 

} 

回答

2

您的問題是由Flash使用預乘alpha的事實引起的。通常這不是一個大問題,但是如果您的像素值具有非常低的阿爾法值,則非常明顯,不幸的是,當您使用模糊的軟毛羽筆刷時,該像素值非常常見。

預乘法會導致像素中的信息丟失 - 當您的alpha值較低時,顏色值會變爲四捨五入,這樣當您在應用程序中緩慢繪製顏色值並且相同像素彼此相對時,一次又一次將導致該地區變得越來越黑暗。

有關預乘問題的更多細節檢查舊的文章我的:http://www.quasimondo.com/archives/000665.php

沒有什麼可以做這個除非你處理alpha通道,並分別對RGB通道。但是,你還必須自己做所有的合成,這不是一項微不足道的任務,並且可能會讓你的應用程序變得太慢。

1

我很驚訝的是,BlurFilter沒有工作。過去我很幸運。可能值得玩Flex Filter Explorer以查看設置是否需要調整。

你可以嘗試的另一件事是繪製幾個同心圓與透明度和減少半徑來模擬有模糊的邊緣。

+0

這是一個好主意,但也有不規則形狀的刷子難以同心創建。看起來,任何模糊的形狀,當繪製到位圖時受到這些小文物 – 2011-03-06 15:28:22

0

如果刷顏色是堅實的,你可以用發光濾鏡嘗試爲好,精確的設置也可以實現

+0

我只是試了一下,但GlowFilter有同樣的問題 – 2011-03-07 16:49:41

0

我相信這是enterFrame事件更多的問題比它與你的邏輯。我注意到,如果您將enter_frame處理程序更改爲mouse_move處理程序,它會更好。使用enter_frame的問題在於你一遍又一遍地繪製相同的項目 - 自然有它自己的工件 - 所以在600次繪製之後,它將開始顯示那些工件。我認爲使用mouse_move會更好。

如果你不得不使用enter_frame,我會建議列出enter_frame和mouse_move,並且大大減少enter_frames的draw的不透明度。

這很好地爲我工作:

stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove); 
+0

聽老鼠移動有同樣的問題,只是不太明顯。在我的實際代碼中,我將在最後一個鼠標點和當前點之間進行插值,以便間隔正確分隔。但是無論間距如何,工件總是存在的,只是程度較小。 – 2011-03-07 19:59:20

+0

我看到你的問題 - 那個很爛的人。看起來Flash是真的把你搞砸了 - 看起來像blurfilter吮吸/和/或預倍alpha? ....嘗試改變你的模糊質量爲1 - 這似乎使很多文物....但我認爲最終,你將不得不創建自己的着色器... – ansiart 2011-03-07 20:47:47

+0

這就是我害怕。我現在在着色器上工作:s – 2011-03-07 20:53:57

0

我不知道這是否有什麼關係呢,但你在設置透明度,但你的BitmapData不是透明的。

brushMap = new BitmapData(radius*2, radius*2, true, 0x00ffffff); 

brushMap = new BitmapData(radius*2, radius*2, true, 0); 

同時,嘗試改變的pixelSnapping。 ALWAYS值爲PixelSnapping。 從不,但我想你已經嘗試過。

+0

brushMap僅用於onMove2 copyPixels()調用。由於其ARGB,0x00ffffff和0x0幾乎相同。無論如何,這與問題無關。沒有像pixelSnapping運氣,我試過所有的設置...真的希望我能找到一個簡單的解決方案 – 2011-03-08 20:49:42

0

更改畫筆的cacheAsBitmap屬性爲true。

brush.cacheAsBitmap = true; 

sprite將作爲位圖而不是矢量保存在內存中,所以繪製時它會更準確地映射像素。