The HSL format is a lot easier than RGB for finding complimentary colors. Just add 180 degrees to the hue. So, I come into a time where I ACTUALLY need to do this. I found an article on how RGB can be converted to HSL. Then I did stuff, and proceeded on the long journey of converting it back. It was a trip, so I'm posting it here for reference! Also, in this example, if the color is a shade of grey, it will get the color opposite on the grayscale. Remove the commented line (that says to remove if you don't want this) if you don't want that to happen. I hope this works for you, as it will stick with me forever! It will NOT be perfect, so if you have any suggestions for speed or functionality, PLEASE DO NOT hesitate to write a comment. This is a reference post, after all. If it's incorrect at all it's my duty to change the OP to not mislead anybody. I am NOT perfectly confident in how efficient or effective the following method is. The equation can be found here: Math behind colorspace conversions, RGB
function getComplimentary(color)
local hue = 0
local sat = 0
local lum = 0
local r = color.r
local g = color.g
local b = color.b
local rpc = r/255
local gpc = g/255
local bpc = b/255
local min = math.min(rpc,gpc,bpc)
local max = math.max(rpc,gpc,bpc)
lum = (min + max)/2
if !(min == max) then
if lum < 0.5 then
sat = (max-min)/(max+min)
elseif lum > 0.5 then
sat = (max-min)/(2-max-min)
end
end
if rpc == max then
hue = (gpc-bpc)/(max-min)
elseif gpc == max then
hue = 2 + (bpc-rpc)/(max-min)
elseif bpc == max then
hue = 4 + (rpc-gpc)/(max-min)
end
hue = hue*60
if hue < 0 then hue = hue + 360 end -- FULLY CALCULATED
hue = hue + 180 -- FINDING COMPLIMENTARY
hue = NeutralizeHue(hue) -- SETTING TO BASE 360
local newR = 0;
local newB = 0;
local newG = 0;
if sat = 0 then -- START TO CONVERT BACK; CHECK IF SHADE OF GREY
local level = lum*255
level = math.abs(level - 255) -- REMOVE THIS LINE IF YOU DON'T WANT GREY TO RETURN OPPOSITE...
newR = level
newB = level
newG = level
return Color(newR, newB, newG)
end
local tempvar1; -- START CONVERSTION FOR NON-GREYS
local tempvar2;
if lum < 0.5 then
tempvar1 = lum*(1+sat)
elseif lum >= 0.5 then
tempvar1 = (lum + sat) – (lum * sat)
end
tempvar2 = 2*(lum – tempvar1)
hue = hue/360
local temp_R = NeutralizeZeroOne(hue + 0.333)
local temp_G = NeutralizeZeroOne(hue)
local temp_B = NeutralizeZeroOne(hue - 0.333)
r = RGBValueTest(temp_R, tempvar1, tempvar2)
g = RGBValueTest(temp_G, tempvar1, tempvar2)
b = RGBValueTest(temp_B, tempvar1, tempvar2)
return Color(r, g, b)
end
function RGBValueTest(value, temp1, temp2)
local num = value
if 2*num < 1 then return temp1 end
if 6*num < 1 then return temp2+(temp1 – temp2)*6*num end
if 3*num < 2 then return temp2 + (temp1 – temp2)*(0.666 – num)*6 end
return num
end
function NeutralizeZeroOne(value)
local num
if value < 0 then num = value + 1 end
if value > 1 then num = value - 1 end
return num
end
function NeutralizeHue(value)
local num = value;
local left = num - 360
local mult = math.floor(left/360)
for i=0,mult do
num = num - 360
end
return num
end
Yep, this should work like a charm. I'm pretty retarded.
function getComplimentaryColor(color)
local h, s, v = ColorToHSV(color)
h = h + 180
if h > 360 then h = h - 360 end
if s == 0 then -- If you don't want greys to return opposite, erase from here...
v = v + 0.5
if v > 1 then v = v - 1 end
end -- ... to here!
return HSVToColor(h, s, v) -- This used to be an issue [Until June 23 2016]
end
I think HSVToColor already wraps the numbers to go between 360 anyway, so there's no need for this line:
if h > 360 then h = h - 360 end
Also, you could use modulus for this because it looks a whole lot simpler:
h = ( h + 180 ) % 360
Anyway, this might work:
local function getComplimentaryColor( color )
local h, s, v = ColorToHSV( color )
return HSVToColor( h + 180, s, v )
end
Sorry, you need to Log In to post a reply to this thread.