Convert rgb to hex - javascript

I wanted to find a way to code a program that would convert ANY rgb including ones with negative integers into a hex number, like this software.
http://www.javascripter.net/faq/rgbtohex.htm
I have this already but it doesn't seem to be working with the rgb:
rgb(-5, 231, -17)
function rgb2hex(rgb){
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
}
Thanks to anyone who can help!

Try this,
function colorToHex(color) {
if (color.substr(0, 1) === '#') {
return color;
}
var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
var red = parseInt(digits[2]);
var green = parseInt(digits[3]);
var blue = parseInt(digits[4]);
var rgb = blue | (green << 8) | (red << 16);
return digits[1] + '#' + rgb.toString(16);
};
colorToHex('rgb(120, 120, 240)');
Ref: http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx/

Related

Why does not JS background colour of input field check work? [duplicate]

Using the following jQuery will get the RGB value of an element's background color:
$('#selector').css('backgroundColor');
Is there a way to get the hex value rather than the RGB?
TL;DR
Use this clean one-line function with both rgb and rgba support:
const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`
2021 updated answer
Much time has passed since I originally answered this question. Then cool ECMAScript 5 and 2015+ features became largely available on browsers, like arrow functions, Array.map, String.padStart and template strings. Since some years, it's possible to write cross-browser one-liner rgb2hex:
const rgb2hex = (rgb) => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`
// Use as you wish...
console.log(rgb2hex('rgb(0,0,0)'))
console.log(rgb2hex('rgb(255, 255, 255)'))
console.log(rgb2hex('rgb(255,0,0)'))
console.log(rgb2hex('rgb(38, 170, 90)'))
It works by using a regular expression to get each digit inside the rgb string, slice(1) to get only the digits (the first result of match is the full string itself), map to iterate through each digit, each iteration converting to Number with parseInt, then back to an hexadecimal String (through a base-16 conversion), adding zero if needed via padStart. Finally, join each converted/adjusted digit to a unique String starting with '#'.
Of course, we could extend it without much effort as an one-liner rgba2hex:
const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`
// Now it doesn't matter if 'rgb' or 'rgba'...
console.log(rgba2hex('rgb(0,0,0)'))
console.log(rgba2hex('rgb(255, 255, 255)'))
console.log(rgba2hex('rgb(255,0,0)'))
console.log(rgba2hex('rgb(38, 170, 90)'))
console.log(rgba2hex('rgba(255, 0, 0, 0.5)'))
console.log(rgba2hex('rgba(0,255,0,1)'))
console.log(rgba2hex('rgba(127,127,127,0.25)'))
And that's it. But if you want to dive deep in the old school JavaScript world, keep reading.
Original 2010 answer
Here is the cleaner solution I wrote based on #Matt suggestion:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
Some browsers already returns colors as hexadecimal (as of Internet Explorer 8 and below). If you need to deal with those cases, just append a condition inside the function, like #gfrobenius suggested:
function rgb2hex(rgb) {
if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
If you're using jQuery and want a more complete approach, you can use CSS Hooks available since jQuery 1.4.3, as I showed when answering this question: Can I force jQuery.css("backgroundColor") returns on hexadecimal format?
var hexDigits = new Array
("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
function hex(x) {
return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
}
(Source)
Most browsers seem to return the RGB value when using:
$('#selector').css('backgroundColor');
Only I.E (only 6 tested so far) returns the Hex value.
To avoid error messages in I.E, you could wrap the function in an if statement:
function rgb2hex(rgb) {
if ( rgb.search("rgb") == -1 ) {
return rgb;
} else {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
}
Updated #ErickPetru for rgba compatibility:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
I updated the regex to match the alpha value if defined, but not use it.
Here's an ES6 one liner that doesn't use jQuery:
var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => parseInt(color).toString(16).padStart(2, '0')).join('');
Here is a version that also checks for transparent, I needed this since my object was to insert the result into a style attribute, where the transparent version of a hex color is actually the word "transparent"..
function rgb2hex(rgb) {
if ( rgb.search("rgb") == -1 ) {
return rgb;
}
else if ( rgb == 'rgba(0, 0, 0, 0)' ) {
return 'transparent';
}
else {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
}
Short
// c - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex=c=>'#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``
// rgb - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex= c=> '#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``
console.log(rgb2hex("rgb(12,233,43"));
Function that returns background color of an element in hex.
function getBgColorHex(elem){
var color = elem.css('background-color')
var hex;
if(color.indexOf('#')>-1){
//for IE
hex = color;
} else {
var rgb = color.match(/\d+/g);
hex = '#'+ ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2);
}
return hex;
}
usage example:
$('#div1').click(function(){
alert(getBgColorHex($(this));
}
jsfiddle
Readable && Reg-exp free (no Reg-exp)
I've created a function that uses readable basic functions and no reg-exps.
The function accepts color in hex, rgb or rgba CSS format and returns hex representation.
EDIT: there was a bug with parsing out rgba() format, fixed...
function getHexColor( color ){
//if color is already in hex, just return it...
if( color.indexOf('#') != -1 ) return color;
//leave only "R,G,B" :
color = color
.replace("rgba", "") //must go BEFORE rgb replace
.replace("rgb", "")
.replace("(", "")
.replace(")", "");
color = color.split(","); // get Array["R","G","B"]
// 0) add leading #
// 1) add leading zero, so we get 0XY or 0X
// 2) append leading zero with parsed out int value of R/G/B
// converted to HEX string representation
// 3) slice out 2 last chars (get last 2 chars) =>
// => we get XY from 0XY and 0X stays the same
return "#"
+ ( '0' + parseInt(color[0], 10).toString(16) ).slice(-2)
+ ( '0' + parseInt(color[1], 10).toString(16) ).slice(-2)
+ ( '0' + parseInt(color[2], 10).toString(16) ).slice(-2);
}
Same answer like #Jim F answer but ES6 syntax , so, less instructions :
const rgb2hex = (rgb) => {
if (rgb.search("rgb") === -1) return rgb;
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
const hex = (x) => ("0" + parseInt(x).toString(16)).slice(-2);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
};
color class taken from bootstrap color picker
// Color object
var Color = function(val) {
this.value = {
h: 1,
s: 1,
b: 1,
a: 1
};
this.setColor(val);
};
Color.prototype = {
constructor: Color,
//parse a string to HSB
setColor: function(val){
val = val.toLowerCase();
var that = this;
$.each( CPGlobal.stringParsers, function( i, parser ) {
var match = parser.re.exec( val ),
values = match && parser.parse( match ),
space = parser.space||'rgba';
if ( values ) {
if (space === 'hsla') {
that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
} else {
that.value = CPGlobal.RGBtoHSB.apply(null, values);
}
return false;
}
});
},
setHue: function(h) {
this.value.h = 1- h;
},
setSaturation: function(s) {
this.value.s = s;
},
setLightness: function(b) {
this.value.b = 1- b;
},
setAlpha: function(a) {
this.value.a = parseInt((1 - a)*100, 10)/100;
},
// HSBtoRGB from RaphaelJS
// https://github.com/DmitryBaranovskiy/raphael/
toRGB: function(h, s, b, a) {
if (!h) {
h = this.value.h;
s = this.value.s;
b = this.value.b;
}
h *= 360;
var R, G, B, X, C;
h = (h % 360) / 60;
C = b * s;
X = C * (1 - Math.abs(h % 2 - 1));
R = G = B = b - C;
h = ~~h;
R += [C, X, 0, 0, X, C][h];
G += [X, C, C, X, 0, 0][h];
B += [0, 0, X, C, C, X][h];
return {
r: Math.round(R*255),
g: Math.round(G*255),
b: Math.round(B*255),
a: a||this.value.a
};
},
toHex: function(h, s, b, a){
var rgb = this.toRGB(h, s, b, a);
return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
},
toHSL: function(h, s, b, a){
if (!h) {
h = this.value.h;
s = this.value.s;
b = this.value.b;
}
var H = h,
L = (2 - s) * b,
S = s * b;
if (L > 0 && L <= 1) {
S /= L;
} else {
S /= 2 - L;
}
L /= 2;
if (S > 1) {
S = 1;
}
return {
h: H,
s: S,
l: L,
a: a||this.value.a
};
}
};
how to use
var color = new Color("RGB(0,5,5)");
color.toHex()
Just to add to #Justin's answer above..
it should be
var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => String("0" + parseInt(color).toString(16)).slice(-2)).join('');
As the above parse int functions truncates leading zeroes, thus produces incorrect color codes of 5 or 4 letters may be... i.e. for rgb(216, 160, 10) it produces #d8a0a while it should be #d8a00a.
Thanks
This one looks a bit nicer:
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var r = parseInt(rgb[0], 10);
var g = parseInt(rgb[1], 10);
var b = parseInt(rgb[2], 10);
var hex = '#'+ r.toString(16) + g.toString(16) + b.toString(16);
a more succinct one-liner:
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ Number(rgb[0]).toString(16) + Number(rgb[1]).toString(16) + Number(rgb[2]).toString(16);
forcing jQuery to always return hex:
$.cssHooks.backgroundColor = {
get: function(elem) {
if (elem.currentStyle)
var bg = elem.currentStyle["backgroundColor"];
else if (window.getComputedStyle) {
var bg = document.defaultView.getComputedStyle(elem,
null).getPropertyValue("background-color");
}
if (bg.search("rgb") == -1) {
return bg;
} else {
bg = bg.match(/\d+/g);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(bg[0]) + hex(bg[1]) + hex(bg[2]);
}
}
}
Since the question was using JQuery, here’s a JQuery plugin based on Daniel Elliott’s code:
$.fn.cssAsHex = function(colorProp) {
var hexDigits = '0123456789abcdef';
function hex(x) {
return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
};
// Convert RGB color to Hex format
function rgb2hex(rgb) {
var rgbRegex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return '#' + hex(rgbRegex[1]) + hex(rgbRegex[2]) + hex(rgbRegex[3]);
};
return rgb2hex(this.css(colorProp));
};
Use it like:
var hexBackgroundColor = $('#myElement').cssAsHex('background-color');
Here's a solution I found that does not throw scripting errors in IE:
http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx
Steven Pribilinskiy's answer drops leading zeroes, for example #ff0000 becomes #ff00.
A solution is to append a leading 0 and substring off the last 2 digits.
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ String('0' + Number(rgb[0]).toString(16)).slice(-2) + String('0' + Number(rgb[1]).toString(16)).slice(-2) + String('0' + Number(rgb[2]).toString(16)).slice(-2);
Improved function "hex"
function hex(x){
return isNaN(x) ? "00" : hexDigits[x >> 4] + hexDigits[x & 0xf];
// or option without hexDigits array
return (x >> 4).toString(16)+(x & 0xf).toString(16);
}
Here is my solution, also does touppercase by the use of an argument and checks for other possible white-spaces and capitalisation in the supplied string.
var a = "rgb(10, 128, 255)";
var b = "rgb( 10, 128, 255)";
var c = "rgb(10, 128, 255 )";
var d = "rgb ( 10, 128, 255 )";
var e = "RGB ( 10, 128, 255 )";
var f = "rgb(10,128,255)";
var g = "rgb(10, 128,)";
var rgbToHex = (function () {
var rx = /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
function pad(num) {
if (num.length === 1) {
num = "0" + num;
}
return num;
}
return function (rgb, uppercase) {
var rxArray = rgb.match(rx),
hex;
if (rxArray !== null) {
hex = pad(parseInt(rxArray[1], 10).toString(16)) + pad(parseInt(rxArray[2], 10).toString(16)) + pad(parseInt(rxArray[3], 10).toString(16));
if (uppercase === true) {
hex = hex.toUpperCase();
}
return hex;
}
return;
};
}());
console.log(rgbToHex(a));
console.log(rgbToHex(b, true));
console.log(rgbToHex(c));
console.log(rgbToHex(d));
console.log(rgbToHex(e));
console.log(rgbToHex(f));
console.log(rgbToHex(g));
On jsfiddle
Speed comparison on jsperf
A further improvement could be to trim() the rgb string
var rxArray = rgb.trim().match(rx),
My beautiful non-standard solution
HTML
<div id="selector" style="background-color:#f5b405"></div>
jQuery
$("#selector").attr("style").replace("background-color:", "");
Result
#f5b405
Convert RGB to Hex
I am using Jasmine protractor and I was getting errors like
- Expected [ 'rgba(255, 255, 255, 1)' ] to contain '#fff'.
Below function worked fine for me.
function RGBAToHexA(test:string) {
let sep = test.toString().indexOf(",") > -1 ? "," : " ";
const rgba = test.toString().substring(5).split(")")[0].split(sep);
console.log(rgba)
let r = (+rgba[0]).toString(16),
g = (+rgba[1]).toString(16),
b = (+rgba[2]).toString(16),
a = Math.round(+rgba[3] * 255).toString(16);
if (r.length == 1)
r = "0" + r;
if (g.length == 1)
g = "0" + g;
if (b.length == 1)
b = "0" + b;
if (a.length == 1)
a = "0" + a;
return "#" + r + g + b + a;
}
describe('Check CSS', function() {
it('should check css of login page', async function(){
browser.waitForAngularEnabled(true);
browser.actions().mouseMove(element(by.css('.btn-auth, .btn-auth:hover'))).perform(); // mouse hover on button
csspage.Loc_auth_btn.getCssValue('color').then(function(color){
console.log(RGBAToHexA(color))
expect( RGBAToHexA(color)).toContain(cssData.hoverauth.color);
})
To all the Functional Programming lovers, here is a somewhat functional approach :)
const getHexColor = (rgbValue) =>
rgbValue.replace("rgb(", "").replace(")", "").split(",")
.map(colorValue => (colorValue > 15 ? "0" : "") + colorValue.toString(16))
.reduce((acc, hexValue) => acc + hexValue, "#")
then use it like:
const testRGB = "rgb(13,23,12)"
getHexColor(testRGB)
my compact version
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
if(/^#/.test(rgb))return rgb;// if returns colors as hexadecimal
let re = /\d+/g;
let hex = x => (x >> 4).toString(16)+(x & 0xf).toString(16);
return "#"+hex(re.exec(rgb))+hex(re.exec(rgb))+hex(re.exec(rgb));
}
full cases (rgb, rgba, transparent...etc) solution (coffeeScript)
rgb2hex: (rgb, transparentDefault=null)->
return null unless rgb
return rgb if rgb.indexOf('#') != -1
return transparentDefault || 'transparent' if rgb == 'rgba(0, 0, 0, 0)'
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
hex = (x)->
("0" + parseInt(x).toString(16)).slice(-2)
'#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3])
Hi here's my solution after getting the element's color with Javascript
function rgb_hex(rgb_string_js){ //example: "rgb(102,54,255)"
var new_rgb_list = rgb_string_js.replace("rgb(","").replace(")","").split(",");
return ("#" + parseInt(new_rgb_list[0]).toString(16) + parseInt(new_rgb_list[1]).toString(16) + parseInt(new_rgb_list[2]).toString(16));
}

How to convert RGBA to Hex color code using javascript

I tried to convert rgba to hex color code, but unable to covert opacity value remaining color I able to convert,
Below is my code
var colorcode = "rgba(0, 0, 0, 0.74)";
var finalCode = rgba2hex(colorcode)
function rgba2hex(orig) {
var a, isPercent,
rgb = orig.replace(/\s/g, '').match(/^rgba?\((\d+),(\d+),(\d+),?([^,\s)]+)?/i),
alpha = (rgb && rgb[4] || "").trim(),
hex = rgb ?
(rgb[1] | 1 << 8).toString(16).slice(1) +
(rgb[2] | 1 << 8).toString(16).slice(1) +
(rgb[3] | 1 << 8).toString(16).slice(1) : orig;
if (alpha !== "") { a = alpha; }
else { a = 01; }
hex = hex + a;
return hex;
}
console.log(finalCode)
Here I need alpha value also convert to hex code.
Please suggest how to convert
Output
Expect:000000bd
Since the alpha channel in your rgba() notation is expressed as a 0 ~ 1 value, you need to multiply it by 255 before trying to convert it to its HEX form:
var colorcode = "rgba(0, 0, 0, 0.74)";
var finalCode = rgba2hex(colorcode)
function rgba2hex(orig) {
var a, isPercent,
rgb = orig.replace(/\s/g, '').match(/^rgba?\((\d+),(\d+),(\d+),?([^,\s)]+)?/i),
alpha = (rgb && rgb[4] || "").trim(),
hex = rgb ?
(rgb[1] | 1 << 8).toString(16).slice(1) +
(rgb[2] | 1 << 8).toString(16).slice(1) +
(rgb[3] | 1 << 8).toString(16).slice(1) : orig;
if (alpha !== "") {
a = alpha;
} else {
a = 01;
}
// multiply before convert to HEX
a = ((a * 255) | 1 << 8).toString(16).slice(1)
hex = hex + a;
return hex;
}
function test(colorcode) {
console.log(colorcode, rgba2hex(colorcode));
}
test("rgba(0, 0, 0, 0.74)");
test("rgba(0, 0, 0, 1)");
test("rgba(0, 0, 0, 0)");
test("rgba(0, 255, 0, 0.5)");
But note that this is just one of the rgba notation, and that it will e.g fail with percent based notation.
Note also that all browsers do not support RGBA HEX notation, so you might prefer an other method to convert your values depending on what you want to do with it.
My solution. Hope be useful.
const rgbaToHex = (color: string): string => {
if (/^rgb/.test(color)) {
const rgba = color.replace(/^rgba?\(|\s+|\)$/g, '').split(',');
// rgb to hex
// eslint-disable-next-line no-bitwise
let hex = `#${((1 << 24) + (parseInt(rgba[0], 10) << 16) + (parseInt(rgba[1], 10) << 8) + parseInt(rgba[2], 10))
.toString(16)
.slice(1)}`;
// added alpha param if exists
if (rgba[4]) {
const alpha = Math.round(0o1 * 255);
const hexAlpha = (alpha + 0x10000).toString(16).substr(-2).toUpperCase();
hex += hexAlpha;
}
return hex;
}
return color;
};
Great #kaiido, i tried this way
function rgba2hex(orig) {
var a, isPercent,
rgb = orig.replace(/\s/g, '').match(/^rgba?\((\d+),(\d+),(\d+),?([^,\s)]+)?/i),
alpha = (rgb && rgb[4] || "").trim(),
hex = rgb ?
(rgb[1] | 1 << 8).toString(16).slice(1) +
(rgb[2] | 1 << 8).toString(16).slice(1) +
(rgb[3] | 1 << 8).toString(16).slice(1) : orig;
if (alpha !== "") {
a = alpha;
} else {
a = 01;
}
a = Math.round(a * 100) / 100;
var alpha = Math.round(a * 255);
var hexAlpha = (alpha + 0x10000).toString(16).substr(-2).toUpperCase();
hex = hex + hexAlpha;
return hex;
}
Try this:
✓ Works with alpha rgba(255, 255, 255, 0) => #ffffff00
✓ Works with single digits rgba(0, 0, 0, 0) => #00000000
✓ Works with RGB as well rgba(124, 255, 3) => #7cff03
✓ You can slice alpha channel away rgba(255, 255, 255, 0) => #ffffff
function RGBAToHexA(rgba, forceRemoveAlpha = false) {
return "#" + rgba.replace(/^rgba?\(|\s+|\)$/g, '') // Get's rgba / rgb string values
.split(',') // splits them at ","
.filter((string, index) => !forceRemoveAlpha || index !== 3)
.map(string => parseFloat(string)) // Converts them to numbers
.map((number, index) => index === 3 ? Math.round(number * 255) : number) // Converts alpha to 255 number
.map(number => number.toString(16)) // Converts numbers to hex
.map(string => string.length === 1 ? "0" + string : string) // Adds 0 when length of one number is 1
.join("") // Puts the array to togehter to a string
}
//
// Only tests below! Click "Run code snippet" to see results
//
// RGBA with Alpha value
expect(RGBAToHexA("rgba(255, 255, 255, 0)"), "#ffffff00")
expect(RGBAToHexA("rgba(0, 0, 0, 0)"), "#00000000")
expect(RGBAToHexA("rgba(124, 255, 3, 0.5)"), "#7cff0380")
expect(RGBAToHexA("rgba(124, 255, 3, 1)"), "#7cff03ff")
// RGB value
expect(RGBAToHexA("rgba(255, 255, 255)"), "#ffffff")
expect(RGBAToHexA("rgba(0, 0, 0)"), "#000000")
expect(RGBAToHexA("rgba(124, 255, 3)"), "#7cff03")
// RGBA without Alpha value
expect(RGBAToHexA("rgba(255, 255, 255, 0)", true), "#ffffff")
expect(RGBAToHexA("rgba(0, 0, 0, 0)", true), "#000000")
expect(RGBAToHexA("rgba(124, 255, 3, 0.5)", true), "#7cff03")
expect(RGBAToHexA("rgba(124, 255, 3, 1)", true), "#7cff03")
function expect(result, expectation) {
console.log(result === expectation ? "✓" : "X", result, expectation)
}
Code is built based on:
https://css-tricks.com/converting-color-spaces-in-javascript/
If you have the rgba color as a string, you can do something like this.
const color = 'rgba(249,6,6,1,0)';
const rgba = color.replace(/^rgba?\(|\s+|\)$/g, '').split(',');
const hex = `#${((1 << 24) + (parseInt(rgba[0]) << 16) + (parseInt(rgba[1]) << 8) + parseInt(rgba[2])).toString(16).slice(1)}`;
console.log(hex); // #f90606
Just create a function to be more effective! Code is same as above.
var color;
function HexCode(color){
const rgba = color.replace(/^rgba?\(|\s+|\)$/g, '').split(',');
const hex = `#${((1 << 24) + (parseInt(rgba[0]) << 16) + (parseInt(rgba[1]) << 8) + parseInt(rgba[2])).toString(16).slice(1)}`;
return hex;
}
console.log(HexCode('rgba(0,255,255,0.1)'))
Here is a simplified option.
function rgbToHex(rgb) {
return '#' + rgb.match(/[0-9|.]+/g).map((x,i) => i === 3 ? parseInt(255 * parseFloat(x)).toString(16) : parseInt(x).toString(16)).join('')
}
Works for rgb and rgba.

How can I generate the opposite color according to current color?

I'm trying to create a color opposite of current color. I mean if current color is black, then I need to generate white.
Actually I have a text (the color of this text is dynamic, its color can be made at random). That text is into a div and I need to set the opposite color of that text for the background-color of div. I would like that text be clear in the div (color perspective).
The opposite color means: Dark / Bright
I have the current color of text and I can pass it to this function:
var TextColor = #F0F0F0; // for example (it is a bright color)
function create_opp_color(current color) {
// create opposite color according to current color
}
create_opp_color(TextColor); // this should be something like "#202020" (or a dark color)
Is there any idea to create create_opp_color() function?
UPDATE: Production-ready code on GitHub.
This is how I'd do it:
Convert HEX to RGB
Invert the R,G and B components
Convert each component back to HEX
Pad each component with zeros and output.
function invertColor(hex) {
if (hex.indexOf('#') === 0) {
hex = hex.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6) {
throw new Error('Invalid HEX color.');
}
// invert color components
var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16),
g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16),
b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16);
// pad each with zeros and return
return '#' + padZero(r) + padZero(g) + padZero(b);
}
function padZero(str, len) {
len = len || 2;
var zeros = new Array(len).join('0');
return (zeros + str).slice(-len);
}
Example Output:
Advanced Version:
This has a bw option that will decide whether to invert to black or white; so you'll get more contrast which is generally better for the human eye.
function invertColor(hex, bw) {
if (hex.indexOf('#') === 0) {
hex = hex.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6) {
throw new Error('Invalid HEX color.');
}
var r = parseInt(hex.slice(0, 2), 16),
g = parseInt(hex.slice(2, 4), 16),
b = parseInt(hex.slice(4, 6), 16);
if (bw) {
// https://stackoverflow.com/a/3943023/112731
return (r * 0.299 + g * 0.587 + b * 0.114) > 186
? '#000000'
: '#FFFFFF';
}
// invert color components
r = (255 - r).toString(16);
g = (255 - g).toString(16);
b = (255 - b).toString(16);
// pad each with zeros and return
return "#" + padZero(r) + padZero(g) + padZero(b);
}
Example Output:
Simple and elegant.
function invertHex(hex) {
return (Number(`0x1${hex}`) ^ 0xFFFFFF).toString(16).substr(1).toUpperCase()
}
invertHex('00FF00'); // Returns FF00FF
Simple way to achieve this with CSS:
mix-blend-mode: difference;
color:white;
Pure CSS implementation of #Onur's answer bw part.
<input type="color" oninput="['--r','--g','--b'].forEach((k,i)=>this.nextElementSibling.style.setProperty(k,parseInt(event.target.value.slice(1+i*2,3+i*2),16)))" />
<div style="--r: 0; --g: 0; --b: 0; --c: calc(-1 * ((var(--r) * 0.299 + var(--g) * 0.587 + var(--b) * 0.114) - 186) * 255)">
<div style="background-color: rgb(var(--r), var(--g), var(--b)); color: rgb(var(--c), var(--c), var(--c))">Test</div>
</div>
How about, CSS filter: invert(1), it has a decent cross-browser compatibility and it work with text and images or whatever your content is.
For a black and white inverted color add some more filters filter: saturate(0) grayscale(1) brightness(.7) contrast(1000%) invert(1)
const div = document.querySelector("div");
const b = document.querySelector("b");
const input = document.querySelector("input");
input.oninput = (e) => {
const color = e.target.value;
div.style.background = color;
b.style.color = color;
b.innerText = color;
}
body {
font-family: Arial;
background: #333;
}
div {
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
min-width: 100px;
padding: .5em 1em;
border: 2px solid #FFF;
border-radius: 15px;
background: #378ad3;
font-style: normal;
}
b {
/* Inverting the color */
/* ᐯᐯᐯᐯᐯᐯᐯᐯᐯᐯᐯᐯ */
filter: saturate(0) grayscale(1) brightness(.7) contrast(1000%) invert(1);
}
input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
<div>
<b>#378ad3</b>
<input type="color" value="#378ad3"/>
</div>
Watch out Accesibility (AA/AAA). Colour contrast by itself is useless. Really different colors can have no contrast at all for colour blind people.
IMHO a calculation for such a color could go like this:
(Use "HLS" for simplicity)
Rotate Hue 180º to get the (maybe useless) maximal color contrast
Calculate Brightness Difference.
( Calculate Colour Difference... unnecesary, it's maximal or almost )
Calculate Contrast Ratio.
If the resulting color complies the requirements calculation ends, if not, loop:
If Brightness Difference is not enought increase or
decrese calculated color luminosity (L) by a certain amount or ratio (up or
down depending on the original colour brightness: > or < than the mid
value)
Check if it complies your requirements, if it does calculation ends.
if luminosity can be increased (or decrased) any more there is no valid color to comply the requirements, just try black and white, take "the best one" of those (probably the one with bigger contrast ratio) and end.
In my understanding of your question, by opposite color you mean inverted color.
InvertedColorComponent = 0xFF - ColorComponent
So for the color red (#FF0000) this means:
R = 0xFF or 255
G = 0x00 or 0
B = 0x00 or 0
inverted color red (#00FFFF) is:
R = 0xFF - 0xFF = 0x00 or 255 - 255 = 0
G = 0xFF - 0x00 = 0xFF or 255 - 0 = 255
B = 0xFF - 0x00 = 0xFF or 255 - 0 = 255
Another examples:
Black (#000000) becomes White (#FFFFFF).
Orange (#FFA500) becomes #005AFF
This is a simple function that invert an hexadecimal color
const invertColor = (col) => {
col = col.toLowerCase();
const colors = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
let inverseColor = '#'
col.replace('#','').split('').forEach(i => {
const index = colors.indexOf(i)
inverseColor += colors.reverse()[index]
})
return inverseColor
}
Codepen example
Simply flipping background color to text color won't work with some middle range values, e.g. 0x808080. I had tried with shifting the color values instead - (v + 0x80) % 0x100. See a demo here.
Agreeing with the comment from miguel-svq - although expecting to see more detailed algorithms for each calculation step.
It is possible to convert a HEX color using the snippets
function invertColor(color) {
return '#' + ("000000" + (0xFFFFFF ^ parseInt(color.substring(1),16)).toString(16)).slice(-6);
}
Function to Invert Color of Element. Gets the luminosity of each and if they are close, inverts text color.
function adjustColor(element) {
var style = window.getComputedStyle(element);
var background = new Color(style['background-color']);
var text = new Color(style['color']);
if (Math.abs(background.luma - text.luma) < 100) {
element.style.color = text.inverted.toString();
}
}
The Color "Class" below. Accepts hex, rgb, rgba (even with percents), and can output to either one as well. Explorer will need polyfills for String.padStart and String.startsWith and the interpolated string in the toString() method will need to be modified using concat instead.
const Color = (function () {
function toHex(num, padding) { return num.toString(16).padStart(padding || 2); }
function parsePart(value) {
var perc = value.lastIndexOf('%');
return perc < 0 ? value : value.substr(0, perc);
}
function Color(data) {
if (arguments.length > 1) {
this[0] = arguments[0];
this[1] = arguments[1];
this[2] = arguments[2];
if (arguments.length > 3) { this[3] = arguments[3]; }
} else if (data instanceof Color || Array.isArray(data)) {
this[0] = data[0];
this[1] = data[1];
this[2] = data[2];
this[3] = data[3];
} else if (typeof data === 'string') {
data = data.trim();
if (data[0] === "#") {
switch (data.length) {
case 4:
this[0] = parseInt(data[1], 16); this[0] = (this[0] << 4) | this[0];
this[1] = parseInt(data[2], 16); this[1] = (this[1] << 4) | this[1];
this[2] = parseInt(data[3], 16); this[2] = (this[2] << 4) | this[2];
break;
case 9:
this[3] = parseInt(data.substr(7, 2), 16);
//Fall Through
case 7:
this[0] = parseInt(data.substr(1, 2), 16);
this[1] = parseInt(data.substr(3, 2), 16);
this[2] = parseInt(data.substr(5, 2), 16);
break;
}
} else if (data.startsWith("rgb")) {
var parts = data.substr(data[3] === "a" ? 5 : 4, data.length - (data[3] === "a" ? 6 : 5)).split(',');
this.r = parsePart(parts[0]);
this.g = parsePart(parts[1]);
this.b = parsePart(parts[2]);
if (parts.length > 3) { this.a = parsePart(parts[3]); }
}
}
}
Color.prototype = {
constructor: Color,
0: 255,
1: 255,
2: 255,
3: 255,
get r() { return this[0]; },
set r(value) { this[0] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get g() { return this[1]; },
set g(value) { this[1] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get b() { return this[2]; },
set b(value) { this[2] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get a() { return this[3] / 255; },
set a(value) { this[3] = value == null ? 255 : Math.max(Math.min(value > 1 ? value : parseFloat(value) * 255, 255), 0); },
get luma() { return .299 * this.r + .587 * this.g + .114 * this.b; },
get inverted() { return new Color(255 - this[0], 255 - this[1], 255 - this[2], this[3]); },
toString: function (option) {
if (option === 16) {
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b) + (this[3] === 255 ? '' : toHex(this[3]));
} else if (option === '%') {
if (this.a !== 1) {
return `rgba(${this.r / 255 * 100}%, ${this.b / 255 * 100}%, ${this.g / 255 * 100}%, ${this.a / 255})`;
} else {
return `rgb(${this.r / 255 * 100}%, ${this.b / 255 * 100}%, ${this.g / 255 * 100})%`;
}
} else {
if (this.a !== 1) {
return `rgba(${this.r}, ${this.b}, ${this.g}, ${this.a})`;
} else {
return `rgb(${this.r}, ${this.b}, ${this.g})`;
}
}
}
};
return Color;
}());
Python alternatives of Onur's answer:
def hex_to_rgb(value):
value = value.lstrip('#')
lv = len(value)
return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
def invertColor(color, bw=False):
# strip the # from the beginning
color = color.lstrip('#')
# convert the string into hex
color = int(color, 16)
# invert the three bytes
# as good as substracting each of RGB component by 255(FF)
comp_color = 0xFFFFFF ^ color
# convert the color back to hex by prefixing a #
comp_color = "#%06X" % comp_color
rgb_color = hex_to_rgb(comp_color)
if (bw):
# http://stackoverflow.com/a/3943023/112731
bw_value = rgb_color[0]*0.299 + rgb_color[0]*0.587 + rgb_color[0]*0.114
if (bw_value>186):
comp_color = "#FFFFFF"
else:
comp_color = "#000000"
# return the result
return comp_color
color = "#fffff1"
print invertColor(color, bw=True)
For Typescript lovers, here what I use:
invertHex(hex: string) {
if (hex.indexOf('#') === 0) {
hex = hex.slice(1);
}
if (hex.length != 6) {
console.warn('Hex color must be six hex numbers in length.');
return '#' + hex;
}
hex = hex.toUpperCase();
const splitNum = hex.split('');
let resultNum = '';
const simpleNum = 'FEDCBA9876'.split('');
const complexNum = {
A: '5', B: '4', C: '3', D: '2', E: '1', F: '0'
};
for (let i = 0; i < 6; i++) {
if (!isNaN(Number(splitNum[i]))) {
resultNum += simpleNum[splitNum[i]];
} else if (complexNum[splitNum[i]]) {
resultNum += complexNum[splitNum[i]];
} else {
console.warn('Hex colors must only include hex numbers 0-9, and A-F');
return '#' + hex;
}
}
return '#' + resultNum;
}

Convert hexadecimal color to integer in javascript

I'm trying to convert a hexadecimal color string to a int in javascript.
The color int must be the same format as VB6. I think the bytes are not in the normal order. Ex: 255 is red (#ff0000) and 16776960 is Aqua (#00ffff)
I have a function to do the inverse: (But someone in the comments told me that it's not correct)
function VBColorToHEX(i) {
var hex = (i & 0xFF).toString(16) +
((i >> 8) & 0xFF).toString(16) +
((i >> 16) & 0xFF).toString(16) +
((i >> 24) & 0xFF).toString(16);
hex += '000000';
hex = hex.substring(0, 6);
return "#" + hex;
}
But was unable to write a function to return to my initial value.
Can you help me?
EDIT:
I corrected my original function by padding each separate colors:
function VBColorToHEX(i) {
var r = (i & 0xFF).toString(16);
var g = ((i >> 8) & 0xFF).toString(16);
var b = ((i >> 16) & 0xFF).toString(16);
r = ('0' + r).slice(-2);
g = ('0' + g).slice(-2);
b = ('0' + b).slice(-2);
return "#" + r + g + b;
}
Here's a working version of your original function, which I think will make more sense to you about how it actually works.
function VBColorToHEX(i) {
var bbggrr = ("000000" + i.toString(16)).slice(-6);
var rrggbb = bbggrr.substr(4, 2) + bbggrr.substr(2, 2) + bbggrr.substr(0, 2);
return "#" + rrggbb;
}
Then, to do the reverse, do this:
function HEXToVBColor(rrggbb) {
var bbggrr = rrggbb.substr(4, 2) + rrggbb.substr(2, 2) + rrggbb.substr(0, 2);
return parseInt(bbggrr, 16);
}
function VBColorToHEX(i) {
var hex = (i & 0xFF).toString(16) +
((i >> 8) & 0xFF).toString(16) +
((i >> 16) & 0xFF).toString(16) +
((i >> 24) & 0xFF).toString(16);
hex += '000000'; // pad result
hex = hex.substring(0, 6);
return "#" + hex;
}
You're padding the result with zeroes instead of padding each color value.
For instance if i = 657930, the string hex value is something like #0A0A0A but you'll output #AAA000 instead.
Beside, if you're extracting 4 color channels you need 8 chars and not 6.
PS for the padding, see for instance this solution.

JavaScript - how do you programmatically calculate colours?

In a JavaScript/jQuery app, I want to set the color of a div element based on an external variable. From low to high values of this variable, you go past the colors green to red. Now, I could do this:
setColor: function(quantity)
{
var color;
if(quantity <= -1000)
{
color = '#00ff00'
}
else if(quantity > -1000 && quantity <= -900)
{
color = '#11ee00'
}
// a million more else if statements
return color;
}
Anything that's -1000 or below is #00ff00 (green), and everything that's +1000 or above is #ff0000 (red), with 0 being #ffff00 (yellow). There's lots of color variations in between these 3 extremes: for example, a value of -950 would be a slightly more redder shade of green than -951.
But isn't there a formula for this kind of stuff, so that I don't end with a 1000 line function?
"A slightly more redder shade of green" becomes yellowish, because the color in the middle between red and green is yellow. So this function returns an RGB-string beeing pure green when value is <= lower limit, red when value >= upper limit and yellow when value is middle (0 in your case), and all shades in between.
var low = -1000, upp = 1000,
mid = (upp + low) / 2, dif = (upp - low) / 2;
function grade(value) {
var r = 255, g = 255, b = 0;
if (value <= low) r = 0;
else if (value >= upp) g = 0;
else if (value < mid) r = Math.round(255 * Math.abs(low - value) / dif);
else if (value > mid) g = Math.round(255 * Math.abs(upp - value) / dif);
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
Adjust vars low and upp to your usecase. The function is easy to adapt to colorchanges between green/cyan/blue or red/purple/blue. If you need a full rainbow some more effort is required.
First of all it is good to separate decoration logic(color value) and set classes for the different colors and set those to the div.
I had a task of that kind and used sin fuctions of every chanel with different amplitude, period and shift for every channel:
var ColorPicker = {
colors: {},
init: function(range){
var ra = 190,
rp = 8/3*range,
rs = range*2/3;
var ga = 190,
gp = range,
gs = 0;
var ba = 150,
bp = 8/3*range,
bs = range;
var pipi = 2*Math.PI;
var r, g, b, w;
for (var i = 0; i < range; i++) {
r = ra*Math.cos(i*pipi/rp + rs*pipi/range);
g = ga*Math.cos(i*pipi/gp + gs*pipi/range);
b = ba*Math.cos(i*pipi/bp + bs*pipi/range);
r = Math.round( ( r > 0 ) ? r : 0 );
g = Math.round( ( g > 0 ) ? g : 0 );
b = Math.round( ( b > 0 ) ? b : 0 );
w = Math.round( i/range*255);
this.colors[i] = {red: r, green: g, blue: b, white: w};
};
},
getColorObj: function(grade){
return this.colors[grade];
},
getRGB: function(grade, coef){
var o = this.colors[grade];
if (!coef){
coef = 1;
}
var r = (Math.round(o.red*coef)>255)?255:Math.round(o.red*coef),
g = (Math.round(o.green*coef)>255)?255:Math.round(o.green*coef),
b = (Math.round(o.blue*coef)>255)?255:Math.round(o.blue*coef);
return 'rgb(' + r + ','
+ g + ','
+ b + ')';
},
// get shades of BW
getW: function(grade){
var o = this.colors[grade];
return 'rgb(' + o.white + ','
+ o.white + ','
+ 0.9*o.white + ')';
},
// opposite to BW
getB: function(grade){
var o = this.colors[grade],
b = 255 - o.white;
// console.log(b);
return 'rgb(' + b + ','
+ b + ','
+ .9*b + ')';
},
};
May need to rewrite it though. Don't think it is an optimal solution now.
There is a color manipulation library that's called TinyColor.
What you want to do, is vary the hue. This would be done like this:
var red = tinycolor("#FF0000").toHsv();
var green = tinycolor("#00FF00").toHsv(), h, col, hex;
h = green.h + (red.h-green.h)*(quantity+1000)/2000;
col = tinycolor({h: h, s: 0.5, v: 0.5});
hex = col.toHex();
See demo here

Categories

Resources