# *extremely* weird—all rgb to hsl converters always return 1.0

I should say I have had this same result with many different lua RGB to HSB converters.

I am trying to find just the saturation value of an rgb color.

No matter what formula I find online, or that I get out of ChatGPT, I always always always get back an s value of 1.0.

Here is just one example. For any Rgb value I put in here, I get 1.0 back:

``````  function saturationFromColor(c)
local r, g, b = c.r / 255, c.g / 255, c.b / 255
local max = math.max(r, g, b)
local min = math.min(r, g, b)
local c = max - min
local h, s, b = 0, 0, 0

if c == 0 then
h = 0
elseif max == r then
h = ((g - b) / c) % 6
elseif max == g then
h = ((b - r) / c) + 2
else
h = ((r - g) / c) + 4
end

h = h * 60

if max == 0 then
s = 0
else
s = c / max
end

b = max

return s
end
``````

ChatGPT was going crazy because no matter what code it gave me I kept telling it “this doesn’t work”. Does anybody else have the same result?

@UberGoober I get values other than 1 for s. If I use r,g,b as 255,128,64 then I get

h = 40.20942408377
s = 0.74901960784314
b= 1.0

Anytime either r,g,b is 0, you’ll get s = 1. Since s= (max - min) / max, you’ll get (max - 0) / max. That will always be 1.

Edit: I also noticed that your using local r,g,b and local h,s,b. You’re setting h,s,b to 0’s which will 0 out the b for r,g,b.

1 Like

@UberGoober See the RGB to HSV conversion program I just put on WebRepo.

1 Like

You could use this:

`````` local RGBToHSB = function(vals) -- converts: RGB to HSB (Hue,Saturation,Brightness)
local r,g,b = vals.r/255, vals.g/255, vals.b/255 -- normalized properties
local max,min = math.max(r,g,b),math.min(r,g,b)
local chroma = (r == 0 or g == 0 or b == 0) and max or max - min
local hue = chroma == 0 and 0 or max == r and 60 * (((g - b)/chroma) % 6) or
max == g and 60 * (((b - r)/chroma) + 2) or max == b and 60 * (((r - g)/chroma) + 4)
local b,s = max; s = chroma == 0 and 0 or chroma/b
return {h = hue, s = s, b = b} end -- returns: (table) HSB Values {h = ?, s = ?, b = ?}
``````

You could also check this out Colors.lua. I created this a few years ago for converting between color spaces. You could get the correct values by doing something like

color(255,128,244):toHSB()

Thanks guys! Looks good.

That’s a condensed way of doing it. I find it very hard to figure out what’s really happening though. I understand the and/or/xor etc tables but that doesn’t help much. It’s like I have to take each group and determine true/false then determine and/or of what else it’s doing. You also have to determine how the values of the variables affect everything, true if not 0, otherwise false. I would never attempt to code anything like that, but I guess if you do code like that, it gets easier. I just wouldn’t want to debug someone’s code that had a lot of that in it.

This is the equivalent code with the if / elseif / else syntax. I just find that the code is more condensed too using the and / or syntax as you don’t have to assign variables multiple times.

``````local RGBToHSB = function(vals) -- converts: RGB to HSB (Hue,Saturation,Brightness)
local r,g,b = vals.r/255, vals.g/255, vals.b/255 -- normalized properties
local max,min = math.max(r,g,b),math.min(r,g,b)

local chroma
if r == 0 or g == 0 or b == 0 then
chroma = max
else
chroma = max - min
end

local hue
if chroma == 0 then
hue = 0
elseif max == r then
hue = 60 * (((g - b)/chroma) % 6)
elseif max == g then
hue = 60 * (((b - r)/chroma) + 2)
elseif max == b then
hue = 60 * (((r - g)/chroma) + 4)
end

local b = max

local s
if chroma == 0 then
s = 0
else
s = chroma / b
end

return {h = hue, s = s, b = b}  -- returns: (table) HSB Values {h = ?, s = ?, b = ?}

end
``````

@Beckett2000 I don’t know if you’re using WebRepo yet, but I have an RGB to HSV program there. If you don’t, here is the program.

``````-- Convert RGB to HSV

viewer.mode=FULLSCREEN

function setup()
rectMode(CENTER)
boxR=input(WIDTH/2-100,HEIGHT-200,90,30,1,"R")
boxG=input(WIDTH/2-100,HEIGHT-275,90,30,1,"G")
boxB=input(WIDTH/2-100,HEIGHT-350,90,30,1,"B")
boxH=input(WIDTH/2,HEIGHT-200,90,30,2,"H")
boxS=input(WIDTH/2,HEIGHT-275,90,30,2,"S")
boxV=input(WIDTH/2,HEIGHT-350,90,30,2,"V")
boxC=input(WIDTH/2+100,HEIGHT-200,90,30,2,"RGB Color")
boxX=input(WIDTH/2+100,HEIGHT-275,90,30,2,"RGB Hex")

boxTab={boxR,boxG,boxB,boxH,boxS,boxV,boxC,boxX}
end

function draw()
background(32, 59, 83)         -- screen color
for nbr,box in pairs(boxTab) do             -- loop thru table
box:draw()                            -- draw each box
end
end

pushStyle()
fontSize(36)
fill(255,0,0)
text("RGB to HSV Converter",WIDTH/2,HEIGHT-50)   -- draw text
fontSize(20)
fill(224, 149, 127, 255)            -- set color
text("( Tap each R, G, B box to input a value )",WIDTH/2,HEIGHT-100)
popStyle()
end

function touched(t)                     -- check which box is selected
for nbr,box in pairs(boxTab) do     -- loop thru table
if box:touched(t) then          -- box touched
return                      -- exit function
end
end
end

function keyboard(k)
for nbr,box in pairs(boxTab) do -- loop thru table
box:keyboard(k)             -- get input from box
end
end

input=class()

input.msg=""
input.str=""

function input:init(x,y,w,h,type,txt)
self.x=x            -- x position
self.y=y            -- y position
self.w=w            -- width
self.h=h            -- height
self.type=type      -- 1=input box  2=output box
self.txt=txt        -- text to show above box
self.val="0"        -- data keyed in box
self.sel=false      -- box selected true/false
end

function input:draw()
pushStyle()
fill(0)                         -- set background for box
if self.txt=="RGB Color" then
self.val=""
fill(boxR.val,boxG.val,boxB.val)
end
if self.txt=="RGB Hex" then
self.val=string.format("%02X%02X%02X",boxR.val,boxG.val,boxB.val)
end
if self.sel then                    -- set selected color for box
fill(105, 101, 31, 255)
if input.msg~="" then
fill(0,255,0)
text(input.msg,WIDTH/2,HEIGHT-140)
end
end
stroke(255)                     -- box outline color
strokeWidth(2)                      -- outline size
rect(self.x,self.y,self.w,self.h)   -- draw box
fill(255)                       -- set text color
text(self.txt,self.x,self.y+self.h) -- box name
text(self.val,self.x+4,self.y)      -- box text
popStyle()
end

function input:keyboard(k)
if self.sel then
if input.msg~="" then
input.msg=""
self.val="0"
input.str="0"
end
if k==BACKSPACE then            -- backspace key pressed
input.str=string.sub(input.str,1,#input.str-1) -- remove last digit
if #input.str==0 then
input.str="0"
end
elseif k>="0" and k<="9" then           -- only digits 1 thru 9
if string.sub(input.str,1,1) =="0" then
end
input.str=input.str..k              -- update keyed value
end
self.val=input.str                      -- save keyed value
if math.tointeger(self.val)>255 then    -- check valid range
input.str=""
input.msg="ERROR:  Must be 0-255"
end
input:convert()
end
end

function input:touched(t)
if t.state==BEGAN then
input.msg=""
if not isKeyboardShowing() then
showKeyboard()      -- show keyboard if its not displayed
end
input.str="0"           -- set to 0
for z=1,#boxTab do      -- clear selected flag for all boxes
boxTab[z].sel=false
end
-- check which box was selected
if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
t.y>self.y-self.h/2 and t.y<self.y+self.h/2 and self.type==1 then
self.val="0"        -- reset val
self.sel=true       -- set selected flag
return true         -- box selected
end
end
return false                -- no box selected
end

function input:convert()        -- convert RGB to HSV
local r=math.tointeger(boxR.val)/255
local g=math.tointeger(boxG.val)/255
local b=math.tointeger(boxB.val)/255
local max,min=math.max(r,g,b),math.min(r,g,b)
local diff=max-min h,s,v=0,0,0
if diff==0 then
h=0
else
if max==r then
h=(((g-b)/diff)%6)*60
end
if max==g then
h=(((b-r)/diff)+2)*60
end
if max==b then
h=(((r-g)/diff)+4)*60
end
end
if max==0 then
s=0
else
s=(diff/max)
end
boxH.val=string.format("%d°",h//1)
boxS.val=string.format("%2.1f%%",s*100)
boxV.val=string.format("%2.1f%%",max*100)
end
``````

@dave1707 I ran your program code and it looks pretty good. It’s useful to have an example which shows the values and resulting color. The only differences I saw in your conversion were that you scale your values to 100. I originally did this in colors.lua, but didn’t here to make the values match those gotten by UberGoober. I don’t know how to use WebRepo though. If you could let me know I would appreciate it.

@Steppers Can you help out here. I don’t know where the latest zip is.

@dave1707 1.0.3 Should be on WebRepo now.
Sourced from here: https://codeawebrepo.co.uk/RGB-HSV/1.0.3/project.zip