Javascript: преобразование HSV в RGB, вывод правильный, но перемешанный - PullRequest
0 голосов
/ 28 ноября 2018

Я построил функцию для преобразования RGB в HSV, используя формулу, найденную в Wikipedia .В то время как числа в выводе кажутся правильными, их положение постоянно меняется в зависимости от того, кто из них больше.

Примеры:

   Given HSV: [204, 100,  94]
Expected RGB: [  0, 144, 240]
  Output RGB: [240,   0, 144]

   Given HSV: [240, 100,  94]
Expected RGB: [  0,   0, 240]
  Output RGB: [240,   0,   0]

   Given HSV: [120, 100,  94]
Expected RGB: [  0, 240,   0]
  Output RGB: [240,   0,   0]

И это только правильно, потому что красный цвет оказывается наибольшим числом:

   Given HSV: [  0, 100,  94]
Expected RGB: [240,   0,   0]
  Output RGB: [240,   0,   0]

Вот функция:

function hsvRGB(h, s, v) {
    h /= 60, s /= 100, v /= 100;    // Convert [deg, %, %] to ranges 0-6, 0-1, 0-1

    var r, g, b;                    // Set up for later
    var r1, g1, b1;                 // Set up for later

    var c = v*s;                    // Chroma

    var x = c*(1-Math.abs(h%2-1));

    if ( h <= 0 )       [r1, g1, b1] = [0, 0, 0];
    if ( 0 <= h <= 1 )  [r1, g1, b1] = [c, x, 0];
    if ( 1 < h <= 2 )   [r1, g1, b1] = [x, c, 0];
    if ( 2 < h <= 3 )   [r1, g1, b1] = [0, c, x];
    if ( 3 < h <= 4 )   [r1, g1, b1] = [0, x, c];
    if ( 4 < h <= 5 )   [r1, g1, b1] = [x, 0, c];
    if ( 5 < h <= 6 )   [r1, g1, b1] = [c, 0, x];
    var m = v-c;
    [r, g, b] = [r1 + m, g1 + m, b1 + m];

    return [r*255, g*255, b*255];   // Output 0-255 instead of 0-1
}

Я проверял и перепроверил свою функцию по формуле в Википедии, и я не вижу ничего, что она делает, что янет, но я смотрю на это так долго, что мне может понадобиться вторая пара глаз.

1 Ответ

0 голосов
/ 28 ноября 2018

Во-первых, самая важная проблема заключается в том, что хотя

if ( 0 <= h <= 1 )

выглядит разумно, это не работает так, как можно подумать.Он интерпретируется JavaScript, как если бы он был написан

if ((0 <= h) <= 1)

Операторы сравнения JavaScript возвращают логические результаты, поэтому, хотя он синтаксически правильный, он делает что-то совершенно иное, чем проверка, находится ли h между0 и 1.

Поскольку алгоритм использует угол H входного значения для выбора между одним из шести различных сценариев, все это можно сделать немного проще с помощью switch утверждение (как упомянуто в комментарии к вопросу).Во-первых, код, как написано, обрабатывает случай отрицательного h, что нормально, но, поскольку это угловое значение, можно просто принудительно ввести его в диапазон [0, 360):

function hsvRGB(h, s, v) {
    while (h < 0) h += 360; // could be smarter but just for illustration
    h = h % 360;
    h /= 60, s /= 100, v /= 100;    // Convert [deg, %, %] to ranges 0-6, 0-1, 0-1

Так что теперь h находится между 0 и 6;это может быть 0, но никогда не будет точно 6.Затем мы можем использовать switch, чтобы различать случаи:

    switch (Math.floor(h)) {
      case 0: [r1, g1, b1] = [c, x, 0]; break;
      case 1: [r1, g1, b1] = [x, c, 0]; break;
      case 2: [r1, g1, b1] = [0, c, x]; break;
      case 3: [r1, g1, b1] = [0, x, c]; break;
      case 4: [r1, g1, b1] = [x, 0, c]; break;
      case 5: [r1, g1, b1] = [c, 0, x]; break;
    }
...