If you’ve ever needed to convert a bunch of JPG images into PDF files without clicking through some online tool or installing bloated software, PowerShell is your best friend. It’s already on your Windows machine, it’s scriptable, and once you set it up — you can convert one file or a thousand with the same command.
In this tutorial, I’ll walk you through four different ways to convert JPG to PDF using PowerShell, from the simplest no-install method to more powerful approaches using third-party libraries. I’ll show you working code for each one and explain what’s happening so you’re not just copying and pasting blind.
Let’s get into it.
What You Need Before You Start
Before running any of the scripts below, just make sure:
- You’re on Windows 10 or Windows 11 (most methods rely on built-in Windows features)
- You have PowerShell 5.1 or PowerShell 7+ installed
- You have the JPG files you want to convert saved somewhere accessible
- For the library-based methods, you’ll need to download a DLL file (I’ll show you exactly where)
Method 1: Using Microsoft Print to PDF (No Install Required)
This is hands down the easiest method. Windows ships with a built-in virtual printer called Microsoft Print to PDF, and you can use it from PowerShell to convert JPG files without installing anything.
Here’s how it works: you configure the PDF printer to output to a specific file path, then “print” the JPG to it. Windows handles the rest.
Step 1 – Set the output port on the Microsoft Print to PDF printer:
$OutputPDF = "C:\Output\photo.pdf"
# Set the printer port to write directly to a file path
Add-PrinterPort -Name $OutputPDF
Set-Printer -Name "Microsoft Print to PDF" -PortName $OutputPDF
Step 2 – Print the JPG to the PDF printer:
$JPGFile = "C:\Images\photo.jpg"
Start-Process -FilePath $JPGFile -Verb PrintTo -ArgumentList "Microsoft Print to PDF"
Start-Sleep -Seconds 3
Step 3 – Clean up the printer port after you’re done:
Remove-PrinterPort -Name $OutputPDF
The Start-Sleep gives the print job time to finish before the script moves on. If you’re converting large images, bump that up to 5 seconds.
To batch convert a whole folder of JPGs:
$InputFolder = "C:\Images"
$OutputFolder = "C:\Output"
Get-ChildItem -Path $InputFolder -Filter "*.jpg" | ForEach-Object {
$OutputPDF = Join-Path -Path $OutputFolder -ChildPath "$($_.BaseName).pdf"
Add-PrinterPort -Name $OutputPDF
Set-Printer -Name "Microsoft Print to PDF" -PortName $OutputPDF
Start-Process -FilePath $_.FullName -Verb PrintTo -ArgumentList "Microsoft Print to PDF"
Start-Sleep -Seconds 3
Remove-PrinterPort -Name $OutputPDF
}
Write-Host "All done! PDFs saved to $OutputFolder"
This loops through every .jpg in the folder, creates a matching PDF with the same base filename, and saves it to your output folder. Pretty neat for something that needs zero extra software.
Pros:
- No downloads or installs
- Works on any modern Windows machine
Cons:
- Slightly slow (due to the sleep timer)
- The page size depends on the printer’s default settings — you don’t control margins tightly
Check out PowerShell Convert HTML to Plain Text
Method 2: Using the iTextSharp Library
If you need more control — like fitting the image exactly to the page size, no white margins, no cropping — iTextSharp is a great option. It’s a popular .NET PDF library that PowerShell can load directly.
Step 1 – Download the iTextSharp DLL:
Go to NuGet.org, search for iTextSharp, and download the package. Or use this direct approach: download the .nupkg file and rename it to .zip, then extract it. Grab the itextsharp.dll file from inside the lib folder and place it somewhere like C:\Tools\itextsharp.dll.
Step 2 – Convert a single JPG to PDF:
# Load the iTextSharp library
[System.Reflection.Assembly]::LoadFrom("C:\Tools\itextsharp.dll") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
$InputJPG = "C:\Images\photo.jpg"
$OutputPDF = "C:\Output\photo.pdf"
# Get the image dimensions so the PDF page matches exactly
$bitmap = New-Object System.Drawing.Bitmap($InputJPG)
$imgWidth = $bitmap.Width
$imgHeight = $bitmap.Height
$bitmap.Dispose()
# Create a PDF document sized to match the image
$pageSize = New-Object iTextSharp.text.Rectangle($imgWidth, $imgHeight)
$document = New-Object iTextSharp.text.Document($pageSize, 0, 0, 0, 0)
$stream = New-Object System.IO.FileStream($OutputPDF, [System.IO.FileMode]::Create)
[iTextSharp.text.pdf.PdfWriter]::GetInstance($document, $stream) | Out-Null
$document.Open()
$image = [iTextSharp.text.Image]::GetInstance($InputJPG)
$image.SetAbsolutePosition(0, 0)
$image.ScaleToFit($imgWidth, $imgHeight)
$document.Add($image) | Out-Null
$document.Close()
$stream.Close()
Write-Host "PDF created at: $OutputPDF"
The key thing here is $pageSize = New-Object iTextSharp.text.Rectangle($imgWidth, $imgHeight) — this creates a PDF page that matches the JPG dimensions exactly. No blank margins, no squished image.
Step 3 – Batch convert a folder:
[System.Reflection.Assembly]::LoadFrom("C:\Tools\itextsharp.dll") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
$InputFolder = "C:\Images"
$OutputFolder = "C:\Output"
Get-ChildItem -Path $InputFolder -Filter "*.jpg" | ForEach-Object {
$InputJPG = $_.FullName
$OutputPDF = Join-Path $OutputFolder "$($_.BaseName).pdf"
$bitmap = New-Object System.Drawing.Bitmap($InputJPG)
$imgWidth = $bitmap.Width
$imgHeight = $bitmap.Height
$bitmap.Dispose()
$pageSize = New-Object iTextSharp.text.Rectangle($imgWidth, $imgHeight)
$document = New-Object iTextSharp.text.Document($pageSize, 0, 0, 0, 0)
$stream = New-Object System.IO.FileStream($OutputPDF, [System.IO.FileMode]::Create)
[iTextSharp.text.pdf.PdfWriter]::GetInstance($document, $stream) | Out-Null
$document.Open()
$image = [iTextSharp.text.Image]::GetInstance($InputJPG)
$image.SetAbsolutePosition(0, 0)
$image.ScaleToFit($imgWidth, $imgHeight)
$document.Add($image) | Out-Null
$document.Close()
$stream.Close()
Write-Host "Converted: $($_.Name)"
}
Write-Host "Batch conversion complete."Pros:
- Pixel-perfect output — page size matches the image
- Very fast for large batches
- Free and open-source
Cons:
- You need to manually download the DLL
- Requires a bit of setup the first time
Read How to Convert XML to Table in PowerShell
Method 3: Using PdfSharp Library
PdfSharp is another lightweight .NET library that works similarly to iTextSharp. Some people prefer it because it’s fully open-source and has slightly simpler syntax for image drawing.
Step 1 – Get the PdfSharp DLL:
Download it from NuGet (PdfSharp package), extract the .nupkg as a zip, and grab PdfSharp.dll from the lib folder. Place it at C:\Tools\PdfSharp.dll.
Step 2 – Convert a single JPG:
Add-Type -Path "C:\Tools\PdfSharp.dll"
$InputJPG = "C:\Images\photo.jpg"
$OutputPDF = "C:\Output\photo.pdf"
# Create a new PDF document
$doc = New-Object PdfSharp.Pdf.PdfDocument
$page = $doc.AddPage()
# Load the image and size the page to match
$xImage = [PdfSharp.Drawing.XImage]::FromFile($InputJPG)
$page.Width = $xImage.PointWidth
$page.Height = $xImage.PointHeight
# Draw the image on the page
$gfx = [PdfSharp.Drawing.XGraphics]::FromPdfPage($page)
$gfx.DrawImage($xImage, 0, 0, $page.Width, $page.Height)
$doc.Save($OutputPDF)
$doc.Close()
Write-Host "PDF saved: $OutputPDF"
Step 3 – Batch convert:
Add-Type -Path "C:\Tools\PdfSharp.dll"
$InputFolder = "C:\Images"
$OutputFolder = "C:\Output"
Get-ChildItem -Path $InputFolder -Filter "*.jpg" | ForEach-Object {
$InputJPG = $_.FullName
$OutputPDF = Join-Path $OutputFolder "$($_.BaseName).pdf"
$doc = New-Object PdfSharp.Pdf.PdfDocument
$page = $doc.AddPage()
$xImage = [PdfSharp.Drawing.XImage]::FromFile($InputJPG)
$page.Width = $xImage.PointWidth
$page.Height = $xImage.PointHeight
$gfx = [PdfSharp.Drawing.XGraphics]::FromPdfPage($page)
$gfx.DrawImage($xImage, 0, 0, $page.Width, $page.Height)
$doc.Save($OutputPDF)
$doc.Close()
Write-Host "Done: $($_.Name)"
}
Pros:
- Clean, readable syntax
- Good for embedding images in exact pixel dimensions
- Works great for single-image-per-PDF scenarios
Cons:
- Same DLL download requirement as iTextSharp
- Not ideal if you need to combine multiple images into one PDF (more code needed)
Check out PowerShell Convert Double to Int
Method 4: Combine Multiple JPGs Into One PDF
Sometimes you don’t want one PDF per image — you want all your JPGs merged into a single multi-page PDF. Here’s how to do that using iTextSharp:
[System.Reflection.Assembly]::LoadFrom("C:\Tools\itextsharp.dll") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
$InputFolder = "C:\Images"
$OutputPDF = "C:\Output\combined.pdf"
$images = Get-ChildItem -Path $InputFolder -Filter "*.jpg" | Sort-Object Name
# Use the first image's dimensions to set the initial page size
$firstBitmap = New-Object System.Drawing.Bitmap($images[0].FullName)
$initPageSize = New-Object iTextSharp.text.Rectangle($firstBitmap.Width, $firstBitmap.Height)
$firstBitmap.Dispose()
$document = New-Object iTextSharp.text.Document($initPageSize, 0, 0, 0, 0)
$stream = New-Object System.IO.FileStream($OutputPDF, [System.IO.FileMode]::Create)
[iTextSharp.text.pdf.PdfWriter]::GetInstance($document, $stream) | Out-Null
$document.Open()
foreach ($imgFile in $images) {
$bitmap = New-Object System.Drawing.Bitmap($imgFile.FullName)
$imgWidth = $bitmap.Width
$imgHeight = $bitmap.Height
$bitmap.Dispose()
$document.SetPageSize((New-Object iTextSharp.text.Rectangle($imgWidth, $imgHeight)))
$document.NewPage()
$image = [iTextSharp.text.Image]::GetInstance($imgFile.FullName)
$image.SetAbsolutePosition(0, 0)
$image.ScaleToFit($imgWidth, $imgHeight)
$document.Add($image) | Out-Null
Write-Host "Added: $($imgFile.Name)"
}
$document.Close()
$stream.Close()
Write-Host "Combined PDF saved to: $OutputPDF"This script sorts your images by filename (so the order is predictable), then adds each one as a new page in a single PDF. Each page automatically resizes to match the dimensions of that specific image.
Check out PowerShell Convert Time to Seconds
Which Method Should You Use?
Here’s a quick guide to help you pick:
| Scenario | Best Method |
|---|---|
| Quick one-off conversion, no installs | Method 1 (Microsoft Print to PDF) |
| Pixel-perfect single or batch conversion | Method 2 (iTextSharp) |
| Simple batch with clean code | Method 3 (PdfSharp) |
| Merge all JPGs into one PDF file | Method 4 (iTextSharp multi-page) |
Common Errors and Quick Fixes
“Add-PrinterPort: Access Denied”
Run PowerShell as Administrator. The print spooler cmdlets need elevated permissions.
“Could not load file or assembly ‘itextsharp.dll'”
Double-check the path in your LoadFrom() call. Make sure you’re pointing to the correct .dll file and not the .nupkg package file.
PDFs are coming out blank
This usually happens with Method 1 when the sleep time isn’t long enough. Increase Start-Sleep -Seconds 3 to 5 or 7 and try again.
Images look stretched or cropped
In iTextSharp, make sure you’re using ScaleToFit() and setting the page size to match the image dimensions. Skipping either of those steps causes layout issues.
“Access to the path is denied” when saving
Make sure your output folder actually exists before running the script. Add this line before the conversion loop: if (!(Test-Path $OutputFolder)) { New-Item -ItemType Directory -Path $OutputFolder | Out-Null }
Check out PowerShell: Convert Array of Objects to Array of Strings
Important Things to Keep in Mind
- Always run PowerShell as Administrator when using printer-related cmdlets
- For large batches (500+ files), Method 2 or 3 will be significantly faster than Method 1
- When naming your output files, using
$_.BaseNamekeeps things clean — it takes the original filename and just swaps the extension - If you’re processing images that come from a scanner (like scanned invoices), sorting them by
LastWriteTimeinstead ofNamekeeps them in the order they were scanned
Wrapping Up
Converting JPG to PDF in PowerShell isn’t one of those things that’s immediately obvious, but once you know the tools available — the built-in print-to-PDF path, iTextSharp, and PdfSharp — it’s actually pretty straightforward.
Method 1 gets you up and running in two minutes with no downloads. Methods 2 and 3 give you proper programmatic control for anything more serious. And Method 4 solves the “combine everything into one file” problem cleanly.
Pick the one that fits your situation, customize the file paths, and you’re good to go.
You may also like the following tutorials:
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.