...

View Full Version : how could I calculate opposite colors from RBG values



brothercake
01-17-2003, 12:35 AM
So given an RGB background color I'm looking for a formula to calculate the contrasting foreground color.

any ideas?

jkd
01-17-2003, 01:38 AM
Isn't the contrasting color 180 degrees on the hue? Or what exactly are you defining it to be?

brothercake
01-17-2003, 01:47 AM
Well I'm not exactly sure ... but I think this (http://www.lascaux.ch/english/farben/sirius_farbkreis.htm) shows the contrasting colors I'm after, so then yeah - I guess I am looking for a 180 degree change ... but math is not my strongpoint ... I don't know how to calculate the numbers :(

What I'm actually working with is three sliders which change the page RGB - I want the text color to change automatically with it, so it's always visible - or, at least, the closest to that I can get :)

jkd
01-17-2003, 02:08 AM
A little bit much, but it is a trimmed down Color library I wrote for my Color Picker:


function Color(str) {
var cmykSet = 0;
var hslSet = 0;

if (/rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)/.exec(str))
this.type = 'RGB, 0-255';
else if (/rgb\((\d{1,3}(?:\.\d+)?)%,\s*(\d{1,3}(?:\.\d+)?)%,\s*(\d{1,3}(?:\.\d+)?)%\)/.exec(str))
this.type = 'RGB, 0-100%';
else if (/^#([\da-f])([\da-f])([\da-f])$/i.exec(str))
this.type = 'HEX, SIMPLE';
else if (/^#([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(str))
this.type = 'HEX, EXPANDED';

// extra, supported color types not usable in browsers (HSL is defined in CSS3 Color Module though)
else if (/cmy\(([01](?:\.\d+)?),\s*([01](?:\.\d+)?),\s*([01](?:\.\d+)?)\)/.exec(str))
this.type = 'CMY';
else if (/cmyk\(([01](?:\.\d+)?),\s*([01](?:\.\d+)?),\s*([01](?:\.\d+)?),\s*([01](?:\.\d+)?)\)/.exec(str))
this.type = 'CMYK';
else if (/hsl\((\d{1,3}(?:\.\d+)?),\s*(\d{1,3}(?:\.\d+)?)%,\s*(\d{1,3}(?:\.\d+)?)%\)/.exec(str))
this.type = 'HSL';
else
this.type = 'INVALID';

switch (this.type) {
case 'RGB, 0-255':
this.r = parseInt(RegExp.$1);
this.g = parseInt(RegExp.$2);
this.b = parseInt(RegExp.$3);
break;
case 'RGB, 0-100%':
this.r = parseFloat(RegExp.$1) * 2.55;
this.g = parseFloat(RegExp.$2) * 2.55;
this.b = parseFloat(RegExp.$3) * 2.55;
break;
case 'HEX, SIMPLE':
this.r = parseInt(RegExp.$1 + RegExp.$1, 16);
this.g = parseInt(RegExp.$2 + RegExp.$2, 16);
this.b = parseInt(RegExp.$3 + RegExp.$3, 16);
break;
case 'HEX, EXPANDED':
this.r = parseInt(RegExp.$1, 16);
this.g = parseInt(RegExp.$2, 16);
this.b = parseInt(RegExp.$3, 16);
break;
case 'CMY':
this.c = parseFloat(RegExp.$1);
this.m = parseFloat(RegExp.$2);
this.y = parseFloat(RegExp.$3);
this.k = Math.min(this.c, this.m, this.y);
this.r = (1 - this.c) * 255;
this.g = (1 - this.m) * 255;
this.b = (1 - this.y) * 255;
this.c = (this.c - this.k) / (1 - this.k);
this.m = (this.m - this.k) / (1 - this.k);
this.y = (this.y - this.k) / (1 - this.k);
cmykSet = 1;
break;
case 'CMYK':
this.c = parseFloat(RegExp.$1);
this.m = parseFloat(RegExp.$2);
this.y = parseFloat(RegExp.$3);
this.k = parseFloat(RegExp.$4);
this.r = (1 - (this.c * (1 - this.k) + this.k)) * 255;
this.g = (1 - (this.m * (1 - this.k) + this.k)) * 255;
this.b = (1 - (this.y * (1 - this.k) + this.k)) * 255;
cmykSet = 1;
break;
case 'HSL':
var m1, m2, hue;
this.h = parseFloat(RegExp.$1);
this.s = parseFloat(RegExp.$2) / 100;
this.l = parseFloat(RegExp.$3) / 100;
if (this.s == 0)
this.r = this.g = this.b = this.l * 255;
else {
if (this.l <= 0.5)
m2 = this.l * (this.s + 1);
else
m2 = this.l + this.s - this.l * this.s;
m1 = this.l * 2 - m2;
hue = this.h / 360;
this.r = Color._HueToRgb(m1, m2, hue + 1/3);
this.g = Color._HueToRgb(m1, m2, hue);
this.b = Color._HueToRgb(m1, m2, hue - 1/3);
}
hslSet = 1;
break;
case 'INVALID':
default:
this.r = this.g = this.b = this.c = this.m = this.y = this.k = this.h = this.s = this.l = Number.NaN;
break;
}
if (!cmykSet) {
this.c = 1 - (this.r / 255);
this.m = 1 - (this.g / 255);
this.y = 1 - (this.b / 255);
this.k = Math.min(this.c, this.m, this.y);
this.c = (this.c - this.k) / (1 - this.k);
this.m = (this.m - this.k) / (1 - this.k);
this.y = (this.y - this.k) / (1 - this.k);
cmykSet = 1;
}
if (!hslSet) {
var r = this.r / 255;
var g = this.g / 255;
var b = this.b / 255;
var min = Math.min(r, g, b);
var max = Math.max(r, g, b);

this.l = (min + max)/2;
if (min == max)
this.h = this.s = 0;
else {
this.s = 1 - min / max;
switch (max) {
case r:
this.h = 6 + (g - b)/(max - min);
break;
case g:
this.h = 2 + (b - r)/(max - min);
break;
case b:
this.h = 4 + (r - g)/(max - min);
break;
}
this.h = (this.h * 60) % 360;

}
hslSet = 1;
}

this.toString = this.toRGBValue = function() {
return 'rgb(' + Math.round(this.r) + ', ' + Math.round(this.g) + ', ' + Math.round(this.b) + ')';
}
this.isColor = function() {
return this.type != 'INVALID';
}
this.toWebSafe = function() {
var websafe = ['0', '3', '6', '9', 'c', 'f'];
var r, g, b, temp;
if (this.r % 51 < 25)
temp = Math.floor(this.r / 51);
else
temp = Math.ceil(this.r / 51);
r = websafe[temp];
if (this.g % 51 < 25)
temp = Math.floor(this.g / 51);
else
temp = Math.ceil(this.g / 51);
g = websafe[temp];
if (this.b % 51 < 25)
temp = Math.floor(this.b / 51);
else
temp = Math.ceil(this.b / 51);
b = websafe[temp];
return new Color('#' + r + g + b);
}
}

Color._HueToRgb = function(m1, m2, hue) {
var v;
if (hue < 0)
hue += 1;
else if (hue > 1)
hue -= 1;

if (6 * hue < 1)
v = m1 + (m2 - m1) * hue * 6;
else if (2 * hue < 1)
v = m2;
else if (3 * hue < 2)
v = m1 + (m2 - m1) * (2/3 - hue) * 6;
else
v = m1;

return (255 * v);
}


Something like:

var oriColor = new Color('thecolorstring');

var contrasted = new Color('hsl(' + (oriColor.h + 180) % 360 + ', ' + oriColor.s + '%, ' + oriColor.l + '%)');

And now contrasted.toString() is the color with same saturation and lightness, but opposite on the hue.

brothercake
01-17-2003, 02:33 AM
Wow :thumbsup: Thanks man, that's amazing



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum