{"id":3903,"date":"2025-12-22T15:28:48","date_gmt":"2025-12-22T15:28:48","guid":{"rendered":"https:\/\/bkupdate.in\/?page_id=3903"},"modified":"2026-03-12T08:37:40","modified_gmt":"2026-03-12T08:37:40","slug":"jpg-to-pdf-converter","status":"publish","type":"page","link":"https:\/\/bkupdate.in\/?page_id=3903","title":{"rendered":"JPG to PDF Converter"},"content":{"rendered":"\n<!-- JPG to PDF Converter - Scoped for WordPress -->\n<!-- jsPDF & CropperJS -->\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"><\/script>\n<link href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/cropperjs\/1.5.12\/cropper.min.css\" rel=\"stylesheet\">\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/cropperjs\/1.5.12\/cropper.min.js\"><\/script>\n<!-- Fonts -->\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;600;700&#038;family=Space+Grotesk:wght@400;500;700&#038;display=swap\" rel=\"stylesheet\">\n\n<style>\n:root {\n    --jp-primary: #6366f1;\n    --jp-primary-hover: #4f46e5;\n    --jp-secondary: #8b5cf6;\n    --jp-text-dark: #1f2937;\n    --jp-text-light: #6b7280;\n    --jp-card-bg: #ffffff;\n\n    --jp-cyber-blue: #00F0FF;\n    --jp-cyber-purple: #BD00FF;\n    --jp-cyber-green: #10B981;\n    --jp-cyber-bg: #0B0E14;\n}\n\n\/* scope sab kuch sirf is tool ke andar *\/\n.bk-jpg-pdf-wrapper * {\n    box-sizing: border-box;\n    font-family: 'Inter', sans-serif;\n}\n\n.bk-jpg-pdf-wrapper {\n    background: #f3f4f6;\n    padding: 30px 0;\n}\n\n.bk-jpg-pdf-wrapper .container {\n    width: 100%;\n    max-width: 900px;\n    background: var(--jp-card-bg);\n    margin: 0 auto;\n    border-radius: 24px;\n    padding: 40px 24px;\n    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);\n}\n\n\/* Header *\/\n.bk-jpg-pdf-wrapper header {\n    text-align: center;\n    margin-bottom: 30px;\n}\n.bk-jpg-pdf-wrapper header h1 {\n    font-size: 2rem;\n    background: -webkit-linear-gradient(45deg, var(--jp-primary), var(--jp-secondary));\n    -webkit-background-clip: text;\n    -webkit-text-fill-color: transparent;\n    margin-bottom: 8px;\n    font-weight: 800;\n}\n.bk-jpg-pdf-wrapper header p {\n    font-size: 0.95rem;\n    color: var(--jp-text-light);\n}\n\n\/* Upload *\/\n.bk-jpg-pdf-wrapper .upload-area {\n    border: 2px dashed #c7c7c7;\n    border-radius: 16px;\n    padding: 40px 20px;\n    text-align: center;\n    background: #f9fafb;\n    transition: all 0.3s;\n    cursor: pointer;\n}\n.bk-jpg-pdf-wrapper .upload-area:hover,\n.bk-jpg-pdf-wrapper .upload-area.dragover {\n    border-color: var(--jp-primary);\n    background: #eef2ff;\n    box-shadow: 0 10px 20px rgba(99, 102, 241, 0.1);\n}\n.bk-jpg-pdf-wrapper .upload-icon {\n    font-size: 3rem;\n    color: var(--jp-primary);\n    margin-bottom: 12px;\n}\n.bk-jpg-pdf-wrapper .upload-text {\n    font-size: 1.1rem;\n    font-weight: 600;\n    color: var(--jp-text-dark);\n}\n.bk-jpg-pdf-wrapper .upload-subtext {\n    font-size: 0.85rem;\n    color: var(--jp-text-light);\n    margin-bottom: 14px;\n}\n.bk-jpg-pdf-wrapper .browse-btn {\n    display: inline-block;\n    background: var(--jp-primary);\n    color: #fff;\n    padding: 8px 20px;\n    border-radius: 999px;\n    font-size: 0.85rem;\n    font-weight: 600;\n}\n.bk-jpg-pdf-wrapper #fileInput { display: none; }\n\n\/* Preview *\/\n.bk-jpg-pdf-wrapper .preview-section {\n    margin-top: 24px;\n    display: none;\n    border-top: 1px solid #e5e7eb;\n    padding-top: 18px;\n}\n.bk-jpg-pdf-wrapper .preview-title {\n    font-size: 1rem;\n    color: var(--jp-text-dark);\n    margin-bottom: 16px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n}\n.bk-jpg-pdf-wrapper .preview-title small {\n    color: var(--jp-text-light);\n}\n.bk-jpg-pdf-wrapper .preview-container {\n    display: grid;\n    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));\n    gap: 16px;\n}\n.bk-jpg-pdf-wrapper .preview-item {\n    background: #fff;\n    border-radius: 12px;\n    overflow: hidden;\n    border: 1px solid #f3f4f6;\n    box-shadow: 0 4px 6px rgba(0,0,0,0.05);\n    cursor: grab;\n    transition: all 0.2s;\n}\n.bk-jpg-pdf-wrapper .preview-item.dragging {\n    opacity: 0.4;\n    border: 2px dashed var(--jp-primary);\n}\n.bk-jpg-pdf-wrapper .preview-img {\n    width: 100%;\n    height: 110px;\n    object-fit: cover;\n    border-bottom: 1px solid #f3f4f6;\n}\n.bk-jpg-pdf-wrapper .preview-info {\n    padding: 8px;\n}\n.bk-jpg-pdf-wrapper .preview-name {\n    font-size: 0.75rem;\n    color: var(--jp-text-dark);\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    text-align: center;\n    margin-bottom: 6px;\n}\n.bk-jpg-pdf-wrapper .preview-actions {\n    display: flex;\n    justify-content: center;\n    gap: 8px;\n}\n.bk-jpg-pdf-wrapper .action-icon-btn {\n    background: #f3f4f6;\n    border: none;\n    width: 28px;\n    height: 28px;\n    border-radius: 999px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 0.8rem;\n    cursor: pointer;\n}\n.bk-jpg-pdf-wrapper .crop-btn { color: var(--jp-primary); }\n.bk-jpg-pdf-wrapper .remove-btn { color: #ef4444; }\n\n\/* Bottom buttons *\/\n.bk-jpg-pdf-wrapper .action-buttons {\n    display: flex;\n    justify-content: center;\n    gap: 16px;\n    margin-top: 28px;\n    flex-wrap: wrap;\n}\n.bk-jpg-pdf-wrapper .main-btn {\n    padding: 12px 28px;\n    border-radius: 999px;\n    border: none;\n    font-size: 0.95rem;\n    font-weight: 700;\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    cursor: pointer;\n}\n.bk-jpg-pdf-wrapper .convert-btn {\n    background: linear-gradient(135deg, var(--jp-primary), var(--jp-secondary));\n    color: #fff;\n}\n.bk-jpg-pdf-wrapper .convert-btn:disabled {\n    background: #9ca3af;\n    cursor: not-allowed;\n}\n.bk-jpg-pdf-wrapper .download-btn {\n    background: linear-gradient(135deg, #10b981, #059669);\n    color: #fff;\n    display: none;\n}\n\n\/* Loader (scoped) *\/\n.bk-jpg-pdf-wrapper .loader-overlay {\n    position: fixed;\n    inset: 0;\n    background-color: var(--jp-cyber-bg);\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n    z-index: 9999;\n    opacity: 1;\n    transition: opacity 0.3s ease;\n    font-family: 'Space Grotesk', monospace;\n}\n.bk-jpg-pdf-wrapper .loader-overlay.hidden {\n    opacity: 0;\n    pointer-events: none;\n}\n.bk-jpg-pdf-wrapper .spinner-container {\n    width: 16rem;\n    height: 16rem;\n    position: relative;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n}\n.bk-jpg-pdf-wrapper .spinner-ring-outer {\n    position: absolute;\n    inset: 0;\n    border-top: 4px solid var(--jp-cyber-blue);\n    border-radius: 9999px;\n    animation: jp-spin 1s linear infinite;\n}\n.bk-jpg-pdf-wrapper .spinner-ring-inner {\n    position: absolute;\n    inset: 0.5rem;\n    border-bottom: 4px solid var(--jp-cyber-purple);\n    border-radius: 9999px;\n    animation: jp-spin 1s linear infinite reverse;\n}\n.bk-jpg-pdf-wrapper .spinner-text {\n    position: absolute;\n    inset: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--jp-cyber-blue);\n    font-size: 0.85rem;\n    animation: jp-pulse 1.5s ease-in-out infinite;\n    font-weight: 700;\n    letter-spacing: 2px;\n}\n.bk-jpg-pdf-wrapper .console-text {\n    margin-top: 1.5rem;\n    color: var(--jp-cyber-green);\n    font-size: 0.9rem;\n    height: 1.5rem;\n}\n.bk-jpg-pdf-wrapper .loader-bar-bg {\n    width: 16rem;\n    height: 0.25rem;\n    background-color: #1F2937;\n    border-radius: 9999px;\n    margin-top: 0.8rem;\n    overflow: hidden;\n}\n.bk-jpg-pdf-wrapper .loader-bar-fill {\n    height: 100%;\n    background-color: var(--jp-cyber-green);\n    width: 0;\n    transition: width 0.3s linear;\n}\n@keyframes jp-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }\n@keyframes jp-pulse { 0%,100%{opacity:1;} 50%{opacity:0.5;} }\n\n\/* Crop modal *\/\n.bk-jpg-pdf-wrapper .crop-modal {\n    position: fixed;\n    inset: 0;\n    background: rgba(0,0,0,0.85);\n    z-index: 10000;\n    display: none;\n    justify-content: center;\n    align-items: center;\n    padding: 16px;\n}\n.bk-jpg-pdf-wrapper .modal-content {\n    background: #ffffff;\n    padding: 20px;\n    border-radius: 18px;\n    width: 100%;\n    max-width: 800px;\n    max-height: 90vh;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n}\n.bk-jpg-pdf-wrapper .modal-content h2 {\n    margin-bottom: 16px;\n    color: var(--jp-text-dark);\n}\n.bk-jpg-pdf-wrapper .modal-image-container {\n    width: 100%;\n    height: 60vh;\n    background: #f3f4f6;\n    margin-bottom: 16px;\n    border-radius: 10px;\n    overflow: hidden;\n}\n.bk-jpg-pdf-wrapper .modal-image-container img {\n    max-width: 100%;\n    max-height: 100%;\n    display: block;\n}\n.bk-jpg-pdf-wrapper .modal-buttons {\n    display: flex;\n    gap: 10px;\n}\n.bk-jpg-pdf-wrapper .modal-btn {\n    padding: 8px 20px;\n    border-radius: 8px;\n    border: none;\n    font-weight: 600;\n    cursor: pointer;\n    font-size: 0.9rem;\n}\n.bk-jpg-pdf-wrapper .save-crop-btn {\n    background: var(--jp-primary);\n    color: #fff;\n}\n.bk-jpg-pdf-wrapper .cancel-crop-btn {\n    background: #e5e7eb;\n    color: var(--jp-text-dark);\n}\n\n\/* Responsive *\/\n@media (max-width:768px){\n  .bk-jpg-pdf-wrapper .container{\n    border-radius:16px;\n    padding:24px 16px;\n  }\n  .bk-jpg-pdf-wrapper header h1{font-size:1.6rem;}\n  .bk-jpg-pdf-wrapper .action-buttons{flex-direction:column;}\n  .bk-jpg-pdf-wrapper .main-btn{width:100%;justify-content:center;}\n}\n<\/style>\n\n<div class=\"bk-jpg-pdf-wrapper\">\n  <!-- Loader -->\n  <div id=\"fullscreenLoader\" class=\"loader-overlay hidden\">\n      <div class=\"spinner-container\">\n          <div class=\"spinner-ring-outer\"><\/div>\n          <div class=\"spinner-ring-inner\"><\/div>\n          <div class=\"spinner-text\">PROCESSING<\/div>\n      <\/div>\n      <div id=\"consoleText\" class=\"console-text\">&gt; System Ready&#8230;<\/div>\n      <div class=\"loader-bar-bg\">\n          <div id=\"loaderBar\" class=\"loader-bar-fill\"><\/div>\n      <\/div>\n  <\/div>\n\n  <!-- Crop modal -->\n  <div class=\"crop-modal\" id=\"cropModal\">\n      <div class=\"modal-content\">\n          <h2>Adjust Image<\/h2>\n          <div class=\"modal-image-container\">\n              <img decoding=\"async\" id=\"imageToCrop\" src=\"\" alt=\"Image to crop\">\n          <\/div>\n          <div class=\"modal-buttons\">\n              <button class=\"modal-btn cancel-crop-btn\" id=\"cancelCropBtn\">Cancel<\/button>\n              <button class=\"modal-btn save-crop-btn\" id=\"saveCropBtn\">Apply Crop<\/button>\n          <\/div>\n      <\/div>\n  <\/div>\n\n  <div class=\"container\">\n      <header>\n          <h1>JPG to PDF Converter<\/h1>\n          <p>Smart Compression: Automatically reduces file size by ~40% or fits under 1MB.<\/p>\n      <\/header>\n      \n      <div class=\"upload-area\" id=\"uploadArea\">\n          <div class=\"upload-icon\">\ud83d\udce4<\/div>\n          <div class=\"upload-text\">Drop your JPGs here<\/div>\n          <div class=\"upload-subtext\">or click to browse<\/div>\n          <div class=\"browse-btn\" id=\"browseBtn\">Select Files<\/div>\n          <input type=\"file\" id=\"fileInput\" accept=\".jpg,.jpeg,.jpe,.jfif\" multiple>\n      <\/div>\n      \n      <div class=\"preview-section\" id=\"previewSection\">\n          <div class=\"preview-title\">\n              <span>Selected Images<\/span>\n              <small>(Drag to reorder)<\/small>\n          <\/div>\n          <div class=\"preview-container\" id=\"previewContainer\"><\/div>\n      <\/div>\n      \n      <div class=\"action-buttons\">\n          <button class=\"main-btn convert-btn\" id=\"convertBtn\">\n              Convert to PDF\n          <\/button>\n          <button class=\"main-btn download-btn\" id=\"downloadBtn\">\n              Download PDF\n          <\/button>\n      <\/div>\n  <\/div>\n<\/div>\n\n<script>\ndocument.addEventListener('DOMContentLoaded', () => {\n    const { jsPDF } = window.jspdf;\n\n    const uploadArea = document.getElementById('uploadArea');\n    const fileInput = document.getElementById('fileInput');\n    const browseBtn = document.getElementById('browseBtn');\n    const previewSection = document.getElementById('previewSection');\n    const previewContainer = document.getElementById('previewContainer');\n    const convertBtn = document.getElementById('convertBtn');\n    const downloadBtn = document.getElementById('downloadBtn');\n\n    const fullscreenLoader = document.getElementById('fullscreenLoader');\n    const consoleTxt = document.getElementById('consoleText');\n    const loaderBar = document.getElementById('loaderBar');\n\n    const cropModal = document.getElementById('cropModal');\n    const imageToCrop = document.getElementById('imageToCrop');\n    const saveCropBtn = document.getElementById('saveCropBtn');\n    const cancelCropBtn = document.getElementById('cancelCropBtn');\n\n    let selectedFiles = [];\n    let pdfData = null;\n    let cropper = null;\n    let currentCropIndex = -1;\n    let dragStartIndex;\n\n    browseBtn.addEventListener('click', (e) => {\n        e.stopPropagation();\n        fileInput.click();\n    });\n    uploadArea.addEventListener('click', () => fileInput.click());\n    fileInput.addEventListener('change', (e) => handleFiles(e.target.files));\n\n    uploadArea.addEventListener('dragover', (e) => {\n        e.preventDefault();\n        uploadArea.classList.add('dragover');\n    });\n    uploadArea.addEventListener('dragleave', () => {\n        uploadArea.classList.remove('dragover');\n    });\n    uploadArea.addEventListener('drop', (e) => {\n        e.preventDefault();\n        uploadArea.classList.remove('dragover');\n        if (e.dataTransfer.files.length) handleFiles(e.dataTransfer.files);\n    });\n\n    convertBtn.addEventListener('click', convertToPdf);\n    downloadBtn.addEventListener('click', downloadPdf);\n    saveCropBtn.addEventListener('click', saveCroppedImage);\n    cancelCropBtn.addEventListener('click', closeCropModal);\n\n    async function handleFiles(files) {\n        const imageFiles = Array.from(files).filter(file =>\n            file.type.startsWith('image\/') &&\n            (file.name.toLowerCase().endsWith('.jpg') || file.name.toLowerCase().endsWith('.jpeg'))\n        );\n        if (!imageFiles.length) {\n            alert('Please select valid JPG images.');\n            return;\n        }\n        for (const file of imageFiles) {\n            const dataUrl = await readFileAsDataURL(file);\n            selectedFiles.push({ originalFile: file, dataUrl, croppedDataUrl: null });\n        }\n        updatePreview();\n        previewSection.style.display = 'block';\n        downloadBtn.style.display = 'none';\n        convertBtn.disabled = false;\n        convertBtn.textContent = 'Convert to PDF';\n        pdfData = null;\n    }\n\n    function updatePreview() {\n        previewContainer.innerHTML = '';\n        selectedFiles.forEach((fileData, index) => {\n            const div = document.createElement('div');\n            div.className = 'preview-item';\n            div.setAttribute('draggable', 'true');\n            div.dataset.index = index;\n\n            const imgUrl = fileData.croppedDataUrl || fileData.dataUrl;\n            div.innerHTML = `\n                <img decoding=\"async\" src=\"${imgUrl}\" class=\"preview-img\" alt=\"${fileData.originalFile.name}\">\n                <div class=\"preview-info\">\n                    <div class=\"preview-name\">${fileData.originalFile.name}<\/div>\n                    <div class=\"preview-actions\">\n                        <button class=\"action-icon-btn crop-btn\" data-index=\"${index}\">\u2702\ufe0f<\/button>\n                        <button class=\"action-icon-btn remove-btn\" data-index=\"${index}\">\u2715<\/button>\n                    <\/div>\n                <\/div>\n            `;\n            previewContainer.appendChild(div);\n        });\n\n        addDragListeners();\n        document.querySelectorAll('.crop-btn').forEach(b => b.addEventListener('click', openCropModal));\n        document.querySelectorAll('.remove-btn').forEach(b => b.addEventListener('click', removeImage));\n    }\n\n    function addDragListeners() {\n        const items = document.querySelectorAll('.preview-item');\n        items.forEach(item => {\n            item.addEventListener('dragstart', function(e) {\n                this.classList.add('dragging');\n                dragStartIndex = +this.dataset.index;\n            });\n            item.addEventListener('dragover', e => e.preventDefault());\n            item.addEventListener('drop', function(e) {\n                e.preventDefault();\n                const dropIndex = +this.dataset.index;\n                if (dragStartIndex !== dropIndex) {\n                    const moved = selectedFiles.splice(dragStartIndex, 1)[0];\n                    selectedFiles.splice(dropIndex, 0, moved);\n                    updatePreview();\n                }\n            });\n            item.addEventListener('dragend', () => {\n                document.querySelectorAll('.preview-item').forEach(i => i.classList.remove('dragging'));\n            });\n        });\n    }\n\n    function removeImage(e) {\n        const idx = parseInt(e.currentTarget.getAttribute('data-index'));\n        selectedFiles.splice(idx, 1);\n        updatePreview();\n        if (!selectedFiles.length) {\n            previewSection.style.display = 'none';\n            downloadBtn.style.display = 'none';\n            convertBtn.disabled = false;\n        }\n    }\n\n    function openCropModal(e) {\n        currentCropIndex = parseInt(e.currentTarget.getAttribute('data-index'));\n        const fileData = selectedFiles[currentCropIndex];\n        imageToCrop.src = fileData.dataUrl;\n        cropModal.style.display = 'flex';\n        if (cropper) cropper.destroy();\n        cropper = new Cropper(imageToCrop, {\n            aspectRatio: NaN,\n            viewMode: 1,\n            background: false,\n            autoCropArea: 0.9\n        });\n    }\n\n    function closeCropModal() {\n        cropModal.style.display = 'none';\n        if (cropper) {\n            cropper.destroy();\n            cropper = null;\n        }\n    }\n\n    function saveCroppedImage() {\n        if (!cropper) return;\n        const c = cropper.getCroppedCanvas();\n        const url = c.toDataURL('image\/jpeg', 0.95);\n        selectedFiles[currentCropIndex].croppedDataUrl = url;\n        updatePreview();\n        closeCropModal();\n    }\n\n    function readFileAsDataURL(file) {\n        return new Promise((res, rej) => {\n            const r = new FileReader();\n            r.onload = () => res(r.result);\n            r.onerror = rej;\n            r.readAsDataURL(file);\n        });\n    }\n\n    async function getCompressedImageData(dataUrl, quality) {\n        return new Promise(resolve => {\n            const img = new Image();\n            img.onload = () => {\n                const canvas = document.createElement('canvas');\n                canvas.width = img.width;\n                canvas.height = img.height;\n                const ctx = canvas.getContext('2d');\n                ctx.drawImage(img, 0, 0);\n                const newUrl = canvas.toDataURL('image\/jpeg', quality);\n                const head = 'data:image\/jpeg;base64,';\n                const size = Math.round((newUrl.length - head.length) * 3 \/ 4);\n                resolve({ dataUrl: newUrl, width: img.width, height: img.height, size });\n            };\n            img.src = dataUrl;\n        });\n    }\n\n    async function convertToPdf() {\n        if (!selectedFiles.length) return;\n\n        convertBtn.disabled = true;\n        fullscreenLoader.classList.remove('hidden');\n\n        const logs = [\n            \"Scanning JPG Files...\",\n            \"Analyzing Dimensions...\",\n            \"Applying Smart Compression (40%)...\",\n            \"Optimizing Output Quality...\",\n            \"Building PDF Document...\"\n        ];\n        let i = 0;\n        loaderBar.style.width = \"0%\";\n        consoleTxt.innerText = \"> Initializing...\";\n        const anim = setInterval(() => {\n            if (i < logs.length) {\n                consoleTxt.innerText = \"> \" + logs[i];\n                loaderBar.style.width = ((i + 1) * 20) + \"%\";\n                i++;\n            } else {\n                clearInterval(anim);\n                consoleTxt.innerText = \"> Conversion Complete!\";\n            }\n        }, 900);\n\n        setTimeout(async () => {\n            clearInterval(anim);\n            loaderBar.style.width = \"100%\";\n\n            const totalInputSize = selectedFiles.reduce((a, f) => a + f.originalFile.size, 0);\n            const MAX_PDF = 1 * 1024 * 1024;\n            const TARGET = Math.min(MAX_PDF, totalInputSize * 0.6);\n\n            let quality = 0.9;\n            let compressedImages = [];\n            let totalSize = Infinity;\n\n            try {\n                while (totalSize > TARGET && quality > 0.1) {\n                    totalSize = 0;\n                    let tmp = [];\n                    for (const f of selectedFiles) {\n                        const src = f.croppedDataUrl || f.dataUrl;\n                        const comp = await getCompressedImageData(src, quality);\n                        totalSize += comp.size;\n                        tmp.push(comp);\n                    }\n                    if (totalSize <= TARGET) {\n                        compressedImages = tmp;\n                        break;\n                    }\n                    quality -= 0.15;\n                    if (quality < 0.1) compressedImages = tmp;\n                }\n\n                const pdf = new jsPDF();\n                for (let i = 0; i < compressedImages.length; i++) {\n                    const img = compressedImages[i];\n                    if (i > 0) pdf.addPage();\n                    const w = pdf.internal.pageSize.getWidth();\n                    const h = pdf.internal.pageSize.getHeight();\n                    const ratio = Math.min(w \/ img.width, h \/ img.height);\n                    const iw = img.width * ratio;\n                    const ih = img.height * ratio;\n                    const x = (w - iw) \/ 2;\n                    const y = (h - ih) \/ 2;\n                    pdf.addImage(img.dataUrl, 'JPEG', x, y, iw, ih);\n                }\n                pdfData = pdf.output('blob');\n\n                fullscreenLoader.classList.add('hidden');\n                downloadBtn.style.display = 'flex';\n                convertBtn.textContent = 'Converted';\n\n            } catch (err) {\n                console.error(err);\n                alert('Error during conversion.');\n                fullscreenLoader.classList.add('hidden');\n                convertBtn.disabled = false;\n            }\n        }, 5000);\n    }\n\n    function downloadPdf() {\n        if (!pdfData) return;\n        const firstName = selectedFiles[0].originalFile.name;\n        const base = firstName.substring(0, firstName.lastIndexOf('.')) || firstName;\n        const url = URL.createObjectURL(pdfData);\n        const a = document.createElement('a');\n        a.href = url;\n        a.download = base + '_compressed.pdf';\n        document.body.appendChild(a);\n        a.click();\n        document.body.removeChild(a);\n    }\n});\n<\/script>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>PROCESSING &gt; System Ready&#8230; Adjust Image Cancel Apply Crop JPG to PDF Converter Smart Compression: Automatically reduces file &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"JPG to PDF Converter\" class=\"read-more button\" href=\"https:\/\/bkupdate.in\/?page_id=3903#more-3903\" aria-label=\"Read more about JPG to PDF Converter\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3903","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/bkupdate.in\/index.php?rest_route=\/wp\/v2\/pages\/3903","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bkupdate.in\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bkupdate.in\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bkupdate.in\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bkupdate.in\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3903"}],"version-history":[{"count":3,"href":"https:\/\/bkupdate.in\/index.php?rest_route=\/wp\/v2\/pages\/3903\/revisions"}],"predecessor-version":[{"id":4795,"href":"https:\/\/bkupdate.in\/index.php?rest_route=\/wp\/v2\/pages\/3903\/revisions\/4795"}],"wp:attachment":[{"href":"https:\/\/bkupdate.in\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3903"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}