algorithm - RGB => HSL => 色调范围名称转换算法关闭正 60 度

标签 algorithm ruby colors

背景
为了练习(在 ruby 中),我正在实现一些颜色转换算法。我试图在 EasyRGB.com 上转换可用的伪代码到 ruby 。转换似乎工作正常。

根据 HSL color space theory红色恰好在 0 度,红色的色调范围约占色环的 60 度,从 -30 度到 30 度(这取决于人们想要将色轮划分的精细程度)。

HSL Color Wheel
(来源:med.sc.edu)

出于我的目的,我将轮子分成 6 个部分。与其他五个色相范围各占 60 度。

问题
当我尝试使用由我的转换函数生成的色调值时,我的计算偏离正 60 度。

根据颜色理论应该是什么结果

def hue_name_from_hue_value(hue_value)
    color_angle = hue_value * 360

    # still can't do grays
    # saturation of 0 = gray
    # lightness of 0 = black
    # lightness of 1 = white
    # there has to be a threshold for when it's considered white or black
    # there has to be a threshold for when it's considered gray or the color in question

    if 30 >= color_angle and color_angle < 90
        return HUE_LIST[:YELLOW]
    elsif 90 >= color_angle and color_angle < 150
        return HUE_LIST[:GREEN]
    elsif 150 >= color_angle and color_angle < 210
        return HUE_LIST[:CYAN]
    elsif 210 >= color_angle and color_angle < 270
        return HUE_LIST[:BLUE]
    elsif 270 >= color_angle and color_angle < 330
        return HUE_LIST[:MAGENTA]
    else
        return HUE_LIST[:RED]
    end
end

实际结果

def hue_name_from_hue_value(hue_value)
    color_angle = hue_value * 360

    if 30 >= color_angle and color_angle < 90
        return HUE_LIST[:RED]
    elsif 90 >= color_angle and color_angle < 150
        return HUE_LIST[:YELLOW]
    elsif 150 >= color_angle and color_angle < 210
        return HUE_LIST[:GREEN]
    elsif 210 >= color_angle and color_angle < 270
        return HUE_LIST[:CYAN]
    elsif 270 >= color_angle and color_angle < 330
        return HUE_LIST[:BLUE]
    else
        return HUE_LIST[:MAGENTA]
    end
end

问题
为什么我的转换关闭了 60 度(是否关闭了 60 度)? 我已经包含了我实现 RGB 到 HSL 算法的源代码以供引用。

EasyRGB.com伪代码

var_R = ( R / 255 )                     //RGB from 0 to 255
var_G = ( G / 255 )
var_B = ( B / 255 )

var_Min = min( var_R, var_G, var_B )    //Min. value of RGB
var_Max = max( var_R, var_G, var_B )    //Max. value of RGB
del_Max = var_Max - var_Min             //Delta RGB value

L = ( var_Max + var_Min ) / 2

if ( del_Max == 0 )                     //This is a gray, no chroma...
{
   H = 0                                //HSL results from 0 to 1
   S = 0
}
else                                    //Chromatic data...
{
   if ( L < 0.5 ) S = del_Max / ( var_Max + var_Min )
   else           S = del_Max / ( 2 - var_Max - var_Min )

   del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max
   del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max
   del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max

   if      ( var_R == var_Max ) H = del_B - del_G
   else if ( var_G == var_Max ) H = ( 1 / 3 ) + del_R - del_B
   else if ( var_B == var_Max ) H = ( 2 / 3 ) + del_G - del_R

   if ( H < 0 ) H += 1
   if ( H > 1 ) H -= 1
}

我在 Ruby 中实现的伪代码

def rgb_to_hsl(red, green, blue)
    hsl_values = {:hue => 0, :saturation => 0, :lightness => 0}

    if
        (red.is_a?(Integer) && green.is_a?(Integer) && blue.is_a?(Integer)) == false
        return hsl_values
    end

    red /= 255.to_f
    green /= 255.to_f
    blue /= 255.to_f

    hue = 0.to_f
    saturation = 0.to_f
    lightness = 0.to_f

    minimum = [red, green, blue].min
    maximum = [red, green, blue].max
    delta_max = maximum - minimum

    lightness = (maximum + minimum) / 2

    if delta_max == 0 #gray
        hue = 0
        saturation = 0
    else
        if lightness < 0.5
            saturation = delta_max / (maximum + minimum)
        else
            saturation = delta_max / (2 - maximum - minimum)
        end

        delta_red = (((maximum - red) / 6) + (maximum / 2)) / delta_max
        delta_green = (((maximum - green) / 6) + (maximum / 2)) / delta_max
        delta_blue = (((maximum - blue) / 6) + (maximum / 2)) / delta_max

        if red == maximum
            hue = delta_blue - delta_green
        elsif green == maximum
            hue = (1 / 3) + delta_red - delta_blue
        elsif blue == maximum
            hue = (2 / 3) + delta_green - delta_red
        end

        if hue < 0
            hue += 1
        end

        if hue > 1
            hue -= 1
        end
    end

    hsl_values[:hue] = hue
    hsl_values[:saturation] = saturation
    hsl_values[:lightness] = lightness
    return hsl_values
end

最佳答案

在对 Ruby 语言进行一些研究后,我找到了问题的答案。

首先,我遇到了一个舍入错误,因为我的一些计算没有进行 float 学运算。我通过将 to_f 方法附加到需要的整数来解决这些问题。

其次,我确定色调的逻辑有误。我找到了 between?(a, b) 方法并将其替换为我编写的等式。这解决了问题。

重写后的代码如下。

def hue_name_from_hue_value(hue_value)
    color_angle = hue_value * 360

    if color_angle.between?(31, 90)
        return HUE_LIST[:YELLOW]
    elsif color_angle.between?(91,150)
        return HUE_LIST[:GREEN]
    elsif color_angle.between?(151,210)
        return HUE_LIST[:CYAN]
    elsif color_angle.between?(211,270)
        return HUE_LIST[:BLUE]
    elsif color_angle.between?(271,330)
        return HUE_LIST[:MAGENTA]
    else
        return HUE_LIST[:RED]
    end
end

关于algorithm - RGB => HSL => 色调范围名称转换算法关闭正 60 度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27451695/

相关文章:

html - 选择时更改输入字段的颜色

arrays - 组织数组的算法

php - 创建固定长度的可索引非重复组合

algorithm - Picopala算法实现

mysql - Ruby 中特定键等效时特定值的总和

ruby - 为在线商店生成订单号的最佳方式?

c++ - 在 SDL2 和 C++ 中编码图像和改变颜色

algorithm - 移动向量 y 的最大值,其中 y 随每一步而变化

ruby - 为什么 .to_s 会破坏这段代码?

Android可用性测试——色盲