{"id":766,"date":"2025-02-07T10:36:12","date_gmt":"2025-02-07T10:36:12","guid":{"rendered":"https:\/\/ocr365.com\/?page_id=766"},"modified":"2025-03-16T06:07:24","modified_gmt":"2025-03-16T06:07:24","slug":"png-para-texto","status":"publish","type":"page","link":"https:\/\/ocr365.com\/pt\/png-to-text\/","title":{"rendered":"Conversor de PNG para texto: PNG para OCR"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"766\" class=\"elementor elementor-766\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1133dad9 e-con-full e-flex e-con e-parent\" data-id=\"1133dad9\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dc55306 elementor-widget elementor-widget-ucaddon_dual_color_heading\" data-id=\"dc55306\" data-element_type=\"widget\" data-widget_type=\"ucaddon_dual_color_heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!-- start Dual Color Heading -->\n\n<div class=\"ue-dual-color-heading\">\n  <h2>\n    <span class=\"ue-title-one\">Png to<\/span> <span class=\"ue-title-two\">Text<\/span>\n  <\/h2>\n<\/div>\n<!-- end Dual Color Heading -->\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-16066ca8 elementor-widget elementor-widget-shortcode\" data-id=\"16066ca8\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><!-- Prevent specific elements from being auto-translated -->\n<meta name=\"google\" content=\"notranslate\">\n       \n<div class=\"vision-upload-container\">\n    <form id=\"visionUploadForm\" method=\"post\" enctype=\"multipart\/form-data\">\n        <!-- Initial upload area -->\n        <div class=\"upload-area\" id=\"initialUploadArea\">\n            <div class=\"upload-instructions\">\n                <div class=\"upload-icon\">\n                    <i class=\"fas fa-cloud-arrow-up\"><\/i>\n                <\/div>\n                <h3>Upload Images<\/h3>\n                <p class=\"upload-desc\">Drop Files<\/p>\n            <\/div>\n            \n            <!-- Native file input with custom button -->\n            <div class=\"file-input-wrapper\">\n                <input type=\"file\" \n                       id=\"visionFileInput\" \n                       name=\"files[]\" \n                       accept=\"image\/jpeg,image\/png,image\/gif,image\/bmp,image\/webp,image\/tiff\" \n                       multiple\n                       style=\"opacity: 0; position: absolute; z-index: -1;\">\n                <button type=\"button\" class=\"custom-file-button\">\n                    <i class=\"fas fa-cloud-arrow-up\"><\/i>\n                    <span class=\"button-text\">Select Images<\/span>\n                <\/button>\n            <\/div>\n            <\/div>\n            \n        <!-- Image Gallery View - initially hidden -->\n        <div class=\"vision-gallery-container\" id=\"imageGalleryView\" style=\"display: none;\">\n            <!-- Gallery Header -->\n            <div class=\"gallery-header\">\n                <div class=\"gallery-info\">\n                    <div class=\"image-counter\">\n                        <i class=\"fas fa-images\"><\/i>\n                        <span class=\"images-count\">0<\/span>\n                    <\/div>\n                <\/div>\n                <div class=\"gallery-actions\">\n                    <button type=\"button\" class=\"action-btn add-more-btn\" title=\"Add More Images\">\n                        <i class=\"fas fa-plus\"><\/i><span class=\"btn-text\">Add<\/span>\n                    <\/button>\n                    <div class=\"selection-controls\">\n                        <button type=\"button\" class=\"action-btn delete-selected\" disabled title=\"Delete Selected Images\">\n                            <i class=\"fas fa-trash\"><\/i><span class=\"btn-text\">Delete<\/span>\n                        <\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- Gallery Grid -->\n            <div class=\"gallery-grid view-grid\">\n                <!-- Images will be populated here -->\n        <\/div>\n\n            <!-- Convert button - only shown below image gallery -->\n        <button type=\"submit\" id=\"visionConvertButton\" disabled>\n                <span class=\"dashicons dashicons-text-page\"><\/span>\n            Convert        <\/button>\n        \n        <!-- Daily Limit Warning - hidden by default -->\n        <div id=\"visionDailyLimitWarning\" class=\"vision-daily-limit-warning\" style=\"display: none;\">\n            <div class=\"limit-warning-content\">\n                <button type=\"button\" class=\"limit-close-btn\" onclick=\"document.getElementById('visionDailyLimitWarning').style.display='none';\">\u00d7<\/button>\n                <div class=\"limit-icon\">\n                    <span class=\"dashicons dashicons-warning\"><\/span>\n                <\/div>\n                <div class=\"limit-message\">\n                    <p class=\"limit-main-text\">You have reached your daily limit of <span class=\"limit-count\">5<\/span> free conversions<\/p>\n                    <p class=\"limit-reset-text\">\n                        Please try again tomorrow or <a href=\"https:\/\/ocr365.com\/pt\/pricing\/\" class=\"inline-upgrade-link\" data-no-translation>upgrade<\/a> for unlimited conversions                    <\/p>\n                    <div class=\"limit-countdown\" id=\"limitCountdown\">\n                        <span class=\"limit-countdown-label\">Resets in:<\/span>\n                        <span class=\"limit-countdown-time\" id=\"limitCountdownTime\">--:--:--<\/span>\n                    <\/div>\n                <\/div>\n                <div class=\"limit-actions\">\n                    <a href=\"https:\/\/ocr365.com\/pt\/pricing\/\" class=\"limit-upgrade-btn\" data-no-translation>\n                        Upgrade Now                    <\/a>\n                <\/div>\n            <\/div>\n        <\/div>\n        \n        <!-- Cloudflare Turnstile Container - only shown for non-subscribers -->\n                <div id=\"visionTurnstileContainer\" class=\"turnstile-container\" style=\"display: none; margin: 20px auto; text-align: center;\">\n            <!-- Turnstile widget will be rendered here -->\n        <\/div>\n                <\/div>\n\n        <!-- Progress Container -->\n        <div id=\"visionProgressContainer\" class=\"vision-progress-container\" style=\"display: none;\">\n            <div class=\"vision-progress-message\">\n                <div class=\"vision-progress-icon\">\n                    <span class=\"dashicons dashicons-update\"><\/span>\n                <\/div>\n                <div class=\"vision-progress-text\">Processing your images...<\/div>\n            <\/div>\n            <div class=\"vision-progress-status\">\n                <div class=\"vision-progress-bar\"><\/div>\n            <\/div>\n        <\/div>\n\n        <!-- Results Container -->\n        <div id=\"visionResults\"><\/div>\n\n        <!-- Error Messages -->\n        <div id=\"visionErrorMessages\" class=\"error-message\" style=\"display: none;\"><\/div>\n    <\/form>\n<\/div>\n\n<!-- Image Preview Modal -->\n<div class=\"vision-image-preview-modal\">\n    <div class=\"modal-overlay\"><\/div>\n    <div class=\"modal-content\">\n        <button class=\"modal-close\"><i class=\"fas fa-times\"><\/i><\/button>\n        <div class=\"preview-navigation\">\n            <button class=\"nav-btn prev-image\"><i class=\"fas fa-chevron-left\"><\/i><\/button>\n            <div class=\"preview-image-container\">\n                <img decoding=\"async\" src=\"\" alt=\"Preview\" class=\"preview-image\">\n            <\/div>\n            <button class=\"nav-btn next-image\"><i class=\"fas fa-chevron-right\"><\/i><\/button>\n        <\/div>\n        <div class=\"preview-info\">\n            <h3 class=\"preview-filename\"><\/h3>\n            <div class=\"preview-metadata\">\n                <span class=\"preview-size\"><\/span>\n                <span class=\"preview-dimensions\"><\/span>\n                <span class=\"preview-type\"><\/span>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<!-- Modal window for limit notification -->\n<div id=\"visionLimitModal\" class=\"vision-limit-modal\">\n    <div class=\"vision-limit-content\">\n        <div class=\"vision-limit-close\" id=\"limitModalCloseBtn\">\u00d7<\/div>\n        \n        <div class=\"vision-limit-header\">\n            <div class=\"limit-icon\">\n                <span class=\"dashicons dashicons-lock\"><\/span>\n            <\/div>\n            <h3>Batch Upload Limit<\/h3>\n            <p>You have reached the batch upload limit for free users<\/p>\n        <\/div>\n\n        <div class=\"vision-limit-plan\">\n            <div class=\"plan-badge\">Pro<\/div>\n            <ul class=\"vision-limit-features\">\n                <li>\n                    Larger batch upload limits\n                <\/li>\n                <li>\n                    Unlimited daily conversions\n                <\/li>\n                <li>\n                    Priority processing\n                <\/li>\n            <\/ul>\n        <\/div>\n\n        <div class=\"vision-limit-actions\">\n            <a href=\"https:\/\/ocr365.com\/pt\/pricing\/\" \n               class=\"vision-upgrade-button\" data-no-translation>\n                Upgrade to Pro\n            <\/a>\n        <\/div>\n    <\/div>\n<\/div>\n\n<script>\n\/\/ Wait for DOM to be fully loaded\ndocument.addEventListener('DOMContentLoaded', function() {\n    \/\/ Get the close button element\n    var closeBtn = document.getElementById('limitModalCloseBtn');\n    if (closeBtn) {\n        \/\/ Add click event listener\n        closeBtn.addEventListener('click', function() {\n            \/\/ Check if global closeModal function exists\n            if (typeof closeModal === 'function') {\n                closeModal();\n            } else {\n                \/\/ If function doesn't exist, hide modal directly\n                var modal = document.getElementById('visionLimitModal');\n                if (modal) {\n                    modal.style.display = 'none';\n                    document.body.style.overflow = '';\n                }\n            }\n        });\n    }\n});\n<\/script> \n<!-- Add required libraries -->\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.4.0\/css\/all.min.css\">\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\/FileSaver.js\/2.0.5\/FileSaver.min.js\"><\/script>\n\n<script>\n\/\/ Define a simple and effective returnToUpload function\nwindow.returnToUpload = function(event) {\n    if (event) event.preventDefault();\n    \n    \/\/ Show upload area\n    document.getElementById('initialUploadArea').style.display = 'block';\n    document.getElementById('visionResults').style.display = 'none';\n    \n    \/\/ Remove body class when results are hidden\n    document.body.classList.remove('vision-results-active');\n    \n    \/\/ Clear results container\n    document.getElementById('visionResults').innerHTML = '';\n    \n    return false;\n};\n\ndocument.addEventListener('DOMContentLoaded', function() {\n    var fileInput = document.getElementById('visionFileInput');\n    var customButton = document.querySelector('.custom-file-button .button-text');\n    var convertButton = document.getElementById('visionConvertButton');\n    var selectedFilesMap = new Map();\n    var initialUploadArea = document.getElementById('initialUploadArea');\n    var imageGalleryView = document.getElementById('imageGalleryView');\n    var galleryGrid = document.querySelector('.gallery-grid');\n    var previewModal = document.querySelector('.vision-image-preview-modal');\n    var turnstileContainer = document.getElementById('visionTurnstileContainer');\n    var turnstileToken = '';\n    var turnstileWidgetId = null;\n    let currentImageIndex = 0;\n    let galleryItems = [];\n    let isSubmitting = false; \/\/ Add submission status flag\n    \n    \/\/ Output debug information to verify wpVision object is correctly loaded\n    console.log('VisionPlugin initialization - Batch upload limits:', {\n        wpVision: typeof wpVision !== 'undefined' ? {\n            maxFiles: wpVision.maxFiles,\n            subscriptionType: wpVision.subscriptionType\n        } : 'undefined',\n        maxBatchLimit: typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n            (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 'undefined'\n    });\n    \n    \/\/ Ensure progress container is hidden on page load\n    const progressContainer = document.getElementById('visionProgressContainer');\n    if (progressContainer) {\n        progressContainer.style.display = 'none';\n    }\n    \n    \/\/ Initialize drag and drop functionality\n    initializeDragDrop();\n    \n    function initializeDragDrop() {\n        if (!initialUploadArea) return;\n        \n        \/\/ Add event listeners for drag and drop area\n        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n            initialUploadArea.addEventListener(eventName, preventDefaults, false);\n        });\n        \n        \/\/ Add drag effects\n        initialUploadArea.addEventListener('dragenter', highlight, false);\n        initialUploadArea.addEventListener('dragover', highlight, false);\n        initialUploadArea.addEventListener('dragleave', unhighlight, false);\n        initialUploadArea.addEventListener('drop', unhighlight, false);\n        \n        \/\/ Handle file drop\n        initialUploadArea.addEventListener('drop', handleDrop, false);\n        \n        function preventDefaults(e) {\n            e.preventDefault();\n            e.stopPropagation();\n        }\n        \n        function highlight() {\n            initialUploadArea.classList.add('highlight');\n        }\n        \n        function unhighlight() {\n            initialUploadArea.classList.remove('highlight');\n        }\n        \n        function handleDrop(e) {\n            const dt = e.dataTransfer;\n            const files = dt.files;\n            \n            \/\/ Directly use the same logic as click upload\n            if (files && files.length > 0) {\n                \/\/ Set dropped files to the file input element to trigger the same handling as click upload\n                try {\n                    \/\/ Create a DataTransfer object\n                    const dataTransfer = new DataTransfer();\n                    \n                    \/\/ Add all dropped files\n                    Array.from(files).forEach(file => {\n                        dataTransfer.items.add(file);\n                    });\n                    \n                    \/\/ Set to file input element\n                    fileInput.files = dataTransfer.files;\n                    \n                    \/\/ Manually trigger change event to execute the same logic as click upload\n                    const event = new Event('change', { bubbles: true });\n                    fileInput.dispatchEvent(event);\n                } catch (error) {\n                    console.error('Error setting files:', error);\n                    \/\/ If file setting fails, show an error\n                    showError('Error processing files, please try selecting files using the upload button.');\n                }\n            }\n        }\n    }\n    \n    if (fileInput && customButton) {\n        fileInput.addEventListener('change', function() {\n            \/\/ Check file limits before adding files\n            const newFiles = Array.from(this.files);\n            \n            \/\/ Check and filter duplicate files\n            const uniqueFiles = filterDuplicateFiles(newFiles);\n            \n            \/\/ If all files are duplicates, notify the user\n            if (uniqueFiles.length === 0 && newFiles.length > 0) {\n                showError('Duplicate files detected', 'warning');\n                return;\n            }\n            \n            \/\/ Use the same checking method as handleFiles function\n            \/\/ Check file limits with auto-trimming enabled\n            if (!checkFileLimits(uniqueFiles, true)) return;\n            \n            \/\/ Get the limited files if needed\n            const limitedFiles = getLimitedFiles(uniqueFiles);\n            if (limitedFiles.length === 0) return;\n            \n            \/\/ Store allowed files\n            limitedFiles.forEach((file, index) => {\n                const fileId = 'file_' + Date.now() + '_' + index;\n                selectedFilesMap.set(fileId, file);\n            });\n            \n            updateButtonText();\n            updateGalleryInfo();\n            showGalleryView();\n            renderGalleryItems();\n        });\n\n        \/\/ Function to check for duplicate files\n        function filterDuplicateFiles(newFiles) {\n            const uniqueFiles = [];\n            \n            newFiles.forEach(newFile => {\n                let isDuplicate = false;\n                \n                \/\/ Check existing files for duplicates\n                selectedFilesMap.forEach(existingFile => {\n                    \/\/ Determine if files are identical by name and size\n                    if (existingFile.name === newFile.name && existingFile.size === newFile.size) {\n                        isDuplicate = true;\n                    }\n                });\n                \n                \/\/ If not a duplicate, add to unique files list\n                if (!isDuplicate) {\n                    uniqueFiles.push(newFile);\n                }\n            });\n            \n            return uniqueFiles;\n        }\n\n        \/\/ Trigger file input when custom button is clicked\n        document.querySelector('.custom-file-button').addEventListener('click', function() {\n            fileInput.click();\n        });\n        \n        \/\/ Add more images button\n        document.querySelector('.add-more-btn').addEventListener('click', function() {\n            \/\/ Create a new file input element\n            const newFileInput = document.createElement('input');\n            newFileInput.type = 'file';\n            newFileInput.multiple = true;\n            newFileInput.accept = 'image\/jpeg,image\/png,image\/gif,image\/bmp,image\/webp,image\/tiff';\n            \n            \/\/ Listen for change event on new file input\n            newFileInput.addEventListener('change', function(e) {\n                \/\/ Get newly selected files\n                const newFiles = Array.from(this.files);\n                \n                \/\/ Use the same duplicate file filter function\n                const uniqueFiles = filterDuplicateFiles(newFiles);\n                \n                \/\/ If all files are duplicates, show a warning\n                if (uniqueFiles.length === 0 && newFiles.length > 0) {\n                    showError('Duplicate files detected', 'warning');\n                    document.body.removeChild(newFileInput); \/\/ Remove temporary element\n                    return;\n                }\n                \n                \/\/ Calculate current files count and max files limit\n                const currentCount = selectedFilesMap.size;\n                const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                    (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n                \n                \/\/ First check file limits without auto-trimming to show modal\n                if (currentCount + uniqueFiles.length > maxFiles) {\n                    checkFileLimits(uniqueFiles, false);\n                }\n                \n                \/\/ Now check with auto-trimming to process files\n                if (!checkFileLimits(uniqueFiles, true)) {\n                    document.body.removeChild(newFileInput); \/\/ Remove temporary element\n                    return;\n                }\n                \n                \/\/ Get the limited files if needed\n                const limitedFiles = getLimitedFiles(uniqueFiles);\n                if (limitedFiles.length === 0) {\n                    document.body.removeChild(newFileInput); \/\/ Remove temporary element\n                    return;\n                }\n                \n                \/\/ Store allowed files\n                limitedFiles.forEach((file, index) => {\n                    const fileId = 'file_' + Date.now() + '_' + index;\n                    selectedFilesMap.set(fileId, file);\n                });\n                \n                updateButtonText();\n                updateGalleryInfo();\n                showGalleryView();\n                renderGalleryItems();\n                \n                \/\/ Remove the temporary file input element\n                document.body.removeChild(newFileInput);\n            });\n            \n            \/\/ Append new file input to body and trigger click\n            document.body.appendChild(newFileInput);\n            newFileInput.style.display = 'none';\n            newFileInput.click();\n        });\n        \n        \/\/ Delete selected button\n        document.querySelector('.delete-selected').addEventListener('click', function() {\n            const selectedCheckboxes = document.querySelectorAll('.gallery-item-checkbox:checked');\n            selectedCheckboxes.forEach(checkbox => {\n                const galleryItem = checkbox.closest('.gallery-item');\n                if (galleryItem) {\n                    const fileId = galleryItem.getAttribute('data-file-id');\n                    selectedFilesMap.delete(fileId);\n                    galleryItem.remove();\n                }\n            });\n            \n            updateGalleryInfo();\n            updateButtonText();\n            updateDeleteSelectedButton();\n            \n            \/\/ If no images left, return to initial upload view\n            if (selectedFilesMap.size === 0) {\n                showInitialUploadArea();\n            }\n        });\n        \n        \/\/ Handle gallery item events (preview and delete)\n        galleryGrid.addEventListener('click', function(e) {\n            \/\/ Handle preview action\n            if (e.target.closest('.preview-action')) {\n                const galleryItem = e.target.closest('.gallery-item');\n                openPreviewModal(galleryItem);\n            }\n            \n            \/\/ Handle delete action\n            if (e.target.closest('.delete-action')) {\n                const galleryItem = e.target.closest('.gallery-item');\n                const fileId = galleryItem.getAttribute('data-file-id');\n                selectedFilesMap.delete(fileId);\n                galleryItem.remove();\n                \n                updateGalleryInfo();\n                updateButtonText();\n                \n                \/\/ Update gallery items array\n                galleryItems = Array.from(document.querySelectorAll('.gallery-item'));\n                \n                \/\/ If no images left, return to initial upload view\n                if (selectedFilesMap.size === 0) {\n                    showInitialUploadArea();\n                }\n            }\n        });\n        \n        \/\/ Image preview modal handlers\n        document.querySelector('.modal-close').addEventListener('click', closePreviewModal);\n        document.querySelector('.modal-overlay').addEventListener('click', function(e) {\n            if (e.target === this) {\n                closePreviewModal();\n            }\n        });\n        \n        \/\/ Navigation in preview modal\n        document.querySelector('.prev-image').addEventListener('click', function() {\n            if (currentImageIndex > 0) {\n                currentImageIndex--;\n                updatePreviewImage();\n            }\n        });\n        \n        document.querySelector('.next-image').addEventListener('click', function() {\n            if (currentImageIndex < galleryItems.length - 1) {\n                currentImageIndex++;\n                updatePreviewImage();\n            }\n        });\n\n        \/\/ Function to update button text and file input state\n        function updateButtonText() {\n            const filesCount = selectedFilesMap.size;\n            customButton.textContent = filesCount > 0 ? \n                'Images Selected' : \n                'Select Images';\n            \n            \/\/ Show\/hide convert button based on file count\n            if (filesCount > 0) {\n                convertButton.classList.add('show');\n                convertButton.disabled = false;\n            } else {\n                convertButton.classList.remove('show');\n                convertButton.disabled = true;\n            }\n\n            \/\/ Sync the native file input with selected files\n            const dataTransfer = new DataTransfer();\n            selectedFilesMap.forEach(file => {\n                dataTransfer.items.add(file);\n            });\n            fileInput.files = dataTransfer.files;\n        }\n\n        \/\/ Function to show gallery view\n        function showGalleryView() {\n            if (initialUploadArea && imageGalleryView) {\n                initialUploadArea.style.display = 'none';\n                imageGalleryView.style.display = 'flex';\n            }\n        }\n        \n        \/\/ Function to show initial upload area\n        function showInitialUploadArea() {\n            if (initialUploadArea && imageGalleryView) {\n                initialUploadArea.style.display = 'block';\n                imageGalleryView.style.display = 'none';\n            }\n        }\n        \n        \/\/ Update gallery info (count, etc)\n        function updateGalleryInfo() {\n            const count = selectedFilesMap.size;\n            document.querySelector('.images-count').textContent = count;\n            \n            \/\/ Update convert button state\n            if (convertButton) {\n                convertButton.disabled = count === 0;\n                convertButton.classList.toggle('show', count > 0);\n            }\n            \n            \/\/ Update delete selected button state\n            updateDeleteSelectedButton();\n        }\n        \n        \/\/ Render all gallery items\n        function renderGalleryItems() {\n            \/\/ Clear current gallery\n            galleryGrid.innerHTML = '';\n            galleryItems = [];\n            \n            \/\/ Add each file to the gallery\n            selectedFilesMap.forEach((file, fileId) => {\n                createGalleryItem(file, fileId);\n            });\n            \n            \/\/ Update gallery info after rendering\n            updateGalleryInfo();\n        }\n        \n        \/\/ Create a single gallery item\n        function createGalleryItem(file, fileId) {\n            const reader = new FileReader();\n            const galleryItem = document.createElement('div');\n            galleryItem.className = 'gallery-item';\n            galleryItem.setAttribute('data-file-id', fileId);\n            \n            reader.onload = function(e) {\n                \/\/ Create image element to get dimensions\n                const img = new Image();\n                img.onload = function() {\n                    const dimensions = `${this.width} \u00d7 ${this.height}`;\n                    \n                    \/\/ Update item HTML\n                    galleryItem.innerHTML = `\n                        <div class=\"item-checkbox\">\n                            <input type=\"checkbox\" class=\"gallery-item-checkbox\">\n                        <\/div>\n                        <div class=\"item-preview\">\n                            <img decoding=\"async\" src=\"${e.target.result}\" alt=\"${file.name}\">\n                            <div class=\"item-overlay\">\n                                <button type=\"button\" class=\"item-action preview-action\"><i class=\"fas fa-search-plus\"><\/i><\/button>\n                                <button type=\"button\" class=\"item-action delete-action\"><i class=\"fas fa-trash\"><\/i><\/button>\n                            <\/div>\n                        <\/div>\n                        <div class=\"item-info\">\n                            <h4 class=\"item-name\" title=\"${file.name}\">${file.name}<\/h4>\n                            <span class=\"item-meta\">${formatFileSize(file.size)} \u00b7 ${dimensions}<\/span>\n                        <\/div>\n                    `;\n                    \n                    \/\/ Add event listeners for checkbox\n                    const checkbox = galleryItem.querySelector('.gallery-item-checkbox');\n                    checkbox.addEventListener('change', function() {\n                        updateDeleteSelectedButton();\n                    });\n                    \n                    \/\/ Update gallery items array\n                    galleryItems = Array.from(document.querySelectorAll('.gallery-item'));\n                };\n                img.src = e.target.result;\n            };\n            \n            reader.onerror = function() {\n                console.error(\"Error reading file:\", file.name);\n            };\n            \n            reader.readAsDataURL(file);\n            galleryGrid.appendChild(galleryItem);\n        }\n        \n        \/\/ Format file size for display\n        function formatFileSize(bytes) {\n            if (bytes === 0) return '0 Bytes';\n            const k = 1024;\n            const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n            const i = Math.floor(Math.log(bytes) \/ Math.log(k));\n            return parseFloat((bytes \/ Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n        }\n        \n        \/\/ Open preview modal\n        function openPreviewModal(galleryItem) {\n            galleryItems = Array.from(document.querySelectorAll('.gallery-item'));\n            currentImageIndex = galleryItems.indexOf(galleryItem);\n            \n            updatePreviewImage();\n            previewModal.classList.add('open');\n            document.body.style.overflow = 'hidden'; \/\/ Prevent background scrolling\n        }\n        \n        \/\/ Close preview modal\n        function closePreviewModal() {\n            previewModal.classList.remove('open');\n            document.body.style.overflow = '';\n        }\n        \n        \/\/ Update preview image and navigation\n        function updatePreviewImage() {\n            const galleryItem = galleryItems[currentImageIndex];\n            const fileId = galleryItem.getAttribute('data-file-id');\n            const file = selectedFilesMap.get(fileId);\n            const img = galleryItem.querySelector('.item-preview img');\n            const name = galleryItem.querySelector('.item-name').textContent;\n            const metaText = galleryItem.querySelector('.item-meta').textContent;\n            \n            \/\/ Update modal content\n            document.querySelector('.preview-image').src = img.src;\n            document.querySelector('.preview-filename').textContent = name;\n            \n            \/\/ Parse metadata\n            const sizeMatch = metaText.match(\/([0-9.]+\\s+[A-Z]+)\/);\n            const dimensionsMatch = metaText.match(\/([0-9]+\\s+\u00d7\\s+[0-9]+)\/);\n            \n            if (sizeMatch) document.querySelector('.preview-size').textContent = sizeMatch[0];\n            if (dimensionsMatch) document.querySelector('.preview-dimensions').textContent = dimensionsMatch[0];\n            document.querySelector('.preview-type').textContent = file.type.split('\/')[1].toUpperCase();\n            \n            \/\/ Update navigation buttons\n            document.querySelector('.prev-image').disabled = currentImageIndex === 0;\n            document.querySelector('.next-image').disabled = currentImageIndex === galleryItems.length - 1;\n        }\n        \n        \/\/ Update delete selected button state\n        function updateDeleteSelectedButton() {\n            const selectedCount = document.querySelectorAll('.gallery-item-checkbox:checked').length;\n            document.querySelector('.delete-selected').disabled = selectedCount === 0;\n        }\n\n        \/\/ Keyboard navigation for preview modal\n        document.addEventListener('keydown', function(e) {\n            if (!previewModal.classList.contains('open')) return;\n            \n            switch(e.key) {\n                case 'Escape':\n                    closePreviewModal();\n                    break;\n                case 'ArrowLeft':\n                    if (currentImageIndex > 0) {\n                        currentImageIndex--;\n                        updatePreviewImage();\n                    }\n                    break;\n                case 'ArrowRight':\n                    if (currentImageIndex < galleryItems.length - 1) {\n                        currentImageIndex++;\n                        updatePreviewImage();\n                    }\n                    break;\n            }\n        });\n\n        \/\/ Update file handling function\n        function handleFiles(files) {\n            if (!files.length) return;\n            \n            \/\/ Filter files for valid types first\n            const validFiles = Array.from(files).filter(file => {\n                \/\/ Define allowed MIME types\n                const allowedTypes = [\n                    'image\/jpeg',\n                    'image\/png',\n                    'image\/gif',\n                    'image\/bmp',\n                    'image\/webp',\n                    'image\/tiff'\n                ];\n                \n                const isValid = allowedTypes.includes(file.type);\n                \n                if (!isValid) {\n                    showError(`${file.name} is not a supported image format. Supported formats: JPEG, PNG, GIF, BMP, WebP, TIFF`);\n                }\n                \n                return isValid;\n            });\n            \n            \/\/ Calculate current files count and max files limit\n            const currentCount = selectedFilesMap.size;\n            const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n            \n            \/\/ First check file limits without auto-trimming to show modal\n            if (currentCount + validFiles.length > maxFiles) {\n                checkFileLimits(validFiles, false);\n            }\n            \n            \/\/ Now check with auto-trimming to process files\n            if (!checkFileLimits(validFiles, true)) return;\n            \n            \/\/ Get the limited files if needed\n            const limitedFiles = getLimitedFiles(validFiles);\n            if (limitedFiles.length === 0) return;\n            \n            \/\/ Process each file\n            limitedFiles.forEach(file => {\n                const fileId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);\n                selectedFilesMap.set(fileId, file);\n                createFilePreview(file, fileId);\n            });\n            \n            \/\/ Update UI\n            updateButtonText();\n            showGalleryView();\n            renderGalleryItems();\n        }\n\n        \/\/ Add function to check file limits\n        function checkFileLimits(files, shouldTrim = false) {\n            const currentCount = selectedFilesMap.size;\n            const newCount = files.length;\n            const totalCount = currentCount + newCount;\n            \n            \/\/ Get maximum file limit\n            const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n            \n            \/\/ Add detailed debug logs\n            console.log('Checking batch upload limits:', {\n                currentFilesCount: currentCount,\n                newFilesCount: newCount, \n                totalFilesCount: totalCount,\n                maxLimit: maxFiles,\n                subscriptionType: wpVision.subscriptionType,\n                shouldTrim: shouldTrim,\n                exceedsLimit: totalCount > maxFiles\n            });\n            \n            if (totalCount > maxFiles) {\n                \/\/ If not in trim mode, just show the modal and return false\n                if (!shouldTrim) {\n                    const limitModal = document.getElementById('visionLimitModal');\n                    if (limitModal) {\n                        limitModal.style.display = 'flex';\n                        document.body.style.overflow = 'hidden';\n                    } else {\n                        alert(`You can upload a maximum of ${maxFiles} images at once. Please remove some images and try again.`);\n                    }\n                    return false;\n                }\n                \n                \/\/ Calculate how many more files we can add\n                const remainingSlots = Math.max(0, maxFiles - currentCount);\n                \n                \/\/ If we can't add any more files\n                if (remainingSlots <= 0) {\n                    const limitModal = document.getElementById('visionLimitModal');\n                    if (limitModal) {\n                        limitModal.style.display = 'flex';\n                        document.body.style.overflow = 'hidden';\n                    }\n                    return false;\n                }\n                \n                \/\/ Always show the modal when exceeding limits, even in trim mode\n                const limitModal = document.getElementById('visionLimitModal');\n                if (limitModal) {\n                    limitModal.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                }\n                \n                \/\/ Return true since we'll process some files\n                return true;\n            }\n            \n            return true;\n        }\n        \n        \/\/ Function to get limited files according to subscription limits\n        function getLimitedFiles(files) {\n            const currentCount = selectedFilesMap.size;\n            \n            \/\/ Get maximum file limit\n            const maxFiles = typeof wpVision !== 'undefined' && wpVision.maxFiles ? \n                (wpVision.maxFiles[wpVision.subscriptionType] || wpVision.maxFiles.free) : 3;\n                \n            if (currentCount + files.length > maxFiles) {\n                \/\/ Calculate how many more files we can add\n                const remainingSlots = Math.max(0, maxFiles - currentCount);\n                \n                \/\/ If we can't add any more files\n                if (remainingSlots <= 0) {\n                    return [];\n                }\n                \n                \/\/ Return only the allowed number of files\n                return files.slice(0, remainingSlots);\n            }\n            \n            \/\/ If within limits, return all files\n            return files;\n        }\n\n        \/\/ Add function to show errors\n        function showError(message, type = 'error', duration = 3000) {\n            \/\/ Create or get toast notification element\n            let toastElement = document.querySelector('.vision-notification-toast');\n            if (!toastElement) {\n                toastElement = document.createElement('div');\n                toastElement.className = 'vision-notification-toast';\n                document.body.appendChild(toastElement);\n            }\n            \n            \/\/ Set notification type style\n            toastElement.className = `vision-notification-toast ${type}`;\n            \n            \/\/ Set notification content\n            toastElement.innerHTML = `\n                <div class=\"toast-icon\">\n                    ${type === 'error' ? '<i class=\"fas fa-exclamation-circle\"><\/i>' : \n                      type === 'warning' ? '<i class=\"fas fa-exclamation-triangle\"><\/i>' : \n                      '<i class=\"fas fa-info-circle\"><\/i>'}\n                <\/div>\n                <div class=\"toast-message\">${message}<\/div>\n            `;\n            \n            \/\/ Show notification\n            toastElement.classList.add('show');\n            \n            \/\/ Set auto-hide\n            setTimeout(() => {\n                toastElement.classList.remove('show');\n            }, duration);\n        }\n\n        \/\/ Add form submission event listener\n        document.getElementById('visionUploadForm').addEventListener('submit', function(e) {\n            e.preventDefault();\n            \n            \/\/ Prevent multiple submissions\n            if (isSubmitting) {\n                console.log('Form is already being submitted');\n                return;\n            }\n            \n            \/\/ Make sure results container is empty and hidden initially\n            const resultsContainer = document.getElementById('visionResults');\n            if (resultsContainer) {\n                resultsContainer.innerHTML = '';\n                resultsContainer.style.display = 'none';\n            }\n            \n            \/\/ Check if user is a subscriber\n            const isSubscriber = wpVision.isSubscriber;\n            \n            \/\/ If Turnstile is enabled and user is not a subscriber\n            if (wpVision.turnstile.enabled && !isSubscriber) {\n                \/\/ If Turnstile token is not yet obtained, show the Turnstile widget\n                if (!turnstileToken) {\n                    \/\/ Show Turnstile container\n                    if (turnstileContainer) {\n                        turnstileContainer.style.display = 'block';\n                    }\n                    \n                    \/\/ Scroll to Turnstile container\n                    if (turnstileContainer) {\n                        turnstileContainer.scrollIntoView({ behavior: 'smooth', block: 'center' });\n                    }\n                    \n                    \/\/ Render Turnstile widget if not already rendered\n                    if (!turnstileWidgetId && turnstileContainer) {\n                        turnstileWidgetId = turnstile.render('#visionTurnstileContainer', {\n                            sitekey: wpVision.turnstile.siteKey,\n                            callback: function(token) {\n                                console.log('Turnstile verification successful');\n                                \/\/ Store token\n                                turnstileToken = token;\n                                \n                                \/\/ Hide Turnstile container\n                                if (turnstileContainer) {\n                                    turnstileContainer.style.display = 'none';\n                                }\n                                \n                                \/\/ Now start the actual form submission process\n                                startFormSubmission();\n                            },\n                            'expired-callback': function() {\n                                \/\/ Reset token\n                                turnstileToken = '';\n                                turnstileWidgetId = null;\n                            }\n                        });\n                    }\n                    \n                    return;\n                }\n            }\n            \n            \/\/ If we reach here, either user is a subscriber or Turnstile verification is complete\n            startFormSubmission();\n        });\n        \n        \/\/ Override the global showProgress function to prevent it from being called elsewhere\n        window.showProgress = function() {\n            console.log('Global showProgress called but ignored');\n            \/\/ Do nothing - we'll control progress display ourselves\n        };\n        \n        \/\/ Function to start the form submission process\n        function startFormSubmission() {\n            console.log('Starting form submission process');\n            isSubmitting = true;\n            \n            \/\/ Hide image gallery and initial upload area\n            if (imageGalleryView) {\n                imageGalleryView.style.display = 'none';\n            }\n            \n            if (initialUploadArea) {\n                initialUploadArea.style.display = 'none';\n            }\n            \n            \/\/ Show loading state on button\n            if (convertButton) {\n                convertButton.disabled = true;\n                convertButton.innerHTML = '<span class=\"dashicons dashicons-update rotating\"><\/span> Converting...';\n            }\n            \n            \/\/ Now show results container with progress animation\n            const resultsContainer = document.getElementById('visionResults');\n            if (resultsContainer) {\n                resultsContainer.style.display = 'block';\n                \n                \/\/ Create animated progress indicator\n                const progressHtml = `\n                    <div class=\"vision-animated-loader\">\n                        <div class=\"loader-pulse\">\n                            <div class=\"loader-track\"><\/div>\n                            <div class=\"loader-progress\"><\/div>\n                            <div class=\"loader-circle\"><\/div>\n                            <div class=\"loader-particles\">\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                                <div class=\"particle\"><\/div>\n                            <\/div>\n                            <div class=\"loader-complete\"><\/div>\n                        <\/div>\n                    <\/div>\n                `;\n                \n                resultsContainer.innerHTML = progressHtml;\n            }\n            \n            \/\/ Now proceed with the actual AJAX submission\n            submitFormData();\n        }\n        \n        \/\/ Function to submit the form data via AJAX\n        async function submitFormData() {\n            try {\n                \/\/ Create FormData object\n                const formData = new FormData();\n                \n                \/\/ Add all selected files\n                selectedFilesMap.forEach((file, fileId) => {\n                    formData.append('files[]', file);\n                });\n                \n                \/\/ Add other necessary data\n                formData.append('action', 'vision_convert_images');\n                formData.append('nonce', wpVision.nonce);\n                \n                \/\/ Add Turnstile token if available\n                if (turnstileToken) {\n                    formData.append('turnstile_token', turnstileToken);\n                }\n                \n                console.log('Sending AJAX request');\n                \/\/ Send a single AJAX request\n                const response = await fetch(wpVision.ajaxurl, {\n                    method: 'POST',\n                    body: formData,\n                    credentials: 'same-origin'\n                });\n\n                const data = await response.json();\n                \n                \/\/ Clear animated progress indicator\n                const resultsContainer = document.getElementById('visionResults');\n                if (resultsContainer) {\n                    resultsContainer.innerHTML = '';\n                }\n                \n                \/\/ Check for daily limit error in error response\n                if (!data.success && data.data && data.data.error === 'daily_limit_reached') {\n                    console.log('Daily limit reached:', data.data);\n                    \n                    \/\/ Update daily uploads count\n                    if (data.data.dailyUploadsCount !== undefined) {\n                        wpVision.dailyUploadsCount = data.data.dailyUploadsCount;\n                    }\n                    \n                    \/\/ Show gallery view again\n                    if (imageGalleryView) {\n                        imageGalleryView.style.display = 'block';\n                    }\n                    \n                    \/\/ Show daily limit warning\n                    const limitWarning = document.getElementById('visionDailyLimitWarning');\n                    if (limitWarning) {\n                        limitWarning.style.display = 'block';\n                        limitWarning.classList.add('show');\n                    }\n                    \n                    \/\/ Disable convert button\n                    if (convertButton) {\n                        convertButton.disabled = true;\n                        convertButton.classList.add('disabled-by-limit');\n                    }\n                    \n                    \/\/ Start countdown timer\n                    startLimitCountdown();\n                    \n                    \/\/ Show user-friendly message\n                    showError(data.data.message || 'Daily limit reached. Please try again tomorrow.');\n                    return;\n                }\n                \n                if (data.success) {\n                    console.log('AJAX request successful');\n                    \n                    \/\/ Update daily uploads count if provided in response\n                    if (data.data.dailyUploadsCount !== undefined) {\n                        wpVision.dailyUploadsCount = data.data.dailyUploadsCount;\n                        \n                        \/\/ If we've reached the limit during this upload, show warning after displaying results\n                        if (data.data.reachedLimit) {\n                            setTimeout(() => {\n                                const limitWarning = document.getElementById('visionDailyLimitWarning');\n                                if (limitWarning) {\n                                    limitWarning.style.display = 'block';\n                                    limitWarning.classList.add('show');\n                                }\n                                \n                                \/\/ Start countdown timer\n                                startLimitCountdown();\n                            }, 1000);\n                        }\n                    }\n                    \n                    \/\/ Display conversion results\n                    const results = data.data.results || data.data;\n                    displayResults(results);\n                } else {\n                    console.log('AJAX request failed:', data.data);\n                    showError(data.data || 'Error processing images');\n                    \n                    \/\/ Show gallery view again\n                    if (imageGalleryView) {\n                        imageGalleryView.style.display = 'block';\n                    }\n                    \n                    \/\/ Reset Turnstile if verification failed\n                    if (data.data && data.data.includes && data.data.includes('verification')) {\n                        turnstileToken = '';\n                        if (turnstileWidgetId) {\n                            turnstile.reset(turnstileWidgetId);\n                        }\n                        if (turnstileContainer) {\n                            turnstileContainer.style.display = 'block';\n                        }\n                    }\n                }\n            } catch (error) {\n                console.error('Error:', error);\n                showError('Network error occurred');\n                \n                \/\/ Show gallery view again\n                if (imageGalleryView) {\n                    imageGalleryView.style.display = 'block';\n                }\n                \n                \/\/ Clear animated progress indicator\n                const resultsContainer = document.getElementById('visionResults');\n                if (resultsContainer) {\n                    resultsContainer.innerHTML = '';\n                }\n            } finally {\n                \/\/ Reset button state\n                if (convertButton) {\n                    convertButton.disabled = false;\n                    convertButton.innerHTML = '<span class=\"dashicons dashicons-text-page\"><\/span> Convert';\n                }\n                \n                isSubmitting = false; \/\/ Reset submission status\n            }\n        }\n        \n        \/\/ Start limit countdown timer\n        function startLimitCountdown() {\n            const countdownElem = document.getElementById('limitCountdownTime');\n            if (!countdownElem) return;\n            \n            \/\/ Clear previous interval if any\n            if (window.limitCountdownInterval) {\n                clearInterval(window.limitCountdownInterval);\n            }\n            \n            \/\/ Update countdown time\n            function updateCountdown() {\n                const now = new Date();\n                const tomorrow = new Date();\n                tomorrow.setHours(24, 0, 0, 0);\n                \n                const diff = tomorrow - now;\n                const hours = Math.floor(diff \/ (1000 * 60 * 60));\n                const minutes = Math.floor((diff % (1000 * 60 * 60)) \/ (1000 * 60));\n                const seconds = Math.floor((diff % (1000 * 60)) \/ 1000);\n                \n                countdownElem.textContent = \n                    String(hours).padStart(2, '0') + ':' + \n                    String(minutes).padStart(2, '0') + ':' + \n                    String(seconds).padStart(2, '0');\n            }\n            \n            \/\/ Update immediately\n            updateCountdown();\n            \n            \/\/ Update every second\n            window.limitCountdownInterval = setInterval(updateCountdown, 1000);\n        }\n\n        \/\/ Display function for showing conversion results\n        function displayResults(resultData) {\n            const resultsContainer = document.getElementById('visionResults');\n            \n            \/\/ Make sure progress container is hidden\n            const progressContainer = document.getElementById('visionProgressContainer');\n            if (progressContainer) {\n                progressContainer.style.display = 'none';\n            }\n\n            \/\/ Make results container visible\n            if (resultsContainer) {\n                resultsContainer.style.display = 'block';\n            }\n\n            \/\/ Add class to body when results are shown\n            document.body.classList.add('vision-results-active');\n            \n            \/\/ Store original data in a global variable\n            window.visionResultData = resultData;\n            \n            \/\/ Create header HTML\n            const headerHtml = `\n                <div class=\"results-header mobile-friendly\">\n                    <div class=\"header-left\">\n                        <button type=\"button\" class=\"result-button return-button\" onclick=\"return returnToUpload(event)\" title=\"Return to upload\">\n                            <span class=\"dashicons dashicons-arrow-left-alt\"><\/span>\n                            <span class=\"button-text\">Back<\/span>\n                        <\/button>\n                    <\/div>\n                    <div class=\"header-center\">\n                        <div class=\"expand-controls\">\n                            <button type=\"button\" class=\"result-button toggle-all-button\" onclick=\"return toggleAllResults(event)\" title=\"Toggle expand\/collapse all\">\n                                <span class=\"dashicons dashicons-arrow-down-alt2\"><\/span>\n                                <span class=\"button-text\">Expand All<\/span>\n                            <\/button>\n                        <\/div>\n                    <\/div>\n                    <div class=\"header-right\">\n                        <button type=\"button\" class=\"result-button download-all-button\" onclick=\"return downloadAllResults(event)\" title=\"Download results as TXT or ZIP\">\n                            <span class=\"dashicons dashicons-download\"><\/span>\n                            <span class=\"button-text\">Download All<\/span>\n                        <\/button>\n                    <\/div>\n                <\/div>\n            `;\n\n            \/\/ Generate results HTML with accordion functionality\n            const resultsHtml = resultData.map((result, index) => {\n                if (result.error) {\n                    return `\n                        <div class=\"result-item\">\n                            <div class=\"result-header\">\n                                <h3>${result.fileName}<\/h3>\n                                <span class=\"toggle-icon dashicons dashicons-arrow-down-alt2\"><\/span>\n                            <\/div>\n                            <div class=\"result-body\">\n                                <div class=\"result-error\">${result.error}<\/div>\n                            <\/div>\n                        <\/div>\n                    `;\n                }\n                \n                \/\/ Get image URL from selected files\n                const originalImage = selectedFilesMap.get(Array.from(selectedFilesMap.keys()).find(key => \n                    selectedFilesMap.get(key).name === result.fileName\n                ));\n                const imageUrl = originalImage ? URL.createObjectURL(originalImage) : '';\n                \n                \/\/ First item expanded by default, others collapsed\n                const isExpanded = index === 0 ? 'expanded' : '';\n                \n                \/\/ Create truncated filename for display - more characters for desktop\n                const isMobile = window.innerWidth <= 768;\n                const isTablet = window.innerWidth > 768 && window.innerWidth <= 1024;\n                \/\/ Adjust character limits for different device types\n                const charLimit = isMobile ? 15 : (isTablet ? 30 : 60); \/\/ Shorter on mobile, medium on tablet, longer on desktop\n                const truncatedFileName = result.fileName.length > charLimit ? \n                    result.fileName.substring(0, charLimit - 3) + '...' : \n                    result.fileName;\n                \n                return `\n                    <div class=\"result-item ${isExpanded}\" data-id=\"${result.id}\">\n                        <div class=\"result-header\" onclick=\"toggleResultItem(this.parentElement)\">\n                            <table style=\"width:auto; border:none; margin:0; padding:0; border-spacing:0; border-collapse:collapse;\">\n                                <tr>\n                                    <td style=\"vertical-align:middle; padding:0; white-space:nowrap;\">\n                                        <span class=\"toggle-icon dashicons dashicons-arrow-down-alt2\"><\/span>\n                                        <h3 title=\"${result.fileName}\" style=\"display:inline-block; max-width:calc(100% - 10px); text-overflow:ellipsis; overflow:hidden;\">${truncatedFileName}<\/h3>\n                                    <\/td>\n                                <\/tr>\n                            <\/table>\n                            <div class=\"result-header-actions\">\n                                <button type=\"button\" class=\"item-action-btn preview-icon-btn vision-custom-btn\" onclick=\"event.stopPropagation(); openPreviewModal('${imageUrl}', '${result.fileName}', '${result.text.replace(\/'\/g, \"\\\\'\").replace(\/\\n\/g, \"\\\\n\")}')\" title=\"View Image and Text\">\n                                    <i class=\"fas fa-eye\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#0ea5e9 !important;\"><\/i>\n                                    <span class=\"btn-action-text\">Preview<\/span>\n                                <\/button>\n                                <button type=\"button\" class=\"item-action-btn copy-icon-btn vision-custom-btn\" onclick=\"event.stopPropagation(); return copyText(this, event)\" title=\"Copy Text\">\n                                    <i class=\"fas fa-copy\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#4f46e5 !important;\"><\/i>\n                                    <span class=\"btn-action-text\">Copy<\/span>\n                                <\/button>\n                                <button type=\"button\" class=\"item-action-btn download-icon-btn vision-custom-btn\" onclick=\"event.stopPropagation(); return visionDownloadText(this, event)\" title=\"Download Text\">\n                                    <i class=\"fas fa-file-download\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#2563eb !important;\"><\/i>\n                                    <span class=\"btn-action-text\">Download<\/span>\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                        <div class=\"result-body\">\n                            <div class=\"result-content\">\n                                <div class=\"result-image-preview\">\n                                    <img decoding=\"async\" src=\"${imageUrl}\" alt=\"${result.fileName}\" onclick=\"openPreviewModal('${imageUrl}', '${result.fileName}', '${result.text.replace(\/'\/g, \"\\\\'\").replace(\/\\n\/g, \"\\\\n\")}')\">\n                                    <div class=\"image-click-indicator\" title=\"Click to view in detail\" onclick=\"openPreviewModal('${imageUrl}', '${result.fileName}', '${result.text.replace(\/'\/g, \"\\\\'\").replace(\/\\n\/g, \"\\\\n\")}')\">\n                                        <span class=\"dashicons dashicons-visibility\"><\/span>\n                                    <\/div>\n                                <\/div>\n                                <div class=\"result-text-container\">\n                                    <div class=\"result-text notranslate\" contenteditable=\"true\" translate=\"no\" data-notranslate>${result.text}<\/div>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                `;\n            }).join('');\n\n            \/\/ Add modal for enhanced preview\n            const modalHtml = `\n                <div class=\"vision-preview-modal\">\n                    <div class=\"modal-container\">\n                        <div class=\"modal-image-section\">\n                            <div class=\"modal-image-container\">\n                                <img decoding=\"async\" class=\"modal-image\" src=\"\" alt=\"\">\n                            <\/div>\n                            <div class=\"modal-image-controls\">\n                                <div class=\"image-control\" onclick=\"zoomImage(-0.1)\">\n                                    <span class=\"dashicons dashicons-minus\"><\/span>\n                                <\/div>\n                                <div class=\"image-control\" onclick=\"zoomImage(0.1)\">\n                                    <span class=\"dashicons dashicons-plus\"><\/span>\n                                <\/div>\n                                <div class=\"image-control\" onclick=\"rotateImage()\">\n                                    <span class=\"dashicons dashicons-redo\"><\/span>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                        <div class=\"modal-text-section\">\n                            <div class=\"modal-header\">\n                                <h3 class=\"modal-title\"><\/h3>\n                            <\/div>\n                            <div class=\"modal-text-content notranslate\" translate=\"no\" data-notranslate><\/div>\n                        <\/div>\n                        <div class=\"modal-close\" onclick=\"closePreviewModal()\">\n                            <span class=\"dashicons dashicons-no-alt\"><\/span>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            `;\n            \n            \/\/ Set container content and add event handlers\n            resultsContainer.innerHTML = headerHtml + resultsHtml + modalHtml;\n            \n            \/\/ Hide upload elements and show results\n            document.getElementById('imageGalleryView').style.display = 'none';\n            document.getElementById('initialUploadArea').style.display = 'none';\n            resultsContainer.style.display = 'block';\n        }\n\n        \/\/ Toggle accordion result item\n        window.toggleResultItem = function(item) {\n            \/\/ Close all items first\n            document.querySelectorAll('.result-item.expanded').forEach(expandedItem => {\n                if (expandedItem !== item) {\n                    expandedItem.classList.remove('expanded');\n                }\n            });\n            \n            \/\/ Toggle current item\n            item.classList.toggle('expanded');\n        }\n        \n        \/\/ Toggle all result items (expand\/collapse)\n        window.toggleAllResults = function(event) {\n            if (event) event.preventDefault();\n            \n            const button = event.currentTarget;\n            const isExpanded = button.getAttribute('data-expanded') === 'true';\n            \n            if (isExpanded) {\n                \/\/ Collapse all\n                document.querySelectorAll('.result-item').forEach(item => {\n                    item.classList.remove('expanded');\n                });\n                \n                \/\/ Update button\n                button.innerHTML = '<span class=\"dashicons dashicons-arrow-down-alt2\"><\/span><span class=\"button-text\">Expand All<\/span>';\n                button.setAttribute('data-expanded', 'false');\n            } else {\n                \/\/ Expand all\n                document.querySelectorAll('.result-item').forEach(item => {\n                    item.classList.add('expanded');\n                });\n                \n                \/\/ Update button\n                button.innerHTML = '<span class=\"dashicons dashicons-arrow-up-alt2\"><\/span><span class=\"button-text\">Collapse All<\/span>';\n                button.setAttribute('data-expanded', 'true');\n            }\n            \n            return false;\n        }\n        \n        \/\/ Copy text to clipboard\n        window.copyText = function(button, event) {\n            \/\/ Prevent any default action and stop event propagation\n            if (event) {\n                event.preventDefault();\n                event.stopPropagation();\n            }\n            \n            \/\/ Find the closest result item and get the text content\n            const resultItem = button.closest('.result-item');\n            const textContent = resultItem.querySelector('.result-text').textContent;\n            \n            \/\/ Save original icon for restoration\n            const originalIcon = button.innerHTML;\n            \n            \/\/ Use the clipboard API to copy the text\n            navigator.clipboard.writeText(textContent)\n                .then(() => {\n                    \/\/ Show success feedback - ONLY ICON, NO TEXT\n                    button.innerHTML = '<i class=\"fas fa-check\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#22c55e !important;\"><\/i>';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        button.innerHTML = originalIcon;\n                    }, 2000);\n                })\n                .catch(err => {\n                    console.error('Failed to copy text: ', err);\n                    \n                    \/\/ Show error feedback - ONLY ICON, NO TEXT\n                    button.innerHTML = '<i class=\"fas fa-exclamation-triangle\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#ef4444 !important;\"><\/i>';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        button.innerHTML = originalIcon;\n                    }, 2000);\n                });\n            \n            \/\/ Return false to prevent default action\n            return false;\n        }\n        \n        \/\/ Download text as file\n        window.visionDownloadText = function(button, event) {\n            \/\/ Prevent any default action and stop event propagation\n            if (event) {\n                event.preventDefault();\n                event.stopPropagation();\n            }\n            \n            \/\/ Find the closest result item and get necessary data\n            const resultItem = button.closest('.result-item');\n            const textContent = resultItem.querySelector('.result-text').textContent;\n            const fileName = resultItem.querySelector('.result-header h3').textContent;\n            \n            \/\/ Save original icon for restoration\n            const originalIcon = button.innerHTML;\n            \n            \/\/ Create a Blob with the text content\n            const blob = new Blob([textContent], {type: 'text\/plain;charset=utf-8'});\n            \n            \/\/ Use FileSaver.js to save the file\n            try {\n                \/\/ Show downloading feedback\n                button.innerHTML = '<i class=\"fas fa-spinner fa-spin\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#2563eb !important;\"><\/i>';\n                \n                \/\/ Download the file\n                saveAs(blob, fileName.replace(\/\\.[^\/.]+$\/, \"\") + '.txt');\n                \n                \/\/ Reset button after a delay\n                setTimeout(() => {\n                    button.innerHTML = originalIcon;\n                }, 2000);\n            } catch (err) {\n                console.error('Failed to download text: ', err);\n                \n                \/\/ Show error feedback\n                button.innerHTML = '<i class=\"fas fa-exclamation-triangle\" style=\"font-size:20px !important; width:20px !important; height:20px !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; margin:0 !important; color:#ef4444 !important;\"><\/i>';\n                \n                \/\/ Reset button after a delay\n                setTimeout(() => {\n                    button.innerHTML = originalIcon;\n                }, 2000);\n            }\n            \n            \/\/ Return false to prevent default action\n            return false;\n        }\n        \n        \/\/ Open enhanced preview modal\n        window.openPreviewModal = function(imageUrl, fileName, textContent) {\n            const modal = document.querySelector('.vision-preview-modal');\n            const modalImage = modal.querySelector('.modal-image');\n            const modalTitle = modal.querySelector('.modal-title');\n            const modalTextContent = modal.querySelector('.modal-text-content');\n            \n            \/\/ Set content\n            modalImage.src = imageUrl;\n            modalImage.setAttribute('data-scale', '1');\n            modalImage.setAttribute('data-rotate', '0');\n            modalTitle.textContent = fileName;\n            \n            \/\/ Properly handle text formatting, preserving line breaks\n            const formattedText = textContent.replace(\/\\\\n\/g, \"\\n\");\n            \n            \/\/ Clear content\n            modalTextContent.innerHTML = '';\n            \n            \/\/ Split text into paragraphs and add to container\n            const paragraphs = formattedText.split(\"\\n\");\n            paragraphs.forEach(paragraph => {\n                if (paragraph.trim()) {\n                    const p = document.createElement('p');\n                    p.textContent = paragraph;\n                    p.style.margin = '0 0 12px 0';\n                    modalTextContent.appendChild(p);\n                } else {\n                    \/\/ Add extra spacing for empty lines\n                    const spacer = document.createElement('div');\n                    spacer.style.height = '12px';\n                    modalTextContent.appendChild(spacer);\n                }\n            });\n            \n            \/\/ Show modal\n            modal.classList.add('open');\n            document.body.style.overflow = 'hidden';\n        }\n        \n        \/\/ Close preview modal\n        window.closePreviewModal = function() {\n            const modal = document.querySelector('.vision-preview-modal');\n            modal.classList.remove('open');\n            document.body.style.overflow = '';\n        }\n        \n        \/\/ Image zoom functionality\n        window.zoomImage = function(delta) {\n            const modalImage = document.querySelector('.modal-image');\n            let scale = parseFloat(modalImage.getAttribute('data-scale') || '1');\n            scale = Math.max(0.5, Math.min(3, scale + delta));\n            modalImage.setAttribute('data-scale', scale);\n            modalImage.style.transform = `scale(${scale}) rotate(${modalImage.getAttribute('data-rotate')}deg)`;\n        }\n        \n        \/\/ Image rotate functionality\n        window.rotateImage = function() {\n            const modalImage = document.querySelector('.modal-image');\n            let rotate = parseInt(modalImage.getAttribute('data-rotate') || '0');\n            rotate = (rotate + 90) % 360;\n            modalImage.setAttribute('data-rotate', rotate);\n            modalImage.style.transform = `scale(${modalImage.getAttribute('data-scale')}) rotate(${rotate}deg)`;\n        }\n        \n        \/\/ Reset image transformation\n        window.resetImage = function() {\n            const modalImage = document.querySelector('.modal-image');\n            modalImage.setAttribute('data-scale', '1');\n            modalImage.setAttribute('data-rotate', '0');\n            modalImage.style.transform = 'scale(1) rotate(0deg)';\n        }\n        \n        \/\/ Download all texts (single TXT or ZIP for multiple)\n        window.downloadAllResults = function(event) {\n            \/\/ Prevent any default action\n            if (event) event.preventDefault();\n            \n            \/\/ Get all valid result items (excluding those with errors)\n            const resultItems = Array.from(document.querySelectorAll('.result-item'))\n                .filter(item => !item.querySelector('.result-error'));\n            \n            if (resultItems.length === 0) {\n                console.warn('No valid result items found');\n                return;\n            }\n            \n            \/\/ Show download status\n            const downloadBtn = document.querySelector('.download-all-button');\n            const originalText = downloadBtn.innerHTML;\n            \n            \/\/ If there's only one item, download it directly as TXT\n            if (resultItems.length === 1) {\n                const item = resultItems[0];\n                const fileName = item.querySelector('.result-header h3').textContent;\n                const textContent = item.querySelector('.result-text').textContent;\n                \n                \/\/ Update button text\n                downloadBtn.innerHTML = '<span class=\"dashicons dashicons-download\"><\/span> Downloading...';\n                \n                \/\/ Create and download a single text file\n                const blob = new Blob([textContent], {type: 'text\/plain;charset=utf-8'});\n                saveAs(blob, fileName.replace(\/\\.[^\/.]+$\/, \"\") + '.txt');\n                \n                \/\/ Update button to show success\n                downloadBtn.innerHTML = '<span class=\"dashicons dashicons-yes\"><\/span> Downloaded!';\n                \n                \/\/ Reset button after a delay\n                setTimeout(() => {\n                    downloadBtn.innerHTML = originalText;\n                }, 2000);\n                \n                return false;\n            }\n            \n            \/\/ For multiple items, create a ZIP file (existing logic)\n            \/\/ Check if JSZip is available\n            if (typeof JSZip === 'undefined') {\n                console.error('JSZip is not loaded');\n                return;\n            }\n            \n            \/\/ Update button for ZIP creation\n            downloadBtn.innerHTML = '<span class=\"dashicons dashicons-update rotating\"><\/span> Creating zip...';\n            \n            \/\/ Create a new zip file\n            const zip = new JSZip();\n            \n            \/\/ Add each text file to the zip\n            resultItems.forEach((item) => {\n                const fileName = item.querySelector('.result-header h3').textContent;\n                const textContent = item.querySelector('.result-text').textContent;\n                \n                \/\/ Add file to zip\n                zip.file(fileName.replace(\/\\.[^\/.]+$\/, \"\") + '.txt', textContent);\n            });\n            \n            \/\/ Generate the zip file\n            zip.generateAsync({type: 'blob'})\n                .then(blob => {\n                    \/\/ Use FileSaver.js to save the zip file\n                    saveAs(blob, 'converted_texts_' + new Date().toISOString().slice(0, 10) + '.zip');\n                    \n                    \/\/ Update button to show success\n                    downloadBtn.innerHTML = '<span class=\"dashicons dashicons-yes\"><\/span> Downloaded!';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        downloadBtn.innerHTML = originalText;\n                    }, 2000);\n                })\n                .catch(err => {\n                    console.error('Failed to create zip file: ', err);\n                    \n                    \/\/ Show error on button\n                    downloadBtn.innerHTML = '<span class=\"dashicons dashicons-warning\"><\/span> Error!';\n                    \n                    \/\/ Reset button after a delay\n                    setTimeout(() => {\n                        downloadBtn.innerHTML = originalText;\n                    }, 2000);\n                });\n        }\n\n        \/\/ Check daily limit on page load\n        if (wpVision && wpVision.dailyUploadsCount !== undefined && wpVision.dailyLimit !== undefined) {\n            if (!wpVision.isSubscriber && wpVision.dailyUploadsCount >= wpVision.dailyLimit) {\n                const limitWarning = document.getElementById('visionDailyLimitWarning');\n                if (limitWarning) {\n                    limitWarning.style.display = 'block';\n                    limitWarning.classList.add('show');\n                    \n                    \/\/ Disable convert button\n                    if (convertButton) {\n                        convertButton.disabled = true;\n                        convertButton.classList.add('disabled-by-limit');\n                    }\n                    \n                    \/\/ Start the countdown\n                    startLimitCountdown();\n                }\n            }\n        }\n    }\n});\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b136d0e e-flex e-con-boxed e-con e-parent\" data-id=\"b136d0e\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-780b82e elementor-widget elementor-widget-html\" data-id=\"780b82e\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\r\n    * {\r\n      margin: 0;\r\n      padding: 0;\r\n      box-sizing: border-box;\r\n      font-family: 'Segoe UI', 'SF Pro Display', Arial, sans-serif;\r\n    }\r\n    \r\n    body {\r\n      background-color: #fafafa;\r\n    }\r\n    \r\n    .premium-features {\r\n      display: flex;\r\n      justify-content: center;\r\n      flex-wrap: wrap;\r\n      gap: 16px;\r\n      padding: 20px 10px;\r\n      max-width: 900px;\r\n      margin: 0 auto;\r\n    }\r\n    \r\n    .premium-badge {\r\n      display: flex;\r\n      align-items: center;\r\n      gap: 12px;\r\n      background-color: white;\r\n      padding: 10px 16px;\r\n      border-radius: 50px;\r\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\r\n      transition: all 0.3s ease;\r\n      border: 1px solid rgba(0, 0, 0, 0.05);\r\n    }\r\n    \r\n    .premium-badge:hover {\r\n      transform: translateY(-3px);\r\n      box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);\r\n    }\r\n    \r\n    .badge-icon {\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      width: 28px;\r\n      height: 28px;\r\n      border-radius: 50%;\r\n      color: white;\r\n      font-size: 14px;\r\n    }\r\n    .premium-badge:nth-child(1) .badge-icon {\r\n      background: linear-gradient(135deg, #ff6f00 0%, #ff8f00 100%);\r\n    }\r\n\r\n    .premium-badge:nth-child(2) .badge-icon {\r\n      background: linear-gradient(135deg, #ab47bc 0%, #8e24aa 100%);\r\n    }\r\n\r\n    .premium-badge:nth-child(3) .badge-icon {\r\n      background: linear-gradient(135deg, #00c853 0%, #009624 100%);\r\n    }\r\n    \r\n    .badge-icon svg {\r\n      width: 16px;\r\n      height: 16px;\r\n      fill: none;\r\n      stroke: currentColor;\r\n      stroke-width: 2;\r\n      stroke-linecap: round;\r\n      stroke-linejoin: round;\r\n    }\r\n    \r\n    .badge-text {\r\n      font-size: 14px;\r\n      font-weight: 600;\r\n      color: #333;\r\n    }\r\n    \r\n    \/* Media queries for responsiveness *\/\r\n    @media (max-width: 768px) {\r\n      .premium-features {\r\n        padding: 15px 10px;\r\n      }\r\n    }\r\n    \r\n    @media (max-width: 480px) {\r\n      .premium-features {\r\n        flex-direction: column;\r\n        align-items: center;\r\n      }\r\n      \r\n      .premium-badge {\r\n        width: 100%;\r\n        max-width: 260px;\r\n        justify-content: flex-start;\r\n      }\r\n    }\r\n  <\/style>\r\n<\/head>\r\n<body>\r\n  <div class=\"premium-features\">\r\n    <div class=\"premium-badge\">\r\n      <div class=\"badge-icon\">\r\n        <svg viewBox=\"0 0 24 24\">\r\n          <circle cx=\"12\" cy=\"12\" r=\"10\"><\/circle>\r\n          <line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\"><\/line>\r\n          <path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"><\/path>\r\n        <\/svg>\r\n      <\/div>\r\n      <div class=\"badge-text\">Supports 100+ Languages<\/div>\r\n    <\/div>\r\n    \r\n    <div class=\"premium-badge\">\r\n      <div class=\"badge-icon\">\r\n        <svg viewBox=\"0 0 24 24\">\r\n          <path d=\"M20 6L9 17l-5-5\"><\/path>\r\n        <\/svg>\r\n      <\/div>\r\n      <div class=\"badge-text\">99.8% Accuracy<\/div>\r\n    <\/div>\r\n    \r\n    <div class=\"premium-badge\">\r\n      <div class=\"badge-icon\">\r\n        <svg viewBox=\"0 0 24 24\">\r\n          <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"><\/rect>\r\n          <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"><\/path>\r\n        <\/svg>\r\n      <\/div>\r\n      <div class=\"badge-text\">Secure & Private<\/div>\r\n    <\/div>\r\n  <\/div>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-aaed4f1 e-flex e-con-boxed e-con e-parent\" data-id=\"aaed4f1\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-abbbac5 elementor-widget elementor-widget-shortcode\" data-id=\"abbbac5\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><script async src=\"https:\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js?client=ca-pub-8069529413860845\"\n     crossorigin=\"anonymous\"><\/script>\n<!-- 1000-100 -->\n<ins class=\"adsbygoogle\"\n     style=\"display:inline-block;width:1000px;height:100px\"\n     data-ad-client=\"ca-pub-8069529413860845\"\n     data-ad-slot=\"9855343712\"><\/ins>\n<script>\n     (adsbygoogle = window.adsbygoogle || []).push({});\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-5049b33a e-flex e-con-boxed e-con e-parent\" data-id=\"5049b33a\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7dc6e7c elementor-widget elementor-widget-text-editor\" data-id=\"7dc6e7c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The <strong data-start=\"632\" data-end=\"657\">PNG to Text Converter<\/strong> is a free, web-based tool that extracts text embedded within PNG images. You can use it for a variety of tasks, from converting screenshots of documents to extracting text from pictures containing quotes, business cards, or even handwritten notes. It\u2019s a highly practical tool for anyone needing to transform image-based content into usable, editable text.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-317d7f3 elementor-widget elementor-widget-heading\" data-id=\"317d7f3\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Features<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-45ecf806 elementor-widget elementor-widget-ucaddon_uc_material_bullets\" data-id=\"45ecf806\" data-element_type=\"widget\" data-widget_type=\"ucaddon_uc_material_bullets.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!-- start Icon Bullets -->\n\t\t<link id='font-awesome-css' href='https:\/\/ocr365.com\/wp-content\/plugins\/unlimited-elements-for-elementor-premium\/assets_libraries\/font-awesome6\/fontawesome-all.min.css' type='text\/css' rel='stylesheet' >\n\t\t<link id='font-awesome-4-shim-css' href='https:\/\/ocr365.com\/wp-content\/plugins\/unlimited-elements-for-elementor-premium\/assets_libraries\/font-awesome6\/fontawesome-v4-shims.min.css' type='text\/css' rel='stylesheet' >\n\n<style>\/* widget: Icon Bullets *\/\n\n\n\n#uc_uc_material_bullets_elementor_45ecf806 *{\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-icon-wrapper{\n\tdisplay: flex;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-icon{\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  flex-grow:0;\n  flex-shrink:0;\n  line-height:1em;\n  transition:0.3s;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-icon svg{\n  height:1em;\n  width:1em;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .uc_material_bullets_row{\n\tfont-weight:400;\n\toverflow:hidden;\n\tdisplay:flex;\n\tposition:relative;\n\ttext-align:left;\n\twidth:100%;   \n    transition:0.3s;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .uc_material_bullets_row a.ue-item-link{\n  position:absolute;\n  display:block;\n  top:0;\n  right:0;\n  left:0;\n  bottom:0;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .uc_material_bullets_row:last-child{\n\tmargin-bottom:0px !important;\n}\n\n\n#uc_uc_material_bullets_elementor_45ecf806 .uc_material_bullets_row {\n\tposition:relative;\n\tvertical-align:middle;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .uc_material_bullets_row .uc_content_box{\n\tdisplay:flex;\n    flex-direction:column;\n    justify-content:center;\n    align-items: flex-start;\n    flex-grow:1;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-bullets{\n  display:grid;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-text, \n#uc_uc_material_bullets_elementor_45ecf806 .ue-title, \n#uc_uc_material_bullets_elementor_45ecf806 .ue-seperator{\n  width:100%;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-seperator-line{\n  display:inline-block;\n  font-size:0px;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .ue-seperator{\n  font-size:0px;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806.uc-remote-parent .uc_material_bullets_row{\n  cursor:pointer;\n}\n\n.ue-title{\n  font-size:21px;\n  margin:0;\n}\n\n#uc_uc_material_bullets_elementor_45ecf806 .uc_content_box > *{\n  transition: all .3s;\n}\n\n<\/style>\n\n<div class=\"uc_material_bullets  \"  id=\"uc_uc_material_bullets_elementor_45ecf806\"  >   \t\n    \t<div class=\"ue-bullets uc-items-wrapper\">\n          \t<div class=\"uc_material_bullets_row elementor-repeater-item-4061aae\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">1<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">No Registration<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Convert PNG to text instantly without signing up or logging in. Simple and hassle-free!<\/div>\t\n  <\/div>\n    \t\n<\/div>\n<div class=\"uc_material_bullets_row elementor-repeater-item-c647ca0\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">2<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">Easy Conversion<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Upload your PNG and extract text in seconds\u2014no complicated steps required!<\/div>\t\n  <\/div>\n    \t\n<\/div>\n<div class=\"uc_material_bullets_row elementor-repeater-item-6336972\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">3<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">99.8% Accuracy<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Our advanced OCR ensures highly precise text extraction with 99.8% accuracy.<\/div>\t\n  <\/div>\n    \t\n<\/div>\n<div class=\"uc_material_bullets_row elementor-repeater-item-ed5c934\">\n  <div class=\"ue-icon-wrapper\">\n              <div class=\"ue-icon\">\n                                       <span class=\"ue-icon-text\">4<\/span> \t\n\n                \n              <\/div>\n  <\/div>\n  <div class=\"uc_content_box uc_ceal\">\n    <div class=\"ue-title\">100+ Languages<\/div>\n    \n    \t\n    \n    <div class=\"ue-text\">Extract text from PNGs in over 100 languages, handling global content effortlessly.<\/div>\t\n  <\/div>\n    \t\n<\/div>\n\n      <\/div>\n<\/div>\n<!-- end Icon Bullets -->\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-76219fd5 elementor-widget elementor-widget-heading\" data-id=\"76219fd5\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">How to Convert PNG to Text?<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2a6956bb elementor-widget elementor-widget-ucaddon_step_process\" data-id=\"2a6956bb\" data-element_type=\"widget\" data-widget_type=\"ucaddon_step_process.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!-- start Step Process -->\n\n<style>\/* widget: Step Process *\/\n\n#uc_step_process_elementor_2a6956bb\n{\n  display:flex;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-link\n{\n  display:block;\n  position:absolute;\n  top:0px;\n  bottom:0px;\n  left:0px;\n  right:0px;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item\n{\n  flex:1;\n  display:flex;\n  flex-direction:column;\n  position:relative;\n}\n#uc_step_process_elementor_2a6956bb .ue-item-highlight\n{\n  display: flex;\n  align-items:center;\n  \n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item-gap\n{\n  flex-grow:0;\n  flex-shrink:0;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item-line\n{\n  height:1px;\n  flex-grow:1;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-icon\n{\n  display:flex;\n  justify-content:center;\n  align-items:center;\n  flex-grow:0;\n  flex-shrink:0;\n  position:relative;\n  line-height:1em;\n  transition:0.3s;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-icon svg\n{\n  height:1em;\n  width:1em;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-label\n{\n  position:absolute;\n  left:0px;\n  top:0px;\n  display:flex;\n  justify-content:center;\n  align-items:center;\n}\n.ue-step-label\n{\n  font-size:9px;\n  line-height:1em;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item-content\n{\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item:last-child .ue-step-item-line:last-child\n{\n  opacity:0;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item:first-child .ue-step-item-line:first-child\n{\n  opacity:0;\n}\n\n#uc_step_process_elementor_2a6956bb .ue-step-item-spacer\n{\n  flex-grow:0;\n  flex-shrink:0;\n  \n}\n\n#uc_step_process_elementor_2a6956bb .ue-graphic-image img\n{\n  \n}\n\n\n#uc_step_process_elementor_2a6956bb.uc-remote-parent .ue-step-item\n{\n  cursor:pointer;\n}\n\n\n\n\n\n\n@media only screen and (max-width: 768px) {\n  #uc_step_process_elementor_2a6956bb\n    {\n      flex-direction:column;\n    }\n  \n  #uc_step_process_elementor_2a6956bb .ue-step-item\n  {\n    flex-direction:row;\n  }\n  \n  #uc_step_process_elementor_2a6956bb .ue-item-highlight\n  {\n    flex-direction:column;\n  }\n  \n   #uc_step_process_elementor_2a6956bb .ue-step-item .ue-step-item-line:first-child\n    {\n      display:none;\n    }\n  \n\n    #uc_step_process_elementor_2a6956bb  .ue-step-item-gap:nth-child(2)\n     {\n      display:none;    \n      }\n   #uc_step_process_elementor_2a6956bb  .ue-step-item-line:first-child\n      {\n      display:none;    \n      }\n  \n    #uc_step_process_elementor_2a6956bb  .ue-step-item-line\n      {\n        height:100%;\n        width:1px;\n      }\n}\n\n\n\n<\/style>\n\n<div id=\"uc_step_process_elementor_2a6956bb\" class=\"uc-items-wrapper  \"  >\n <div class=\"ue-step-item ue-item elementor-repeater-item-b77fdec\">\n    <div class=\"ue-item-highlight\">\n      \n      <div class=\"ue-step-item-line\"><\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-icon \">\n        <span class=\"ue-icon\"><i class='fas fa-photo-video'><\/i><\/span>                        \n              <\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-item-line\"><\/div>\n      \n    <\/div>\n    \n    <div class=\"ue-step-item-spacer\"><\/div>\n    \n    <div class=\"ue-step-item-content\">  \n       <div class=\"ue-step-item-content-title\">Upload Your PNG<\/div>       <div class=\"ue-step-item-content-text\">Select and upload your PNG file to the tool.<\/div>    <\/div>\n  \n    <\/div>\n<div class=\"ue-step-item ue-item elementor-repeater-item-fea387d\">\n    <div class=\"ue-item-highlight\">\n      \n      <div class=\"ue-step-item-line\"><\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-icon \">\n        <span class=\"ue-icon\"><i class='fas fa-cloud-upload-alt'><\/i><\/span>                        \n              <\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-item-line\"><\/div>\n      \n    <\/div>\n    \n    <div class=\"ue-step-item-spacer\"><\/div>\n    \n    <div class=\"ue-step-item-content\">  \n       <div class=\"ue-step-item-content-title\">Extract Text Automatically<\/div>       <div class=\"ue-step-item-content-text\">Our OCR system will process and recognize the text in seconds.<\/div>    <\/div>\n  \n    <\/div>\n<div class=\"ue-step-item ue-item elementor-repeater-item-4860be0\">\n    <div class=\"ue-item-highlight\">\n      \n      <div class=\"ue-step-item-line\"><\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-icon \">\n        <span class=\"ue-icon\"><i class='fas fa-sync'><\/i><\/span>                        \n              <\/div>\n      <div class=\"ue-step-item-gap\"><\/div>\n      <div class=\"ue-step-item-line\"><\/div>\n      \n    <\/div>\n    \n    <div class=\"ue-step-item-spacer\"><\/div>\n    \n    <div class=\"ue-step-item-content\">  \n       <div class=\"ue-step-item-content-title\">Copy or Download<\/div>       <div class=\"ue-step-item-content-text\">Retrieve the extracted text and save it as needed.<\/div>    <\/div>\n  \n    <\/div>\n\n<\/div>\n<!-- end Step Process -->\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-23140b9 e-con-full e-flex e-con e-child\" data-id=\"23140b9\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7f8bd44 elementor-widget elementor-widget-text-editor\" data-id=\"7f8bd44\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3 style=\"text-align: center;\" data-sourcepos=\"86:1-86:41\"><strong>Why Choose Our PNG to Text Converter?<\/strong><\/h3><p data-sourcepos=\"88:1-88:109\">In a market saturated with online tools, our PNG to Text converter stands out for several compelling reasons:<\/p><ul data-sourcepos=\"90:1-96:0\"><li data-sourcepos=\"90:1-90:148\"><strong>Unwavering Commitment to Accuracy:<\/strong> We have invested in cutting-edge OCR technology to ensure the highest possible accuracy in text extraction.<\/li><li data-sourcepos=\"91:1-91:146\"><strong>User-Centric Design:<\/strong> Our tool boasts a clean, intuitive, and user-friendly interface, making the conversion process effortless for everyone.<\/li><li data-sourcepos=\"92:1-92:169\"><strong>Speed and Efficiency:<\/strong> We understand the importance of time. Our tool is optimized for speed, allowing you to convert your PNG files to text in a matter of seconds.<\/li><li data-sourcepos=\"93:1-93:100\"><strong>Robust Language Support:<\/strong> We support a wide range of languages, catering to a global user base.<\/li><li data-sourcepos=\"94:1-94:160\"><strong>Secure and Private:<\/strong> We prioritize your data security and privacy. Your uploaded files are processed securely, and we do not store your data unnecessarily.<\/li><li data-sourcepos=\"95:1-96:0\"><strong>Continuous Improvement:<\/strong> We are constantly working to enhance our tool, incorporating the latest advancements in OCR technology and user feedback to provide the best possible experience.<\/li><\/ul><h3 style=\"text-align: center;\" data-sourcepos=\"58:1-58:65\"><strong>The Significance of Image Quality in Accurate Text Extraction<\/strong><\/h3><p data-sourcepos=\"60:1-60:259\">While our PNG to Text converter is designed to handle various image qualities, it&#8217;s important to understand that the quality of the input PNG image significantly impacts the accuracy of the text extraction. To achieve the best results, consider the following:<\/p><ul data-sourcepos=\"62:1-67:0\"><li data-sourcepos=\"62:1-62:142\"><strong>Resolution:<\/strong> Higher resolution images generally lead to better accuracy as there are more pixels available for the OCR engine to analyze.<\/li><li data-sourcepos=\"63:1-63:76\"><strong>Clarity:<\/strong> Ensure the text in the image is clear, sharp, and not blurry.<\/li><li data-sourcepos=\"64:1-64:121\"><strong>Contrast:<\/strong> Good contrast between the text and the background makes it easier for the OCR to identify the characters.<\/li><li data-sourcepos=\"65:1-65:243\"><strong>Orientation:<\/strong> Make sure the image is correctly oriented. If the text is rotated or skewed, it can hinder the recognition process. Our tool may offer automatic rotation correction, but it&#8217;s always best to provide a properly oriented image.<\/li><li data-sourcepos=\"66:1-67:0\"><strong>Minimal Noise:<\/strong> Avoid images with excessive noise or artifacts, as these can interfere with character recognition.<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-24db313 elementor-widget elementor-widget-heading\" data-id=\"24db313\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Frequently Asked Questions<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9120cca elementor-widget elementor-widget-text-editor\" data-id=\"9120cca\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div><strong>What kind of images work best?\u00a0<\/strong><\/div><div>The tool performs best with high-quality images where the text is clearly visible. High contrast and well-lit images lead to the best OCR results.<\/div><div>\u00a0<\/div><div><strong>How do I ensure my text is accurate?\u00a0<\/strong><\/div><div>Ensure the PNG image is of good quality, with clear, readable text. Avoid blurry or low-resolution images for the best OCR performance.<\/div><div>\u00a0<\/div><div><p data-sourcepos=\"99:1-100:154\"><strong>Q: Is your PNG to Text converter free to use?<\/strong><\/p><p data-sourcepos=\"99:1-100:154\">A: Yes, our basic PNG to Text converter is free for you to use. We may offer premium features or subscription options for users with more demanding needs.<\/p><p data-sourcepos=\"102:1-103:148\"><strong>Q: What types of PNG images can I convert to text?<\/strong><\/p><p data-sourcepos=\"102:1-103:148\">A: You can convert various types of PNG images containing text, such as scanned documents, screenshots, infographics, and images with embedded text.<\/p><p data-sourcepos=\"105:1-106:158\"><strong>Q: Is there a limit to the file size or number of PNG files I can convert?<\/strong><\/p><p data-sourcepos=\"105:1-106:158\">A: Our free version may have certain limitations on file size and the number of conversions. Please refer to our pricing or usage guidelines for more details.<\/p><p data-sourcepos=\"108:1-109:122\"><strong>Q: Do I need to install any software to use your PNG to Text converter?<\/strong><\/p><p data-sourcepos=\"108:1-109:122\">A: No, our tool is entirely web-based. You can access it directly from your web browser without any software installation.<\/p><p data-sourcepos=\"111:1-112:194\"><strong>Q: What happens to my uploaded PNG files after conversion?<\/strong><\/p><p data-sourcepos=\"111:1-112:194\">A: We take your privacy seriously. Your uploaded files are typically processed and then deleted from our servers shortly after the conversion is complete. We do not store your files permanently.<\/p><p data-sourcepos=\"114:1-115:154\"><strong>Q: Can your tool convert handwritten text from PNG images?<\/strong><\/p><p data-sourcepos=\"114:1-115:154\">A: While our tool is highly accurate for typed or printed text, the accuracy for handwritten text may vary depending on the legibility of the handwriting.<\/p><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bde515c elementor-widget elementor-widget-shortcode\" data-id=\"bde515c\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">\n\n<div class=\"kk-star-ratings kksr-shortcode\"\n    data-payload='{&quot;id&quot;:&quot;766&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;shortcode&quot;,&quot;align&quot;:&quot;&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;6&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;valign&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;5&quot;,&quot;greet&quot;:&quot;Rate this page&quot;,&quot;legend&quot;:&quot;5\\\/5 - (6 votes)&quot;,&quot;size&quot;:&quot;15&quot;,&quot;title&quot;:&quot;PNG to Text Converter: PNG to OCR&quot;,&quot;width&quot;:&quot;97.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 97.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 5px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 15px; height: 15px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 12px;\">\n            5\/5 - (6 votes)    <\/div>\n    <\/div>\n<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Png to Text Supports 100+ Languages 99.8% Accuracy Secure &#038; Private The PNG to Text Converter is a free, web-based tool that extracts text embedded within PNG images. You can use it for a variety of tasks, from converting screenshots of documents to extracting text from pictures containing quotes, business cards, or even handwritten notes. [&#8230;]\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-766","page","type-page","status-publish","hentry"],"rankMath":{"parentDomain":"ocr365.com","noFollowDomains":[],"noFollowExcludeDomains":[],"noFollowExternalLinks":false,"featuredImageNotice":"The featured image should be at least 200 by 200 pixels to be picked up by Facebook and other social media sites.","pluginReviewed":false,"postSettings":{"linkSuggestions":true,"useFocusKeyword":false},"frontEndScore":false,"postName":"png-to-text","permalinkFormat":"https:\/\/ocr365.com\/pt\/%pagename%\/","showLockModifiedDate":true,"assessor":{"focusKeywordLink":"https:\/\/ocr365.com\/wp-admin\/edit.php?focus_keyword=%focus_keyword%&post_type=%post_type%","hasTOCPlugin":true,"primaryTaxonomy":false,"serpData":{"title":"Conversor de PNG para texto: PNG para OCR","description":"O PNG to Text Converter usa tecnologia OCR para extrair rapidamente texto de imagens PNG, facilitando a transforma\u00e7\u00e3o de suas imagens em texto edit\u00e1vel.","focusKeywords":"","pillarContent":false,"canonicalUrl":"","breadcrumbTitle":"","advancedRobots":{"max-snippet":"-1","max-video-preview":"-1","max-image-preview":"large"},"facebookTitle":"","facebookDescription":"","facebookImage":"","facebookImageID":"","facebookHasOverlay":false,"facebookImageOverlay":"","facebookAuthor":"","twitterCardType":"","twitterUseFacebook":true,"twitterTitle":"","twitterDescription":"","twitterImage":"","twitterImageID":"","twitterHasOverlay":false,"twitterImageOverlay":"","twitterPlayerUrl":"","twitterPlayerSize":"","twitterPlayerStream":"","twitterPlayerStreamCtype":"","twitterAppDescription":"","twitterAppIphoneName":"","twitterAppIphoneID":"","twitterAppIphoneUrl":"","twitterAppIpadName":"","twitterAppIpadID":"","twitterAppIpadUrl":"","twitterAppGoogleplayName":"","twitterAppGoogleplayID":"","twitterAppGoogleplayUrl":"","twitterAppCountry":"","robots":{"index":true},"twitterAuthor":"username","primaryTerm":0,"authorName":"admin","titleTemplate":"%title% %sep% %sitename%","descriptionTemplate":"%excerpt%","showScoreFrontend":true,"lockModifiedDate":false},"powerWords":[],"diacritics":{"A":"[\\u0041\\u24B6\\uFF21\\u00C0\\u00C1\\u00C2\\u1EA6\\u1EA4\\u1EAA\\u1EA8\\u00C3\\u0100\\u0102\\u1EB0\\u1EAE\\u1EB4\\u1EB2\\u0226\\u01E0\\u00C4\\u01DE\\u1EA2\\u00C5\\u01FA\\u01CD\\u0200\\u0202\\u1EA0\\u1EAC\\u1EB6\\u1E00\\u0104\\u023A\\u2C6F]","AA":"[\\uA732]","AE":"[\\u00C6\\u01FC\\u01E2]","AO":"[\\uA734]","AU":"[\\uA736]","AV":"[\\uA738\\uA73A]","AY":"[\\uA73C]","B":"[\\u0042\\u24B7\\uFF22\\u1E02\\u1E04\\u1E06\\u0243\\u0182\\u0181]","C":"[\\u0043\\u24B8\\uFF23\\u0106\\u0108\\u010A\\u010C\\u00C7\\u1E08\\u0187\\u023B\\uA73E]","D":"[\\u0044\\u24B9\\uFF24\\u1E0A\\u010E\\u1E0C\\u1E10\\u1E12\\u1E0E\\u0110\\u018B\\u018A\\u0189\\uA779]","DZ":"[\\u01F1\\u01C4]","Dz":"[\\u01F2\\u01C5]","E":"[\\u0045\\u24BA\\uFF25\\u00C8\\u00C9\\u00CA\\u1EC0\\u1EBE\\u1EC4\\u1EC2\\u1EBC\\u0112\\u1E14\\u1E16\\u0114\\u0116\\u00CB\\u1EBA\\u011A\\u0204\\u0206\\u1EB8\\u1EC6\\u0228\\u1E1C\\u0118\\u1E18\\u1E1A\\u0190\\u018E]","F":"[\\u0046\\u24BB\\uFF26\\u1E1E\\u0191\\uA77B]","G":"[\\u0047\\u24BC\\uFF27\\u01F4\\u011C\\u1E20\\u011E\\u0120\\u01E6\\u0122\\u01E4\\u0193\\uA7A0\\uA77D\\uA77E]","H":"[\\u0048\\u24BD\\uFF28\\u0124\\u1E22\\u1E26\\u021E\\u1E24\\u1E28\\u1E2A\\u0126\\u2C67\\u2C75\\uA78D]","I":"[\\u0049\\u24BE\\uFF29\\u00CC\\u00CD\\u00CE\\u0128\\u012A\\u012C\\u0130\\u00CF\\u1E2E\\u1EC8\\u01CF\\u0208\\u020A\\u1ECA\\u012E\\u1E2C\\u0197]","J":"[\\u004A\\u24BF\\uFF2A\\u0134\\u0248]","K":"[\\u004B\\u24C0\\uFF2B\\u1E30\\u01E8\\u1E32\\u0136\\u1E34\\u0198\\u2C69\\uA740\\uA742\\uA744\\uA7A2]","L":"[\\u004C\\u24C1\\uFF2C\\u013F\\u0139\\u013D\\u1E36\\u1E38\\u013B\\u1E3C\\u1E3A\\u0141\\u023D\\u2C62\\u2C60\\uA748\\uA746\\uA780]","LJ":"[\\u01C7]","Lj":"[\\u01C8]","M":"[\\u004D\\u24C2\\uFF2D\\u1E3E\\u1E40\\u1E42\\u2C6E\\u019C]","N":"[\\u004E\\u24C3\\uFF2E\\u01F8\\u0143\\u00D1\\u1E44\\u0147\\u1E46\\u0145\\u1E4A\\u1E48\\u0220\\u019D\\uA790\\uA7A4]","NJ":"[\\u01CA]","Nj":"[\\u01CB]","O":"[\\u004F\\u24C4\\uFF2F\\u00D2\\u00D3\\u00D4\\u1ED2\\u1ED0\\u1ED6\\u1ED4\\u00D5\\u1E4C\\u022C\\u1E4E\\u014C\\u1E50\\u1E52\\u014E\\u022E\\u0230\\u00D6\\u022A\\u1ECE\\u0150\\u01D1\\u020C\\u020E\\u01A0\\u1EDC\\u1EDA\\u1EE0\\u1EDE\\u1EE2\\u1ECC\\u1ED8\\u01EA\\u01EC\\u00D8\\u01FE\\u0186\\u019F\\uA74A\\uA74C]","OI":"[\\u01A2]","OO":"[\\uA74E]","OU":"[\\u0222]","P":"[\\u0050\\u24C5\\uFF30\\u1E54\\u1E56\\u01A4\\u2C63\\uA750\\uA752\\uA754]","Q":"[\\u0051\\u24C6\\uFF31\\uA756\\uA758\\u024A]","R":"[\\u0052\\u24C7\\uFF32\\u0154\\u1E58\\u0158\\u0210\\u0212\\u1E5A\\u1E5C\\u0156\\u1E5E\\u024C\\u2C64\\uA75A\\uA7A6\\uA782]","S":"[\\u0053\\u24C8\\uFF33\\u1E9E\\u015A\\u1E64\\u015C\\u1E60\\u0160\\u1E66\\u1E62\\u1E68\\u0218\\u015E\\u2C7E\\uA7A8\\uA784]","T":"[\\u0054\\u24C9\\uFF34\\u1E6A\\u0164\\u1E6C\\u021A\\u0162\\u1E70\\u1E6E\\u0166\\u01AC\\u01AE\\u023E\\uA786]","TZ":"[\\uA728]","U":"[\\u0055\\u24CA\\uFF35\\u00D9\\u00DA\\u00DB\\u0168\\u1E78\\u016A\\u1E7A\\u016C\\u00DC\\u01DB\\u01D7\\u01D5\\u01D9\\u1EE6\\u016E\\u0170\\u01D3\\u0214\\u0216\\u01AF\\u1EEA\\u1EE8\\u1EEE\\u1EEC\\u1EF0\\u1EE4\\u1E72\\u0172\\u1E76\\u1E74\\u0244]","V":"[\\u0056\\u24CB\\uFF36\\u1E7C\\u1E7E\\u01B2\\uA75E\\u0245]","VY":"[\\uA760]","W":"[\\u0057\\u24CC\\uFF37\\u1E80\\u1E82\\u0174\\u1E86\\u1E84\\u1E88\\u2C72]","X":"[\\u0058\\u24CD\\uFF38\\u1E8A\\u1E8C]","Y":"[\\u0059\\u24CE\\uFF39\\u1EF2\\u00DD\\u0176\\u1EF8\\u0232\\u1E8E\\u0178\\u1EF6\\u1EF4\\u01B3\\u024E\\u1EFE]","Z":"[\\u005A\\u24CF\\uFF3A\\u0179\\u1E90\\u017B\\u017D\\u1E92\\u1E94\\u01B5\\u0224\\u2C7F\\u2C6B\\uA762]","a":"[\\u0061\\u24D0\\uFF41\\u1E9A\\u00E0\\u00E1\\u00E2\\u1EA7\\u1EA5\\u1EAB\\u1EA9\\u00E3\\u0101\\u0103\\u1EB1\\u1EAF\\u1EB5\\u1EB3\\u0227\\u01E1\\u00E4\\u01DF\\u1EA3\\u00E5\\u01FB\\u01CE\\u0201\\u0203\\u1EA1\\u1EAD\\u1EB7\\u1E01\\u0105\\u2C65\\u0250]","aa":"[\\uA733]","ae":"[\\u00E6\\u01FD\\u01E3]","ao":"[\\uA735]","au":"[\\uA737]","av":"[\\uA739\\uA73B]","ay":"[\\uA73D]","b":"[\\u0062\\u24D1\\uFF42\\u1E03\\u1E05\\u1E07\\u0180\\u0183\\u0253]","c":"[\\u0063\\u24D2\\uFF43\\u0107\\u0109\\u010B\\u010D\\u00E7\\u1E09\\u0188\\u023C\\uA73F\\u2184]","d":"[\\u0064\\u24D3\\uFF44\\u1E0B\\u010F\\u1E0D\\u1E11\\u1E13\\u1E0F\\u0111\\u018C\\u0256\\u0257\\uA77A]","dz":"[\\u01F3\\u01C6]","e":"[\\u0065\\u24D4\\uFF45\\u00E8\\u00E9\\u00EA\\u1EC1\\u1EBF\\u1EC5\\u1EC3\\u1EBD\\u0113\\u1E15\\u1E17\\u0115\\u0117\\u00EB\\u1EBB\\u011B\\u0205\\u0207\\u1EB9\\u1EC7\\u0229\\u1E1D\\u0119\\u1E19\\u1E1B\\u0247\\u025B\\u01DD]","f":"[\\u0066\\u24D5\\uFF46\\u1E1F\\u0192\\uA77C]","g":"[\\u0067\\u24D6\\uFF47\\u01F5\\u011D\\u1E21\\u011F\\u0121\\u01E7\\u0123\\u01E5\\u0260\\uA7A1\\u1D79\\uA77F]","h":"[\\u0068\\u24D7\\uFF48\\u0125\\u1E23\\u1E27\\u021F\\u1E25\\u1E29\\u1E2B\\u1E96\\u0127\\u2C68\\u2C76\\u0265]","hv":"[\\u0195]","i":"[\\u0069\\u24D8\\uFF49\\u00EC\\u00ED\\u00EE\\u0129\\u012B\\u012D\\u00EF\\u1E2F\\u1EC9\\u01D0\\u0209\\u020B\\u1ECB\\u012F\\u1E2D\\u0268\\u0131]","j":"[\\u006A\\u24D9\\uFF4A\\u0135\\u01F0\\u0249]","k":"[\\u006B\\u24DA\\uFF4B\\u1E31\\u01E9\\u1E33\\u0137\\u1E35\\u0199\\u2C6A\\uA741\\uA743\\uA745\\uA7A3]","l":"[\\u006C\\u24DB\\uFF4C\\u0140\\u013A\\u013E\\u1E37\\u1E39\\u013C\\u1E3D\\u1E3B\\u017F\\u0142\\u019A\\u026B\\u2C61\\uA749\\uA781\\uA747]","lj":"[\\u01C9]","m":"[\\u006D\\u24DC\\uFF4D\\u1E3F\\u1E41\\u1E43\\u0271\\u026F]","n":"[\\u006E\\u24DD\\uFF4E\\u01F9\\u0144\\u00F1\\u1E45\\u0148\\u1E47\\u0146\\u1E4B\\u1E49\\u019E\\u0272\\u0149\\uA791\\uA7A5]","nj":"[\\u01CC]","o":"[\\u006F\\u24DE\\uFF4F\\u00F2\\u00F3\\u00F4\\u1ED3\\u1ED1\\u1ED7\\u1ED5\\u00F5\\u1E4D\\u022D\\u1E4F\\u014D\\u1E51\\u1E53\\u014F\\u022F\\u0231\\u00F6\\u022B\\u1ECF\\u0151\\u01D2\\u020D\\u020F\\u01A1\\u1EDD\\u1EDB\\u1EE1\\u1EDF\\u1EE3\\u1ECD\\u1ED9\\u01EB\\u01ED\\u00F8\\u01FF\\u0254\\uA74B\\uA74D\\u0275]","oi":"[\\u01A3]","ou":"[\\u0223]","oo":"[\\uA74F]","p":"[\\u0070\\u24DF\\uFF50\\u1E55\\u1E57\\u01A5\\u1D7D\\uA751\\uA753\\uA755]","q":"[\\u0071\\u24E0\\uFF51\\u024B\\uA757\\uA759]","r":"[\\u0072\\u24E1\\uFF52\\u0155\\u1E59\\u0159\\u0211\\u0213\\u1E5B\\u1E5D\\u0157\\u1E5F\\u024D\\u027D\\uA75B\\uA7A7\\uA783]","s":"[\\u0073\\u24E2\\uFF53\\u015B\\u1E65\\u015D\\u1E61\\u0161\\u1E67\\u1E63\\u1E69\\u0219\\u015F\\u023F\\uA7A9\\uA785\\u1E9B]","ss":"[\\u00DF]","t":"[\\u0074\\u24E3\\uFF54\\u1E6B\\u1E97\\u0165\\u1E6D\\u021B\\u0163\\u1E71\\u1E6F\\u0167\\u01AD\\u0288\\u2C66\\uA787]","tz":"[\\uA729]","u":"[\\u0075\\u24E4\\uFF55\\u00F9\\u00FA\\u00FB\\u0169\\u1E79\\u016B\\u1E7B\\u016D\\u00FC\\u01DC\\u01D8\\u01D6\\u01DA\\u1EE7\\u016F\\u0171\\u01D4\\u0215\\u0217\\u01B0\\u1EEB\\u1EE9\\u1EEF\\u1EED\\u1EF1\\u1EE5\\u1E73\\u0173\\u1E77\\u1E75\\u0289]","v":"[\\u0076\\u24E5\\uFF56\\u1E7D\\u1E7F\\u028B\\uA75F\\u028C]","vy":"[\\uA761]","w":"[\\u0077\\u24E6\\uFF57\\u1E81\\u1E83\\u0175\\u1E87\\u1E85\\u1E98\\u1E89\\u2C73]","x":"[\\u0078\\u24E7\\uFF58\\u1E8B\\u1E8D]","y":"[\\u0079\\u24E8\\uFF59\\u1EF3\\u00FD\\u0177\\u1EF9\\u0233\\u1E8F\\u00FF\\u1EF7\\u1E99\\u1EF5\\u01B4\\u024F\\u1EFF]","z":"[\\u007A\\u24E9\\uFF5A\\u017A\\u1E91\\u017C\\u017E\\u1E93\\u1E95\\u01B6\\u0225\\u0240\\u2C6C\\uA763]"},"researchesTests":["contentHasTOC","contentHasShortParagraphs","contentHasAssets","keywordInTitle","keywordInMetaDescription","keywordInPermalink","keywordIn10Percent","keywordInContent","keywordInSubheadings","keywordInImageAlt","keywordDensity","keywordNotUsed","lengthContent","lengthPermalink","linksHasInternal","linksHasExternals","linksNotAllExternals","titleStartWithKeyword","titleSentiment","titleHasPowerWords","titleHasNumber","hasContentAI"],"hasRedirection":false,"hasBreadcrumb":false},"homeUrl":"https:\/\/ocr365.com\/pt","objectID":766,"objectType":"post","locale":"pt","localeFull":"pt_PT","overlayImages":{"play":{"name":"Play icon","url":"https:\/\/ocr365.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-play.png","path":"\/var\/www\/vhosts\/ocr365.com\/httpdocs\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-play.png","position":"middle_center"},"gif":{"name":"GIF icon","url":"https:\/\/ocr365.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-gif.png","path":"\/var\/www\/vhosts\/ocr365.com\/httpdocs\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/icon-gif.png","position":"middle_center"}},"defautOgImage":"https:\/\/ocr365.com\/wp-content\/uploads\/2025\/01\/LOGO8.png","customPermalinks":true,"isUserRegistered":false,"autoSuggestKeywords":false,"connectSiteUrl":"https:\/\/rankmath.com\/auth?site=https%3A%2F%2Focr365.com%2Fpt&r=https%3A%2F%2Focr365.com%2Fpt%2Fwp-json%2Fwp%2Fv2%2Fpages%2F766%3Fnonce%3D2c49548879","maxTags":5,"trendsIcon":"<svg viewBox=\"0 0 610 610\"><path d=\"M18.85,446,174.32,290.48l58.08,58.08L76.93,504a14.54,14.54,0,0,1-20.55,0L18.83,466.48a14.54,14.54,0,0,1,0-20.55Z\" style=\"fill:#4285f4\"\/><path d=\"M242.65,242.66,377.59,377.6l-47.75,47.75a14.54,14.54,0,0,1-20.55,0L174.37,290.43l47.75-47.75A14.52,14.52,0,0,1,242.65,242.66Z\" style=\"fill:#ea4335\"\/><polygon points=\"319.53 319.53 479.26 159.8 537.34 217.88 377.61 377.62 319.53 319.53\" style=\"fill:#fabb05\"\/><path d=\"M594.26,262.73V118.61h0a16.94,16.94,0,0,0-16.94-16.94H433.2a16.94,16.94,0,0,0-12,28.92L565.34,274.71h0a16.94,16.94,0,0,0,28.92-12Z\" style=\"fill:#34a853\"\/><rect width=\"610\" height=\"610\" style=\"fill:none\"\/><\/svg>","showScore":true,"siteFavIcon":"https:\/\/ocr365.com\/wp-content\/uploads\/2025\/01\/cropped-512-32x32.png","canUser":{"general":false,"advanced":false,"snippet":false,"social":false,"analysis":false,"analytics":false,"content_ai":false},"showKeywordIntent":true,"isPro":false,"is_front_page":false,"trendsUpgradeLink":"https:\/\/rankmath.com\/pricing\/?utm_source=Plugin&utm_medium=CE%20General%20Tab%20Trends&utm_campaign=WP","trendsUpgradeLabel":"Upgrade","trendsPreviewImage":"https:\/\/ocr365.com\/wp-content\/plugins\/seo-by-rank-math\/assets\/admin\/img\/trends-preview.jpg","currentEditor":false,"homepageData":{"assessor":{"powerWords":[],"diacritics":true,"researchesTests":["contentHasTOC","contentHasShortParagraphs","contentHasAssets","keywordInTitle","keywordInMetaDescription","keywordInPermalink","keywordIn10Percent","keywordInContent","keywordInSubheadings","keywordInImageAlt","keywordDensity","keywordNotUsed","lengthContent","lengthPermalink","linksHasInternal","linksHasExternals","linksNotAllExternals","titleStartWithKeyword","titleSentiment","titleHasPowerWords","titleHasNumber","hasContentAI"],"hasBreadcrumb":false,"serpData":{"title":"%sitename% %page% %sep% %sitedesc%","description":"","titleTemplate":"%sitename% %page% %sep% %sitedesc%","descriptionTemplate":"","focusKeywords":"","breadcrumbTitle":"Home","robots":{"index":true},"advancedRobots":{"max-snippet":"-1","max-video-preview":"-1","max-image-preview":"large"},"facebookTitle":"","facebookDescription":"","facebookImage":"","facebookImageID":""}}},"tocTitle":"Table of Contents","tocExcludeHeadings":[],"listStyle":"ul"},"_links":{"self":[{"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/pages\/766","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/comments?post=766"}],"version-history":[{"count":25,"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/pages\/766\/revisions"}],"predecessor-version":[{"id":1597,"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/pages\/766\/revisions\/1597"}],"wp:attachment":[{"href":"https:\/\/ocr365.com\/pt\/wp-json\/wp\/v2\/media?parent=766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}