### Batch Image Processing with Progress and Error Handling (JavaScript) Source: https://context7.com/adt109119/nanobananawatermarkremover/llms.txt Handles multiple images sequentially with progress tracking and error handling for each file. This function filters for PNG or JPEG files, processes them using `processImage`, logs progress, and handles potential errors. It also manages the downloading of successfully processed images. ```javascript const dropZone = document.getElementById('dropZone'); dropZone.addEventListener('drop', async (e) => { e.preventDefault(); const files = Array.from(e.dataTransfer.files).filter(file => file.type === 'image/png' || file.type === 'image/jpeg' ); if (files.length === 0) { alert('Please drop PNG or JPEG images'); return; } console.log(`Processing ${files.length} images...`); const results = []; let processed = 0; for (const file of files) { try { console.log(`[${processed + 1}/${files.length}] Processing: ${file.name}`); const result = await processImage(file); results.push(result); if (result.success) { console.log(`✓ ${result.filename}`); } } catch (error) { console.error(`✗ ${file.name}: ${error.message}`); results.push({ filename: file.name, error: error.message, success: false }); } processed++; const progress = (processed / files.length) * 100; console.log(`Progress: ${progress.toFixed(0)}%`); } // Download all successful results for (const result of results) { if (result.success) { const url = URL.createObjectURL(result.blob); const link = document.createElement('a'); link.href = url; link.download = result.filename; link.click(); URL.revokeObjectURL(url); // Delay to prevent browser blocking multiple downloads await new Promise(resolve => setTimeout(resolve, 300)); } } console.log(`Completed: ${results.filter(r => r.success).length}/${files.length} successful`); }); ``` -------------------------------- ### Process Single Image - JavaScript Source: https://context7.com/adt109119/nanobananawatermarkremover/llms.txt Orchestrates the complete image processing workflow, including mask selection, watermark detection, and removal. It handles file input, initiates processing, and manages the download of the processed image. Dependencies include browser DOM APIs and the `processImage` function. ```javascript // Process a single file const fileInput = document.getElementById('fileInput'); fileInput.addEventListener('change', async (e) => { const file = e.target.files[0]; try { const result = await processImage(file); if (result.success) { if (result.noWatermark) { console.log('No watermark detected, original returned'); } else { console.log(`Watermark removed from ${result.filename}`); console.log(`Mask used: ${result.maskSize}x${result.maskSize}, margin: ${result.margin}px`); } // Create download link const url = URL.createObjectURL(result.blob); const link = document.createElement('a'); link.href = url; link.download = result.filename; link.click(); URL.revokeObjectURL(url); } } catch (error) { console.error('Processing failed:', error.message); } }); // Returns object structure: // { // filename: "image_(watermark removed).png", // originalName: "image.png", // blob: Blob, // originalBlob: Blob, // width: 1920, // height: 1080, // maskSize: 96, // margin: 64, // success: true, // noWatermark: false // } ``` -------------------------------- ### JavaScript: Implement Reverse Alpha Blending for Watermark Removal Source: https://context7.com/adt109119/nanobananawatermarkremover/llms.txt This snippet demonstrates how to use the `reverseAlphaBlend` function to remove watermarks from an image. It involves loading an image, drawing it onto a canvas, applying the reverse alpha blending algorithm using a pre-loaded watermark mask, and then outputting the processed image. Dependencies include browser canvas API and image loading capabilities. It takes an ImageData object and mask details as input and outputs the modified ImageData. ```javascript const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const image = new Image(); image.src = 'watermarked-image.png'; image.onload = () => { canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image, 0, 0); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); // Assume mask is pre-loaded with alpha channel const mask = { imageData: maskImageData, // ImageData with alpha channel width: 96, height: 96, margin: 64 }; // Apply reverse alpha blending reverseAlphaBlend(imageData, mask, canvas.width, canvas.height); // Put processed data back to canvas ctx.putImageData(imageData, 0, 0); // Convert to blob for download canvas.toBlob((blob) => { const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'watermark_removed.png'; link.click(); }, 'image/png'); }; // Function implementation (app.js:764-823) function reverseAlphaBlend(imageData, mask, imgWidth, imgHeight) { const imgPixels = imageData.data; const maskPixels = mask.imageData.data; const offsetX = imgWidth - mask.width - mask.margin; const offsetY = imgHeight - mask.height - mask.margin; for (let my = 0; my < mask.height; my++) { for (let mx = 0; mx < mask.width; mx++) { const imgX = offsetX + mx; const imgY = offsetY + my; if (imgX < 0 || imgY < 0 || imgX >= imgWidth || imgY >= imgHeight) continue; const imgIdx = (imgY * imgWidth + imgX) * 4; const maskIdx = (my * mask.width + mx) * 4; const alpha = maskPixels[maskIdx + 3] / 255; if (alpha < 0.01) continue; const invAlpha = 1 - alpha; if (invAlpha < 0.01) continue; // Reverse Alpha Blending: Original = (Composite - Watermark × α) / (1 - α) const origR = (imgPixels[imgIdx] - maskPixels[maskIdx] * alpha) / invAlpha; const origG = (imgPixels[imgIdx + 1] - maskPixels[maskIdx + 1] * alpha) / invAlpha; const origB = (imgPixels[imgIdx + 2] - maskPixels[maskIdx + 2] * alpha) / invAlpha; imgPixels[imgIdx] = Math.max(0, Math.min(255, Math.round(origR))); imgPixels[imgIdx + 1] = Math.max(0, Math.min(255, Math.round(origG))); imgPixels[imgIdx + 2] = Math.max(0, Math.min(255, Math.round(origB))); } } } ``` -------------------------------- ### Preprocess Mask - JavaScript Source: https://context7.com/adt109119/nanobananawatermarkremover/llms.txt Converts grayscale watermark mask images into alpha channel data for reverse blending calculations. This function takes raw image data and transforms it, suitable for use in watermark removal algorithms. It expects a grayscale image where white represents the watermark area. ```javascript // Load and preprocess watermark mask async function loadCustomMask(maskPath) { const image = new Image(); image.src = maskPath; await new Promise((resolve) => { image.onload = resolve; }); const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); const rawImageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const processed = preprocessMask(rawImageData); return { image, canvas, ctx, imageData: processed, width: image.width, height: image.height }; } // Function converts black-background white-watermark images // Input: Grayscale mask where white = watermark area // Output: ImageData with RGB(255,255,255) and luminance as alpha function preprocessMask(imageData) { const data = imageData.data; const processed = new ImageData(imageData.width, imageData.height); const output = processed.data; for (let i = 0; i < data.length; i += 4) { // Calculate luminance as alpha value const luminance = Math.round( 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2] ); output[i] = 255; // R - White watermark output[i + 1] = 255; // G output[i + 2] = 255; // B output[i + 3] = luminance; // Alpha from luminance } return processed; } // Usage example const mask48 = await loadCustomMask('assets/mask_48.png'); const mask96 = await loadCustomMask('assets/mask_96.png'); ``` -------------------------------- ### Detect Watermark - JavaScript Source: https://context7.com/adt109119/nanobananawatermarkremover/llms.txt Intelligently detects if a watermark is present in an image by analyzing brightness in potential watermark areas compared to surrounding regions. It utilizes a mask and image data to make this determination. The function returns whether a watermark was detected and details about the image and mask used. ```javascript // Detect if image has watermark before processing async function checkImageForWatermark(imageFile) { const image = await loadImageFromFile(imageFile); const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); // Select appropriate mask based on image size const mask = (image.width > 1024 && image.height > 1024) ? state.masks.get(96) : state.masks.get(48); const hasWatermark = detectWatermark(imageData, mask, canvas.width, canvas.height); return { hasWatermark, imageWidth: image.width, imageHeight: image.height, maskSize: mask.width }; } // Example usage const file = document.querySelector('input[type="file"]').files[0]; const detection = await checkImageForWatermark(file); if (detection.hasWatermark) { console.log(`Watermark detected using ${detection.maskSize}px mask`); } else { console.log('No watermark found, processing skipped'); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.