【问题标题】:Javascript: Converting HSV to RGB, output correct but shuffledJavascript:将 HSV 转换为 RGB,输出正确但已打乱
【发布时间】:2019-04-30 12:52:25
【问题描述】:

我已经使用我在Wikipedia 上找到的公式构建了一个将 RGB 转换为 HSV 的函数。虽然输出中的数字看起来是正确的,但它们的位置会根据哪个更大而不断变化。

例子:

   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
}

我一直在根据 Wikipedia 上的公式检查并重新检查我的函数,但我看不到它所做的任何我看不到的事情,但我已经研究了很长时间,以至于我可能只是需要第二双眼睛。

【问题讨论】:

  • 0 &lt;= h &lt;= 1 没有做它看起来可能做的事情。你想要0 &lt;= h &amp;&amp; h &lt;= 1
  • 你不能在那里也使用if..else if吗?这样你就不需要第一次检查了
  • @Pointy Dang, 0 &lt;= h &lt;= 1 在我单独测试时似乎有效,但我想我测试得不够彻底。你是对的。 @George我不确定我还会使用什么。他们都不是else
  • @TanzNukeTerror 我的意思是做if(h &lt;= o){} else if (h &lt;=1){} etc 然后你就不需要第一部分0 &lt;= h 因为如果是这样的话它会被前一个块捕获
  • @George 哦,我明白了,我以为你的意思是“你不能”就像“你在不应该使用的时候使用它”,我的错。维基百科上的公式大多是直接转换的。一旦它正常工作,我将继续努力。

标签: javascript colors rgb hsv


【解决方案1】:

首先,最重要的问题是,虽然

if ( 0 <= h <= 1 )

看起来很合理,但它并不像人们想象的那样工作。它被 JavaScript 解释为好像它是编写的一样

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

JavaScript 比较运算符返回布尔结果,因此虽然它在语法上正确,但它所做的事情与检查h 是否在01 之间完全不同。

因为该算法使用输入值的 H 角在六种不同场景之一之间进行选择,所以可以使用 switch 语句更简单地完成整个事情(如对问题的评论中所述)。首先,编写的代码处理h 为负数的情况,这很好,但由于它是一个 angular 值,因此只需将其强制到[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 介于06 之间;它可能是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;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2015-03-11
    相关资源
    最近更新 更多