級別: 初級 Michael, 高級軟件工程師
2004 年 4 月 05 日 沒有什么能象命令行工具這樣適合于處理大批量的任務(wù),對于圖像操作也不例外。Web 開發(fā)人員和管理員會喜歡輕松處理大量文件的能力,無論是使用命令行還是腳本。程序員 Michael Still 介紹了 ImageMagick 套件,這是一個用于以多種格式對圖像進(jìn)行縮放大小、旋轉(zhuǎn)、轉(zhuǎn)換和其它操作的 Linux 工具箱,無論圖像的數(shù)量是一個還是上百個,它都可以一次處理掉。 本文展示了如何使用命令行工具執(zhí)行圖像操作。這種任務(wù)對我而言相當(dāng)常見,因?yàn)槲覔碛袔撞繑?shù)碼相機(jī),并且現(xiàn)在管理著一個擁有幾千張精彩照片的資料庫。對于經(jīng)常需要對大量圖像進(jìn)行批處理的 Web 開發(fā)人員和管理員而言,命令行工具是特別具有吸引力的選擇,因?yàn)殚_發(fā)人員可以將它們合并成腳本。但即使您只想執(zhí)行一兩次操作,選擇命令行也可以節(jié)省時間。 本文中討論的命令行工具是優(yōu)秀的 ImageMagick 套件的一部分,該套件是隨 Red Hat Linux 一起提供的,并可免費(fèi)在線下載(請參閱 參考資料)。也可以通過 C、C++、Perl、Python、Java 和其它幾種語言使用 ImageMagick,Linux 程序員會喜歡這樣做。 請注意,有許多種方法可以完成本文中所討論的任務(wù)。我討論了我所使用的方法,它對我確實(shí)很有效。這并不意味著除此之外的其它工具就很差勁;僅僅表示我對于現(xiàn)在所使用的工具很滿意。 本文采用了以具體問題作為示例進(jìn)行討論這種形式,但其思想應(yīng)該也適用于其它問題領(lǐng)域。 生成縮略圖 我對照片集所執(zhí)行的第一個操作是生成縮略圖。我還想減少圖像的大小,以適用于網(wǎng)站版本因?yàn)樵S多人實(shí)際上并不想看到我兒子的 1920 x 1440 像素的照片。 我使用 convert 工具,它是 ImageMagick 套件的一部分。 convert 確實(shí)很酷。除了圖像縮放,它還具有平滑處理、均衡圖像組、模糊化、在圖像格式間進(jìn)行轉(zhuǎn)換、修剪、去斑濾鏡、抖動、繪制邊界、翻轉(zhuǎn)、連接、重新采樣、調(diào)整大小以及許多功能。查看聯(lián)機(jī)幫助頁以獲取關(guān)于它的各種命令行選項(xiàng)的更多信息。本文稍后還討論了 convert 所提供的許多在視覺上比較有趣的效果。 讓我們假定我希望為這幅非常美麗的玫瑰圖像制作縮略圖:
圖 1. 玫瑰的照片 要用 convert 調(diào)整圖像的大小,只要使用 -sample 命令行選項(xiàng)。例如,讓我們假定我希望得到 80 x 40 像素的縮略圖。則命令行將是: # convert -sample 80x40 input.jpg output.jpg | 這生成了如下的縮略圖: 圖 2. 生成縮略圖的第一次嘗試 ImageMagick 會自動地考慮在縮放圖像大小時圖像的兩條鄰邊所產(chǎn)生的比例。這意味著新的圖像的高寬比與原圖相同。在上面的示例中,這意味著縮放后的圖像實(shí)際上是 53 x 40 像素,而不是所要求的 80 x 40 像素。指定輸出圖像大小的另一種方法是使用百分?jǐn)?shù)。如果您不能確定輸入圖像的大小,或者并不是刻意地要得到確切大小的新圖像,那么這種方法比較方便。以下是關(guān)于如何使用百分?jǐn)?shù)的示例: # convert -sample 25%x25% input.jpg output.jpg | 現(xiàn)在,我們得到了如下所示的縮略圖: 圖 3. 生成縮略圖的第二次嘗試 使用該命令,您可以在某個目錄中生成圖像的縮略圖。雖然本文并不是關(guān)于 shell 腳本編制的,但我會迅速地向您展示一個示例,以說明如何生成當(dāng)前目錄中每個 JPEG 的縮略圖: 清單 1. 為當(dāng)前目錄中的所有 JPEG 生成縮略圖 for img in `ls *.jpg` do convert -sample 25%x25% $img thumb-$img done | 這會生成一系列大小為實(shí)際圖像 25% 的縮略圖,其文件名稱是在 JPEG 文件名的前面加上 thumb-前綴。
獲取關(guān)于圖像文件的信息 另一個常見任務(wù)是確定圖像文件的尺寸(dimension)。例如,您可能需要知道前一個示例中的縮略圖有多大。 許多圖像處理庫提供了用于此用途的優(yōu)秀工具。例如,libtiff(TIFF 庫,我先前曾寫過有關(guān)這個庫的文章;請參閱 參考資料)提供了 tiffinfo , tiffinfo 顯示了關(guān)于 TIFF 文件的下列種類的信息:
清單 2. tiffinfo 的樣本輸出 TIFF Directory at offset 0x146 Image Width: 352 Image Length: 288 Bits/Sample: 8 Compression Scheme: Deflate Photometric Interpretation: RGB color Samples/Pixel: 3 Planar Configuration: single image plane | 這并不是一個關(guān)于如何使用 tiffinfo 的詳盡示例,但您可以看到它返回了諸如圖像大小、像素深度(每個樣本的位數(shù)和每個像素的樣本數(shù)的組合)以及所用的壓縮方案之類的有用信息。 類似地,有一個返回 PNG 文件的類似信息的 pnginfo 命令:
清單 3. pnginfo 的樣本輸出 sample.png... Image Width: 640 Image Length: 480 Bitdepth (Bits/Sample): 8 Channels (Samples/Pixel): 3 Pixel depth (Pixel Depth): 24 Colour Type (Photometric Interpretation): RGB Image filter: Single row per byte filter Interlacing: No interlacing Compression Scheme: Deflate method 8, 32k window Resolution: 0, 0 (unit unknown) FillOrder: msb-to-lsb Byte Order: Network (Big Endian) Number of text strings: 0 of 0 | 我不清楚是否存在用于其它格式(諸如 BMP、GIF 和 JPEG)功能相當(dāng)?shù)膯蝹€工具。但是,ImageMagick 又一次幫了我們的忙,這次是使用名為 identify 的工具。 # identify -verbose sample.png |
清單 4. identify 的樣本輸出 Image: sample.png Format: PNG (Portable Network Graphics) Geometry: 640x480 Class: DirectClass Type: true color Depth: 8 bits-per-pixel component Colors: 142360 Filesize: 555.6k Interlace: None Background Color: grey100 Border Color: #DFDFDF Matte Color: grey74 Dispose: Undefined Iterations: 0 Compression: Zip signature: 361fe70ae623ef6f1fca44e0d29d157c2d701039fcf0f8625862925d881e13a4 Tainted: False User Time: 0.190u Elapsed Time: 0:01 | 您可以看到 identify 顯示了一串關(guān)于圖像文件的有用信息,如以像素為單位的圖像大小、圖像的色深以及圖像的格式。 | pnginfo 當(dāng)我開始使用 PNG 時,我成為 libtiff 用戶已經(jīng)有相當(dāng)長一段時間了。當(dāng)時,沒有與 tiffinfo 功能相當(dāng)?shù)墓ぞ哂糜?PNG 文件,因此我編寫了 pnginfo 。(您可以通過 參考資料中的鏈接下載 pnginfo )。 | | identify 還有 -format 命令行標(biāo)志,它允許您僅指定想要輸出的信息。例如,如果您只對圖像尺寸感興趣,則可以使用如下命令: # identify -format "%wx%h" sample.png | 輸出類似于: 此處, %w 表示圖像寬度,而 %h 表示圖像高度。有關(guān)可以與該選項(xiàng)一起使用的格式化字符的更多信息,請查看 identify 聯(lián)機(jī)幫助頁。
旋轉(zhuǎn)圖像 另一種經(jīng)常需要用到的圖像操作是旋轉(zhuǎn)圖像。例如,我用數(shù)碼相機(jī)所拍攝的許多照片都旋轉(zhuǎn)了九十度,因?yàn)槲沂前严鄼C(jī)豎過來拍攝它們的。相機(jī)不會為我旋轉(zhuǎn)這些照片,因此我編寫了一個腳本,以便在從相機(jī)下載這些圖像之后完成旋轉(zhuǎn)任務(wù)。 例如,這是我在最近去塔斯馬尼亞島的亞瑟港旅游時拍攝的一幅照片: 圖 4. 橫臥的亞瑟港 為了旋轉(zhuǎn)該照片,我們再次求助于 convert 命令: # convert -rotate 90 input.jpg output.jpg | 該命令生成了如下所示的圖像: 圖 5. 亞瑟港 請注意 -rotate 選項(xiàng)的參數(shù)是將圖像向右旋轉(zhuǎn)的度數(shù)。要向左旋轉(zhuǎn),請使用負(fù)數(shù)。
更改圖像的格式 convert 命令還能夠轉(zhuǎn)換圖像文件的格式。這包括圖像格式之間的轉(zhuǎn)換(如將 JPEG 圖像轉(zhuǎn)換成 PNG)以及從顏色到灰度之間的轉(zhuǎn)換、抖動和類似操作。 convert 根據(jù)命令行中給定的文件擴(kuò)展名來了解輸入和輸出的圖像格式分別是什么。因此,要將 JPEG 轉(zhuǎn)換成 PNG,使用如下所示的命令行: # convert input.jpg output.png 在我撰寫本文時,ImageMagick 支持 89 種圖像格式。查看 ImageMagick 網(wǎng)站(請參閱 參考資料)以獲取更多信息。
向圖像添加文本注釋 有時您需要向圖像添加文本注釋。例如,假設(shè)您的公司擁有標(biāo)準(zhǔn)的名片圖像,并希望在將名片發(fā)送到打印機(jī)之前將每個雇員的詳細(xì)信息都添加到名片上面。另一個示例是為通過您網(wǎng)站上的在線課程的用戶生成表示證書(presentation certificate)。 讓我們假定您從這幅圖入手: 圖 6. 2002 年芙蘿莉雅蝶園藝博覽會(FLORIADE 2002)照片 您可以使用下列命令行,為該圖注釋一些標(biāo)識信息: # convert -font helvetica -fill white -pointsize 36 -draw ‘text 10,50 "Floriade 2002, Canberra, Australia"‘ floriade.jpg comment.jpg | 這里是結(jié)果: 圖 7. 加注釋的 2002 年芙蘿莉雅蝶園藝博覽會照片 迄今為止,這是我在本文中所展示的最復(fù)雜的 convert 命令行了,因此我將花些時間來解釋它。 -font helvetica 將注釋的字體設(shè)置為 Helvetica。也可以在此處指定字體文件的路徑。這個示例給圖像添加了標(biāo)記,這樣未經(jīng)許可其它網(wǎng)站就不能再使用該圖像了,但它是使用位于非標(biāo)準(zhǔn)位置的字體來完成該任務(wù)的: # convert -font fonts/1900805.ttf -fill white -pointsize 36 \ -draw ‘text 10,475 "stillhq.com"‘ \ floriade.jpg stillhq.jpg 以下是結(jié)果: 圖 8. 帶標(biāo)記的圖像 -fill white 用白色而不是標(biāo)準(zhǔn)的黑色來填充字母。 -pointsize 36 以點(diǎn)為單位指定字母的大小。一英寸等于 72 點(diǎn)。 -draw ‘text 10,50 "..."‘ 是一組繪圖命令,在本例中是移動到位置 10, 50,然后繪制出雙引號中的文本。使用單引號是因?yàn)槿绻枰L制多個字,則繪圖命令中需要使用雙引號,而您不能在雙引號中再用雙引號。
其它更富藝術(shù)性的轉(zhuǎn)換 convert 還實(shí)現(xiàn)了一系列相當(dāng)藝術(shù)性的轉(zhuǎn)換。我將在此處演示一些在視覺上比較有趣的轉(zhuǎn)換。如果您對此感興趣,應(yīng)該查看 ImageMagick 的聯(lián)機(jī)幫助頁和網(wǎng)站以獲取更多信息。這是我將用于該演示的輸入圖像: 圖 9. 烏奴奴(Uluru)夕照 這張烏奴奴(以前稱為艾爾斯巖(Ayers Rock))的照片是在日落時分照的。 炭筆 炭筆效果模擬出該圖像的素描畫。 # convert -charcoal 2 input.jpg output.jpg | 其結(jié)果如下所示: 圖 10. 應(yīng)用炭筆效果之后的烏奴奴夕照 增加 -charcoal 選項(xiàng)的參數(shù)的數(shù)值會增加應(yīng)用于該圖像的“炭筆”數(shù)量,但也會延緩生成圖像的過程。下面是一個使用稍多炭筆的示例。 # convert -charcoal 10 input.jpg output.jpg | 它產(chǎn)生了如下結(jié)果: 圖 11. 應(yīng)用更多炭筆效果之后的烏奴奴夕照 如果您真的想近乎瘋狂地使用大量炭筆: # convert -charcoal 200 input.jpg output.jpg | 您會得到這樣的結(jié)果: 圖 12. 應(yīng)用過量炭筆效果之后的烏奴奴夕照 | 指定三個值 要指定三個值,每個值分別代表紅色、綠色和藍(lán)色三個采樣,使用 red/green/blue 形式的參數(shù)。例如, 10/20/30 意味著紅色的值是 10、綠色值為 20 而藍(lán)色值為 30。您也可以在這個構(gòu)造中使用百分?jǐn)?shù)。 | | 著色 著色是將每個像素的顏色與指定顏色混合的過程。該效果的參數(shù)就是要用來混合的顏色??梢杂靡粋€百分?jǐn)?shù)(它將分別用于紅色、綠色和藍(lán)色),也可以用三個百分?jǐn)?shù)來指定這個參數(shù)。也可以提供三個實(shí)際值中的一個。 # convert -colorize 255 input.jpg output.jpg | 以下是著色之后的烏奴奴: 圖 13. 應(yīng)用著色效果之后的烏奴奴夕照 內(nèi)爆(Implode) 內(nèi)爆效果模擬了您圖像的中心被吸入虛擬黑洞的情形。所用的參數(shù)是您所期望的內(nèi)爆效果量。 # convert -implode 4 input.jpg output.jpg | 內(nèi)爆的烏奴奴如下所示: 圖 14. 內(nèi)爆之后的烏奴奴夕照 | solarize 參數(shù) ImageMagick 文檔聲明 solarize 的參數(shù)總是百分?jǐn)?shù)。嚴(yán)格地說,這并不正確。如果參數(shù)以百分號結(jié)尾,那么就把它當(dāng)作百分?jǐn)?shù)。否則,就將它當(dāng)作一個字面值。 | | 曝光 曝光是在相片沖洗過程中把底片暴露在光線中所發(fā)生的效果。這里,輸入?yún)?shù)是應(yīng)用于該效果的亮度,可以指定為絕對值,也可以是可用于像素的最大可能值的百分?jǐn)?shù)。如果像素超過閾值,則對它求反。
# convert -solarize 42 input.jpg output.jpg | 在曝光之后,我們的圖像如下所示: 圖 15. 曝光之后的烏奴奴夕照 發(fā)散 spread 在圖像之內(nèi)以隨機(jī)的數(shù)量移動像素。所用的參數(shù)是被移到新選擇的位置的像素區(qū)域的大小。所以它指定了輸出和輸入的相似程度: # convert -spread 5 input.jpg output.jpg | 再次使用烏奴奴,這次是發(fā)散之后的情形: 圖 16. 發(fā)散之后的烏奴奴夕照
在一次 ImageMagick 調(diào)用中執(zhí)行多條命令 您已經(jīng)看到了將命令與注釋示例聯(lián)系起來的示例。但是,可以將本文中提到的任意 ImageMagick 命令鏈接起來。例如,也許我們希望制作某圖像的縮略圖,然后對它應(yīng)用發(fā)散。在發(fā)散發(fā)生之后,我們將應(yīng)用炭筆效果: # convert -sample 25%x25% -spread 4 -charcoal 4 input.jpg output.jpg | 這會產(chǎn)生: 圖 17. 應(yīng)用了一系列效果之后的烏奴奴
圖像操作技巧 在迫不及待地動手修改您所擁有的每一幅圖像之前,您應(yīng)該記住一些關(guān)于圖像操作的事情。首先,您應(yīng)該考慮一下打算長期使用什么圖像格式,免得最終有了一大堆某種格式的圖像之后再來后悔就晚了。這一點(diǎn)特別容易做到,因?yàn)檎绫疚南惹八懻摰模梢允褂?convert 來更改圖像的格式。 JPEG 壓縮對于諸如照片之類的大圖像很適合。但其壓縮通常是 有損的(換句話說,在壓縮過程中會丟棄圖像數(shù)據(jù))。這使得 JPEG 非常不適于壓縮需要保持字跡清晰的文本。另一件需要牢記的事情是:損失是累積的。 如果您不希望在一系列操作之后產(chǎn)生的累積損失會影響到彩色圖像的圖像品質(zhì),通常 PNG 是個不錯的選擇。 有關(guān)該主題的更多信息,請參閱我所著的關(guān)于用 libtiff 處理彩色圖像的文章“ Graphics programming with libtiff,Part 2”(請參閱下面的 參考資料中的鏈接)。 您還應(yīng)該記住本文中所展示的大多數(shù)操作是單向的。例如,如果您將圖像縮小了,則圖像數(shù)據(jù)就丟失了。如果此后您再放大該圖像,則輸出將很粗糙。例如,讓我們拍一幅照片,制作縮略圖,然后再擴(kuò)大該圖像。為了節(jié)省一些篇幅,在此,我將只包括最初和最后的圖像,而省略中間的縮略圖。 圖 18. 凱恩斯瀑布 現(xiàn)在,我們將把縮小和放大操作鏈接在一起: # convert -sample 10% -sample 1000% input.jpg output.jpg | 這產(chǎn)生了如下所示的圖像: 圖 19. 斑駁的瀑布 很難在最終的圖像中看出瀑布來,盡管分散您的眼光似乎有些幫助。
結(jié)束語 在本文中我們討論了一些有趣的事情,ImageMagick 可以完成這些任務(wù)以滿足您的命令行圖像處理需求。這里所描述的工具并不能解決所有問題,有時您會需要定制代碼段,但是通用的命令行圖像處理工具通常可以大幅度地減輕工作負(fù)擔(dān)。
參考資料
關(guān)于作者 | | | Michael 已在圖像處理領(lǐng)域工作了好多年,包括為澳大利亞政府部門管理和開發(fā)大型圖像數(shù)據(jù)庫的幾年。目前,他正在為 Tower Software 工作,該公司制造名為 TRIM 的世界領(lǐng)先的 EDMS 和記錄管理軟件包。Michael 還是名為 Panda 的開放源碼 PDF 生成 API 以及一系列其它開放源碼的開發(fā)人員??赏ㄟ^ mikal@stillhq.com與 Michael 聯(lián)系。 | |