Convert your JPG images to PDF documents online for free. Combine multiple images into a single PDF with our professional converter tool. No installation or registration required.
or click to select files from your computer
Supports JPG, JPEG, PNG, BMP • Max 10MB per image
Select or drag-and-drop your JPG images into the converter tool.
Preview and rearrange your images in the desired order for the PDF.
Choose page orientation, image quality, and other PDF settings.
Click convert and download your professional PDF document.
All processing happens locally in your browser. Your images never leave your device, ensuring complete privacy and security.
Convert multiple images to PDF in seconds. Our optimized algorithm ensures quick processing without compromising quality.
Works perfectly on all devices - desktop, tablet, and mobile. Convert images to PDF anywhere, anytime.
No daily limits or restrictions. Convert as many images to PDF as you need, completely free of charge.
Supports JPG, JPEG, PNG, BMP, and other common image formats. Mix different formats in a single PDF.
Control page orientation, image quality, and layout to create PDFs that meet your specific requirements.
${file.name}
${formatFileSize(file.size)}
Converting...'; // Convert images to PDF await createPDFFromImages(); // Show download button showDownload(); } catch (error) { console.error('Conversion error:', error); showNotification('Error converting images to PDF: ' + error.message, 'error'); } finally { hideProgress(); isProcessing = false; convertBtn.disabled = false; convertBtn.innerHTML = ' Convert to PDF'; } } async function loadPDFLib() { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.min.js'; script.onload = () => { console.log('PDF-lib loaded successfully'); resolve(); }; script.onerror = reject; document.head.appendChild(script); }); } async function createPDFFromImages() { const totalImages = selectedImages.length; const orientation = document.getElementById('pageOrientation')?.value || 'portrait'; const quality = document.getElementById('imageQuality')?.value || 'high'; // Get PDF-lib classes const { PDFDocument } = window.PDFLib; // Create new PDF document const pdfDoc = await PDFDocument.create(); updateProgress(5, 'Creating PDF document...'); for (let i = 0; i < totalImages; i++) { const image = selectedImages[i]; const progress = Math.round(5 + ((i / totalImages) * 90)); updateProgress(progress, `Processing image ${i + 1} of ${totalImages}...`); try { // Read image data const imageArrayBuffer = await image.arrayBuffer(); // Determine image format and embed let embeddedImage; if (image.type === 'image/jpeg' || image.type === 'image/jpg') { embeddedImage = await pdfDoc.embedJpg(imageArrayBuffer); } else if (image.type === 'image/png') { embeddedImage = await pdfDoc.embedPng(imageArrayBuffer); } else { // Convert other formats to PNG using canvas const pngArrayBuffer = await convertImageToPng(image); embeddedImage = await pdfDoc.embedPng(pngArrayBuffer); } // Get image dimensions const imgDims = embeddedImage.scale(1); // Calculate page size based on orientation and image let pageWidth, pageHeight; if (orientation === 'landscape') { pageWidth = Math.max(imgDims.width, imgDims.height); pageHeight = Math.min(imgDims.width, imgDims.height); } else { pageWidth = Math.min(imgDims.width, imgDims.height); pageHeight = Math.max(imgDims.width, imgDims.height); } // Use standard page size if image is very small or very large const maxSize = 841.89; // A4 height in points const minSize = 595.28; // A4 width in points if (pageWidth > maxSize || pageHeight > maxSize) { const scale = Math.min(maxSize / pageWidth, maxSize / pageHeight); pageWidth *= scale; pageHeight *= scale; } if (pageWidth < minSize) pageWidth = minSize; if (pageHeight < minSize) pageHeight = minSize; // Create page const page = pdfDoc.addPage([pageWidth, pageHeight]); // Calculate image scale to fit page const scaleX = pageWidth / imgDims.width; const scaleY = pageHeight / imgDims.height; const scale = Math.min(scaleX, scaleY) * 0.95; // 95% to leave small margin const scaledWidth = imgDims.width * scale; const scaledHeight = imgDims.height * scale; // Center image on page const x = (pageWidth - scaledWidth) / 2; const y = (pageHeight - scaledHeight) / 2; // Draw image on page page.drawImage(embeddedImage, { x: x, y: y, width: scaledWidth, height: scaledHeight, }); } catch (imageError) { console.error(`Error processing image ${i + 1}:`, imageError); throw new Error(`Failed to process image: ${image.name}`); } } updateProgress(95, 'Finalizing PDF...'); // Save PDF const pdfBytes = await pdfDoc.save(); // Create download blob window.generatedPDFBlob = new Blob([pdfBytes], { type: 'application/pdf' }); updateProgress(100, 'PDF created successfully!'); } async function convertImageToPng(imageFile) { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = function() { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); canvas.toBlob(async (blob) => { const arrayBuffer = await blob.arrayBuffer(); resolve(arrayBuffer); }, 'image/png'); }; img.onerror = reject; img.src = URL.createObjectURL(imageFile); }); } function showProgress() { if (loadingSpinner) { loadingSpinner.style.display = 'block'; } } function hideProgress() { if (loadingSpinner) { loadingSpinner.style.display = 'none'; } } function updateProgress(percent, text) { // Progress indication through loading spinner and notifications showNotification(text, 'success'); } function showDownload() { if (downloadSection) { downloadSection.style.display = 'block'; } // Set up download button if it exists if (downloadBtn) { downloadBtn.onclick = downloadPDF; } } function resetTool() { selectedImages = []; isProcessing = false; if (fileInput) fileInput.value = ''; // Show drop zone again if (dropZone) dropZone.style.display = 'block'; // Hide other sections if (fileInfoArea) fileInfoArea.style.display = 'none'; if (imagePreview) imagePreview.style.display = 'none'; if (actionButtons) actionButtons.style.display = 'none'; if (downloadSection) downloadSection.style.display = 'none'; if (loadingSpinner) loadingSpinner.style.display = 'none'; // Reset convert button if (convertBtn) { convertBtn.disabled = true; convertBtn.classList.add('opacity-50', 'cursor-not-allowed'); convertBtn.innerHTML = ' Convert to PDF'; } // Clear file list and image grid if (fileList) fileList.innerHTML = ''; if (imageGrid) imageGrid.innerHTML = ''; } function formatFileSize(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } function showNotification(message, type = 'success') { // Create notification element if it doesn't exist let notification = document.getElementById('notification'); if (!notification) { notification = document.createElement('div'); notification.id = 'notification'; notification.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 12px 24px; border-radius: 8px; color: white; font-weight: 500; z-index: 9999; transform: translateX(400px); transition: transform 0.3s ease; `; document.body.appendChild(notification); } // Set message and style based on type notification.textContent = message; notification.style.backgroundColor = type === 'success' ? '#10b981' : '#ef4444'; // Show notification notification.style.transform = 'translateX(0)'; // Hide after 4 seconds setTimeout(() => { notification.style.transform = 'translateX(400px)'; }, 4000); } // Global functions for inline event handlers window.removeImage = function(index) { selectedImages.splice(index, 1); if (selectedImages.length === 0) { resetTool(); } else { showFileInfo(); displayImagePreviews(); } }; window.moveImageUp = function(index) { if (index > 0) { [selectedImages[index], selectedImages[index - 1]] = [selectedImages[index - 1], selectedImages[index]]; displayImagePreviews(); } }; window.moveImageDown = function(index) { if (index < selectedImages.length - 1) { [selectedImages[index], selectedImages[index + 1]] = [selectedImages[index + 1], selectedImages[index]]; displayImagePreviews(); } }; function downloadPDF() { if (!window.generatedPDFBlob) { showNotification('No PDF to download. Please convert images first.', 'error'); return; } const url = URL.createObjectURL(window.generatedPDFBlob); const a = document.createElement('a'); a.href = url; a.download = 'converted-images.pdf'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); showNotification('PDF downloaded successfully!', 'success'); } // Enhanced FAQ functionality with accordion behavior window.toggleFAQ = function(element) { const answer = element.nextElementSibling; const icon = element.querySelector('i'); const question = element; const allAnswers = document.querySelectorAll('.faq-answer'); const allQuestions = document.querySelectorAll('.faq-question'); // Close all other FAQs (accordion behavior) allAnswers.forEach(ans => { if (ans !== answer && ans.classList.contains('active')) { ans.classList.remove('active'); } }); allQuestions.forEach(q => { if (q !== question && q.classList.contains('active')) { q.classList.remove('active'); } }); // Toggle current FAQ const isActive = answer.classList.contains('active'); if (isActive) { answer.classList.remove('active'); question.classList.remove('active'); } else { answer.classList.add('active'); question.classList.add('active'); } // Update icon if (answer.classList.contains('active')) { icon.classList.remove('fa-chevron-down'); icon.classList.add('fa-chevron-up'); } else { icon.classList.add('fa-chevron-down'); icon.classList.remove('fa-chevron-up'); } }; });