Watermark Removal Tool📤
Drop Image Here
or choose upload method
💡 How to use: Paint over watermark → Click "Remove Watermark" → Save
');
};window.reloadFile = function() {
if (originalImg) {
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
baseImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
maskCtx.clearRect(0, 0, maskCanvas.width, maskCanvas.height);
overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
render();
pushHistory();
}
};function runProcess() {
var maskData = maskCtx.getImageData(0, 0, maskCanvas.width, maskCanvas.height).data;
var hasMask = false;
for (var i = 3; i < maskData.length; i += 4) {
if (maskData[i] > 0) { hasMask = true; break; }
}
if (!hasMask) return alert('Please paint over the watermark first.');showLoader('Processing...');
setTimeout(function() {
var method = methodSel.value;
var w = canvas.width, h = canvas.height;
var src = new Uint8ClampedArray(baseImageData.data);
var out = new Uint8ClampedArray(src);try {
if (method === 'blur') {
inpaintBlur(src, out, maskData, w, h);
} else if (method === 'neighbor') {
inpaintNeighbor(src, out, maskData, w, h);
} else {
inpaintSmart(src, out, maskData, w, h);
}var result = new ImageData(out, w, h);
ctx.putImageData(result, 0, 0);
baseImageData = ctx.getImageData(0, 0, w, h);
maskCtx.clearRect(0, 0, w, h);
overlayCtx.clearRect(0, 0, w, h);
render();
pushHistory();
downloadBtn.disabled = false;
} catch (err) {
console.error(err);
alert('Processing error: ' + err.message);
} finally {
hideLoader();
}
}, 50);
}function inpaintBlur(src, out, mask, w, h) {
var passes = 4;
var cur = new Uint8ClampedArray(src);
var tmp = new Uint8ClampedArray(src.length);
for (var p = 0; p < passes; p++) {
boxBlur(cur, tmp, w, h, 6);
var temp = cur; cur = tmp; tmp = temp;
}
for (var i = 0; i < mask.length; i += 4) {
if (mask[i + 3] > 0) {
out[i] = cur[i];
out[i + 1] = cur[i + 1];
out[i + 2] = cur[i + 2];
}
}
}function boxBlur(src, dst, w, h, radius) {
var r = radius;
var size = (2 * r + 1) * (2 * r + 1);
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var rr = 0, gg = 0, bb = 0;
for (var dy = -r; dy <= r; dy++) {
for (var dx = -r; dx <= r; dx++) {
var nx = Math.min(w - 1, Math.max(0, x + dx));
var ny = Math.min(h - 1, Math.max(0, y + dy));
var idx = (ny * w + nx) * 4;
rr += src[idx];
gg += src[idx + 1];
bb += src[idx + 2];
}
}
var idx = (y * w + x) * 4;
dst[idx] = rr / size;
dst[idx + 1] = gg / size;
dst[idx + 2] = bb / size;
dst[idx + 3] = 255;
}
}
}function inpaintNeighbor(src, out, mask, w, h) {
var unmasked = [];
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var idx = (y * w + x) * 4;
if (mask[idx + 3] === 0) unmasked.push({ x: x, y: y, idx: idx });
}
}
if (unmasked.length === 0) return;
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var idx = (y * w + x) * 4;
if (mask[idx + 3] === 0) continue;
var best = null, bestD = Infinity;
for (var u = 0; u < unmasked.length; u++) {
var d = Math.pow(unmasked[u].x - x, 2) + Math.pow(unmasked[u].y - y, 2);
if (d < bestD) { bestD = d; best = unmasked[u]; }
if (d === 0) break;
}
if (best) {
out[idx] = src[best.idx];
out[idx + 1] = src[best.idx + 1];
out[idx + 2] = src[best.idx + 2];
}
}
}
}function inpaintSmart(src, out, mask, w, h) {
var RADIUS = 25;
var R2 = RADIUS * RADIUS;
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var idx = (y * w + x) * 4;
if (mask[idx + 3] === 0) continue;
var sumR = 0, sumG = 0, sumB = 0, sumW = 0;
var x0 = Math.max(0, x - RADIUS);
var x1 = Math.min(w - 1, x + RADIUS);
var y0 = Math.max(0, y - RADIUS);
var y1 = Math.min(h - 1, y + RADIUS);
for (var yy = y0; yy <= y1; yy++) {
for (var xx = x0; xx <= x1; xx++) {
var sidx = (yy * w + xx) * 4;
if (mask[sidx + 3] !== 0) continue;
var dx = xx - x, dy = yy - y;
var d2 = dx * dx + dy * dy;
if (d2 > R2) continue;
var weight = 1 / (1 + Math.sqrt(d2));
sumR += src[sidx] * weight;
sumG += src[sidx + 1] * weight;
sumB += src[sidx + 2] * weight;
sumW += weight;
}
}
if (sumW > 0) {
out[idx] = sumR / sumW;
out[idx + 1] = sumG / sumW;
out[idx + 2] = sumB / sumW;
}
}
}
}function showLoader(t) {
loaderText.textContent = t;
loader.classList.add('active');
}
function hideLoader() {
loader.classList.remove('active');
}
document.addEventListener('click', function(e) {
if (!e.target.closest('.upload-btn')) {
$('uploadDropdown').classList.remove('show');
}
});
})();