18

如果我加载图像,如何循环遍历其所有像素并将白色像素(或我指定的任何颜色)变为透明?

我对如何做到这一点有一个想法,但循环过程应该像一个二维数组,所以它会涉及两个 for 循环。

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

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

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

4

3 回答 3

30

它使用起来非常简单getImageDataputImageData只需注意图像越大,性能就会受到相当大的影响。您只需要确定当前像素是否为白色,然后将其 alpha 更改为 0。

现场演示

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

更多资源

于 2012-07-13T14:23:44.027 回答
8

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

MarvinJ的情况下,给定一种颜色,您可以使用一行将所有像素设置为透明:

image.setColorToAlpha(0, 0);

输入图像

在此处输入图像描述

结果:

在此处输入图像描述

可运行示例:

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> 

于 2017-12-13T12:34:56.123 回答
0

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>

于 2017-05-26T01:57:34.643 回答