【问题标题】:How to properly convert hsl colors to rgb colors in lua?如何在lua中正确地将hsl颜色转换为rgb颜色?
【发布时间】:2023-06-27 13:11:02
【问题描述】:

我有以下代码:

#!/usr/bin/env lua5.3
-- Code adapted from https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua#L51

local function hslToRgb(h, s, l, a)
    local r, g, b

    h = (h / 255)
    s = (s / 100)
    l = (l / 100)

    if s == 0 then
        r, g, b = l, l, l -- achromatic
    else
        local function hue2rgb(p, q, t)
            if t < 0   then t = t + 1 end
            if t > 1   then t = t - 1 end
            if t < 1/6 then return p + (q - p) * 6 * t end
            if t < 1/2 then return q end
            if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
            return p
        end

        local q
        if l < 0.5 then q = l * (1 + s) else q = l + s - l * s end
        local p = 2 * l - q

        r = hue2rgb(p, q, h + 1/3)
        g = hue2rgb(p, q, h)
        b = hue2rgb(p, q, h - 1/3)
    end

    if not a then a = 1 end
    return r * 255, g * 255, b * 255, a * 255
end

local h,s,l,a
h,s,l,a = hslToRgb(220, 16.4, 21.6)

print(h,s,l,a)
-- expected output: 46  52  64  255
--   actual output: 64.11312    46.04688    60.92496    255

但是,正如最后所说,它输出的颜色值是完全错误的。小数点不是问题(例如,输出它们不是问题;它们的值仍然是错误的)。

【问题讨论】:

  • 没时间出道。你能写出它给你算法的值吗,白色、黑色、红色、黄色、绿色、蓝色和中灰色)。通常使用此类数据,您应该了解差异(可能是不同的约定:线性/伽马校正;零角度,色调方向,范围(但在这种情况下似乎很清楚)。此外,还有不同的解释跨度>

标签: colors lua rgb hsl


【解决方案1】:

以度数计算的色调值,因此最大值不是 255,而是 360:

function hslToRgb(h, s, l)
    h = h / 360
    s = s / 100
    l = l / 100

    local r, g, b;

    if s == 0 then
        r, g, b = l, l, l; -- achromatic
    else
        local function hue2rgb(p, q, t)
            if t < 0 then t = t + 1 end
            if t > 1 then t = t - 1 end
            if t < 1 / 6 then return p + (q - p) * 6 * t end
            if t < 1 / 2 then return q end
            if t < 2 / 3 then return p + (q - p) * (2 / 3 - t) * 6 end
            return p;
        end

        local q = l < 0.5 and l * (1 + s) or l + s - l * s;
        local p = 2 * l - q;
        r = hue2rgb(p, q, h + 1 / 3);
        g = hue2rgb(p, q, h);
        b = hue2rgb(p, q, h - 1 / 3);
    end

    if not a then a = 1 end
    return r * 255, g * 255, b * 255, a * 255
end

你可以看到这段代码在here工作。

【讨论】:

  • 谢谢,这就是解决方案
【解决方案2】:

我现在一直在研究一种更优雅的 HSV 到 RGB 问题的解决方案,这就是我想出的。

local ceil = math.ceil
local abs = math.abs

local function clamp(v, min, max)
    if v < min then return min end
    if v > max then return max end
    return v
end

local function HSV(h, s, v)
    local vert = ceil(h / 120)
    local r = abs(((h / 60) - 2 * vert))
    local r, g, b = clamp(r, 1 - s, 1), clamp(2 - r, 1 - s, 1), (1 - s * v)

    if vert == 1 then return r, g, b end
    if vert == 2 then return b, r, g end
    if vert == 3 then return g, b, r end
end

【讨论】:

    【解决方案3】:
    -- HSV to RGB
    min = math.min
    max = math.max
    abs = math.abs
    
    local function HSV2RGB (h, s, v)
        local k1 = v*(1-s)
        local k2 = v - k1
        local r = min (max (3*abs (((h      )/180)%2-1)-1, 0), 1)
        local g = min (max (3*abs (((h  -120)/180)%2-1)-1, 0), 1)
        local b = min (max (3*abs (((h  +120)/180)%2-1)-1, 0), 1)
        return k1 + k2 * r, k1 + k2 * g, k1 + k2 * b
    end
    

    【讨论】: