How to Convert JPG to PDF Using PowerShell (4 Methods)

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:

ScenarioBest Method
Quick one-off conversion, no installsMethod 1 (Microsoft Print to PDF)
Pixel-perfect single or batch conversionMethod 2 (iTextSharp)
Simple batch with clean codeMethod 3 (PdfSharp)
Merge all JPGs into one PDF fileMethod 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 $_.BaseName keeps 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 LastWriteTime instead of Name keeps 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:

100 PowerShell cmdlets download free

100 POWERSHELL CMDLETS E-BOOK

FREE Download an eBook that contains 100 PowerShell cmdlets with complete script and examples.