Reputation: 107
I am following the tutorial on WC3 found here: http://www.w3schools.com/tags/canvas_getimagedata.asp
I have my image loaded up and next to this is the canvas which I have a nice boarder and I'm intending to display side-by-side images. I am attempting to invert the color of the pixel as the demonstration but I cannot get the colors to change I don't understand why.
Here is my code pen where I separated the HTML from the JS: http://codepen.io/kKasper/pen/zBXWOZ
document.getElementById("team").onload = function() {
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("team");
ctx.drawImage(img, 0, 0);
var imgData = ctx.getImageData(0, 0, c.width, c.height);
// invert colors
var i;
for (i = 0; i < imgData.data.length; i += 4) {
imgData.data[i] = 255 - imgData.data[i];
imgData.data[i+1] = 255 - imgData.data[i+1];
imgData.data[i+2] = 255 - imgData.data[i+2];
imgData.data[i+3] = 255;
}
ctx.putImageData(imgData, 0, 0);
};
It appears that ctx.drawImage(img, 0, 0); is drawing my image inside the canvas. For some reason the function that works on the WC3 tutorial is not working properly on my image because when it draws the image after the function there are no changes.
Can anyone help me solve this please?
Upvotes: 8
Views: 14982
Reputation: 17922
ctx.filter = 'invert(1)'
is best but has limited browser support, so check if it is supported, otherwise use ctx.globalCompositeOperation = 'difference'
which alone does not maintain transparency, but a clipping mask can be created and used to reset that. As some old browsers like IE do not support difference
also check if that is supported and revert to using the ImageData and if the image does not have CORS support catch any error caused by tainted canvas.
if (ctx.filter) {
ctx.filter = 'invert(1)';
ctx.drawImage(img, 0, 0);
} else {
ctx.drawImage(img, 0, 0);
ctx.globalCompositeOperation = 'difference';
if (ctx.globalCompositeOperation === 'difference') {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, img.width, img.height);
var canvas2 = document.createElement('canvas');
var ctx2 = canvas2.getContext('2d');
canvas2.width = img.width;
canvas2.height = img.height;
ctx2.drawImage(img, 0, 0);
ctx2.globalCompositeOperation = 'source-in';
ctx2.fillStyle = 'black';
ctx2.fillRect(0, 0, img.width, img.height);
ctx.globalCompositeOperation = 'destination-in';
ctx.drawImage(canvas2, 0, 0);
} else {
try {
var imgData = ctx.getImageData(0, 0, img.width, img.height);
var data = imgData.data;
for (var i = 0; i < data.length; i += (i % 4 === 2 ? 2 : 1)) {
data[i] = 255 - data[i];
}
ctx.putImageData(imgData, 0, 0);
} catch (e) {}
}
}
Upvotes: 2
Reputation: 18043
Similar to markE's answer, but maintains transparency / alpha channel during draw.
ctx.filter = 'invert(1)'
ctx.drawImage(img, 0, 0)
There's loads of other filters you can apply as well
if you want to save to a base64
data url, you can use the following after drawing to your canvas
const dataUrl = canvas.toDataURL()
If you're getting error messages about a tainted canvas, before you set your image.src, set the crossOrigin
property to 'Anonymous'
:
const img = new Image()
img.crossOrigin = 'Anonymous'
img.onload = myLoadFn
img.src = myImgUrl
Upvotes: 6
Reputation: 105015
You can use compositing to invert your image as long as your browser supports blending.
Advantages:
getImageData
ctx.drawImage(img,0,0);
ctx.globalCompositeOperation='difference';
ctx.fillStyle='white';
ctx.fillRect(0,0,canvas.width,canvas.height);
Upvotes: 26
Reputation: 3854
Try opening your browser's developer console on your Codepen. I'm getting this error:
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
This means that you've drawn an image from another domain (i.e. not codepen.io
) onto the canvas. As a security feature to prevent malicious scripts from communicating with external domains, browsers will disallow JS from accessing such data. See the MDN article on the same-origin policy.
Try running your code from a local file, or using an image from the same domain as the page. I bet it will work.
The dev console is your friend!
Upvotes: 0