2010-03-31 3 views
1

Я делаю небольшое приложение, где дети могут заполнять предварительно установленные иллюстрации цветами. Я успешно реализовал ковш краски стиля MS-paint, используя алгоритм заполнения заливки. Однако вблизи краев элементов изображения пиксели остаются незаполненными, потому что линии сглажены. Это связано с тем, что текущее условие для заполнения - colourAtCurrentPixel == colourToReplace, которое не работает на смешанных пикселях на линиях. (цвета RGB uints)Мягкая краска Заполнитель: Цветное равенство

Я хотел бы добавить вариант сглаживания/подбора, например, в 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

Спасибо, что я делаю что-то вроде этого сейчас. См. Мой ответ –

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