const canvas = document.getElementById('redactor-canvas'); const ctx = canvas.getContext('2d'); let imageBounds = null; function placeholder() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#f8fafc'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#52606d'; ctx.font = '18px Arial'; ctx.fillText('Choose an image to redact it locally.', 230, 132); } function blurRect(x, y, width, height) { ctx.save(); ctx.filter = 'blur(14px)'; ctx.drawImage(canvas, x, y, width, height, x, y, width, height); ctx.restore(); ctx.fillStyle = 'rgba(47, 133, 90, 0.18)'; ctx.fillRect(x, y, width, height); } document.getElementById('redactor-input').addEventListener('change', (event) => { const [file] = event.target.files; if (!file) return; const image = new Image(); image.onload = () => { const scale = Math.min(canvas.width / image.width, canvas.height / image.height); const width = image.width * scale; const height = image.height * scale; const x = (canvas.width - width) / 2; const y = (canvas.height - height) / 2; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(image, x, y, width, height); imageBounds = { x, y, width, height }; URL.revokeObjectURL(image.src); }; image.src = URL.createObjectURL(file); }); document.getElementById('auto-redact').addEventListener('click', () => { const bounds = imageBounds || { x: 150, y: 45, width: 420, height: 170 }; blurRect(bounds.x + bounds.width * 0.33, bounds.y + bounds.height * 0.16, bounds.width * 0.28, bounds.height * 0.32); blurRect(bounds.x + bounds.width * 0.12, bounds.y + bounds.height * 0.68, bounds.width * 0.42, bounds.height * 0.16); }); document.getElementById('download-redacted').addEventListener('click', () => { const link = document.createElement('a'); link.download = 'redacted-image.png'; link.href = canvas.toDataURL('image/png'); link.click(); }); placeholder();