![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1cb297beb7392a15e02f1ae7f191677e.png)
<img id="original-img"
src="https://gd1.alicdn.com/imgextra/i1/1674937161/O1CN01IlOmos22lmtklugqq_!!1674937161.jpg_400x400.jpg">
<canvas id="result-canvas"></canvas>
<script>
class ImageBackgroundRemover {
constructor(options = {}) {
this.tolerance = options.tolerance || 10;
this.step = options.step || 1;
this.maxLoop = options.maxLoop || 10000000;
}
removeBackground(imageUrl) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
img.src = imageUrl;
img.onload = () => {
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
const imgData = ctx.getImageData(0, 0, img.width, img.height);
const bgColor = this.findBgColor(imgData);
if (!bgColor) {
reject(new Error("Unable to find background color."));
return;
}
const resultImgData = this.removeBgColor(imgData, bgColor);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.putImageData(resultImgData, 0, 0);
const base64 = canvas.toDataURL("image/png");
resolve(base64);
};
img.onerror = () => {
reject(new Error("Failed to load image."));
};
});
}
findBgColor(imgData) {
const count = new Uint32Array(256 * 256 * 256);
let maxCount = 0;
let bgColor = null;
const toleranceSquared = this.tolerance ** 2;
let loopCount = 0;
for (let y = 0; y < imgData.height; y += this.step) {
for (let x = 0; x < imgData.width; x += this.step) {
const i = (x + y * imgData.width) * 4;
const r = imgData.data[i];
const g = imgData.data[i + 1];
const b = imgData.data[i + 2];
const a = imgData.data[i + 3];
const key = r << 16 | g << 8 | b;
count[key]++;
if (count[key] > maxCount) {
maxCount = count[key];
bgColor = [r, g, b, a];
}
if (maxCount > imgData.width * imgData.height / 2) {
return bgColor;
}
loopCount++;
if (loopCount >= this.maxLoop) {
return null;
}
}
}
if (bgColor[3] < 255 && distance(bgColor, [0, 0, 0, 0]) <= toleranceSquared) {
return [0, 0, 0, 0];
}
return bgColor;
}
removeBgColor(imgData, bgColor) {
const resultImgData = new ImageData(imgData.width, imgData.height);
const toleranceSquared = this.tolerance ** 2;
for (let y = 0; y < imgData.height; y++) {
for (let x = 0; x < imgData.width; x++) {
const i = (x + y * imgData.width) * 4;
const r = imgData.data[i];
const g = imgData.data[i + 1];
const b = imgData.data[i + 2];
const a = imgData.data[i + 3];
if (this.distance([r, g, b, a], bgColor) <= toleranceSquared) {
resultImgData.data[i] = 0;
resultImgData.data[i + 1] = 0;
resultImgData.data[i + 2] = 0;
resultImgData.data[i + 3] = 0;
} else {
resultImgData.data[i] = r;
resultImgData.data[i + 1] = g;
resultImgData.data[i + 2] = b;
resultImgData.data[i + 3] = a;
}
}
}
return resultImgData;
}
distance(c1, c2) {
const dr = c1[0] - c2[0];
const dg = c1[1] - c2[1];
const db = c1[2] - c2[2];
const da = c1[3] - c2[3];
return dr * dr + dg * dg + db * db + da * da;
}
}
const remover = new ImageBackgroundRemover({
tolerance: 10
});
remover.removeBackground('https://gd1.alicdn.com/imgextra/i1/1674937161/O1CN01IlOmos22lmtklugqq_!!1674937161.jpg_400x400.jpg').then(base64 => {
const canvas = document.getElementById('result-canvas');
canvas.width = 500;
canvas.height = 500;
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
};
img.src = base64;
}).catch(err => {
alert(err);
});
</script>
<img id="original-img" src="https://gd1.alicdn.com/imgextra/i1/1674937161/O1CN01IlOmos22lmtklugqq_!!1674937161.jpg_400x400.jpg">
<canvas id="result-canvas"></canvas>
<script>
const imageUrl = document.getElementById('original-img').src;
removeBackground(imageUrl, {
tolerance: 10
}).then(base64 => {
const canvas = document.getElementById('result-canvas');
canvas.width = 500;
canvas.height = 500;
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
};
img.src = base64;
}).catch(err => {
alert(err);
});
function removeBackground(imageUrl, options = {}) {
const {
tolerance = 10, step = 1, maxLoop = 10000000
} = options;
const img = new Image();
img.crossOrigin = "anonymous";
img.src = imageUrl;
return new Promise((resolve, reject) => {
img.onload = function () {
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
const imgData = ctx.getImageData(0, 0, img.width, img.height);
const bgColor = findBgColor(imgData, tolerance, step, maxLoop);
if (!bgColor) {
reject(new Error("Unable to find background color."));
return;
}
const resultImgData = removeBgColor(imgData, bgColor, tolerance);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.putImageData(resultImgData, 0, 0);
const base64 = canvas.toDataURL("image/png");
resolve(base64);
};
img.onerror = function () {
reject(new Error("Failed to load image."));
};
});
}
function findBgColor(imgData, tolerance, step, maxLoop) {
const count = new Uint32Array(256 * 256 * 256);
let maxCount = 0;
let bgColor = null;
const toleranceSquared = tolerance ** 2;
let loopCount = 0;
for (let y = 0; y < imgData.height; y += step) {
for (let x = 0; x < imgData.width; x += step) {
const i = (x + y * imgData.width) * 4;
const r = imgData.data[i];
const g = imgData.data[i + 1];
const b = imgData.data[i + 2];
const a = imgData.data[i + 3];
const key = r << 16 | g << 8 | b;
count[key]++;
if (count[key] > maxCount) {
maxCount = count[key];
bgColor = [r, g, b, a];
}
if (maxCount > imgData.width * imgData.height / 2) {
return bgColor;
}
loopCount++;
if (loopCount >= maxLoop) {
return null;
}
}
}
if (bgColor[3] < 255 && distance(bgColor, [0, 0, 0, 0]) <= toleranceSquared) {
return [0, 0, 0, 0];
}
return bgColor;
}
function removeBgColor(imgData, bgColor, tolerance) {
const resultImgData = new ImageData(imgData.width, imgData.height);
const toleranceSquared = tolerance ** 2;
for (let y = 0; y < imgData.height; y++) {
for (let x = 0; x < imgData.width; x++) {
const i = (x + y * imgData.width) * 4;
const r = imgData.data[i];
const g = imgData.data[i + 1];
const b = imgData.data[i + 2];
const a = imgData.data[i + 3];
if (distance([r, g, b, a], bgColor) <= toleranceSquared) {
resultImgData.data[i] = 0;
resultImgData.data[i + 1] = 0;
resultImgData.data[i + 2] = 0;
resultImgData.data[i + 3] = 0;
} else {
resultImgData.data[i] = r;
resultImgData.data[i + 1] = g;
resultImgData.data[i + 2] = b;
resultImgData.data[i + 3] = a;
}
}
}
return resultImgData;
}
function distance(c1, c2) {
const dr = c1[0] - c2[0];
const dg = c1[1] - c2[1];
const db = c1[2] - c2[2];
const da = c1[3] - c2[3];
return dr * dr + dg * dg + db * db + da * da;
}
</script>