利用canvas,将纯色背景移除,同时扣取内容部分

151 阅读1分钟

`/*

Title body { background: #ccc; } .container { height: 400px; width: 800px; -webkit-perspective: 1000px; -moz-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px; } .box { perspective-origin: 50% 50%; -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; background: red; height: 100%; width: 100%; transform: rotateX(60deg); } 开始抠图
  • @Description :
  • @Author : AbleXu
  • @Date : 2022-02-17 16:03:33
  • @LastEditors : AbleXu
  • @LastEditTime: 2022-02-17 17:30:58 / class Matting { /*
    • 构造函数
    • @param file */ constructor(file) { this.file = file }

createStream() { let reader = new FileReader() let ext = this.file.name.substring(this.file.name.lastIndexOf(".") + 1).toLowerCase() if (ext != 'png' && ext != 'jpg' && ext != 'jpeg') { alert("图片的格式必须为png或者jpg或者jpeg格式!") return } reader.onload = (e) => { let src = e.target.result let img = new Image() img.src = src // img.id = "img" // img.style.display = "block" // document.querySelector('body').appendChild(img) const that = this img.onload = function() { let w = img.width let h = img.height that.fitch(w, h, img)

  }
  
}
reader.readAsDataURL(this.file)

}

fitch(width, height, img) { let dataUrl let c = document.createElement("canvas") c.width = width c.height = height let ctx = c.getContext("2d") ctx.drawImage(img, 0, 0) /** * 取图片四个脚边的像素点rgba * @type {*} */ let tl = Array.prototype.slice.call(ctx.getImageData(0, 0, 1, 1).data).join(',') let tr = Array.prototype.slice.call(ctx.getImageData(width - 1, 0, 1, 1).data).join(',') let br = Array.prototype.slice.call(ctx.getImageData(width - 1, height - 1, 1, 1).data).join(',') let bl = Array.prototype.slice.call(ctx.getImageData(0, height - 1, 1, 1).data).join(',') let imgdata = [tl, tr, bl, br] // 四个取色点 let selfImageData = [] // 当前rgba imgdata.sort() console.log("imgdata", imgdata) // 目前只支持纯色背景抠图,简单的判断是否为纯色 let deferNum = 1 // this.unique(imgdata).length if (deferNum <= 1) { { selfImageData = imgdata[1].split(",") // 设置要扣除的主题色 let isPNG = true // 判断是否已经扣过 let imgDataUrl = ctx.getImageData(0, 0, width, height) //获取像素点 let data = imgDataUrl.data for (let i = 0; i < data.length; i += 4) { // 得到 RGBA 通道的值 let r = data[i] let g = data[i + 1] let b = data[i + 2]

      /**
       * function 判断颜色是不是属于背景色
       * @param numerical
       * @param index
       * @returns {boolean}
       */
      let isIn = (numerical, index) => {
        if (selfImageData[3] == 0) {
          isPNG = false
          return false
        }
        return numerical >= parseInt(selfImageData[index]) - 5 && numerical <= parseInt(selfImageData[index]) + 5 // 去掉边缘色
      }

      if ([r, g, b].every(isIn)) {
        data[i] = 255
        data[i + 1] = 255 
        data[i + 2] = 255
        data[i + 3] = 0 // 设置背景透明
      }
    }
    // 将修改后的代码复制回画布中
    ctx.putImageData(imgDataUrl, 0, 0)
    dataUrl = c.toDataURL("image/png")

    
    this.getImageBoundRect(dataUrl)
    
    // if (isPNG) {
    //   /**
    //    * 创建下载链接 进行图片下载
    //    * @type {Element}
    //    */
    //   let a = document.createElement('a')
    //   a.href = dataUrl //下载图片
    //   a.download = '未命名.png'
    //   a.click()
    // }
    // else {
    //   alert('背景已抠除!')
    // }
  }
}
else {
  alert('只支持纯色背景抠图!')
}

}

getImageBoundRect(src) { let img = new Image() img.src = src // img.id = "img" // img.style.display = "block" // document.querySelector('body').appendChild(img) const that = this img.onload = function() {

  let c = document.createElement('canvas');//创建处理画布对象
  let ctx = c.getContext('2d');
  c.width = img.width;
  c.height = img.height;
  ctx.drawImage(img,0,0);//绘制
  let imgData = ctx.getImageData(0, 0, c.width, c.height).data;//读取图片数据
  let lOffset = c.width, rOffset = 0,tOffset = c.height, bOffset = 0;
  for (let i = 0; i < c.width; i++) {
    for (let j = 0; j < c.height; j++) {
      let pos = (i + c.width * j) * 4;
      if (imgData[pos + 3] > 0) {
        // 这个条件说第j行第i列的像素不是透明的
        bOffset = Math.max(j, bOffset); // 找到不透明区域最底部的纵坐标
        rOffset = Math.max(i, rOffset); // 找到不透明区域的最右端
        tOffset = Math.min(j, tOffset); // 找到不透明区域的最上端
        lOffset = Math.min(i, lOffset); // 找到不透明区域的最左端
      }
    }
  }
  lOffset++;
  rOffset++;
  tOffset++;
  bOffset++;
  let x = document.createElement("canvas");//创建处理后画布对象
  x.width = rOffset-lOffset;
  x.height = bOffset-tOffset;
  let xx = x.getContext("2d");
  xx.drawImage(img, lOffset, tOffset, x.width, x.height, 0, 0, x.width, x.height);//绘制
  // console.log(x.toDataURL());//得到最终裁剪出来的base64

  let dataUrl = x.toDataURL("image/png")

  that.creatNewImage(dataUrl)
}

}

creatNewImage(src) { let img = new Image() img.src = src img.id = "img" img.style.display = "block" img.style.width = "100%"

document.querySelector('.box').appendChild(img)

} }`