ImageMagick 範例 --
影像檔案處理

索引
ImageMagick 範例前言與索引
影像格式摘要
讀取影像
儲存影像
特殊輸出檔案格式 (ImageMagick 特有)
miff:   info:   null:   txt:   sparse-color:   histogram:   mpr:   mpc:   fd:   inline:  
clipboard: -- 從 Windows 剪貼簿讀取/寫入
ephemeral: -- 讀取後自動刪除
show:win:x: -- 直接顯示影像
x:(作為輸入) -- 顯示擷取和重新繪製
影像格式的委託和編碼器
超大型影像處理
大量影像的長串流、影片序列
要處理影像,您不僅需要運算子來處理影像,還需要盡可能以多種不同的檔案格式讀取和寫入影像。在本節中,我們將概觀介紹 IM 檔案格式。

影像格式摘要

ImageMagick 最常見的用途之一不是修改影像,而是將影像從一種影像格式轉換為另一種影像格式。事實上,這也是 IM 創建的初衷,就是為了進行這種影像格式轉換。這就是為什麼主要的 IM 命令稱為「magick」。為此,ImageMagick 可以處理令人眼花撩亂的影像和檔案格式陣列。除了這個陣列之外,還有大量的特殊輸入和輸出格式,用於內建測試影像、簡單影像創建以及專為程式設計 Shell 腳本和程式設計的影像格式。如需完整清單,請參閱 IM 網站上的IM 影像格式頁面。對於 ImageMagick 的新手來說,這一切可能會讓人卻步。我最好的建議是忽略大多數檔案格式,因為您可能永遠不會用到它們。相反地,請專注於您想做的事情,並嘗試去做。如果您不知道該怎麼做,請嘗試在這些頁面和網路上尋找範例。如需 IM 範例中演示的影像格式,請參閱參考索引,檔案格式

讀取影像

IM 預設會嘗試根據檔案本身中的「魔術」檔案識別碼來判斷影像格式類型。但是,如果失敗,您需要使用檔案後綴或添加前綴格式來指定影像檔案格式。某些格式不會讀取任何檔案,並且會忽略任何給定的檔名。以下是一些常見的內建影像…

  logo:      granite:     rose:
其中一些會根據作為檔名給定的參數以及可能控制最終影像大小的額外「-size」來產生影像…

  -size 30x30  canvas:red
  -size 30x30  gradient:yellow-lime
  -size 30x30  pattern:fishscales
  magick import:
在某些情況下,您甚至可以使用多種格式…

  -size 30x30  tile:pattern:gray95
然而,在這種情況下,這是多餘的,因為 'pattern:' 格式編碼器內建了 'tile:' 編碼器。但它確實明確說明了你想要做什麼。IM 也可以透過指定影像的 URL 來下載發佈在「全球資訊網」上的影像。這基本上提供了一個 'http:' 影像編碼器,這就是它可以運作的原因。

  magick http://www.ict.griffith.edu.au/anthony/images/anthony_castle.gif \
          -resize 100x100 castle_logo.png
[IM Output]
如您所見,此命令從 WWW 讀取影像並調整其大小,最後將結果儲存到磁碟。
當給定前綴檔案格式時,作為檔名一部分給定的任何後綴都不會影響檔案的讀取方式。事實上,這在讀取某些檔案格式時至關重要,例如「text:」與「txt:」檔案格式處理。當然,如果影像產生器實際上讀取影像檔案以特殊方式處理它(例如「tile:」),那麼後綴(或前綴)檔案格式將再次變得重要,就像在上一個範例中一樣
可以使用特殊的編碼器前綴「implicit::」來「關閉」任何編碼器的使用,從而在檔名中使用「:」。檔名可以包含特殊的「檔案中繼字元」,例如「*」和「?」。IM 將展開這些字元以產生要讀取的檔名列表,從而避免需要外部 shell 來執行此操作,或避免命令列長度限制的問題。例如...

  magick montage  '*.jpg' -geometry 50x50+2+2  image_index.gif
這將產生當前目錄中所有 JPEG 檔案的單個蒙太奇索引影像。但請注意,我需要引用參數以防止我的 UNIX shell 展開檔名,而不是 ImageMagick。有關更完整的「magick montage」規格,請參見下文。當然,Linux shell 也可以展開傳遞給它們的未加引號的「*」和「?」字元。但是,在某些情況下,如果檔案列表擴展到非常多的檔名,您可能會發現自己遇到了「命令列限制」。以下是如何使用 Linux shell 展開檔名的其他範例...

  magick image_[0-9].gif  image_[1-9][0-9].gif  animation.gif
  magick image_?.gif  image_??.gif  image_???.gif  animation.gif
  magick image_(?|??|???|????).gif  animation.gif
另請參閱下面的讀取影格、讀取修飾符,了解檔名中格式化的遞增數字。如果檔名只是單個字元字串「-」,則 IM 從標準輸入讀取影像。

  cat tree.gif | magick - -frame 5x5+2+2 read_stdin.gif
[IM Output]
請注意,某些影像檔案格式允許您將多個影像檔案簡單地附加在一起,形成一個長的多影像串流。這些格式包括簡單的 PbmPlus/NetPBM 影像格式,以及 IM 自己的特殊檔案格式 MIFF:

  for image in eye.gif news.gif storm.gif
  do
    magick $image  miff:-
  done |
    magick - -frame 5x5+2+2 +append read_multiple_stdin.gif
[IM Output]
檔名開頭的特殊字元「@」表示將檔名替換為給定檔案的內容。也就是說,您可以讀取包含檔案列表的檔案!

  echo "eye.gif news.gif storm.gif" > filelist.txt
  magick @filelist.txt  -frame 5x5+2+2 +append filelist.gif
[IM Output]
您也可以將「@」與特殊檔名「-」一起使用,以從標準輸入讀取檔名。

  echo "eye.gif news.gif storm.gif" |\
    magick @- -frame 5x5+2+2 +append filelist_stdin.gif
[IM Output]
在 IM v6.5.2-1 中添加了使用「@」語法從檔案中讀取檔名列表的功能。
作為安全預防措施,這僅適用於實際的影像檔案。它不適用於影像產生器,例如「rose:」或「label:string」。它也不能用於從檔案中「包含」命令列選項。

讀取修飾符或提取設定

影像可以在讀入記憶體後立即進行修改,但在實際將影像添加到當前影像序列之前。您可以指定「-extract」設定。例如,我在這裡裁剪玫瑰影像...

  magick -extract 32x32+20+5 rose: +repage rose_extract.gif
[IM Output]
或者,您可以使用方括號「[...]」將讀取修飾符附加到檔名的末尾。例如...

  magick 'rose:[32x32+20+5]' +repage  rose_read_modifier.gif
[IM Output]
但請注意, '[]' 字元通常也是特殊的 shell 中繼字元,因此如果您使用它們,最好將額外的修飾符號用引號括起來,以防止 UNIX shell 對其進行解釋。「-extract」設定和讀取修飾符號的功能相同,但後者會覆蓋前者。此外,當您使用修飾符號時,您必須讓 IM 處理任何特殊的檔案展開中繼字元,例如 '*' 和 '?',因為 UNIX shell 不會因為修飾符號而「找到」請求的檔案。在這種情況下,它的實際作用取決於 shell。因此,在使用讀取修飾符號時,應將整個檔案名稱用引號括起來。這些讀取修飾符號的真正目的是透過移除不需要的影像或縮小影像尺寸來限制所需的記憶體量,同時仍將影像讀入記憶體。例如,當讀入整個目錄的大型 JPEG 影像時。以下是所有特殊讀取修飾符號(以及「-extract」設定)及其效果的清單。 '#' 代表某個數字。
'[#]' '[#-#]' '[#,#,#]' [#,#-#,#]'. 讀取影格
將從已讀入的影像的多影像檔案格式中選擇特定的子影格。給定的數字 '#' 索引指定要讀取的影格編號。可以在逗號順序或索引範圍中指定多個索引。影像索引從第一個影像的零開始,第二個影像的索引為 1,依此類推。如果您指定負索引,則計數從影像序列的末尾開始,以相反的順序排列,-1 表示最後一個影像,-2 表示倒數第二個影像。這與 影像列表運算子 所使用的慣例完全相同。例如

  magick document.pdf'[0]'     first_page_of_pdf.gif
  magick animation.gif'[1-3]'  second_to_fourth_frames.gif
  magick animation.gif'[-1,2]' last_then_the_third_frame.gif
您也可以讓 IM 根據數字列表讀取影像。例如..

  magick 'image_%03d.png[5-7]' ...
將讀入檔案「image_005.png」、「image_006.png」和「image_007.png」。使用此方法,您不能使用負索引。
'[#x#]' 讀取調整大小
從 IM 版本 6.2.6-2 開始,新增了一個新的修飾符號,以幫助 IM 使用者處理非常大的影像。此修飾符號將在將剛讀入的影像新增到記憶體中已存在的其他影像之前立即調整其大小。
這可以縮小影像或放大影像。例如...

  magick pattern:gray95'[60x60]' enlarged_dots.gif
[IM Output]
警告:讀取修飾符號目前不使用任何調整大小標記,例如 '!'(不保留長寬比)或 '>'(僅縮小較大的影像。(如果您提出請求,可能會使用)您也可以將其用作指定純色畫布大小的替代方法。實際上發生的事情是它正在調整預設單像素影像的大小。例如...

      magick 'canvas:DodgerBlue[50x50]'  canvas_size.gif
    
[IM Output]
當您嘗試讀入大量非常大的影像時,修飾符號最重要,因為每個影像在讀取下一個影像之前都會調整大小,從而顯著節省處理這些影像所需的總記憶體。例如,不要...

  magick montage '*.tiff'  -geometry 100x100+5+5 -frame 4  index.jpg
它會先讀入所有 tiff 檔案,然後調整它們的大小。您可以改為執行...

  magick montage '*.tiff[100x100]'  -geometry 100x100+5+5 -frame 4  index.jpg
這將讀入每個影像並調整其大小,然後再處理下一個影像。從而減少記憶體使用量,並可能防止在達到記憶體限制時出現磁碟交換(磁碟震盪)。對於 JPEG 影像,我也建議您使用特殊的「-define」設定,產生類似於...

  magick montage -define jpeg:size=200x200 '*.jpg[100x100]' -strip \
          -geometry 100x100+5+5 -frame 4  index.png
這個特殊設定會被傳遞給 JPEG 函式庫,並用於在讀取過程中限制 JPEG 影像的大小。 但這並非精確值,產生的影像大小會介於該大小或兩倍大小之間,同時保持長寬比。 如需更多詳細資訊,請參閱讀取 JPEG 影像。 其組合的結果是讀取速度更快,JPEG 影像的記憶體使用量更低。 尤其是在產生大量小縮圖時。 請參閱一般縮圖建立
'[#x#+#+#]' 讀取裁剪
從 IM v6.3.1 開始,如果您還添加了偏移量,則上述內容將成為讀取的影像的裁剪區域。 例如,要從更大的影像中取得較小的 600x400 像素子區段。

  magick 'image.png[600x400+1900+2900]' tileimage.png
但是,這會將整個影像讀入記憶體,然後在最終將其添加到當前影像序列之前對其進行裁剪。 如果您想處理非常大的影像,我建議您查看“stream”命令,並將您的影像通過管道傳輸到“magick”命令以進行進一步處理。 請參閱下面的巨量影像處理
如果影像是“gzip”壓縮的,IM 會在嘗試確定影像格式和解碼影像檔案格式之前自動將其解壓縮到一個臨時檔案中。 因此,您不僅可以 gzip 壓縮格式儲存影像,還可以直接在以後的 IM 處理中使用它們。 對於大型基於文字的影像,這可以節省大量的磁碟空間。
PNG 格式在其格式規範中包含“gzip”壓縮。 在這種情況下,兩位數 PNG“-quality”設定的第一位數定義了壓縮級別。 如需更多詳細資訊,請參閱PNG 影像檔案格式範例。
以上只是將影像讀入 ImageMagick 時可用的特殊輸入選項的簡要概述。 ImageMagick 網站上的命令列剖析頁面上提供了完整摘要。
如前所示,影像輸入可以通過一些 IM 設定進行修改,例如用於影像建立的“-size”和用於 JPEG 讀取的“-define jpeg:size=??”。 其他選項也會影響影像輸入的建立,包括“-page”、 “-type”、 “-dispose”、 “-delay”。 請參閱設定/變更影像中繼資料
在腳本中將使用者提供的參數傳遞給 IM 時要非常小心,確保參數符合您的預期。 例如,您不希望讓網路影像處理腳本返回系統密碼檔案的影像。

輸入檔名中繼字元處理

建構中
Not only does the shell handle meta-characters (unless that argument is
quoted) but IM also does its own form of meta-character handling in filenames.

For example
  magick *.jpg ....

is expanded by the shell BEFORE passing the filenames to IM, while

  magick '*.jpg' ....

will have the shell pass "*.jpg" to ImageMagick, which then expands into
an internal list of filenames!  This was provided for Windows Dos support, and
as a method to preventing command line limit overflows in command such as
"magick mogrify" and "magick montage", which typically process long lists of images.

As such to actually get IM to read a file names literially named on disk as
'*.jpg'  you need to use any of the following forms...

  magick '\*.jpg' ....
  magick "\*.jpg" ....
  magick "\\*.jpg" ....
  magick \\\*.jpg ....

NOTE; the second line is NOT recommended as some shells (not bash) and some
APIs (C programs, possibly PHP) may actually remove the single backslash, and
pass '*.jpg' to IM which it will again expand!

On top of '?' and '*',  IM also adds the meta-character handling of  ':', '%'
and '[...]' for read modifier handling.  These however have a different
meaning  (codec specification, scene number inclusion, and read modifiers) to
normal shell syntax of those meta-characters.

For example DOS uses will need to escape a 'drive-letter' in filename paths
being passed to ImageMagick.  For example...

  magick C\:\path\to\image.jpg ....

Another example is when loading an image containg a time code.  For example..

  magick "time_10\:30.jpg" ....

will read the filename "time_10:30.jpg" from disk.  Without the backslash, IM
may think that the image should be read with a non-existant image file format
(or delegate) "time_10:", and fail in an unexpected way.

An alternative is to use a question mark...

  magick "time_10?30.jpg" ...

However that may also match another file such as "time_10_30.jpg" as well!

壓縮影像

建構中
IM will also read files that have been compressed, and given the appropriate
suffix, or image format specification.

That is, an image saved as "image.gif.gz"  will first be uncomressed, before
being decoded from its GIF image format.

Gzipped XPixmap (xpm) and NetPbm/PbmPlus (ppm) images is also automatically
handled, both by Imagemagick, and the formats normal delegate library.  As
such you can use the compressed forms directly either in IM, or in other
programs that understand these file formats.

See  Saving Compressed Images below.

儲存影像

處理影像是很好,但以正確的方式儲存結果也同樣重要。 “magick”、 “magick montage”和“magick composite”的最後一個參數定義了檔名和影像格式,用於最終寫入影像(預設影像輸出)。 儘管您也可以使用“-write”在影像序列中間儲存影像(見下文)。 要指定要儲存影像或多個影像的檔案格式,可以使用檔名後綴(例如我在幾乎所有這些範例中使用的後綴),或在檔名前面加上字串“{format}:”。 例如...

  magick tree.gif    GIF:tree_image
[IM Output]
如果您檢查結果圖像,您會發現實際上建立了一個 GIF 圖像文件,即使文件名本身沒有「.gif」文件後綴。格式的大小寫不敏感,因此您可以使用小寫或大寫。當您想要將圖像保存到命令的標準輸出(使用「-」文件名)時,此圖像格式規範變得尤為重要。此特殊文件名沒有後綴,因此您*必須*告訴 ImageMagick 使用哪種格式。如果您不這樣做,圖像將默認為圖像來源的原始圖像格式(如果已知)。例如,這裡我們使用「-」將 IM 像素枚舉寫入屏幕,以將結果輸出到標準輸出。

  magick tree.gif  -resize 1x3\!  txt:-
[IM Text]
它也用於通過 shell「管道」將圖像傳遞給另一個命令,例如「magick identify」,而無需將其保存到臨時文件。

  magick tree.gif -resize 200% miff:- | identify -
[IM Text]
在這種情況下,您還可以發現特殊的「-」文件名也用於表示通過「magick identify」命令從標準輸入讀取圖像。有關更多信息,請參閱命令行的剖析,輸出文件名的官方指南。

檔名百分比跳脫字元

保存文件名可以包含一些特殊的百分號轉義(%)序列。具體來說,是「%d」、「%x」和「%o」。這些使用 C 語言的「printf()」格式將圖像的「場景編號」插入文件名中。有關更多信息,請參閱下面的寫入多圖像序列。當然,這意味著如果您想在文件名中插入百分號,則需要將其加倍(「%%」)。從 IM v6.4.8-4 開始,您現在還可以在最終文件名中插入預先準備好的特殊設置(必須以「filename:」開頭)。例如...

  magick rose: -set filename:mysize "%wx%h" 'rose_%[filename:mysize].png'
[IM Output]
這會將內置的玫瑰圖像保存到包含該圖像像素大小的文件中。具體來說,文件名為「rose_70x46.gif」。這將讓您(通過一些間接方式)使用任何圖像屬性百分號轉義作為輸出文件名的一部分。請注意,只有「%[filename:標籤]」圖像屬性可以在輸出文件名中使用(以及普通的「%d」轉義)。此限制出於安全原因,並且合法圖像文件名可能包含「%」和「[]」。警告:不要在文件名設置中包含文件後綴!IM 將不會看到它,並使用原始文件格式保存圖像,而不是包含在文件名設置中的文件格式。也就是說,文件名將具有您指定的文件後綴,但圖像格式可能不同!「filename:」設置不必對每個圖像都相同。您可以為正在使用的每個圖像生成,甚至計算或設置不同的設置。這是另一個示例,我在其中修改圖像,並將其寫入使用每個單獨圖像的原始文件名構建的新文件名。

  magick eye.gif news.gif storm.gif    -scale 200% \
          -set filename:f '%t_magnify.%e' +adjoin '%[filename:f]'
[IM Output] [IM Output] [IM Output]
這會將每個圖像(例如「eye.gif」)放大,並將其保存到當前目錄中的「eye_magnify.gif」文件中。但是,所有三個圖像都被讀入內存,然後由一個命令修改。由於可能達到內存限制並因此進行磁盤交換(抖動),因此不建議將此解決方案用於大量圖像或非常大量的圖像。請注意,在這種情況下,「+adjoin」對於防止 IM 將所有圖像保存到多圖像 GIF 動畫中至關重要,僅使用第一個圖像的文件名。我還確保使用「%e」轉義序列保留文件名的原始後綴。通常,在文件名設置中包含後綴是一個壞主意,因為 IM 在確定輸出文件格式時,不會在它來自轉義序列時看到它。但是,在這種情況下,格式沒有改變,所以沒有問題。需要注意的是。要獲取圖像的確切原始文件名,請使用「%d/%f」或「%d/%t.%e」。您也可以使用「%m」代替「%e」,它是 IM 在原始圖像文件中找到的實際格式(大寫)(可能與原始圖像文件名後綴不匹配)。請注意,對於內置圖像,許多這些轉義序列字符串都是空白的。此外,如果沒有目錄,「%d」將為空。這是 IMv7 的一個已知問題。另一個使用「文件名轉義序列」的例子是在平鋪裁剪圖像中,該技術用於根據計算出的平鋪位置為每個生成的圖像生成文件名。另請參閱使用轉換而不是 Morgify中的示例。

自動 GZip 後綴

如果給出「.gz」後綴,IM 還將自動「gzip」圖像。例如,在這裡我將內置的「rose:」圖像保存為「gzip」ed、未壓縮的 GIF 文件。我關閉了 GIF 的正常 LZW 壓縮,因為它會阻止「gzip」壓縮實現其最佳壓縮。

  magick rose: -compress none  rose.gif.gz
[IM Output]
瀏覽器如何處理 gzip 圖像取決於 Web 服務器返回的文件類型以及瀏覽器如何處理壓縮圖像。因此,我沒有直接顯示上面的圖像。單擊「藝術」圖標,查看您的瀏覽器對此 Web 服務器中的此類圖像的處理方式。將此大小與正常保存的 LZW 壓縮 GIF 圖像進行比較...

  magick rose: rose.gif
[IM Output]
gzip」ed rose 的大小為[IM 文字]字節,而正常的 LZW 壓縮 rose 的大小為[IM 文字]字節。如您所見,GZIP 壓縮實際上比 GIF 格式使用的 LZW 壓縮略好,因此可能更適合於歸檔目的。GZip 圖像文件更常用於長期存儲默認情況下没有任何壓縮的圖像文件格式。這包括 IM 文件格式「MIFF:」和更簡單的NetPBM圖像文件格式。

已儲存屬性

建構中
Other Settings specific to image writing....
    -depth  -quality  -compress -type  -loop
    -set label   -set comment
Also see Image Depth,
Image Type,
JPEG Quality,
PNG Quality.
GIF loop.

Talk about file compressions, which are part of various image formats.

Different compressions are used for different image formats.

Especially the JPEG to TIFF compression change needed.

Using or "-compress
None" and "-compress" NetPBM text/binary format selection.

The GIF compression and the copyright patent.

Other than using IM to reduce -quality or changing the format to something
else the -compression option is rarely used.  Often it is only used internally
by IM to save images using the same compression the image was read with.

加密影像

IM 還允許您使用選項「-encipher」和「-decipher」保存使用密碼加密的敏感圖像。請參閱加密圖像

寫入多個圖像 - 並排技術

儲存影像的一大問題是 ImageMagick 是以有序序列(清單)處理影像,而不是一次只處理一張影像。因此,IM 會嘗試將目前影像序列中的所有影像寫入給定的檔名中。如果檔案格式允許多個影像,IM 預設會將目前影像序列中的所有影像儲存到該影像檔案中。例如,如果您查看GIF 動畫基本知識範例頁面,您將看到它會將多個影像影格儲存到單一影像檔案格式中以產生動畫。如果輸出格式不允許您將多個影像儲存到一個檔案中,IM 將改為產生多個檔案。例如,儲存為 JPEGPNG 等影像格式時。您也可以對允許每個檔案包含多個影像的影像格式強制執行此行為,例如 GIFPS,方法是使用「+adjoin」輸出檔案處理設定。

  magick eye.gif news.gif storm.gif  +adjoin  image.gif
[IM Output] [IM Output] [IM Output]
如果您仔細查看上面產生的三個影像的檔名,您將看到 IM 產生了名為「image-0.gif」到「image-2.gif」的影像。
在 ImageMagick 6.2.0 版之前,上述輸出的檔名會是「image.gif.0」到「image.gif.2」。由於檔名後綴遺失,這導致許多問題,因此已更改為在檔名後綴之前新增影像編號。
另一種方法是在輸出檔名中新增「C 語言 printf()」建構「%d」。這個特殊字串將會替換為序列中每個影像的目前影像編號。

  magick eye.gif news.gif storm.gif  +adjoin  image_%d.gif
[IM Output] [IM Output] [IM Output]
在這裡,我們產生了影像「image_0.gif」到「image_2.gif」,使用底線而不是 IM 預設的破折號。
您不僅可以使用「%d」表示十進制數,還可以可以使用「%x」表示十六進制數(小寫)、「%X」表示十六進制數(大寫)或「%o」表示八進制數。

如果您真的想要一個百分比符號,後面跟著這些字母中的一個,那麼您需要將百分比符號加倍以跳脫其含義。也就是說,您需要使用「%%」來確保您實際上產生的是一個百分比符號。

輸出檔名中的「%d」實際上會自動啟用 ImageMagick 的「+adjoin」設定。
然而,雖然我在上面實際上不需要「+adjoin」,但最好還是提供它,只是為了清楚表明您正在產生單獨的影像。
這對於少量影像很有效,但如果您有超過十個影像,您將會得到一個位數和兩位數混合的影像。如果您有超過一百個,您也會得到三位數。發生這種情況時,目錄清單將不再按順序列出已儲存的影像,因為「image_15.gif」會按字母順序出現在「image_5.gif」之前。當然,有一些方法可以解決這個問題。例如,使用命令列 shell 運算式,如..

  magick image_[0-9].gif  image_[1-9][0-9].gif  animation.gif
  magick image_?.gif  image_??.gif  image_???.gif  animation.gif
  magick image_(?|??|???|????).gif  animation.gif
  magick 'image_%d.gif[0-123]'  animation.gif
最後一種方法是處理檔案序列的正確 IM 方法,但您需要知道要使用的數字範圍。「%d」會將每個數字格式化以符合檔名(請參閱下文)在任何情況下,這很麻煩且容易出錯,如果檔案遺失可能會產生錯誤,並且可能取決於您使用的電腦系統類型。最好完全避免這個問題。如果您熟悉「C」語言(請查看 UNIX 系統手冊頁以了解「printf」),那麼您可能知道,如果您使用「%03d」之類的內容,您將始終獲得 3 位數的影像序列影格編號(帶前導零)。在這種情況下,影像名稱將是「images_000.gif」、「images_001.gif」等等。

  magick eye.gif news.gif storm.gif  +adjoin  image_%03d.gif
[IM Output] [IM Output] [IM Output]
使用這種方法,圖像不僅會被編號,而且還會按字母順序列出,這使得圖像文件的處理變得更加容易。因此,我建議您在計劃將多個圖像寫入單獨的圖像文件時,在輸出文件名中添加「%03d」或其他適當的內容。

寫入場景編號

如果您希望圖像序列從「1」而不是「0」開始,並且不想重命名所有生成的圖像文件,最簡單的解決方案是在要寫入的序列前面添加一個「垃圾」圖像。

  magick null:  eye.gif news.gif storm.gif  +adjoin  image_%01d_of_3.gif
  rm image_0_of_3.gif
[IM Output] [IM Output] [IM Output]
當然,您可以在圖像處理後使用「+insert」來做到這一點。這並不是一個特別好的解決方案,但它有效、簡單,並且與舊版本 IM 相容。從 IM 6.2 版本開始,您可以使用「-scene」設置來設置當前圖像序列的起始編號。

  magick eye.gif news.gif storm.gif  +adjoin -scene 101 image_%03d.gif
[IM Output] [IM Output] [IM Output]
這將產生圖像文件「image_101.gif」到「image_103.gif」。

寫入影像多次

在寫入圖像的主題上,可以使用特殊的「-write」圖像運算符從一系列圖像操作的中間寫入圖像。當您希望在圖像處理過程中的不同點輸出圖像多次時,這非常有用。例如,請參閱使用調試進行複雜圖像處理。這是一個例子,我有一張鸚鵡的照片,由柯達無損真彩色圖像套件(圖像 23)提供,但我想使用一個命令將它們保存為一系列不同的尺寸...

  magick parrots_orig.png \
          \( +clone -resize x128  -write  parrots_lrg.jpg +delete \) \
          \( +clone -resize x96   -write  parrots_big.jpg +delete \) \
          \( +clone -resize x64   -write  parrots_med.jpg +delete \) \
                    -resize x32           parrots_sml.jpg
[IM Output] [IM Output] [IM Output] [IM Output]
如您所見,我們可以使用圖像列表運算符來處理圖像的「副本」,寫入結果,然後刪除並返回到原始源圖像,根據需要重複此過程多次。在這種特殊情況下,這意味著我不必一遍又一遍地調整相同圖像的大小,從而累積調整大小錯誤。這也意味著我可以輕鬆地先生成較小的圖像,然後再生成較大的圖像,而不會出現問題,或者為每個生成的圖像文件以不同的方式修改圖像。也就是說,每個圖像的順序和修改是無關緊要的!請注意,「+clone」實際上並不會複製圖像數據!IM 使用引用計數克隆過程,該過程僅在更新圖像像素時才複製它們。因此,在上述過程中,實際上只使用了足夠的內存來保存原始圖像和生成的圖像。這也使得「+clone」非常快速且節省內存。
以下是執行相同操作的另一種技術,但使用「MPR:」(見下文)而不是「-clone」將原始圖像保存在命名的圖像寄存器中。

  magick scroll.gif  -background lightsteelblue -flatten  -alpha off \
          -write mpr:scroll  -resize x128  -write scroll_lrg.jpg +delete \
                 mpr:scroll  -resize x96   -write scroll_big.jpg +delete \
                 mpr:scroll  -resize x64   -write scroll_med.jpg +delete \
                 mpr:scroll  -resize x32          scroll_sml.jpg
[IM Output] [IM Output] [IM Output] [IM Output]
在修改記憶體中的影像並寫入之前,我們會先將原始影像的一個副本儲存到「mpr:scroll」影像暫存器中。請注意,MPR 暫存器實際上可以儲存一整個影像序列。一旦該操作的結果被寫入並從記憶體中刪除,原始影像(或影像序列)就會被恢復,並根據需要重複該過程多次。當然,如前所述,在最後一個影像上不需要使用「-write」,因為我們可以像往常一樣將其輸出。如果您確實使用了「-write」,則可以使用另一個特殊檔案格式「NULL:」來捨棄最後一個影像(見下文)。關於「-write」的警告:由於某些檔案格式要求影像採用特殊格式才能寫入,「-write」運算子可能會修改影像。例如,GIF 影像可能會降低色彩深度(請參閱量化和抖動)。但是,其他格式會保留原始影像(請參閱下面的MIFFMPC)。如果您需要避免這些變更(因為您不僅僅是在之後刪除影像),可以使用「+write」,它會建立影像的內部副本以供寫入,然後再將其刪除。但是請記住,這可能會導致記憶體使用量增加一倍,以儲存寫入修改後的影像副本。至少在短時間內是這樣。

特殊檔案格式(IM 特定)

如您在上面看到的(並將在下一節常用影像檔案格式中探討),ImageMagick 理解大量的知名影像檔案格式。它還包含大量的特殊影像產生器(如畫布建立中所舉例)。除此之外,還有一些非常特殊的檔案格式,允許對影像進行一些非常特殊的處理。
miff:
是 ImageMagick 檔案格式。整個影像序列和與影像相關聯的「所有」屬性都儲存在此檔案格式中。當然,只有 ImageMagick 命令才能讀取此格式,因此它不適合在不同的影像處理軟體包之間傳輸。「miff:」檔案格式的主要用途是在以長時間和複雜的方式處理影像時作為中間儲存格式。當將影像從一個 IM 命令「管道傳輸」到另一個 IM 命令時,它也適用於傳遞影像中繼資料和其他與影像相關聯的屬性。我建議在寫入「miff:」時包含「+depth」選項。這會將影像的「輸入深度」重置為 IM 記憶體品質,以便為中間影像儲存使用最佳品質。當然,您可以使用「-depth 8」來「裁剪」儲存影像深度,以減少磁碟上的影像大小,但是這也會強制執行量子舍入效應(除非也啟用了HDRI 浮點數儲存)。對於那些有興趣解析此格式的人來說,它以包含所有影像屬性的純文字標頭開頭。標頭以包含單個換頁字元的行結尾。此標頭本身是一種在各種影像處理腳本中提取基本影像資訊的實用方法。例如,這裡我使用 GNU-sed 命令列出「miff:」標頭直到換頁分隔符號,顯示內建「rose:」影像的所有屬性。


magick rose: miff:- | sed -n '/^\f$/q; p'
[IM Text]
這實際上非常有用,因為它揭示了 IM 了解的圖像的所有當前設置標誌和元數據。但是,也有一些統計信息,因為這些信息是由“magick identify”命令、“-identify”操作符或特殊的“info:”格式生成的;如果使用“-verbose”選項請求的話。(見下文)圖像文件格式的解析要求非常低,雖然沒有壓縮,但可以處理 IM 知道的任何類型的圖像。對於臨時圖像和您可以使用的流水線圖像命令來說,它幾乎是最理想的格式,儘管 ImageMagick 程序是唯一可以讀取它的程序。另請參見下面的“MPR”圖像內存寄存器和“MPC”內存磁盤映射格式。
原始圖像數據(二進制)實際上以四個字符序列“\n\f\n:”(換頁符在一行上,後面跟著一個冒號)作為前綴。這些數據應該如何讀取的編碼在標頭數據中,但通常由 RGB 元組中的二進制整數組成。但可以有更多通道,甚至可以由浮點數甚至雙精度數據值組成。

在很多方面,它實際上與二進制 PbmPlus 圖像文件格式相同,只是標頭大大擴展以保存圖像元數據,並且通道數量和數據類型有更多變化。
MIFF 圖像串流
miff:”格式是一種“串流”圖像文件格式。也就是說,多個圖像的處理只需將圖像一個接一個地附加或串聯在一起即可。這意味著您可以生成多個圖像的“流”,只需將圖像寫入相同的目的地,例如管道。即使單個圖像是由不同的命令生成的。例如,您可以擁有一個圖像處理命令循環,每個命令僅輸出一個“串流”MIFF 圖像。循環之後,您可以將圖像“流”通過管道傳輸到單個命令中,以生成蒙太奇、拼貼畫、動畫或其他內容。例如,以下內容生成了一個以字母“b”開頭的顏色列表,然後使用“magick”命令循環生成帶標籤的色塊,一次一種顏色。然後將這些“通過管道傳輸”到“magick montage”中以生成簡單的顏色表。

  magick -list color | egrep '^b' | \
    while read color junk; do \
       magick -label $color -size 70x20 xc:$color +depth miff:-; \
    done |\
      magick montage - -frame 5 -tile 6x -geometry +2+2 \
              -background none color_table.png
[IM Text]
上面的具體示例已編程到腳本“show_colors”中,您可以使用該腳本搜索、查找和顯示顏色,以便在圖像處理中使用。上面是一個“串流圖像管道”的示例,它對於生成多圖像序列非常有用。此技術的其他示例包括 分層圖像的程序化定位地圖中的圖釘按名稱顏色 中的“命名顏色圖像”以及隨機漣漪 中顯示的動畫。此技術也可以與“-write miff:-”等操作一起使用,以便從單個命令中的多個位置輸出 miff 格式的圖像。每個圖像都將在最終輸出流中自動附加在一起。這對於調試複雜的圖像處理命令特別有用。另一種方法(通常在 PHP 腳本中使用)是使用“生成命令”技術,該技術使用 shell 腳本生成要運行的長“magick”命令。圖像扭曲動畫 中的腳本使用了這種技術。
info:
info:」檔案格式(IM v6.2.4 中新增)*不會*輸出實際圖像!此格式基本上會輸出與 ImageMagick「magick identify」指令相同的資訊。與「magick identify」相同,此輸出格式由「-format」和「-verbose」選項控制,允許您根據圖像屬性轉義頁面中的定義,僅輸出您感興趣的特定資訊。例如,我們可以使用以下指令來擷取結果圖像格式的單行識別,而不是像上面那樣(請參閱儲存圖像)將 MIFF 圖像管道傳輸到「magick identify」。

  magick granite:  info:-
[IM Text]
當然,您可以使用「-format」設定以特定且更易於解析的方式輸出所需的資訊。「info:」的實用之處在於,您現在可以生成圖像,同時提取有關圖像的額外資訊。這是通過使用「-write」運算符將此特殊圖像格式儲存到檔案(或指令的正常標準輸出)來完成的。

  magick rose: -shave 12x0 -repage 64x64+9+9 \
          -format '%wx%h %g'  -write info:info_paged.txt    paged.gif
[IM Output]
[IM Text]
還有一個「-identify」運算符,它等效於使用「-write info:」將圖像識別資訊輸出到標準輸出。這使得在除錯 IM 指令時更容易監控圖像的變化。例如...

  magick logo:           -identify \
          -trim           -identify \
          +repage         -identify \
          -resize 80x80\! -identify \
          logo_thumbnail.gif
[IM Output]
[IM Text]
在這裡,您可以看到「-trim」如何減小圖像的大小,但保留了圖像哪一部分被修剪的「裁剪」資訊,然後「+repage」刪除了額外的「畫布」或「頁面」資訊,依此類推。同樣,與「magick identify」指令一樣,如果啟用了「-verbose」設定,「info:」和「-identify」都會變得更加詳細。在這裡,我將長輸出限制為僅顯示前幾行,以便您對其有所了解。

  magick rose: -verbose  info:  | head
[IM Text]
-verbose」設定還會導致將有關讀入或讀出圖像的額外資訊列印到標準錯誤輸出(「info:」格式除外)。它還會導致某些運算符(如「-colors」)輸出額外資訊。因此,您可能希望在將其與「-identify」或「info:」格式一起使用後將其關閉。

例如  
-verbose -write info:image_info.txt +verbose  或  -verbose -identify +verbose
以程式設計方式讀取任何形式的「identify」的輸出時,應以區分大小寫的方式進行。這確保了不同版本的 ImageMagick 之間更好的向後相容性。
注意:「info:」(和「-identify」)只是一種輸出格式,產生的輸出與「identify」指令相同。您無法使用「info:」檔案格式讀取或建立圖像。您也可以使用「-print」來列印資訊,但这只會針對整個圖像序列套用一次。這表示您可以使用此運算符來計算涉及多個圖像的更複雜的「%[fx:...]」運算式。但請記住,與上述其他方法不同,它只會在所有圖像中套用一次。
null:
作為輸出格式,這將會「丟棄」圖像結果。因此,如果在 "magick", "magick montage" 或 "magick composite" 命令中將其用作最後一個參數,則最終結果將不會被儲存!為什麼?因為您可能對圖像處理過程中產生的特定圖像比整體結果更感興趣,尤其是在除錯時。例如,這裡我們從圖像序列中提取並儲存一個圖像,然後使用 "null:" 丟棄所有其他圖像。

  magick eye.gif news.gif storm.gif tree.gif rose: logo: \
            \( -clone 2 -write write_storm.gif \)   null:
[IM Output]
這比嘗試一次刪除所有其他圖像要簡單得多。但是,作為輸入圖像格式,"null:" 將在目前的圖像序列中產生一個帶有特殊「空來源」標記的單一透明像素的特殊佔位符圖像。這個特殊的圖像對於 在蒙太奇中保留空白 以及作為多圖像 圖層合成 的列表分隔符尤其重要。它與另一個稱為「遺漏圖像」的特殊圖像格式密切相關,後者可以通過 "-crop" 等操作產生。當操作產生空結果或無意義的結果時,就會產生這種圖像格式。這兩種圖像都是單一透明像素,因此 "null:" 圖像也將被視為「遺漏圖像」。目前還沒有方法可以從目前的圖像序列中移除任何 "null:" 甚至「遺漏圖像」。不過,已經有人提出了這樣的方法。如果您發現自己需要這樣的方法,請發郵件給我。
txt:
這是一個簡單的 ASCII 文字檔案,基本上列出了圖像中的每個像素,每行一個。它不是一個通用的文字轉圖像轉換器,關於這一點,請參閱 多行文字檔案範例。如果「像素列舉」無法辨識,則圖像將被傳遞到 "text:" 格式編碼器,以純文字檔案的形式呈現。例如,這裡有一個 "netscape:" 圖像縮放到 2x2 像素的圖像,然後使用 "txt:" 圖像格式列出。

  magick netscape: -scale 2x2\! txt_netscape.txt
[IM Text]
圖像的第一行(標題)包含了圖像的基本資訊。這些資訊包括... *檔案魔數:* 圖像標題將此檔案定義為特殊的 IM 文字圖像格式(例如「ImageMagick 像素列舉」檔案),這在電腦領域被稱為檔案的「魔數」或代碼串,用於識別此檔案屬於此特定檔案格式。 *圖像大小:* 接下來的兩個數字定義了此檔案中包含的圖像的大小。將這兩個數字相乘,您還可以知道應該在標題後面跟隨多少行才能完整定義圖像。IM 總是會輸出這麼多行,不過正如您稍後在閱讀時將會看到的那樣,您並不需要定義*所有*像素。 *最大值:* 標題中的最後一個數字定義了圖像資料可能出現的「最大值」。在上面的例子中,這個值是 '255',這是使用 8 位元深度產生的結果。它以這種深度輸出內建的 "netscape:" 圖像的原因是,它在內部是使用 8 位元值定義的,因此 IM 保留了圖像的這個深度級別。有關更多資訊,請參閱 深度設定 部分。但是您可以覆蓋深度設定(最高可達您的 IM 的 Q 或 編譯時品質 設定的限制),方法是更改圖像的 "-depth"。例如,這裡我將顏色值輸出為 16 位元值(從 0 到 65535)...

  magick netscape: -scale 2x2\! -depth 16 txt_netscape_16.txt
[IM Text]
目前,您無法設定要在輸出檔案格式中使用的特定「最大值」。您只能根據目前的 "-depth" 設定定義不同的值,使最大值等於 2^depth-1
色彩空間: 標題中的最後一項定義了後續數據的 色彩空間。如果圖像包含任何透明度,則還會在色彩空間名稱後附加最後一個字母「a」(表示 alpha),並在括號之間添加額外的數字列。灰階圖像將輸出「grey」作為圖像,但將定義至少三個數字,這些數字對於每個像素將是相同的值。例如,以下是使用添加了 alpha 通道的「LAB色彩空間 的相同圖像!

  magick netscape: -scale 2x2\! -colorspace LAB -alpha set txt_cspace_lab.txt
[IM Text]
初始標題之後是「像素數據」行,圖像中的每個像素一行。坐標: 冒號「:」之前的兩個數字是像素位置,從 0 開始。顏色值: 此後,像素的顏色值(從 0 到標題中給定的「最大值」)在括號中給出,根據圖像的當前色彩空間,可以是 3 到 5 個數字。空格是可選的,因此在解析括號中的數字時建議謹慎。
這些值通常是整數。但是,從 IM v6.9.2-1 開始,如果使用「-depth 16」給出特殊定義「-define txt:compliance=css」,則這些值將表示為帶有「%」符號的百分比值。這是 SVG、CSS 規範的一部分。
顏色註釋: 括號中的數字之後的任何內容都被視為註釋。IM 將使用可以解析為顏色參數的格式來填充有關像素顏色的額外信息(有關這些顏色規範的詳細信息,請參閱「-fill」手冊條目)。但是,顏色註釋是可變的,儘管它通常以井號(「#」)十六進制顏色值開頭,之後可能會輸出 RGB() 值或顏色名稱,具體取決於給定的像素數據。這些顏色名稱應該可以被 ImageMagick 理解,但僅供參考,因為它純粹是一個註釋。提供哪些顏色高度依賴於您使用的 IM 版本,尤其是在早期的 IM v6 版本和之前的版本中。不能保證此註釋區域將來不會再次更改,因此最好不要依賴它。IM 在讀取像素枚舉圖像時不會這樣做。以下是在 shell 腳本中正確讀取像素枚舉的示例。TXT 圖像的確切格式由 convert 命令定義,然後使用「tail」刪除標題,「tr」將每個非數字字符替換為單個空格,以便後面的「while」可以輕鬆讀取數字,刪除可能留下的任何後續註釋號碼。

  magick rose: -resize 3x2\! -depth 8 -colorspace RGB -alpha off txt:- |
    tail -n +2 | tr -cs '0-9.\n'  ' ' |
      while read x y r g b junk; do
        echo "$x,$y = rgb($r,$g,$b)"
      done
[IM Text]

讀取 TXT 圖像也是有效的。您不需要定義圖像中的所有像素。事實上,您甚至不需要按正確的順序排列像素!ImageMagick 只會依次讀取每條定義像素的行,並將其「繪製」到空白圖像畫布上。只有每行括號中的數字用於此目的,而不是顏色名稱。初始空白畫布被清除並設置為當前背景顏色。因此,「txt:」圖像未提供的任何像素都將保留為此顏色。有關「txt:」圖像的有趣用途,請查看正向像素映射,其中我輸出了一個枚舉像素圖像,然後更改每個像素位置以旋轉(扭曲)圖像,然後將枚舉像素圖像讀回 IM。在生成的圖像中,某些像素位置未定義,而其他位置則添加了多個像素。IM 毫無問題地處理了這個問題。
txt:」格式在搭配「-unique-colors」運算子時特別有用,它會將目前影像序列中的每個影像替換為一個新的影像,其中包含找到的每種獨特色彩的一個像素。當輸出為「txt:」格式的檔案時,您將獲得影像中所含色彩的基本摘要(但不包含其計數或直方圖)。例如,以下是樹木影像所使用的色彩。由於 GIF 只能使用 8 位元數字,因此色彩也以相同的 深度 輸出。

  magick tree.gif -unique-colors txt:-
[IM Output]
[IM Text]
除了使用 IM「txt:」格式之外,還有另一種選擇,就是使用各種 NetPBM 影像檔案格式。IM 預設會將此格式輸出為二進制,但您可以關閉「-compress」來輸出 NetPBM 格式的 ASCII 文字版本。例如。

    magick tree.gif -unique-colors -compress None -depth 8 tree_netpbm.ppm
[IM Text]
您可能會注意到,以上數字與 IM 的列舉像素(「txt:」)格式中的數字相符。如需產生 IM 可讀取的 NetPBM 格式影像的一些範例,請參閱調整大小的漸層。如果您只想取得特定像素的色彩,您可以將影像裁剪為一個像素,並將其輸出為「txt:」影像。

  magick rose: -crop 1x1+12+26 txt:
[IM Text]
或者,您可以使用特殊的 FX Escape 格式 以 IM 可直接使用的形式輸出色彩。

  magick rose: -format '%[pixel:u.p{12,26}]' info:
[IM Text]
另請參閱提取影像色彩
sparse-color:
這是一種特殊的輸出影像格式,它將傳回一個簡單的逗號分隔清單,其中包含每個非透明像素的座標和色彩。輸出字串適合直接輸入到稀疏色彩運算子。例如,這會在「rose:」影像中找到最接近純紅色的一些像素。

  magick rose: -alpha set -fuzz 13% +transparent red sparse-color:
[IM Text]
在許多方面,這比上面顯示的「txt:」格式更有用,但前提是只涉及幾個像素。但請注意,在撰寫本文時,輸出全部在一行中。Shell 腳本可能會將輸出中的空格轉換為換行符。
histogram:
這實際上是「miff:」影像格式,但帶有一個非常大的影像註釋,其中包含影像中所有色彩的完整計數。也就是「miff:」文字標頭「Comment={...}」屬性中。例如,我們再次列出「tree」影像中存在的色彩,但這次包含每種色彩的像素計數。文字直方圖註釋是使用第二個「info:」格式的 magick identify 從「histogram:」影像中提取的。

  magick tree.gif  -define histogram:unique-colors=true \
           -format %c histogram:info:-
[IM Output]
[IM Text]
info:」輸出格式已添加到 IM v6.2.4 中。對於此版本之前的 IM 版本,請使用..

  magick tree.gif histogram:- | identify -format %c -
您會注意到,該格式與之前的 TXT 或 IM 像素列舉影像格式幾乎完全相同,包括對色彩值的註釋。唯一的區別是 X,Y 位置已被像素計數所取代。
建立此註釋可能需要很長時間。從 IM v6.6.1-5 開始,您可以添加特殊設定「-define histogram:unique-colors=false」,如果您不需要此註釋產生,則可以關閉它。
影像本身是一個直方圖,大小為 256x200 像素。x 軸是色彩值(0-255),y 軸是像素計數(標準化為像素數)。每個通道的直方圖以其代表的色彩顯示,並加在一起。因此,紅色和藍色重疊形成洋紅色。換句話說,每個色彩通道都有自己的獨立直方圖。
如果您想將影像轉換為其他格式,只需將其儲存為該格式。「histogram:」是一種特殊的影像處理格式。它會對影像進行處理,然後以檔案名後綴或其他「格式:」代碼指定的格式輸出。

  magick rose: \
          -define histogram:unique-colors=false \
          histogram:histogram.gif
[IM Output]
非常暗的影像會在直方圖左側形成高峰,而明亮的影像則會在右側形成高峰。同樣地,中間色調會在直方圖中間呈現。為了更清楚地說明,我將各個顏色通道的直方圖分開顯示。我也移除了直方圖文字註解(如果有的話),並調整了影像大小以便顯示。

  magick histogram.gif -strip -resize 50% -separate  histogram-%d.gif
[IM Output]
紅色
[IM Output]
綠色
[IM Output]
藍色
在上面的「rose:」影像中,您可以看到紅色分佈較廣,顯示出它在影像中的重要性。另一方面,綠色和藍色在左側形成峰值,表示它們對影像的影響很小。
如果您對影像的亮度比對其顏色更感興趣,請在產生「histogram:」影像之前,將影像轉換為灰階。

  magick rose: -colorspace Gray \
          -define histogram:unique-colors=false \
          histogram:histogram_gray.gif
[IM Output]
如您所見,灰階影像的直方圖略有不同。由於主要的紅色變成了更接近中間色調的灰色,因此在直方圖的中心形成了一個峰值。此外,影像中少量的灰白色區域現在在圖表的右側形成了一個明顯的峰值。最左側完全空白的區域也表明影像中沒有任何暗區。
另一方面,可以通過簡單地將原始影像中的所有顏色通道分離並附加在一起來產生更好的「全局」直方圖。生成的直方圖表示所有顏色值,而不管該值來自哪個通道。

  magick rose: -separate -append \
          -define histogram:unique-colors=false \
          histogram:histogram_values.gif
[IM Output]
遺憾的是,由於「histogram:」是一種輸出格式,如果您想進一步處理影像,您需要將影像「管道」到另一個命令、將其保存到磁碟,或者使用特殊的「mpr:」保存/讀取功能。請參閱下方「mpr:」中的範例。如果能將產生直方圖(和其他圖表)的方法作為運算符而不是特殊的輸出格式,那就太好了。
mpr:{標籤}
(記憶體程式寄存器)會將整個影像序列儲存到指定的記憶體寄存器中,之後您可以從中讀取影像數據。因此,如果您想將影像儲存起來供以後在複雜的影像操作中使用,您可以這樣做。在處理結束時寫入「mpr:」是沒有用的,因為程式記憶體在程式結束時會返回給系統。因此,如果您需要在不同的處理過程中使用影像,則需要使用寫入操作將影像儲存到檔案中。賦予「mpr:」的「標籤」可以是您喜歡的任何名稱,它只是影像在記憶體中儲存位置的標籤。對於那些編寫腳本且不想處理名稱的人來說,它甚至可以只是一個簡單的數字,儘管名稱可以使您的腳本更易於理解。儲存影像後(請參閱下方),您可以根據需要多次從相同的「標籤」記憶體位置再次讀取影像。例如...

  magick tree.gif -write mpr:tree  +delete \
          \
          mpr:tree  mpr:tree  mpr:tree   +append  mpr.gif
[IM Output]
請注意上述影像處理中「+delete」的使用。在上述範例中並非必要(只需重新讀取「mpr:tree」兩次而非三次),但將影像儲存在「mpr:」暫存器後,刪除目前影像序列中的所有影像是非常常見的做法。基本上,上述兩行可以視為兩個完全獨立的「magick」指令,但使用命名記憶體暫存器來儲存中間影像,而不是使用磁碟空間。在許多方面,使用「mpr:」類似於使用CloneDuplicate(我們在上述範例中可以使用),但使用「mpr:」允許我們完全移除所有影像,以清除目前的影像清單,以便進行其他工作。此方法的最大優點是,它也允許您使用僅適用於輸入影像的設定和操作。例如,將其與輸入影像「tile:」運算子一起使用,將影像平鋪到更大的區域。

  magick tree.gif -flip   -write mpr:tree  +delete \
          -size 64x64 tile:mpr:tree   mpr_tile.gif
[IM Output]
您也可以使用「mpr:」來擷取某些特殊輸出影像格式過濾器的輸出,以進行進一步處理。例如,在這裡,我們儲存「histogram:」的輸出影像,然後將其讀回,繼續在同一個指令中進行處理,

  magick rose: -define histogram:unique-colors=false \
          -write histogram:mpr:hgram  +delete \
          mpr:hgram  -strip  -resize 50%  histogram_resized.gif
[IM Output]
mpr:」記憶體儲存實際上是唯一的方法,可以透過特殊的輸入/輸出過濾器(例如輸出檔案格式,如「histogram:」,或輸入檔案格式,如「tile:」)重複使用已在記憶體中的影像。對於使用實際輸入影像的特殊選項也是如此,例如「-tile」或使用另一個影像作為來源的「色彩映射」影像。請參閱多影像色彩映射。請注意,IMv7 中正在將此類選項替換為不需要從檔案讀取影像的版本。這也是唯一可以使用-draw 'image'方法使用生成的記憶體影像覆蓋影像的方法,儘管還有許多其他技術可以做到這一點。「mpr:」影像實際上儲存的是「整個影像序列」,而不僅僅是一張影像。這有點像為目前的影像序列拍攝快照,以便您稍後可以重新載入它以進行進一步處理。例如,這允許您複製整個動畫序列以進行複製或克隆,而無需知道實際涉及多少影像。有關執行此操作的範例,請參閱圖層合成。當「mpr:」中有多個影像時,您實際上仍然可以從該序列中提取個別影像!使用「mpr:image'[2]'」將從使用「-write mpr:image」儲存的多影像序列中提取第三個影像。例如,在這裡,我從一組四個影像中提取了「風暴」影像。

  magick eye.gif news.gif storm.gif tree.gif \
          -write mpr:images  -delete 0--1 \
          \
          mpr:images'[2]'   mpr_extract.gif
[IM Output]
影像克隆運算子通常無法處理未知數量的影像,實際上在添加Clone運算子之前,「mpr:」是唯一可用的複製記憶體中影像的方法,而無需使用中間磁碟檔案。
從 IM v6.8.2 開始,您也可以將影像儲存在遠端 IM 快取守護程式中。這允許在單獨執行的 IM 指令之間傳遞影像(及其中數據),而無需使用磁碟空間。請參閱分散式像素快取守護程式
mpc:
這是一種專門針對 IM 的磁碟儲存格式,最初設計用於處理非常大的影像。基本上,它是一個程式記憶體的記憶體映射磁碟檔案,儲存到磁碟時會變成兩個二進制檔案:一個是包含影像中繼資料的「.mpc」檔案,另一個是包含影像像素快取的「.cache」檔案。
MPC:」格式會建立兩個檔案來儲存一張影像
此類檔案在 IM 重新編譯或升級後將無法使用,並且僅適用於針對特定機器編譯的 IM。 因此,它僅適用於臨時的「快速讀取」檔案,例如儲存腳本影像處理中使用的臨時影像,而不適合長期儲存。舉例來說...

  magick very_big_image.tif  very_big_image.mpc
將會在磁碟上建立兩個檔案。一個是小型的「very_big_image.mpc」檔案,另一個是稱為「very_big_image.cache」的特殊記憶體傾印檔案。第二個檔案的大小可能會比任何其他影像檔案格式大得多,因為它只是一個原始的、未壓縮的記憶體傾印。但是,該檔案不需要「讀入」或「解碼」,而是可以直接「分頁」到電腦記憶體中,並按原樣使用,而無需任何處理開銷。只需要大量的磁碟空間和磁碟 I/O。換句話說,它只需要磁碟存取時間即可讀取,而無需任何檔案格式處理。也就是說,不需要對資料進行解碼。由於影像是「記憶體就緒」的,因此它特別適用於各種大小的臨時影像,因為它可以在您發出下一個 IM 命令時立即使用。但請記住,會產生兩個檔案,並且它們會比一般的影像檔案大小大,因此請注意您的磁碟使用量和腳本清理。我自己的 IM 腳本充分利用了這個功能。例如,請參閱腳本「去像素化」和「垂直分割」,它們在影像處理操作中使用了相當大量的臨時影像檔案。這對於需要能夠反覆讀取相同影像的腳本或Mogrify Alpha 合成非常有用,因為 IM 不必解碼影像或使用大量記憶體來儲存它。這對於處理非常大的影像也非常有用,在這種情況下,您必須提取或裁剪影像中較小的一部分以進行實際處理。但是,由於大多數影像操作實際上會在處理過程中建立影像的克隆副本,因此仍然可以建立新的記憶體內副本。因此,仍然需要小心謹慎。裁剪調整大小到更小的影像大小是處理 MPC 大型影像最安全的操作。如需更多資訊,請參閱下面的超大型影像處理
fd:{file_descriptor}
這個特殊的檔案名稱允許您指定影像是要從中讀取還是寫入的特定「檔案描述符」。名稱「fd:0」是程式的「標準輸入」,而「fd:1」是程式的「標準輸出」。這些等同於使用「-」作為檔案名稱。但是,您可以指定任何要讀取/寫入影像的「檔案描述符」。包括「標準錯誤輸出」的「fd:2」,或父程式可能已安排的任何其他先前開啟的檔案控制代碼。這最常見的用途是在非常進階的 shell 腳本中,您可能有多個影像檔案串流。或者用於可能同時開啟多個檔案串流的網路守護程式。
inline:{base64_file|data:base64_data}
內嵌影像允許您讀取以特殊 base64 編碼定義的影像。例如,要讀取 base64 編碼的影像,請使用...
inline:base64_image.txt
此編碼可以來自檔案,但更常見的情況是直接作為讀取參數給出,而不是作為來自某些外部圖像源的檔案名稱。這通常用於在命令行或 API 圖像處理中作為「blob」的替代方案。或者將圖像數據直接放在命令行上...
inline:data:mime-type;base64,/9j/4AAQSk...knrn//2Q==
例如,讓我們對一個非常小的圖像進行 base64 編碼(有許多程序可以讓您進行這種轉換)...

  openssl enc -base64 -in noseguy.gif
[IM Text]
請注意,base64 數據可以包含任意數量的空白,例如回車和換行符。格式會簡單地忽略它。它也只使用普通的 ASCII 字符,這就是為什麼它被用於編碼電子郵件和網頁的二進制數據。它還允許將二進制數據存儲在程序和腳本中而不會出現問題。例如,我可以在 shell 腳本中使用以下命令,以便腳本本身內建了圖像,因此不需要單獨的外部圖像源。

  magick 'inline:data:image/gif;base64,
      R0lGODlhIAAgAPIEAAAAAB6Q/76+vvXes////wAAAAAAAAAAACH5BAEAAAUALAAA
      AAAgACAAAAOBWLrc/jDKCYG1NBcwegeaxHkeGD4j+Z1OWl4Yu6mAYAu1ebpwL/OE
      YCDA0YWAQuJqRwsSeEyaRTUwTlxUqjUymmZpmeI3u62Mv+XWmUzBrpeit7YtB1/r
      pTAefv942UcXVX9+MjNVfheGCl18i4ddjwwpPjEslFKDUWeRGj2fnw0JADs=
    '  b64_noseguy.gif
[IM Output]
請記住,圖像可以在您的腳本(shell 或 API)中使用。您不需要單獨的外部圖像文件,這會使原本簡單的腳本安裝變得更加複雜。 *那麼為什麼「inline:」會有這種相當複雜的形式?* 基本上是因為這是 HTML 網頁中內嵌圖像所使用的格式。例如,在以下示例中,右側的圖像是使用以下形式的 HTML 標籤直接內嵌在網頁上的,而不是作為單獨的外部文件:

  <IMG SRC="data:image/gif;base64,
        R0lGODlhIAAgAPIEAAAAAB6Q/76+vvXes////wAAAAAAAAAAACH5BAEAAAUALAAA
        AAAgACAAAAOBWLrc/jDKCYG1NBcwegeaxHkeGD4j+Z1OWl4Yu6mAYAu1ebpwL/OE
        YCDA0YWAQuJqRwsSeEyaRTUwTlxUqjUymmZpmeI3u62Mv+XWmUzBrpeit7YtB1/r
        pTAefv942UcXVX9+MjNVfheGCl18i4ddjwwpPjEslFKDUWeRGj2fnw0JADs="
      ALT="Nose Guy" WIDTH=32  HEIGHT=32  VSPACE=5 HSPACE=5 BORDER=0 >
Nose Guy
這不適用於所有網路瀏覽器,例如,它不適用於 IE7 及更早版本,但適用於 IE8。基本上,大多數現代網路瀏覽器都能理解它。
相同的內嵌數據格式也用於電子郵件標題中的「面部」圖像,可能還有許多其他文件類型。題外話:由於 ImageMagick 的「神奇」部分,大多數圖像文件格式不需要包含 mime 類型(長字符串中的「image/gif」部分)。實際上,IM 還是完全忽略了它)。但是,仍然需要逗號「,」來標記內嵌圖像數據字符串該部分的結尾。

  magick 'inline:data:,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//U
       b//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ek
       yky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguW
       w6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7
    '  b64_folder.gif
[IM Output]
警告:命令行選項輸入限制為 5000 個字符。此外,許多 shell(尤其是 PC-DOS 輸入)對命令行總長度有限制。因此,這不適合非常大的 base64 圖像。
clipboard:
從 Windows 剪貼板讀取圖像或將圖像寫入 Windows 剪貼板。(僅限 Windows)。
ephemeral:{image_file}
讀取然後刪除這個影像檔案。這是一個特殊的影像讀取檔案格式,它會讓 IM 在將指定的影像檔案讀入記憶體後將其刪除。請注意,當讀取的檔案被移除時,記憶體中的影像將不會被處理,甚至不會被儲存。這非常危險,使用時應格外小心。它主要用於委派產生。在這裡,背景委派將讀取輸入影像,然後在取得資料後將其刪除。這反過來會通知前景的「父」處理程序,「子」處理程序已準備好自行繼續進行,因為它已完成讀取提供的影像。然後主程式可以清理並分別繼續其影像處理,或者乾脆退出,視情況而定。「show:」影像輸出委派將其與「magick display」命令一起使用,以在主命令繼續或退出之前自動在背景顯示影像。(見下文)例如,我在一個呼叫「flicker_cmp」的 shell 腳本中使用了這個功能,以顯示一些中間結果,但當 IM 通過刪除給定的第二個影像來發出程式已完成讀取其輸入影像的信號時,它會自動繼續(或退出)。如果您需要該反饋,但也需要保留正在讀取的影像,則建立原始影像的副本、硬連結或符號連結,並將該檔案作為「ephemeral:」傳遞。這樣,當它被刪除時,原始影像就會被保留。注意:目前沒有辦法讓「animate」或「display」在動畫完成或實際將影像顯示出來時發出信號。:-( 但是您可以讓「magick」讀取一個單獨的「ephemeral:」影像,以通知控制腳本它已到達其影像處理中的特定點。

  # Blur an image, and show an on screen comparision before
  # auto-deleting and exiting.
  magick rose: input_image.png
  magick input_image.png -blur 0x5  blurred.png
  flicker_cmp input_image.png ephemeral:blurred.png &

  # wait for the second image to have been read and deleted!
  while [ -f blurred.png ]; do usleep 100; done

  # At this point we can continue (or exit) without problems.
  # while the on screen display continues in background.
  rm -f input_image.png
我還將其用於其他背景程式中,作為該背景程式已準備好繼續的信號。
show:win:x: -- 直接在螢幕上顯示影像
這些是特殊的輸出格式,會將影像結果直接顯示在螢幕上。它不會將影像儲存到檔案中,而是僅顯示結果。這對於快速測試 IM 命令以查看結果非常有用,強烈建議將其用於此目的。但是,它們只是「display」和「animate」命令的非常簡單的版本。例如,快速摘要目錄中的影像...

  magick montage *.jpg show:
查看兩個影像之間不同的區域...

  magick compare image1.png image2.png show:
此處列出的所有格式實際上都呼叫「display」程式來執行其任務。但是,它們各自以不同的方式處理作業。例如,「show:」將使用產生委派來執行單獨的「display」程式。這表示一旦顯示影像,原始命令將繼續其處理(通常是退出,除非您使用「-write show:」)。另一方面,使用「x:」或「win:」將會等待您退出顯示視窗,然後才允許原始命令繼續(並退出)。不幸的是,這些方法都無法很好地顯示動畫。為此,最好將動畫(以 MIFF 格式)透過管道傳輸到「animate」命令。
x:(作為輸入) - 讀取 X Window 顯示
您也可以使用「x:」運算子讀取當前的 X 視窗顯示內容,方式與使用「import」指令非常相似。事實上,在沒有選項的情況下,它的作用與「import」指令完全相同。使用滑鼠左鍵選擇要擷取副本的視窗,或使用滑鼠中鍵標記出一個區域。例如,要使用滑鼠選擇一個視窗,然後在另一個視窗中顯示剛才擷取的視窗(在顯示擷取的視窗後退出)...

  magick x:  show:
警告:如果您擷取的視窗未映射(已圖示化),或者有另一個視窗覆蓋在它上面,則圖像內容將包含空白區域或重疊視窗的內容!!!因此,請確保在擷取視窗時,該視窗在螢幕上完全可見。要擷取整個顯示畫面,請使用「root」作為視窗名稱。

  magick x:'root'  full_screen_dump.jpg
或者使用讀取修飾符來擷取顯示畫面的特定區域。

  magick x:'root[300x400+879+122]'  part_screen_dump.jpg
通過提供視窗名稱,您可以擷取特定的視窗。例如,這將擷取標題為「MailEd」的視窗...

  magick x:'MailEd'  window.jpg
然而,這並不能很好地工作,因為您經常會有多個同名的視窗,或者根本無法確定視窗的名稱。更好的方法是使用「X 視窗 ID」告訴 IM 想要的確切視窗,「X 視窗 ID」是 X 顯示畫面用來唯一識別特定視窗(或子視窗)的編號。X 視窗 ID 通常使用「xwininfo」指令查詢,但也可以使用其他程式(例如「xdotool」和「xwit」)以及其他工具(例如「xprop」)來查找有關視窗的信息。例如,視窗類別、名稱、標題、大小和位置、子視窗以及視窗管理器裝飾等信息。例如,查找標題或名稱中包含「Mozilla Firefox」的所有視窗...

  xwininfo -root -all | grep "Mozilla Firefox"
然後,我可以從上面的輸出中提取我想要的視窗的 X 視窗 ID。這是我在我的視窗管理器中的一個稍微複雜一點的 bash 腳本。當我按下一個按鈕時,它會查找當前「焦點」所在的視窗的 ID,擷取它,然後根據之前進行的任何擷取,使用下一個擷取編號將文件命名為 PNG 格式,並保存到我的當前目錄中。

  bash -c "
    id=$(xprop -root _NET_ACTIVE_WINDOW | sed 's/.* //')
    magick x:$id capture-tmp-$$.png
    num=$( ls capture-[0-9]*.png 2>/dev/null | sed -n '$ s/[^0-9]//gp' )
    num=$( printf %03d $(expr $num + 1) )
    mv capture-tmp-$$.png capture-$num.png
  "
大多數終端程式都會在環境變數「WINDOWID」中告訴您它們用於在 magick 顯示畫面中顯示文字的 X 視窗 ID。因此,如果您從 XTerm 或 Gnome 終端的指令列運行此程式,您將擷取當前終端視窗的副本。

  magick x:$WINDOWID  this_terminal.png
現在來點有趣的... 在這裡,我擷取了當前終端的內容,在其中繪製了一些東西,然後使用「display」將其繪製回同一個終端視窗!

  window=`xwininfo -children -id $WINDOWID |\
                  sed -n 's/^ *\(0x[^ ]*\).*/\1/p'`; \
  window="${window:-$WINDOWID}"; \
  magick x:$window -background black \
          -draw 'fill black         rectangle 40,40 160,160' \
          -draw 'stroke red         line 50,50 50,150 line 50,150 150,150' \
          -draw 'fill lime          circle 110,100 80,100' \
          -draw 'stroke dodgerblue  line 50,150 150,50' \
          rose: -geometry +180+60 -composite \
          png:- |\
    magick display -window $window -
上面的第一個指令是為「XTerm」視窗設計的,它要求您「magick display」到的視窗是提供的「WINDOWID」的子視窗。如果沒有找到「子」視窗(例如「Gnome-Terminal」視窗的情況),則第二行會恢復為「WINDOWID」的原始值。確定要使用的視窗後,將擷取它、在其上繪製並將其還原到終端視窗!然後,您就可以直接在當前終端視窗中獲得即時的圖形輸出。下面是一個更簡單的示例,每次運行時,它都會使視窗內容變暗。嘗試在實際的「xterm」視窗中運行幾次,您會發現終端視窗中的指令越舊,它就越暗!

  window=`xwininfo -children -id $WINDOWID |\
                  sed -n 's/^ *\(0x[^ ]*\).*/\1/p'`; \
  window="${window:-$WINDOWID}"; \
  magick x:$window -background black -colorize 20% png:- |\
    magick display -window $window -
這是一個「螢幕擷圖」,顯示了我在自己的「xterm」視窗中重複上述操作時發生的情況...
[snapshot]
請注意,雖然終端機的內容會被修改,但这只是暫時的。如果您最小化、遮擋或切換桌面螢幕,然後再回到終端機,修改後的內容將會遺失,因為終端機會重新繪製視窗,並抹去您自己的「繪圖」。上述操作在「Gnome 終端機」上的效果不如在「XTerm」上好,因為前者喜歡在每次滾動時「重新繪製」其視窗,而「XTerm」則不會。想像一下,IM 腳本將圖表和其他內容的結果直接顯示在各個視窗中,作為大型用戶端程式的一部分。事實上,許多 PostScript 檢視器,甚至許多網頁瀏覽器都是以這種方式顯示來自特殊子程式的輸出。也就是說,它們讓該子程式接管並直接繪製到提供的子視窗中。請嘗試一下,並透過電子郵件或IM 使用者論壇告訴我(和其他人)您的成果。

圖像格式的編碼器和委託

編碼器是動態連結程式庫模組(通常以 C 程式語言編寫),用於處理圖像輸入和輸出的「格式」方面。使用者也可以使用它們來建立特殊用途的濾鏡。它們可能需要安裝額外的外部程式庫,這些程式庫通常稱為「委託程式庫」。它們僅在需要時才作為動態模組載入,這意味著除非您確實要使用該編碼器,否則不需要安裝編碼器使用的相關程式庫。這些範例不會涉及編寫編碼器所需的 C 程式設計,但在原始碼中有一個範例編碼器,可用於建立您自己的編碼器模組。
委託只是一個 IM 知道的命令,允許它在不同格式之間進行轉換。這使得 IM 可以使用更「簡單」且預先寫好的命令,而不需要更複雜的二進制編碼器來處理某些圖像文件格式。要獲得可用委託的列表,請使用特殊命令...

  magick -list delegate
Im 使用的最著名的「委託」程式是「ghostscript」,它允許 IM 讀取非常複雜的 Postscript 和 PDF 格式向量圖像,並將其轉換為 IM 可以讀取的其他點陣圖像文件格式。然而,「委託命令」對使用者來說也非常有用,因為它允許您擴展 IM,使其能夠處理特殊類型的圖像,或者提供替代方法來讀取和寫入這些圖像。這些「命令」本身列在一個名為「delegates.xml」的文件中,該文件位於 IM 的系統配置目錄中。但它也會讀取位於使用者個人 Linux/UNIX 家目錄的「.magick」子目錄中的「delegates.xml」。使用者應該將他們的「命令委託」放在第二個文件中。

輸入委託命令範例

例如,我可以在我的 Linux/UNIX 家目錄的「.magick」子目錄中建立一個個人的「delegates.xml」文件,格式如下...

<?xml version="1.0" encoding="UTF-8"?>
<delegatemap>
  <delegate decode="flip" command="magick '%i' -flip 'miff:%o'"/>
</delegatemap>
這是一個完整的「委託」配置文件,但只有中間那一行是實際的委託。這是一個非常簡單的例子,它告訴 IM,如果它看到一個帶有「.flip」後綴或「flip:」格式前綴的圖像,它應該調用上面的命令來讀取「flip」格式的圖像。例如..

  magick flip:tree.gif   delegate_tree_flip.gif
[IM Output]
在這種情況下,所有委派命令所做的就是在原始 IM 命令讀取和處理圖像之前,使用單獨的 IM "magick" 命令將圖像“翻轉”過來!委派假設該命令將理解給定的圖像文件格式,並且它將返回 IM 本身可以理解和處理的任何圖像文件格式(在本例中為 MIFF 圖像文件格式)。委派的 '%i' 和 '%o' 部分代表臨時文件名,該命令是提供的輸入和輸出文件名,委派應該使用這些文件名。這些文件名由 IM 生成,並將位於臨時目錄中。這些臨時文件名也沒有任何圖像後綴,因此如果需要,請務必在前面加上所需的圖像格式類型。這樣做是出於安全原因,並且因為 IM 本身可能只讀取數據流,而不是實際文件。這也意味著委派命令在完成後不必處理諸如清理這些文件之類的事情。還有其他 '%' 替換,用於諸如中間臨時文件的第二個臨時文件名、圖像密度、大小等。有關這些轉義和其他委派選項的更多詳細信息,請參見 IM 安裝的“系統”"delegate.xml" 文件頂部的註釋。現在這似乎是一個相當愚蠢和微不足道的例子,但它基本上意味著您現在可以使用輔助命令將任何數據文件轉換為 IM 理解的任何圖像。然後,IM 將知道如何根據圖像後綴或格式前綴自動處理該數據類型,而您无需記住所有細節。許多此類委派已添加到系統文件中,因此值得一看。
出於安全原因,個人 "delegates.xml" 文件中的委派不會覆蓋系統安裝的 "delegates.xml" 文件中定義的委派。您只能在您的主目錄中的 ".magick/delegates.xml" 中添加新的唯一委派格式,稍後重複的委派將被忽略。

當然,如果輸入格式在內部已經知道,那麼當然不會查看系統委派。

此外,一如既往,請清理任何用戶(尤其是網絡用戶)輸入,因為您不希望用戶在您不知情的情況下使用委派。

例如,從 IM v6.4.2-6 開始,"autotrace:" 委派被添加到系統委派文件中,它將在讀取任何輸入圖像時運行 "AutoTrace" 命令。IM 將輸入圖像轉換為委派程序所需的 PNG 圖像格式,通過委派對其進行過濾,然後讀取生成的 SVG(通常通過外部 RSVG 庫),以生成原始輸入位圖圖像的平滑邊緣版本。請參閱 光柵到矢量轉換器示例。如果轉換器生成多個圖像文件(例如 PNG),則需要將所有這些單獨的圖像合併為單個多圖像格式(例如 MIFF),以便 IM 可以從一個輸出文件中讀取多個圖像。有時 IM 會將多個委派程序串在一起以讀取圖像。例如,要將“HTML”頁面讀取為圖像,它首先調用委派 "html2ps" 將其轉換為 PostScript。然後它使用特殊的 "ghostscript" 程序委派將生成的 PostScript 文件轉換為一組多個圖像。當然,由於委派程序中可能存在的複雜交互、錯誤安裝和錯誤,像這樣使用兩個或多個委派可能會產生其他問題。但總的來說,它是有效的,並且是 ImageMagick 神奇之處的關鍵方面。

輸出委託範例

保存到 IM 不直接理解的特定圖像文件格式時,也會執行類似的操作。例如,通過將此委派添加到您的個人 ".magick/delegates.xml" 文件中,您可以告訴 IM 如何創建 '.xyzzy' 圖像文件。

  <delegate decode="gif" encode="xyzzy" command='mv "%i" "%o"'/>
當然,這只是將 GIF 圖像文件快速複製為 TMP 圖像文件,但該命令可以是任何類型的圖像轉換器、腳本或您喜歡的 shell 命令序列。 有了該個人代理,IM 現在可以創建您的“.xyzzy”圖像,前提是至少提供了一種實現方法。

  magick rose: -negate   rose.xyzzy
  magick identify rose.xyzzy
請注意,上述標識符不理解“.xyzzy”後綴(未提供輸入代理)。 但是,由於未提供特定代理,因此文件“magic”(文件本身內的標識字符串)會告訴 IM 它實際上是 GIF 圖像格式,因此 IM 無論如何都能夠正確處理它,而無需特殊的輸入代理或編碼器。 這實際上就是“ImageMagick”的“MAGIC”部分。

代理清單

IM 可用於轉換圖像格式的外部代理的完整列表是從名為“delegates.xml”的特殊系統文件以及個人的“delegates.xml”文件(見下文)中讀取的。 如果您能找到這個文件,它會很有趣。 但是,此文件的格式過於複雜,無法在此處詳細介紹,儘管它在系統文件和在線提供的以及 ImageMagick 安裝(docs 區域)中提供的說明手冊中都有說明。 可以使用“-list delegate”選項打印從這些文件中讀取的代理和轉換的簡要摘要...

  magick -list delegate
但是請注意,使用“stealth="True"”聲明的代理不會被“-list delegate”選項列出。 所有代理都是可選的,並且可以為特定轉換創建多個代理。 如果一個代理不可用(或者它出錯並且沒有創建圖像),那麼 IM 將嘗試下一個代理,直到找到一個有效的代理,或者它用盡了要嘗試的代理,此時將產生一個錯誤,指示它無法讀取該圖像。

列印委託

我曾經創建過的最有用的代理之一是讓我可以輕鬆地將圖像打印到 PostScript 打印機。 打印機已經使用 Linux“lpr”命令設置好了,它可以接受 PNG 格式的圖像或 PostScript 文件。 這是簡單的“PRT:我決定創建的代理。
[IM Output]

  <delegate decode="ps" encode="prt" command='lpr "%i"'/>
請注意,我決定對傳遞給系統上“lpr”命令的圖像使用 PostScript 格式(“decode="ps"”)。 我選擇它是因為我可以使用“-density”等選項來調整輸出圖像的大小。 例如,我可以創建一個命令來從我的屏幕中抓取一個窗口,修改圖像,使其適合打印頁面(如我所願),然後打印出來。

  magick x:Loopy -shave 6 -chop 0x24 -modulate 220,0 \
          -bordercolor white -border 50x150 -density 130   prt:
我也可以使用“decode="png"”,但是我的系統會放大或縮小圖像以始終完全填充 A4 頁面。 但是您可能會喜歡這樣。

  <delegate decode="png" encode="prt" command='lpr "%i"'/>

產生外部命令

外部命令代理不僅用於在文件之間轉換圖像,還可以用作在後台運行(或“生成”)複雜命令的快捷方式。 這樣的代理將在其上添加屬性“spawn="True"”,並將啟動命令,等待它刪除其輸入圖像,然後 IM 將照常繼續,讓命令在後台運行。 例如,兩個輸出代理“show”和“win”都提供了在 IM“display”程序中顯示命令結果的簡單方法。 例如..

  magick rose: label:rose -append   show:
這會將標籤附加到內建的「rose」影像,並將其顯示在螢幕上。 當產生代理程式讀取其輸入影像並將其刪除時(通常使用特殊的「ephemeral:」輸入格式,見上文),啟動 IM 將繼續(並退出),將「display」程式在背景中運行以顯示結果。 以下是「show」產生代理程式,顯示在「display」指令中使用「ephemeral:」的方式。

  magick -list delegate | grep show
遺憾的是,「list」選項沒有顯示代理程式的「spawn="True"」旗標,但已為此代理程式定義。 這比試圖記住腳本化的「display」指令所需的所有特殊選項要方便得多。 也許您有一些經常執行的複雜指令。

Postscript 和 PDF 代理程式

透過使用代理程式,ImageMagick 可以利用外部程式來執行一些更複雜和專業的影像格式轉換。例如,雖然 Postscript (PS:) 和 Encapsulated Postscript (EPS:) 可以由 ImageMagick 直接寫入。 IM 無法讀取這些檔案格式。 Postscript 是一種完整的電腦語言,需要非常複雜的直譯器才能從中建立影像。 因此,處理這種檔案格式的讀取遠遠超出了 IM 的範圍。 為了克服這個問題,IM 會尋找一個名為「ghostscript」的外部代理程式來執行將 PS 或 EPS 格式檔案轉換為 IM 可以輕鬆讀取的其他影像格式的工作。 當然,這意味著如果您收到如下錯誤訊息...
convert: 沒有適用於此影像格式的解碼代理程式 `...'
基本上意味著 IM 無法找到合適的外部程式來將您提供的影像格式轉換為 IM 本身可以處理的影像格式。 對於 Postscript 影像,這通常意味著「ghostscript」未安裝、配置錯誤或位於系統上的未知位置。
[IM Output]
PDF/PS「ghostscript」代理程式採用內部使用的特殊格式。 IM 會在內部檢查 Postscript 格式影像,以嘗試透過給定的代理程式確定如何精確地光柵化檔案。

事實上,存在多個 PS 代理程式,IM 會根據情況選擇使用哪個代理程式。 例如,所使用的 ghostscript 裝置('bmpsep8' 或 'pngalpha')取決於之前是否設定了「-colorspace RGB」。

對於 PDF,我們使用「ps:color」代理程式而不是「ps:alpha」,因為「pngalpha」ghostscript 裝置僅支援一對一的頁面到影像轉換,而 PDF 通常是多頁的。

直接代理程式格式轉換 (Taint)

代理程式系統還允許 IM 呼叫外部程式將影像從一種格式轉換為另一種格式,而無需 ImageMagick 本身對影像進行任何處理。 但前提是目標影像可由 IM 作為影像讀取,並且「magick」的最終結果是影像的「未受污染」副本。 例如,如果您嘗試使用此指令將「Adobe Illustrator」檔案(「.ai」)(一種 Postscript 類型)轉換為 EPS(Encapsulated Postscript)...

  magick -density 300   map.ai  map.eps
然後 IM 會將「map.ai」轉換成 EPS 檔案(位於「/tmp」),這是一種它能理解的格式。然後在讀入記憶體(使用「eps」委派之後),它會發現它實際上並不需要修改它(它保持「未受污染」)。因為沒有對圖像進行任何更改,而且圖像已經被轉換為「eps」檔案格式,IM 會短路自己,直接將其生成的「eps」檔案複製到「map.eps」。也就是說,EPS 檔案將只是原始未更改的 Adobe Illustrator 檔案的副本!換句話說,IM 僅使用其內部委派來處理檔案(實際上只是重新命名它)。它從未真正處理圖像本身,因此圖像仍然是純向量圖像。這實際上是「magick」作為 ImageMagick 版本 1 中的一個程式的最初目的。所有其他操作和設定都是在很長一段時間內後來添加的。 但是,您可以使用特殊的「-taint」運算符將其標記為已修改,而不實際修改它,從而強制 IM 實際讀入和寫出圖像作為點陣圖。

  magick -density 300 map.ai  -taint  map.eps
在這裡,IM 讀取的圖像確實變成了「已修改」或「已污染」,因此它會將記憶體中的圖像版本寫入最終的 EPS 檔案,而不是簡單地複製輸入檔案。

其他委託範例

修改 CMYK Postscript 的 Postscript 委派

請參閱 John 的部落格

DCRaw 8 位元處理過的相機圖像委派

用於讀取 8 位元完全處理過的「原始」數位相機圖像(CRW、CR2、NEF 等)的替代委派是...

  <delegate decode="dcraw8" command='dcraw -v -w -O "%o" "%i"'/>
這將讀取「原始」相機圖像,並將其轉換為 PNG 檔案格式(儘管您也可以輕鬆地添加「-T」標誌並使用 TIFF 圖像格式)。該輸出圖像輪流可由 ImageMagick 讀取。通過添加此委派,您可以簡單地將其用於任何 ImageMagick 圖像讀取操作(任何 API,而不僅僅是命令列),IM 將處理所有檔案 IO 和清理。例如...

  magick dcraw8:image.crw  image.png
如果您沒有定義「dcraw」可執行檔的檔案路徑,IM 將沿著用戶當前的 PATH 環境變數搜尋程式,但是允許這樣做可能會導致安全問題。系統安裝的委派通常會完整定義命令路徑。請參閱此 IM 使用者論壇討論 中的註釋。

使用「ffmpeg」的視訊解碼器委派

例如,這是 Mikko Koppanen 在他的 Mikko 的部落格 網站上發布的委派。將其添加到您家目錄中「.magick」目錄下的個人「delegates.xml」檔案中...

  <delegate decode="ffmpeg" command="'ffmpeg' -i '%i' -y -vcodec png -ss %s -vframes 1 -an -f rawvideo '%o'" />
IM 現在可以使用「ffmpeg」程式從 MPEG 視訊圖像中解碼幀。例如。

  magick "ffmpeg:test1.mpg[40]"  frame_40.png

真正的大規模圖像處理

為了處理任何種類的大型圖像,您最好使用 Q8 版本的 ImageMagick,它的記憶體需求是更高品質的 Q16 版本的一半。使用「identify -version」檢查您的 IM 的編譯 Q 級別。對於中等大小的圖像,您可以嘗試使用「-limit」來增加處理限制(例如處理「-limit area 8192 -limit memory 8192」),以便嘗試避免 IM 將圖像資料快取到磁碟。但是,您的系統可能會拒絕大型記憶體請求,並且仍然強制 IM 將圖像快取到磁碟(速度慢約 1000 倍)。要查看 IM 是否正在使用磁碟快取進行圖像處理,您可以使用「-debug cache」來監控該動作。另請參閱 IM 論壇討論

記憶體/磁碟管理

如果您打算處理非常大的圖像,您可能需要確保 IM 不會耗盡所有電腦記憶體,並通過要求它立即使用臨時交換磁碟檔案來減慢其他程式的處理速度(通過花費所有時間在記憶體和磁碟交換之間進行交換)。例如,這是一種在很長一段時間內處理非常大的圖像的好方法,而不會阻止您使用電腦執行其他操作。基本上,它會強制 IM 將所有內容都快取到磁碟。

  env MAGICK_TMPDIR=/data nice -5 \
    magick -limit memory 32 -limit map 32 \
            huge_9Gb_file.psd  -scene 1 +adjoin layer_%d.png
當然,這假設「/data」有足夠的檔案和磁碟空間來處理圖像的記憶體需求。

記憶體映射磁碟檔案

如果您要在同一個來源圖像上執行許多操作,並且您有足夠的磁碟空間,則可以使用 MPC 圖像格式,這種格式建立成本很高,但在載入時幾乎沒有開銷...

  magick mybigassimage.jpg mybigassimage.mpc
  magick mybigassimage.mpc   -resize 50%  resized.jpg
  magick mybigassimage.mpc   -rotate 90   rotated.jpg
  ...etc...
  rm -f mybigassimage.mpc mybigassimage.cache
這將允許您以最小的成本和記憶體使用量多次讀取非常大的圖像。在 IM 論壇討論 將大圖像切割成圖磚 中介紹了一個使用這種方法的腳本化圖磚範例,並在 裁剪非常大的圖像 中重新討論。基本上,MPC 圖像格式檔案由兩個實際檔案組成,一個資訊性「.mpc」檔案和一個「.cache」中的圖像直接記憶體分頁副本。當然,您需要在完成後清理這兩個檔案。設計這種方法是為了讓 IM 不必在每次執行新的「magick」命令時都重新解析圖像格式並將其快取到磁碟。此外,如果您只訪問輸入圖像的某些部分,則每個命令都不需要處理整個圖像,而是可以根據需要從快取的磁碟檔案中讀取該較小的部分。如果您打算處理非常大的 MPC 圖像副本,最好先提取或 裁剪 圖像中較小的部分以進行實際處理。這是因為對圖像執行的幾乎所有操作通常都會導致建立結果的新記憶體內副本,因此初始裁剪是一個非常好的主意。如果您有記憶體,您也可以嘗試使用「記憶體磁碟」,例如「TMPFS」或 RamDisk 類型檔案系統。但請注意,填滿此類磁碟也會直接填滿您的電腦記憶體。所以實際上您只是將一種記憶體用途換成了另一種。

分段處理圖像

雖然您可以使用上述 MPC 方法從來源圖像中裁剪出各個部分以進行進一步處理,但您仍然需要讀取和寫入整個圖像,而對於大型圖像,這仍然需要很多時間。IM 還為圖像開發了一個更簡單的管線處理器,稱為「stream」。這個程式有一組有限的圖像操作,這些操作設計為一次只處理圖像的一行掃描線(像素行)。因此,以這種方式處理圖像時,僅使用足夠的記憶體來保存單行像素。例如,這允許您從非常大的圖像中提取較小的區域以進行進一步處理,而無需先將整個圖像讀入記憶體。但是,「stream」的輸出是原始 RGB 圖像值,因此建議進行一些後處理。

  magick stream -map rgb -storage-type char -extract 600x400+1900+2900 image.png - |\
    magick -depth 8 -size 600x400 rgb:- tileimage.png
您不必將輸出保存到檔案中,而是可以直接繼續處理較小的圖像。例如...

  magick stream -map rgb -storage-type char -extract 600x400+1900+2900 image.png - |\
    magick -depth 8 -size 600x400 rgb:-  ...more_processing_here...  tile.png
這將只會在不先讀入整個較大影像的情況下,處理提取的 600x400 像素影像。速度問題...Peter V <peter.v@pv2c.com> 指出... 根據我的經驗,與使用 MPC 檔案或使用 "magick -crop" 相比,使用 "串流" 來切割 800MB 的 PNM 檔案是最快的方法。哪些格式有效...以影像失真聞名的 Paul Heckbert 指出,"串流" 命令適用於某些檔案格式(特別是 JPEG),但不適用於其他類型,例如可能交錯的 PSB。我認為這取決於特定檔案格式的「編碼器」是否支援逐行串流像素。這可能是因為產生檔案格式「編碼器」的程式設計師只是沒有時間或需要「串流」。在這種情況下,可能需要熟悉該影像檔案格式的程式設計師做更多工作來完成「編碼器」模組。此外,像 SVG 或 WMV 這樣的向量影像檔案格式,或由某些「委託者」預先處理的影像,例如數位相機影像檔案格式,不可能「串流」,因為影像中沒有實際的像素行,只有繪製的物件(線條、多邊形和漸變陰影)。JPEG 影像區段根據 IM 論壇的討論 從大型 JPEG 提取區域,您可以使用專用的 JPEG 程式,例如由 JPEG Club 開發的特殊 "jpegtran" 和 "jpegcrop",可以從 JPEG 影像中提取區域而無需實際解碼數據。也就是說,將 JPEG 無損裁剪到另一個 JPEG 影像。例如..

  jpegtran -crop 100x100+0+0 -copy none huge.jpeg  crop.jpg
但是有一些注意事項。左上角的起點將移至較小的 8 或 16 的倍數,並且最終影像大小會相應增加。這是因為 JPEG 影像使用「頻率編碼塊」,這些塊的大小通常為 8x8 像素或 16x16 像素(由 JPEG 取樣因子決定,1 = 8 像素,2 = 16 像素)。如果要進行無損複製,則需要保留這些塊。對於「+0+0」偏移量,它已經位於適當的邊界,因此上述操作應會產生精確的 100x100 像素裁剪。但是對於其他偏移量,您需要對提取的區域進行一些最終清理。例如...

  jpegtran -crop 100x100+123+425 -copy none huge.jpeg  crop.jpg
  magick crop.jpg -gravity SouthEast -crop 100x100+0+0 +repage crop_fixed.png

以區塊處理影像 (PbmPlus)

在不將整個影像保留在記憶體中的情況下,以區塊處理大型影像是個更困難的問題。基本上,當您分割影像時,您需要保留一整列影像,或者在分割大型影像或稍後將其重新組合在一起時打開多個串流(每列影像一個)。最常用的技術是簡單地將每個影像區塊另存為磁碟上的單獨影像檔案。事實上,這通常是儲存超大型影像的更好方法,因為程式可以只讀取任何給定時刻需要處理的「區塊」,從而產生一種「基於磁碟」的隨機存取影像。這種大型影像儲存方式,結合金字塔型多解析度結構,實際上就是「Google 地圖」的工作原理。雖然 IM 沒有任何工具可以在使用少量記憶體的情況下分割(區塊裁剪)大型影像,但 PbmPlus/NetPBM 可以做到這一點。Pbmpus 處理一小部分例如,在這裡我使用 PbmPlus 工具從大型影像中剪切(裁剪)一小部分,對其進行處理,然後將其合成為原始影像。

  tifftopnm INPUT.tif input.pam

  pamcut {left} {top} {width} {height} input.pam  part.pam
  # process smaller "part.pam" image here
  pamcomp -xoff={left} -yoff={top} - input.pam output.pam

  pamtotiff output.pam OUTPUT.tif

tifftopnm」會將影像轉換為影像資料流,並執行與 ImageMagick「stream」指令類似的作業。「pamcut」相當於裁剪操作,並且會從輸入影像中擷取較小的區域。除了 *寬度* 或 *高度* 之外,您也可以指定裁剪的 *右* 或 *下* 界線。您可以使用「magick」指令替換「magick stream」指令,可以使用一般的 ImageMagick 來處理中央部分,如果您喜歡自找麻煩,也可以使用一系列的 PbmPlus 等效工具。「pamcomp」應該將修改過的影像部分覆蓋回原始影像的 PbmPlus 版本。其他可能替代「pamcomp」的工具是「pnmpaste」,但這不會處理透明度,無法進行像素混合。請注意,透過使用片段合成,應該可以扭曲小圖塊,並在之後將它們重新組合成更大的影像。Pbmpus 切割(圖塊裁剪)處理我們可以使用「pamdice」和「pamundice」或其他替代方案來產生和合併可以單獨處理的較小影像圖塊,但由於「每列多個影像圖塊問題」,因此必須將檔案儲存到不同的磁碟檔案(或命名管道)中。一個範例指令碼「pam_diced_flip.pl」由bugbear提供,用於使用較小的圖塊「翻轉」或「旋轉」(僅限 90 度)非常大的 PbmPlus 影像。這通常需要您將整個影像讀入記憶體。請注意,它確實會使用大量的暫存檔案,但它的記憶體佔用空間非常小。

VIPS 和 NIP,一個大型影像 TIFF 處理器

Jenny Drake < jennydrake @ lineone.net > 報告... 您可能也想看看「Vips」和「nip」的非 IM 替代方案,它們是由倫敦國家肖像館開發的,旨在使用規格較低的電腦處理非常大的影像檔案(通常是 TIFF)。「Vips」是底層引擎,「nip」是圖形介面。可在 Linux、Windows 和部分 Mac 上運作。

大量影像的長串流,影片序列

影像串流是另一個問題領域。這裡的問題不在於影像的大小,而在於所涉及的影像數量之多。數量多到您通常不想將它們全部載入記憶體,甚至不想像一般影像那樣將它們個別儲存到磁碟。這類影像的最大問題當然是影片處理和動畫。處理這類影像的關鍵是串流影像檔案格式,其中影像可以簡單地一個接一個地串連在一起,成為一個檔案串流。我們在上面的MIFF 影像串流中簡要地提到了這一點。與 ImageMagick 自己的MIFF格式一樣,PbmPlus/NetPBM也是一種串流格式(幾乎相同,只是更簡單),但在影片影像串流處理中更為人所知和常用。在一個論壇討論中,讀取多個影像,一位使用者想要處理由「ffmpeg」影片處理程式產生的一系列 PPM 影像。Pbmplus影像(如MIFF影像)可以簡單地串連在一起,以產生多影像串流。目前,IM 不允許您僅從這樣的串流中讀取一張影像、處理它,然後再讀取另一張單獨的影像。所有 IM 指令都將始終讀取整個串流,然後將其關閉。這將作為 IMv7 指令碼處理的一部分進行修復。一種解決方案是一個名為「process_ppm_pipeline」的小型 Perl 指令碼,它將接受一系列 PPM 影像,並在每張影像到達時對其執行單獨的「magick」指令。輸出也是一系列 PPM 影像,這些影像會產生新的影像串流。例如,讀取影片並「翻轉」每一幀,一次一幀...

  ffmpeg input.mpg -f image2pipe -vcodec ppm | pnmtopnm -plain |
    process_ppm_pipeline -flip |
      ffmpeg -f image2pipe -vcodec jpeg output.mpg
pnmtopnm -plain」至關重要,因為此腳本目前僅處理 ASCII-PPM 影像串流,不過透過一些更聰明的方法,它也可以處理任何二進制(原始)Pbmplus 影像串流,甚至MIFF 影像串流。這樣的工具甚至可以用於處理多個串流(列)的超大型影像。不過,這可能需要對相關指令的內部處理有更深入的了解。如果能找到一種方法,將此類影像細分為圖塊串流,然後在最後重新構建大型影像。最終,我希望加入一種機制,讓您可以要求編碼器從多影像檔案串流中僅讀取並返回一張影像,而不關閉該串流,以便稍後可以再次讀取另一張影像。透過這種方式,Im 就可以一次處理一個影像串流。更新:IMv7 可以一次從串流中讀取一張影像。使用迴圈或管道指令,應該可以產生串流影像濾鏡。需要更多實驗。