轉換 PDF 到圖片:Python & Rust 簡單的方法

又是一個轉換格式的教學紀錄
這次的是把 PDF 轉成圖片
轉換 PDF 成圖片
有時候要上傳檔案到網站,網站上只支援圖片格式,但手上只有 PDF 檔案。
這時候就需要轉換 PDF 成圖片了,這邊提供不同程式語言轉換的方法。
其中最推薦使用 Python,便利性很高。
Python
我找了幾個套件可以轉換 PDF 成圖片,可以選一個來用。
pdf2image
安裝 pdf2image。
pip install pdf2image
我們設定 DPI 為 300,並將 test.pdf 裡面每一頁的都轉換成圖片。
from pdf2image import convert_from_path
pages = convert_from_path('test.pdf', dpi=300)
for count, page in enumerate(pages):
page.save(f'test_{count}.png')
fitz
安裝 PyMuPDF
pip install PyMuPDF
與上面一樣,我們設定 DPI 為 300,並將 test.pdf 裡面每一頁的都轉換成圖片。
import fitz
import io
from PIL import Image
pdf = fitz.open('test.pdf')
for count, page in enumerate(pdf.pages()):
pixmap = page.get_pixmap(dpi=300)
image = Image.open(io.BytesIO(pixmap.tobytes()))
image.save(f'test_{count}.png')
Rust
Rust 的部分,這裡用的是 pdfium_render,它是 Pdfium 的 Rust interface,所以我們還需要先下載 pdfium 的 dll。
這邊可以去這裡下在對應平台上已編譯好的版本:Github - pdfium-binaries。
如果你用的是 Windows 的話,可以下載這個檔案。

Windows 下載版本
tgz 是壓縮檔,要解壓縮後才能使用,解壓縮完後會看到裡面的內容如下。

pdfium-v8-win-x64.tgz
之後我將這個資料夾取名為 pdfium-win-x64
,並放置到專案資料夾內,專案資料夾內的結構大概是這樣:
.
├─pdfium-win-x64
│ ├─bin
│ ├─include
│ └─lib
├─src
├── Cargo.lock
├── Cargo.toml
└── target
之後就可以執行下方的程式了,由於我的資料夾名稱為 pdfium-win-x64
,因此程式中我們要連結的函式庫的目錄我們要設定為 pdfium-win-x64\\bin
,dpi 的部分我們一樣設定為 300,並將所有頁面轉成圖片。
use image::ImageFormat;
use pdfium_render::prelude::*;
pub fn main() -> Result<(), PdfiumError> {
// 讀取函式庫
let bindings = Pdfium::bind_to_library(
Pdfium::pdfium_platform_library_name_at_path("pdfium-win-x64\\bin"),
)
.or_else(
|_| Pdfium::bind_to_system_library(),
)?;
let pdfium = Pdfium::new(bindings);
// 設定轉換的參數
const DPI: i32 = 300;
let render_config = PdfRenderConfig::new()
.scale_page_height_by_factor(DPI as f32 / 72f32)
.scale_page_width_by_factor(DPI as f32 / 72f32);
// 讀取 pdf 檔案並開始轉換
let document = pdfium.load_pdf_from_file("test.pdf", None)?;
for (index, page) in document.pages().iter().enumerate() {
let result = page
.render_with_config(&render_config)?
.as_image()
.to_rgba8()
.save_with_format(format!("test_{}.png", index), ImageFormat::Png);
assert!(result.is_ok());
}
Ok(())
}
自製 Online Converter
想說都既然寫了個 Rust 的轉換,又想到 Rust 可以編譯成 WebAssembly 放到瀏覽器上執行,索性就直接繼續研究,將讀取 Pdf 並轉換成圖片的部分和多個圖片壓縮成 zip 檔案的部分一併都用 Rust 寫,剩下簡單寫個前端來呼叫就可以了,整個轉換過程都在瀏覽器中執行,並不會傳到伺服器上,請放心服用,轉換完成後會自動下載,也可以自行設定圖片的 DPI,如果要比較好的畫質可以選擇將 DPI 設為 300,但需要比較久的轉換時間。
Reference
- https://stackoverflow.com/questions/46184239/extract-a-page-from-a-pdf-as-a-jpeg
- https://stackoverflow.com/questions/14759637/python-pil-bytes-to-image
- https://forum.patagames.com/posts/t549-How-can-i-set-the-Rendering-Resolution–DPI–when-Render-to-Image
- https://github.com/ajrcarey/pdfium-render
- https://github.com/bblanchon/pdfium-binaries
- https://stackoverflow.com/questions/71303643/how-to-convert-a-pdf-to-a-jpg-png-in-python-with-the-highest-possible-quality
- https://pymupdf.io/
- https://github.com/Belval/pdf2image
- https://ithelp.ithome.com.tw/articles/10216858
- https://stackoverflow.com/questions/5587973/javascript-upload-file
- https://stackoverflow.com/questions/72510506/how-to-convert-a-file-object-to-a-url
- https://stackoverflow.com/questions/35038884/download-file-from-bytes-in-javascript
- https://stackoverflow.com/questions/50602006/how-can-i-check-if-stdiocursor-has-unconsumed-data
如果你覺得這篇文章有用 可以考慮贊助飲料給大貓咪