使用 ImageMagick 调整图像大小

作者:Dave Taylor

当然,您可以打开像 GIMP 这样的图形程序来调整图像大小,但是如果您想调整 10、50 或 200 张图像的大小呢?ImageMagick 的 convert 程序正是您所需要的。

在我之前的文章中,我开始了一个关于在命令行中使用 ImageMagick的系列文章,但后来我不得不停下来处理大规模的迁移项目,即将我的 AskDaveTaylor.com 网站从一台服务器迁移到另一台服务器,同时将其放入一个完全不同的后端软件系统——简直是疯狂。我仍在修复问题并清理所有这些疯狂的混乱局面。

因此,我的上一篇文章偏离主题,讨论了帮助迁移过程的脚本。我仍在研究这些快速、简短的脚本,包括我今天早上写的一个


for entry in blog/*
do
  new=$(echo $entry | sed 's/blog\///')
  echo "Redirect 301 $entry $new"
done

您能跟踪这个循环的作用吗?唯一棘手的部分是 new= 语句,它从 for 语句中匹配的文件名中删除 blog/;否则,它非常简单。

不过说真的,让我们回到 ImageMagick。您可以使用命令行实用程序做很多事情。但首先,让我看看我上次停在哪儿了。

我刚刚展示了一个简单的 ImageMagick 命令行工具示例,用于识别图像的尺寸,并将其作为创建缩放 HTML img 标签的基础。这是脚本


#!/bin/sh
identify=/usr/bin/identify
scale=$1
image=$2   # needs input validation code

height=$($identify $image | cut -d\   -f3 | cut -dx -f1)
width=$($identify $image | cut -d\   -f3 | cut -dx -f2)
newwidth="$(echo $width \* $scale | bc | cut -d. -f1)"
newheight="$(echo $height \* $scale | bc | cut -d. -f1)"
echo "<img src=$image height=$newheight width=$newwidth>"
exit 0

(实际上,如果您一直在关注,我忍不住稍微调整了一下,但我仍然很懒,尚未验证输入。您可以很容易地添加该代码。)

使用方法


$ scaledown.sh 0.5 pvp.jpg
<img src=pvp.jpg height=152 width=485>

好的,这是一种减少网页上图像显示的方法,但是任何尝试加速网站的人都知道这里存在一个巨大的问题:减少显示图像的容器并不会减少图像本身。网站访问者仍然必须下载原始图像,这会浪费大量带宽并影响性能。

因此,让我们更新脚本,创建一个新的、更小的图像版本作为其输出的一部分。

输入 convert 命令

identify 命令是了解图形图像文件特定信息的绝佳方法,但是要操作它,您需要切换到 convert

convert 有数百万个命令行选项,但我在这里使用的一个是 -resize,像这样


$ convert pvp-big.jpg -resize 0.5 pvp-0.5.jpg
$ identify pvp-big.jpg pvp-0.5.jpg
pvp-big.jpg JPEG 970x305 970x305+0+0 8-bit DirectClass 127kb
pvp-0.5.jpg JPEG 1x1 1x1+0+0 8-bit DirectClass 1.1kb

嗯...您可以看到发生了什么,对吗?图像从 970x305 变为 1x1。哎呀。

这是怎么发生的?问题是我给 -resize 选项传递了错误的参数类型。实际上,它需要一个百分比(奇怪的是),所以 -resize 50%-resize 50 都可以工作


$ convert pvp-big.jpg -resize 50 pvp-50.jpg
$ convert pvp-big.jpg -resize 50% pvp-50%.jpg
$ identify pvp*
pvp-50.jpg[1] JPEG 50x16 50x16+0+0 8-bit DirectClass 2.01kb
pvp-50%.jpg[2] JPEG 485x153 485x153+0+0 8-bit DirectClass 44.7kb
pvp-big.jpg[3] JPEG 970x305 970x305+0+0 8-bit DirectClass 127kb

一点数学运算表明,-resize 50 意味着宽度被缩放到 50 像素,高度按比例缩小到微小的 16 像素。另一方面,-resize 50% 实现了目标,将图像缩小到合理的 485x153。

因此,脚本将需要用户输入适当的百分比值或进行其他补偿。为了让它更有趣,让我们让输出文件名获得一个后缀,表示新的几何尺寸(正如 ImageMagick 喜欢引用的高度 x 宽度值)。在这种情况下,目标是让 pvp-big.jpg 缩小 50%,并复制为 pvp-big.285x153.jpg。

与其使用原始脚本中的 bc 语句,不如让 ImageMagick 通过以下工作流程来完成工作

  1. 将图像转换为调整大小后的图像并保存为临时文件。

  2. 使用 identify 获取临时文件的新尺寸。

  3. 根据几何尺寸创建新文件名。

  4. 将临时文件重命名为指定了几何尺寸的新文件名。

事实证明,这要轻松得多,因为不再需要数学运算,这是一件好事!

最困难的部分是创建新文件名,这比转换本身涉及更多的代码行。它涉及到找出文件名后缀,分割文件名,并构建一个新的文件名,将新的图像几何尺寸插入中间。

这是结果(很长)


#!/bin/sh
convert=/usr/bin/convert
identify=/usr/bin/identify
resize=$1
source=$2
if [ -z "$resize" -o -z "$source" ] ; then
  echo "Usage: $0 resize sourcefile"; ;exit 1
fi
if [ ! -r $source ] ; then
  echo "Error: can't read source file $source" ; exit 1
fi
# let's grab the filename suffix
filetype=$(echo $source | rev | cut -d. -f1 | rev)
 
tempfile="resize.$filetype" # temp file name

# create the newly sized temp version of the image
$convert $source -resize $resize $tempfile

# figure out geometry, the assemble new filename
geometry=$($identify $tempfile | cut -d\   -f3 )

newfilebase=$(echo $source | sed "s/$filetype//")
newfilename=$newfilebase$geometry.$filetype

# rename temp file and we're done
mv $tempfile $newfilename

echo \*\* resized $source to new size $resize. result = $newfilename

exit 0

就是这样。如果您逐步进行,它并不十分复杂。实际上,回到我之前提出的四步算法。这几乎完全在脚本中的注释中重复了。

唯一的细微之处是 newfilename 组装的顺序,它只是将一系列变量串在一起,使其值紧密结合。

让我们试一试,看看会发生什么


sh resize.sh 50% pvp.jpg
** resized pvp.jpg to new size 50%. result = pvp.485x153.jpg

我持怀疑态度,所以让我们通过使用 identify 获取其尺寸来测试新的图像文件


$ identify pvp.485x153.jpg
pvp.485x153.jpg JPEG 485x153 485x153+0+0 8-bit DirectClass 44.7kb

完美。更重要的是,看看图像大小由于缩小了 50% 而缩小了多少


$ ls -l pvp.jpg pvp.485x153.jpg
-rw-rw-r-- 1 taylor taylor  45751 Oct  9 04:14 pvp.485x153.jpg
-rw-r--r-- 1 taylor taylor 130347 Sep  5 08:20 pvp.jpg

绝对的胜利,并且是一个非常方便的脚本,可以保留下来。

当然,更好的位置参数检查和快速检查以确保 resize 参数不是什么疯狂的东西会是很好的编码,但它不是一个糟糕的脚本,它服务于非常有用的目的。

就这样。在我的下一篇文章中,我计划研究添加浮雕——叠加在图形上的文本——作为一种从命令行为照片集添加水印的简单方法。在那之前,再见!

Dave Taylor 长期以来一直在 UNIX 和 Linux 系统上编写 shell 脚本。他是Learning Unix for Mac OS XWicked Cool Shell Scripts 的作者。您可以在 Twitter 上找到他 @DaveTaylor,您可以通过他的技术问答网站联系他:Ask Dave Taylor

加载 Disqus 评论