Free Job Alert: Latest Jobs | Admit Cards | Results

All-in-One Tools

JPG to PDF

Convert JPG and PNG images into a single PDF file.


or drop images here

Merge PDF files

Combine multiple PDFs into one, in the order you choose.


or drop PDFs here

${item.file.name}

`; filesQueue.appendChild(card); }); filesQueue.querySelectorAll('.remove-btn').forEach(btn => { btn.addEventListener('click', () => { const id = Number(btn.dataset.id); imageFiles = imageFiles.filter(f => f.id !== id); renderQueue(); }); }); filesQueue.querySelectorAll('.rotate-btn').forEach(btn => { btn.addEventListener('click', () => { const id = Number(btn.dataset.id); const item = imageFiles.find(f => f.id === id); item.rotation = (item.rotation + 90) % 360; const img = filesQueue.querySelector(`.file-card[data-id="${id}"] img`); if (img) img.style.transform = `rotate(${item.rotation}deg)`; }); }); } new Sortable(filesQueue, { animation: 150, onEnd: () => { const newOrder = Array.from(filesQueue.children).map(c => Number(c.dataset.id)); imageFiles = newOrder.map(id => imageFiles.find(f => f.id === id)); renderQueue(); } }); function rotatePixels(file, url, angle) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => { const canvas = document.createElement('canvas'); const swap = (angle === 90 || angle === 270); canvas.width = swap ? img.naturalHeight : img.naturalWidth; canvas.height = swap ? img.naturalWidth : img.naturalHeight; const ctx = canvas.getContext('2d'); ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate(angle * Math.PI / 180); ctx.drawImage(img, -img.naturalWidth / 2, -img.naturalHeight / 2); const isPng = file.type === 'image/png'; canvas.toBlob(blob => { if (!blob) { file.arrayBuffer().then(bytes => resolve({ bytes, isPng })).catch(reject); return; } blob.arrayBuffer().then(bytes => resolve({ bytes, isPng })).catch(reject); }, isPng ? 'image/png' : 'image/jpeg', 0.95); }; img.onerror = () => { file.arrayBuffer().then(bytes => resolve({ bytes, isPng: file.type === 'image/png' })).catch(reject); }; img.src = url; }); } async function addImageToDoc(pdfDoc, item) { const { bytes, isPng } = await rotatePixels(item.file, item.url, item.rotation); const img = isPng ? await pdfDoc.embedPng(bytes) : await pdfDoc.embedJpg(bytes); const pageSizeKey = pageSizeSelect.value; const margin = MARGINS[marginKey]; let pageW, pageH; if (pageSizeKey === 'original') { pageW = img.width + margin * 2; pageH = img.height + margin * 2; } else { const base = PAGE_SIZES[pageSizeKey]; pageW = orientation === 'landscape' ? Math.max(base.w, base.h) : Math.min(base.w, base.h); pageH = orientation === 'landscape' ? Math.min(base.w, base.h) : Math.max(base.w, base.h); } const availW = pageW - margin * 2; const availH = pageH - margin * 2; const scale = Math.min(availW / img.width, availH / img.height); const drawW = img.width * scale; const drawH = img.height * scale; const x = margin + (availW - drawW) / 2; const y = margin + (availH - drawH) / 2; const page = pdfDoc.addPage([pageW, pageH]); page.drawImage(img, { x, y, width: drawW, height: drawH }); } function triggerDownload(blobUrl, filename) { const tempLink = document.createElement('a'); tempLink.href = blobUrl; tempLink.download = filename; document.body.appendChild(tempLink); tempLink.click(); document.body.removeChild(tempLink); } convertBtn.addEventListener('click', async () => { if (imageFiles.length === 0) return; convertBtn.disabled = true; convertBtn.innerHTML = ' Converting...'; try { if (mergeImagesCheckbox.checked || imageFiles.length === 1) { const pdfDoc = await PDFDocument.create(); for (const item of imageFiles) { await addImageToDoc(pdfDoc, item); } const pdfBytes = await pdfDoc.save(); const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const blobUrl = URL.createObjectURL(blob); downloadLink.href = blobUrl; downloadLink.setAttribute('download', 'converted.pdf'); triggerDownload(blobUrl, 'converted.pdf'); } else { const zip = new JSZip(); let i = 1; for (const item of imageFiles) { const pdfDoc = await PDFDocument.create(); await addImageToDoc(pdfDoc, item); const pdfBytes = await pdfDoc.save(); const baseName = item.file.name.replace(/\.[^.]+$/, ''); zip.file(`${i}_${baseName}.pdf`, pdfBytes); i++; } const zipBlob = await zip.generateAsync({ type: 'blob' }); const blobUrl = URL.createObjectURL(zipBlob); downloadLink.href = blobUrl; downloadLink.setAttribute('download', 'converted_images.zip'); triggerDownload(blobUrl, 'converted_images.zip'); } workspaceView.classList.add('hidden'); optionsPanelJpg.classList.add('hidden'); downloadView.classList.remove('hidden'); } catch (err) { alert('Something went wrong converting your images: ' + err.message); } finally { convertBtn.disabled = false; convertBtn.innerHTML = 'Convert to PDF '; } }); window.resetJpgTool = function () { imageFiles.forEach(f => URL.revokeObjectURL(f.url)); imageFiles = []; downloadView.classList.add('hidden'); uploadView.classList.remove('hidden'); }; })(); /* ========================================================= TOOL 3: PDF MERGER ========================================================= */ (function () { const { PDFDocument, degrees } = PDFLib; const dropZoneMerge = document.getElementById('dropZoneMerge'); const fileInputMerge = document.getElementById('fileInputMerge'); const addMoreBtnMerge = document.getElementById('addMoreBtnMerge'); const sortBtnMerge = document.getElementById('sortBtnMerge'); const mergeBtn = document.getElementById('mergeBtn'); const uploadViewMerge = document.getElementById('uploadViewMerge'); const workspaceViewMerge = document.getElementById('workspaceViewMerge'); const downloadViewMerge = document.getElementById('downloadViewMerge'); const filesQueueMerge = document.getElementById('filesQueueMerge'); const downloadLinkMerge = document.getElementById('downloadLinkMerge'); const optionsPanelMerge = document.getElementById('optionsPanelMerge'); const fileCountBadgeMerge = document.getElementById('fileCountBadgeMerge'); let pdfFiles = []; // { id, file, thumbUrl, pageCount, rotation } let uidMerge = 0; dropZoneMerge.addEventListener('click', () => fileInputMerge.click()); addMoreBtnMerge.addEventListener('click', () => fileInputMerge.click()); fileInputMerge.addEventListener('change', (e) => addPdfFiles(e.target.files)); ['dragover', 'dragenter'].forEach(evt => dropZoneMerge.addEventListener(evt, (e) => { e.preventDefault(); dropZoneMerge.classList.add('border-red-500'); }) ); ['dragleave', 'drop'].forEach(evt => dropZoneMerge.addEventListener(evt, (e) => { e.preventDefault(); dropZoneMerge.classList.remove('border-red-500'); }) ); dropZoneMerge.addEventListener('drop', (e) => addPdfFiles(e.dataTransfer.files)); sortBtnMerge.addEventListener('click', () => { pdfFiles.sort((a, b) => a.file.name.localeCompare(b.file.name)); renderQueueMerge(); }); async function makeThumbnail(file) { const bytes = await file.arrayBuffer(); const loadingTask = pdfjsLib.getDocument({ data: bytes }); const pdf = await loadingTask.promise; const page = await pdf.getPage(1); const viewport = page.getViewport({ scale: 0.5 }); const canvas = document.createElement('canvas'); canvas.width = viewport.width; canvas.height = viewport.height; const ctx = canvas.getContext('2d'); await page.render({ canvasContext: ctx, viewport }).promise; return { thumbUrl: canvas.toDataURL('image/png'), pageCount: pdf.numPages }; } async function addPdfFiles(fileList) { const files = Array.from(fileList).filter(f => f.type === 'application/pdf'); for (const file of files) { const entry = { id: uidMerge++, file, thumbUrl: null, pageCount: null, rotation: 0 }; pdfFiles.push(entry); renderQueueMerge(); try { const { thumbUrl, pageCount } = await makeThumbnail(file); entry.thumbUrl = thumbUrl; entry.pageCount = pageCount; renderQueueMerge(); } catch (err) { console.error('Could not render thumbnail for', file.name, err); } } fileInputMerge.value = ''; } function renderQueueMerge() { if (pdfFiles.length === 0) { uploadViewMerge.classList.remove('hidden'); workspaceViewMerge.classList.add('hidden'); optionsPanelMerge.classList.add('hidden'); return; } uploadViewMerge.classList.add('hidden'); workspaceViewMerge.classList.remove('hidden'); optionsPanelMerge.classList.remove('hidden'); fileCountBadgeMerge.textContent = pdfFiles.length; filesQueueMerge.innerHTML = ''; pdfFiles.forEach((item, index) => { const card = document.createElement('div'); card.className = 'file-card bg-white rounded-lg shadow-sm p-3'; card.dataset.id = item.id; const thumbInner = item.thumbUrl ? `` : ``; card.innerHTML = `
${thumbInner} ${item.pageCount ? `${item.pageCount} pg` : ''}

${item.file.name}

`; filesQueueMerge.appendChild(card); }); filesQueueMerge.querySelectorAll('.remove-btn').forEach(btn => { btn.addEventListener('click', () => { const id = Number(btn.dataset.id); pdfFiles = pdfFiles.filter(f => f.id !== id); renderQueueMerge(); }); }); filesQueueMerge.querySelectorAll('.rotate-btn').forEach(btn => { btn.addEventListener('click', () => { const id = Number(btn.dataset.id); const item = pdfFiles.find(f => f.id === id); item.rotation = (item.rotation + 90) % 360; const img = filesQueueMerge.querySelector(`.file-card[data-id="${id}"] img`); if (img) img.style.transform = `rotate(${item.rotation}deg)`; }); }); } new Sortable(filesQueueMerge, { animation: 150, onEnd: () => { const newOrder = Array.from(filesQueueMerge.children).map(c => Number(c.dataset.id)); pdfFiles = newOrder.map(id => pdfFiles.find(f => f.id === id)); renderQueueMerge(); } }); mergeBtn.addEventListener('click', async () => { if (pdfFiles.length < 2) { alert('Please add at least 2 PDF files to merge.'); return; } mergeBtn.disabled = true; mergeBtn.innerHTML = ' Merging...'; try { const mergedPdf = await PDFDocument.create(); for (const item of pdfFiles) { const bytes = await item.file.arrayBuffer(); const srcDoc = await PDFDocument.load(bytes); const copiedPages = await mergedPdf.copyPages(srcDoc, srcDoc.getPageIndices()); copiedPages.forEach(page => { if (item.rotation) { const current = page.getRotation().angle || 0; page.setRotation(degrees((current + item.rotation) % 360)); } mergedPdf.addPage(page); }); } const mergedBytes = await mergedPdf.save(); const blob = new Blob([mergedBytes], { type: 'application/pdf' }); const blobUrl = URL.createObjectURL(blob); downloadLinkMerge.href = blobUrl; const tempLink = document.createElement('a'); tempLink.href = blobUrl; tempLink.download = 'merged.pdf'; document.body.appendChild(tempLink); tempLink.click(); document.body.removeChild(tempLink); workspaceViewMerge.classList.add('hidden'); optionsPanelMerge.classList.add('hidden'); downloadViewMerge.classList.remove('hidden'); } catch (err) { alert('Something went wrong merging your PDFs: ' + err.message); } finally { mergeBtn.disabled = false; mergeBtn.innerHTML = 'Merge PDF '; } }); window.resetMergeTool = function () { pdfFiles = []; downloadViewMerge.classList.add('hidden'); uploadViewMerge.classList.remove('hidden'); }; })();

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top