最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - HTML5 Canvas: Invert Color of Pixels - Stack Overflow

programmeradmin0浏览0评论

I am following the tutorial on WC3 found here: .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:

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?

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?

Share Improve this question asked Aug 19, 2016 at 21:58 Kasper_SkyKasper_Sky 1071 gold badge1 silver badge3 bronze badges 2
  • 1 Your code works on my side. Make sure the image you are loading is actually available and being loaded. – ASDFGerte Commented Aug 19, 2016 at 22:15
  • 1 I needed to do exactly this, except preserve transparency for a drawn image. By adding a conditional check within the loop for imgData.data[i] > 0, you avoid all transparent pixels. – EvilJordan Commented Dec 4, 2016 at 3:08
Add a comment  | 

4 Answers 4

Reset to default 26

You can use compositing to invert your image as long as your browser supports blending.

Advantages:

  • This is faster than getImageData
  • The canvas won't object with cross-origin security restrictions

ctx.drawImage(img,0,0);
ctx.globalCompositeOperation='difference';
ctx.fillStyle='white';
ctx.fillRect(0,0,canvas.width,canvas.height);

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

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) {}
    }
  }

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!

发布评论

评论列表(0)

  1. 暂无评论