使用 ImageMagick 调整图像大小
当然,您可以打开像 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 通过以下工作流程来完成工作
-
将图像转换为调整大小后的图像并保存为临时文件。
-
使用
identify
获取临时文件的新尺寸。 -
根据几何尺寸创建新文件名。
-
将临时文件重命名为指定了几何尺寸的新文件名。
事实证明,这要轻松得多,因为不再需要数学运算,这是一件好事!
最困难的部分是创建新文件名,这比转换本身涉及更多的代码行。它涉及到找出文件名后缀,分割文件名,并构建一个新的文件名,将新的图像几何尺寸插入中间。
这是结果(很长)
#!/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 参数不是什么疯狂的东西会是很好的编码,但它不是一个糟糕的脚本,它服务于非常有用的目的。
就这样。在我的下一篇文章中,我计划研究添加浮雕——叠加在图形上的文本——作为一种从命令行为照片集添加水印的简单方法。在那之前,再见!