内容


通过命令行进一步处理图形

在 Linux 上使用 ImageMagick 的提示与技巧

Comments

去年我为 developerWorks 写了一篇关于在命令行中使用 ImageMagick 处理图像的文章。那篇文章得到了相当好的评价,此后我通过电子邮件收到了很多关于 ImageMagick 的问题。本文是对上一篇文章中讨论的技术的扩展,并且回答了那些我力所能及的问题。如果这是您在 IBM DeveloperWorks 发现的第一篇关于 ImageMagick 的文章,那么您最好先去阅读其第一篇文章(在 参考资料 部分可以找到它的链接)。

本文采用了根据示例来讨论特定问题的论述方法,但是那些概念同样适用于其他问题空间。这个方法和前一篇文章所采用的方法相同。这里讨论到的技术也可以和我们先前讨论的那些技术结合到一起使用。

应该注意的是,有很多方法可以完成本文中讨论的内容。我将只讨论我所使用的方法,并且知道这些方法适合我。这并不是说除此以外其他工具不好,而只是表示我喜欢我现在使用的工具。

圆角

如果您看一看 Mac OS/X,以及很多 Web 站点,那些图片有非常漂亮的圆角。您怎样才能用 ImageMagick 实现这一效果?好的,我们将展示一些使用 composite 命令来生成这种效果的灵活方法。

不过,在我们达到目的之前,让我们先谈一下我们将要运用的策略。如果您考虑一下,可以通过将一些标准预制的角叠加到原始图像上来制作出具有圆角的图像。甚至不需要是圆的角 —— 我们可以用尖角,或者是更有趣的东西。

记住将角的多余部分设置为透明的。这一透明特性可以让我们要叠加角的图像仍可以显示出来。这可能会让人有些迷惑,因为有一些图像浏览器,比如 xview,将以黑色或者其他颜色来表示透明。

图 1. 用 xview 显示的圆角
用 xview 显示的圆角

实际的角图像被叠加到一个图像上之后会变得更为清晰,所以让我们来继续做下去。我有一张以前在堪培拉的一个湖岸边拍摄的小图片。在没有圆角时,这张小图片看起来是这样的:

图 2. Burley Griffin 湖
湖风景

您可以使用 composite 命令将一个图像叠加到另一个图像上。让我们只叠加一个角,来看看发生了什么:

composite -gravity NorthEast rounded-ne.png lake.png lake-1.png

其中 gravity 参数定义了在图像何处放置叠加的图像 —— 在我们的示例中是圆角。这一特定的命令让我们得到了下面的图像:

图 3. 有一个圆角的 Burley Griffin 湖
湖风景

下面我们再来处理其他的角:

composite -gravity NorthEast rounded-ne.png lake.png lake-1.png
composite -gravity NorthWest rounded-nw.png lake-1.png lake-2.png
composite -gravity SouthEast rounded-se.png lake-2.png lake-3.png
composite -gravity SouthWest rounded-sw.png lake-3.png lake-4.png

这将带给我们最终的图像:

图 4. 圆角的 Burley Griffin 湖
湖风景

依我拙见,这看起来有一些酷。您还应该注意到,这些角图像不必是圆的。如果您对尖角或者类似的东西感兴趣,那些同样是可能的 —— 只需要在位图编辑器中改变角的图像。实际上,您甚至可以用您的徽标取代角来叠加到图像上。

如果您想使用我的圆角,可以访问在本文末尾参考资料部分列出的链接。

最后,下面是一个小脚本,让您可以将指定目录下的所有 png 图像的角变为圆角:

for img in *.png do composite -gravity NorthEast rounded-ne.png $img.png $img-1.png
composite -gravity NorthWest rounded-nw.png $img-1.png $img-2.png
composite -gravity SouthEast rounded-se.png $img-2.png $img-3.png
composite -gravity SouthWest rounded-sw.png $img-3.png $img-4.png
done

为图像添加边框

有一些读者提出的另一个问题是如何给图像添加边框。同样,通过 ImageMagick 可以轻松完成。

凸边或凹边

我将要介绍的第一类边框是凸边或凹边。这个效果是通过调节图像边缘的颜色而实现的,看起会感觉图像像是从周围表面凸起或者凹下。为实现这个效果,您需要指定一个尺寸,首先是水平尺寸,然后是垂直尺寸。这些尺寸的大小必须满足这样一个规则,尺寸的二倍必须小于或等于在那个方向上图像的尺寸大小。例如,您不可以指定边框垂直尺寸大于图像垂直尺寸的一半 —— 其实这主要是说您不可以制作一个比原图还要大的边框。

使用 -raise 命令行参数来创建凸边。例如,为创建一个 5 像素乘 5 像素的边,我们执行:

convert -raise 5x5 tree.png tree-raised.png

这将给出最终的图像:

图 5. 带有凸边的图像
带有凸边的水边的一些树
带有凸边的水边的一些树

只需要将命令行参数换为 +raise 就可以创建一个凹边。例如:

convert +raise 5x5 tree.png tree-lowered.png

这将得到一个稍有不同的图像:

图 6. 带有凹边的图像
带有凹边的水边的一些树
带有凹边的水边的一些树

一个简单的纯色边

如果您喜欢稍微简洁一些的风格,您可能对纯色的边感兴趣。ImageMagick 同样可以为您完成这一任务。

convert -bordercolor red -border 5x5 flower.png flower-border.png

这将创建:

图 7. 带有红边的图像
带有红边的一些花

我们可以在命令行中为边指定哪些颜色?是这样,这个列表太长了以至于在本文中无法给出。执行下面这个命令可以得到列表的一个拷贝:

convert -list color

从桔黄色到原木色,从玉米色到贝壳白,有 683 种“基本”颜色可以选择 —— 更不用说您还可以使用以下方法来指定您自己的颜色了,这里 R 表示红色值,G 表示绿色值,B 表示蓝色值,A 是 alpha(透明度)值:

  • #RGB - (R,G,B 是十六进制数,每个 4 位)
  • #RRGGBB - (每个 8 位)
  • #RRRGGGBBB - (每个 12 位)
  • #RRRRGGGGBBBB - (每个 16 位)
  • #RGBA - (每个 4 位)
  • #RRGGBBAA - (每个 8 位)
  • #RRRGGGBBBAAA - (每个 12 位)
  • #RRRRGGGGBBBBAAAA - (每个 16 位)
  • rgb(r,g,b) - (r,g,b 是十进制数)
  • rgba(r,g,b,a) - (r,g,b,a 是十进制数)

构建一个更复杂的边框

接下来让我们用 -frame 命令行参数构建一个更为复杂的边框。首先我们将添加一个和前面的示例中构建的边相同(只是颜色不同)的边框。

convert -mattecolor black -frame 5x5 beach.png beach-frame.png

用参数 -mattcolor-frame 替换了 -bordercolor-border,不过其余部分与 border 命令相同。

图 8. 简单的黑色边
有简单黑色边框的海滩图片
有简单黑色边框的海滩图片

现在我们可以做一些更复杂的事情,添加一些类似于用 -raise 命令得到的阴影。

convert -mattecolor black -frame 5x5+2 beach.png beach-frame2.png

现在是这样了:

图 9. 同一张图片,不过有一些更多的修饰
带有稍复杂的边的海滩图片
带有稍复杂的边的海滩图片

最后,我们可以添加一些更多的修饰,以达到我期望的最终效果:

convert -mattecolor black -frame 5x5+2+2 beach.png beach-frame3.png

最后我们得到:

图 10. 完成的边框
带有已完成边框的海滩图片
带有已完成边框的海滩图片

如果您正在寻找为您的图像制作漂亮的边框的方法,那么我建议您花一些时间来研究 -frame 命令的参数。例如,这里有一些有趣的边框,加在了澳大利亚 King’s Canyon 的岩石图片上。

要深入了解可用的各种不同边框,请参考 convert 的手册页。

convert -mattecolor gray -frame 25x25+0+25 rock.png rock-frame1.png

convert -mattecolor gray -frame 25x25+25+0 rock.png rock-frame2.png

图 11. 两个边框
两张有漂亮边框的岩石图片
两张有漂亮边框的岩石图片

同时处理多个图像

在我的上一篇文章中,我已经给出了同时转换多个图像的代码。正如一些人所指出的,我给出的代码并不是最好的方法。

下面是我以前给出的代码:

清单 1. 生成当前目录下所有 JPEG 图片的缩略图

for img in `ls *.jpg`
do
  convert -sample 25%x25% $img thumb-$img
done

现在已经证明这是不好的 bash 风格,因为它没有很好地处理文件名中的空格(每个词将被认为是一个单独的文件名)。取而代之,一个更好的方法是:

清单 2. 生成当前目录下所有 JPEG 图片的缩略图,具有更好的 bash 风格

for img in *.jpg
do
  convert -sample 25%x25% $img thumb-$img
done

这将更好地处理文件名中的空格。

不过,结果证明这两个方案 ImageMagick 都不需要 —— 我们可以只使用 mogrify 命令。 mogrify 命令用于转换一系列文件(虽然它同样可以处理单一的图像)。

前面的代码片断将变成:

mogrify -sample 25%x25% *.jpg

注意,这将会导致原始图像被新图像所覆盖。很难指定输出文件名,这是 mogrify 的局限性之一。 指定输出文件名的惟一的方法是,改变输出文件相对于输入文件的格式。这样的结果是新的图像具有了不同的扩展名。例如:

mogrify -format png -sample 25%x25% *.jpg

这将创建一系列输出文件,这些文件的末尾的 jpg 将由 png 所取代,同时伴随着文件格式的改变。

前面定义的所有转换也都可以用 mogrify 命令来完成,所以,如果您不在意原始文件被覆盖的话,这是一个很好的选择。如果您不希望原始文件被覆盖,那么您可以将它们拷贝到一个临时目录来对它们进行转换(mogrify),并改变它们的名字 —— 或者您继续使用 convert 和 bash。

PDF 处理

到现在为止我们所讨论过的示例(不管是本文的还是前文的),都是针对独立图像的简单转换。ImageMagick 还可以一次进行不止一个图像的有趣转换,值得关注。

最常见的示例是 ImageMagick 的 PDF 处理。让我们假想一个情形,您给出了一个包含一系列图像(每页一个)的 PDF 文件。ImageMagick 将为您导出那些图像到单独的文件中。例如,下面是一个 PDF 文档的屏幕截图,其中有一些我最近到 linux.conf.au 旅游的图片(顺便说一句,实在是太美了):

图 12. 带有几个图像的 PDF 样例
PDF 中的一些图像
PDF 中的一些图像

让我们假定上面的 PDF 是一个朋友发给您的。您希望将图像导出以进行进一步的处理。

convert 当然可以将这些图像从 PDF 文档中导出:

convert foo.pdf pages.png

这将是我们想要做的 —— 每一页被导出为自己的 PNG 文件。不过,有一个命名方面的意外的副作用。

清单 3. 检查文件名

mikal@deathstar:~/foo$ convert foo.pdf pages.png
mikal@deathstar:~/foo$ ls pages*
pages.png.0  pages.png.1  pages.png.2  pages.png.3  pages.png.4
mikal@deathstar:~/foo$

由于命令创建了不只一个 PNG 文件,所以文件名被附加了一个惟一的编号。如果您接下来尝试使用基于文件扩展名来判断文件类型的代码或者脚本,那么将会受到影响。

作为一个友好的工具, convert 让我们可以更好地指定文件名。前面的命令实际上应该是像这样:

清单 4. 从 PDF 文档中导出页,赋以更好的文件名

mikal@deathstar:~/foo$ convert foo.pdf pages-%03d.png
mikal@deathstar:~/foo$ ls pages*
pages-000.png  pages-001.png  pages-002.png  pages-003.png  pages-004.png
mikal@deathstar:~/foo$

%03d printf风格的格式说明符。对于这种用法您需要了解的只是 %d代表一个十进制数,而且您还可以通过向序列中插入一个 0<number> 来引入一组前导零。数字指定了显示的值应该占用的位数。

还应该注意的是,您可以导出包含文本的 PDF 页。实际上其幕后机制是 ImageMagick 使用 Ghostscript 来呈现页,然后将其转换为您所选择的图像格式。不过没有进行光学字符识别 —— 您得到的是位图。

您还可以用 convert 将多个图像文件转换为 PDF。实际上前面的示例中的 PDF 是通过下面这个命令构建的:

convert dsc* foo.pdf

只需要向 convert 传递图像文件的一个列表,并确保最后一个文件名是您要将它们放入的 PDF 文档的名字。

支持每个文件多个图像的其他格式

当与 ImageMagick 一起使用时,还有其他 45 种文件格式可以存储不止一个图像,本文的 参考资料 部分有一个链接指向其完全列表。

所有这些的处理方式都与提到的 PDF 示例相同。其中一些也很有趣。能将 postscript 文件的页导出为图像(例如,考虑将您发表的论文作成缩略图放在您的 Web 站点上),或者能将您刚收到的多页传真的所有页作成一个 TIFF 图像,这些都是很方便的。

您甚至可以从 MPEG 影片中导出帧,不过那需要更深入地讨论,已经不在本文的范围之内。

结束语

在本文中我们对我的上一篇关于 ImageMagick 的文章中讨论的一些有趣的技术进行了进一步描述,包括如何使您的图像变为圆角(尤其是上一次我们讨论的小图片),给您的图像添加各种不同的漂亮边框,以及如何同时处理多幅图像。最后介绍了如何自多页格式(的文件) 中导出图像,以及如何构建新的多页文档。

如果您正在寻找更多的参考资料,那么我鼓励您去访问本文 参考资料部分中给出的 ImageMagick Web 站点。还有,如果您有什么问题的话欢迎给我写信。

非常感谢那些向我提出实际问题的人,是这些问题促成了本文。我还要感谢您的耐心,因为过了很长时间我才回答这些问题。


相关主题

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
  • ImageMagick 是一个工具和库的集合,可以读、写和处理多于 89 种主要格式的图像。 ImageMagick Web 站点是一个极好的资源,提供了 ImageMagick 源代码的下载。
  • 在 Anthony Thyssen 的 ImageMagick Examples网页中进一步学习。
  • GIMP,或者说是 GNU Image Manipulation Program,是一个自由发布的软件套件,用于照片润饰、图像合成和图像创作。它遵循 GNU General Public License (GPL) 发布。
  • 本文中的很多图片都是我最近到 linux.conf.au 的旅途中拍摄的。
  • Graphics from the command line”( developerWorks, 2003 年 7 月)是本系列的第一篇文章,讨论了如何用 ImageMagick 生成缩略图、旋转、进行有趣的处理以及确定图像信息。
  • 用 libtiff 进行图形编程”( developerWorks, 2002 年 3 月)讨论了黑白图像处理的概念,它尤其专注于 TIFF 图像。
  • 用 libtiff 进行图形编程,第 2 部分”( developerWorks, 2002 年 6 月)讨论了彩色 TIFF 图像,而且还讨论了诸如哪种压缩方案适合于您之类的重要主题。
  • Scalable Vector Graphics (SVG) 是一种用 XML 描述 2D 向量图形的应用程序语言,具有动画和脚本功能。从 通过命令行处理图形developerWorks, 2002 年 2 月)开始入门。
  • IBM Toolkit for MPEG-4 是一组 Java 类和 API,附有样例和 MPEG-4 生成应用程序。它还是 alphaWorks 的最热门下载之一 —— 您自己来查找原因吧!
  • 得到图片了?用 VoiceXML 给您的 Web 站点添加声音。通过这篇 Voice-Enabling Your Web SitesdeveloperWorks, 2001 年 11 月)入门。
  • 得到了图片 声音?使用 IBM Tivoli Web Site Analyzer 来找出会产生哪些影响。IBM Tivoli Web Site Analyzer 捕获、分析、存储并报告 Web 站点的使用率、健康状况、完整性和站点内容,并提供来访者站点交互和站点整体性能的基本度量标准。
  • developerWorks Linux 专区可以找到更多为 Linux 开发者准备的参考资料。
  • 在 Developer Bookstore 的 Linux 区可以找到很多精选的 Linux 书籍。

评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=21475
ArticleTitle=通过命令行进一步处理图形
publish-date=04012004