ImageMagick 範例 --
API 與腳本
- 索引
-
ImageMagick 範例前言與索引
-
API 和其他 IM 使用方法
- Windows 和 DOS
- PHP
- 使用 Shell 命令的 PHP
- PHP Imagick (PHP ImageMagick API)
- PerlMagick (Perl Magick 腳本)
-
安全性問題
-
更好的 ImageMagick Shell/PHP 腳本的提示
-
為什麼要使用多個 "magick" 命令
-
加速 IM(一般而言)
-
從原始碼編譯 ImageMagick
API 和其他 IM 使用方法
用於實際影像處理的 API(應用程式介面)實際上並不比使用 CLI 命令(例如「magick
」(它本身代表一種 shell-API)更快。IM 中的所有影像處理都使用相同的「核心」函式庫。因此,如果你正在執行複雜的任務,例如影像扭曲,那麼在 shell「magick
」上使用 API 對整體處理「速度」幾乎沒有影響。*那麼為什麼要使用 API 而不是命令列?* shell 會不斷地「分支出」許多不同的命令(不僅僅是 IM 的「magick
」命令,儘管 shell 有一些「內建命令」),每次執行時都必須載入並初始化這些命令。每個 IM 命令還必須重新初始化其設定檔、解析命令列參數、重新讀取你正在處理的任何影像,並且經常將結果儲存回磁碟。所有這些都需要時間,導致它們速度變慢。也就是說,所有這些額外的步驟都需要時間和處理能力,所以如果你經常這樣做,API 就開始有意義了。API 還可以讓你做一些命令列無法做到的事情。- 如果 API 已經在執行,則幾乎不需要設定時間。
- 將許多影像清單的陣列儲存在記憶體中,你可以按任何順序處理這些清單。例如,我有一個程式可以讀取數百張影像,在讀取時將它們縮略成 32x32 像素的影像,然後 magick 將它們兩兩比較(100 張影像進行 9,900 次比較)。另一個例子是按一般顏色對記憶體中的影像進行排序!
- 你可以以任何順序進行許多不同的影像處理執行緒。你不需要在處理下一張影像或步驟之前「完成」一個處理序列。例如,想像一個解決拼圖遊戲的程式!
- 您可以從圖像中檢索信息,並以複雜的方式使用該信息來修改圖像處理,而無需一遍又一遍地重新初始化圖像處理(重新讀取配置和圖像)。例如,在確定圖像的取景要求之前,先獲取圖像大小。
- 循環瀏覽圖像,對每個圖像進行不同的操作!例如,生成動畫序列,每個幀都以稍微不同的方式扭曲。
- 直接且完全隨機地訪問圖像數據。例如,在圖像中尋找“人臉”。
- 使用MPC 圖像保存(更快地重新讀取)中間圖像。請參閱我的腳本divide_vert
- 使用流水線進行並行處理(甚至可以使用不同的機器執行不同的步驟!),以更好地利用處理器並避免將中間圖像保存到磁盤。請參閱enlarge_image,了解一個流水線腳本示例,其中一個步驟將圖像傳送到序列中的下一個(有時是可選的)步驟。
- 使用循環單獨處理每個圖像,然後將圖像結果流傳送到最終的“合併所有圖像”步驟。我有許多這樣的腳本...請參閱分層圖像的程序化定位以獲取一個這樣的腳本。
Windows 和 DOS
有關使用 Windows 和 DOS 腳本使用 CLI API 的示例已移至在 Windows 下使用。PHP(來自“system()
”函數的 IM 命令)
PHP 用戶可以使用三種方式使用 ImageMagick,- “
imagick
PECL 接口 - “
MagicWand
”接口 - 使用“system()”和“exec()”函數運行 CLI“
magick
”命令。
使用 Shell 命令的 PHP
有關使用此技術的具體信息的最佳來源是 IM 論壇用戶Bonzo及其網站RubbleWebs。請注意,PHP 運行“magick
”時使用的環境可能與您從命令行獲得的環境不同,甚至可能以不同的用戶身份運行。因此,在命令行上可行的方法可能需要稍微調整一下才能在 PHP Web 驅動腳本中運行。以下是 ISP 命令行 IM 接口初始測試的推薦過程,假設您在遠程系統上沒有直接的命令行“shell”訪問權限。也就是說,您只能上傳 Web 文件以供執行。因此,我們需要做的第一件事是在系統上嘗試找到“magick
”命令,安裝的版本以及 PHP 運行的環境。在 Linux Web 服務上,從 ISP 的 Web 服務器上傳並訪問此 PHP 腳本...
|
pwd
" 會告訴您執行 PHP 腳本的當前目錄。 這可能是也可能不是 PHP 腳本所在的目錄,而且您可能無法從 PHP 腳本寫入該目錄表單。 接下來的兩個命令會告訴您,使用 "type
" 時,預設提供的命令 PATH 上是否有 "magick
",以及如果有,它在哪裡。 "locate
" 命令應該會找到伺服器上存在的所有 "magick
" 命令(假設它是 Linux 伺服器),但也可能會找到其他非 ImageMagick 的 "magick
" 命令、檔案和目錄。 您需要解讀結果。 接下來的三個命令假設 "magick
" 位於命令 PATH 上,並要求它報告其版本號,以及 IM 認為它可以訪問哪些字體。 哪個命令會報告哪些字體取決於安裝的 IM 版本的舊程度。 如果您只看到錯誤,則表示 "magick
" 不在命令列路徑上,並且您的 ISP 提供者沒有正確初始化網路伺服器 "PATH
" 和 "LD_LIBRARY_PATH
" 以包含它。 請參閱 "env
" 命令的輸出,以了解它們定義的內容。 如果是這種情況,您需要找出它的確切位置,並使用類似以下 PHP 腳本的內容。 這將使您的腳本可移植性降低,因為它是針對該特定 ISP 進行硬編碼的。 例如,假設 "magick
" 命令位於 "/opt/php5extras/ImageMagick/bin
" 中,則您可以設定一個變數來指定其位置。 這通常作為應用程式配置和安裝過程的一部分完成,適用於在不同 ISP 主機上使用的 PHP 腳本),
|
ldd
" 庫錯誤,則表示 "LD_LIBRARY_PATH
" 錯誤,並且 ISP 在安裝過程中肯定出現了問題,您需要報告錯誤,並讓他們修復網路伺服器的 "LD_LIBRARY_PATH
" 環境變數設定,或重新安裝 ImageMagick。 您可以設定 magick 命令的位置,也可以在頂部使用如下所示的行來調整 PATH 環境變數。 但是,這種方法通常在預設情況下會被典型的 PHP 系統配置「拒絕」...
|
|
|
|
當您讓該基本腳本正常工作後,您可以嘗試 PHP 測試腳本中列出的其中一種字體(修改以下內容以適合您的 PHP 伺服器)。 例如,在當時我可用的 Solaris 伺服器上,我注意到可以使用「
Utopia
」字體集,因此我可以嘗試使用該字體創建標籤...
|
範例 Shell 到 PHP 的轉換
這裡我們有一個相當典型的 ImageMagick 命令...
|
|
magick
" 命令的長命令行拆分開來,以便於理解圖像處理順序,方便日後編輯。這是使用 PHP 附加字符串完成的,而不是 shell 腳本中使用的 shell 行延續符號。還要注意到後幾行開頭的額外空格。以及將原始命令中出現的其他反斜杠加倍。或者,您可以使用單引號而不是反斜杠來保護這些選項。我還使用了一些 PHP 變量,以便於調整 PHP 腳本生成的圖像,以更好地控制結果。但是,當我將這些選項插入 "magick
" 中時,我使用了單引號來保護它們,防止被 shell 進一步修改。但要注意插入的字符串中的單引號!您可以將這些選項設為 PHP 輸入參數,以便您可以為從 Web 請求傳遞給它的任何輸入文本生成圖像。您還可以在同一個系統調用字符串中執行多個 shell 命令。事實上,如果您需要,一個系統調用甚至可以包含一個完整的 shell 腳本!因此,您可以在一個系統調用中完成 shell 循環和多個命令(以及清理操作)。這一點可能很多人沒有意識到。基本上,如果您足夠小心,就可以同時充分利用 PHP 提供的數學功能和 shell 的腳本編寫能力。只要注意引號即可。有關從 PHP 調用 ImageMagick 命令的各種示例,請參閱Rubble Web,在 PHP 中編寫 IM 代碼,其中描述了大約四種不同的技術。注意額外的引號
請注意,通常 PHP 中的 IM 命令會被額外的一組引號(通常是雙引號)包裹,因此必須注意允許使用這些額外的引號級別。請記住,當 PHP 執行一個字符串時.... PHP 會進行引號、反斜杠和變量替換,Shell 然後會拆分參數並進行自己的變量和引號替換。如果存在,它還會執行任何 "2>&1" 類型的文件描述符重定向。ImageMagick 會獲得一個參數數組,但也會針對 DOS(DOS 環境不處理元字符)和諸如 coder:*.gif[50x50] 之類的參數進行自己的文件名元字符處理,這些參數由於 coder: 前綴或 [...] 讀取修飾符而導致 shell 無法擴展。也就是說,會進行大量的參數解析!這可能意味著要處理大量的引號和反斜杠。需要謹慎和預先思考。我建議您至少閱讀 PHP 手冊中關於程序執行函數的內容,其中包括:PHP exec()、system() 和 passthru()。還要查看反引號運算符。特別需要注意的是,要了解究竟返回了什麼(通常只有最後一行)並傳遞給了調用客戶端(其他所有內容)。PHP 安全性
請記住...On the net, the only users you can trust not to be potentially hostile are those who are *activally* hostile. -- Programming Perl - Camel Book, r3
- 參數中的二進制字符 - 一種常見的黑客技術
- 參數中出現意外的空格、製表符、換行符和回車符。
- 反斜杠(目錄分隔符)和 '..' 路徑,以及 Windows 下文件名中的 '\' 和 ';'。
- 文件擴展元字符,包括 "
~*?[]{}<>
" 以及 ImageMagick 特有的特殊 "@
" 元字符。 - 其他 shell 元字符,包括 "
$#;
" 以及三個引號字符 '\''、'\"'、'\`' - 參數與 ImageMagick 預期的不符。使用 "
-list
" 來閱讀 IM 針對特定選項可以理解的參數類型。例如,用戶輸入 "-gravity
" 選項,則只有 10 種不同的設置。 - 等等...
寫入檔案系統
如上所述,如果您按照上述初始程序進行操作,您將會確定 PHP 通常在伺服器上以不同的、更受限制的使用者身分執行。因此,它通常無法寫入包含腳本的目錄(或實際執行的任何位置)。出於安全原因,您通常不想寫入該目錄!如果您真的希望 PHP 寫入文件,請讓它將圖像(或數據)保存到「/tmp
」中一個唯一的文件名,並且最重要的是事後清理,無論是在正常退出時,還是出現任何錯誤時。令人驚訝的是,一個沒有正確清理的應用程式,其剩餘的臨時文件會以多快的速度填滿磁碟。如果 Web 伺服器必須能夠看到保存的文件(圖像),請為這些文件建立一個特殊的「程式寫入」子目錄。應該如何做。 大多數 PHP 應用程式實際上是通過使用資料庫後端來避免向檔案系統寫入任何內容。也就是說,Cookie、令牌、使用者數據、圖像等等都被寫入到資料庫中,例如(按複雜性和規模排序)SQLite、PostgresSQL、MySQL 和 Oracle。它根本不會在檔案系統中保存任何內容。系統程式設計師通常會在安裝應用程式時使用該資訊來配置 PHP 應用程式。圖像通常由相同或單獨的 PHP 腳本重現,該腳本會查找圖像「blob」並將其輸出到客戶端。圖像可以作為「內嵌」圖像與 HTML 本身一起發送(請參閱「內嵌:
」格式,其中演示了 HTML 內嵌圖像),或者作為單個「多合一」圖像發送,因此客戶端 HTML/JAVA 只有一個圖像請求,而不是 20 個單獨的請求。最後一點。應該始終存在某種清理舊數據的方法。一個兩年沒有登錄的使用者,他的數據可能應該被刪除。獲取錯誤輸出
嘗試以下方法之一...
|
|
|
|
更安全的 ImageMagick 命令...
理想情況下,出於安全因素考量,您應該避免使用 shell 來將單個長字符串解析為單獨的命令和參數。 最好自己完成! 這意味著您將命令的參數作為單獨字符串的數組提供,而不是作為一個單獨的 shell 解析字符串。 通過這樣做,您可以防止出現 shell 語法錯誤的可能性、shell 需要的額外引用負擔,以及防止某些駭客破壞 shell 命令並運行他們自己的命令(非常糟糕)。 另一方面,您會失去 shell 腳本、管道和文件重定向,但當您已經使用 PHP 或其他一些包裝語言時,這通常不是什麼大問題。 在 PHP 中,我可以找到的唯一允許我直接調用命令而不使用 shell 的函數是 pcntl_exec() 函數。 這基本上避免了 shell,並直接調用命令。 但是,它是一個真正的“execl()”系統調用,它會用給定的命令替換當前進程。 也就是說,它不會執行將其作為子進程運行所需的“fork()”和文件描述符鏈接。 因此,pcntl_exec() 實際上對於一般用途來說級別太低,並且實現“無 shell”命令可能會變得相當複雜。 我很驚訝 PHP 界面尚未提供更簡單、更安全的“避免使用 shell”命令調用。 但我不是 PHP 程序員。 另一方面,Perl 提供了許多安全調用子命令和進程的方法,這通常使其比 PHP 更適合作為 Web 界面。 任何具有 PHP 安全知識的人願意提供更多信息或提供更多信息的指針嗎?PHP“IMagick”API
要測試 PHP PECL Imagick 模組是否真的有效,請將簡單的測試“image.jpg
”圖像和此 PHP 腳本上傳到同一個可通過 Web 訪問的目錄。
|
PHP“MagickWand”
您可以使用以下方法檢查 PHP MagickWand 模組是否是 PHP 安裝的一部分...
|
image.png
”和此腳本...
|
複雜的 PHP 腳本...
如果您需要生成並輸出 HTML 和圖像,請考慮設計您的 PHP 腳本,以便單獨的 HTML 請求或輸入選項可以從相同或不同的 PHP 腳本生成您在網頁文件上需要的各個部分。也就是說,頂層 PHP 腳本可以輸出帶有適當 <IMG> 標籤的 HTML,這些標籤會調用自身(或另一個 PHP 腳本)並帶有適當的選項,以創建或修改顯示在第一個頂層 PHP 腳本上的圖像。這在很多相冊和圖表 PHP 腳本中都有用到。所有這些都由 URL 調用的 GET 和 PATH_INFO 擴展名控制。請注意,您不能在 IMG 標籤中使用 POST。通過這種方式,您應該能夠完全避免為 PHP 生成的網頁生成、保存和清理臨時圖像的需要。這是一種充滿問題的解決方案,例如資源限制和垃圾回收,使其成為一種非常糟糕的編程技術。這種技術在ImageMagick 書籍中都有探討,儘管它實際上使用的 ImageMagick 有點過時了。Perl Magick 腳本
PerlMagick API 是一種將「magick
」命令轉換為腳本的好方法,該腳本還可以處理數據庫、大量圖像或其他更複雜的圖像處理,否則這是可能的。最好的幫助是查看 PerlMagick 的「演示」腳本,這些腳本既包含在源代碼中,通常也安裝在 PerlMagick 的文檔區域中。在我的系統中,它位於「/usr/share/doc/ImageMagick-perl-*/demo/
」。在這個目錄中,有越來越多的簡單示例,展示了如何讀取、寫入和處理各種圖像。同時還提供了腳本「demo.pl」,它列出了幾乎所有常見的圖像處理選項,以及如何使用它們。將命令行「magick
」命令轉換為 perl 時,您需要記住一些事項。- 首先要記住的是,PerlMagick 不會自動刪除已處理的新圖像。許多運算符會從舊圖像創建新的修改後圖像,而其他運算符則會直接修改現有圖像。
- 此外,許多運算符不會將特定操作應用於整個圖像列表,而只會應用於您提供的列表中的第一個圖像。這意味著您需要自己循環遍歷圖像序列(perl 數組)。
- 您可以擁有許多圖像序列。實際上,您通常會將每個圖像讀入其自己的獨立圖像序列中,而不必像在命令行中那樣使用單個圖像序列。
- 此外,一旦您將圖像加載到內存中,就可以輕鬆提取現有圖像的大小。這意味著您可以直接創建新的畫布,而無需像在命令行中那樣克隆和清除現有圖像。但是,克隆圖像也會複製圖像的元數據,因此您可能希望跟踪數碼照片等圖像的元數據。
- 在每個主要過程之後,尤其是在讀取圖像時,檢查圖像錯誤(如PerlMagick頁面上所示)。
magick
" 命令中使用括號和額外的克隆操作通常不是問題。 轉換腳本中最難的部分通常是將命令列選項映射到 PerlMagick 函式呼叫。 我發現最快的方法是獲取 IM 的原始程式碼,查看 "MagickWand/mogrify.c
" 檔案,然後搜尋您在使用的特定命令列選項。 例如,假設要搜尋 -threshold
選項,請搜尋包含引號的 "threshold"
。 將會有兩個相符的項目,一個用於快速語法解析以確保找到所有選項,另一個用於該選項的實際內部呼叫。 在這裡,您將找到所使用的程式庫函式的名稱,並且該名稱通常會直接映射到 Perl 函式。 在這種情況下... BilevelImageChannel()
安全警告
在編寫供公開使用的腳本時,尤其是在世界上任何人都可以執行的基於 Web 的 PHP 腳本時,檢查所有可能來自未知(甚至已知)使用者的東西至關重要。 我的意思是所有東西,從參數、檔案名稱、URL 到圖像。 在您驗證某些輸入參數之前,該參數可能包含字母、數字、空格、標點符號,甚至是「空」和控制字元。 在您徹底檢查它之前,它應該被視為可疑的,並且不應該被使用。 您是否使用某些 Web 控制的輸入表單並不重要。 稍微懂一點技術的人可以輕鬆地使用他自己的參數呼叫您的 PHP,而完全不使用該輸入表單。 不要相信他們不會這樣做,機器人就在那裡,閱讀輸入表單並建立他們自己的「駭客」參數,試圖入侵隨機腳本。檔案名稱中的中繼字元
作為一個安全問題,您應該特別注意包含空格、引號、標點符號、控制字元或其他中繼字元的檔案名稱,因為 IM 和 Shell 都可能會嘗試擴展它們。 問題在於名為 '*?@${&) .jpg
' 的檔案實際上在 UNIX 下是一個完全合法的檔案名稱,但許多程式在處理它時會遇到問題,如果該程式(如 shell 和 IM)也進行檔名擴展。 請記住,即使您阻止 shell 進行「全域」中繼字元擴展,IM 本身也會進行此擴展(用於 DOS)。 因此,阻止所有此類字元(並產生錯誤)可能是一個明智的做法。 作為一種安全措施,如果檔案名稱中包含任何未知或不尋常的字元(例如不是字母、數字或預期後綴中的任何字元),則通常最好出錯並中止。 在將此類檔案名稱傳遞給 shell 命令或 IM 之前。 最好限制更多並阻止事情發生,而不是允許壞事發生。更好的 ImageMagick Shell/PHP 腳本的提示
這些是我提出的一些關於腳本程式設計的基本觀點,這些觀點是關於發送到 IM 郵件清單以供他人使用的貢獻 shell 腳本。 我最初私下將這些內容發送給作者(他將保持匿名),他對此表示感謝。 它們並不都是特定於 IM 的,但無論如何都應該應用,作為標準的程式設計實踐。 特別是如果您打算讓其他人使用、查看和/或除錯您的程式或腳本。 反過來,這將使您的腳本更有用。- 將「help」或「doc」放在腳本和程式的頂部。這讓其他人更容易理解特定程式的作用,而無需安裝或運行腳本。我自己經常會丟棄沒有明確註釋說明其用途的程式,而不是嘗試編譯或運行此類未知腳本。事實上,我看過很多大型項目,它們的第一個 README 文件甚至沒有說明這個龐大而複雜的項目是做什麼的!程式設計師只是假設,如果您下載了它,您一定知道它是做什麼的!還要確保「錯誤選項」(例如「-?」)不僅會列印選項的概要,還會快速概述程式的功能或哪裡可以找到此類説明。不要只是指向一個遠程網站,這個網站可能在 10 年後就消失了!有關列印自身「開頭註釋」的腳本示例,請參閱 IM 腳本區域中的「jigsaw」腳本。Perl 可以使用 POD 進行自我說明(請參閱 perl 的「
Pod::Usage
」模組)。例如,請參閱貢獻的 dpx_timecode.pl 腳本。將説明作為「here 文件」放在第一個子例程中也是可以接受的,並且適用於大多數語言。但是要把該子例程放在腳本或程式的頂部,而不是底部或中間。 - 確保您清理了代碼,刪除了舊的、過時的代碼和註釋,盡可能使代碼簡潔明瞭。簡明扼要,並附帶簡單的註釋階段(如果可能)。再次請參閱「jigsaw」腳本。
- 確保在結束時清理臨時文件。使用「trap」shell 命令在文件退出或中斷時刪除它們。您當然可以多次重複使用單個臨時文件,因此您不需要太多臨時文件,尤其是在使用 IM v6 魔法命令的情況下。再次請參閱「jigsaw」腳本,並搜尋「trap」。
- 此外,並非每個人都使用系統 X,儘管在您看來可能並非如此。不要提及特定的系統要求或解決問題的方法。對您有效的方法可能完全不適合他們的系統和設定。他們甚至可能無法連接到網際網路!只要說找不到 ImageMagick 的「
magick
」命令即可。如果您想新增安裝需求或建議,請將其作為單獨的、更廣泛的文件的一部分新增。 - 請檢查使用的 IM 版本是否足夠高,或者新增向後相容的變更。我特意在整個 IM 示例中給出了「版本警告」說明,說明何時添加了各種特殊功能。這使得在建立具有單一最低版本檢查的腳本時更容易。以下是一種簡單的方法,可以在 shell 腳本中獲取用於測試目的的單一版本號。它提取 4 個版本號,並插入適當數量的零,使每個數字都變成 2 位數,從而產生一個簡單的 8 位數。
IM_VERSION=`magick -list configure | \ sed '/^LIB_VERSION_NUMBER /!d; s//,/; s/,/,0/g; s/,0*\([0-9][0-9]\)/\1/g'`
06030510
」,而下一個版本 IM v6.3.6.0 將產生「06030600
」。PHP 版本的上述內容可以從 RubbleWeb 的字體列表 示例頁面獲得。可以使用簡單的數字或字串測試來測試產生的字串,以瞭解可用的 ImageMagick 版本是否足夠現代,足以滿足腳本的需求。例如...if [ "$IM_VERSION" -lt '06030600' ]; then echo >&2 "The perspective distortion operator is not available." echo >&2 "Sorry your installed ImageMagick is too old -- ABORTING" exit 10 fi
-list
」設定「type
」會傳回「已知字體」清單。在後續版本中,您需要改用「font
」設定。因此,在這裡我可以執行版本檢查,以使用正確的設定來獲取所需的信息。if [ "$IM_VERSION" -lt '06030507' ]; then font_list="type"; else font_list="font"; fi avail_fonts=`magick -list $font_list | cut -d\ -f1 |\ egrep -v '^($|----|Path:|Name$)'`
expr
」而不是「[
」測試……if expr + "$im_version" \>= "06030507" >/dev/null; then ...
+
」通常是不需要的,至少對於這個測試來說是這樣,但如果變數可能包含特殊關鍵字「match
」,則需要它,因為它會給「expr
」帶來問題,尤其是在用於字串或子字串操作時。 - 您也可以利用「
-list
」信息輸出,檢查當前安裝的 ImageMagick 中是否添加了一些特殊功能。magick -list distort | grep 'Arc' >/dev/null 2>&1 if [ "$?" -ne 0 ]; then echo >&2 "Arc distortion method not available." echo >&2 "Sorry your installed ImageMagick is too old -- ABORTING" exit 10 fi
-distort Arc
」)可能會在正式準備好供一般使用之前出現。因此,版本檢查可能仍然是更好的主意。這就是為什麼在 IM 示例中,我嘗試註明(查找符號)新功能變得足夠穩定以供一般使用時的 IM 版本。
- 不要使用非常非常長的單行命令。特別是對於複雜的「convert」命令。使用續行方法(如上所示)將它們拆分,例如 UNIX 中的「
\
」、DOS 中的「^
」和 PHP 中的「.
」字符串連接。但是,我的意思不是將每個設置和操作都放在單獨的行上。每行執行一個主要操作或階段,創建新圖像、修改圖像、與其他圖像合併等。將特定運算符所需的所有操作設置放在該運算符之前。將每一行視為單個處理步驟。這使您可以分隔這些行,以便更容易閱讀和理解各個處理步驟。運算符分隔得越清晰,複雜的圖像處理過程就越容易理解。使用額外的括號、在各個階段縮進行,甚至在大型處理塊之間添加空行,都可以更容易地查看大型和長操作的主要階段。我在 IM 示例中都使用了這些技術,以便使示例更容易理解,因此請隨意瀏覽!最後,關於特定命令正在執行的操作的額外註釋,可以讓其他人(甚至兩個月後的你自己)在閱讀和理解你的腳本時產生很大的差異。可惜的是,你目前無法在長命令行中插入註釋! - 盡量不要依賴太多外部程序,或者只在它們可用的情況下使用它們(並提供可能的替代方案)。其他人可能沒有安裝該程序,或者更喜歡使用其他程序。如果程序的使用可以是可選的,請使其成為可選的,可以由用戶控制,或者在找到時自動使用。盡可能不要將其作為強制性要求。例如,您可以使用「
pngcrush
」、「optipng
」、「pngnq
」來壓縮 PNG 圖像,其效果比 IM 通常提供的更好(IM 被設計成通用的,而不是專用的)。同樣,「gifsicle
」、「intergif
」或其他用於 GIF 動畫的 LZW 壓縮優化器也有其優缺點。只是不要將其作為腳本運行的絕對要求。舉一個實際的例子,舊版本的「gif2anim」沒有使用 ImageMagick 的「magick identify
」來查找 GIF 特定的元數據,而是依賴於修補版本的「giftrans
」。由於 ImageMagick 的「magick identify
」的改進,後來不再需要此要求,因此我刪除了該要求,以使腳本更廣泛地使用。ImageMagick 本身有很多可選的要求,例如用於 PostScript 和 PDF 文檔閱讀的「ghostscript
」,或者用於正確處理 SVG 向量圖像的「librsvg
」。如果這些庫可用,IM 將會非常樂意地使用它們。IM 將這些庫視為可選的,只有在您想要處理這些格式的圖像時才需要它們。以下是一段代碼片段,您可以使用它來檢查腳本依賴項(在非常精簡的 cygwin 環境中尤其有用)...# Check Dependencies to scripts correct working DEPENDENCIES="sed awk grep tr bc magick identify" # adjust to suit for i in $DEPENDENCIES; do type $i >/dev/null 2>&1 || Usage "Required program dependency \"$i\" missing" done
- 進一步說明最後一點。如果您需要在使用 IM 的 shell 腳本中進行浮點數學運算,則可以使用 IM 本身來完成這些運算,而不是依賴於某些其他程序,例如「
awk
」或「bc
」,這些程序可能不可用(尤其是在 Windows 上的 cygwin 下)。例如,在這裡,我們使用「magick
」來計算以度為單位的特定角度的 sin()...angle=-20 sine=`magick xc: -format "%[fx:sin( $angle *pi/180)]" info:` echo $sine
-0.34202
」。您可以使用精度操作控制調整小數位數。默認情況下,它被設置為 6 位數。 - 讓用戶決定要使用的輸入/輸出圖像格式。ImageMagick 主要是一個圖像轉換器,能夠使用許多不同的格式。它可以輸出到屏幕、PostScript、打印機,或者將圖像通過管道傳輸到另一個命令進行進一步處理。不要將用戶限制在特定的格式。例如,「jigsaw」和「gif_anim_montage」腳本允許用戶指定任何輸入或輸出圖像。這樣,用戶就可以將圖像通過管道傳輸到該腳本中或從該腳本中傳輸出來,以便使用其他程序和腳本進行進一步處理。例如,我經常使用如下命令...
gif_anim_montage animation.miff show:
URL:
」或「HTTP:
」輸入格式從萬維網讀取。不要限制這些可能性,除非它成為安全問題(例如在網絡使用中)。 - 僅讀取輸入圖像和輸出多個圖像一次!如果用戶提供了管道文件名或 URL,則不應嘗試多次讀取這些圖像,否則可能會出現問題。當您需要多次引用該圖像時,請使用臨時文件、克隆圖像或「
MPC:
」保存輸入圖像的副本。如果您可以從管道處理多個圖像,那就更好了。再次請參閱「jigsaw」腳本,以獲取在您被迫多次處理輸入圖像或以與程序參數所暗示的順序不同的順序處理輸入圖像時將輸入圖像保存到臨時文件的示例。
你為什麼要使用多個「magick」命令
- Willem 於 2006 年 10 月 25 日星期三寫道...
- 我很好奇;有時候我在你的範例中看到你會調用多次 Convert 來獲得想要的結果。一般來說,我預期不需要調用 magick 多次;應該可以在一次調用中完成所有操作(但命令會更複雜)。你同意這個說法嗎?
magick /tmp/image1.png ..operations.. /tmp/image1.png |
讓 IM 更快(總體而言)
有很多方法可以讓 IM 更快地工作。以下是需要牢記的最重要方面。隨著您向下瀏覽清單,加速會變得更小,或者需要對 IM 安裝進行更複雜的更改。- IM Q8(或每個顏色值 8 位,每個像素 3 到 4 位元組)比具有更高顏色解析度的 IM Q16 預設值快得多(快 3 到 4 倍)。如果您不需要圖像的 Q16,也許您應該將您的 IM 替換為 Q8 版本。但是請注意,僅使用 8 位內部品質會影響整體圖像處理,因為中間圖像會丟失資訊。有關此相反的情況,請參閱 HDRI。
- 如果可能,請使用單個「
magick
」命令,以便對單個圖像進行所有必要的處理。這可以節省初始化、建立臨時檔案或命令之間的管道,甚至是這些管道和磁碟 I/O 的圖像檔案格式的編碼/解碼。當然,有時您仍然需要使用多個命令,以允許可選的圖像處理步驟,例如涉及圖像大小、顏色甚至可選處理步驟的計算。IMv7 腳本在這方面將有所幫助。 - Shell 腳本本身就很慢。它被解釋,需要多個步驟和額外的檔案處理到磁碟。由於新的 IM v6 選項處理,這當然更好,允許您在單個命令中執行大量圖像處理操作。儘管如此,您很少能在單個「
magick
」命令中完成所有操作,因此您經常必須使用多個命令才能實現您想要的目標。因此,像 perl、ruby 或 PHP magick 模組這樣的 API 更快,因為它刪除了 shell 和 IM 命令列 API 的所有解釋方面。它還減少了 IM 在讀取字體和顏色定義時經歷的初始化步驟。 - API 還可以在程式生命週期內保存所有圖像,甚至多個圖像清單(只要您有足夠的記憶體)。這意味著您可以切換和更改正在處理的圖像,而無需像在命令列上那樣對圖像進行混洗和調整。當您還需要根據先前的圖像處理步驟進行額外計算時,這一點尤其有用。
- GIF 圖像檔案格式的寫入速度很慢。 IM 必須努力減少(量化)圖像的顏色,以適應檔案格式的有限顏色。 即使這樣,您通常也需要做額外的工作才能使其正確,尤其是對於 GIF 動畫而言。 PNG 和 JPEG 速度更快,但 PNG 的成本是大小,JPEG 的成本是品質損失。 雖然實際上 GIF 圖像的品質更差!
- 預先準備和快取圖像,例如背景、疊加層、框架、遮罩,或預先生成顏色查找表、變形圖、模板、遮罩等。所有這些都可以使您的處理時間大不相同。 考慮一下 beforehand 可以做些什麼。 預先生成的大型圖像庫比嘗試根據需要建立圖像要快得多。另請參閱將「MPC:」用於中間和快取圖像。 這些是磁盤上的記憶體映射圖像,基本上讀取時間為零,但對其他任何東西或其他機器都毫無用處。 它們應該只在主要圖像處理過程開始時建立,並且不要長時間儲存,因為任何最小的軟體或系統升級都會使它們失效,並且可能會導致分段錯誤。
- 如果可以使用 Alpha 合成、更簡單的 評估、簡單數學運算 或其他技術,請避免使用 FX,特效圖像運算符。 如果您確實需要使用它們,請嘗試將其使用限制在盡可能小的圖像,或圖像的單個通道(處理灰度時)。
- 當幾個較小的 圖像模糊 可能更快時,請避免使用大尺寸的。 做一些時間測試,看看哪個更快。 其他 形態學 和 捲積運算符(例如高斯和陰影運算符)也是如此。
- 對小區域的複雜處理使用較小的子圖像或區域。 例如,在遮罩和重新著色之前找到並提取人的眼睛(使用區域)可以比處理完整的大版本圖像帶來巨大的速度提升。 差異越大,節省越大。
- 當讀取大量甚至大量圖像時,最好使用 讀取修飾符 在讀取每個圖像後立即調整大小或裁剪它們,從而減少其總體記憶體需求。 對於 JPEG,您甚至可以使用特殊的「
jpeg:size
」程式庫修飾符來避免分配記憶體。 這反過來又防止了「磁盤抖動」(這會使電腦速度非常慢)。 特別是當涉及大量大型圖像時,例如在生成 已建立索引的蒙太奇目錄 或其他多圖像拼貼時。 - 對於必須從磁盤處理的 真正非常大的圖像,最好將它們分成更小的塊進行處理。
- 同樣對於大型圖像... 如果您使用的是 Windows 64 位作業系統,請使用 64 位 ImageMagick 發行版。 它使用更大的位址空間,並且可以比 32 位 Windows 將更大的圖像放入記憶體。
- IM 預設使用多個執行緒進行單個圖像處理操作。 這意味著具有兩個或多個「核心」的電腦通常會比單個 CPU 機器更快地處理圖像。 對於大型圖像,OpenMP 多執行緒功能可以產生明確的速度優勢,因為它使用更多 CPU 來完成單個圖像處理操作。 請注意,在 IM 中,只有單個圖像處理操作是並行的。 因此,節省更多的是大型圖像處理,而不是處理大量圖像時(見下文)。
- 對於小圖像,使用 IM 的多執行緒功能不會給您帶來太多優勢。在這種情況下,同時在不同圖像上運行多個轉換可以產生更高的吞吐量。當多個 PHP Web 請求可以啟動多個圖像“magick”命令時,也可能會發生這種情況。在這兩種情況下,由於 CPU 爭用,啟用多執行緒可能會非常不利,最好通過將“
MAGICK_THREAD_LIMIT
”環境變量設置為“1
”來禁用 OpenMP。請參閱 IM 論壇討論 線程會降低“convert”的速度。您可能還想查看MAGICK_THROTTLE
,以使 ImageMagick 更頻繁地在更合適的時間點放棄對 CPU 的控制。 - 如果您要對圖像執行大量小操作(例如繪圖),請嘗試不要使用任何顏色名稱。使用哈希顏色(例如“
#00AA99
”)或 rgb 數字(例如“rgb(0,160,100)
”)指定顏色,以阻止 IM 加載顏色名稱表(它相當大!)。您也可以嘗試刪除或削減系統“字體”列表定義文件(來自“type.xml
”。或者完全刪除這些文件,並直接通過文件名指定字體。基本上減少了額外配置信息的加載,IM 將在特定圖像處理需要時讀取和初始化這些信息。因此,要么不要使用它們,要么減少配置文件的大小和影響。 - 將 ImageMagick 構建為共享庫(默認)可以大大減少加載時間。庫和編碼器模塊僅在需要時加載,因此 IM 的動態版本不會加載在圖像處理期間不需要使用的任何內容。此外,共享庫往往會保持可用狀態,因此第二次運行時可能不需要重新加載。
- 如果您將 ImageMagick 作為 Apache 模塊的一部分調用,它也會減少啟動時間,因為零件將被加載一次並保持可用以供多次使用,而不需要一遍又一遍地重新加載。隨著將來出現永久運行的“守護進程”IM 進程,這可能會變得更加實用。
從源代碼編譯 ImageMagick
從 SRPM 構建適用於 Linux 的 ImageMagick RPM
您不需要 root 權限即可實際構建 RPM,但您需要 root 權限才能安裝 RPM。我使用它在Fedora Linux 系統下生成和安裝 IM,但它也被報告適用於CentOS 5.4(企業版 Redhat)Linux 系統(請參閱更具體的CentOS 上的 IM 筆記)。首先從Linux 源碼包獲取最新的源碼包版本。首先確保您的機器擁有它需要的所有編譯器和工具。
|
![]() ![]() |
“sudo ”是一個以 root 身份運行命令的程序,如果您被允許,否則請使用 root shell 並從上面刪除“sudo ”部分。 |
|
|
- 您還應確保還安裝了這些軟件包及其依賴項(例如 jpeg 和 png 開發庫)
-
freetype-devel ghostscript-devel libwmf-devel jasper-devel lcms-devel bzip2-devel librsvg2 librsvg2-devel liblpr-1 liblqr-1-devel libtool-ltdl-devel autotrace-devel
- “ImageMagick 示例”中的一些示例也可能使用這些可選軟件包和庫提供的程序,但構建過程不需要這些程序。
-
gnuplot autotrace
liblqr
”模組才能啟用Liquid Rescale 運算符。現在下載一個 SRPM(源 RPM)軟件包,用於構建您的二進制 RPM。或者使用...從現有的 TAR 或 SVN 下載構建 SRPM。
|
|
rpmbuild
”,它將在其中提取 SRPM 源代碼,並構建 IM 的編譯軟件包 RPM 版本。![]() ![]() |
在舊版本的 Fedora 和 Redhat 上,這是在“/usr/src ”中完成的,該目錄通常僅限 root 使用。但是,您可以將此目錄設置為由您擁有或可寫入,這樣您仍然可以在不需要完全 root 訪問權限的情況下進行構建。 |
|
|
sudo
”命令的說明)...
|
--nodeps
”。要升級現有安裝,我通常會這樣做(以 root 身份)。
|
要稍後刪除 IM,您可以像這樣刪除軟件包(同樣以 root 身份)...
|
有時我只想從系統中完全清理和清除所有 IM 的痕跡。為此,我首先使用上一條命令從系統中刪除實際的軟件包(如下所示)。然後我運行以下刪除命令。請注意,我對此不作任何保證,我會事先徹底檢查命令,以確保它們不會刪除不應該刪除的內容。如果它遺漏了任何內容,或者刪除了不應該刪除的內容,請告訴我,以便我可以更新它。
|
yum upgrade
”命令。享受。Ubuntu 上的 ImageMagick 原始碼
要獲取用於構建 ImageMagick 的所有開發庫,請使用以下內容
|
在 MacOSX 上編譯
在 MacOSX 上安裝 ImageMagick 的最簡單方法是使用 MacPorts。但以下是指向有關為 MacOSX 編譯的信息的指針。我不知道它是否有效或是否有幫助,因為我從未使用過它。但請參閱在沒有 Fink 或 MacPorts 的情況下安裝 ImageMagick和在 Snow Leopard 中安裝 ImageMagick。以上內容是根據IM 用戶論壇上的討論改寫的。編譯 HDRI 版本的 IM
關於編譯 HDRI 版本 IM 的資訊,請參閱 IM 主要網站上的 在 ImageMagick 中啟用 HDRI,另請參閱使用者論壇上的 傅立葉變換公告討論,以取得 Windows 和 Ubuntu Linux 的特定資訊。建立個人 ImageMagick
您不一定總是有權限以超級使用者的身分存取您正在處理影像工作的機器,而且通常擁有該權限的人也不想更新他們的 ImageMagick 安裝。可能是因為套件管理問題或相容性問題。如果您有命令列存取權限(例如透過 SSH),則並非毫無希望。您可以安裝並使用個人版本的 ImageMagick。壞消息是您仍然需要系統管理員安裝編譯器和開發套件(請參閱上方),但這些通常已經存在,因此並非總是問題。首先,決定要在哪個子目錄中安裝您的 IM 版本。專用目錄是最佳選擇,因為這表示您只需刪除整個目錄即可移除安裝。在我的例子中,我會安裝到我的 home 目錄的「apps/im」子目錄中。
|
|
--disable-installed
」和「--prefix
」。其他部分會停用個人版本 ImageMagick 中更多選用層面的編譯。您可以根據需要修改它們。現在要使用您自己安裝的版本,而不是正常的系統版本,您只需要設定以下環境變數。
|
|
--disable-installed
」選項建立的 Imagemagick 需要設定變數「$MAGICK_HOME
」。其他兩個環境變數可確保我們使用個人版本,而不是任何可能也已安裝的系統版本。警告:請勿混用上述變數。請全部定義它們,或不要以這種方式定義它們。您使用的 IM 可執行檔也必須使用與那些可執行檔一起建置的相同程式庫、編碼器和設定檔。混合使用系統版本和個人版本可能會導致區段錯誤和記憶體錯誤。
您可以在不重新編譯的情況下移動個人 IM 的位置,但您不僅需要修改上述環境變數,還需要變更(或移除)「
delegate.xml
」檔案中個人安裝版本的「show:
」委派所使用的「magick display
」程式的硬編碼路徑。如需 IM 這方面的更多資訊,請參閱委派。為了方便我在系統安裝版本和多個個人版本的 IM 之間切換,我通常根本不會設定上述變數。相反的,我會呼叫一個指令碼,在呼叫特定版本的 IM 之前設定這些變數。例如,我有一個使用HDRI 編譯的個人版本 IM,我只在 ImageMagick 範例中將其用於特定範例。我通常不想使用這個版本,而是在大多數影像工作中偏好使用非 HDRI 系統安裝版本。因此,我在我的個人區域「
$HOME/apps/im_hdri
」中安裝了「HDRI」版本的 IM,並建立了一個名為「hdri
」的指令碼,其中包含...
|
hdri
」,則會執行系統預設版本的 ImageMagick。警告:如果腳本找不到您個人版本的 ImageMagick,它會自動改用系統版本。上述「版本」檢查是一項重要的測試,用於確保我實際上使用的是個人版本,而不是系統版本。您也可以使用「which」指令精確檢查腳本嘗試執行的 magick 指令。
|
magick
」指令,而是可以執行任何指令,例如 ImageMagick Shell Scripts,以便該腳本使用 HDRI 版本的 magick,而不是系統預設的 convert 指令。
|