目錄

廣告 AD

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

又是一個轉換格式的教學紀錄

這次的是把 PDF 轉成圖片

廣告 AD

有時候要上傳檔案到網站,網站上只支援圖片格式,但手上只有 PDF 檔案。

這時候就需要轉換 PDF 成圖片了,這邊提供不同程式語言轉換的方法。

其中最推薦使用 Python,便利性很高。


我找了幾個套件可以轉換 PDF 成圖片,可以選一個來用。


Github - pdf2image

安裝 pdf2image。

cmd

pip install pdf2image

我們設定 DPI 為 300,並將 test.pdf 裡面每一頁的都轉換成圖片。

Python

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')

HomePage - PyMuPDF

安裝 PyMuPDF

cmd

pip install PyMuPDF

與上面一樣,我們設定 DPI 為 300,並將 test.pdf 裡面每一頁的都轉換成圖片。

Python

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')

Github - pdfium-render

Rust 的部分,這裡用的是 pdfium_render,它是 Pdfium 的 Rust interface,所以我們還需要先下載 pdfium 的 dll。


這邊可以去這裡下在對應平台上已編譯好的版本:Github - pdfium-binaries

如果你用的是 Windows 的話,可以下載這個檔案。

Windows 下載版本


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

pdfium-v8-win-x64.tgz


之後我將這個資料夾取名為 pdfium-win-x64,並放置到專案資料夾內,專案資料夾內的結構大概是這樣:

txt

.
├─pdfium-win-x64      
│  ├─bin
│  ├─include
│  └─lib
├─src
├── Cargo.lock
├── Cargo.toml
└── target

之後就可以執行下方的程式了,由於我的資料夾名稱為 pdfium-win-x64,因此程式中我們要連結的函式庫的目錄我們要設定為 pdfium-win-x64\\bin,dpi 的部分我們一樣設定為 300,並將所有頁面轉成圖片。

rust

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(())
}

想說都既然寫了個 Rust 的轉換,又想到 Rust 可以編譯成 WebAssembly 放到瀏覽器上執行,索性就直接繼續研究,將讀取 Pdf 並轉換成圖片的部分和多個圖片壓縮成 zip 檔案的部分一併都用 Rust 寫,剩下簡單寫個前端來呼叫就可以了,整個轉換過程都在瀏覽器中執行,並不會傳到伺服器上,請放心服用,轉換完成後會自動下載,也可以自行設定圖片的 DPI,如果要比較好的畫質可以選擇將 DPI 設為 300,但需要比較久的轉換時間。


DPI:


廣告 AD