javascript - Canvas change image background color but keep it's "effects" -
i have image need change it's background color, keep "effects" on (on image black dots, white lines etc.)
here's orginal image:
i managed change color, keep removing "effects". preview:
here's code:
//let's want red var r = 255; var g = 0; var b = 0; var imgelement = document.getelementbyid('img'); var canvas = document.getelementbyid('canvas'); canvas.width = imgelement.width; canvas.height = imgelement.height; var ctx = canvas.getcontext("2d"); ctx.drawimage(imgelement, 0, 0); var imagedata = ctx.getimagedata(0, 0, canvas.width, canvas.height); var data = imagedata.data; (var = 0; < data.length; += 4) { if (data[i + 3] !== 0) { data[i] = r; data[i + 1] = g; data[i + 2] = b; data[i + 3] = data[i + 3]; } } ctx.putimagedata(imagedata, 0, 0);
<img src="foo" id="img" /> <canvas id="canvas"></canvas>
how prevent that?
for modern browsers except internet explorer, can use compositing change hue of original image while leaving saturation & lightness unchanged. "recolor" original image while leaving contours intact.
example code works in modern browsers except internet explorer
var canvas=document.getelementbyid("canvas"); var ctx=canvas.getcontext("2d"); var img=new image(); img.onload=start; img.src="https://dl.dropboxusercontent.com/u/139992952/multple/m449a.png"; function start(){ // create overlay solid #00d9c6 color var tempcanvas=document.createelement('canvas'); var tempctx=tempcanvas.getcontext('2d'); canvas.width=tempcanvas.width=img.width; canvas.height=tempcanvas.height=img.height; tempctx.drawimage(img,0,0); tempctx.globalcompositeoperation='source-atop'; tempctx.fillstyle='#00d9c6'; tempctx.fillrect(0,0,tempcanvas.width,tempcanvas.height); // canvas.width=img.width; canvas.height=img.height; // use compositing change hue of original image ctx.drawimage(img,0,0); ctx.globalcompositeoperation='hue'; ctx.drawimage(tempcanvas,0,0); // clean up: reset compositing default ctx.globalcompositeoperation='source-over'; }
#canvas{border:1px solid red; }
<canvas id="canvas" width=300 height=300></canvas>
since internet explorer not support blend compositing, have manually.
- read rgba value of each pixel.
- convert rgba value hsl.
- shift hue value (the "h" in hsl) difference between blue hue , desired green hue.
- convert hue-shifted hsl value rgba value.
- write hue-shifted rgba value pixel.
here's example code of manually shifting hue:
important note: manual method works manipulating pixels .getimagedata
. therefore must make sure original image hosted on same domain webpage. otherwise, canvas become tainted security reasons , not able use .getimagedata
.
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 greenish colors recolorpants(-.33); } function recolorpants(colorshift) { var imgdata = ctx.getimagedata(150, 0, canvas.width, canvas.height); var data = imgdata.data; (var = 0; < data.length; += 4) { red = data[i + 0]; green = data[i + 1]; blue = data[i + 2]; alpha = data[i + 3]; // skip transparent/semitransparent pixels if (alpha < 200) { continue; } var hsl = rgbtohsl(red, green, blue); var hue = hsl.h * 360; // change blueish pixels 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), }); }
<p>example shifting color hue .getimagedata</p> <p>(original: left, recolored: right)</p> <canvas id="canvas" width=300 height=300></canvas>
Comments
Post a Comment