利用canvas 实现纯色背景替换 可清空纯色背景

当我们找到一些图,会发现有白色或其他颜色的背景,如果是纯色背景,那么我们可以利用canvas的技术来一键替换掉背景,从而实现"抠图"效果

一、原始图片

二、开始替换

网站地址:https://huatuya.com

2.1 选择图片
2.2 选择空白背景色点击
2.3 完事之后点击预览进行下载

三、最终效果

四、核心原理

主要是利用canvas技术 将图片四个角的1像素的颜色取出,然后 全局替换这个颜色,最好替换原图片

核心代码:

javascript 复制代码
const currentImg =reactive({obj:{src:'图片地址'}})
//一键替换背景色
const processImage = () => {
	if (!currentImg.obj) return;
	setTimeout(() => {
		try {
			// 获取图片数据
			const img = new Image();
			img.src = currentImg.obj.src;
			const classId = 'koutu' + currentImg.obj.id;
			let resultCanvas = document.querySelector('#' + classId);
			if (!resultCanvas) {
				resultCanvas = document.createElement('canvas');
				resultCanvas.setAttribute('id', classId); //添加样式属性
				document.body.appendChild(resultCanvas);
			}
			img.onload = () => {
				try {
					// 设置Canvas尺寸
					// originalCanvas.value.width = img.width;
					// originalCanvas.value.height = img.height;

					resultCanvas.width = img.width;
					resultCanvas.height = img.height;
					const resultCtx = resultCanvas.getContext('2d');
					// 绘制原始图片到结果canvas
					resultCtx.drawImage(img, 0, 0);

					// 获取像素数据
					const imageData = resultCtx.getImageData(0, 0, img.width, img.height);
					const data = imageData.data;

					// 获取背景色(取四个角的颜色平均值)
					const corners = [
						{ x: 0, y: 0 },
						{ x: img.width - 1, y: 0 },
						{ x: 0, y: img.height - 1 },
						{ x: img.width - 1, y: img.height - 1 }
					];

					let rSum = 0,
						gSum = 0,
						bSum = 0;
					let validCorners = 0;

					for (const corner of corners) {
						const index = (corner.y * img.width + corner.x) * 4;
						// 确保索引在有效范围内
						if (index >= 0 && index < data.length) {
							rSum += data[index];
							gSum += data[index + 1];
							bSum += data[index + 2];
							validCorners++;
						}
					}

					if (validCorners === 0) {
						console.log('无法检测图片背景色');
						//isProcessing.value = false;
						return;
					}

					const bgR = Math.round(rSum / validCorners);
					const bgG = Math.round(gSum / validCorners);
					const bgB = Math.round(bSum / validCorners);

					// 替换背景色
					for (let i = 0; i < data.length; i += 4) {
						const r = data[i];
						const g = data[i + 1];
						const b = data[i + 2];

						// 计算与背景色的差异
						const diff = Math.sqrt(Math.pow(r - bgR, 2) + Math.pow(g - bgG, 2) + Math.pow(b - bgB, 2));

						// 如果颜色接近背景色,则替换
						if (diff < tolerance.value) {
							if (!backgroundColor.value || backgroundColor.value === 'transparent') {
								// 设置为透明
								data[i + 3] = 0;
							} else {
								// 设置为指定颜色
								const hex = backgroundColor.value;
								if (hex.startsWith('#')) {
									data[i] = parseInt(hex.substr(1, 2), 16);
									data[i + 1] = parseInt(hex.substr(3, 2), 16);
									data[i + 2] = parseInt(hex.substr(5, 2), 16);
								}
							}
						}
					}

					// 将处理后的数据放回canvas
					resultCtx.putImageData(imageData, 0, 0);

					// 生成结果图片
					currentImg.obj.src = resultCanvas.toDataURL('image/png');
					document.body.removeChild(document.getElementById(classId));
					console.log('替换成功!');

				} catch (error) {
					console.log(error);
				}
			};
		} catch (error) {
			console.log('处理图片时出错: ' + error.message);
		}
	}, 100);
};

有不理解的可以留言讨论,也可关注订阅号,解锁更多全栈知识!

原文地址:https://daimane.com/articles/691d88a3f67dd004c87f59cc

或者访问学习网站 https://daimane.com获取更多知识

相关推荐
我叫黑大帅5 分钟前
前端如何利用 GitHub Actions 自动构建并发布到 GitHub Pages?
前端·面试·github
smallLabel8 分钟前
记一次 OpenClaw 飞书插件接入填坑指南: Error: spawn EINVAL
前端
zzjyr11 分钟前
react前端项目 fetch原生 与 umijs request 四种请求区别
前端
我叫黑大帅11 分钟前
前端总说的防抖与节流到底是什么?
前端·javascript·面试
小时前端11 分钟前
微信小程序选不了本地文件?用 web-view + H5 一招搞定
前端·微信小程序·uni-app
71Ove12 分钟前
告别手写字符串!UniApp 路由全自动类型生成工具
前端
掘金安东尼14 分钟前
从平面到空间:用 React Three Fiber 构建 3D 产品网格
前端·javascript·面试
小时前端14 分钟前
HTTPS 页面加载 HTTP 脚本被拦?同源代理来救场
前端·https
用户6837093595514 分钟前
在 Rokid AR 眼镜里玩消消乐:基于 Unity 2022 LTS + UXR 3.0 SDK 的轻量级 AR 游戏尝试
前端
zzjyr16 分钟前
@umijs/max 中导出的 request 方法,如何实现 GET/POST/PUT/DELETE 这四种核心请求
前端