{"id":423,"date":"2026-07-13T17:47:51","date_gmt":"2026-07-13T17:47:51","guid":{"rendered":"https:\/\/freewebtools.co.in\/?page_id=423"},"modified":"2026-07-16T17:22:34","modified_gmt":"2026-07-16T17:22:34","slug":"jpg-to-text","status":"publish","type":"page","link":"https:\/\/freewebtools.co.in\/index.php\/jpg-to-text\/","title":{"rendered":"JPG to TEXT"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Enterprise Local OCR Engine &#8211; Pro Edition<\/title>\n    \n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/tesseract.js@5.0.5\/dist\/tesseract.min.js\"><\/script>\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jszip\/3.10.1\/jszip.min.js\"><\/script>\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2pdf.js\/0.10.1\/html2pdf.bundle.min.js\"><\/script>\n\n    <style>\n        \/* Modern Premium CSS Reset and Typography with Namespace WP-safe Prefixes *\/\n        :root {\n            --wpot-primary-gradient: linear-gradient(135deg, #2563eb 0%, #4f46e5 100%);\n            --wpot-hover-gradient: linear-gradient(135deg, #1d4ed8 0%, #4338ca 100%);\n            --wpot-bg-light: #f8fafc;\n            --wpot-card-glass: rgba(255, 255, 255, 0.95);\n            --wpot-text-main: #0f172a;\n            --wpot-text-muted: #64748b;\n            --wpot-border-color: #e2e8f0;\n            --wpot-radius-lg: 16px;\n            --wpot-radius-md: 10px;\n            --wpot-shadow-sm: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);\n            --wpot-shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.08);\n            --wpot-transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n        }\n\n        .wpot-ocr-wrapper {\n            font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n            background-color: var(--wpot-bg-light);\n            color: var(--wpot-text-main);\n            line-height: 1.5;\n            padding: 2rem 1rem;\n            box-sizing: border-box;\n            min-height: 100vh;\n        }\n\n        .wpot-ocr-container {\n            max-width: 1400px;\n            margin: 0 auto;\n            display: flex;\n            flex-direction: column;\n            gap: 2rem;\n            box-sizing: border-box;\n        }\n\n        \/* HEADER *\/\n        .wpot-ocr-header {\n            text-align: center;\n            margin-bottom: 1rem;\n        }\n\n        .wpot-ocr-header h1 {\n            font-size: 2.5rem;\n            font-weight: 800;\n            background: var(--wpot-primary-gradient);\n            -webkit-background-clip: text;\n            -webkit-text-fill-color: transparent;\n            margin: 0 0 0.5rem 0;\n            letter-spacing: -0.025em;\n        }\n\n        .wpot-ocr-header p {\n            color: var(--wpot-text-muted);\n            font-size: 1.1rem;\n            margin: 0;\n        }\n\n        \/* DASHBOARD GRID *\/\n        .wpot-grid-system {\n            display: grid;\n            grid-template-columns: 1fr;\n            gap: 2rem;\n        }\n\n        @media (min-width: 1024px) {\n            .wpot-grid-system {\n                grid-template-columns: 1.1fr 0.9fr;\n            }\n        }\n\n        \/* SAAS GLASS CARD *\/\n        .wpot-glass-card {\n            background: var(--wpot-card-glass);\n            border: 1px solid var(--wpot-border-color);\n            border-radius: var(--wpot-radius-lg);\n            box-shadow: var(--wpot-shadow-lg);\n            padding: 2rem;\n            box-sizing: border-box;\n            backdrop-filter: blur(8px);\n            display: flex;\n            flex-direction: column;\n            gap: 1.5rem;\n        }\n\n        \/* DRAG & DROP UPLOADER *\/\n        .wpot-drop-zone {\n            border: 2px dashed #cbd5e1;\n            border-radius: var(--wpot-radius-md);\n            padding: 3rem 2rem;\n            text-align: center;\n            cursor: pointer;\n            transition: var(--wpot-transition-smooth);\n            background: rgba(255, 255, 255, 0.5);\n            position: relative;\n            outline: none;\n        }\n\n        .wpot-drop-zone:hover, .wpot-drop-zone.wpot-dragover {\n            border-color: #4f46e5;\n            background: rgba(79, 70, 229, 0.03);\n        }\n\n        .wpot-drop-zone svg {\n            width: 64px;\n            height: 64px;\n            color: #4f46e5;\n            margin-bottom: 1rem;\n            transition: var(--wpot-transition-smooth);\n        }\n\n        .wpot-drop-zone:hover svg {\n            transform: translateY(-5px);\n        }\n\n        .wpot-file-input {\n            display: none;\n        }\n\n        \/* STICKY CONFIG BAR *\/\n        .wpot-sticky-config {\n            position: sticky;\n            top: 20px;\n            z-index: 100;\n            background: rgba(255, 255, 255, 0.9);\n            backdrop-filter: blur(12px);\n            padding: 1rem;\n            border-radius: var(--wpot-radius-md);\n            border: 1px solid var(--wpot-border-color);\n            display: flex;\n            flex-wrap: wrap;\n            gap: 1rem;\n            align-items: center;\n            justify-content: space-between;\n            box-shadow: var(--wpot-shadow-sm);\n        }\n\n        .wpot-config-group {\n            display: flex;\n            align-items: center;\n            gap: 0.5rem;\n        }\n\n        .wpot-select, .wpot-input {\n            padding: 0.5rem 1rem;\n            border: 1px solid var(--wpot-border-color);\n            border-radius: var(--wpot-radius-md);\n            background: #ffffff;\n            font-size: 0.9rem;\n            outline: none;\n            transition: var(--wpot-transition-smooth);\n        }\n\n        .wpot-select:focus, .wpot-input:focus {\n            border-color: #4f46e5;\n            box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);\n        }\n\n        \/* BATCH PREVIEW MANAGER *\/\n        .wpot-batch-wrapper {\n            max-height: 400px;\n            overflow-y: auto;\n            border: 1px solid var(--wpot-border-color);\n            border-radius: var(--wpot-radius-md);\n            padding: 0.5rem;\n            background: #f1f5f9;\n        }\n\n        .wpot-batch-item {\n            background: #ffffff;\n            border: 1px solid var(--wpot-border-color);\n            border-radius: var(--wpot-radius-md);\n            padding: 0.75rem;\n            margin-bottom: 0.5rem;\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            gap: 1rem;\n            transition: var(--wpot-transition-smooth);\n        }\n\n        .wpot-batch-item.wpot-active-item {\n            border-color: #4f46e5;\n            box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.1);\n        }\n\n        .wpot-batch-thumb {\n            width: 50px;\n            height: 50px;\n            object-fit: cover;\n            border-radius: 4px;\n            background: #e2e8f0;\n        }\n\n        .wpot-batch-meta {\n            flex: 1;\n            font-size: 0.85rem;\n        }\n\n        .wpot-batch-name {\n            font-weight: 600;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 150px;\n        }\n\n        .wpot-batch-actions {\n            display: flex;\n            gap: 0.5rem;\n        }\n\n        \/* IMAGE PREPROCESSING TOOLBOX *\/\n        .wpot-editor-box {\n            border: 1px solid var(--wpot-border-color);\n            border-radius: var(--wpot-radius-md);\n            overflow: hidden;\n            background: #ffffff;\n        }\n\n        .wpot-canvas-container {\n            position: relative;\n            background: #0f172a;\n            min-height: 300px;\n            max-height: 500px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            overflow: hidden;\n        }\n\n        .wpot-preview-canvas {\n            max-width: 100%;\n            max-height: 480px;\n            object-fit: contain;\n            transition: transform 0.2s ease;\n        }\n\n        .wpot-controls-grid {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n            gap: 0.75rem;\n            padding: 1rem;\n            background: #f8fafc;\n            border-top: 1px solid var(--wpot-border-color);\n        }\n\n        .wpot-slider-container {\n            display: flex;\n            flex-direction: column;\n            gap: 0.25rem;\n            font-size: 0.75rem;\n            font-weight: 600;\n        }\n\n        .wpot-slider {\n            width: 100%;\n            accent-color: #4f46e5;\n        }\n\n        \/* ACTION MATRIX BUTTONS *\/\n        .wpot-btn {\n            background: var(--wpot-primary-gradient);\n            color: #ffffff;\n            border: none;\n            padding: 0.6rem 1.2rem;\n            border-radius: var(--wpot-radius-md);\n            font-weight: 600;\n            font-size: 0.9rem;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 0.5rem;\n            transition: var(--wpot-transition-smooth);\n            text-decoration: none;\n            user-select: none;\n        }\n\n        .wpot-btn:hover {\n            background: var(--wpot-hover-gradient);\n            transform: translateY(-1px);\n            box-shadow: 0 4px 12px rgba(79, 70, 229, 0.2);\n        }\n\n        .wpot-btn:active {\n            transform: translateY(0);\n        }\n\n        .wpot-btn-secondary {\n            background: #ffffff;\n            border: 1px solid var(--wpot-border-color);\n            color: var(--wpot-text-main);\n        }\n\n        .wpot-btn-secondary:hover {\n            background: #f1f5f9;\n            transform: none;\n            box-shadow: none;\n        }\n\n        .wpot-btn-danger {\n            background: #fee2e2;\n            color: #ef4444;\n            border: 1px solid #fecaca;\n        }\n\n        .wpot-btn-danger:hover {\n            background: #fecaca;\n            transform: none;\n            box-shadow: none;\n        }\n\n        \/* LIVE REAL-TIME PROGRESS BAR *\/\n        .wpot-progress-wrap {\n            background: #f1f5f9;\n            border-radius: 9999px;\n            overflow: hidden;\n            height: 8px;\n            width: 100%;\n            display: none;\n        }\n\n        .wpot-progress-bar {\n            background: var(--wpot-primary-gradient);\n            width: 0%;\n            height: 100%;\n            transition: width 0.1s linear;\n        }\n\n        \/* EDITABLE TEXT AREA & LINE NUMBERS *\/\n        .wpot-editor-grid {\n            display: grid;\n            grid-template-columns: auto 1fr;\n            border: 1px solid var(--wpot-border-color);\n            border-radius: var(--wpot-radius-md);\n            overflow: hidden;\n            background: #ffffff;\n            min-height: 350px;\n        }\n\n        .wpot-line-numbers {\n            padding: 1rem 0.5rem;\n            background: #f8fafc;\n            border-right: 1px solid var(--wpot-border-color);\n            color: var(--wpot-text-muted);\n            font-family: monospace;\n            font-size: 0.85rem;\n            text-align: right;\n            user-select: none;\n            min-width: 25px;\n        }\n\n        .wpot-text-container {\n            position: relative;\n            width: 100%;\n        }\n\n        .wpot-textarea-editor {\n            width: 100%;\n            height: 100%;\n            min-height: 350px;\n            border: none;\n            outline: none;\n            padding: 1rem;\n            font-family: inherit;\n            font-size: 0.95rem;\n            line-height: 1.6;\n            resize: vertical;\n            box-sizing: border-box;\n            background: transparent;\n        }\n\n        \/* STATS PANEL *\/\n        .wpot-stats-grid {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));\n            gap: 1rem;\n            background: #f8fafc;\n            padding: 1rem;\n            border-radius: var(--wpot-radius-md);\n            border: 1px solid var(--wpot-border-color);\n        }\n\n        .wpot-stat-card {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            text-align: center;\n        }\n\n        .wpot-stat-val {\n            font-size: 1.25rem;\n            font-weight: 800;\n            color: #4f46e5;\n        }\n\n        .wpot-stat-lbl {\n            font-size: 0.75rem;\n            color: var(--wpot-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.05em;\n        }\n\n        \/* SEARCH AND REPLACE FLOATING BAR *\/\n        .wpot-search-panel {\n            display: flex;\n            flex-wrap: wrap;\n            gap: 0.5rem;\n            padding: 0.75rem;\n            background: #f1f5f9;\n            border-radius: var(--wpot-radius-md);\n            align-items: center;\n        }\n\n        \/* HISTORY LOGGER *\/\n        .wpot-history-tray {\n            display: flex;\n            flex-direction: column;\n            gap: 0.5rem;\n            max-height: 150px;\n            overflow-y: auto;\n        }\n\n        .wpot-history-item {\n            background: #ffffff;\n            border: 1px solid var(--wpot-border-color);\n            padding: 0.5rem 0.75rem;\n            border-radius: 6px;\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            font-size: 0.8rem;\n        }\n\n        \/* NOTIFICATIONS & TOASTS *\/\n        .wpot-toast-container {\n            position: fixed;\n            bottom: 20px;\n            right: 20px;\n            z-index: 9999;\n            display: flex;\n            flex-direction: column;\n            gap: 0.5rem;\n        }\n\n        .wpot-toast {\n            background: #0f172a;\n            color: #ffffff;\n            padding: 0.75rem 1.25rem;\n            border-radius: var(--wpot-radius-md);\n            box-shadow: var(--wpot-shadow-lg);\n            font-size: 0.85rem;\n            animation: wpotFadeIn 0.3s ease forwards;\n        }\n\n        @keyframes wpotFadeIn {\n            from { opacity: 0; transform: translateY(10px); }\n            to { opacity: 1; transform: translateY(0); }\n        }\n\n        .wpot-hidden {\n            display: none !important;\n        }\n    <\/style>\n<\/head>\n<body class=\"wpot-ocr-wrapper\">\n\n<div class=\"wpot-ocr-container\">\n    <header class=\"wpot-ocr-header\">\n        <h1>SaaS Local OCR &#038; Prep Tool<\/h1>\n        <p>Preprocess and extract vector-accurate text in your browser locally. No servers. Total privacy.<\/p>\n    <\/header>\n\n    <section class=\"wpot-sticky-config\">\n        <div class=\"wpot-config-group\">\n            <label for=\"wpot-opt-lang\" style=\"font-weight: 700; font-size: 0.85rem;\">Engine Language:<\/label>\n            <select id=\"wpot-opt-lang\" class=\"wpot-select\">\n                <option value=\"eng\">English<\/option>\n                <option value=\"hin\">Hindi (\u0939\u093f\u0928\u094d\u0926\u0940)<\/option>\n                <option value=\"eng+hin\">Mixed (English + Hindi)<\/option>\n                <option value=\"spa\">Spanish (Espa\u00f1ol)<\/option>\n                <option value=\"fra\">French (Fran\u00e7ais)<\/option>\n                <option value=\"deu\">German (Deutsch)<\/option>\n            <\/select>\n        <\/div>\n\n        <div class=\"wpot-config-group\">\n            <label for=\"wpot-opt-mode\" style=\"font-weight: 700; font-size: 0.85rem;\">Accuracy Target:<\/label>\n            <select id=\"wpot-opt-mode\" class=\"wpot-select\">\n                <option value=\"high\">High Accuracy Mode<\/option>\n                <option value=\"fast\">Fast Scan Mode<\/option>\n            <\/select>\n        <\/div>\n\n        <div class=\"wpot-config-group\">\n            <button class=\"wpot-btn\" id=\"wpot-trigger-ocr\">\ud83d\ude80 Run Batch Extraction<\/button>\n            <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-reset\">\ud83d\udd04 Clear All<\/button>\n        <\/div>\n    <\/section>\n\n    <main class=\"wpot-grid-system\">\n        \n        <section class=\"wpot-glass-card\">\n            <h3 style=\"margin:0; font-weight: 800; font-size: 1.25rem;\">1. Raw Source Input Pipeline<\/h3>\n\n            <div class=\"wpot-drop-zone\" id=\"wpot-drag-area\" tabindex=\"0\">\n                <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                    <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\"><\/path>\n                <\/svg>\n                <p style=\"margin: 0.5rem 0; font-weight: 700;\">Drag and drop clean image files here<\/p>\n                <p style=\"margin: 0; font-size: 0.8rem; color: var(--wpot-text-muted);\">Supports JPG, PNG, WEBP, BMP, GIF, TIFF. Or paste direct from clipboard.<\/p>\n                <input type=\"file\" id=\"wpot-file-input\" class=\"wpot-file-input\" accept=\"image\/*\" multiple>\n            <\/div>\n\n            <div id=\"wpot-batch-container\" class=\"wpot-batch-wrapper wpot-hidden\">\n                <div style=\"font-size:0.8rem; font-weight:700; margin-bottom:0.5rem; display:flex; justify-content:space-between; align-items:center;\">\n                    <span>Active Queued Documents:<\/span>\n                    <button class=\"wpot-btn wpot-btn-danger\" id=\"wpot-clear-queue-btn\" style=\"padding: 2px 8px; font-size: 0.75rem;\">Clear Queue<\/button>\n                <\/div>\n                <div id=\"wpot-batch-list\"><\/div>\n            <\/div>\n\n            <div class=\"wpot-editor-box wpot-hidden\" id=\"wpot-editor-container\">\n                <div class=\"wpot-canvas-container\">\n                    <canvas id=\"wpot-canvas-preview\" class=\"wpot-preview-canvas\"><\/canvas>\n                <\/div>\n\n                <div class=\"wpot-controls-grid\">\n                    <div class=\"wpot-slider-container\">\n                        <label>Brightness<\/label>\n                        <input type=\"range\" id=\"wpot-slide-brightness\" class=\"wpot-slider\" min=\"-100\" max=\"100\" value=\"0\">\n                    <\/div>\n                    <div class=\"wpot-slider-container\">\n                        <label>Contrast<\/label>\n                        <input type=\"range\" id=\"wpot-slide-contrast\" class=\"wpot-slider\" min=\"-100\" max=\"100\" value=\"0\">\n                    <\/div>\n                    <div class=\"wpot-slider-container\" style=\"flex-direction:row; align-items:center; gap:0.5rem; margin-top:0.75rem;\">\n                        <input type=\"checkbox\" id=\"wpot-chk-grayscale\">\n                        <label for=\"wpot-chk-grayscale\">Grayscale<\/label>\n                    <\/div>\n                    <div class=\"wpot-slider-container\" style=\"flex-direction:row; align-items:center; gap:0.5rem; margin-top:0.75rem;\">\n                        <input type=\"checkbox\" id=\"wpot-chk-threshold\">\n                        <label for=\"wpot-chk-threshold\">Binary B&#038;W<\/label>\n                    <\/div>\n                    <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-rotate-l\" style=\"padding: 4px;\">\u21a9 Rotate L<\/button>\n                    <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-rotate-r\" style=\"padding: 4px;\">\u21aa Rotate R<\/button>\n                    <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-invert\" style=\"padding: 4px;\">Invert<\/button>\n                    <button class=\"wpot-btn\" id=\"wpot-btn-auto-enhance\" style=\"padding: 4px;\">\u2728 Auto Enhance<\/button>\n                <\/div>\n            <\/div>\n\n            <div class=\"wpot-progress-wrap\" id=\"wpot-ocr-progress-container\">\n                <div class=\"wpot-progress-bar\" id=\"wpot-ocr-progress\"><\/div>\n            <\/div>\n            <div id=\"wpot-status-log\" style=\"font-size:0.85rem; color: #4f46e5; font-weight:700; text-align:center;\"><\/div>\n        <\/section>\n\n        <section class=\"wpot-glass-card\">\n            <div style=\"display:flex; justify-content:space-between; align-items:center;\">\n                <h3 style=\"margin:0; font-weight: 800; font-size: 1.25rem;\">2. Output &#038; Downstream Text Editor<\/h3>\n                <div style=\"display:flex; gap:0.5rem;\">\n                    <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-toggle-dark\" style=\"padding: 4px 8px; font-size:0.75rem;\">Dark Mode Preview<\/button>\n                <\/div>\n            <\/div>\n\n            <div class=\"wpot-search-panel\">\n                <input type=\"text\" id=\"wpot-search-find\" class=\"wpot-input\" style=\"flex:1; min-width:100px;\" placeholder=\"Find...\">\n                <input type=\"text\" id=\"wpot-search-replace\" class=\"wpot-input\" style=\"flex:1; min-width:100px;\" placeholder=\"Replace with...\">\n                <button class=\"wpot-btn\" id=\"wpot-btn-replace\" style=\"padding: 0.5rem 1rem;\">Replace<\/button>\n            <\/div>\n\n            <div class=\"wpot-editor-grid\" id=\"wpot-editor-grid\">\n                <div class=\"wpot-line-numbers\" id=\"wpot-line-numbers\">1<\/div>\n                <div class=\"wpot-text-container\">\n                    <textarea id=\"wpot-text-output\" class=\"wpot-textarea-editor\" placeholder=\"Extracted markdown, plain paragraphs, or tabular tables will output here dynamically...\"><\/textarea>\n                <\/div>\n            <\/div>\n\n            <div class=\"wpot-stats-grid\">\n                <div class=\"wpot-stat-card\">\n                    <span class=\"wpot-stat-val\" id=\"wpot-stat-chars\">0<\/span>\n                    <span class=\"wpot-stat-lbl\">Characters<\/span>\n                <\/div>\n                <div class=\"wpot-stat-card\">\n                    <span class=\"wpot-stat-val\" id=\"wpot-stat-words\">0<\/span>\n                    <span class=\"wpot-stat-lbl\">Words<\/span>\n                <\/div>\n                <div class=\"wpot-stat-card\">\n                    <span class=\"wpot-stat-val\" id=\"wpot-stat-lines\">1<\/span>\n                    <span class=\"wpot-stat-lbl\">Lines<\/span>\n                <\/div>\n                <div class=\"wpot-stat-card\">\n                    <span class=\"wpot-stat-val\" id=\"wpot-stat-speed\">0s<\/span>\n                    <span class=\"wpot-stat-lbl\">Proc Time<\/span>\n                <\/div>\n                <div class=\"wpot-stat-card\">\n                    <span class=\"wpot-stat-val\" id=\"wpot-stat-confidence\">0%<\/span>\n                    <span class=\"wpot-stat-lbl\">Accuracy<\/span>\n                <\/div>\n            <\/div>\n\n            <div style=\"display:flex; flex-wrap:wrap; gap:0.75rem;\">\n                <button class=\"wpot-btn\" id=\"wpot-btn-copy\" style=\"flex:1; min-width:120px;\">\ud83d\udccb Copy Text<\/button>\n                <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-dl-txt\" style=\"flex:1; min-width:100px;\">Save .TXT<\/button>\n                <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-dl-doc\" style=\"flex:1; min-width:100px;\">Save .DOCX<\/button>\n                <button class=\"wpot-btn wpot-btn-secondary\" id=\"wpot-btn-dl-pdf\" style=\"flex:1; min-width:100px;\">Save PDF Document<\/button>\n            <\/div>\n\n            <hr style=\"border:0; border-top:1px solid var(--wpot-border-color); margin:0.5rem 0;\">\n\n            <div>\n                <h4 style=\"margin: 0 0 0.5rem 0; font-size: 0.9rem; font-weight: 700;\">Recent Local Session Extractions:<\/h4>\n                <div class=\"wpot-history-tray\" id=\"wpot-history-tray\">\n                    <span style=\"font-size: 0.8rem; color: var(--wpot-text-muted);\">No records found in this browser storage session.<\/span>\n                <\/div>\n            <\/div>\n        <\/section>\n    <\/main>\n<\/div>\n\n<div class=\"wpot-toast-container\" id=\"wpot-toast-container\"><\/div>\n\n<script>\n(function() {\n    'use strict';\n\n    \/\/ Application Global Isolated Namespace Properties\n    const wpotState = {\n        queue: [],\n        activeIndex: -1,\n        processedCount: 0,\n        originalImage: null,\n        preprocessedImage: null,\n        history: [],\n        filters: {\n            brightness: 0,\n            contrast: 0,\n            grayscale: false,\n            threshold: false,\n            rotation: 0,\n            inverted: false\n        }\n    };\n\n    \/\/ DOM selectors initialized carefully matching ID prefix guidelines\n    const dragArea = document.getElementById('wpot-drag-area');\n    const fileInput = document.getElementById('wpot-file-input');\n    const batchContainer = document.getElementById('wpot-batch-container');\n    const batchList = document.getElementById('wpot-batch-list');\n    const editorContainer = document.getElementById('wpot-editor-container');\n    const previewCanvas = document.getElementById('wpot-canvas-preview');\n    const runBtn = document.getElementById('wpot-trigger-ocr');\n    const textOutput = document.getElementById('wpot-text-output');\n    const lineNumbers = document.getElementById('wpot-line-numbers');\n    const progressBarContainer = document.getElementById('wpot-ocr-progress-container');\n    const progressBar = document.getElementById('wpot-ocr-progress');\n    const statusLog = document.getElementById('wpot-status-log');\n    const clearQueueBtn = document.getElementById('wpot-clear-queue-btn');\n\n    \/\/ Setup basic event listeners safely without inline dependencies\n    document.addEventListener('DOMContentLoaded', () => {\n        wpotInitDragAndDrop();\n        wpotInitSliders();\n        wpotInitButtons();\n        wpotInitEditorSync();\n        wpotLoadHistory();\n    });\n\n    function wpotToast(message) {\n        const container = document.getElementById('wpot-toast-container');\n        const toast = document.createElement('div');\n        toast.className = 'wpot-toast';\n        toast.innerText = message;\n        container.appendChild(toast);\n        setTimeout(() => toast.remove(), 4000);\n    }\n\n    function wpotInitDragAndDrop() {\n        ['dragenter', 'dragover'].forEach(eventName => {\n            dragArea.addEventListener(eventName, (e) => {\n                e.preventDefault();\n                dragArea.classList.add('wpot-dragover');\n            }, false);\n        });\n\n        ['dragleave', 'drop'].forEach(eventName => {\n            dragArea.addEventListener(eventName, (e) => {\n                e.preventDefault();\n                dragArea.classList.remove('wpot-dragover');\n            }, false);\n        });\n\n        dragArea.addEventListener('drop', (e) => {\n            const dt = e.dataTransfer;\n            const files = dt.files;\n            wpotHandleFiles(files);\n        });\n\n        dragArea.addEventListener('click', () => fileInput.click());\n        fileInput.addEventListener('change', (e) => wpotHandleFiles(e.target.files));\n\n        document.addEventListener('paste', (e) => {\n            const items = (e.clipboardData || e.originalEvent.clipboardData).items;\n            for (let index in items) {\n                const item = items[index];\n                if (item.kind === 'file') {\n                    const blob = item.getAsFile();\n                    wpotHandleFiles([blob]);\n                }\n            }\n        });\n    }\n\n    function wpotHandleFiles(files) {\n        if (!files || files.length === 0) return;\n        Array.from(files).forEach(file => {\n            if (file.type.startsWith('image\/')) {\n                const reader = new FileReader();\n                reader.onload = (e) => {\n                    const queueItem = {\n                        id: 'item-' + Date.now() + '-' + Math.random().toString(36).substr(2, 5),\n                        name: file.name,\n                        dataUrl: e.target.result,\n                        processedText: '',\n                        confidence: 0,\n                        processingTime: 0\n                    };\n                    wpotState.queue.push(queueItem);\n                    wpotUpdateQueueUI();\n                    if (wpotState.activeIndex === -1) {\n                        wpotSelectQueueItem(wpotState.queue.length - 1);\n                    }\n                };\n                reader.readAsDataURL(file);\n            } else {\n                wpotToast('Unsupported file type skipped.');\n            }\n        });\n    }\n\n    function wpotUpdateQueueUI() {\n        if (wpotState.queue.length > 0) {\n            batchContainer.classList.remove('wpot-hidden');\n        } else {\n            batchContainer.classList.add('wpot-hidden');\n            editorContainer.classList.add('wpot-hidden');\n            wpotState.activeIndex = -1;\n            return;\n        }\n\n        batchList.innerHTML = '';\n        wpotState.queue.forEach((item, index) => {\n            const element = document.createElement('div');\n            element.className = `wpot-batch-item ${index === wpotState.activeIndex ? 'wpot-active-item' : ''}`;\n            element.innerHTML = `\n                <img decoding=\"async\" class=\"wpot-batch-thumb\" src=\"${item.dataUrl}\">\n                <div class=\"wpot-batch-meta\">\n                    <div class=\"wpot-batch-name\">${item.name}<\/div>\n                    <div style=\"font-size:0.7rem; color: var(--wpot-text-muted);\">\n                        ${item.processedText ? 'Processed \u2713' : 'Queued'}\n                    <\/div>\n                <\/div>\n                <div class=\"wpot-batch-actions\">\n                    <button class=\"wpot-btn wpot-btn-danger\" style=\"padding: 2px 6px;\" data-id=\"${item.id}\">\u2715<\/button>\n                <\/div>\n            `;\n\n            element.addEventListener('click', (e) => {\n                if (e.target.tagName !== 'BUTTON') {\n                    wpotSelectQueueItem(index);\n                }\n            });\n\n            element.querySelector('button').addEventListener('click', (e) => {\n                e.stopPropagation();\n                wpotRemoveQueueItem(item.id);\n            });\n\n            batchList.appendChild(element);\n        });\n    }\n\n    function wpotSelectQueueItem(index) {\n        if (index < 0 || index >= wpotState.queue.length) return;\n        wpotState.activeIndex = index;\n        wpotUpdateQueueUI();\n\n        const item = wpotState.queue[index];\n        const img = new Image();\n        img.src = item.dataUrl;\n        img.onload = () => {\n            wpotState.originalImage = img;\n            editorContainer.classList.remove('wpot-hidden');\n            wpotResetFilters();\n            wpotApplyFilters();\n            if (item.processedText) {\n                textOutput.value = item.processedText;\n                wpotUpdateEditorLines();\n                wpotUpdateStats(item);\n            }\n        };\n    }\n\n    function wpotRemoveQueueItem(id) {\n        const index = wpotState.queue.findIndex(item => item.id === id);\n        if (index > -1) {\n            wpotState.queue.splice(index, 1);\n            if (wpotState.activeIndex === index) {\n                wpotState.activeIndex = wpotState.queue.length > 0 ? 0 : -1;\n            } else if (wpotState.activeIndex > index) {\n                wpotState.activeIndex--;\n            }\n            wpotUpdateQueueUI();\n            if (wpotState.activeIndex > -1) {\n                wpotSelectQueueItem(wpotState.activeIndex);\n            }\n        }\n    }\n\n    function wpotResetFilters() {\n        wpotState.filters = {\n            brightness: 0,\n            contrast: 0,\n            grayscale: false,\n            threshold: false,\n            rotation: 0,\n            inverted: false\n        };\n        document.getElementById('wpot-slide-brightness').value = 0;\n        document.getElementById('wpot-slide-contrast').value = 0;\n        document.getElementById('wpot-chk-grayscale').checked = false;\n        document.getElementById('wpot-chk-threshold').checked = false;\n    }\n\n    function wpotInitSliders() {\n        document.getElementById('wpot-slide-brightness').addEventListener('input', (e) => {\n            wpotState.filters.brightness = parseInt(e.target.value);\n            wpotApplyFilters();\n        });\n        document.getElementById('wpot-slide-contrast').addEventListener('input', (e) => {\n            wpotState.filters.contrast = parseInt(e.target.value);\n            wpotApplyFilters();\n        });\n        document.getElementById('wpot-chk-grayscale').addEventListener('change', (e) => {\n            wpotState.filters.grayscale = e.target.checked;\n            wpotApplyFilters();\n        });\n        document.getElementById('wpot-chk-threshold').addEventListener('change', (e) => {\n            wpotState.filters.threshold = e.target.checked;\n            wpotApplyFilters();\n        });\n    }\n\n    function wpotApplyFilters() {\n        if (!wpotState.originalImage) return;\n\n        const ctx = previewCanvas.getContext('2d');\n        const img = wpotState.originalImage;\n\n        \/\/ Manage clean coordinate transformations mapping rotation safely\n        const rotationRad = (wpotState.filters.rotation * Math.PI) \/ 180;\n        if (wpotState.filters.rotation % 180 === 0) {\n            previewCanvas.width = img.width;\n            previewCanvas.height = img.height;\n        } else {\n            previewCanvas.width = img.height;\n            previewCanvas.height = img.width;\n        }\n\n        ctx.clearRect(0, 0, previewCanvas.width, previewCanvas.height);\n        ctx.save();\n        ctx.translate(previewCanvas.width \/ 2, previewCanvas.height \/ 2);\n        ctx.rotate(rotationRad);\n        ctx.drawImage(img, -img.width \/ 2, -img.height \/ 2);\n        ctx.restore();\n\n        \/\/ Process Canvas pixels sequentially matching strict local pipelines\n        const imageData = ctx.getImageData(0, 0, previewCanvas.width, previewCanvas.height);\n        const data = imageData.data;\n        const brightness = wpotState.filters.brightness;\n        const contrastFactor = (259 * (wpotState.filters.contrast + 255)) \/ (255 * (259 - wpotState.filters.contrast));\n\n        for (let i = 0; i < data.length; i += 4) {\n            let r = data[i];\n            let g = data[i+1];\n            let b = data[i+2];\n\n            \/\/ Inversion Filter\n            if (wpotState.filters.inverted) {\n                r = 255 - r;\n                g = 255 - g;\n                b = 255 - b;\n            }\n\n            \/\/ Brightness filter Adjustment\n            r += brightness;\n            g += brightness;\n            b += brightness;\n\n            \/\/ Contrast modifier\n            r = contrastFactor * (r - 128) + 128;\n            g = contrastFactor * (g - 128) + 128;\n            b = contrastFactor * (b - 128) + 128;\n\n            \/\/ Grayscale processing matching standard luma values\n            if (wpotState.filters.grayscale || wpotState.filters.threshold) {\n                const gray = 0.299 * r + 0.587 * g + 0.114 * b;\n                if (wpotState.filters.threshold) {\n                    const binary = gray > 128 ? 255 : 0;\n                    r = g = b = binary;\n                } else {\n                    r = g = b = gray;\n                }\n            }\n\n            \/\/ Clamp final processed byte color bounds safely\n            data[i] = Math.max(0, Math.min(255, r));\n            data[i+1] = Math.max(0, Math.min(255, g));\n            data[i+2] = Math.max(0, Math.min(255, b));\n        }\n\n        ctx.putImageData(imageData, 0, 0);\n    }\n\n    function wpotInitButtons() {\n        document.getElementById('wpot-btn-rotate-l').addEventListener('click', () => {\n            wpotState.filters.rotation = (wpotState.filters.rotation - 90) % 360;\n            wpotApplyFilters();\n        });\n\n        document.getElementById('wpot-btn-rotate-r').addEventListener('click', () => {\n            wpotState.filters.rotation = (wpotState.filters.rotation + 90) % 360;\n            wpotApplyFilters();\n        });\n\n        document.getElementById('wpot-btn-invert').addEventListener('click', () => {\n            wpotState.filters.inverted = !wpotState.filters.inverted;\n            wpotApplyFilters();\n        });\n\n        document.getElementById('wpot-btn-auto-enhance').addEventListener('click', () => {\n            wpotState.filters.contrast = 25;\n            wpotState.filters.brightness = 10;\n            wpotState.filters.threshold = false;\n            wpotState.filters.grayscale = false;\n            document.getElementById('wpot-slide-contrast').value = 25;\n            document.getElementById('wpot-slide-brightness').value = 10;\n            wpotApplyFilters();\n            wpotToast(\"Auto Enhancement processing applied.\");\n        });\n\n        runBtn.addEventListener('click', () => {\n            wpotExecuteBatchOCR();\n        });\n\n        clearQueueBtn.addEventListener('click', () => {\n            wpotState.queue = [];\n            wpotUpdateQueueUI();\n            textOutput.value = '';\n            wpotUpdateEditorLines();\n            wpotToast(\"Batch queue emptied.\");\n        });\n\n        document.getElementById('wpot-btn-reset').addEventListener('click', () => {\n            location.reload();\n        });\n\n        \/\/ Toggle editor styling dark visual preview mode\n        document.getElementById('wpot-btn-toggle-dark').addEventListener('click', (e) => {\n            const grid = document.getElementById('wpot-editor-grid');\n            if (grid.style.background === 'rgb(15, 23, 42)') {\n                grid.style.background = '#ffffff';\n                grid.style.color = 'var(--wpot-text-main)';\n                e.target.innerText = \"Dark Mode Preview\";\n            } else {\n                grid.style.background = '#0f172a';\n                grid.style.color = '#38bdf8';\n                e.target.innerText = \"Light Mode Preview\";\n            }\n        });\n\n        \/\/ Search & replace triggers\n        document.getElementById('wpot-btn-replace').addEventListener('click', () => {\n            const findText = document.getElementById('wpot-search-find').value;\n            const repText = document.getElementById('wpot-search-replace').value;\n            if (!findText) return;\n            const updated = textOutput.value.replaceAll(findText, repText);\n            textOutput.value = updated;\n            wpotUpdateEditorLines();\n            wpotToast(\"Global replacement executed.\");\n        });\n\n        \/\/ Export download functions\n        document.getElementById('wpot-btn-copy').addEventListener('click', () => {\n            navigator.clipboard.writeText(textOutput.value).then(() => {\n                wpotToast(\"Output text successfully copied to clipboard.\");\n            });\n        });\n\n        document.getElementById('wpot-btn-dl-txt').addEventListener('click', () => {\n            wpotTriggerDownload(textOutput.value, 'txt_extraction.txt', 'text\/plain');\n        });\n\n        document.getElementById('wpot-btn-dl-doc').addEventListener('click', () => {\n            \/\/ Generating valid rich XML-formatted DOCX wrapper dynamically\n            const header = \"<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http:\/\/www.w3.org\/TR\/REC-html40'><head><title>Document<\/title><\/head><body>\";\n            const footer = \"<\/body><\/html>\";\n            const source = header + textOutput.value.replace(\/\\n\/g, \"<p><\/p>\") + footer;\n            wpotTriggerDownload(source, 'docx_extraction.doc', 'application\/vnd.ms-word');\n        });\n\n        document.getElementById('wpot-btn-dl-pdf').addEventListener('click', () => {\n            const element = document.createElement('pre');\n            element.style.padding = '30px';\n            element.style.fontFamily = 'Helvetica, Arial, sans-serif';\n            element.style.whiteSpace = 'pre-wrap';\n            element.innerText = textOutput.value || \"Empty extraction content.\";\n            \n            const options = {\n                margin: 15,\n                filename: `local_ocr_${Date.now()}.pdf`,\n                image: { type: 'jpeg', quality: 0.98 },\n                html2canvas: { scale: 2 },\n                jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }\n            };\n            html2pdf().from(element).set(options).save();\n        });\n    }\n\n    function wpotTriggerDownload(content, filename, contentType) {\n        const blob = new Blob([content], { type: contentType });\n        const a = document.createElement('a');\n        a.href = URL.createObjectURL(blob);\n        a.download = filename;\n        document.body.appendChild(a);\n        a.click();\n        document.body.removeChild(a);\n    }\n\n    \/\/ Engine executing localized OCR scans sequential matching Tesseract instance logic\n    async function wpotExecuteBatchOCR() {\n        if (wpotState.queue.length === 0) {\n            wpotToast(\"Queue is empty. Please feed or drag pictures first.\");\n            return;\n        }\n\n        runBtn.disabled = true;\n        progressBarContainer.style.display = 'block';\n        \n        const lang = document.getElementById('wpot-opt-lang').value;\n        statusLog.innerText = \"Initializing localized OCR libraries...\";\n\n        try {\n            \/\/ Spawn separate web-worker parameters matching standard fallback paths\n            const worker = await Tesseract.createWorker(lang, 1, {\n                logger: m => {\n                    if (m.status === 'recognizing') {\n                        const prog = Math.round(m.progress * 100);\n                        progressBar.style.width = prog + '%';\n                        statusLog.innerText = `Extracting matching text layers: ${prog}%`;\n                    }\n                }\n            });\n\n            \/\/ Iterate queued entries synchronously\n            for (let i = 0; i < wpotState.queue.length; i++) {\n                const item = wpotState.queue[i];\n                if (item.processedText) continue; \/\/ Skip processing already executed items\n\n                statusLog.innerText = `Processing batch file [${i+1}\/${wpotState.queue.length}]: ${item.name}`;\n                wpotSelectQueueItem(i);\n\n                const t0 = performance.now();\n                \n                \/\/ OCR executes directly using preprocessed canvas matching modifications\n                const dataUrl = previewCanvas.toDataURL('image\/png');\n                const ret = await worker.recognize(dataUrl);\n                const t1 = performance.now();\n\n                item.processedText = ret.data.text;\n                item.confidence = Math.round(ret.data.confidence);\n                item.processingTime = Math.round((t1 - t0) \/ 1000);\n\n                wpotUpdateQueueUI();\n                if (i === wpotState.activeIndex) {\n                    textOutput.value = item.processedText;\n                    wpotUpdateEditorLines();\n                    wpotUpdateStats(item);\n                }\n            }\n\n            await worker.terminate();\n            statusLog.innerText = \"Batch conversion completed successfully.\";\n            wpotToast(\"Extraction completed with absolute safety.\");\n            wpotSaveHistory(wpotState.queue[wpotState.activeIndex]);\n\n        } catch (err) {\n            statusLog.innerText = \"Execution halted due to system faults.\";\n            wpotToast(\"Error encountered: \" + err.message);\n        } finally {\n            runBtn.disabled = false;\n            progressBarContainer.style.display = 'none';\n        }\n    }\n\n    \/\/ Live Editor Text Metrics Sync Lines\n    function wpotInitEditorSync() {\n        textOutput.addEventListener('input', () => {\n            wpotUpdateEditorLines();\n            wpotUpdateStats();\n        });\n    }\n\n    function wpotUpdateEditorLines() {\n        const val = textOutput.value;\n        const matches = val.split('\\n');\n        let indexString = '';\n        for (let i = 1; i <= matches.length; i++) {\n            indexString += i + '<br>';\n        }\n        lineNumbers.innerHTML = indexString;\n    }\n\n    function wpotUpdateStats(item = null) {\n        const val = textOutput.value;\n        const chars = val.length;\n        const words = val.trim() === '' ? 0 : val.trim().split(\/\\s+\/).length;\n        const lines = val.split('\\n').length;\n\n        document.getElementById('wpot-stat-chars').innerText = chars;\n        document.getElementById('wpot-stat-words').innerText = words;\n        document.getElementById('wpot-stat-lines').innerText = lines;\n\n        if (item) {\n            document.getElementById('wpot-stat-speed').innerText = item.processingTime + 's';\n            document.getElementById('wpot-stat-confidence').innerText = item.confidence + '%';\n        }\n    }\n\n    function wpotSaveHistory(item) {\n        if (!item || !item.processedText) return;\n        const entry = {\n            id: Date.now(),\n            name: item.name,\n            snippet: item.processedText.substring(0, 45) + '...',\n            rawText: item.processedText\n        };\n        wpotState.history.unshift(entry);\n        if (wpotState.history.length > 5) wpotState.history.pop();\n        localStorage.setItem('wpot_ocr_history_recs', JSON.stringify(wpotState.history));\n        wpotLoadHistory();\n    }\n\n    function wpotLoadHistory() {\n        const saved = localStorage.getItem('wpot_ocr_history_recs');\n        const tray = document.getElementById('wpot-history-tray');\n        if (saved) {\n            wpotState.history = JSON.parse(saved);\n            tray.innerHTML = '';\n            wpotState.history.forEach(item => {\n                const el = document.createElement('div');\n                el.className = 'wpot-history-item';\n                el.innerHTML = `\n                    <div style=\"flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;\">\n                        <strong>${item.name}<\/strong> - <span style=\"color:var(--wpot-text-muted);\">${item.snippet}<\/span>\n                    <\/div>\n                    <button class=\"wpot-btn\" style=\"padding:2px 8px; font-size:0.75rem;\">Restore<\/button>\n                `;\n                el.querySelector('button').addEventListener('click', () => {\n                    textOutput.value = item.rawText;\n                    wpotUpdateEditorLines();\n                    wpotUpdateStats();\n                    wpotToast(\"Archived record restored into editor workspace.\");\n                });\n                tray.appendChild(el);\n            });\n        }\n    }\n\n})();\n<\/script>\n\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Enterprise Local OCR Engine &#8211; Pro Edition SaaS Local OCR &#038; Prep Tool Preprocess and extract vector-accurate text in your browser locally. No servers. Total privacy. Engine Language: EnglishHindi (\u0939\u093f\u0928\u094d\u0926\u0940)Mixed (English + Hindi)Spanish (Espa\u00f1ol)French (Fran\u00e7ais)German (Deutsch) Accuracy Target: High Accuracy ModeFast Scan Mode \ud83d\ude80 Run Batch Extraction \ud83d\udd04 Clear All 1. Raw Source Input Pipeline [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-423","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/423","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/comments?post=423"}],"version-history":[{"count":5,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/423\/revisions"}],"predecessor-version":[{"id":518,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/423\/revisions\/518"}],"wp:attachment":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/media?parent=423"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}