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

后端 未结 3 907
时光取名叫无心
时光取名叫无心 2020-12-04 23:09

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

相关标签:
3条回答
  • 2020-12-04 23:17

    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

    • Pixel manipulation with canvas
    • Further info on pixel manipulation with canvas
    0 讨论(0)
  • 2020-12-04 23:31

    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>

    0 讨论(0)
  • 2020-12-04 23:38

    You can use an image processing framework to not handle pixel data manually.

    In the case of MarvinJ, given a color, you can set all pixels to transparent with a single line:

    image.setColorToAlpha(0, 0);
    

    Input image:

    Result:

    Runnable Example:

    var canvas = document.getElementById("canvas");
    image = new MarvinImage();
    image.load("https://i.imgur.com/UuvzbLx.png", imageLoaded);
    
    function imageLoaded(){
    	image.setColorToAlpha(0, 0);	
    	image.draw(canvas);
    }
    <script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
    <div style="width:400px; height:352px;  background-image: linear-gradient(45deg, #808080 25%, transparent 25%),
    	linear-gradient(-45deg, #808080 25%, transparent 25%),
    	linear-gradient(45deg, transparent 75%, #808080 75%), 
    	linear-gradient(-45deg, transparent 75%, #808080 75%);
    	background-size: 20px 20px;
    	background-position: 0 0, 0 10px, 10px -10px, -10px 0px;">
    <canvas id="canvas" width="400" height="352"></canvas>
    </div> 

    0 讨论(0)
提交回复
热议问题