2012-11-06 92 views
0

我想使用PHP,ImageMagick和Imagick(PHP類)來創建PDF的縮略圖。有些PDF只會有一個頁面,有些會有很多。我想指定一個數字(N)的縮略圖來創建,其中一個用於PDF中的前N個頁面。如何使用Imagick,ImageMagick和PHP從PDF創建特定數量的縮略圖?

下面的代碼有效,但是當PDF沒有足夠的頁面時會產生錯誤(因爲我試圖在不存在的PDF頁面上實例化Imagick)。我也知道ImageMagick可以在從命令行使用PDF時爲所有頁面創建縮略圖。我想以最有效的方式(內存和處理器)模仿這種行爲,同時控制創建的拇指數量......我只需要大型PDF中前N頁的縮略圖。

我已經看過各種方法來確定PDF中的頁面數量,它們似乎都是資源密集型的。也許下面的代碼是我最好的選擇。它完成了我的目標,但困擾我,因爲它會導致一些錯誤......即使它們不影響最終結果。

這裏是我的代碼,目前的工作(有錯誤時,PDF比N頁更少):

private function create_thumbnails(
    $num_thumbs = 3  // how many thumbnails to create, defaults to one 
) { 

    echo "\n\n creating thumbnails ... "; 

    $num_thumbs_created = 0; 
    while($num_thumbs_created < $num_thumbs) 
    { 

     try { 

      // instantiate imagick with the pdf 
      $Image = new Imagick($this->file_path_pdf . '[' . $num_thumbs_created . ']'); 

      // define image file 
      $Image->setImageColorspace(255); 
      $Image->setCompression(Imagick::COMPRESSION_JPEG); 
      $Image->setCompressionQuality(60); 
      $Image->setImageFormat('jpg'); 

      // size the thumbnail 
      // - resized relative to 8.5x11 (assuming most pdfs are paper sized) 
      $Image->resizeImage(180, 232, imagick::FILTER_POINT, 1); 

      // save image 
      $Image->writeImage(substr($this->File->path, 0, -4) . '-' . $num_thumbs_created . '.jpg'); 
      $Image->clear(); 

      $num_thumbs_created++; 

     } catch(Exception $e) { 

      echo "\n * failed to create some or all thumbnails: " . $e->getMessage(); 
      break; 

     } 

    } 

    $Image->destroy(); 

    echo "done"; 

} 
+0

你看過poppler庫嗎? http://poppler.freedesktop.org/你必須運行pdfinfo命令,從輸出字符串中提取頁面數量,然後你就可以得到它......有點迂迴,但它會工作。 –

+0

@MAtthew:但在這點上,他可以從cli執行imagemagick並做到這一點。 – prodigitalson

+0

@prodigitalson雖然imagemagick identify命令比poppler的pdfinfo慢得多。我同意它不完全乾淨和直接,但有時候稍候更容易破解cli命令並稍後重構。 –

回答

1

Im相當肯定,如果你打開一個PDF,然後Imagick::getNumberImages會給你的頁面的數量。同樣在這一點上,你可以用magick迭代它們,而不必每頁實例化。所有這些都是基於文檔的猜測。所以你必須測試和找出自己:

private function create_thumbnails($num_thumbs = 3) { 

    echo "\n\n creating thumbnails ... "; 

    try { 
     $Image = new Imagick($this->file_path_pdf); 
     $nbCreated = 0; 
     if($num_thumbs > 0) { 
      foreach($Image as $idx => $im) { 
       if($nbCreated < $num_thumbs) { 
       $im->setImageColorspace(255); 
       $im->setCompression(Imagick::COMPRESSION_JPEG); 
       $im->setCompressionQuality(60); 
       $im->setImageFormat('jpg'); 

       $im->resizeImage(180, 232, imagick::FILTER_POINT, 1); 

       // save image 
       $im->writeImage($idx . '-' . $nbCreated . '.jpg'); 
       $im->clear(); 

       $nbCreated++; 
       } 
       else 
       { 
       break; // pop out of loop we have reach our limit and are done 
       } 
      } 

     } 

     $Image->destroy(); 
    } 
    catch(Exception $e) { 
     echo "\n * failed to create some or all thumbnails: " . $e->getMessage(); 
     $Image->destroy();  
    } 

    echo "done"; 
} 

注意我也改變你有你的嘗試/趕上。如果出現錯誤,IMO最好保釋並停止創建圖像,因爲如果處理單個文件的機會是每次迭代都會出現錯誤,所以它可能更有效地停止第一個異常。你可以很容易地將它包裹在不同的位置,這就是我將如何做到這一點。

+1

(編輯)這很好。謝謝作爲一個警告,我沒有對此代碼運行任何性能測試。其中一些絕對是資源密集型的,但大多數圖像轉換過程是。我不確定它的其他方面是否會導致問題。 –

+1

我不認爲有任何理由調用'getNumberImages()',因爲我們已經將縮略圖的數量限制爲在我們遍歷foreach循環中的Imagick對象時在PDF中的頁數。 –

+0

@ T.BrianJones:是的...對於getNumberImages調用是正確的......因爲我們正在對一個強制限制的foreach進行調用,所以它毫無意義。就性能而言......我認爲與使用你遇到麻煩的暗示的唯一區別在於,每次可能只有一個頁面在內存中 - 但同時你必須打開每個頁面,然後將它們徹底銷燬,所以我的直覺本能是最簡單的方法,無需在shell中調用一些轉換實用程序。 – prodigitalson

相關問題