Smoothly fade image RGB by setting SRC data Javascript - javascript

I am working on emulating the behavior of the server box on https://mcprohosting.com/ but without sending multiple images (currently there are 3 images that rotate using javascripts .fadeout() calls and such.
My best attempt at doing this right now consists of parsing over the image pixels using HTML 5.
That being said there are a few problems:
I can't figure out how to smoothly transition between 3 preset colors.
The entire RGB spectrum is getting affected, whereas only the green colored section should be affected.
The logo is also being affected, how would I go about excluding this from the changed section? I presume I would have to manually specific the bounds of this element, but how would I do that specifically?
EDITED
I now convert RGB to HSL and vice-versa in order to do this change, the problem still lies in that the 'lightness' appears to be off. The dark parts of the server are too dark and lose detail
Here is the code:
<script type="text/javascript">
var mug = document.getElementById("server_green");
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var originalPixels = null;
var currentPixels = null;
function getPixels(img) {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
originalPixels = ctx.getImageData(0, 0, img.width, img.height);
currentPixels = ctx.getImageData(0, 0, img.width, img.height);
img.onload = null;
}
var t = 0;
function changeColor() {
//Checks if the image was loaded
if(!originalPixels) {
return;
}
//var blue = changeHue(rgbToHex(originalPixels.data[i], originalPixels.data[i + 1], originalPixels.data[i + 2]), t);
//var green = changeHue(rgbToHex(originalPixels.data[i], originalPixels.data[i + 1], originalPixels.data[i + 2]), t);
for(var i = 0, L = originalPixels.data.length; i < L; i += 4) {
var red = changeHue(originalPixels.data[i], originalPixels.data[i + 1], originalPixels.data[i + 2], t);
// If it's not a transparent pixel
if(currentPixels.data[i + 3] > 0 && originalPixels.data[i + 1] <= 255) {
currentPixels.data[i] = originalPixels.data[i] / 255 * red[0];
currentPixels.data[i + 1] = originalPixels.data[i + 1] / 255 * red[1];
currentPixels.data[i + 2] = originalPixels.data[i + 2] / 255 * red[2];
}
}
ctx.putImageData(currentPixels, 0, 0);
var data = canvas.toDataURL("image/png");
mug.src = data;
t += 10;
console.log("Running: " + t);
}
$(document).ready(function() {
setInterval(function() {
changeColor();
}, 10);
});
function changeHue(r, g, b, degree) {
var hsl = rgbToHSL(r, g, b);
hsl.h += degree;
if (hsl.h > 360) {
hsl.h -= 360;
} else if (hsl.h < 0) {
hsl.h += 360;
}
return hslToRGB(hsl);
}
function rgbToHSL(r, g, b) {
r = r / 255;
g = g / 255;
b = b / 255;
var cMax = Math.max(r, g, b),
cMin = Math.min(r, g, b),
delta = cMax - cMin,
l = (cMax + cMin) / 3,
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
}
}
function hslToRGB(hsl) {
var h = hsl.h,
s = hsl.s,
l = hsl.l,
//Chroma
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);
var rgb = new Array(r, g, b);
return rgb;
}
function normalize_rgb_value(color, m) {
color = Math.floor((color + m) * 255);
if (color < 0) {
color = 0;
}
return color;
}
</script>
And the resulting image (too dark) http://puu.sh/614dn/bf85b336ca.jpg

alternate solution (still using one image):
use a transparent png and + a coloring layer (beneath the png)
change the coloring layer's color with css transitions or javascript

The problem you are facing is caused by the color model, for instance white is made from red, green and blue. by adjusting the blue, you also affect the white.
you could use a solid chroma key to achieve the desired result, test the pixel for the key color and adjust if it's a match.
Here is a tutorial.

Related

JS - Find x,y of middle of black square in image

I have a bunch of images like this one:
http://i.imgur.com/kW8UaA4.png
I need to find the x,y of the middle of the dark square.
I currently have the following code:
https://jsfiddle.net/brampower/tw08fdhf/
function rgbToHsl(r, g, b) {
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b),
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 ({
h: h,
s: s,
l: l,
});
}
function solve_darkest(url, callback) {
var image = new Image();
image.crossOrigin = "Anonymous";
image.src = url;
image.onload = function(){
var canvas = document.createElement('canvas');
var WIDTH = image.width;
var HEIGHT = image.height;
canvas.width = WIDTH;
canvas.height = HEIGHT;
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
document.body.appendChild(canvas);
var imgData = context.getImageData(0, 0, WIDTH, HEIGHT);
var pixel = 0;
var darkest_pixel_lightness = 100;
var darkest_pixel_location = 0;
for (var i = 0; i < imgData.data.length; i += 4, pixel++) {
red = imgData.data[i + 0];
green = imgData.data[i + 1];
blue = imgData.data[i + 2];
alpha = imgData.data[i + 3];
if (alpha < 230) {
continue;
}
console.log(Math.floor(pixel / WIDTH) + " ", i % WIDTH);
var hsl = rgbToHsl(red, green, blue);
var lightness = hsl.l;
if (lightness < darkest_pixel_lightness) {
darkest_pixel_lightness = lightness;
darkest_pixel_location = pixel;
}
}
var y = Math.floor(darkest_pixel_location / WIDTH);
var x = darkest_pixel_location % WIDTH;
callback(x,y);
};
}
image_url = 'http://i.imgur.com/kW8UaA4.png';
solve_darkest(image_url, function(x, y) {
setTimeout(function() {
alert('x: '+x+' y: '+y);
}, 100);
});
But it is not giving me the results I am expecting. It loops through all the pixels and then returns the x and y of the darkest pixel. However, it appears that the darkest pixel doesn't reside in the dark square area.
What can I do to make it return the x,y of the middle of the darker square?

How to accurately filter RGB value for chroma-key effect

I just read this tutorial and tried this example. So I downloaded a video from web for my own testing. All I have to do is tweak rgb values in if conditions
HERE is the sample code from example
computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;
for (let i = 0; i < l; i++) {
let r = frame.data[i * 4 + 0];
let g = frame.data[i * 4 + 1];
let b = frame.data[i * 4 + 2];
if (g > 100 && r > 100 && b < 43)
frame.data[i * 4 + 3] = 0;
}
this.ctx2.putImageData(frame, 0, 0);
return;
}
In the tutorial example its filtering out yellow(not yellow I guess) color. The sample video I downloaded uses green background. So I tweaked rgb value in if condition to get desired results
After multiple tries, I managed to get this.
Now what I want to know is how can I accurately filter out green screen (or any other screen)perfectly without guessing. Or randomly tweaking values.
With just guessing it take hours to get it perfectly right. And this is just a sample with a real world application. It can take maybe more.
NOTE: The example is working in Firefox for now..
You probably just need a better algorithm. Here's one, it's not perfect, but you can tweak it a lot easier.
Basically you'll just need a colorpicker, and pick the lightest and darkest values from the video (putting the RGB values in the l_ and d_ variables respectively). You can adjust the tolerance a little bit if you need to, but getting the l_ and r_ values just right by picking different areas with the color picker will give you a better key.
let l_r = 131,
l_g = 190,
l_b = 137,
d_r = 74,
d_g = 148,
d_b = 100;
let tolerance = 0.05;
let processor = {
timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
let self = this;
setTimeout(function () {
self.timerCallback();
}, 0);
},
doLoad: function() {
this.video = document.getElementById("video");
this.c1 = document.getElementById("c1");
this.ctx1 = this.c1.getContext("2d");
this.c2 = document.getElementById("c2");
this.ctx2 = this.c2.getContext("2d");
let self = this;
this.video.addEventListener("play", function() {
self.width = self.video.videoWidth;
self.height = self.video.videoHeight;
self.timerCallback();
}, false);
},
calculateDistance: function(c, min, max) {
if(c < min) return min - c;
if(c > max) return c - max;
return 0;
},
computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;
for (let i = 0; i < l; i++) {
let _r = frame.data[i * 4 + 0];
let _g = frame.data[i * 4 + 1];
let _b = frame.data[i * 4 + 2];
let difference = this.calculateDistance(_r, d_r, l_r) +
this.calculateDistance(_g, d_g, l_g) +
this.calculateDistance(_b, d_b, l_b);
difference /= (255 * 3); // convert to percent
if (difference < tolerance)
frame.data[i * 4 + 3] = 0;
}
this.ctx2.putImageData(frame, 0, 0);
return;
}
};
// :/
If performance does not matter, then you could work in another color space e.g. HSV. You could use the left top pixel as reference.
You compare the hue value of the reference point with hue value other pixels, and exclude all pixels that exceed a certain threshold and dark and light areas using saturation and value.
This how ever does not completely get rid of color bleeding, there you might need to do some color correct/desaturation.
function rgb2hsv () {
var rr, gg, bb,
r = arguments[0] / 255,
g = arguments[1] / 255,
b = arguments[2] / 255,
h, s,
v = Math.max(r, g, b),
diff = v - Math.min(r, g, b),
diffc = function(c){
return (v - c) / 6 / diff + 1 / 2;
};
if (diff == 0) {
h = s = 0;
} else {
s = diff / v;
rr = diffc(r);
gg = diffc(g);
bb = diffc(b);
if (r === v) {
h = bb - gg;
}else if (g === v) {
h = (1 / 3) + rr - bb;
}else if (b === v) {
h = (2 / 3) + gg - rr;
}
if (h < 0) {
h += 1;
}else if (h > 1) {
h -= 1;
}
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
v: Math.round(v * 100)
};
}
let processor = {
timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
let self = this;
setTimeout(function () {
self.timerCallback();
}, 0);
},
doLoad: function() {
this.video = document.getElementById("video");
this.c1 = document.getElementById("c1");
this.ctx1 = this.c1.getContext("2d");
this.c2 = document.getElementById("c2");
this.ctx2 = this.c2.getContext("2d");
let self = this;
this.video.addEventListener("play", function() {
self.width = self.video.videoWidth / 2;
self.height = self.video.videoHeight / 2;
self.timerCallback();
}, false);
},
computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;
let reference = rgb2hsv(frame.data[0], frame.data[1], frame.data[2]);
for (let i = 0; i < l; i++) {
let r = frame.data[i * 4 + 0];
let g = frame.data[i * 4 + 1];
let b = frame.data[i * 4 + 2];
let hsv = rgb2hsv(r, g, b);
let hueDifference = Math.abs(hsv.h - reference.h);
if( hueDifference < 20 && hsv.v > 50 && hsv.s > 50 ) {
frame.data[i * 4 + 3] = 0;
}
}
this.ctx2.putImageData(frame, 0, 0);
return;
}
};

ocanvas sprite hue change

I'm using ocanvas to design a game and I'm wondering if there is some way to change the hue of a sprite. If not, is there a way to integrate an html5 canvas way of changing the hue of a sprite to ocanvas?
I don't have information about ocanvas, but here's how to change the hue of a sprite drawn onto an html5 canvas.
This method uses context.getImageData to fetch the color data of every pixel on the canvas. Then any pixel with a blue-ish hue is changed to a green-ish hue.
Note: If your sprites have more discrete coloring (f.ex: the sprite has a specific blue color that you wish to change to a specific green color) then you won't need to convert to-and-from the HSL color format.
If necessary, you can convert this recolored html5 canvas into a sprite-image to include in ocanvas using .toDataURL.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.crossOrigin="anonymous";
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/marioStanding.png";
function start(){
ctx.drawImage(img,0,0);
ctx.drawImage(img,150,0);
// shift blueish colors to greenish colors
recolorPants(-.33);
}
function recolorPants(colorshift){
var imgData=ctx.getImageData(150,0,canvas.width,canvas.height);
var data=imgData.data;
for(var i=0;i<data.length;i+=4){
red=data[i+0];
green=data[i+1];
blue=data[i+2];
alpha=data[i+3];
// skip transparent/semiTransparent pixels
if(alpha<230){continue;}
var hsl=rgbToHsl(red,green,blue);
var hue=hsl.h*360;
// change blueish pixels to the new color
if(hue>200 && hue<300){
var newRgb=hslToRgb(hsl.h+colorshift,hsl.s,hsl.l);
data[i+0]=newRgb.r;
data[i+1]=newRgb.g;
data[i+2]=newRgb.b;
data[i+3]=255;
}
}
ctx.putImageData(imgData,150,0);
}
function rgbToHsl(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), 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({
h:h,
s:s,
l:l,
});
}
function hslToRgb(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return({
r:Math.round(r * 255),
g:Math.round(g * 255),
b:Math.round(b * 255),
});
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<p>Example shifting color Hue with .getImageData</p>
<p>(Original: left, Recolored: right)</p>
<canvas id="canvas" width=300 height=300></canvas>
Another popular solution is to use grayscale images and color them in JS via globalCompositeOperation in canvas. Described in detail here: http://buildnewgames.com/global-composit-operations/#colored-sprite-masks-with-codesource-atopcode
I put together an example of how it could be done in conjunction with oCanvas: http://jsfiddle.net/g0tj7vrv/
HTML:
<script src="https://cdnjs.cloudflare.com/ajax/libs/ocanvas/2.7.4/ocanvas.min.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
JS:
var canvas = oCanvas.create({
canvas: '#canvas',
background: '#000'
});
canvas.display.register('colorizedImage', {
hue: '',
path: '',
width: 0,
heigth: 0,
_renderNewColor: function(tempImage) {
if (!this._tempCanvas) {
this._tempCanvas = document.createElement('canvas');
}
this._createColorizedImage(this._tempCanvas, tempImage, this.hue);
var self = this;
setTimeout(function() {
self.core.redraw();
}, 0);
},
_createColorizedImage: function(tempCanvas, imageElement, hue) {
var tempContext = tempCanvas.getContext('2d');
tempCanvas.width = imageElement.width;
tempCanvas.height = imageElement.height;
tempContext.drawImage(imageElement, 0, 0);
tempContext.fillStyle = 'hsla(' + hue + ', 50%, 50%, 0.5)';
tempContext.globalCompositeOperation = 'source-atop';
tempContext.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
}
}, function(context) {
if (this._tempCanvas) {
var origin = this.getOrigin();
var x = this.abs_x - origin.x;
var y = this.abs_y - origin.y;
var w = this.width || this._tempCanvas.width;
var h = this.height || this._tempCanvas.height;
context.drawImage(this._tempCanvas, x, y, w, h);
}
if (this.path !== this._lastPathBeingLoaded) {
this._lastPathBeingLoaded = this.path;
var tempImage = new Image();
tempImage.src = this.path;
var self = this;
tempImage.onload = function() {
if (self.path === this.src) {
self._renderNewColor(tempImage);
}
};
this._lastImageElement = tempImage;
}
if (this.hue !== this._lastHueBeingLoaded) {
this._lastHueBeingLoaded = this.hue;
this._renderNewColor(this._lastImageElement);
}
});
var colorizedImage = canvas.display.colorizedImage({
hue: 0,
path: 'https://dl.dropboxusercontent.com/u/2645586/gco/cobra-primary.png',
origin: {x: -60, y: 0},
width: 120,
height: 120,
x: canvas.width / 2,
y: canvas.height / 2
});
canvas.addChild(colorizedImage);
canvas.setLoop(function() {
colorizedImage.hue = (colorizedImage.hue + 10) % 360;
colorizedImage.rotation -= 2;
}).start();

Filtering specific range of numbers from an array

I'm creating an algorithm that will blur the border of a canvas(image). Before applying the blur effect, I am creating an array filtered that includes all pixel values that needs to be blurred.
I've created an example with a 10×10px image.
function compute(w, h, bW) {
w *= 4;
var ignored = [];
for (y = bW; y < (h - bW); y++) {
for (x = 0; x < (w - (bW * 4 * 2)); x++) {
ignored.push(w * y + x + bW * 4);
}
}
console.log(ignored);
function range(limit) {
return Array.apply(null, Array(limit)).map(function(_, i) {
return i;
})
}
Array.prototype.diff = function(array) {
return this.filter(function(elem) {
return array.indexOf(elem) === -1;
})
}
var filtered = range(w * h).diff(ignored);
console.log(filtered);
return filtered;
}
compute(10, 10, 2);
//////////////////////////////////////////////////////////////////
// Below is just to display the numbers that are being filtered //
// Here, the size is 100 x 100 px with 10px border width //
//////////////////////////////////////////////////////////////////
var pixels = compute(100, 100, 10);
var c = document.getElementsByTagName('canvas')[0];
var ctx = c.getContext('2d');
var imgD = ctx.createImageData(100, 100);
for (var i = 0; i < imgD.data.length; i += 4) {
if (pixels.indexOf(i) > 0) {
imgD.data[i + 0] = 0;
imgD.data[i + 1] = 0;
imgD.data[i + 2] = 0;
imgD.data[i + 3] = 255;
} else {
imgD.data[i + 0] = 255;
imgD.data[i + 1] = 0;
imgD.data[i + 2] = 0;
imgD.data[i + 3] = 255;
}
}
ctx.putImageData(imgD, 10, 10);
<canvas></canvas>
The array filtered contains all the numbers that has the background color and ignored contains all the numbers that has the background color and in the image.
My question is:
How do I change my code so that the array filtered will have the numbers with background color and and not ?
An Example on a bit high resolution(65×65px):
FIDDLEJS : http://jsfiddle.net/t14gr6pL/2/
Explanation:
It depends on the width of your triangles (the second color). In the 64*64 example, this width is 7.
Let's assume that this width (tw) is calculate like this (you can change) :
var tw = (2 * bW) - 1;
So your code would be:
function compute(w, h, bW) {
var filtered = [];
var WIDTH_MULTIPLICATOR = 4;
var bH = bW;
w *= WIDTH_MULTIPLICATOR;
bW *= WIDTH_MULTIPLICATOR;
var triangleWidth = (2 * bW) - 1;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
if (
// Borders
(Math.min(x, w - x) < bW) ||
(Math.min(y, h - y) < bH) ||
// Adding "Triangles"
(Math.min(x, w - x) < bW + triangleWidth - Math.max(0, Math.min(y, h - y) - bH) * WIDTH_MULTIPLICATOR)
) {
filtered.push(w * y + x);
}
}
}
return filtered;
}

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

Categories

Resources