| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>LocalTools - PDF Editor & Image Scraper</title> |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> |
| <link rel="stylesheet" href="/static/css/styles.css" /> |
| </head> |
| <body> |
|
|
| |
| <div class="animated-bg"></div> |
|
|
| |
| <button class="mobile-menu-btn" id="mobileMenuBtn"> |
| <svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/> |
| </svg> |
| </button> |
|
|
| |
| <div class="sidebar-overlay" id="sidebarOverlay"></div> |
|
|
| <div class="app-container"> |
|
|
| |
| <aside class="sidebar" id="sidebar"> |
| <div class="sidebar-header"> |
| <div class="logo"> |
| <div class="logo-icon">LT</div> |
| <div class="logo-text"> |
| <h1>LocalTools</h1> |
| <span>v1.0</span> |
| </div> |
| </div> |
| </div> |
|
|
| <nav class="sidebar-nav"> |
| <div class="nav-section"> |
| <div class="nav-section-title">Tools</div> |
| <button class="nav-item active" data-page="pdf"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span>PDF Editor</span> |
| </button> |
| <button class="nav-item" data-page="watermark"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/> |
| </svg> |
| <span>Watermark Remover</span> |
| </button> |
| <button class="nav-item" data-page="img2pdf"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span>Images to PDF</span> |
| </button> |
| <button class="nav-item" data-page="merge"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/> |
| </svg> |
| <span>Merge PDFs</span> |
| </button> |
| <button class="nav-item" data-page="split"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2"/> |
| </svg> |
| <span>Split PDF</span> |
| </button> |
| <button class="nav-item" data-page="pdf2img"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span>PDF to Images</span> |
| </button> |
| <button class="nav-item" data-page="compress"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/> |
| </svg> |
| <span>Compress PDF</span> |
| </button> |
| <button class="nav-item" data-page="rotate"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/> |
| </svg> |
| <span>Rotate Pages</span> |
| </button> |
| <button class="nav-item" data-page="pagenums"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14"/> |
| </svg> |
| <span>Page Numbers</span> |
| </button> |
| <button class="nav-item" data-page="ocr"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span>PDF to Text (OCR)</span> |
| </button> |
| <button class="nav-item" data-page="images"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/> |
| </svg> |
| <span>Image Scraper</span> |
| </button> |
| </div> |
|
|
| <div class="nav-section"> |
| <div class="nav-section-title">Image Tools</div> |
| <button class="nav-item" data-page="rembg"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z"/> |
| </svg> |
| <span>Remove Background</span> |
| </button> |
| <button class="nav-item" data-page="enhance"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/> |
| </svg> |
| <span>Enhance Quality</span> |
| </button> |
| <button class="nav-item" data-page="imgwatermark"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/> |
| </svg> |
| <span>Add Watermark</span> |
| </button> |
| <button class="nav-item" data-page="resize"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"/> |
| </svg> |
| <span>Resize Image</span> |
| </button> |
| <button class="nav-item" data-page="convert"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/> |
| </svg> |
| <span>Convert Format</span> |
| </button> |
| <button class="nav-item" data-page="compressimg"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span>Compress Image</span> |
| </button> |
| </div> |
|
|
| <div class="nav-section"> |
| <div class="nav-section-title">Quick Actions</div> |
| <button class="nav-item" id="navRecentFiles"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| <span>Recent Files</span> |
| </button> |
| <button class="nav-item" id="navKeyboardShortcuts"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707"/> |
| </svg> |
| <span>Keyboard Shortcuts</span> |
| </button> |
| </div> |
| </nav> |
|
|
| <div class="sidebar-footer"> |
| |
| <div class="setup-notice" id="setupNotice"> |
| <div class="setup-notice-header"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| <span>How to Run</span> |
| <button class="setup-notice-close" id="closeSetupNotice">×</button> |
| </div> |
| <div class="setup-notice-body"> |
| |
| <p><strong>Run server</strong> (choose one):</p> |
| <div class="setup-notice-code"> |
| <code>python server.py</code> |
| <button class="copy-btn" data-copy="python server.py"> |
| <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg> |
| </button> |
| </div> |
| <p class="setup-notice-or">— or with auto-reload —</p> |
| <div class="setup-notice-code"> |
| <code>python -m uvicorn server:app --reload --host 127.0.0.1 --port 8000</code> |
| <button class="copy-btn" data-copy="python -m uvicorn server:app --reload --host 127.0.0.1 --port 8000"> |
| <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg> |
| </button> |
| </div> |
| <p class="setup-notice-hint">Open <strong>http://127.0.0.1:8000</strong> in browser</p> |
| </div> |
| </div> |
|
|
| <div class="theme-toggle" id="themeToggle"> |
| <div class="theme-toggle-label"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/> |
| </svg> |
| <span>Dark Mode</span> |
| </div> |
| <div class="theme-switch"></div> |
| </div> |
| </div> |
| </aside> |
|
|
| |
| <main class="main-content"> |
|
|
| |
| <div id="page-pdf" class="page active"> |
| |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">PDF Editor</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>PDF Editor</h2> |
| <p>Crop margins, remove pages, and add watermarks to your PDF files. Upload directly or import from URL.</p> |
| </div> |
|
|
| |
| <div class="step-indicator" id="pdfStepIndicator"></div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/></svg> |
| Import PDF |
| </h3> |
| <p>Drag & drop a file or paste a URL (Google Drive supported)</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <label class="form-label">Upload PDF File</label> |
| <div id="pdfDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop your PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="pdf_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label">Or paste PDF URL / Google Drive Link</label> |
| <input type="text" id="pdf_url" class="form-input" placeholder="https://drive.google.com/file/d/... or direct PDF URL" /> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="output_name" class="form-input" value="cropped.pdf" /> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"/></svg> |
| Edit Options |
| </h3> |
| <p>Configure cropping, page removal, and watermark</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2"> |
| <div class="form-group"> |
| <label class="form-label"> |
| Pages to Remove |
| <span class="optional">(optional)</span> |
| <span class="help-tip tooltip" data-tooltip="Enter page numbers like 1,3,5 or ranges like 2-6">?</span> |
| </label> |
| <input type="text" id="remove_pages" class="form-input" placeholder="e.g., 1,3,5 or 2-6" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Unit</label> |
| <select id="unit" class="form-select"> |
| <option value="mm" selected>Millimeters (mm)</option> |
| <option value="cm">Centimeters (cm)</option> |
| <option value="in">Inches (in)</option> |
| <option value="pt">Points (pt)</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label"> |
| Crop Margins |
| <span class="help-tip tooltip" data-tooltip="Amount to cut from each edge of the page">?</span> |
| </label> |
| <div class="grid-4"> |
| <input type="number" id="top" class="form-input tooltip-bottom" data-tooltip="Top margin" step="0.1" placeholder="Top" /> |
| <input type="number" id="bottom" class="form-input tooltip-bottom" data-tooltip="Bottom margin" step="0.1" placeholder="Bottom" /> |
| <input type="number" id="left" class="form-input tooltip-bottom" data-tooltip="Left margin" step="0.1" placeholder="Left" /> |
| <input type="number" id="right" class="form-input tooltip-bottom" data-tooltip="Right margin" step="0.1" placeholder="Right" /> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label"> |
| Watermark |
| <span class="optional">(optional)</span> |
| <span class="help-tip tooltip" data-tooltip="Add diagonal text watermark to all pages">?</span> |
| </label> |
| <div class="grid-3"> |
| <input type="text" id="watermark_text" class="form-input" data-tooltip="Watermark text" placeholder="Text" /> |
| <input type="number" id="watermark_size" class="form-input" data-tooltip="Font size in points" value="36" placeholder="Size" /> |
| <input type="number" id="watermark_rotate" class="form-input" data-tooltip="Rotation angle in degrees" value="45" placeholder="Angle" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnBefore" class="btn btn-secondary tooltip" data-tooltip="Load and preview the original PDF"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview Original |
| </button> |
| <button id="btnAfter" class="btn btn-primary tooltip" data-tooltip="Apply changes and download the processed PDF"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Process & Download |
| </button> |
| <button id="btnClearConfig" class="btn btn-secondary tooltip" data-tooltip="Reset all settings to defaults"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg> |
| Reset |
| </button> |
| </div> |
|
|
| <div id="pdfProgress" class="progress-container"> |
| <div class="progress-bar"> |
| <div class="progress-fill"></div> |
| </div> |
| <div class="progress-text">Processing...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview |
| </h3> |
| <p>Compare original and processed PDF</p> |
| </div> |
| <div class="card-body"> |
| <div class="preview-container"> |
| <div class="preview-toolbar"> |
| <div class="preview-tabs"> |
| <button class="preview-tab active" data-preview="before">Original</button> |
| <button class="preview-tab" data-preview="after">Processed</button> |
| </div> |
| <div class="preview-actions"> |
| <button class="preview-action-btn tooltip" id="btnSplitView" data-tooltip="Compare side by side"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2"/></svg> |
| </button> |
| <button class="preview-action-btn tooltip" id="btnFullscreen" data-tooltip="View fullscreen"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"/></svg> |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div id="preview-before" class="preview-panel active"> |
| <div class="preview-frame"> |
| <iframe id="frameBefore"></iframe> |
| </div> |
| </div> |
| <div id="preview-after" class="preview-panel"> |
| <div class="preview-frame"> |
| <iframe id="frameAfter"></iframe> |
| </div> |
| </div> |
|
|
| |
| <div id="splitView" class="split-view"> |
| <div class="split-panel"> |
| <div class="split-panel-header"> |
| <span class="dot before"></span> |
| Original |
| </div> |
| <iframe id="splitFrameBefore"></iframe> |
| </div> |
| <div class="split-panel"> |
| <div class="split-panel-header"> |
| <span class="dot after"></span> |
| Processed |
| </div> |
| <iframe id="splitFrameAfter"></iframe> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-watermark" class="page"> |
| |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Watermark Remover</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Watermark Remover</h2> |
| <p>Remove text watermarks from scanned PDFs and photo notes using image processing.</p> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/></svg> |
| Import PDF |
| </h3> |
| <p>Upload a PDF with watermarks to remove</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <label class="form-label">Upload PDF File</label> |
| <div id="wmDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop your PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="wm_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label">Or paste PDF URL / Google Drive Link</label> |
| <input type="text" id="wm_url" class="form-input" placeholder="https://drive.google.com/file/d/... or direct PDF URL" /> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"/></svg> |
| Removal Settings |
| </h3> |
| <p>Configure how the watermark should be removed</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2"> |
| <div class="form-group"> |
| <label class="form-label"> |
| Watermark Text |
| <span class="help-tip tooltip" data-tooltip="The text of the watermark (for reference)">?</span> |
| </label> |
| <input type="text" id="wm_text" class="form-input" value="Educated Nepal" placeholder="e.g., Educated Nepal" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Removal Method</label> |
| <select id="wm_method" class="form-select"> |
| <option value="inpaint" selected>Inpaint (Best for handwritten notes)</option> |
| <option value="threshold">Threshold (Light watermarks on white)</option> |
| <option value="color">Color-based (Gray watermarks)</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label"> |
| Removal Intensity |
| <span class="help-tip tooltip" data-tooltip="Higher = more aggressive removal (may affect content)">?</span> |
| </label> |
| <input type="range" id="wm_intensity" min="0" max="100" value="50" style="width: 100%;" /> |
| <div style="display: flex; justify-content: space-between; font-size: 11px; color: var(--text-muted); margin-top: 4px;"> |
| <span>Light (0)</span> |
| <span id="wm_intensity_value">50</span> |
| <span>Strong (100)</span> |
| </div> |
| </div> |
|
|
| <div class="grid-2"> |
| <div class="form-group"> |
| <label class="form-label"> |
| Processing DPI |
| <span class="help-tip tooltip" data-tooltip="Lower = smaller file, higher = better quality">?</span> |
| </label> |
| <select id="wm_dpi" class="form-select"> |
| <option value="72">72 DPI (Smallest file)</option> |
| <option value="100">100 DPI (Small file)</option> |
| <option value="120" selected>120 DPI (Balanced)</option> |
| <option value="150">150 DPI (Good quality)</option> |
| <option value="200">200 DPI (High quality)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label"> |
| Output Quality |
| <span class="help-tip tooltip" data-tooltip="JPEG quality - lower = smaller file">?</span> |
| </label> |
| <select id="wm_quality" class="form-select"> |
| <option value="50">50% (Smallest file)</option> |
| <option value="65">65% (Small file)</option> |
| <option value="75" selected>75% (Balanced)</option> |
| <option value="85">85% (Good quality)</option> |
| <option value="92">92% (High quality)</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="wm_output_name" class="form-input" value="cleaned.pdf" /> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnWmPreview" class="btn btn-secondary"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview Page 1 |
| </button> |
| <button id="btnRemoveWatermark" class="btn btn-primary"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg> |
| Process All & Download |
| </button> |
| </div> |
|
|
| <div id="wmProgress" class="progress-container"> |
| <div class="progress-bar"> |
| <div class="progress-fill"></div> |
| </div> |
| <div class="progress-text">Processing...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="wmPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and processed (Page 1)</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="wmPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Processed</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="wmPreviewProcessed" style="width: 100%; display: block;" alt="Processed" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg> |
| Tips for Best Results |
| </h3> |
| </div> |
| <div class="card-body"> |
| <div style="display: grid; gap: 12px;"> |
| <div style="display: flex; gap: 12px; align-items: flex-start;"> |
| <div style="width: 24px; height: 24px; background: var(--primary-light); border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0;"> |
| <span style="font-size: 12px; font-weight: 600; color: var(--primary);">1</span> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; color: var(--text);">Start with Inpaint method</div> |
| <div style="font-size: 12px; color: var(--text-muted);">Best for handwritten notes with light gray watermarks</div> |
| </div> |
| </div> |
| <div style="display: flex; gap: 12px; align-items: flex-start;"> |
| <div style="width: 24px; height: 24px; background: var(--primary-light); border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0;"> |
| <span style="font-size: 12px; font-weight: 600; color: var(--primary);">2</span> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; color: var(--text);">Adjust intensity gradually</div> |
| <div style="font-size: 12px; color: var(--text-muted);">If watermark persists, increase intensity. If content gets damaged, decrease it.</div> |
| </div> |
| </div> |
| <div style="display: flex; gap: 12px; align-items: flex-start;"> |
| <div style="width: 24px; height: 24px; background: var(--primary-light); border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0;"> |
| <span style="font-size: 12px; font-weight: 600; color: var(--primary);">3</span> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; color: var(--text);">Try different methods</div> |
| <div style="font-size: 12px; color: var(--text-muted);">Threshold works well for very light watermarks, Color-based for consistent gray text.</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-img2pdf" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Images to PDF</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Images to PDF</h2> |
| <p>Convert multiple images to a single PDF. Drag to reorder images before conversion.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg> |
| Upload Images |
| </h3> |
| <p>Select multiple images - drag to reorder</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="img2pdfDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop images here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, GIF, WebP</div> |
| </div> |
| <input type="file" id="img2pdf_files" accept="image/*" multiple style="display: none;" /> |
| </div> |
|
|
| <div id="img2pdfPreview" class="image-grid" style="margin-top: 16px; min-height: 0;"></div> |
|
|
| <div class="grid-2" style="margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Page Size</label> |
| <select id="img2pdf_pagesize" class="form-select"> |
| <option value="a4" selected>A4</option> |
| <option value="letter">Letter</option> |
| <option value="a3">A3</option> |
| <option value="fit">Fit to Image</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="img2pdf_output" class="form-input" value="images.pdf" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnImg2Pdf" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Create PDF |
| </button> |
| <button id="btnImg2PdfClear" class="btn btn-secondary" disabled>Clear All</button> |
| </div> |
|
|
| <div id="img2pdfProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Creating PDF...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-merge" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Merge PDFs</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Merge PDFs</h2> |
| <p>Combine multiple PDF files into one. Drag to reorder before merging.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg> |
| Upload PDFs |
| </h3> |
| <p>Select multiple PDF files - drag to reorder</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="mergeDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop PDF files here, or click to browse</div> |
| <div class="drop-zone-hint">Select 2 or more PDFs to merge</div> |
| </div> |
| <input type="file" id="merge_files" accept="application/pdf" multiple style="display: none;" /> |
| </div> |
|
|
| <div id="mergeFileList" style="margin-top: 16px;"></div> |
|
|
| <div class="form-group" style="margin-top: 20px;"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="merge_output" class="form-input" value="merged.pdf" /> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnMerge" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Merge PDFs |
| </button> |
| <button id="btnMergeClear" class="btn btn-secondary" disabled>Clear All</button> |
| </div> |
|
|
| <div id="mergeProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Merging PDFs...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-split" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Split PDF</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Split PDF</h2> |
| <p>Split a PDF into multiple files - by page, range, or chunks.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2"/></svg> |
| Upload PDF |
| </h3> |
| <p>Select a PDF file to split</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="splitDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="split_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-2" style="margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Split Mode</label> |
| <select id="split_mode" class="form-select"> |
| <option value="all" selected>Every Page (ZIP)</option> |
| <option value="range">Extract Pages</option> |
| <option value="chunks">Split into Chunks</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label" id="split_pages_label">Pages / Chunk Size</label> |
| <input type="text" id="split_pages" class="form-input" placeholder="e.g., 1,3,5-8 or chunk size" /> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label">Output Filename Prefix</label> |
| <input type="text" id="split_output" class="form-input" value="split" /> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnSplit" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Split PDF |
| </button> |
| </div> |
|
|
| <div id="splitProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Splitting PDF...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-images" class="page"> |
| |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Image Scraper</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Image Scraper</h2> |
| <p>Extract high-quality images from any webpage. Automatically filters out small icons and duplicates.</p> |
| </div> |
|
|
| |
| <div class="step-indicator" id="imageStepIndicator"></div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg> |
| Scrape Images |
| </h3> |
| <p>Enter a webpage URL to extract all images</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <label class="form-label">Webpage URL</label> |
| <input type="text" id="page_url" class="form-input" placeholder="https://example.com/article" /> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnScrape" class="btn btn-primary"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg> |
| Fetch Images |
| </button> |
| <button id="btnSelectAll" class="btn btn-secondary" disabled>Select All</button> |
| <button id="btnSelectNone" class="btn btn-secondary" disabled>Clear Selection</button> |
| </div> |
|
|
| <div id="imgProgress" class="progress-container"> |
| <div class="progress-bar"> |
| <div class="progress-fill"></div> |
| </div> |
| <div class="progress-text">Scraping images...</div> |
| </div> |
|
|
| |
| <div id="imageSkeleton" class="image-grid-skeleton" style="display: none; margin-top: 20px;"> |
| <div class="image-card-skeleton"> |
| <div class="skeleton skeleton-image"></div> |
| <div class="skeleton-meta"> |
| <div class="skeleton skeleton-text"></div> |
| <div class="skeleton skeleton-text"></div> |
| </div> |
| </div> |
| <div class="image-card-skeleton"> |
| <div class="skeleton skeleton-image"></div> |
| <div class="skeleton-meta"> |
| <div class="skeleton skeleton-text"></div> |
| <div class="skeleton skeleton-text"></div> |
| </div> |
| </div> |
| <div class="image-card-skeleton"> |
| <div class="skeleton skeleton-image"></div> |
| <div class="skeleton-meta"> |
| <div class="skeleton skeleton-text"></div> |
| <div class="skeleton skeleton-text"></div> |
| </div> |
| </div> |
| <div class="image-card-skeleton"> |
| <div class="skeleton skeleton-image"></div> |
| <div class="skeleton-meta"> |
| <div class="skeleton skeleton-text"></div> |
| <div class="skeleton skeleton-text"></div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="image-toolbar" id="imageToolbar" style="display: none;"> |
| <div class="image-toolbar-left"> |
| <span class="counter-badge" id="img_counter">0 images • 0 selected</span> |
| </div> |
| <div class="image-toolbar-right"> |
| <div class="download-section"> |
| <input type="text" id="zip_name" class="form-input" value="images.zip" /> |
| <button id="btnZip" class="btn btn-success" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| ZIP |
| </button> |
| </div> |
| <div class="download-section"> |
| <input type="text" id="pdf_name" class="form-input" value="images.pdf" /> |
| <button id="btnPdf" class="btn btn-success" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| PDF |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="imgGrid" class="image-grid"></div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-pdf2img" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">PDF to Images</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>PDF to Images</h2> |
| <p>Convert PDF pages to PNG or JPG images. Download as a ZIP file.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg> |
| Convert PDF |
| </h3> |
| <p>Upload a PDF to extract pages as images</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="pdf2imgDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="pdf2img_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Image Format</label> |
| <select id="pdf2img_format" class="form-select"> |
| <option value="png" selected>PNG (Lossless)</option> |
| <option value="jpg">JPG (Smaller)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label"> |
| Quality (DPI) |
| <span class="help-tip tooltip" data-tooltip="Higher DPI = sharper images but larger files">?</span> |
| </label> |
| <select id="pdf2img_dpi" class="form-select"> |
| <option value="150">150 DPI (Web preview)</option> |
| <option value="200" selected>200 DPI (Good quality)</option> |
| <option value="300">300 DPI (Print quality)</option> |
| <option value="400">400 DPI (Ultra sharp)</option> |
| <option value="600">600 DPI (Maximum - OCR/Archive)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Pages <span class="optional">(optional)</span></label> |
| <input type="text" id="pdf2img_pages" class="form-input" placeholder="e.g., 1,3,5-8 or leave empty for all" /> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="pdf2img_output" class="form-input" value="pages" /> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnPdf2Img" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Convert & Download |
| </button> |
| </div> |
|
|
| <div id="pdf2imgProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Converting...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-compress" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Compress PDF</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Compress PDF</h2> |
| <p>Reduce PDF file size by compressing images and removing metadata.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/></svg> |
| Compress PDF |
| </h3> |
| <p>Upload a PDF to reduce its file size</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="compressDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="compress_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-2" style="margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Quality: <span id="compress_quality_val">60</span>%</label> |
| <input type="range" id="compress_quality" min="10" max="100" value="60" style="width: 100%;" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="compress_output" class="form-input" value="compressed.pdf" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnCompressPreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview Page 1 |
| </button> |
| <button id="btnCompress" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Compress & Download |
| </button> |
| </div> |
|
|
| <div id="compressProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Compressing...</div> |
| </div> |
|
|
| <div id="compressResult" style="display: none; margin-top: 16px; padding: 16px; background: var(--success-light); border-radius: var(--radius); border: 1px solid var(--success);"> |
| <div style="display: flex; align-items: center; gap: 12px;"> |
| <svg width="24" height="24" fill="none" stroke="var(--success)" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| <div> |
| <div style="font-weight: 600; color: var(--success);">Compression Complete!</div> |
| <div id="compressStats" style="font-size: 13px; color: var(--text-secondary);"></div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="compressPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and compressed (Page 1)</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="compressPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Compressed</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="compressPreviewProcessed" style="width: 100%; display: block;" alt="Compressed" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-rotate" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Rotate Pages</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Rotate PDF Pages</h2> |
| <p>Rotate all pages or specific pages by 90°, 180°, or 270°.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg> |
| Rotate PDF |
| </h3> |
| <p>Upload a PDF to rotate its pages</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="rotateDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="rotate_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Rotation</label> |
| <select id="rotate_angle" class="form-select"> |
| <option value="90" selected>90° Clockwise</option> |
| <option value="180">180°</option> |
| <option value="270">90° Counter-clockwise</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Pages <span class="optional">(optional)</span></label> |
| <input type="text" id="rotate_pages" class="form-input" placeholder="e.g., 1,3,5-8 or leave empty for all" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="rotate_output" class="form-input" value="rotated.pdf" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnRotatePreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview Page 1 |
| </button> |
| <button id="btnRotate" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Rotate & Download |
| </button> |
| </div> |
|
|
| <div id="rotateProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Rotating...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="rotatePreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and rotated (Page 1)</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="rotatePreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Rotated</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="rotatePreviewProcessed" style="width: 100%; display: block;" alt="Rotated" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-pagenums" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Page Numbers</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Add Page Numbers</h2> |
| <p>Insert page numbers with customizable position and format.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14"/></svg> |
| Add Page Numbers |
| </h3> |
| <p>Upload a PDF to add page numbers</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="pagenumsDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="pagenums_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-2" style="margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Position</label> |
| <select id="pagenums_position" class="form-select"> |
| <option value="bottom-center" selected>Bottom Center</option> |
| <option value="bottom-left">Bottom Left</option> |
| <option value="bottom-right">Bottom Right</option> |
| <option value="top-center">Top Center</option> |
| <option value="top-left">Top Left</option> |
| <option value="top-right">Top Right</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Format</label> |
| <select id="pagenums_format" class="form-select"> |
| <option value="Page {n} of {total}" selected>Page 1 of 10</option> |
| <option value="{n} / {total}">1 / 10</option> |
| <option value="{n}">1</option> |
| <option value="- {n} -">- 1 -</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 12px;"> |
| <div class="form-group"> |
| <label class="form-label">Start Number</label> |
| <input type="number" id="pagenums_start" class="form-input" value="1" min="1" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Font Size</label> |
| <input type="number" id="pagenums_fontsize" class="form-input" value="11" min="8" max="24" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="pagenums_output" class="form-input" value="numbered.pdf" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnPageNumsPreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview Page 1 |
| </button> |
| <button id="btnPageNums" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Add Numbers & Download |
| </button> |
| </div> |
|
|
| <div id="pagenumsProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Processing...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="pagenumsPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and numbered (Page 1)</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="pagenumsPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">With Page Numbers</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="pagenumsPreviewProcessed" style="width: 100%; display: block;" alt="Numbered" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-ocr" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">PDF to Text (OCR)</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>PDF to Text (OCR)</h2> |
| <p>Extract text from PDFs. Uses OCR (Tesseract) for scanned documents.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg> |
| Upload PDF |
| </h3> |
| <p>Select a PDF to extract text from</p> |
| </div> |
| <div class="card-body"> |
| <div id="ocrNotice" class="feature-hint" style="margin-bottom: 16px; display: none;"> |
| <div class="feature-hint-icon">ℹ️</div> |
| <div class="feature-hint-content"> |
| <div class="feature-hint-title">Tesseract not installed</div> |
| <div class="feature-hint-message">Basic text extraction will be used. Install Tesseract for OCR on scanned PDFs.</div> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <div id="ocrDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="ocr_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 16px;"> |
| <div class="form-group"> |
| <label class="form-label">Language</label> |
| <select id="ocr_language" class="form-select"> |
| <option value="eng" selected>English</option> |
| <option value="fra">French</option> |
| <option value="deu">German</option> |
| <option value="spa">Spanish</option> |
| <option value="ita">Italian</option> |
| <option value="por">Portuguese</option> |
| <option value="nld">Dutch</option> |
| <option value="rus">Russian</option> |
| <option value="chi_sim">Chinese (Simplified)</option> |
| <option value="chi_tra">Chinese (Traditional)</option> |
| <option value="jpn">Japanese</option> |
| <option value="kor">Korean</option> |
| <option value="ara">Arabic</option> |
| <option value="hin">Hindi</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Pages <span class="optional">(optional)</span></label> |
| <input type="text" id="ocr_pages" class="form-input" placeholder="e.g., 1,3,5-8 or leave empty for all" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">OCR Quality (DPI)</label> |
| <select id="ocr_dpi" class="form-select"> |
| <option value="150">150 DPI (Fast)</option> |
| <option value="200" selected>200 DPI (Balanced)</option> |
| <option value="300">300 DPI (Best)</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnOcr" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Extract Text |
| </button> |
| <button id="btnOcrCopy" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg> |
| Copy to Clipboard |
| </button> |
| </div> |
|
|
| <div id="ocrProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Extracting text...</div> |
| </div> |
|
|
| <div id="ocrResult" style="display: none; margin-top: 20px;"> |
| <div class="form-group"> |
| <label class="form-label">Extracted Text</label> |
| <textarea id="ocrText" class="form-input" style="min-height: 300px; font-family: monospace; font-size: 13px;" readonly></textarea> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-rembg" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Remove Background</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Remove Background</h2> |
| <p>AI-powered background removal. Works best with photos of people, products, and objects.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z"/></svg> |
| Upload Image |
| </h3> |
| <p>Select an image to remove its background</p> |
| </div> |
| <div class="card-body"> |
| <div id="rembgNotice" class="feature-hint" style="margin-bottom: 16px; display: none;"> |
| <div class="feature-hint-icon">⚠️</div> |
| <div class="feature-hint-content"> |
| <div class="feature-hint-title">rembg not installed</div> |
| <div class="feature-hint-message">Run: pip install rembg[gpu] (or pip install rembg for CPU-only)</div> |
| </div> |
| </div> |
|
|
| <div class="form-group"> |
| <div id="rembgDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop an image here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, WebP</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="rembg_file" accept="image/*" style="display: none;" /> |
| </div> |
|
|
| <div class="form-group" style="margin-top: 16px;"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="rembg_output" class="form-input" value="no-background.png" /> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnRembgPreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview |
| </button> |
| <button id="btnRembg" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Remove Background |
| </button> |
| </div> |
|
|
| <div id="rembgProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Processing (this may take a moment)...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="rembgPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and background removed</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="rembgPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Background Removed</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 50% / 20px 20px;"> |
| <img id="rembgPreviewProcessed" style="width: 100%; display: block;" alt="Processed" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-enhance" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Enhance Quality</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Enhance Quality</h2> |
| <p>Improve image and PDF quality with sharpening, contrast enhancement, and optional upscaling.</p> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg> |
| Enhance Image |
| </h3> |
| <p>Upload an image to enhance its quality</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="enhanceImgDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop an image here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, WebP</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="enhanceimg_file" accept="image/*" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 16px;"> |
| <div class="form-group"> |
| <label class="form-label">Enhancement Level</label> |
| <select id="enhanceimg_level" class="form-select"> |
| <option value="light">Light (Subtle)</option> |
| <option value="medium" selected>Medium (Balanced)</option> |
| <option value="strong">Strong (Noticeable)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Upscale</label> |
| <select id="enhanceimg_upscale" class="form-select"> |
| <option value="1.0" selected>No upscale</option> |
| <option value="1.25">1.25x</option> |
| <option value="1.5">1.5x</option> |
| <option value="2.0">2x</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="enhanceimg_output" class="form-input" value="enhanced" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnEnhanceImgPreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview |
| </button> |
| <button id="btnEnhanceImg" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/></svg> |
| Enhance Image |
| </button> |
| </div> |
|
|
| <div id="enhanceimgProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Enhancing...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="enhanceimgPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and enhanced image</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="enhanceimgPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Enhanced</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="enhanceimgPreviewProcessed" style="width: 100%; display: block;" alt="Enhanced" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" style="margin-top: 24px;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg> |
| Enhance PDF |
| </h3> |
| <p>Improve quality of images within a PDF document</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="enhancePdfDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop a PDF here, or click to browse</div> |
| <div class="drop-zone-hint">Maximum file size: 100MB</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="enhancepdf_file" accept="application/pdf" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-2" style="margin-top: 16px;"> |
| <div class="form-group"> |
| <label class="form-label">Enhancement Level</label> |
| <select id="enhancepdf_level" class="form-select"> |
| <option value="light">Light (Subtle)</option> |
| <option value="medium" selected>Medium (Balanced)</option> |
| <option value="strong">Strong (Noticeable)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="enhancepdf_output" class="form-input" value="enhanced.pdf" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnEnhancePdf" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/></svg> |
| Enhance PDF |
| </button> |
| </div> |
|
|
| <div id="enhancepdfProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Enhancing...</div> |
| </div> |
|
|
| <div id="enhancepdfResult" style="display: none; margin-top: 16px; padding: 16px; background: var(--success-light); border-radius: var(--radius); border: 1px solid var(--success);"> |
| <div style="display: flex; align-items: center; gap: 12px;"> |
| <svg width="24" height="24" fill="none" stroke="var(--success)" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| <div> |
| <div style="font-weight: 600; color: var(--success);">Enhancement Complete!</div> |
| <div id="enhancepdfStats" style="font-size: 13px; color: var(--text-secondary);"></div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" style="margin-top: 24px;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg> |
| Tips |
| </h3> |
| </div> |
| <div class="card-body"> |
| <div style="display: grid; gap: 12px; font-size: 13px; color: var(--text-secondary);"> |
| <div>• <strong>Light:</strong> Subtle improvements, minimal file size increase</div> |
| <div>• <strong>Medium:</strong> Balanced enhancement, recommended for most cases</div> |
| <div>• <strong>Strong:</strong> More noticeable sharpening and contrast boost</div> |
| <div>• <strong>Upscaling:</strong> Increases resolution but also file size</div> |
| <div>• File size is kept reasonable (typically 1.5-2x original for enhanced files)</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-imgwatermark" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Add Watermark</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Add Watermark</h2> |
| <p>Add text watermark to your images with customizable position, opacity, and style.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/></svg> |
| Upload Image |
| </h3> |
| <p>Select an image to add watermark</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="imgwatermarkDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop an image here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, WebP, GIF</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="imgwatermark_file" accept="image/*" style="display: none;" /> |
| </div> |
|
|
| <div class="form-group" style="margin-top: 16px;"> |
| <label class="form-label">Watermark Text</label> |
| <input type="text" id="imgwatermark_text" class="form-input" placeholder="© Your Name" /> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 12px;"> |
| <div class="form-group"> |
| <label class="form-label">Position</label> |
| <select id="imgwatermark_position" class="form-select"> |
| <option value="center" selected>Center</option> |
| <option value="top-left">Top Left</option> |
| <option value="top-center">Top Center</option> |
| <option value="top-right">Top Right</option> |
| <option value="bottom-left">Bottom Left</option> |
| <option value="bottom-center">Bottom Center</option> |
| <option value="bottom-right">Bottom Right</option> |
| <option value="tile">Tile (Repeat)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Opacity (%)</label> |
| <input type="number" id="imgwatermark_opacity" class="form-input" value="50" min="10" max="100" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Font Size</label> |
| <input type="number" id="imgwatermark_fontsize" class="form-input" value="36" min="12" max="200" /> |
| </div> |
| </div> |
|
|
| <div class="grid-2" style="margin-top: 12px;"> |
| <div class="form-group"> |
| <label class="form-label">Color</label> |
| <input type="color" id="imgwatermark_color" class="form-input" value="#000000" style="height: 40px; padding: 4px;" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="imgwatermark_output" class="form-input" value="watermarked" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnImgWatermarkPreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview |
| </button> |
| <button id="btnImgWatermark" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Add Watermark & Download |
| </button> |
| </div> |
|
|
| <div id="imgwatermarkProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Processing...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="imgwatermarkPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and watermarked image</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="imgwatermarkPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">With Watermark</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="imgwatermarkPreviewProcessed" style="width: 100%; display: block;" alt="Watermarked" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-resize" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Resize Image</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Resize Image</h2> |
| <p>Resize images with presets or custom dimensions. Maintains aspect ratio by default.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"/></svg> |
| Upload Image |
| </h3> |
| <p>Select an image to resize</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="resizeDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop an image here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, WebP, GIF</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="resize_file" accept="image/*" style="display: none;" /> |
| </div> |
|
|
| <div class="form-group" style="margin-top: 16px;"> |
| <label class="form-label">Preset</label> |
| <select id="resize_preset" class="form-select"> |
| <option value="custom">Custom Size</option> |
| <option value="thumbnail">Thumbnail (150×150)</option> |
| <option value="small">Small (320×240)</option> |
| <option value="medium">Medium (640×480)</option> |
| <option value="hd">HD (1280×720)</option> |
| <option value="fullhd">Full HD (1920×1080)</option> |
| <option value="4k">4K (3840×2160)</option> |
| <option value="square-sm">Square Small (500×500)</option> |
| <option value="square-lg">Square Large (1000×1000)</option> |
| </select> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 12px;"> |
| <div class="form-group"> |
| <label class="form-label">Width (px)</label> |
| <input type="number" id="resize_width" class="form-input" placeholder="Auto" min="1" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Height (px)</label> |
| <input type="number" id="resize_height" class="form-input" placeholder="Auto" min="1" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="resize_output" class="form-input" value="resized" /> |
| </div> |
| </div> |
|
|
| <div class="form-group" style="margin-top: 12px;"> |
| <label style="display: flex; align-items: center; gap: 8px; cursor: pointer;"> |
| <input type="checkbox" id="resize_aspect" checked style="width: 18px; height: 18px;" /> |
| <span class="form-label" style="margin: 0;">Maintain aspect ratio</span> |
| </label> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnResizePreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview |
| </button> |
| <button id="btnResize" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Resize & Download |
| </button> |
| </div> |
|
|
| <div id="resizeProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Resizing...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="resizePreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and resized image</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original <span id="resizeOriginalSize"></span></div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="resizePreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Resized <span id="resizeNewSize"></span></div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="resizePreviewProcessed" style="width: 100%; display: block;" alt="Resized" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-convert" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Convert Format</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Convert Image Format</h2> |
| <p>Convert images between JPG, PNG, WebP, and GIF formats.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg> |
| Upload Image |
| </h3> |
| <p>Select an image to convert</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="convertDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop an image here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, WebP, GIF</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="convert_file" accept="image/*" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-3" style="margin-top: 16px;"> |
| <div class="form-group"> |
| <label class="form-label">Target Format</label> |
| <select id="convert_format" class="form-select"> |
| <option value="png">PNG (Lossless)</option> |
| <option value="jpg" selected>JPG (Smaller)</option> |
| <option value="webp">WebP (Modern)</option> |
| <option value="gif">GIF</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Quality (JPG/WebP)</label> |
| <input type="number" id="convert_quality" class="form-input" value="90" min="10" max="100" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="convert_output" class="form-input" value="converted" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnConvert" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Convert & Download |
| </button> |
| </div> |
|
|
| <div id="convertProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Converting...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="page-compressimg" class="page"> |
| <nav class="breadcrumbs"> |
| <span class="breadcrumb-item"><a href="#">Home</a></span> |
| <span class="breadcrumb-separator">/</span> |
| <span class="breadcrumb-item active">Compress Image</span> |
| </nav> |
|
|
| <div class="page-header"> |
| <h2>Compress Image</h2> |
| <p>Reduce image file size while maintaining quality. Great for web optimization.</p> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg> |
| Upload Image |
| </h3> |
| <p>Select an image to compress</p> |
| </div> |
| <div class="card-body"> |
| <div class="form-group"> |
| <div id="compressimgDropZone" class="drop-zone"> |
| <svg class="drop-zone-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <div class="drop-zone-text">Drag & drop an image here, or click to browse</div> |
| <div class="drop-zone-hint">Supports JPG, PNG, WebP</div> |
| <div class="drop-zone-file"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> |
| </svg> |
| <span class="drop-zone-file-name"></span> |
| <span class="drop-zone-file-size"></span> |
| <button type="button" class="drop-zone-file-remove">Remove</button> |
| </div> |
| </div> |
| <input type="file" id="compressimg_file" accept="image/*" style="display: none;" /> |
| </div> |
|
|
| <div class="grid-2" style="margin-top: 16px;"> |
| <div class="form-group"> |
| <label class="form-label">Quality: <span id="compressimg_quality_val">70</span>%</label> |
| <input type="range" id="compressimg_quality" min="10" max="100" value="70" style="width: 100%;" /> |
| </div> |
| <div class="form-group"> |
| <label class="form-label">Output Filename</label> |
| <input type="text" id="compressimg_output" class="form-input" value="compressed" /> |
| </div> |
| </div> |
|
|
| <div class="btn-group"> |
| <button id="btnCompressImgPreview" class="btn btn-secondary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> |
| Preview |
| </button> |
| <button id="btnCompressImg" class="btn btn-primary" disabled> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> |
| Compress & Download |
| </button> |
| </div> |
|
|
| <div id="compressimgProgress" class="progress-container"> |
| <div class="progress-bar"><div class="progress-fill"></div></div> |
| <div class="progress-text">Compressing...</div> |
| </div> |
|
|
| <div id="compressimgResult" style="display: none; margin-top: 16px; padding: 16px; background: var(--success-light); border-radius: var(--radius); border: 1px solid var(--success);"> |
| <div style="display: flex; align-items: center; gap: 12px;"> |
| <svg width="24" height="24" fill="none" stroke="var(--success)" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| <div> |
| <div style="font-weight: 600; color: var(--success);">Compression Complete!</div> |
| <div id="compressimgStats" style="font-size: 13px; color: var(--text-secondary);"></div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card" id="compressimgPreviewCard" style="display: none;"> |
| <div class="card-header"> |
| <h3> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg> |
| Preview Comparison |
| </h3> |
| <p>Compare original and compressed image</p> |
| </div> |
| <div class="card-body"> |
| <div class="grid-2" style="gap: 20px;"> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Original</div> |
| <div style="border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="compressimgPreviewOriginal" style="width: 100%; display: block;" alt="Original" /> |
| </div> |
| </div> |
| <div> |
| <div style="font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--primary);">Compressed</div> |
| <div style="border: 1px solid var(--primary); border-radius: var(--radius); overflow: hidden; background: var(--border-light);"> |
| <img id="compressimgPreviewProcessed" style="width: 100%; display: block;" alt="Compressed" /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| </main> |
| </div> |
|
|
| |
| <div class="fullscreen-overlay" id="fullscreenOverlay"> |
| <div class="fullscreen-header"> |
| <span class="fullscreen-title">PDF Preview</span> |
| <button class="fullscreen-close" id="fullscreenClose"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> |
| </svg> |
| </button> |
| </div> |
| <div class="fullscreen-content"> |
| <iframe id="fullscreenFrame"></iframe> |
| </div> |
| </div> |
|
|
| |
| <script src="/static/js/utils.js"></script> |
| <script src="/static/js/pdf-editor.js"></script> |
| <script src="/static/js/pdf-tools.js"></script> |
| <script src="/static/js/image-tools.js"></script> |
| <script src="/static/js/image-scraper.js"></script> |
| <script src="/static/js/app.js"></script> |
|
|
| </body> |
| </html> |
|
|