前端開發者收到一份 40 頁的品牌規範 PDF,需要把其中三頁放進 Figma。支援工程師想從規格書貼一張圖到 Slack。律師需要把簽好的合約某一頁附加在郵件裡,但不想寄出整份檔案。
PDF 是為固定版式文件設計的,而網頁、圖片編輯器與聊天軟體則是以像素為基礎。把 PDF 頁面轉成圖片可以彌補這段落差,但選擇的方法會影響輸出品質、檔案大小以及你保留多少控制權。
PDF 在這件事上既好用又麻煩的原因
PDF 把頁面儲存為一連串繪圖指令:在這裡放這個字形、畫這個向量、在這個尺寸渲染這張圖片。這讓它具備解析度獨立性與視覺一致性,也代表 PDF 本身不是圖片。要轉成圖片,就必須有東西把這些指令渲染到點陣畫布上。
優點:
- 文字與向量在任何縮放比例下都保持銳利,因為它們是以數學方式描述,而非以像素儲存。
- 單一 PDF 可以容納數百頁。
- 字型、色彩設定檔與註解會隨文件一起攜帶。
缺點:
- 不同 PDF 閱讀器的渲染結果不一致。同一頁在 Adobe Acrobat、Preview、Chrome 或無頭函式庫中可能看起來略有差異。
- 掃描件 PDF 只是包在 PDF 容器裡的圖片,所以「轉換」它們其實是重新編碼,可能產生壓縮瑕疵或讓檔案變大。
- 帶有透明、圖層或互動式表單的複雜 PDF,在壓平時可能出現預期外的結果。
- 頁面尺寸不固定。US Letter 頁面在 72 DPI 下是 612 × 792 像素,在 300 DPI 下則是 2550 × 3300。如果沒有指定解析度,輸出可能無法使用。
大家實際上把 PDF 轉成什麼
大多數轉換任務可歸類為三種輸出格式之一,各自有不同的用途。
| 格式 | 最適合 | 取捨 |
|---|---|---|
| JPG | 照片、預覽圖、郵件附件、網路圖庫 | 有損壓縮,但檔案小 |
| PNG | 截圖、圖表、需要透明的情境 | 無損壓縮,照片比 JPG 大 |
| WebP | 現代網頁、應用程式、任何頻寬敏感的情境 | 比 JPG/PNG 更小,支援度略低 |
還有幾個實務上的維度:
- 單頁或批次。 單頁很簡單;一整批發票則需要自動化。
- DPI。 150 DPI 對縮圖來說足夠;300 DPI 是列印與 OCR 的標準;600 DPI 除非要放大檢視細節,否則過剩。
- 色彩空間。 RGB 對螢幕來說安全;CMYK PDF 若用簡陋方式轉成 RGB,顏色可能會偏移。
選擇合適的做法
正確的工具取決於你想優化什麼。
快速的瀏覽器端轉換
如果你只需要把一頁轉成 JPG、PNG 或 WebP,而且檔案不至於敏感到必須留在伺服器上,那麼瀏覽器端轉換是最快的路徑。我們的 PDF 轉 JPG、PDF 轉 PNG 與 PDF 轉 WebP 工具會在本地渲染 PDF。檔案不會離開你的裝置,這對合約、證件與病歷來說很重要。
命令列批次處理
面對一整批 PDF 或 CI 流程時,命令列工具勝出。你可以得到可重複的輸出、控制 DPI,並能編寫腳本。
應用程式內轉換
當轉換是產品的一部分時,直接呼叫函式庫通常比呼叫外部 CLI 更乾淨。這能減少外部依賴,並讓錯誤處理與程式碼庫的其他部分保持一致。
在 Windows 上轉換
Adobe Acrobat
- 開啟 PDF 並前往所需頁面。
- 選擇 檔案 > 匯出為 > 影像 > JPEG/PNG/TIFF。
- 在匯出對話方塊中設定輸出解析度。
- 儲存。
Acrobat 的輸出穩定,但它不是免費軟體,而且沒有付費 SDK 就無法編寫腳本。
PDF-XChange Editor
較輕量的替代方案,有免費版。檔案 > 匯出 > 匯出頁面為影像 可讓你選擇格式、DPI 與頁面範圍。
在 PowerShell 中使用 pdftoppm
在 Windows 上安裝 Poppler 後,即可從 PowerShell 使用 pdftoppm:
pdftoppm -jpeg -r 300 input.pdf output
這會產生 output-1.jpg、output-2.jpg 等檔案,每頁一張,解析度為 300 DPI。
若要輸出帶透明背景的 PNG:
pdftoppm -png -r 300 input.pdf output
若只要單一頁面:
pdftoppm -jpeg -r 300 -f 1 -l 1 input.pdf output
-f 與 -l 旗標分別設定起始頁與結束頁。
在 PowerShell 中使用 ImageMagick
ImageMagick 可以渲染 PDF,但在 Windows 上通常會在背後交給 Ghostscript 處理:
magick -density 300 input.pdf[0] output.jpg
[0] 表示第一頁。如果沒有加,ImageMagick 可能會嘗試產生多幀影像。
在 macOS 上轉換
Preview
- 在 Preview 中開啟 PDF。
- 選取你要的頁面縮圖。
- 選擇 檔案 > 匯出,挑選格式並設定解析度。
Preview 快速且注重隱私,但一次只能處理一頁。
在終端機中使用 sips
macOS 內建 sips,但它對 PDF 文字渲染不佳。只建議用於已經是點陣圖的 PDF:
sips -s format jpeg input.pdf --out output.jpg
若要真正渲染 PDF,請透過 Homebrew 安裝 Poppler:
brew install poppler
pdftoppm -jpeg -r 300 input.pdf output
Automator 快速動作
你可以在 Automator 中建立一個右鍵服務,對任何選取的 PDF 執行 pdftoppm。如果你經常需要轉換頁面,又不希望每次都記住旗標,這會很有用。
在 Linux 上轉換
Poppler 通常是 Linux 上的最佳選擇。
sudo apt install poppler-utils
pdftoppm -jpeg -r 300 input.pdf output
pdftoppm -png -r 300 input.pdf output
若要輸出 WebP,可以先轉成 PNG,再用 cwebp:
pdftoppm -png -r 300 input.pdf temp
cwebp temp-1.png -o output.webp
批次轉換
如果你有一整個資料夾的 PDF,想要每份檔案各輸出第一頁圖片:
for f in *.pdf; do
pdftoppm -jpeg -r 300 -f 1 -l 1 "$f" "${f%.pdf}"
done
ImageMagick
ImageMagick 在 Linux 上也能用,但對 PDF 通常較慢,因為它會透過 Ghostscript 進行點陣化:
magick -density 300 input.pdf[0] -quality 90 output.jpg
-density 必須放在讀取 PDF 之前,放在後面沒有效果。
使用程式碼轉換
TypeScript / Node.js
使用 pdfjs-dist 把頁面渲染到 canvas,再匯出為圖片資料。
import * as pdfjsLib from "pdfjs-dist"
import { createCanvas } from "canvas"
import fs from "fs"
async function pdfPageToPng(
pdfPath: string,
pageNumber: number,
outputPath: string,
scale: number = 2
) {
const data = new Uint8Array(fs.readFileSync(pdfPath))
const pdf = await pdfjsLib.getDocument({ data }).promise
const page = await pdf.getPage(pageNumber)
const viewport = page.getViewport({ scale })
const canvas = createCanvas(viewport.width, viewport.height)
const context = canvas.getContext("2d")
await page.render({ canvasContext: context, viewport }).promise
const buffer = canvas.toBuffer("image/png")
fs.writeFileSync(outputPath, buffer)
await pdf.destroy()
}
await pdfPageToPng("input.pdf", 1, "output.png", 2)
scale 值大致對應 DPI:在 72 DPI 下,scale 為 2 會得到 144 DPI 的輸出。若要 300 DPI,scale 約為 4.17。
在瀏覽器中,我們的 PDF 轉 PNG 轉換器會執行相同的 render-to-canvas 步驟,且不會把檔案傳送到任何地方。
PHP
PHP 可以直接呼叫 pdftoppm,或使用 spatie/pdf-to-image 這類包裝 ImageMagick 的函式庫:
<?php
use Spatie\PdfToImage\Pdf;
$pdf = new Pdf('input.pdf');
$pdf->setPage(1)
->setOutputFormat('png')
->saveImage('output.png');
如果你不想增加依賴,可以直接呼叫 Poppler:
<?php
function pdfPageToPng(string $input, int $page, string $output, int $dpi = 300): void {
$cmd = sprintf(
'pdftoppm -png -r %d -f %d -l %d %s %s',
$dpi,
$page,
$page,
escapeshellarg($input),
escapeshellarg($output)
);
exec($cmd);
}
pdfPageToPng('input.pdf', 1, 'output', 300);
這會寫入 output-1.png。在正式環境使用前,請補上你自己的錯誤檢查。
Go
Go 沒有內建 PDF 渲染器,但 github.com/gen2brain/go-fitz 包裝了 MuPDF:
package main
import (
"image/jpeg"
"os"
"github.com/gen2brain/go-fitz"
)
func main() {
doc, err := fitz.New("input.pdf")
if err != nil {
panic(err)
}
defer doc.Close()
img, err := doc.Image(0)
if err != nil {
panic(err)
}
out, err := os.Create("output.jpg")
if err != nil {
panic(err)
}
defer out.Close()
if err := jpeg.Encode(out, img, &jpeg.Options{Quality: 90}); err != nil {
panic(err)
}
}
go-fitz 會以 PDF 的預設渲染解析度回傳圖片。若需要控制 DPI,請查閱該函式庫的文件。
Java
Apache PDFBox 是 Java PDF 處理的標準選擇。
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class PdfToImage {
public static void main(String[] args) throws IOException {
try (PDDocument document = PDDocument.load(new File("input.pdf"))) {
PDFRenderer renderer = new PDFRenderer(document);
BufferedImage image = renderer.renderImageWithDPI(0, 300);
ImageIO.write(image, "png", new File("output.png"));
}
}
}
Maven 依賴:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.2</version>
</dependency>
renderImageWithDPI 接受以零為底的頁面索引與 DPI 值。
Python
Python 透過 pymupdf 或 pdf2image 可以輕鬆完成。
使用 pymupdf:
import fitz
doc = fitz.open("input.pdf")
page = doc[0]
mat = fitz.Matrix(2, 2)
pix = page.get_pixmap(matrix=mat)
pix.save("output.png")
Matrix 控制縮放比例。若要從 72 DPI 的 PDF 得到約 300 DPI 的輸出,請使用 fitz.Matrix(300/72, 300/72)。
使用包裝 Poppler 的 pdf2image:
from pdf2image import convert_from_path
images = convert_from_path("input.pdf", dpi=300, first_page=1, last_page=1)
images[0].save("output.jpg", "JPEG", quality=90)
pdf2image 很方便,但系統必須已安裝 Poppler。
常見陷阱
- 忘記設定 DPI。 PDF 預設渲染解析度常是 72 或 96 DPI,文字看起來會模糊。如果品質重要,請務必指定輸出 DPI。
- 忽略色彩空間。 CMYK PDF 若不用適當設定檔就轉成 RGB,可能會看起來偏淡或過度飽和。
- 重新編碼掃描件 PDF。 如果 PDF 本身已經是 JPEG 掃描件,轉成 PNG 不會挽回遺失的細節,只會讓檔案變大。
- 字型替代。 無頭伺服器有時缺少 PDF 內嵌的字型,渲染器會用替代字型,導致版面跑掉。在建立 PDF 時內嵌字型可避免這個問題。
- 頁面編號差一。 程式 API 通常使用以零為底的頁面索引;命令列工具通常使用以一為底。
不同情境該用什麼
- 一次性個人使用: macOS 的 Preview、Windows 上的 PDF 閱讀器,或瀏覽器轉換工具。
- 伺服器上的批次處理:
pdftoppm或pdf2image。 - 產品內部整合: Java 用 Apache PDFBox、Python 用
pymupdf、TypeScript 用pdfjs-dist。 - 隱私敏感檔案: 使用瀏覽器端工具,讓 PDF 不會離開裝置。
如果你想完全不安裝任何東西就完成轉換,我們的 PDF 轉 JPG、PDF 轉 PNG 與 PDF 轉 WebP 轉換器全部在瀏覽器中執行。



