2010-03-31 58 views
1

我正在製作一個小應用程序,其中的孩子可以用顏色填充預設插圖。我已經成功地使用洪水填充算法實現了MS-paint風格的油漆桶。但是,在圖像元素的邊緣附近,像素沒有填充,因爲這些線是反鋸齒的。這是因爲當前是否填充的條件是colourAtCurrentPixel == colourToReplace,這對線上的混合像素不起作用。 (顏色是RGB提示)柔軟的油漆桶填充:顏色平等

我想添加一個像Photoshop和其他複雜工具中的平滑/閾值選項,但確定兩種顏色之間的相等/距離的算法是什麼?

if (match(pixel(x,y), colourToReplace) setpixel(x,y,colourToReplaceWith)

如何match填寫()?

這裏,圖像(左爲的情況下,權所需)

alt text http://www.freeimagehosting.net/uploads/6aa7b4ad53.png

這裏是我當前的全碼:

  var b:BitmapData = settings.background; 
      b.lock(); 

      var from:uint = b.getPixel(x,y); 


      var q:Array = []; 


      var xx:int; 
      var yy:int; 
      var w:int = b.width; 
      var h:int = b.height; 
      q.push(y*w + x); 
      while (q.length != 0) { 
       var xy:int = q.shift(); 
       xx = xy % w; 
       yy = (xy - xx)/w; 
       if (b.getPixel(xx,yy) == from) { //<- want to replace this line 
        b.setPixel(xx,yy,to); 
        if (xx != 0) q.push(xy-1); 
        if (xx != w-1) q.push(xy+1); 
        if (yy != 0) q.push(xy-w); 
        if (yy != h-1) q.push(xy+w); 
       } 
      } 
      b.unlock(null); 

回答

1

嗯,我想最自然的方法是計算顏色之間的區別。爲了達到明智的價值,應該計算每個通道的差異。沒有測試過,但下面應該工作:

const perChanThreshold:uint = 5; 
const overallThreshold:uint = perChanThreshold * perChanThreshold * 3; 
function match(source:uint, target:uint):Boolean { 
    var diff:uint = 0, chanDiff:uint; 
    for (var i:int = 0; i < 3; i++) { 
     chanDiff = (source >> (i * 8)) & 0xFF; 
     diff += chanDiff * chanDiff; 
    } 
    return diff <= overallThreshold; 
} 
+1

謝謝,我現在做這樣的事情。看到我的回答 – 2010-03-31 15:01:59

1

製造一些作品:

   c = b.getPixel(xx,yy); 
       if (c == to) continue; 
       if (c != from) d = 
        Math.pow(f1 - (c & 0xFF), 2) + 
        Math.pow(f2 - (c >> 8 & 0xFF), 2) + 
        Math.pow(f3 - (c >> 16 & 0xFF), 2) 
       if (c == from || d < tres) { 
+1

是的,應該完美地工作。 但是請注意,如果您經常打電話(這可能是填充的情況),這不會很好。在浮點數和整數之間來回移動並不是很快,靜態函數調用也不是。 – back2dos 2010-03-31 15:27:06