Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 5 of 5
  1. #1
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts

    how could I calculate opposite colors from RBG values

    So given an RGB background color I'm looking for a formula to calculate the contrasting foreground color.

    any ideas?

  • #2
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Isn't the contrasting color 180 degrees on the hue? Or what exactly are you defining it to be?

  • #3
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Well I'm not exactly sure ... but I think this 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

  • #4
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    A little bit much, but it is a trimmed down Color library I wrote for my Color Picker:
    Code:
    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.

  • #5
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Wow Thanks man, that's amazing
    Last edited by brothercake; 02-18-2003 at 10:50 PM.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •