2012-06-18 3 views
1

В настоящее время я работаю над алгоритмом горизонтального размытия в javascript, хотя я сомневаюсь, что язык имеет значение.Странные результаты, сочетающие цвета

Я получаю данные с холста, который в основном представляет собой огромный массив, где каждые четыре значения (RGBA) обозначают один пиксель. Значение может содержать int от 0 до 255.

Когда я размываю изображение, область между двумя разными цветами превращается в странные цвета! Я нарисовал красный прямоугольник на черном фоне. Используя приведенный ниже алгоритм, я получаю следующий результат (размер 4px):

4px undesired result

Хотя, когда использование размер 1 или 2 пикселя, кажется, что все работает нормально.

2px desired result

Пожалуйста, обратите внимание, что это несколько неаккуратно накопление. Я планирую сделать все ООП!

// s: size 
// w: width 
// h: height 
function blur(s, w, h) { 
    var src = ctx.getImageData(0, 0, w, h); // get imagedata from source 
    var dst = ctx.createImageData(w, h); // create imagedata for dest 
    var x, y, xo, index, rgb; // predefine vars 

    // loop through y axis 
    for(y = 0; y < h; y++) { 
     // loop through x axis 
     for(x = 0; x < w; x++) { 
      rgb = 0; // set total to 0 

      // loop through area around current pixel 
      for(xo = 0 - s; xo <= s; xo++) { 
       // get specific index 
       index = getIndex(x + xo, y, w); 

       // add nothing if the value doesn't exist (borders) 
       // if(isNaN(src.data[index])) continue; 
       if(typeof src.data[index] === 'undefined') continue; 

       // add the values to total 
       rgb += (src.data[index] << 16) + (src.data[index + 1] << 8) + src.data[index + 2]; 
      } 

      // get the average of all pixels in that area 
      rgb = rgb/(s * 2 + 1); 

      // get index of current pixel 
      index = getIndex(x, y, w); 

      // set pixel in dest 
      dst.data[index] = (rgb & 0xff0000) >> 16; // red 
      dst.data[index + 1] = (rgb & 0x00ff00) >> 8; // green 
      dst.data[index + 2] = (rgb & 0x0000ff);  // blue 
      dst.data[index + 3] = 255; // alpha 
     } 
    } 

    // add the new image data 
    ctx.putImageData(dst, 0, 0); 
} 

function getIndex(x, y, w) { 
    // calculate the appropriate index, since every pixel has 4 array values 
    return (y * (w * 4) + (x * 4)); 
} 

Так , что случилось с моим алгоритмом? Я немного потерян. Обратите внимание, что я не ищу существующие объекты/библиотеки/файлы для размытия холста. Мне нравится изобретать все, чтобы воспитывать себя.


Edit: Я также хотел бы добавить, что значения я получаю обратно действительно ценности, которые представляют цвета, показанные на холсте. Это означает, что это определенно просчет в моем алгоритме.

+0

Вам также необходимо предоставить код функции 'getIndex'. – lanzz

+0

@lanzz Я добавил фрагмент! –

+0

Вы уверены, что isNaN? Это выглядит странно, поскольку данные являются целыми числами, и я уверен, что ваш индекс просто перейдет к следующей строке, если вы заходите слишком далеко справа. Тестирование isNaN по целому числу, вероятно, является случайным. –

ответ

2

Вы должны усреднять свои каналы отдельно. Разделение упакованного трехканального значения вряд ли будет поддерживать каждый канал в его байте.

+0

Да. Я был слишком медленным, чтобы добраться до этой линии, но это хорошее объяснение. Кроме того, даже вычисление среднего значения на трех каналах обычно дает плохие результаты: лучше использовать другую систему цветов, такую ​​как HSL. –

+0

конечно! Я такой идиот, это полностью сработало. Благодаря! –

2

Среднее между 0x030000 (темно-красный) и 0x000000 (черный) становится 0x018000, который получает много зеленого (0x80) Вы должны усреднять каналы отдельно.

+0

lanzz было слишком быстро! повезет в следующий раз ;) –

Смежные вопросы