0

I have the following code:

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

But, as stated at the end, the color values it outputs are completely wrong. The decimals are not an issue (as in, it's not an issue that it outputs them; their values are still wrong).

SkyyySi
  • 53
  • 5
  • 1
    I do not have time to debut. Could you write the value it give you the algorithm, for white, black, red, yellow, green, blue and mid-gray). Usually with such data you should understand the differences (possibly a different convention: linear/gamma corrected; angle of zero, direction of hue, range (but in this case it seems clear). And also with that, there are different intepretation – Giacomo Catenazzi Jul 09 '21 at 13:14

3 Answers3

3

A hue value it's calculated in degrees, so the max isn't 255, but 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

You can see this code working here.

Francisco
  • 431
  • 9
  • 16
1
-- 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
darkfrei
  • 122
  • 5
0

I have been working on a more elegant solution to the HSV to RGB problem for a little bit now and this is what I've come up with.

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
Ibet43
  • 11
  • 1