Use CMYK on web page - javascript

I need to use CMYK colors on my web page. Is there any way to use CMYK in CSS or may be convert CMYK to RGB using JavaScript?
EDIT:
I mean I have colors creating algorithm in CMYK notation and I need to use it on web page.

There is no perfect algorithmic way to convert CMYK to RGB. CYMK is a subtractive color system, RGB is an additive color system. Each have different gamuts, which means there are colors that just cannot be represented in the other color system and vice versa. Both are device dependent color spaces, which really means that what color you really get is dependent on which device you use to reproduce that color, which is why you have color profiles for each device that adjust how it produces color into something more "absolute".
The best that you can do is approximate a simulation of one space onto the other. There is an entire field of computer science that is dedicated to this kind of work, and its non-trivial.
If you are looking for a heuristic for doing this, then the link that Cyrille provided is pretty simple math, and easily invertible to accept a CYMK color and produce a reasonable RGB facsimile.
A very simple heuristic is to map cyan to 0x00FFFF, magenta to 0xFF00FF, and yellow to 0xFFFF00, and black (key) to 0x000000. Then do something like this:
function cmykToRGB(c,m,y,k) {
function padZero(str) {
return "000000".substr(str.length)+str
}
var cyan = (c * 255 * (1-k)) << 16;
var magenta = (m * 255 * (1-k)) << 8;
var yellow = (y * 255 * (1-k)) >> 0;
var black = 255 * (1-k);
var white = black | black << 8 | black << 16;
var color = white - (cyan | magenta | yellow );
return ("#"+padZero(color.toString(16)));
}
invoking cmykToRGB with cmyk ranges from 0.0 to 1.0. That should give you back an RGB color code. But again this is just a heuristic, an actual conversation between these color spaces is much more complicated and takes into account a lot more variables then are represented here. You mileage may vary, and the colors you get out of this might not "look right"
jsFiddle here

There's no way to use CMYK in CSS. You can either use RGB or HSL (CSS3 only). Here's a JavaScript algorithm to convert CMYK to RGB (and the other way around).
Edit: the link seems dead now, here's the code from a cached version:
/**
*
* Javascript color conversion
* http://www.webtoolkit.info/
*
**/
function HSV(h, s, v) {
if (h <= 0) { h = 0; }
if (s <= 0) { s = 0; }
if (v <= 0) { v = 0; }
if (h > 360) { h = 360; }
if (s > 100) { s = 100; }
if (v > 100) { v = 100; }
this.h = h;
this.s = s;
this.v = v;
}
function RGB(r, g, b) {
if (r <= 0) { r = 0; }
if (g <= 0) { g = 0; }
if (b <= 0) { b = 0; }
if (r > 255) { r = 255; }
if (g > 255) { g = 255; }
if (b > 255) { b = 255; }
this.r = r;
this.g = g;
this.b = b;
}
function CMYK(c, m, y, k) {
if (c <= 0) { c = 0; }
if (m <= 0) { m = 0; }
if (y <= 0) { y = 0; }
if (k <= 0) { k = 0; }
if (c > 100) { c = 100; }
if (m > 100) { m = 100; }
if (y > 100) { y = 100; }
if (k > 100) { k = 100; }
this.c = c;
this.m = m;
this.y = y;
this.k = k;
}
var ColorConverter = {
_RGBtoHSV : function (RGB) {
var result = new HSV(0, 0, 0);
r = RGB.r / 255;
g = RGB.g / 255;
b = RGB.b / 255;
var minVal = Math.min(r, g, b);
var maxVal = Math.max(r, g, b);
var delta = maxVal - minVal;
result.v = maxVal;
if (delta == 0) {
result.h = 0;
result.s = 0;
} else {
result.s = delta / maxVal;
var del_R = (((maxVal - r) / 6) + (delta / 2)) / delta;
var del_G = (((maxVal - g) / 6) + (delta / 2)) / delta;
var del_B = (((maxVal - b) / 6) + (delta / 2)) / delta;
if (r == maxVal) { result.h = del_B - del_G; }
else if (g == maxVal) { result.h = (1 / 3) + del_R - del_B; }
else if (b == maxVal) { result.h = (2 / 3) + del_G - del_R; }
if (result.h < 0) { result.h += 1; }
if (result.h > 1) { result.h -= 1; }
}
result.h = Math.round(result.h * 360);
result.s = Math.round(result.s * 100);
result.v = Math.round(result.v * 100);
return result;
},
_HSVtoRGB : function (HSV) {
var result = new RGB(0, 0, 0);
var h = HSV.h / 360;
var s = HSV.s / 100;
var v = HSV.v / 100;
if (s == 0) {
result.r = v * 255;
result.g = v * 255;
result.v = v * 255;
} else {
var_h = h * 6;
var_i = Math.floor(var_h);
var_1 = v * (1 - s);
var_2 = v * (1 - s * (var_h - var_i));
var_3 = v * (1 - s * (1 - (var_h - var_i)));
if (var_i == 0) {var_r = v; var_g = var_3; var_b = var_1}
else if (var_i == 1) {var_r = var_2; var_g = v; var_b = var_1}
else if (var_i == 2) {var_r = var_1; var_g = v; var_b = var_3}
else if (var_i == 3) {var_r = var_1; var_g = var_2; var_b = v}
else if (var_i == 4) {var_r = var_3; var_g = var_1; var_b = v}
else {var_r = v; var_g = var_1; var_b = var_2};
result.r = var_r * 255;
result.g = var_g * 255;
result.b = var_b * 255;
result.r = Math.round(result.r);
result.g = Math.round(result.g);
result.b = Math.round(result.b);
}
return result;
},
_CMYKtoRGB : function (CMYK){
var result = new RGB(0, 0, 0);
c = CMYK.c / 100;
m = CMYK.m / 100;
y = CMYK.y / 100;
k = CMYK.k / 100;
result.r = 1 - Math.min( 1, c * ( 1 - k ) + k );
result.g = 1 - Math.min( 1, m * ( 1 - k ) + k );
result.b = 1 - Math.min( 1, y * ( 1 - k ) + k );
result.r = Math.round( result.r * 255 );
result.g = Math.round( result.g * 255 );
result.b = Math.round( result.b * 255 );
return result;
},
_RGBtoCMYK : function (RGB){
var result = new CMYK(0, 0, 0, 0);
r = RGB.r / 255;
g = RGB.g / 255;
b = RGB.b / 255;
result.k = Math.min( 1 - r, 1 - g, 1 - b );
result.c = ( 1 - r - result.k ) / ( 1 - result.k );
result.m = ( 1 - g - result.k ) / ( 1 - result.k );
result.y = ( 1 - b - result.k ) / ( 1 - result.k );
result.c = Math.round( result.c * 100 );
result.m = Math.round( result.m * 100 );
result.y = Math.round( result.y * 100 );
result.k = Math.round( result.k * 100 );
return result;
},
toRGB : function (o) {
if (o instanceof RGB) { return o; }
if (o instanceof HSV) { return this._HSVtoRGB(o); }
if (o instanceof CMYK) { return this._CMYKtoRGB(o); }
},
toHSV : function (o) {
if (o instanceof HSV) { return o; }
if (o instanceof RGB) { return this._RGBtoHSV(o); }
if (o instanceof CMYK) { return this._RGBtoHSV(this._CMYKtoRGB(o)); }
},
toCMYK : function (o) {
if (o instanceof CMYK) { return o; }
if (o instanceof RGB) { return this._RGBtoCMYK(o); }
if (o instanceof HSV) { return this._RGBtoCMYK(this._HSVtoRGB(o)); }
}
}
Usage:
To convert from HSV to RGB use library like this:
var result = ColorConverter.toRGB(new HSV(10, 20, 30));
alert("RGB:" + result.r + ":" + result.g + ":" + result.b);
To convert from RGB to HSV use library like this:
var result = ColorConverter.toHSV(new RGB(10, 20, 30));
alert("HSV:" + result.h + ":" + result.s + ":" + result.v);
The same goes for CMYK.

CMYK support in CSS is currently considered by W3 for CSS3. But it’s mainly meant for printers and “it is not expected that screen-centric user agents support CMYK colors”. I think you can safely bet that none of the current browsers support CMYK for the screen and therefore you have to convert the colors to RGB somehow.

In the CSS Color Module Level 4 of the W3C as of 5 November 2019, there is a function called device-cmyk that can be used to define a device dependent CMYK color value.
Example:
color: device-cmyk(0 81% 81% 30%);
The function returns an RGB value that the device calculates by trying to convert the CMYK color to an RGB value that matches the CMYK color as close as possible.
Note: I can't find anything regarding the browser support. I guess that no browser is currently supporting this.

You can create your own SCSS/SASS function.
SCSS:
#function cmyk($c, $m, $y, $k) {
$c: $c / 100;
$m: $m / 100;
$y: $y / 100;
$k: $k / 100;
$r: 255 * (1 - $c) * (1 - $k);
$g: 255 * (1 - $m) * (1 - $k);
$b: 255 * (1 - $y) * (1 - $k);
#return rgb($r, $g, $b);
}
SASS:
#function cmyk($c, $m, $y, $k)
$c: $c / 100
$m: $m / 100
$y: $y / 100
$k: $k / 100
$r: 255 * (1 - $c) * (1 - $k)
$g: 255 * (1 - $m) * (1 - $k)
$b: 255 * (1 - $y) * (1 - $k)
#return rgb($r, $g, $b)

Related

Converting between color models

I'm trying to make buttons for converting between color models (hex, rgb, hsl).
I've created a button that generates a random color when clicked on.
And I've created a class that generates the random color in rgb and has methods to convert it to hex or hsl.
I tried creating a "click" event listener on each of the color model buttons but I'm not able to access the newly generated color object that I made through the class (block scope).
Should I have just used normal functions to convert instead of a class constructor?
const colorName = document.querySelector(".colorName");
const genColorBtn = document.querySelector("#genColorBtn");
const hexBtn = document.querySelector("#hexBtn");
const rgbBtn = document.querySelector("#rgbBtn");
const hslBtn = document.querySelector("#hslBtn");
// Generate Random Color
const genRandomColor = () => {
const r = Math.floor(Math.random() * 255 + 1);
const g = Math.floor(Math.random() * 255 + 1);
const b = Math.floor(Math.random() * 255 + 1);
return new Color(r, g, b);
};
genColorBtn.addEventListener("click", function () {
const newColor = genRandomColor();
document.body.style.backgroundColor = newColor.rgb();
colorName.innerText = newColor.rgb();
});
// Color Model Conversions
class Color {
constructor(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
this.calcHSL();
}
// Add methods to the prototype.
hex() {
const { r, g, b } = this;
return (
"#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
);
}
rgb() {
const { r, g, b } = this;
return `rgb(${r}, ${g}, ${b})`;
}
hsl() {
const { h, s, l } = this;
return `hsl(${h}, ${s}%, ${l}%)`;
}
// For hsl
calcHSL() {
let { r, g, b } = this;
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r, g, b),
cmax = Math.max(r, g, b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
if (delta == 0) h = 0;
else if (cmax == r)
// Red is max
h = ((g - b) / delta) % 6;
else if (cmax == g)
// Green is max
h = (b - r) / delta + 2;
// Blue is max
else h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0) h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
// Assign h, s, l to the object instance so that we can reuse it.
this.h = h;
this.s = s;
this.l = l;
}
}
<body>
<main>
<h1>Random Color Flipper</h1>
<h2>Color: <span class="colorName">rgb(255, 255, 255)</span></h2>
<div class="colorModes">
<button id="hexBtn">hex</button>
<button id="rgbBtn">rgb</button>
<button id="hslBtn">hsl</button>
</div>
<button id="genColorBtn">Generate Color</button>
</main>
<script src="app.js"></script>
</body>
Your code seems fine, but your hex, rgb and hsl buttons were not wired up. I added a variable curRGB to store the current RGB values (though there is probably a more elegant getter/setter for your Class that could be written). I did take a stab at the hexBtn listener:
hexBtn.addEventListener("click", function () {
colorName.innerText = new Color(...curRGB).hex();
});
const colorName = document.querySelector(".colorName");
const genColorBtn = document.querySelector("#genColorBtn");
const hexBtn = document.querySelector("#hexBtn");
const rgbBtn = document.querySelector("#rgbBtn");
const hslBtn = document.querySelector("#hslBtn");
let curRGB
// Generate Random Color
const genRandomColor = () => {
const r = Math.floor(Math.random() * 255 + 1);
const g = Math.floor(Math.random() * 255 + 1);
const b = Math.floor(Math.random() * 255 + 1);
curRGB = [r, g, b]
return new Color(r, g, b);
};
genColorBtn.addEventListener("click", function () {
const newColor = genRandomColor();
document.body.style.backgroundColor = newColor.rgb();
colorName.innerText = newColor.rgb();
});
hexBtn.addEventListener("click", function () {
colorName.innerText = new Color(...curRGB).hex();
});
// Color Model Conversions
class Color {
constructor(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
this.calcHSL();
}
// Add methods to the prototype.
hex() {
const { r, g, b } = this;
return (
"#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
);
}
rgb() {
const { r, g, b } = this;
return `rgb(${r}, ${g}, ${b})`;
}
hsl() {
const { h, s, l } = this;
return `hsl(${h}, ${s}%, ${l}%)`;
}
// For hsl
calcHSL() {
let { r, g, b } = this;
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r, g, b),
cmax = Math.max(r, g, b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
if (delta == 0) h = 0;
else if (cmax == r)
// Red is max
h = ((g - b) / delta) % 6;
else if (cmax == g)
// Green is max
h = (b - r) / delta + 2;
// Blue is max
else h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0) h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
// Assign h, s, l to the object instance so that we can reuse it.
this.h = h;
this.s = s;
this.l = l;
}
}
<main>
<h1>Random Color Flipper</h1>
<h2>Color: <span class="colorName">rgb(255, 255, 255)</span></h2>
<div class="colorModes">
<button id="hexBtn">hex</button>
<button id="rgbBtn">rgb</button>
<button id="hslBtn">hsl</button>
</div>
<button id="genColorBtn">Generate Color</button>
</main>

Custom marker icons color

Is there any new API to create custom icons given a color and text? I'd like to send an hex color.
I've been using a couple of URL to generate my markers icons but now it seems to be deprecated.
I have not been able to find a new one
There is my old function:
function getIcon(text, fillColor, textColor, outlineColor) {
if (!text) text = '•'; //generic map dot
var iconUrl = "https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=" + text + "|" + fillColor;
//var iconUrl = "http://chart.googleapis.com/chart?cht=d&chdp=mapsapi&chl=pin%27i\\%27[" + text + "%27-2%27f\\hv%27a\\]h\\]o\\" + fillColor + "%27fC\\" + textColor + "%27tC\\" + outlineColor + "%27eC\\Lauto%27f\\&ext=.png";
return iconUrl;
}
Thanks in advance!
If you are open to put in some code here is a link which can convert an image, in your case the marker to a desired colour.
Codepen Link
'use strict';
class Color {
constructor(r, g, b) {
this.set(r, g, b);
}
toString() {
return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)})`;
}
set(r, g, b) {
this.r = this.clamp(r);
this.g = this.clamp(g);
this.b = this.clamp(b);
}
hueRotate(angle = 0) {
angle = angle / 180 * Math.PI;
const sin = Math.sin(angle);
const cos = Math.cos(angle);
this.multiply([
0.213 + cos * 0.787 - sin * 0.213,
0.715 - cos * 0.715 - sin * 0.715,
0.072 - cos * 0.072 + sin * 0.928,
0.213 - cos * 0.213 + sin * 0.143,
0.715 + cos * 0.285 + sin * 0.140,
0.072 - cos * 0.072 - sin * 0.283,
0.213 - cos * 0.213 - sin * 0.787,
0.715 - cos * 0.715 + sin * 0.715,
0.072 + cos * 0.928 + sin * 0.072,
]);
}
grayscale(value = 1) {
this.multiply([
0.2126 + 0.7874 * (1 - value),
0.7152 - 0.7152 * (1 - value),
0.0722 - 0.0722 * (1 - value),
0.2126 - 0.2126 * (1 - value),
0.7152 + 0.2848 * (1 - value),
0.0722 - 0.0722 * (1 - value),
0.2126 - 0.2126 * (1 - value),
0.7152 - 0.7152 * (1 - value),
0.0722 + 0.9278 * (1 - value),
]);
}
sepia(value = 1) {
this.multiply([
0.393 + 0.607 * (1 - value),
0.769 - 0.769 * (1 - value),
0.189 - 0.189 * (1 - value),
0.349 - 0.349 * (1 - value),
0.686 + 0.314 * (1 - value),
0.168 - 0.168 * (1 - value),
0.272 - 0.272 * (1 - value),
0.534 - 0.534 * (1 - value),
0.131 + 0.869 * (1 - value),
]);
}
saturate(value = 1) {
this.multiply([
0.213 + 0.787 * value,
0.715 - 0.715 * value,
0.072 - 0.072 * value,
0.213 - 0.213 * value,
0.715 + 0.285 * value,
0.072 - 0.072 * value,
0.213 - 0.213 * value,
0.715 - 0.715 * value,
0.072 + 0.928 * value,
]);
}
multiply(matrix) {
const newR = this.clamp(this.r * matrix[0] + this.g * matrix[1] + this.b * matrix[2]);
const newG = this.clamp(this.r * matrix[3] + this.g * matrix[4] + this.b * matrix[5]);
const newB = this.clamp(this.r * matrix[6] + this.g * matrix[7] + this.b * matrix[8]);
this.r = newR;
this.g = newG;
this.b = newB;
}
brightness(value = 1) {
this.linear(value);
}
contrast(value = 1) {
this.linear(value, -(0.5 * value) + 0.5);
}
linear(slope = 1, intercept = 0) {
this.r = this.clamp(this.r * slope + intercept * 255);
this.g = this.clamp(this.g * slope + intercept * 255);
this.b = this.clamp(this.b * slope + intercept * 255);
}
invert(value = 1) {
this.r = this.clamp((value + this.r / 255 * (1 - 2 * value)) * 255);
this.g = this.clamp((value + this.g / 255 * (1 - 2 * value)) * 255);
this.b = this.clamp((value + this.b / 255 * (1 - 2 * value)) * 255);
}
hsl() {
// Code taken from https://stackoverflow.com/a/9493060/2688027, licensed under CC BY-SA.
const r = this.r / 255;
const g = this.g / 255;
const b = this.b / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {
h: h * 100,
s: s * 100,
l: l * 100,
};
}
clamp(value) {
if (value > 255) {
value = 255;
} else if (value < 0) {
value = 0;
}
return value;
}
}
class Solver {
constructor(target, baseColor) {
this.target = target;
this.targetHSL = target.hsl();
this.reusedColor = new Color(0, 0, 0);
}
solve() {
const result = this.solveNarrow(this.solveWide());
return {
values: result.values,
loss: result.loss,
filter: this.css(result.values),
};
}
solveWide() {
const A = 5;
const c = 15;
const a = [60, 180, 18000, 600, 1.2, 1.2];
let best = { loss: Infinity };
for (let i = 0; best.loss > 25 && i < 3; i++) {
const initial = [50, 20, 3750, 50, 100, 100];
const result = this.spsa(A, a, c, initial, 1000);
if (result.loss < best.loss) {
best = result;
}
}
return best;
}
solveNarrow(wide) {
const A = wide.loss;
const c = 2;
const A1 = A + 1;
const a = [0.25 * A1, 0.25 * A1, A1, 0.25 * A1, 0.2 * A1, 0.2 * A1];
return this.spsa(A, a, c, wide.values, 500);
}
spsa(A, a, c, values, iters) {
const alpha = 1;
const gamma = 0.16666666666666666;
let best = null;
let bestLoss = Infinity;
const deltas = new Array(6);
const highArgs = new Array(6);
const lowArgs = new Array(6);
for (let k = 0; k < iters; k++) {
const ck = c / Math.pow(k + 1, gamma);
for (let i = 0; i < 6; i++) {
deltas[i] = Math.random() > 0.5 ? 1 : -1;
highArgs[i] = values[i] + ck * deltas[i];
lowArgs[i] = values[i] - ck * deltas[i];
}
const lossDiff = this.loss(highArgs) - this.loss(lowArgs);
for (let i = 0; i < 6; i++) {
const g = lossDiff / (2 * ck) * deltas[i];
const ak = a[i] / Math.pow(A + k + 1, alpha);
values[i] = fix(values[i] - ak * g, i);
}
const loss = this.loss(values);
if (loss < bestLoss) {
best = values.slice(0);
bestLoss = loss;
}
}
return { values: best, loss: bestLoss };
function fix(value, idx) {
let max = 100;
if (idx === 2 /* saturate */) {
max = 7500;
} else if (idx === 4 /* brightness */ || idx === 5 /* contrast */) {
max = 200;
}
if (idx === 3 /* hue-rotate */) {
if (value > max) {
value %= max;
} else if (value < 0) {
value = max + value % max;
}
} else if (value < 0) {
value = 0;
} else if (value > max) {
value = max;
}
return value;
}
}
loss(filters) {
// Argument is array of percentages.
const color = this.reusedColor;
color.set(0, 0, 0);
color.invert(filters[0] / 100);
color.sepia(filters[1] / 100);
color.saturate(filters[2] / 100);
color.hueRotate(filters[3] * 3.6);
color.brightness(filters[4] / 100);
color.contrast(filters[5] / 100);
const colorHSL = color.hsl();
return (
Math.abs(color.r - this.target.r) +
Math.abs(color.g - this.target.g) +
Math.abs(color.b - this.target.b) +
Math.abs(colorHSL.h - this.targetHSL.h) +
Math.abs(colorHSL.s - this.targetHSL.s) +
Math.abs(colorHSL.l - this.targetHSL.l)
);
}
css(filters) {
function fmt(idx, multiplier = 1) {
return Math.round(filters[idx] * multiplier);
}
return `filter: invert(${fmt(0)}%) sepia(${fmt(1)}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(4)}%) contrast(${fmt(5)}%);`;
}
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, (m, r, g, b) => {
return r + r + g + g + b + b;
});
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16),
]
: null;
}
$(document).ready(() => {
$('button.execute').click(() => {
const rgb = hexToRgb($('input.target').val());
if (rgb.length !== 3) {
alert('Invalid format!');
return;
}
const color = new Color(rgb[0], rgb[1], rgb[2]);
const solver = new Solver(color);
const result = solver.solve();
let lossMsg;
if (result.loss < 1) {
lossMsg = 'This is a perfect result.';
} else if (result.loss < 5) {
lossMsg = 'The is close enough.';
} else if (result.loss < 15) {
lossMsg = 'The color is somewhat off. Consider running it again.';
} else {
lossMsg = 'The color is extremely off. Run it again!';
}
$('.realPixel').css('background-color', color.toString());
$('.filterPixel').attr('style', result.filter);
$('.filterDetail').text(result.filter);
$('.lossDetail').html(`Loss: ${result.loss.toFixed(1)}. <b>${lossMsg}</b>`);
});
});
You can then send this filter output to CSS of your marker and it will change the colour of the image

Automatic Hex rgb colour generation

I am generating heatmap style colours in JavaScript based on the values from cold to hot. But for some reason I am getting some pinks and some purples.
There are lots of answers on stackoverflow but they mostly relate to generating using HSL, and unfortunately for Google Earth I need RGBA format (backwards as ABGR)
1 = red = hot
0.5 = green = middle
0 = blue = cold
function generateColor(value) {
var r = Math.round(value * 255),
g = Math.round((1 - Math.abs(0.5 - value)) * 255),
b = Math.round((1 - value) * 255);
r = r.toString(16);
g = g.toString(16);
b = b.toString(16);
if (r.length < 2) {
r += r;
}
if (g.length < 2) {
g += g;
}
if (b.length < 2) {
b += b;
}
return 'ff' + b + g + r;
}
There's a bug in here somewhere!! Here's a fiddle I've been using to try and work out the problem:
http://jsfiddle.net/kmturley/sT8BL/1/
I think your problem is here:
if (r.length < 2) {
r += r;
}
If r is just one character, add a 0, not itself to it:
if (r.length < 2) {
r = "0" + r;
}
In just one line:
r = ("0" + r.toString(16)).slice(-2);
But you can also put most of the function in just a line:
function generateColor(value) {
var r = Math.round(value * 255),
g = Math.round((1 - Math.abs(0.5 - value)) * 255),
b = Math.round((1 - value) * 255);
return (0xff000000 + 0x10000 * b + 256 * g + r).toString(16);
}

Change the Hue of a RGB Color in javascript

Similar to this (how to increase brightness) I want to change the Hue of a RGB (Hex) Color.
Say changeHue("#FF0000", 40) returns "#FFAA00"
Here is the solution I found. I hope its usable and might help in the future. Any improvements or further solutions are very welcome.
Change Hue
// Changes the RGB/HEX temporarily to a HSL-Value, modifies that value
// and changes it back to RGB/HEX.
function changeHue(rgb, degree) {
var hsl = rgbToHSL(rgb);
hsl.h += degree;
if (hsl.h > 360) {
hsl.h -= 360;
}
else if (hsl.h < 0) {
hsl.h += 360;
}
return hslToRGB(hsl);
}
// exepcts a string and returns an object
function rgbToHSL(rgb) {
// strip the leading # if it's there
rgb = rgb.replace(/^\s*#|\s*$/g, '');
// convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
if(rgb.length == 3){
rgb = rgb.replace(/(.)/g, '$1$1');
}
var r = parseInt(rgb.substr(0, 2), 16) / 255,
g = parseInt(rgb.substr(2, 2), 16) / 255,
b = parseInt(rgb.substr(4, 2), 16) / 255,
cMax = Math.max(r, g, b),
cMin = Math.min(r, g, b),
delta = cMax - cMin,
l = (cMax + cMin) / 2,
h = 0,
s = 0;
if (delta == 0) {
h = 0;
}
else if (cMax == r) {
h = 60 * (((g - b) / delta) % 6);
}
else if (cMax == g) {
h = 60 * (((b - r) / delta) + 2);
}
else {
h = 60 * (((r - g) / delta) + 4);
}
if (delta == 0) {
s = 0;
}
else {
s = (delta/(1-Math.abs(2*l - 1)))
}
return {
h: h,
s: s,
l: l
}
}
// expects an object and returns a string
function hslToRGB(hsl) {
var h = hsl.h,
s = hsl.s,
l = hsl.l,
c = (1 - Math.abs(2*l - 1)) * s,
x = c * ( 1 - Math.abs((h / 60 ) % 2 - 1 )),
m = l - c/ 2,
r, g, b;
if (h < 60) {
r = c;
g = x;
b = 0;
}
else if (h < 120) {
r = x;
g = c;
b = 0;
}
else if (h < 180) {
r = 0;
g = c;
b = x;
}
else if (h < 240) {
r = 0;
g = x;
b = c;
}
else if (h < 300) {
r = x;
g = 0;
b = c;
}
else {
r = c;
g = 0;
b = x;
}
r = normalize_rgb_value(r, m);
g = normalize_rgb_value(g, m);
b = normalize_rgb_value(b, m);
return rgbToHex(r,g,b);
}
function normalize_rgb_value(color, m) {
color = Math.floor((color + m) * 255);
if (color < 0) {
color = 0;
}
return color;
}
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
Usage
changeHue("#FF0000", 40) --> returns #ffaa00
changeHue("#D61E1E", 180) --> returns #1ed6d6
changeHue("#2244BB", -80) --> returns #21bb66
References
RGB to HSL
HSL to RGB
Inital Hex to RGB Conversion
If you're not afraid of libraries and a few kb won't ruin your project, you could try sc-color rather than reimplementing the wheel...
Here's a jsfiddle using sc-color. The crux of the code is here:
var c = sc_color("#FF0000").hue(40).hex6();
$("#test").css("background-color", c);
Disclosure: I'm the author of sc-color

Changing pixel in canvas imageData to hsl(60, 100%, 50%)

I would like to change pixels of an HTML5 canvas to an hsl value. It could be any hsl value that is chosen by the user.
I can get the canvas imageData with var imageData = canvas.getImageData(0, 0, 200, 200);
But the imageData.data array contains values in rgba. Actually each value in the array is a byte so -
data[0] = r, data[1] = b, data[2] = g, data[3] = a, data[4] = r, data[5] = b, data[6] = g, data[7] = a etc.
Is there an api that can be used to manipulate imageData? An api that would abstract the raw data so that - data[0] = rgba, data[1] = rgba etc?
And that might have methods like - data[0].setValueHSL(60, 100%, 50%);
If this api does not exist is there a class that can create/represent an hsl value and which can convert the value to rgb?
I am not sure if you are still looking for the answer since this was asked a long time ago. But I was trying to do the same and encountered the answer on Why doesn't this Javascript RGB to HSL code work?, this should do the trick :
function rgbToHsl(r, g, b) {
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return 'hsl(' + Math.floor(h * 360) + ',' + Math.floor(s * 100) + '%,' + Math.floor(l * 100) + '%)';
}
You could write one its as simple as this
parseImageData = function(imageData) {
var newImageData = [];
for ( var i = imageData - 1; i>0; i-4) {
newImageData.push([ imageData[i],
imageData[i-1],
imageData[i-2],
imageData[i-3] ]);
}
return newImageData;
}
then if you want to convert it back
parseNewImageData = function ( newImageData ) {
var imageData = [];
for ( var i = newImageData - 1; i>=0; --i) {
imageData.push( imageData[i][0] );
imageData.push( imageData[i][1] );
imageData.push( imageData[i][2] );
imageData.push( imageData[i][3] );
}
return imageData;
}
super easy and you can make it do specifically what you need it to!
I hope this helps!

Categories

Resources