使用js实现证件照p图,背景扣除和替换,完全开源!!!!

概述

不知道大家有没有被网上的一些付费软件恶心到,昨天本来想p个证件照背景颜色,百度一打开,全是说的免费,一点进去,修好背景之后,下载就要开始付费了。于是我写了以下代码,大家放心,完全免费开源,需要的自取

实现效果

js实现证件照背景色替换

源代码

随便新建一个文件为index.html,将代码复制进去,保存然后双击,即可使用,源码如下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="file" id="fileDom" />
    <canvas width="150" height="150"></canvas>
    颜色:
    <input type="color" id="self_color" />
    &nbsp 透明度(0-255,0表示透明,255表示不透明)<input type="number" id="self_op" />
    <button id="confirm">确认</button>
    <button id="exp">导出</button>
  </body>
  <script>
    const cvs = document.querySelector("canvas");
    const btn = document.querySelector("#confirm");
    const exp = document.querySelector("#exp");
    const selfColor = document.querySelector("#self_color");
    const selfOp = document.querySelector("#self_op");
    const fileDom = document.querySelector("#fileDom");
    let opitityNum = 255;
    let greenColor = [220, 190, 190, 255];

    let ctx = cvs.getContext("2d", {
      willReadFrequently: true,
    });
    let originalImageData;
    function init(src) {
      if (!src) {
        return;
      }
      const img = new Image();
      img.crossOrigin = "";
      img.src = src || "";
      img.onload = () => {
        cvs.width = img.width;
        cvs.height = img.width;
        ctx = cvs.getContext("2d", {
          willReadFrequently: true,
        });
        ctx.drawImage(img, 0, 0);
        originalImageData = ctx.getImageData(0, 0, img.width, img.width);
      };
    }
    function confirm() {
      ctx.putImageData(imgData, 0, 0);
      originalImageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
    }
    function exportImg() {
      var imgDataURL = cvs.toDataURL();
      var a = document.createElement("a");
      a.href = imgDataURL;
      a.download = "image.png";
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    }
    init();
    let imgData = ctx.getImageData(0, 0, cvs.width, cvs.height);
    btn.onclick = confirm;
    exp.onclick = exportImg;
    selfOp.onchange = function () {
      opitityNum = selfOp.value;
      cvs.click();
    };
    selfColor.onchange = () => {
      cvs.click();
    };
    fileDom.onchange = async (e1) => {
      let file = await fileToBase64(e1.target.files[0]);
      init(file);
    };
    cvs.addEventListener("click", (e) => {
      greenColor = conversion(selfColor.value);
      const x = e.offsetX;
      const y = e.offsetY;
      if (!originalImageData) {
        console.error("原始图像数据未初始化!");
        return;
      }
      ctx.putImageData(originalImageData, 0, 0);
      imgData = ctx.getImageData(0, 0, cvs.width, cvs.height);
      const clickColor = getColor(x, y, imgData);
      const stack = [{ x, y }];
      while (stack.length > 0) {
        const { x, y } = stack.pop();
        if (x < 0 || x >= cvs.width || y < 0 || y >= cvs.height) {
          continue;
        }
        const i = point2Index(x, y);
        const color = getColor(x, y, imgData);
        if (diff(color, clickColor) && diff1(color, greenColor) !== 0) {
          imgData.data.set(greenColor, i);
          stack.push({ x: x + 1, y });
          stack.push({ x: x - 1, y });
          stack.push({ x, y: y + 1 });
          stack.push({ x, y: y - 1 });
        }
      }
      ctx.putImageData(imgData, 0, 0);
    });
    function fileToBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function () {
          const base64String = reader.result.split(",")[1];
          resolve(reader.result);
        };
        reader.onerror = function () {
          reject(new Error("Failed to load file"));
        };
      });
    }
    function point2Index(x, y) {
      return (y * cvs.width + x) * 4;
    }
    function conversion(value) {
      let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
      let color = value.toLowerCase();
      if (reg.test(color)) {
        if (color.length === 4) {
          let colorNew = "#";
          for (let i = 1; i < 4; i += 1) {
            colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
          }
          color = colorNew;
        }
        let colorChange = [];
        for (let j = 1; j < 7; j += 2) {
          colorChange.push(parseInt("0x" + color.slice(j, j + 2)));
        }
        colorChange.push(opitityNum);
        return colorChange;
      } else {
        return color;
      }
    }
    function getColor(x, y, imageData) {
      const i = point2Index(x, y);
      return [
        imageData.data[i],
        imageData.data[i + 1],
        imageData.data[i + 2],
        imageData.data[i + 3],
      ];
    }
    function diff1(color1, color2) {
      const res =
        Math.abs(color1[0] - color2[0]) +
        Math.abs(color1[1] - color2[1]) +
        Math.abs(color1[2] - color2[2]) +
        Math.abs(color1[3] - color2[3]);
      return res;
    }
    function diff(color1, color2, tolerance = 30) {
      const rDiff = Math.abs(color1[0] - color2[0]);
      const gDiff = Math.abs(color1[1] - color2[1]);
      const bDiff = Math.abs(color1[2] - color2[2]);
      return rDiff <= tolerance && gDiff <= tolerance && bDiff <= tolerance;
    }
  </script>
</html>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值