如何在 Lua 中正确转换 HSL 颜色为 RGB 颜色?

我有以下代码:

#!/usr/bin/env lua5.3
-- 代码来源: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 -- 黑白色
    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)
-- 预期输出:46  52  64  255
--   实际输出:64.11312    46.04688    60.92496    255

但是,正如末尾所述,它输出的颜色值完全错误。小数并不是问题(例如,它输出它们并不是一个问题;它们的值仍然是错误的)。

点赞
用户6367889
用户6367889

一个色调值是以度数计算的,所以最大值不是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; -- 灰色无色彩
    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

你可以在这里看到这段代码的运行效果。

2021-07-09 22:17:39
用户10158039
用户10158039

我一直在尝试更优雅的解决 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
2022-03-04 01:53:14
用户12968803
用户12968803
- HSV 转 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
2022-03-05 21:14:42