• Finding Complimentary Colors (Epic Maths)
    2 replies, posted
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.