概述
不知道大家有没有被网上的一些付费软件恶心到,昨天本来想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" />
  透明度(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>