文件 1.1.0

轉換流程

本頁說明 convert() 如何把 PDF 頁面渲染成圖片,以及解析度、輸出格式與失敗時的實際行為。

流程

  1. 設定 pdfjsLib.GlobalWorkerOptions.workerSrc 為 cdnjs 上的 pdf.worker.js
  2. 以 getDocument() 解析 file,CMap 從 cdnjs 取得(處理 CJK 等字型編碼)
  3. 解析成功後在 <body> 附加進度遮罩
  4. 所有頁面同時建立 canvas 並渲染,每完成一頁就把 Data URL 推入結果陣列並更新進度
  5. 全部完成後延遲 500ms,resolve 結果陣列並移除遮罩

解析度:scale

輸出像素尺寸 = PDF 頁面尺寸(pt)× scale。預設 1.5;US Letter(612×792 pt)在 scale: 1 時輸出 612×792,在預設值時輸出 918×1188。

<script>
  const sample = async () => (await fetch("/assets/sample.pdf")).arrayBuffer();
  const size = src => new Promise(r => {
    const img = new Image();
    img.onload = () => r(img.width + "x" + img.height);
    img.src = src;
  });
  addEventListener("load", async () => {
    for (const scale of [0.5, 1, 1.5]) {
      const [first] = await new pdf2image({ file: await sample(), type: "png", scale }).convert();
      console.log("scale", scale, "->", await size(first));
    }
  });
</script>
即時預覽 · @pardnchiu/pdf2image@1.1.2

輸出格式:type

type 只接受 png、jpg、webp,其他值回退為 jpg。結果由 canvas.toDataURL("image/" + type) 產生,因此:

type 傳給 toDataURL 實際輸出
png image/png PNG
webp image/webp WebP(瀏覽器不支援時為 PNG)
jpg(預設) image/jpg PNG:瀏覽器只認 image/jpeg,不認得的 MIME 一律回退 PNG

也就是說,目前版本無法輸出 JPEG,預設值實際得到的是 PNG。

<script>
  addEventListener("load", async () => {
    for (const type of ["png", "jpg", "webp", "gif"]) {
      const buffer = await (await fetch("/assets/sample.pdf")).arrayBuffer();
      const [first] = await new pdf2image({ file: buffer, type, scale: 0.5 }).convert();
      console.log(type.padEnd(4), "->", first.slice(0, first.indexOf(";")));
    }
  });
</script>
即時預覽 · @pardnchiu/pdf2image@1.1.2

結果順序

頁面是併發渲染,結果在「每頁完成時」依序推入陣列,而非依頁碼寫入對應位置。頁面複雜度差異大時,images[0] 不保證是第 1 頁。

file 只能用一次

pdf.js 會把傳入的 ArrayBuffer 轉移(transfer)給 worker,轉換後原 buffer 的 byteLength 變成 0。因此:

<script>
  addEventListener("load", async () => {
    const buffer = await (await fetch("/assets/sample.pdf")).arrayBuffer();
    const converter = new pdf2image({ file: buffer, type: "png", scale: 0.5 });
    console.log("first:", (await converter.convert()).length, "pages");
    console.log("buffer byteLength:", buffer.byteLength);
    try {
      await converter.convert();
    } catch (err) {
      console.log("second:", String(err));
    }
    console.log("images kept:", converter.images.length);
  });
</script>
即時預覽 · @pardnchiu/pdf2image@1.1.2

失敗行為

情境 reject 的值
未提供 file 字串 "error The PDF file is empty, i.e. its size is zero bytes."
不是有效的 PDF 字串 "error Invalid PDF structure."
頁面渲染失敗 字串 "error i is not defined":錯誤處理引用了不存在的變數,原始錯誤訊息遺失
重複使用已轉移的 buffer TypeError 物件
pdf.js 尚未載入 ReferenceError 物件(見 核心概念)

reject 值有字串也有 Error,以 String(err) 處理可涵蓋兩者。pdf.js 載入失敗時,套件本身也會呼叫 console.error("error", err)。

<script>
  addEventListener("load", async () => {
    const cases = { "no file": {}, "not a pdf": { file: new TextEncoder().encode("hello").buffer } };
    for (const [name, options] of Object.entries(cases)) {
      try {
        await new pdf2image(options).convert();
      } catch (err) {
        console.log(name, "->", typeof err, String(err));
      }
    }
  });
</script>
即時預覽 · @pardnchiu/pdf2image@1.1.2

相關頁面

EN