使图像白色和透明的算法

时间:2015-05-25 12:34:06

标签: javascript canvas

这里的影响(下图)是通过几个简单的Photoshop步骤实现的,颜色部分变成白色,背景(各种色调的白色灰色)变得透明。是否可以用帆布实现这一目标?

以下圆圈内的图像是最终结果。

图像最初是彩色的,就像第一张图像中的第二张是这样的:

在中间看到那个圆圈,基本上所有的白色都是以别名的方式切割出来的。

与此zoho徽标相同:

底部的第二个原本是这样的:

除了红色R只是中间的Y而不是图像中所见的所有文字和绿色条纹,它周围只有一些灰色阴影的颗粒状纹理。通过photoshop,Y变得透明,纹理和印章刚刚变得坚固,消除了3d阴影等。

将上面的yandex标记放在photoshop算法上给出了这个(我用黑色代替了演示/可见性瞳孔的黑色)

这是在photoshop算法之后的锯齿状,但在最终应用中,图像缩小到大约80x80px,这使得它看起来非常平滑和消除锯齿。所以真正的最终结果是看起来很不错。

2 个答案:

答案 0 :(得分:3)

问题是多方面的,因为有些区域需要不同的方法,例如,最后一个图像,其中主要文本需要转换为白色但保持透明度,而同一图像中的底部条是实心但需要白色要删除的纯色背景时要保留的文本。

通过实施选择区域的工具并手动应用各种操作符 ,它可以实现 - 自动将是一个比看起来更大的挑战。

您可以向用户提出仅上传带有Alpha通道的图片的要求。为此,您可以简单地用白色替换每个非透明像素。在我看来,它更像是一个政策问题,而不是技术问题。

例如

取徽标:

logo



var img = new Image();
img.crossOrigin = "";
img.onload = process;
img.src = "http://i.imgur.com/HIhnb4A.png";        // load the logo

function process() {
  var canvas = document.querySelector("canvas"),   // canvas
      ctx = canvas.getContext("2d"),               // context
      w = this.width,                              // image width/height
      h = this.height,
      idata, data32, len, i, px;                   // iterator, pixel etc.
  
  canvas.width = w;                                // set canvas size
  canvas.height = h;
  ctx.drawImage(this, 0, 0);                       // draw in image
  
  idata = ctx.getImageData(0, 0, w, h);            // get imagedata
  data32 = new Uint32Array(idata.data.buffer);     // use uint32 view for speed
  len = data32.length;
  
  for(i = 0; i < len; i++) {
    // extract alpha channel from a pixel
    px = data32[i] & 0xff000000;                   // little-endian: ABGR
    
    // any non-transparency? ie. alpha > 0
    if (px) {
      data32[i] = px | 0xffffff;    // set this pixel to white, keep alpha level
    }
  }
  
  // done
  ctx.putImageData(idata, 0, 0);
}
&#13;
body {background:gold}
&#13;
<canvas></canvas>
&#13;
&#13;
&#13;

现在问题很容易发现:&#34; @&#34;字符很简单,因为它背后没有透明度。要实现自动化,首先需要淘汰所有白人,然后应用上面演示的过程。但是,这可能适用于这种情况,但对大多数人来说可能不是一件好事。

还会出现抗锯齿问题,因为我们无法分析您想要敲除多少白色,因为我们不会分析白色像素周围的边缘。另一个可能的挑战是ICC校正图像,其中白色可能不是白色,具体取决于所使用的ICC配置文件,浏览器支持等。

但是,它在某种程度上是可行的 - 将上面的代码用一个prestep来删除这个徽标的全白像素:

&#13;
&#13;
var img = new Image();
img.crossOrigin = "";
img.onload = process;
img.src = "http://i.imgur.com/HIhnb4A.png";        // load the logo
function process() {
  var canvas = document.querySelector("canvas"),   // canvas
      ctx = canvas.getContext("2d"),               // context
      w = this.width, h = this.height,
      idata, data32, len, i, px;                   // iterator, pixel etc.
  canvas.width = w;                                // set canvas size
  canvas.height = h;
  ctx.drawImage(this, 0, 0);                       // draw in image
  
  idata = ctx.getImageData(0, 0, w, h);            // get imagedata
  data32 = new Uint32Array(idata.data.buffer);     // use uint32 view for speed
  len = data32.length;
  
  for(i = 0; i < len; i++) {
    px = data32[i];                                // pixel

    // is white? then knock it out
    if (px === 0xffffffff) data32[i] = px = 0;
    
    // extract alpha channel from a pixel
    px = px & 0xff000000;                          // little-endian: ABGR
    
    // any non-transparency? ie. alpha > 0
    if (px) {
      data32[i] = px | 0xffffff;    // set this pixel to white, keep alpha level
    }
  }
  
  ctx.putImageData(idata, 0, 0);
}
&#13;
body {background:gold}
&#13;
<canvas></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

使用此

private draw(base64: string) {
  // example size
  const width = 200;
  const height = 70;
  const image = new Image();
  image.onload = () => {
    const canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext("2d");
    ctx.drawImage(image, 0, 0);
    const imageData = ctx.getImageData(0, 0, width, height);
    for (let x = 0; x < imageData.width; x++) {
      for (let y = 0; y < imageData.height; y++) {
        const offset = (y * imageData.width + x) * 4;
        const r = imageData.data[offset];
        const g = imageData.data[offset + 1];
        const b = imageData.data[offset + 2];
        // if it is pure white, change its alpha to 0
        if (r == 255 && g == 255 && b == 255) {
          imageData.data[offset + 3] = 0;
        }
      }
    }
    ctx.putImageData(imageData, 0, 0);
    // output base64
    const result = canvas.toDataURL();
  };
  image.src = base64;
}