如何在html5和javascript中编辑像素并删除画布图像中的白色背景

时间:2012-07-13 14:15:43

标签: javascript html5 canvas

如果我加载图像,我怎样才能遍历所有像素并将白色像素(或我指定的颜色)转为透明?

我知道如何执行此操作,但循环过程应该像2d数组,因此它将涉及两个for循环。

我以为我会从顶行第一个像素开始,向右迭代,如果它是一个白色像素,然后我把它变成透明,向右移动1个像素,如果它不是白色,那么我就停止了。然后在同一行,我从最左边的像素开始,然后检查,如果是白色,我把它变成透明,然后向左移动1个像素等等......

然后我向下移动1行并重复整个过程..

这样我就不会删除实际图像中的任何白色像素。

3 个答案:

答案 0 :(得分:21)

使用getImageDataputImageData非常简单,只需注意,图像越大,性能就越显着。您只需确定当前像素是否为白色,然后将其alpha更改为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);​

还有人询问你是否可以使这些值模糊检查。它非常简单,只需检查它是否在一定范围内。以下将关闭白色至纯白色透明。

 // 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;
    }

更多资源

答案 1 :(得分:2)

您可以使用图像处理框架手动处理像素数据。

如果是MarvinJ,给定一种颜色,您可以用一行将所有像素设置为透明:

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

输入图片

enter image description here

<强>结果:

enter image description here

可运行的示例:

&#13;
&#13;
<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> 
&#13;
{{1}}
&#13;
&#13;
&#13;

答案 2 :(得分:-1)

Loktar可能有一种“有效”的方法,但它的表现相当惨淡。如果你有很多图像,你不希望你的网站耗尽笔记本电脑/移动设备电池,或者你只是想要速度,这可能是一个问题。这是一种更有效的方法。单击“运行代码片段”按钮,以获取其实际演示。

'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>