Shell 技巧 - 某种程度上的图片大小调整

作者:Dave Taylor

这可能是我使用 Web 的一个特殊习惯,即截取屏幕截图,然后希望缩放它们以适应我的页面(特别是当它们是全屏图像时),但我发现我花费大量时间来计算如何均匀地缩小和缩放图像。

例如,我可能会对我在其中撰写此专栏的窗口进行全尺寸屏幕截图,结果发现它的宽度和高度分别为 722 x 719 像素。但是,如果我要将其包含在我的 Weblog 中,我希望将其缩小到不超过 600 像素,以免破坏我的网站布局。

实际上,我可以在屏幕截图应用程序中缩小图像,或者使用辅助图形应用程序,但事实证明,Web 浏览器可以根据显式的“height”和“width”属性来放大或缩小图像。例如,假设文档窗口名为 edit.png。然后,我可以将图像包含在网页中,使用

<img src="edit.png" alt="editing a file" />

这样就可以正常工作。要缩放,很简单,只需添加 height 和 width 参数。为了使其与图像本身匹配,我会使用

<img src="edit.png" alt="editing" height="719" width="722" />

但是,正如我所说,事实证明你实际上可以计算不同的值,浏览器会缩放它以匹配。例如,要将图像缩小 50%,我会调整它以读取

<img src="edit.png" alt="editing" height="359" width="361" />

所以这就是我在我的网站上所做的,坦率地说,这很麻烦。

相反,我真正想要的是一个实用程序,它可以计算出图像的当前高度和宽度,然后根据缩放因子自动将其缩放到我期望的新值。这就是我们将在本专栏中深入探讨的内容。

计算图像大小

Linux 中有一些非常出色的图像处理软件包,最著名的是 ImageMagick,但我们不需要任何花哨的东西,因为普通的、旧的、未被充分赞扬的 file 命令就可以为我们完成这项工作。我将只关注 PNG(渐进式网络图形)文件,因为它们非常适合大多数 Web 用途,但值得注意的是,许多 Linux file 命令在计算 JPEG 图像的图像尺寸时会遇到困难。

这是一个例子

$ file edit.png
edit.png: PNG image data, 722 x 719, 8-bit/color RGB, non-interlaced

实际上,这包含了很多信息,包括关键要素——图像文件本身的尺寸。在这种情况下,它是宽度 x 高度,因此 722 是宽度(以像素为单位),719 是高度。可以从输出中以多种方式提取这些信息,但最简单的方法是使用 cut

width="$(file $filename | cut -f5 -d\  )"
height="$(file $filename | cut -f7 -d\  )"

但是,如果您尝试这样做,您会发现高度是错误的。它有一个尾随逗号,因为 cut 使用空格作为分隔符(这就是看起来很奇怪的-d\正在指定)。反斜杠转义了 shell 将空格解释为 arg 分隔符。当您输入此内容时,您需要在反斜杠之后和右括号之前留一个空格,原因就在于此。不过,可以使用 sed 修复它

sed 's/,//'

现在我们有了数值,我们如何自动缩放它们?我喜欢使用 bc 二进制计算器,即使它的界面非常粗糙。将 722 乘以 0.50(当然,即 50%),可以这样做

echo 722 * 0.50 | bc

除了 \* 将被扩展。因此,实际上,明智地使用引号可以巧妙地解决这个问题

width="$(echo "$width * $multiplier" | bc)"

这当然更像 shell 脚本,并且效果很好,但​​我发现对于 bc 的某些实现,即使添加scale=0,理论上应该删除乘法运算产生的尾随小数元素,但并没有给我们一个整数返回值。同样,一个简单的修复为我们提供了最终的脚本行

width="$(echo "$width * $multiplier" | bc | cut -d. -f1)"

同样的操作可以得到新计算的“高度”,如果用户指定的乘数小于 1,则会缩小。如果您指定更大的值,您可以同样轻松地放大。

使其作为脚本工作

这是当前的基本脚本

filename="edit.png"
multiplier="0.75"

width="$(file $filename | cut -f5 -d\  )"
height="$(file $filename | cut -f7 -d\  | sed 's/,//')"

width="$(echo "$width * $multiplier" | bc | cut -d. -f1)"
height="$(echo "$height * $multiplier" | bc | cut -d. -f1)"

echo "$filename scaled: width=$width height=$height"

使用指定的文件名进行测试会产生以下结果

$ sh scale-image.sh
edit.png scaled: width=541 height=539

然而,这并不是我真正想要的。首先,我希望能够在命令行上指定文件名和乘数。其次,输出需要稍作调整才能更有用——这些值需要用引号引起来。

这是我希望看到的

$ sh scale-image.sh 0.75 edit.png
edit.png: width="541" height="539"
$

鉴于我们已经拥有的基本脚本,这并不难实现。看看你是否可以自己完成。

提示:我实际上使用“for name; do; done”循环来逐步完成文件缩放,因此我可以指定一组图像并批量计算它们。尝试一下,结合 shift 命令,在乘数值保存到命名变量后将其删除。

Dave Taylor 是一位拥有 26 年 UNIX 经验的资深人士,The Elm Mail System 的创建者,以及最近畅销书 Wicked Cool Shell ScriptsTeach Yourself Unix in 24 Hours 的作者,以及其他 16 本技术书籍。他的主要网站是 www.intuitive.com,他还提供技术支持,网址为 AskDaveTaylor.com。如果您愿意,可以在 Twitter 上关注他:twitter.com/DaveTaylor

加载 Disqus 评论