', '已加载图片'); }; origImg.src = origDataUrl; }; r.readAsDataURL(f); }); function applyFilter(imgData, filter, intensity) { var d = imgData.data; var w = imgData.width, h = imgData.height; function clamp(v) { return v < 0 ? 0 : v > 255 ? 255 : v; } function blend(orig, target) { return Math.round(orig * (1 - intensity) + target * intensity); } for (var i = 0; i < d.length; i += 4) { var r = d[i], g = d[i + 1], b = d[i + 2]; var nr = r, ng = g, nb = b; if (filter === 'grayscale') { var gray = 0.299 * r + 0.587 * g + 0.114 * b; nr = ng = nb = gray; } else if (filter === 'invert') { nr = 255 - r; ng = 255 - g; nb = 255 - b; } else if (filter === 'sepia') { nr = 0.393 * r + 0.769 * g + 0.189 * b; ng = 0.349 * r + 0.686 * g + 0.168 * b; nb = 0.272 * r + 0.534 * g + 0.131 * b; } else if (filter === 'threshold') { var gray2 = 0.299 * r + 0.587 * g + 0.114 * b; var t = gray2 > 128 ? 255 : 0; nr = ng = nb = t; } else if (filter === 'brighten') { nr = r + 50; ng = g + 50; nb = b + 50; } else if (filter === 'darken') { nr = r - 50; ng = g - 50; nb = b - 50; } else if (filter === 'cool') { nr = r * 0.9; ng = g * 1.0; nb = b * 1.15; } else if (filter === 'warm') { nr = r * 1.15; ng = g * 1.05; nb = b * 0.85; } else if (filter === 'posterize') { function post(v) { return Math.round(v / 32) * 32; } nr = post(r); ng = post(g); nb = post(b); } d[i] = clamp(blend(r, nr)); d[i + 1] = clamp(blend(g, ng)); d[i + 2] = clamp(blend(b, nb)); } if (filter === 'mosaic') { var block = Math.max(4, Math.round(20 * intensity)); for (var y = 0; y < h; y += block) { for (var x = 0; x < w; x += block) { var sumR = 0, sumG = 0, sumB = 0, cnt = 0; for (var dy = 0; dy < block && y + dy < h; dy++) { for (var dx = 0; dx < block && x + dx < w; dx++) { var idx = ((y + dy) * w + (x + dx)) * 4; sumR += d[idx]; sumG += d[idx + 1]; sumB += d[idx + 2]; cnt++; } } var avgR = sumR / cnt, avgG = sumG / cnt, avgB = sumB / cnt; for (var dy2 = 0; dy2 < block && y + dy2 < h; dy2++) { for (var dx2 = 0; dx2 < block && x + dx2 < w; dx2++) { var idx2 = ((y + dy2) * w + (x + dx2)) * 4; d[idx2] = avgR; d[idx2 + 1] = avgG; d[idx2 + 2] = avgB; } } } } } if (filter === 'blur') { // 简单 box blur var radius = Math.max(1, Math.round(5 * intensity)); var orig = new Uint8ClampedArray(d); for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { var sumR = 0, sumG = 0, sumB = 0, cnt = 0; for (var dy = -radius; dy <= radius; dy++) { for (var dx = -radius; dx <= radius; dx++) { var ny = y + dy, nx = x + dx; if (ny >= 0 && ny < h && nx >= 0 && nx < w) { var idx = (ny * w + nx) * 4; sumR += orig[idx]; sumG += orig[idx + 1]; sumB += orig[idx + 2]; cnt++; } } } var idx2 = (y * w + x) * 4; d[idx2] = sumR / cnt; d[idx2 + 1] = sumG / cnt; d[idx2 + 2] = sumB / cnt; } } } return imgData; } function apply() { if (!origImg) { showError('请先选图片'); return; } var filter = getVal('filter'); var intensity = parseFloat($('intensity').value); var canvas = $('canvas-out'); canvas.width = origImg.width; canvas.height = origImg.height; var ctx = canvas.getContext('2d'); ctx.drawImage(origImg, 0, 0); var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); imgData = applyFilter(imgData, filter, intensity); ctx.putImageData(imgData, 0, 0); outDataUrl = canvas.toDataURL('image/png'); showResult('

原图:

处理后(' + filter + ', 强度 ' + intensity + '):

', filter + ' 滤镜已应用'); } function download() { if (!outDataUrl) { showError('请先应用'); return; } var a = document.createElement('a'); a.href = outDataUrl; a.download = 'filtered.png'; a.click(); } $('btn-apply').addEventListener('click', apply); $('btn-download').addEventListener('click', download); $('btn-clear').addEventListener('click', function() { $('file').value = ''; origDataUrl = null; outDataUrl = null; origImg = null; var ra = $('result-area'); ra.hidden = true; ra.style.display = 'none'; var em = $('error-msg'); em.hidden = true; em.style.display = 'none'; }); })();