Page 1 of 3

HSV to RGB solution

Posted: Fri Mar 04, 2022 2:01 am
by SliiX
Hello! I have been working on a different method for converting HSV to RGB and I figured I would share it.
I was also wonder if there was a solution to shifting 3 return values other than using that if-statement block at the bottom?

Code: Select all

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

function HSV(h, s, v)
    local vert = ceil(h / 120)
    local rat = abs(((h / 60) - 2 * vert))
    
    -- arc to vertex ratios along with extra channel
    local r, g, b = clamp(rat, 1 - s, 1), clamp(2 - rat, 1 - s, 1), (1 - s * v)
    
    -- vertex shift
    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

Re: HSV to RGB solution

Posted: Fri Mar 04, 2022 8:15 am
by darkfrei

Code: Select all

r, g, b = vert==1 and r,g,b or vert==2 and b,r,g or g,b,r
return r, g, b

Re: HSV to RGB solution

Posted: Fri Mar 04, 2022 9:45 am
by ReFreezed
darkfrei wrote: Fri Mar 04, 2022 8:15 am (nonsense)
My hand went straight through my head when I facepalmed.

Re: HSV to RGB solution

Posted: Fri Mar 04, 2022 12:43 pm
by pgimeno

Code: Select all

r, g, b = select(4 - vert, g, b, r, g, b)
return r, g, b
However, select() breaks traces, so it's not very recommended. The `if` version will probably perform better. I'd remove the last `if`, though: assume that if it's not 1 or 2, it must be 3.

Also, clamp() could be improved:

Code: Select all

local min, max = math.min, math.max

local function clamp(v, vmin, vmax)
  return min(max(v, vmin), vmax)
end
which compiles to faster code.

Re: HSV to RGB solution

Posted: Fri Mar 04, 2022 1:55 pm
by darkfrei
Maybe also the
h = h%360
for some situations, where h can be any value as
h = h + dt to change the hue by the time.

Re: HSV to RGB solution

Posted: Sat Mar 05, 2022 12:04 am
by SliiX
darkfrei wrote: Fri Mar 04, 2022 8:15 am

Code: Select all

r, g, b = vert==1 and r,g,b or vert==2 and b,r,g or g,b,r
return r, g, b
that is quite an interesting solution, I might try that. Although I think the if statements are easier on the eyes personally.
Also broke when shifting to vertex 2

Re: HSV to RGB solution

Posted: Sat Mar 05, 2022 12:06 am
by SliiX
pgimeno wrote: Fri Mar 04, 2022 12:43 pm

Code: Select all

r, g, b = select(4 - vert, g, b, r, g, b)
return r, g, b
However, select() breaks traces, so it's not very recommended. The `if` version will probably perform better. I'd remove the last `if`, though: assume that if it's not 1 or 2, it must be 3.

Also, clamp() could be improved:

Code: Select all

local min, max = math.min, math.max

local function clamp(v, vmin, vmax)
  return min(max(v, vmin), vmax)
end
which compiles to faster code.
That select function is an interesting take, but, it broke on the second vertex, and on the third it didn't return one of the color values.
Also I already tried that clamp function, and the min/max method appears to be slightly slower when I timed it.

Re: HSV to RGB solution

Posted: Sat Mar 05, 2022 12:43 am
by SliiX
I realized I forgot to incorporate the value, I also made some slight changes.

Code: Select all

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

function HSV(h, s, v)
    v = v or 1; s = (1 - s) * v or 0

    local vert = ceil(h / 120)
    local rat = abs((h / 60) - 2 * vert)

    -- arc to vertex ratios along with extra channel
    local r, g = clamp(rat * v, s, 1), clamp((2 - rat) * v, s, 1)

    -- vertex shift
    if vert == 1 then return r, g, s end
    if vert == 2 then return s, r, g end
    return g, s, r
end

Re: HSV to RGB solution

Posted: Sat Mar 05, 2022 9:24 am
by darkfrei
We can use the zigzag function (but with clamp):
2020-09-20T10_56_25-zigzag.png
2020-09-20T10_56_25-zigzag.png (84.55 KiB) Viewed 4946 times

Re: HSV to RGB solution

Posted: Sat Mar 05, 2022 10:07 am
by zorg
SliiX wrote: Sat Mar 05, 2022 12:04 am
darkfrei wrote: Fri Mar 04, 2022 8:15 am

Code: Select all

r, g, b = vert==1 and r,g,b or vert==2 and b,r,g or g,b,r
return r, g, b
that is quite an interesting solution, I might try that. Although I think the if statements are easier on the eyes personally.
Also broke when shifting to vertex 2
I think it broke because it wasn't parenthesized correctly; this might be better:

Code: Select all

r, g, b = vert==1 and r,g,b or (vert==2 and b,r,g or g,b,r)