如何在 lua 中正确地将 hsl 颜色转换为 rgb 颜色?

How to properly convert hsl colors to rgb colors in lua?

我有以下代码:

#!/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

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

以度为单位计算的色调值,因此最大值不是 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

我一直在研究 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
-- 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