欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript提取PDF圖片的方法詳解

 更新時(shí)間:2025年03月13日 09:26:49   作者:NeoYu  
這篇文章主要為大家詳細(xì)介紹了如何使用JavaScript提取 PDF 圖片,即把每一頁(yè)里的多張圖片都提取出來(lái),不是把一整頁(yè)都轉(zhuǎn)換為一張圖片,感興趣的可以了解下

提取 PDF 圖片,是指把每一頁(yè)里的多張圖片都提取出來(lái),不是把一整頁(yè)都轉(zhuǎn)換為一張圖片 ^_^ 。

效果 

技術(shù)實(shí)現(xiàn)詳解 

使用 PDF.js 解析和渲染 PDFs,在 github 上有 43.9kb Star,非常成熟。

一、 引入 pdf.js

需要同時(shí)引入 pdf.js 和 WebWorker,其中 WebWorker 在瀏覽器子線程解析圖片等資源,不阻塞頁(yè)面UI和交互。引入代碼如下:

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.10.111/pdf.js"></script>

<script>
// pdf.js 從性能考慮,使用了 WebWorker, 在瀏覽器子線程解析圖片等資源,不阻塞頁(yè)面UI和交互。
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.10.111/build/pdf.worker.js';
</script>

二、上傳 PDF 文件并監(jiān)聽(tīng)

上傳文件時(shí),使用 FileReader 異步文件讀取對(duì)象,讀取之后轉(zhuǎn)換為 Uint8Array,傳入 pdfjsLib,得到 PDF 加載任務(wù)。

代碼如下:

<input type="file" id="fileInput" name="avatar" title ="選擇 pdf 文件"/>

<script>
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener(
  "change",
  () => {
    const file = fileInput.files[0];
    console.log('fileInput file: ', file);
    // 上傳文件時(shí),使用 FileReader 對(duì)象讀取
    var fileReader = new FileReader();
    fileReader.onload = function() {
          // 將文件對(duì)象轉(zhuǎn)化為 Uint8Array 
          var typedarray = new Uint8Array(this.result);
          // 返回 PDF 加載任務(wù) PDFDocumentLoadingTask
          const loadingTask = pdfjsLib.getDocument(typedarray);
          // 開(kāi)始加載 PDF,這里封裝了一個(gè)函數(shù)
          loadPDFFile(loadingTask);
    };

    fileReader.readAsArrayBuffer(file);
  },
  false
);
</script>

三、獲取和遍歷 PDF 頁(yè)數(shù)

async function loadPDFFile(loadingTask) {
  // PDF 加載任務(wù)
  const pdf = await loadingTask.promise;
  // 獲取 PDF 頁(yè)數(shù)
  const numPages = pdf.numPages;
  for (let curPage = 1; curPage <= numPages; curPage++) {
    // 返回當(dāng)前頁(yè)
    console.log('loadingServerFile curPage: ', curPage);
    const page = await pdf.getPage(curPage);

    const scale = 1.5;
    // 獲取渲染視角尺寸
    const viewport = page.getViewport({ scale });
    // Support HiDPI-screens.
    const outputScale = window.devicePixelRatio || 1;
    // 傳入離屏 Canvas
    const canvas = new OffscreenCanvas(200, 200);
    // 獲取 Canvas 上下文
    const context = canvas.getContext("2d");
    // 轉(zhuǎn)換尺寸
    const transform = outputScale !== 1 
      ? [outputScale, 0, 0, outputScale, 0, 0] 
      : null;

    const renderContext = {
      canvasContext: context,
      transform,
      viewport,
    };
    // 調(diào)用 page.render 觸發(fā)渲染
    const renderTask = page.render(renderContext);
    // 等待 renderTask 渲染任務(wù)
    // await delay(500); // 如果渲染過(guò)快,可能導(dǎo)致 CPU 飆升、電腦可用內(nèi)存不夠,可以加延遲減慢速度
    await renderTask.promise;
  }
}

代碼里使用 OffscreenCanvas,提供了一個(gè)可以脫離屏幕渲染的 canvas 對(duì)象,在主線程和子線程 (web worker) 都可以使用,是為了性能優(yōu)化,提取 PDF 圖片不用渲染到頁(yè)面,但也要渲染任務(wù)

如果渲染過(guò)快,可能導(dǎo)致 CPU 飆升、電腦可用內(nèi)存不夠,可以加延遲 setTimeout 減慢速度

四、提取每頁(yè) PDF 的圖片

在這一步,我們獲取了 pdfjs 提取的 PDF 圖片,是 ImageBitmap 格式,它是對(duì) Canvas 上位圖數(shù)據(jù)的引用,存儲(chǔ)在 GPU 中,可以在 web worker 進(jìn)行生成,從而避免影響主線程繪制 UI,也避免阻塞響應(yīng)用戶(hù)交互。

代碼如下:

async function loadPDFFile(loadingTask) {
    // ...接上一步
    const renderTask = page.render(renderContext);
    // 等待當(dāng)前頁(yè)渲染任務(wù)執(zhí)行
    await renderTask.promise;
    // 獲取操作列表
    const ops = await page.getOperatorList();

    // 提取圖片
    const imageNames = ops.fnArray.reduce((acc, curr, i) => {
      if ([pdfjsLib.OPS.paintImageXObject, pdfjsLib.OPS.paintJpegXObject].includes(curr)) {
        acc.push(ops.argsArray[i][0]);
      }
      return acc;
    }, []);
    for (const imageName of imageNames) {
      console.log('imageName: ', imageName);
      page.objs.get(imageName, (image) => {
        // console.log('image: ', image);
        (async function() {          
          const bmp = image.bitmap;
          // create a canvas
          console.log('bmp: ', bmp);
        })();      
      });
    }
}

五、ImageBitmap 轉(zhuǎn)化為 Img

再堅(jiān)持一下,最后一步啦!─=≡Σ(((つ•?ω•?)つ

在上一步中,我們獲取了在 Canvas 繪圖的引用 ImageBitmap,我們需要轉(zhuǎn)換為瀏覽器下的 Img 圖片。

具體過(guò)程:先將 ImageBitmap 渲染到 Canvas,調(diào)用 canvas.convertToBlob 就能得到 Blob 對(duì)象。

async function loadPDFFile(loadingTask) {
    // ...接上一步,拿到了每頁(yè) PDF 的 image.bitmap 對(duì)象
    for (const imageName of imageNames) {
      console.log('imageName: ', imageName);
      page.objs.get(imageName, (image) => {
        // console.log('image: ', image);
        (async function() {          
            const bmp = image.bitmap;
            console.log('bmp: ', bmp);
            // OffscreenCanvas
            const resizeScale = 1/4; // 這個(gè)可以控制轉(zhuǎn)換后的圖片大小
            const width = bmp.width * resizeScale;
            const height = bmp.height * resizeScale;
            const canvas = new OffscreenCanvas(width, height);
            // 獲取 canvas bitmaprenderer 上下文
            const ctx = canvas.getContext('bitmaprenderer');
            // 把 ImageBitmap 渲染到 OffscreenCanvas
            ctx.transferFromImageBitmap(bmp);
            // 把 canvas 畫(huà)布轉(zhuǎn)化為 Blob 對(duì)象
            // https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas/convertToBlob
            const blob = await canvas.convertToBlob();
            console.log('blob: ', blob); // blob
            // 最后使用 Blob 作為 URL.createObjectURL 的參數(shù),渲染出 img 圖片
            // 如果不需要渲染,則可以講 Blob 數(shù)據(jù)上傳到云存儲(chǔ)
            const img = document.body.appendChild(new Image());
            img.width = width;
            img.height = height;
            img.src = URL.createObjectURL(blob);
        })();      
      });
    }
}

OffscreenCanvas 可以放在 Web Worker 中創(chuàng)建,從而不阻塞主線程的UI繪制和交互響應(yīng)。

bitmaprenderer.transferFromImageBitmap 可以實(shí)現(xiàn)不拷貝數(shù)據(jù),只傳遞地址的方式,把 ImageBitmap 傳遞到 Canvas 上。

背景(緣起)

前段時(shí)間遇到 從 PDF 中提取圖片用于 評(píng)論、審核 的功能。

由于項(xiàng)目時(shí)間趕、任務(wù)重,由后端實(shí)現(xiàn)了一頁(yè) PDF 轉(zhuǎn)換為一張圖片。

后端提取優(yōu)劣:

  • 優(yōu): 用戶(hù)體驗(yàn)好,不影響用戶(hù)電腦性能
  • 劣:加大服務(wù)器壓力
    • 占用大量CPU資源,在我Mac筆記本MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports) 解析時(shí),能看到 CPU 每次都飆到 100% 以上
    • 占用大量?jī)?nèi)存,解析后的圖片,在上傳到 CDN 以前,放在服務(wù)器沒(méi)有釋放
    提取流程變長(zhǎng)
    • 需要把 PDF 文件上傳到服務(wù)器,由后端處理

前端提取優(yōu)劣:

  • 優(yōu): 不占用服務(wù)器資源,在瀏覽器端就能完成提取。
  • 劣: 可能會(huì)引起用戶(hù)電腦卡頓。

以上就是JavaScript提取PDF圖片的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript提取PDF圖片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論