how to edit pixels and remove white background in a canvas image in html5 and javascript

By | January 12, 2018
Questions:

If I load an image, how can I loop through all its pixels and turn the white ones (or which ever color I specify) to be turned transparent?

I have an idea on how to do this, but the looping process should be like a 2d array, so it would involve two for loops.

I was thinking I would start on the top row first pixel, iterating to the right, if its a white pixel, then i turn it transparent, and move 1 pixel to the right, if its not white, then I stop. Then in the same row, I start from the left most pixel, and check, if white, I turn it transparent, then move 1 pixel to the left, etc, etc…

Then I move 1 row down and repeat the whole process..

This way I don’t remove any white pixels in the actual image.

Answers:

Its pretty simple to do using getImageData and putImageData just note you can take a pretty significant hit on performance the larger the image gets. You just need to determine if the current pixel is white, then change its alpha to 0.

Live Demo

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    image = document.getElementById("testImage");

canvas.height = canvas.width = 135;
ctx.drawImage(image,0,0);

var imgd = ctx.getImageData(0, 0, 135, 135),
    pix = imgd.data,
    newColor = {r:0,g:0,b:0, a:0};

for (var i = 0, n = pix.length; i <n; i += 4) {
    var r = pix[i],
            g = pix[i+1],
            b = pix[i+2];

        // If its white then change it
        if(r == 255 && g == 255 && b == 255){ 
            // Change the white to whatever.
            pix[i] = newColor.r;
            pix[i+1] = newColor.g;
            pix[i+2] = newColor.b;
            pix[i+3] = newColor.a;
        }
}

ctx.putImageData(imgd, 0, 0);​

It was also asked if you could make the values sort of fuzzy to check. Its really easy, just check if its in a certain range. The following will turn off white to pure white transparent.

 // If its white or close then change it
    if(r >=230 && g >= 230 && b >= 230){ 
        // Change the white to whatever.
        pix[i] = newColor.r;
        pix[i+1] = newColor.g;
        pix[i+2] = newColor.b;
        pix[i+3] = newColor.a;
    }

More resources

Questions:
Answers:

Loktar may have a method that ‘works’, but it’s performance is rather dismal. This can be a problem if you have lots of images, you don’t want your website to drain laptop/mobile-devices batteries, or if you just want speed. Here is a method that works far more efficiently. Click on the “Run Code Snippet” button for a demo of it in action.

'use-strict'
let fileInput = document.getElementById('fileInput'),
  theCANVAS = document.getElementById('theCanvas'),
  theCANVASctx = theCANVAS.getContext('2d'),
  imgTMP = document.getElementById('imgTMP'),
  rComponent = document.getElementById('r'),
  gComponent = document.getElementById('g'),
  bComponent = document.getElementById('b'),
  aComponent = document.getElementById('a'),
  transColor = "rgba(255, 255, 255, 1)",
  transCode = 0xffffffff;

let makeColorTransparent =
  function(canvasContext, transparentID, width, height) {
    // where all the magic happens
    let theImageData = canvasContext.getImageData(0, 0, width, height),
      theImageDataBufferTMP = new ArrayBuffer(theImageData.data.length),
      theImageDataClamped8TMP = new Uint8ClampedArray(theImageDataBufferTMP),
      theImageDataUint32TMP = new Uint32Array(theImageDataBufferTMP),
      n = theImageDataUint32TMP.length;
    theImageDataClamped8TMP.set(theImageData.data);

    imgDataLoop: while (n--) {
      // effciency at its finest:
      if (theImageDataUint32TMP[n] !== transparentID)
        continue imgDataLoop;
      theImageDataUint32TMP[n] = 0x00000000; // make it transparent
    }
    theImageData.data.set(theImageDataClamped8TMP);
    theCANVASctx.putImageData(theImageData, 0, 0);
  },
  downloadCanvas = function(downloadfilename) {
    theCanvas.toBlob(function(theIMGblob) {
      var thedataURL = URL.createObjectURL(theIMGblob),
        theAtagLink = document.createElement('a');

      theAtagLink.download = '(proccessed)' + downloadfilename;
      document.body.appendChild(theAtagLink);
      theAtagLink.href = thedataURL;
      theAtagLink.click();
    });
  };

fileInput.onchange = function(fileevent) {
  let efiles = fileevent.target.files,
    localTransColor = transColor,
    localTransCode = transCode;

  let cur = efiles.length,
    nextfile = function() {
      if (!cur--) {
        imgTMP.src = '';
        return;
      }
      let fr = new FileReader();
      console.log(efiles[cur]);
      fr.onload = function(dataevt) {
        fr.onload = null;
        let theArrayBuffer = dataevt.target.result,
          theblob = new Blob([theArrayBuffer]);
        imgTMP.src = URL.createObjectURL(theblob);
        imgTMP.onload = function() {
          imgTMP.onload = null;
          let theImagesWidth = imgTMP.naturalWidth,
            theImagesHeight = imgTMP.naturalHeight;

          theCANVAS.width = theImagesWidth;
          theCANVAS.height = theImagesHeight;

          theCANVASctx.fillStyle = localTransColor;
          theCANVASctx.clearRect(
            0,
            0,
            theImagesWidth,
            theImagesHeight
          );
          theCANVASctx.drawImage(imgTMP, 0, 0);
          makeColorTransparent(
            theCANVASctx,
            localTransCode,
            theImagesWidth,
            theImagesHeight
          );

          //now, download the file:
          downloadCanvas(efiles[cur].name);

          //Finally, procced to proccess the next file
          nextfile();
        };
      };
      fr.readAsArrayBuffer(efiles[cur]);
    };
  nextfile();
}

rComponent.oninput = gComponent.oninput =
  bComponent.oninput = aComponent.oninput =
  function() {
    rComponent.value = Math.max(0, Math.min(rComponent.value, 255));
    gComponent.value = Math.max(0, Math.min(gComponent.value, 255));
    bComponent.value = Math.max(0, Math.min(bComponent.value, 255));
    aComponent.value = Math.max(0, Math.min(aComponent.value, 255));
  };

rComponent.onchange = gComponent.onchange =
  bComponent.onchange = aComponent.onchange =
  function() {
    transColor = 'rgba(' +
      rComponent.value + ',' +
      gComponent.value + ',' +
      bComponent.value + ',' +
      aComponent.value / 255 + ',' +
      ')';
    // numberical equivelent of the rgba
    transCode =
      rComponent.value * 0x00000001 +
      gComponent.value * 0x00000100 +
      bComponent.value * 0x00010000 +
      aComponent.value * 0x01000000;
  };
<pre>rgba(<input type="number" value="255" max="255" min="0" step="1" id="r" maxlength="3" minlength="1" />,<input type="number" value="255" max="255" min="0" step="1" id="g" maxlength="3" minlength="1" />,<input type="number" value="255" max="255" min="0" step="1" id="b" maxlength="3" minlength="1" />,<input type="number" value="255" max="255" min="0" step="1" id="a" maxlength="3" minlength="1" />)</pre>

<input type="file" name="filefield" multiple="multiple" accept="image/*" id="fileInput" /><br />
<img id="imgTMP" />
<canvas id="theCanvas"></canvas>

<style>input[type=number]{width: 3em}#theCanvas {display: none}</style>

Leave a Reply

Your email address will not be published. Required fields are marked *