2007/07/25

PHP 生成預覽圖的方法整理

最近在 Komica 的高解析度版碰到有人提問為什麼版面的預覽圖 (或稱縮圖) 有的出不來,4chan 的 High Resolution 版就沒有這樣的情形。事實上我早就知道原因,也在 Pixmicat! 貼圖板上作過應對措施,原因就是 GD 函式庫受限於 PHP 本身執行時記憶體用量的限制,執行 PHP 程式碼時,每一次能使用的上限預設是 8MB (php.ini memory_limit 設定),而 GD 的 ImageCopyResampled() 方法卻是把圖檔轉化成未壓縮的點陣圖形式。因此一張 3000x4000 的 24bit 圖像大概要吃掉 30~40 MB 不等的空間,而這個值遠超過預設的 8MB,因此生成預覽圖時必定失敗,還會在 errorlog 裡附送你「PHP Fatal error: Allowed memory size of XXXX bytes exhausted」的訊息。

一味的加大 memory_limit 並不能解決問題,即使我調到了 128M 好了,難保哪天來個 20000x30000 的巨量圖檔 (假設有的話 ;-)),這時候實在覺得這個上限綁手綁腳。在高解析版的回應提到 ImageMagick 函式庫,這也是一套免費的圖形處理函式庫,不過 GD 幾乎都跟 PHP 綁定,ImageMagick 就比較少看到伺服器有安裝的。試驗一下雖然他也是吃掉巨量記憶體,不同的是他似乎不會受到 memory_limit 的上限束縛,那這就是個好方案了。(假如伺服器的記憶體夠多的話)

PHP 要使用 ImageMagick 有三個方法:1. 直接命令列呼叫 2. Imagick 套件 3. MagickWand for PHP 套件,都需要先安裝 ImageMagick。其中 Imagick 有在 PECL 維護,MagickWand for PHP 似乎是 ImageMagick 官方製作。

1. 直接呼叫
利用命令列方法直接使用 ImageMagick 的執行檔,以下是範例:
$ convert -sample 25%x25% Source.png Destination.jpg

這個方法可以在 PHP 的 exec() 方法使用,但是請注意主機商可能會因為安全因素封鎖此方法。


2. Imagick 套件
http://www.php.net/imagick 就有 API Document,不過這完成度根本就不能當參考嘛,還好他有將方法列出來了比較方便。我推薦這個套件因為他具有物件導向的特性,產生一個 Imagick 物件後就可以使用物件的方法來對圖檔進行操作。以下是範例:


3. MagickWand for PHP 套件
上網搜尋大家比較推這個套件,但是我實際測試的結果似乎水土不服,光讀取圖檔就發生錯誤導致 PHP 當掉,根本不能用,不過有的時候卻又奇蹟似的動作?總之也是值得一用,但是這個套件沒有物件導向的特性,導致方法來方法去的,而方法的第一個總是接受 MagickWand 資源。

題外,雖然官方網站有 API Document 看似完美,實際上很多方法並沒有列出來,像生成預覽圖的 MagickThumbnailImage() 方法竟然不在文件之列,讓我以為他沒有實作。實際上利用 print_r(get_extension_funcs('magickwand')); 查看發現根本就有,這是隱藏裡技嗎?一樣,請看範例:


我發現 ImageMagick 除了不受 memory_limit 限制,支援的格式也十分豐富。BMP 是直接支援的,連 AVI, SVG, AVS, JP2, PSD 都支援,其特效處理功力也非常強大,不過上面並沒有用到。此外智慧式的以副檔名直接判斷檔案格式也十分不錯。

對了,既然標題是「PHP 生成預覽圖的方法整理」,GD 預覽圖自然不可以拋棄,直接給範例:


自此生成預覽圖應該不是難事,如果要生成高解析度圖檔的預覽圖,我建議 ImageMagick + Imagick 套件來生成,短短幾行十分方便,比 GD 還省事,也比較快些,更重要的連 BMP 都直接支援,不必再去找 ImageCreateFromBMP (Pixmicat! 有收錄,原載於 PHP ImageCreate 的 User Contributed Code),而且這還沒有支援全部的 BMP,例如 BITMAPV4HEADER, BITMAPV5HEADER 檔頭、32bit, 32bit with BITFIELDS, 8bit with RLE8, 4bit with RLE4 等格式。

2 則留言:

  1. 請問LINUX抓下Imagick 該套件~要如何安裝呢???
    可以教導一下嗎??

    回覆刪除
  2. http://pecl.php.net/package/imagick

    從這裡抓一份Source然後回去編譯,INSTALL有說明方式,看你是要用編進PHP的還是動態載入的。

    回覆刪除