document.addEventListener('DOMContentLoaded', () => {
const imageUpload = document.getElementById('image-upload');
const blockSizeInput = document.getElementById('block-size');
const blockValueDisplay = document.getElementById('block-value');
const originalCanvas = document.getElementById('original-canvas');
const mosaicCanvas = document.getElementById('mosaic-canvas');
const downloadBtn = document.getElementById('download-btn');
const ctxOriginal = originalCanvas.getContext('2d');
const ctxMosaic = mosaicCanvas.getContext('2d');
let currentImage = null;
let blockSize = parseInt(blockSizeInput.value);
// 更新块大小显示
blockSizeInput.addEventListener('input', () => {
blockSize = parseInt(blockSizeInput.value);
blockValueDisplay.textContent = blockSize;
if (currentImage) {
applyMosaicEffect(currentImage);
}
});
// 图片上传处理
imageUpload.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const img = new Image();
img.onload = () => {
currentImage = img;
displayOriginalImage(img);
applyMosaicEffect(img);
downloadBtn.disabled = false;
};
img.src = event.target.result;
};
reader.readAsDataURL(file);
});
// 显示原图
function displayOriginalImage(img) {
// 设置画布尺寸
const maxWidth = originalCanvas.parentElement.clientWidth - 40;
const maxHeight = originalCanvas.parentElement.clientHeight - 60;
const ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
originalCanvas.width = img.width * ratio;
originalCanvas.height = img.height * ratio;
mosaicCanvas.width = originalCanvas.width;
mosaicCanvas.height = originalCanvas.height;
// 绘制原图
ctxOriginal.clearRect(0, 0, originalCanvas.width, originalCanvas.height);
ctxOriginal.drawImage(img, 0, 0, originalCanvas.width, originalCanvas.height);
}
// 应用马赛克效果
function applyMosaicEffect(img) {
// 复制原图画布到马赛克画布
ctxMosaic.clearRect(0, 0, mosaicCanvas.width, mosaicCanvas.height);
ctxMosaic.drawImage(originalCanvas, 0, 0);
// 获取图像数据
const imageData = ctxMosaic.getImageData(0, 0, mosaicCanvas.width, mosaicCanvas.height);
const data = imageData.data;
// 应用马赛克效果
for (let y = 0; y < mosaicCanvas.height; y += blockSize) {
for (let x = 0; x < mosaicCanvas.width; x += blockSize) {
// 计算当前块的边界
const blockWidth = Math.min(blockSize, mosaicCanvas.width - x);
const blockHeight = Math.min(blockSize, mosaicCanvas.height - y);
// 计算块内平均颜色
const avgColor = getAverageColor(data, x, y, blockWidth, blockHeight, mosaicCanvas.width);
// 填充块
ctxMosaic.fillStyle = `rgb(${avgColor.r}, ${avgColor.g}, ${avgColor.b})`;
ctxMosaic.fillRect(x, y, blockWidth, blockHeight);
}
}
}
// 计算块内平均颜色
function getAverageColor(data, x, y, width, height, canvasWidth) {
let r = 0, g = 0, b = 0, count = 0;
for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {
const pxX = x + j;
const pxY = y + i;
const index = (pxY * canvasWidth + pxX) * 4;
r += data[index];
g += data[index + 1];
b += data[index + 2];
count++;
}
}
return {
r: Math.round(r / count),
g: Math.round(g / count),
b: Math.round(b / count)
};
}
// 下载功能
downloadBtn.addEventListener('click', () => {
if (!currentImage) return;
const link = document.createElement('a');
link.download = 'mosaic-image.png';
link.href = mosaicCanvas.toDataURL('image/png');
link.click();
});
});
评论