ImageMagick 示例 —— 裁切与加边
- 基本裁剪运算符
- 脱靶图像(来自糟糕的裁剪)
- 裁剪带有现有虚拟画布的图像
- 从结果中移除虚拟画布,使用 +repage *
- 带虚拟画布调整的视口裁剪
- 相对于 Gravity 的裁剪
- 按百分比裁剪图像
- 平铺裁剪,将一张图像细分为多张图像
- 居中平铺裁剪,将余料留在边缘四周
- 条带裁剪,裁出行与列
- 象限,围绕单个点切割
- 使用负偏移,移除底部或左侧边缘
- 裁剪成大致等尺寸的分块
- Frame,为图像添加类 3D 边框
- Shave,从图像移除边缘
- 按指定颜色 Trim
- 仅 Trim 图像的一侧
- Trim“模糊”图像 -- 低质量 JPEG 图像
- Trim“噪点”图像 -- 扫描图像或视频图像
在这里我们探讨 ImageMagick 的各种操作,它们允许你对图像动刀,并在图像四周添加画框与边框。也就是说,我们看的是那些在不缩放图像内容的情况下改变图像尺寸的操作。你可能觉得这是个简单的操作,确实如此。如此简单,以至于 IM 提供了海量的方式与方法来实际完成这项任务。多到我需要给它单独一页示例才能把它们全部展示出来。
裁剪(把图像切到合适的尺寸)
裁剪与画布 Page
“[-crop](https://imagemagick.org/command-line-options/#crop)”图像运算符会简单地按你用 geometry 参数指定的尺寸与位置,从当前序列中所有图像里切出那一部分。
magick rose: rose.gif
magick rose: -crop 40x30+10+10 crop.gif
magick rose: -crop 40x30+40+30 crop_br.gif
magick rose: -crop 40x30-10-10 crop_tl.gif
magick rose: -crop 90x60-10-10 crop_all.gif
magick rose: -crop 40x30+90+60 crop_miss.gif
为了让你能确切核对发生了什么,这里是对上面裁剪结果运行“magick identify”的输出。
magick identify rose: crop.gif crop_br.gif crop_tl.gif \
crop_all.gif crop_miss.gif
请注意,所显示图像的尺寸(即其虚拟画布)并未受到“[-crop](https://imagemagick.org/command-line-options/#crop)”操作的影响。实际图像本身已被裁剪,可能变得更小,但用于显示该 GIF 图像的画布仍与原始画布尺寸相同。你还会注意到,所产生的实际图像的尺寸可能并不是你向裁剪请求的那个尺寸。它可能比你预期的小得多,因为裁剪本身部分地或完全地落在了被裁图像的实际区域之外。你还会注意到,在很多情况下图像在虚拟画布上的“偏移”也被改变了,从而使被裁剪图像的像素仍处于它们在原始图像中完全相同的位置。也就是说,图像内容本身不会移动,即便实际图像本身变小了。这意味着,如果你现在修改这张更小的图像,然后将它(使用图层叠加运算符)叠回原始图像之上,它会恰好回到该子图像最初被取出的位置。也就是说,IM 保留了图像的“虚拟画布”“page”或“图层”信息,以便日后使用时予以保留。这对 GIF 动画处理的正确运作尤为重要。有关此点的更多信息请参见拆解 GIF 动画。 | _GIF 图像会主动利用被 IM 裁剪图像中的“page”或“虚拟画布”尺寸与偏移信息。如果你不想要这些信息,请在“[-crop](https://imagemagick.org/command-line-options/#crop)”之后立即用“[+repage](https://imagemagick.org/command-line-options/#repage)”将其移除。
请注意,许多图像格式并不保存这种虚拟 page/画布信息,因此保存为此类格式会自动将其移除。JPEG 就是一种会移除此信息的典型格式。
PNG 格式并不太利用 page/画布信息(多 PNG(MNG)格式除外),但它确实会保存 page 偏移信息(甚至包括负偏移)。IM 还会添加少量元数据,以保留虚拟画布尺寸供其他 IM 命令日后使用。
正因为这种保留,我强烈建议:即便保存为 JPEG 或其他无 page 概念的图像格式,且你并不需要这些信息时,也仍然施加一次“[+repage](https://imagemagick.org/command-line-options/#repage)”,作为预防措施,并明确表明你不想要它。
_
---|---
请注意,裁剪的行为可受这些 define 影响:
| trim:percent-background=X% | 设置一条边缘中可容忍的背景量。以百分比指定。0% 表示不容忍任何背景。50% 表示一条边缘按 fuzz-factor 计可包含最多 50% 的背景像素。 |
|---|---|
| trim:edges={north,east,south,west} | 仅 trim 图像的指定边缘。 |
| trim:minSize=geometry | 将 trim 限制到指定尺寸。 |
| type:features=string | 添加一个字体特性,供 RAQM 委托在复杂文本排版期间使用。它通常用于打开默认未启用的可选字体特性,但也可用于关闭默认字体特性。这些特性包括用于控制 kerning(字距调整)、ligature(连字)以及阿拉伯文的特性。 |
| type:hinting=false | 禁用字体 hinting。正确的字形渲染需要将缩放后的点对齐到目标设备的像素网格,这一操作通常称为 hinting。它的主要目的之一是确保重要的宽度与高度在整个字体中得到一致对待。(例如,常常希望“I”和“T”字形的中央竖线具有相同的像素宽度。Hinting 还会管理诸如笔画(stems)与 overshoots 之类的特征,它们在小像素尺寸下可能引发问题。 |
脱靶图像(来自糟糕的裁剪)
上面示例中的最后一张图像(例如“crop_miss.gif”)还产生了一张特殊的空图像。这类图像可由诸如裁剪、Trim、图层比较,甚至GIF 动画优化等会生成空的或无意义结果的操作所产生。例如在上面前一个示例中,“[-crop](https://imagemagick.org/command-line-options/#crop)”操作脱靶了它正在裁剪的实际图像,于是它产生了这张特殊的“脱靶”图像,以及一些提示性的警告消息……
这张输出图像,即“脱靶”图像,是一张最小化的图像,尺寸为一像素、偏移为 0,但带有原始图像的 page 或画布尺寸,以及该图像可能关联的任何其他元数据。在这里它代表了本应由“[-crop](https://imagemagick.org/command-line-options/#crop)”返回的“空”或“零尺寸”图像,但由于没有任何图像格式能输出“零”尺寸的图像,于是改用一张单个透明像素的图像替代。为了让你看得更清楚,这里给出脱靶图像的“[identify](basics.html#identify)”输出,以及对该单像素图像的“IM 像素枚举”,表明它只包含一个单独的透明像素。
magick identify crop_miss.gif
magick crop_miss.gif crop_miss_data.txt
这张“脱靶”图像基本上与创建一张“[null:](files.html#null)”图像相同,但设置了原始源图像的 page 或虚拟画布尺寸(但不含其偏移),以及所有其他图像元数据,例如 GIF 动画的时序延迟。不过其中的 GIF 处置方法(disposal method)可能会被修改,以确保裁剪后动画仍保持正确。基本上你需要记住,“[-crop](https://imagemagick.org/command-line-options/#crop)”及其他与之类似的相关运算符都可能产生一张特殊的“脱靶”图像。因此在用 IM 编写脚本时,如果有可能出现这种最小化图像并可能给你带来问题,你应当计划好去查找警告消息或这张特殊的“脱靶图像”。如果你不想要警告消息(例如你已预料并会处理偶尔出现的“脱靶”图像),可以在命令行中加上一个“[-quiet](https://imagemagick.org/command-line-options/#quiet)”操作控制设置。这会告诉 IM 不要输出提示性警告消息,只输出真正的错误。目前尚无方法从当前图像序列中移除任何“脱靶”或“[null:](files.html#null)”图像。不过此类方法已被提议用于 IM 的未来版本。如果你发现需要这样的方法,请给我发邮件。
裁剪带有现有虚拟画布的图像
如果一张图像已带有现有的虚拟画布(例如 GIF 动画的某一帧),那么“[-crop](https://imagemagick.org/command-line-options/#crop)”操作将相对于虚拟画布来施加,而非相对于实际图像。也就是说,它会尽力保留被裁剪图像的实际像素数据在画布上的偏移。也就是说,裁剪前的某个特定像素,在裁剪之后相对于虚拟画布应仍位于相同的偏移处。如此一来,分层图像或 GIF 动画的裁剪即便“画布”本身未被裁剪也能继续正确运作。这里我们创建一张在 page 画布上居中的图像,并以多种方式裁剪它。与之前一样,画布尺寸本身不会被该操作修改。
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -crop 32x32+16+16 crop_page.gif
magick paged.gif -crop 32x32+0+0 crop_page_tl.gif
magick paged.gif -crop 32x32+32+32 crop_page_br.gif
magick paged.gif -crop 60x60+2+2 crop_page_all.gif
magick paged.gif -quiet -crop 32x32+56+56 crop_page_miss.gif
magick identify paged.gif crop_page.gif crop_page_tl.gif crop_page_br.gif \
crop_page_all.gif crop_page_miss.gif
上面最后那个示例当然就是那张特殊的脱靶图像。请注意,我用一个“[-quiet](https://imagemagick.org/command-line-options/#quiet)”设置抑制了 IM 通常会发出的警告消息。为了让你看清楚到底发生了什么,让我们更仔细地看一下对图像右下角进行的 page 裁剪。这里我在被裁剪的区域上画了一个半透明的方块。
magick paged.gif -page 64x64+32+32 -size 32x32 xc:'#fff8' \
-alpha set -background none -mosaic crop_area_br.png
由此你可以看到到底发生了什么。尽管裁剪完全包含在 page 画布之内,但裁剪并未完全覆盖实际图像。结果是实际图像比用户原本意图的要小,但仍定位在一个更大的画布或 page 之上。
从结果中移除虚拟画布
如果不想要这种虚拟画布信息,你可以使用特殊的“[+repage](https://imagemagick.org/command-line-options/#repage)”运算符,将 page 画布与位置重置为与实际被裁剪图像相匹配。
magick rose: -crop 40x30+10+10 +repage repage.gif
magick rose: -crop 40x30+40+30 +repage repage_br.gif
magick rose: -crop 40x30-10-10 +repage repage_tl.gif
magick rose: -crop 90x60-10-10 +repage repage_all.gif
magick rose: -quiet -crop 40x30+90+60 +repage repage_miss.gif
这当然就是 IM 新手通常期望从“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符得到的结果。这实际上是如此常见的做法,以至于你可以称它为一条经验法则。
始终在任何类似“crop”的操作之后使用“[+repage](https://imagemagick.org/command-line-options/#repage)”。
除非你确实需要保留那些信息。
上面最后那张图像当然就是那张特殊的裁剪脱靶图像,但我用“[-quiet](https://imagemagick.org/command-line-options/#quiet)”操作设置抑制了警告消息。 |
对于 IM 第 5 版及更早的版本,“[+repage](https://imagemagick.org/command-line-options/#repage)”操作是通过一个“-page +0+0”参数序列来处理的,通常就放在保存为使用虚拟画布与偏移信息的格式(例如 GIF)之前。但那只能在读取或写入文件时使用,从而无法在多个图像处理操作之间使用。__随着 IM 第 6 版的命令行重构,“[-page](https://imagemagick.org/command-line-options/#page)”选项变成了纯粹的图像读取/创建设置,用于创建GIF 动画与图像图层。因此,为了让用户能够设置或更改虚拟画布信息,新增了单独的“[-repage](https://imagemagick.org/command-line-options/#repage)”与“[-set](https://imagemagick.org/command-line-options/#set) page”运算符。 |
|---|---|
带虚拟画布调整的视口裁剪
从 ImageMagick 6.2.4-5 版起,你可以为“[-crop](https://imagemagick.org/command-line-options/#crop)”参数添加一个新的特殊标志。这个“!”标志会告诉裁剪去调整所返回图像的虚拟画布信息,使其相对于被裁剪的区域。换句话说,无论实际被裁剪图像最终的尺寸如何,所返回图像的画布与偏移都会被调整以匹配你请求裁剪的区域。你可以把这个标志理解为:将图像裁剪到与裁剪区域的某个“窗口”或“视口”相匹配。即便有一半图像在那个“窗口”里不可见,所返回部分的虚拟画布与偏移也会匹配那个“视口”。例如……
magick rose: -crop 40x30+10+10\! crop_vp.gif
magick rose: -crop 40x30+40+30\! crop_vp_br.gif
magick rose: -crop 40x30-10-10\! crop_vp_tl.gif
magick rose: -crop 90x60-10-10\! crop_vp_all.gif
magick rose: -quiet -crop 40x30+90+60\! crop_vp_miss.gif
magick identify rose.gif crop_vp.gif crop_vp_br.gif crop_vp_tl.gif \
crop_vp_all.gif crop_vp_miss.gif
| “!”字符对某些 UNIX shell(如“csh”)具有特殊意义,因此必须用反斜杠转义,即便放在引号内也是如此。
---|---
请注意,现在所返回图像的画布尺寸如何与图像被裁剪的区域相匹配。对于完全落在实际图像之内的裁剪,其结果等同于在裁剪后再跟一个“[+repage](https://imagemagick.org/command-line-options/#repage)”。然而,对于任何部分裁剪或脱靶裁剪,其结果将带有一个更大的画布,并且所得图像可能带有偏移。因此,这并不能替代在裁剪后用“[+repage](https://imagemagick.org/command-line-options/#repage)”来重置 page/画布信息。不过你可以在“视口裁剪”之后跟一个Flatten,用真实像素“填满”图像新的虚拟画布。也就是说,你最终会得到一张保证为所请求裁剪尺寸的图像,其中任何“脱靶”区域都以当前的“[-background](https://imagemagick.org/command-line-options/#background)”颜色“视口”填充。例如在把图像填充补满时。 |
magick rose: -crop 100x100-15-25\! -background skyblue -flatten \
crop_viewport.gif
![[IM Output]](../static/img/crop/crop_viewport.gif)
在视口裁剪之后将图像 flatten,实际上等同于使用Extent 运算符(见下文)来提供一次“带补白的裁剪”。在裁剪 GIF 动画时,“视口裁剪”标志也非常重要,因为它不仅调整画布尺寸,还能确保所有图像帧在裁剪区域内仍正确定位。如果没有这个选项,裁剪 GIF 动画会非常困难,需要对图像画布尺寸与偏移进行外部修正。有关此点的示例,请参见动画裁剪,连同画布一起。在许多方面,“视口裁剪”与特殊的视口扭曲设置密切相关,因为两者都表现得像是进入结果图像的一个“窗口”。两者都可用作一种“裁剪”方法。 | “!”标志在生成多图像平铺裁剪时不能使用,在等面积平铺裁剪中也不能使用,在那里它有着不同的含义。请参见下文相应的小节。
---|---
相对于 Gravity 的裁剪
“[-crop](https://imagemagick.org/command-line-options/#crop)”的偏移位置默认相对于图像的左上角。然而,通过设置“[-gravity](https://imagemagick.org/command-line-options/#gravity)”,你可以告诉“[-crop](https://imagemagick.org/command-line-options/#crop)”相对于图像的中心、某个角或某条边缘来切割图像。带 gravity 的裁剪最常见的用途,是裁剪图像的“center”。 |
magick rose: -gravity Center -crop 32x32+0+0 +repage crop_center.gif
![[IM Output]](../static/img/crop/crop_center.gif)
“[-gravity](https://imagemagick.org/command-line-options/#gravity)”设置不仅影响裁剪的初始“零”位置,还会影响裁剪偏移的方向。例如,如果你使用“South”的“[-gravity](https://imagemagick.org/command-line-options/#gravity)”,那么“+0+5”的偏移会使裁剪区域向上偏移,而不是像通常那样向下偏移。 |
magick rose: -gravity South -crop 20x20+0+5 crop_south.gif
![[IM Output]](../static/img/crop/crop_south.gif)
请注意上面裁剪示例的位置。我故意省略了“[+repage](https://imagemagick.org/command-line-options/#repage)”操作,以便你能看到裁剪区域如何相对于图像底部边缘被移位。还要注意,裁剪区域不仅相对于底部(南)边缘,而且该区域被居中“对齐”到底部边缘的中间。所有受 gravity 影响的操作都是如此。
按百分比裁剪图像
“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符还懂得如何将图像裁剪到其原始尺寸的某个百分比。例如下面这条会把图像的尺寸减半。 |
magick rose: -crop 50%x+0+0 crop_half.gif
![[IM Output]](../static/img/crop/crop_half.gif)
| 如果只给出一个尺寸数字,那么该值会同时用于宽度与高度的百分比,且被裁剪区域的最终尺寸会四舍五入到最接近的整数。偏移不是可选的。
---|---
请注意,虽然尺寸可以是百分比,但偏移始终以像素为单位。你不能以图像尺寸的百分比来提供偏移。 |
magick rose: -crop 50%x+30+20 crop_percent.gif
![[IM Output]](../static/img/crop/crop_percent.gif)
| _当裁剪带有偏移时,你必须在参数中提供一个“x”符号,以便该参数能被正确解释。当裁剪区域的宽度与高度只提供了一个数字时,这一点尤为重要。
因此你不能使用诸如“50%+30+20”这样的参数,那是一个错误,会导致裁剪悄无声息地什么也不做。_
---|---
更常见的是从图像中心进行百分比裁剪。 |
magick rose: -gravity Center -crop 50x80%+0+0 crop_percent_center.gif
![[IM Output]](../static/img/crop/crop_percent_center.gif)
| 百分号“%”可以出现在参数中的任意位置,若给出,则同时指代宽度与高度数字。它是一个标志,仅用于声明“图像尺寸”部分是图像虚拟画布或 page 尺寸的一个百分比分数。偏移始终以像素给出。
---|---
你也可以在百分比裁剪中使用“视口裁剪”标志,以自动将裁剪的画布尺寸与偏移设置为被裁剪的区域。 |
magick rose: -gravity Center -crop 50%\! crop_percent_vp.gif
![[IM Output]](../static/img/crop/crop_percent_vp.gif)
| _你不能将百分比尺寸用于平铺裁剪(见下文)。因此,如果未提供偏移而给出了百分比尺寸(如上),则假定偏移为 +0+0。
_
---|---
“!”标志意味着不需要“[+repage](https://imagemagick.org/command-line-options/#repage)”。然而对于本身也可能带有虚拟画布尺寸与偏移的输入图像,仍建议谨慎。
平铺裁剪,将一张图像细分为多张图像
裁剪更有用的一个方面是,当你不给裁剪命令指定具体位置时。也就是说,你给出一个尺寸,而不给出图像中要裁剪的位置。在这种情况下,裁剪不会只生成一张图像,而是生成一整组图像……
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif +gravity -crop 32x32 tiles_%d.gif
magick identify paged.gif tiles_?.gif
| 如果你只想从图像中提取特定数量的瓦片,请看下文的裁剪成大致等尺寸的分块。 | 用“[+gravity](https://imagemagick.org/command-line-options/#gravity)”确保 gravity 处于关闭状态是个好主意。因为在一种特殊情况下(居中的百分比裁剪),gravity 设置会关闭平铺裁剪。gravity 对平铺裁剪的其他影响同样是未定义的。 |
|---|---|
通过使用“[-mosaic](https://imagemagick.org/command-line-options/#mosaic)”或“[-flatten](https://imagemagick.org/command-line-options/#flatten)”图层叠加运算符(参见图层 Flatten),你可以把这些图像全部叠放在彼此之上,从而恢复原始图像。 |
magick tiles_[0-3].gif -background white -mosaic tiles_mosaic.gif
![[IM Output]](../static/img/crop/tiles_mosaic.gif)
然而如你所见,图像的虚拟画布已被“[-mosaic](https://imagemagick.org/command-line-options/#mosaic)”用背景色填满。另一种做法是使用“[-layers](https://imagemagick.org/command-line-options/#layers) merge”(参见图层 Merge),它会把多张图层图像合并为一张新的图层图像,其大小恰好足以容纳所有给定的图像。也就是说,虚拟画布不会被填满,而“[-mosaic](https://imagemagick.org/command-line-options/#mosaic)”或“[-flatten](https://imagemagick.org/command-line-options/#flatten)”图层叠加方法则会填满。 |
magick tiles_[0-3].gif -background none -layers merge tiles_layered.gif
magick identify tiles_layered.gif
[![\[IM Text\]](../static/img/crop/tiles_layered_ident.txt.gif)](../static/img/crop/tiles_layered_ident.txt)
如果你已用“[+repage](https://imagemagick.org/command-line-options/#repage)”重置了画布与偏移信息,那么这些图像就不再包含它们被裁剪时的偏移,也不再包含源图像的原始尺寸。在这种情况下,你可以使用“magick montage”的特殊“concatenation”模式把所有图像重新拼接到一起。你需要告诉 montage 从原始图像中提取了多少行或多少列图像。
magick rose: -crop 20x20 +repage +adjoin rose_tiles_%02d.gif
montage -mode concatenate -tile 4x rose_tiles_*.gif rose_rejoined.gif
请注意,各个图像的名称是从“rose_tiles_00.gif”到“rose_tiles_11.gif”,它们只是这些瓦片在内存中的序号。这并不太理想,因为这些文件名没有给出每张瓦片实际所属位置的简便提示,也没有给出每行每列的瓦片总数。从 IM v6.4.8-4 起,你也可以使用特殊的文件名百分号转义在输出文件名中生成并包含特殊标签。将其与FX 百分号转义结合使用,你可以为每张图像计算出不同的“瓦片位置”。例如……
magick rose: -crop 20x20 \
-set filename:tile "%[fx:page.x/20+1]_%[fx:page.y/20+1]" \
+repage +adjoin "rose_tile_%[filename:tile].gif"
将生成从“rose_tile_1_1.gif”到“rose_tile_4_3.gif”的瓦片图像文件名,这是一种好得多的文件命名方案。颇为巧妙,但确实有效。遗憾的是,你无法格式化百分号转义所生成的数字,比如用零填充或指定确切的浮点位数。至少目前还不行。
居中平铺裁剪
在一次IM 论坛讨论中,有人请求把平铺裁剪居中,以便将“余料图像”均匀地分布到边缘四周。这样做我们就能把完整的瓦片放在图像中央,从而最大化它们的效果。当然,你最终也会得到更多不完整的边缘瓦片。解决方案是将输入图像居中放置在一个虚拟画布上,该画布是所需瓦片尺寸的某个倍数。例如,要把“rose:”图像(尺寸为 70x46 像素)在图像中央(被余料瓦片包围)平铺裁剪成尽可能多的 30x20 完整瓦片,你可以这样做。
-
首先通过将图像尺寸相除来计算你能从图像中得到的完整瓦片数量……
70x46 / 30x20 => 2x2 个完整瓦片 + 余料 -
现在再加 2 行 2 列以容纳余料图像(如有需要)
2x2 + 2x2 => 4x4 张瓦片图像 -
用瓦片尺寸乘以它,得到虚拟画布尺寸。
30x20 * 4x4 => 120x80 画布尺寸 -
减去原始图像尺寸并除以二,得到居中偏移。
( 120x80 - 70x46 ) / 2 => +25+17
所以虚拟画布与居中偏移为 120x80+25+17。这里我们用上面的计算来执行一次居中平铺裁剪……
magick rose: -repage 120x80+25+17 -crop 30x20 +repage rose_30x20_%02d.gif
如果你想保留瓦片的原始偏移位置,但移除居中偏移,你可以用“-repage -25-17\!”做一次相对偏移调整(替换上面的“[+repage](https://imagemagick.org/command-line-options/#repage)”)。如果你没有给瓦片数量额外加上两列两行,从而产生了一个负偏移,你就能有效地忽略余料边缘瓦片,只输出图像中存在的完整且完好的瓦片。
magick rose: -repage 60x40-5-3 -crop 30x20 +repage rose_ctiles_%d.gif
基本上,由于余料现在处于所计算的虚拟画布“之外”,“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符不知道它们曾经存在,因而会忽略它们。同样,将上面的“[+repage](https://imagemagick.org/command-line-options/#repage)”替换为使用取负偏移值“-repage +5+3\!”的相对偏移调整,将恢复瓦片被裁剪时的原始偏移位置。居中平铺裁剪并忽略余料的另一种做法,是直接用一个合适的裁剪替换虚拟画布设置。
magick rose: -gravity center -crop 60x40+0+0 +gravity +repage \
-crop 30x20 +repage rose_ctiles2_%d.gif
上面的做法更容易理解,但也稍慢一些,因为你现在执行了两次裁剪。不过需要的计算更少。但如果你想恢复瓦片的原始偏移,你仍然需要计算所需的相对偏移,在这种情况下,你不妨用前面那种更快的方法、借助图像的虚拟画布来完成任务。
条带裁剪,裁出行与列
在 IM 6.1.1 版中,“[-crop](https://imagemagick.org/command-line-options/#crop)”得到了增强:如果某个尺寸参数缺失或被设为零,那么该缺失的尺寸参数会被设为图像画布/page 的尺寸。在大多数情况下,这足以覆盖位于画布上的图像,前提是相关的偏移也被设为零。这个小改动让你能够轻松地从图像中裁出单独的一行或一列,而无需用诸如“999999”这样的庞大数字来覆盖图像尺寸。例如,这里我们从“page 化”的 rose 图像中提取一行与一列。
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -crop 20x0+30+0 strip_column.gif
magick paged.gif -crop 0x20+0+30 strip_row.gif
magick identify paged.gif strip_column.gif strip_row.gif
[![\[IM Text\]](../static/img/crop/strip_ident.txt.gif)](../static/img/crop/strip_ident.txt)
如果你同时移除两个偏移以及一个尺寸参数,就可以把图像分成一系列条带或列,而不是瓦片。
magick rose: -crop 40x30+10+10 crop.gif
magick crop.gif -quiet -crop 20x strips_%d.gif
magick identify crop.gif strips_?.gif
[![\[IM Text\]](../static/img/crop/strips_ident.txt.gif)](../static/img/crop/strips_ident.txt)
请注意,平铺裁剪(无论是条带式还是其他方式)都是横跨图像的整个 page 画布进行的,因此它对齐到该画布,而_不_仅仅对齐到实际图像。这就是为什么上面示例中所生成的第一张与最后一张实际图像只有 10 像素宽。当然,如果某张特定瓦片(在此例中是“列”)脱靶了虚拟画布上的实际图像(例如上面最后一张图像),那么就会生成一张裁剪脱靶图像。IM 通常会发出的警告被一个“[-quiet](https://imagemagick.org/command-line-options/#quiet)”设置抑制了。除非你预期会发生此类事件并已为此做好准备(例如在脚本中),否则不建议这样做。 | _一张图像有可能被定位成它甚至不出现在自己的 page 或虚拟画布上,或者大到 page 画布只能容纳图像的一个小窗口或一部分。
在这种罕见情况下,不带任何尺寸参数的条带裁剪会把图像的细分搞错,分别产生脱靶图像,或只包含虚拟画布范围内部分的更小瓦片。
然而“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符不会被修复来处理这些罕见的特殊情况,因为那样做会妨碍它在其他情况下的使用,例如下文所举的那些示例。
如果这对你是个问题,请在裁剪之前先用“[+repage](https://imagemagick.org/command-line-options/#repage)”移除虚拟画布,以净化图像的 page 偏移,然后再尝试生成瓦片图像。_
---|---
作为将图像分割成单独行的另一种方法,请看特殊脚本“[divide_vert](../static/img/scripts/divide_vert)”。这个程序会让你按纯单色的水平“间隙”来分割图像。例如,给定一张简单文本的图像,它会把图像分割成“行”与“间隙”交替的多张图像。一个简单的选项可让你移除那些间隙。
象限,围绕单个点切割
当任意裁剪尺寸数字缺失时,它们会被替换为你正在裁剪的图像的画布尺寸。在大多数情况下,这应当会使图像在该维度上的整体都成为裁剪结果的一部分。审慎地使用这些参数,这便提供了将图像围绕某个特定点裁剪成四份的能力(该特定像素会被放置为左下象限图像的右上像素)。要做到这一点,你无需知道图像有多大。例如,这里我把图像围绕点 30,40 裁剪成四个象限
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -crop 30x40+0+0 quadrant_tl.gif
magick paged.gif -crop 0x40+30+0 quadrant_tr.gif
magick paged.gif -crop 30x0+0+40 quadrant_bl.gif
magick paged.gif -crop +30+40 quadrant_br.gif
当然,如果你围绕裁剪的那个点脱靶了实际图像,那么所得到的象限图像中会有两张甚至三张是特殊的裁剪脱靶错误图像。
使用负偏移,移除底部或左侧边缘
没有任何理由说你不能在“[-crop](https://imagemagick.org/command-line-options/#crop)”中使用负偏移。事实上,它有时能带来非常确切的好处。例如,让我们取我们的 page 化 rose 图像,并用越来越大的负偏移逐步裁剪它。我们不会给“[-crop](https://imagemagick.org/command-line-options/#crop)”参数提供图像尺寸,因此它会默认采用图像的画布尺寸。
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -crop -10-10 neg_offset_1.gif
magick paged.gif -crop -20-20 neg_offset_2.gif
magick paged.gif -crop -30-30 neg_offset_3.gif
magick paged.gif -crop -40-40 neg_offset_4.gif
magick paged.gif -crop -50-50 neg_offset_5.gif
如你所见,将偏移稳步减小到更大的负值,会逐渐导致底部与右侧边缘被“砍掉”,最后一个示例几乎脱靶了实际图像。如果我们再往前一步,就会生成一张脱靶图像。这有点像使用“[-chop](https://imagemagick.org/command-line-options/#chop)”运算符,但没有“[-gravity](https://imagemagick.org/command-line-options/#gravity)”设置。参见Chop,移除边缘。当然,由于使用了“[-crop](https://imagemagick.org/command-line-options/#crop)”,你可能需要使用“[+repage](https://imagemagick.org/command-line-options/#repage)”运算符来调整画布/page 信息,而“[-chop](https://imagemagick.org/command-line-options/#chop)”会自动执行这样的调整。这就是生活。
裁剪成大致等尺寸的分块
平铺裁剪最大的问题在于,你只能定义每张瓦片的最终尺寸。当图像尺寸恰好是所需瓦片尺寸的整数倍时,这工作得很好,但正如你所见,如果情况并非如此,你最终会在右侧与底部边缘得到“偏短”的瓦片。例如,让我们再次分割内置的 rose 图像,但试着把它分成 3x3 的瓦片。原始图像为 70x46 像素,因此除以 3 使每张瓦片为 23x15 像素……
magick rose: -crop 23x15 +repage +adjoin rose_23x15_%02d.gif
好吧,如你所见,这并未奏效,因为 rose 图像无法恰好被分成 3 张等尺寸的瓦片。在这种情况下,你最终会得到一张“偏短”1 像素的瓦片。即便你把瓦片尺寸扩大到 24x16 像素,你仍会得到一张比其他瓦片“短”2 像素的瓦片。随着所需瓦片数量增大,这种情况会变得更糟。例如,试着把长度 100 细分成 30 张瓦片。这是不可能的。你要么用长度 3 得到 34 张瓦片,要么用 4 得到 25 张瓦片。要恰好得到 30 张等尺寸的瓦片是不可能的!从 IM v6.5.8-9 起,你现在可以为“[-crop](https://imagemagick.org/command-line-options/#crop)”参数添加特殊的“@”标志。这个标志告诉“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符尽其所能地把图像等分成给定的_瓦片数量_。例如……
magick rose: -crop 3x3@ +repage +adjoin rose_3x3@_%d.gif
结果是图像被分成了尺寸略有不同的瓦片。然而瓦片尺寸至多相差 1 像素!你可以核对一下!作为额外功能,你还可以细分图像,使每张瓦片“重叠”其相邻瓦片。你不仅要使用一个“@”标志,还要指定你想要的重叠像素数。例如,让我们把 rose 分成四份,但带有 20 像素的重叠。
magick rose: -crop 2x2+20+20@ +repage +adjoin rose_2x2+20+20@_%d.gif
同样,所有这些片块至多只相差一像素!不过在此例中,所得图像尺寸相同,因为 rose 可以被 2 整除。然而,若重叠量或图像尺寸为奇数,情况就不会如此。在那种情况下,较大的元素会沿着顶部与左侧边缘排列。然而当有三张瓦片时,较大(或较小)的元素会被放在中间!你甚至可以使用负重叠,以在瓦片之间“跳过”恰好那么多像素!至于你究竟该如何施加该运算符,取决于你想要“重叠”或“跳过”的具体是哪些像素。而这又取决于图像的“边缘”特征(见下文分离间隔排列的平铺图像)。与“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符的任何用法一样,建议你使用“[+repage](https://imagemagick.org/command-line-options/#repage)”来移除“page”偏移(如果不想要它的话)。但被裁剪图像的偏移信息可能非常有用,这正是它被保留的原因。例如你可以用它来命名输出文件,或弄清楚 IM 所计算出的瓦片的尺寸与位置。请注意,等尺寸平铺裁剪是“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符在确定图像哪一部分被裁剪时唯一会忽略图像实际虚拟画布的情形。也就是说,平铺裁剪的计算基于真实图像尺寸而非虚拟画布尺寸。即便如此,最终的瓦片偏移仍将相对于原始虚拟画布。这个裁剪选项也可作为Shave 运算符对“page 化”图像的替代方案。 |
在 IM v6.6.1-0 版之前,带虚拟画布偏移的图像的等尺寸平铺裁剪是有缺陷的。 |
|---|---|
分离间隔排列的平铺图像
你常常会有一张图像,其中含有固定尺寸的瓦片,它们被固定大小的空间分隔开。新的“@”标志裁剪运算符能让你更轻松地裁出这些瓦片,无论是包含还是跳过周围的空间。然而主要的问题在于,尽管“瓦片”图像四周有固定大小的空间,边缘四周的空间量通常却并不那么固定。这就为一组“间隔”图像产生了三种基本的边缘特征样式,每种类型都需要稍有不同地处理。 Montage 化瓦片 这里,原始图像在被拼接到一起之前只是被简单地加上了固定尺寸的边框。结果是你在瓦片之间总会有偶数个像素的间隔。更重要的是,“边缘间隔”恰好是瓦片之间所放间隔的一半。这实际上正是“[montage](montage.html)”为平铺“单元格”留出间隔的方式,下面所示的示例图像就是用这个命令生成的。由于这些图像只是简单地平铺到一起,你可以使用普通的平铺裁剪(如果你知道瓦片尺寸),或使用等尺寸裁剪(如果你知道瓦片数量),来分离子图像与周围的边框。瓦片之间基本上没有重叠,于是可以用一个简单的Shave 运算符从所得瓦片中移除那个边框。
magick montage.gif -crop 5x1@ +repage +adjoin montage_%d.gif
magick montage_?.gif -shave 3x3 montage-3_%d.gif
边缘四周间距相同 这里,子图像不仅以 6 像素“间隔排列”,而且边缘四周也有 6 像素的间距,使其看起来相当整洁美观。这通过使用默认的等尺寸裁剪并配以适当的像素“重叠”量来处理。例如……
magick edged.gif -crop 5x1+6+6@ +repage +adjoin edged+6_%d.gif
请注意运算符如何分离这些图像,使它们保持相同尺寸,但带有 6 像素的重叠。这正是它被设计来做的。通过使用负偏移,你告诉 IM 重叠区域(间隔部分)不应包含在最终结果中。
magick edged.gif -crop 5x1-6-6@ +repage +adjoin edged-6_%d.gif
如果我再进一步、减去更多像素,我甚至可以从上面的数字中 trim 掉一些白色边框。
magick edged.gif -crop 5x1-8-8@ +repage +adjoin edged-8_%d.gif
你甚至可以把它用作Shave 运算符的替代方法,只需指定一个 1 瓦片的裁剪……
magick edged+6_0.gif -crop 1x1-6-6@ +repage tile-shave.gif
单纯间隔的瓦片 最简单的间隔排列平铺图像没有边缘间距,或者已从图像中Trim掉了那个边缘间距。然而要处理这种情况,你需要通过同时包含“@”和“!”两个标志来告诉 IM 这一特殊情况。
magick spaced.gif -crop 5x1+6+6@\! +repage +adjoin spaced+6_%d.gif
请注意,此细分边缘上的图像比中间的图像略短。这就是为什么这种特殊“模式”的操作不是默认行为,尽管它实际上比前一类间隔排列瓦片更简单。还要注意,当同时使用“@”和“!”两个标志时,单瓦片裁剪(在此例中是纵向的)没有任何效果,因为瓦片的顶部与底部都是“边缘”,因而没有“边缘空间”可移除。同样,通过为重叠使用负值,你可以告诉 IM 不要把重叠(间隔)区域包含在瓦片裁剪结果中。
magick spaced.gif -crop 5x1-6-6@\! +repage +adjoin spaced-6_%d.gif
| “!”字符对某些 UNIX shell(如“csh”)具有特殊意义,因此必须用反斜杠转义,即便放在引号内也是如此。
---|---
有了这些公式,你现在应当能够对构成网格的图像进行平铺裁剪了,即便这些图像有重叠或间隔排列。即使你手头的具体问题并不恰好落入上述某一情形,你也应当能够适当地添加或移除边缘像素,使图像落入上述间隔排列图像的某一类别中。
添加/移除图像边缘
Border,在图像四周添加空间
你常常只是想在图像边缘四周添加一点工作空间,但又不想为此需要或依赖于知道图像的尺寸。如今有许多向图像添加额外空间的方法,除了直接添加空间之外,还包括拼接空白图像或标签、合成“Src”叠加,乃至只是把图像定位在一个更大的画布上。但这些方法通常至少需要对你所处理图像的实际大小有所了解。最简单的图像空间添加形式之一是“[-border](https://imagemagick.org/command-line-options/#border)”操作。所添加空间的颜色是“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”设置。这里是一些直截了当的示例……
magick rose: -bordercolor SkyBlue -border 10x10 border.gif
magick rose: -border 15x6 border_default.gif
magick rose: -bordercolor LimeGreen -border 10x0 border_sides.gif
magick rose: -bordercolor Tomato -border 0x10 border_topbot.gif
magick rose: -alpha set -bordercolor none -border 10 border_none.gif
请注意上面最后一张示例图像。边框颜色被设为透明色“none”,但要让它如预期那样工作,我们需要确保图像实际上含有一个“matte”或“alpha”通道。还要注意,如果竖直与水平的边框尺寸相同,你可以省略边框中的第二个数字,只用一个数字。 |
如上所示,“[-border](https://imagemagick.org/command-line-options/#border)”运算符所用的默认颜色是浅灰色,因为它能很好地匹配 WWW 网页默认的灰色 page 颜色。 |
|---|---|
| 你可以将边框指定为图像尺寸的百分比…… |
magick rose: -border 10%x10% border_percent.jpg
![[IM Output]](../static/img/crop/border_percent.jpg)
内部实际发生的是,“[-border](https://imagemagick.org/command-line-options/#border)”创建一张正确尺寸的新图像,然后把原始源图像叠加到这个新背景之上。这本身就是 ImageMagick 中一个非常有用的操作,用于为透明与半透明图像设置背景。也就是说,看似毫无用处的“-border 0”操作,在 IM 第 6 版中是一个非常有用的操作。例如……
magick star.gif -bordercolor LimeGreen -border 0 star_background.gif
| 当然,还有许多其他方法可以移除 Alpha 透明度。 | 为带透明度的图像添加边框时,默认也会填充图像的透明背景,这一事实在 IM 用户与开发团队之间引发了一些争论。该争论的摘要见Border、Frame 及 BorderColor 的使用。 |
|---|---|
Border 与 Alpha 合成
将图像叠加到 bordercolor 画布上的过程由“[-compose](https://imagemagick.org/command-line-options/#compose)”设置控制,它默认设为“[Over](compose.html#over)” alpha 合成。如果它被设为其他某种设置,“[-border](https://imagemagick.org/command-line-options/#border)”操作可能会产生意想不到的结果。例如,这里是把“[-compose](https://imagemagick.org/command-line-options/#compose)”与“[-border](https://imagemagick.org/command-line-options/#border)”图像运算符一起用于一张含有透明区域的图像时,一些更有趣的用法。
magick star.gif -bordercolor LimeGreen \
-compose {_operation_} -border 5 {_result_}
在使用“Over”与“Copy”之间做选择,本质上决定了你是否想保留图像中的透明度。例如,这里是同一张带透明度的“star”图像,但这次添加边框时没有破坏图像的透明度。 |
magick star.gif -bordercolor LimeGreen -compose Copy \
-border 5 star_border_copy.gif
![[IM Output]](../static/img/crop/star_border_copy.gif)
“[Src](compose.html#src)”合成会给图像添加一个透明边框(如果它有 alpha 通道),而不论当前的“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”设置如何。基本上,“[-border](https://imagemagick.org/command-line-options/#border)”所生成的背景画布被忽略了。“[Dst](compose.html#dst)”看起来可能不太有用,但可用于生成一张与原始图像尺寸相同(或略大)的画布。原始图像仅用于确定最终画布的尺寸。更多示例请参见尺寸取自现有图像的画布。有关各种“[-compose](https://imagemagick.org/command-line-options/#compose)”方法的更多信息,请参见Alpha 合成示例。
Border 与虚拟画布
当“[-border](https://imagemagick.org/command-line-options/#border)”被施加到一张含有虚拟画布的图像上时,它仍会围绕该虚拟画布上的实际图像添加边框,而_不_是围绕整个画布。
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -border 5x5 paged_border.gif
请注意,虚拟画布的尺寸也增加了边框厚度的两倍,以容纳所添加的边框。这当然意味着你不能直接简单地向典型的 GIF 动画添加边框,除非你确实想标识动画的各个子帧(例如参见脚本动画帧 Montage,它把这作为一个选项来给叠加图像“加框”)。如果你想添加边框,你应当先合并(Coalesce)动画,以先移除它可能带有的任何帧优化。
Frame,添加类 3D 边框
“[-frame](https://imagemagick.org/command-line-options/#frame)”运算符与“[-border](https://imagemagick.org/command-line-options/#border)”非常相似,如果你看下面生成的第一张示例图像,你会发现它产生的结果完全相同,只是它用的是“[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)”而非“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”。请注意,“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”在生成加框图像时仍会用到,见下文。要正确使用“[-frame](https://imagemagick.org/command-line-options/#frame)”,你需要向命令提供四个参数,而不只是 2 个。额外的参数指定所生成画框“外侧”与“内侧”斜面的宽度。这里是一些用各种设置使用“[-frame](https://imagemagick.org/command-line-options/#frame)”运算符的示例。
magick rose: -frame 10x10 frame.gif
magick rose: -frame 15x6+2+2 frame_wierd.gif
magick rose: -mattecolor SkyBlue -frame 6x6+2+2 frame_blue.gif
magick rose: -mattecolor Tomato -frame 10x10+5+5 frame_red.gif
magick rose: -frame 10x10+10+0 frame_rasied.gif
magick rose: -frame 10x10+6+0 frame_rasied_part.gif
magick rose: -frame 10x10+0+6 frame_sunken_part.gif
magick rose: -frame 10x10+0+10 frame_sunken.gif
使用多次 frame 操作还能产生更怪异的加框样式。
magick rose: -frame 10x10+3+3 frame_normal.gif
magick rose: -frame 3x3+3+0 -frame 7x7+3+0 frame_popped.gif
magick rose: -frame 7x7+0+3 -frame 3x3+0+3 frame_pressed.gif
magick rose: -frame 3x3+3+0 -frame 4x4 -frame 3x3+0+3 frame_inverted.gif
| 默认的“[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)”是比“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”默认设置略深的灰色。这也让它能够匹配 WWW 网页默认的灰色(被诸如“mosaic”和“netscape”等早期浏览器所使用)。(见下文)
---|---
| 虽然“[-frame](https://imagemagick.org/command-line-options/#frame)”实际上可能使用“[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)”颜色,但它还会从这个基色再生成另外四种颜色用于绘制画框。也就是说,很可能会有五种相关的颜色被添加到图像中,而不只是一种。
---|---
稍加努力,你甚至可以重现一张类似“magick montage”的加框图像,连同文本标签一起。 |
magick rose: -mattecolor grey -background grey -frame 3x3+0+3 \
-gravity South -splice 0x15 -annotate 0x0 'A Red Rose' \
-frame 6x6+3+0 frame_montage.gif
![[IM Output]](../static/img/crop/frame_montage.gif)
你甚至可以为画框“[-frame](https://imagemagick.org/command-line-options/#frame)”使用半透明的“[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)”,然后“衬入”一个有趣的图案(例如分形等离子画布),以产生更加多彩的画框。 |
magick rose: -alpha set -mattecolor '#CCC6' -frame 10x10+3+4 \
\( -size 100x100 plasma:fractal -normalize -blur 0x1 \) \
-compose DstOver -composite frame_plasma.gif
![[IM Output]](../static/img/crop/frame_plasma.gif)
或者,你可以单独给画框上色(使用特殊的“Dst”合成设置生成),然后在给画框上好色之后再把图片叠入画框。但那确实就变得非常棘手了。有关使用画框的更高级技巧,请参见加框技巧。
Frame 与 Alpha 合成
Frame 与“[-border](https://imagemagick.org/command-line-options/#border)”运算符密切相关。画框不仅用“[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)”绘制,这个运算符还会利用“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”设置来定义画框最初绘制其上的背景。对于没有透明度的图像,“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”将不可见,因为它被图像本身所覆盖。但对于确实含有一些透明区域的图像,背景色就会变得可见。 |
magick star.gif -frame 6x6+2+2 star_framed.gif
![[IM Output]](../static/img/crop/star_framed.gif)
换句话说,“[-frame](https://imagemagick.org/command-line-options/#frame)”的表现就如同你拿起你的图像,把它叠加到一个带纯色背景的相框上。因此,你图像中任何透明的部分都将被“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”所替换,其默认为浅灰色。 | 为带透明度的图像添加画框时,默认也会用 bordercolor 填充图像的透明背景,这一事实在 IM 用户与开发团队之间引发了一些争论。该争论的摘要见Border、Frame 及 BorderColor 的使用。
---|---
如果你想在加框时保留图像的透明度,你有两种解决方案。第一种是使用透明的“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”,例如“none”。 |
magick star.gif -bordercolor none -frame 6x6+2+2 star_framed_none.gif
![[IM Output]](../static/img/crop/star_framed_none.gif)
另一种解决方案,也是更可取的方法,是确保在图像被添加到画框时保留透明像素。这是通过使用一个名为“[Copy](compose.html#copy)”的特殊“[-compose](https://imagemagick.org/command-line-options/#compose)”方法来完成的。 |
magick star.gif -compose Copy -frame 6x6+2+2 star_framed_copy.gif
![[IM Output]](../static/img/crop/star_framed_copy.gif)
| 将“-bordercolor”用作“[-border](https://imagemagick.org/command-line-options/#border)”与“[-frame](https://imagemagick.org/command-line-options/#frame)”二者的背景图像,是在 IM 6.1.4 版中加入的。在此之前,所生成的背景画布由一张黑色画布构成,边框或画框便绘制其上。
这种对黑色的使用对“magick montage”命令尤其糟糕,因为它在内部处理中大量使用了内部的“[-frame](https://imagemagick.org/command-line-options/#frame)”功能。(参见Montage 背景与透明度处理)
---|---
如你所见,“[-frame](https://imagemagick.org/command-line-options/#frame)”运算符与“[-border](https://imagemagick.org/command-line-options/#border)”一样,也使用“[-compose](https://imagemagick.org/command-line-options/#compose)”设置来定义源图像如何叠加到背景画框上。
magick star.gif -bordercolor LimeGreen \
-compose {_operation_} -frame 6x6+2+2 {_result_}
如果你还想在“magick montage”画框中使用“[-bordercolor](https://imagemagick.org/command-line-options/#bordercolor)”设置,那么使用“[Copy](compose.html#copy)”的“[-compose](https://imagemagick.org/command-line-options/#compose)”设置就变得非常重要。详情请参见Montage 背景与透明度处理。
Frame 与虚拟画布
与Border 与虚拟画布一样,frame 也是围绕该虚拟画布上的实际图像施加的,而_不_是围绕整个画布。
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -frame 5x5+2+2 paged_framed.gif
请注意,虚拟画布的尺寸也增加了边框厚度的两倍,以容纳所添加的画框。这当然意味着你不能直接简单地向典型的 GIF 动画添加画框,除非你确实想标识动画的各个子帧(例如参见动画帧 Montage)。如果你想添加边框,你应当先合并(Coalesce)动画,以先移除它可能带有的任何帧优化。
Shave,从图像移除边缘
“[-border](https://imagemagick.org/command-line-options/#border)”或“[-frame](https://imagemagick.org/command-line-options/#frame)”运算符的逆操作是“[-shave](https://imagemagick.org/command-line-options/#shave)”,若给定相同的参数,它会移除这些命令所添加的空间。
magick border.gif -shave 10x10 shave.gif
magick border.gif -shave 10x0 shave_sides.gif
magick border.gif -shave 0x20 shave_topbot.gif
关于这三个运算符需要记住的要点是,它们在图像_相对_的两侧添加和移除空间,而不只是一侧或相邻的两侧。如果你只想移除图像的一条边缘,那么你需要改用“[-chop](https://imagemagick.org/command-line-options/#chop)”运算符。(见下文Chop 示例)。与之前一样,“[-border](https://imagemagick.org/command-line-options/#border)”“[-frame](https://imagemagick.org/command-line-options/#frame)”和“[-shave](https://imagemagick.org/command-line-options/#shave)”这些运算符只影响虚拟画布上的真实图像,而不影响虚拟画布本身。
magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -border 5x5 paged_border.gif
magick paged_border.gif -frame 5x5+2+2 paged_frame.gif
magick paged_frame.gif -shave 10x10 paged_shave.gif
使用 shave 的一种替代方法是使用新的等尺寸平铺裁剪运算符。这个运算符的优点是,不像“[-shave](https://imagemagick.org/command-line-options/#shave)”,它不会修改所得图像的画布尺寸。
magick paged_frame.gif -crop 1x1-10-10@ paged_tile_shave.gif
| 在 IM v6.6.1-0 版之前,带画布偏移的图像(例如上面的情况)的等尺寸平铺裁剪是有缺陷的。
---|---
Extent,直接调整图像尺寸
经过一些讨论,IM 6.2.4 版加入了一个直接调整图像最终尺寸的运算符。即“[-extent](https://imagemagick.org/command-line-options/#extent)”运算符。如果图像尺寸增大,空间会被添加到图像的右侧或底部边缘。如果尺寸减小,图像数据会被直接丢弃或裁剪以适应新的图像尺寸。在这两种情况下,图像的左上区域很可能保持不受影响。
magick rose: -background skyblue -extent 100x60 extent_enlarge.gif
magick rose: -background skyblue -extent 40x40 extent_shrink.gif
magick rose: -background skyblue -extent 100x40 extent_wider.gif
magick rose: -background skyblue -extent 40x60 extent_taller.gif
如你所见,它会用“[-background](https://imagemagick.org/command-line-options/#background)”颜色填充图像新增的任何区域。 |
在 IM v6.3.2 版之前,“[-extent](https://imagemagick.org/command-line-options/#extent)”只是把任何新增区域的内存清零,即纯黑。它不会用“[-background](https://imagemagick.org/command-line-options/#background)”颜色填充这些区域。 |
|---|---|
此外,在 IM v6.3.2 之后,“[-extent](https://imagemagick.org/command-line-options/#extent)”会使用“[-gravity](https://imagemagick.org/command-line-options/#gravity)”来定义所添加/移除的区域相对于原始图像的位置。 |
magick rose: -gravity north -extent 100x80 extent_north.gif
magick rose: -gravity south -extent 100x80 extent_south.gif
magick rose: -gravity east -extent 100x80 extent_east.gif
magick rose: -gravity west -extent 100x80 extent_west.gif
magick rose: -gravity center -extent 100x80 extent_center.gif
magick rose: -gravity center -extent 40x80 extent_center2.gif
上面最后一个示例表明,extent 也能做居中裁剪,但无需“[-repage](https://imagemagick.org/command-line-options/#repage)”,尽管它确实会用当前的“[-background](https://imagemagick.org/command-line-options/#background)”颜色把图像“flatten”。你甚至可以使用偏移,这基本上意味着Extent 运算符就是一次直截了当的、带背景补白填充的裁剪,无论位置如何。 |
magick rose: -background skyblue -extent 100x100-15-25 extent.png
![[IM Output]](../static/img/crop/extent.png)
这种既能裁剪又能扩展图像、且依从 gravity 的能力,使该运算符非常适合用于对图像进行补白或裁剪,使其适应特定尺寸的区域,例如参见补白/填充缩略图以适配。 请注意,“[-extent](https://imagemagick.org/command-line-options/#extent)”的工作方式与Border和Frame运算符所用的相同“叠加”技术相同。因此,默认情况下,将它用于含有透明度的图像,会用当前的“[-background](https://imagemagick.org/command-line-options/#background)”颜色替换透明度。 |
magick star.gif -background LimeGreen -extent 80x80-10-10 star_extent.gif
![[IM Output]](../static/img/crop/star_extent.gif)
同样,对此的解决方案是要么设置一个合适的“[-compose](https://imagemagick.org/command-line-options/#compose)”方法,要么把“[-background](https://imagemagick.org/command-line-options/#background)”颜色设为“None”。
添加/移除行、列与边缘
Splice,添加行、列与边缘
“[-splice](https://imagemagick.org/command-line-options/#splice)”运算符是 IM 第 6 版的新增功能,参见Splice,创建新图像运算符的示例。它基本上提供了把一行、一列空间添加到图像中间或某一边缘这一急需的能力。所插入空间的颜色来自“[-background](https://imagemagick.org/command-line-options/#background)”颜色设置。
magick rose: -background blue -splice 20x10+40+30 splice.gif
magick rose: -background blue -splice 20x0+40+0 splice_column.gif
magick rose: -background blue -splice 0x10+0+30 splice_row.gif
magick rose: -background blue -splice 20x10 splice_topleft.gif
| 如果未设置背景色,IM 会尝试从图像本身确定这个值。这意味着对于某些图像它可能是白色(通常的默认值),对于另一些图像它可能是黑色,而对于 GIF 格式,它可能是该图像保存时所设的任何背景色。 这基本上意味着,如果你不设置“[-background](https://imagemagick.org/command-line-options/#background)”颜色,它的默认值取决于图像,你可能会得到几乎任何颜色。 在使用任何会用到背景色的运算符之前,始终先设置“[-background](https://imagemagick.org/command-line-options/#background)”。
---|---
现在,虽然向图像添加一行一列很好,但“[-splice](https://imagemagick.org/command-line-options/#splice)”运算符最适合用来只向图像的一条边缘添加空间。具体是哪条边缘,由“[-gravity](https://imagemagick.org/command-line-options/#gravity)”选项与 splice geometry 设置共同决定。
magick rose: -background blue -splice 0x10 splice_top.gif
magick rose: -gravity south \
-background blue -splice 0x10 splice_bottom.gif
magick rose: -background blue -splice 20x0 splice_left.gif
magick rose: -gravity east \
-background blue -splice 20x0 splice_right.gif
magick rose: -gravity southeast \
-background blue -splice 20x10 splice_botright.gif
splice 最常见的用途之一是添加空间用于绘制标签。(参见为图像加标签) |
magick rose: -gravity South -background LimeGreen -splice 0x15 \
-annotate 0x0 'Rose' splice_label.gif
Chop,移除行、列与边缘
“[-splice](https://imagemagick.org/command-line-options/#splice)”天然的逆操作是更为古老的“[-chop](https://imagemagick.org/command-line-options/#chop)”运算符。给定与“[-splice](https://imagemagick.org/command-line-options/#splice)”相同的参数以及相同的“[-gravity](https://imagemagick.org/command-line-options/#gravity)”设置,“[-chop](https://imagemagick.org/command-line-options/#chop)”会把图像恢复为其原始形态。
magick splice.gif -chop 20x10+40+30 splice_chop.gif
magick splice_chop.gif -chop 20x10+30+20 chop.gif
magick chop.gif -background grey \
-splice 20x10+30+20 chop_splice.gif
我继续处理了最后一个示例,以展示你如何颠倒“[-splice](https://imagemagick.org/command-line-options/#splice)”与“[-chop](https://imagemagick.org/command-line-options/#chop)”的顺序,从而在不使用绘制或叠加的情况下,从图像中间“清出”一行或一列(或两者)。Chop 更常用于从图像中切去单独的一条边缘,使用 gravity 来选择那条边缘。例如……
magick frame_red.gif -chop 0x10 chop_top.gif
magick frame_red.gif -chop 10x0 chop_left.gif
magick frame_red.gif -gravity East -chop 10x0 chop_right.gif
magick frame_red.gif -gravity South -chop 0x10 chop_bottom.gif
作为用“[-chop](https://imagemagick.org/command-line-options/#chop)”移除单条边缘的替代方案,你实际上可以改用更通用的“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符。这不需要使用“[-gravity](https://imagemagick.org/command-line-options/#gravity)”来取得底部或右侧边缘,但确实需要你在之后对图像的画布执行“[+repage](https://imagemagick.org/command-line-options/#repage)”。
magick frame_red.gif -crop +0+10 +repage crop_edge_top.gif
magick frame_red.gif -crop +10+0 +repage crop_edge_left.gif
magick frame_red.gif -crop -10+0 +repage crop_edge_right.gif
magick frame_red.gif -crop +0-10 +repage crop_edge_bottom.gif
这依赖于这样一个事实:如果未给“[-crop](https://imagemagick.org/command-line-options/#crop)”指定要移除的图像区域,它会默认采用图像画布的尺寸(不是实际图像,而是图像的虚拟画布)。这意味着你(对于简单图像)可以仅通过偏移被切割的裁剪区域来移除图像边缘。这种用“[-crop](https://imagemagick.org/command-line-options/#crop)”来“砍掉”图像边缘的方法,是由 Don Sheythe 发现并发表的,经过一些讨论后被认定为 IM 的一项“特性”,因而收录于此。
高级裁剪技巧
按给定纵横比裁剪
你可以把图像裁剪成符合特定纵横比,但这很棘手,且要用到一些自行动手的数学技巧。例如,你可以编写一个脚本来做这些计算,然后再做裁剪。或者在 IM v6 中,你可以用扭曲视口来做计算,在一次空操作扭曲期间提取图像所需的部分,如居中正方形裁剪中所述。然而在 ImageMagick 第 7 版中,你现在可以直接在诸如“[-crop](https://imagemagick.org/command-line-options/#crop)”和“[-extent](https://imagemagick.org/command-line-options/#extent)”之类的命令中进行数学计算,从而绕过滥用“[-distort](https://imagemagick.org/command-line-options/#distort)”的需要。这在 IM 开发者论坛裁剪到纵横比中有详细讨论。
Trim,“自动裁剪”运算符
“[-trim](https://imagemagick.org/command-line-options/#trim)”运算符与上文讨论的极为多才多艺的“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符关系非常密切。然而,这个运算符不需要提供参数,而是试图移除图像中颜色或透明度没有变化的任何边框或边缘。换句话说,它移除图像四周“无聊”的部分。 |
请注意,在 ImageMagick 第 5 版及之前,自动裁剪操作是通过向“[-crop](https://imagemagick.org/command-line-options/#crop)”运算符传入“0x0”参数实现的。现已不再如此,因为裁剪中的“零”尺寸参数现在表示“无限”或“到图像尺寸的极限”。 因此,向 crop 传入“0x0”参数现在实际上意味着把图像裁剪成与原始图像画布同样大小的瓦片。换句话说,在 IM v6 中,结果将与原始图像相同,即一次“空操作”。 |
|---|---|
| 例如,这里我们取 IM 徽标,对它调整尺寸,并“trim”或“自动裁剪”掉徽标四周所有多余的空间。 |
magick logo: -resize 30% -trim trim.gif
从上面有两件事值得注意。第一,和“[-crop](https://imagemagick.org/command-line-options/#crop)”一样,“[-trim](https://imagemagick.org/command-line-options/#trim)”会保留图像的画布尺寸。这意味着可以提取出 trim 的数值参数,以便进行进一步处理或调整图像处理(参见Trim“噪点”图像中这样做的一个示例)。 ![[IM Output]](../static/img/crop/trim.gif)
这里我们 trim 图像,但只列出图像被 trim 了哪一部分的结果,而不是实际被 trim 的图像。
magick logo: -resize 30% -trim info:-
不过,如果你不在乎这些信息,只需通过用“[+repage](https://imagemagick.org/command-line-options/#repage)”运算符重置图像的 page 信息,或保存为不保存画布信息的格式(例如 JPEG 格式),把它丢掉即可。这里我们两者都做,以明确表示我们正在丢弃画布信息。 |
magick logo: -resize 30% -trim +repage trim_repage.jpg
![[IM Output]](../static/img/crop/trim_repage.jpg)
第二件值得注意的事情是,trim 实际上并没有一直 trim 到最终图像的最边缘。这在徽标图像的右下角尤为明显,在那里我们能看到脚及其阴影与被 trim 边缘之间有一道明显的缝隙。在这个角落,这里的颜色在数值上变得与图像的背景色不同了。因此,即便我们看不出图像有任何真实变化,“[-trim](https://imagemagick.org/command-line-options/#trim)”运算符却看到了一处细微的颜色变化,所以它没有像我们预期的那样 trim 得那么贴近图像。如果图像全是同一种颜色,那么“[-trim](https://imagemagick.org/command-line-options/#trim)”会把图像 trim 到一张最小化的单像素透明脱靶图像。这是合乎逻辑的,并能防止图像若保持原样可能引发的更严重问题。
按指定颜色 Trim
“[-trim](https://imagemagick.org/command-line-options/#trim)”最令人忧虑的问题之一,尤其是在自动化图像处理脚本中,是 trim 可能有点不可预测。例如,它不会把自己限制在某一种特定颜色,甚至不限于一种颜色。因此你很容易 trim 掉比你预期更多的东西。例如,让我们对一张由条纹颜色构成的简单图像做一次简单的 trim。
magick -size 32x32 xc:red xc:green xc:blue +append stripes.gif
magick stripes.gif -trim +repage stripes_trimmed.gif
如你所见,“[-trim](https://imagemagick.org/command-line-options/#trim)”trim 掉的不只是一种颜色,而是两种颜色!在自动脚本中,这可能非常糟糕,并产生意想不到的结果。如果你知道想从图像中 trim 掉什么颜色,那么更好的办法是向图像添加一道该颜色的一像素宽“[-border](https://imagemagick.org/command-line-options/#border)”。在此例中,让我们取“red”。
magick stripes.gif -bordercolor red -border 1x1 \
-trim +repage stripes_trim_red.gif
当然,像这样使用“[-border](https://imagemagick.org/command-line-options/#border)”也会改变“[-trim](https://imagemagick.org/command-line-options/#trim)”煞费苦心想要保留的画布偏移。因此,如果你在不移除虚拟画布信息的情况下查看结果,你会看到图像被移位了。 ![]() |
![]() |
|---|---|
magick stripes.gif -bordercolor red -border 1x1 -trim \
stripes_trim_red_shifted.gif
![[IM Output]](../static/img/crop/stripes_trim_red_shifted.gif)
那么让我们试着在 trim 指定颜色时纠正虚拟画布尺寸(减去 _边框宽度_ x2)与偏移(减去 _边框宽度_)。 |
magick stripes.gif -bordercolor red -border 1x1 -trim \
-set page '%[fx:page.width-2]x%[fx:page.height-2]+%[fx:page.x-1]+%[fx:page.y-1]' \
stripes_trim_red_fix.gif
![[IM Output]](../static/img/crop/stripes_trim_red_fix.gif)
请注意,我正在恢复原始图像的画布尺寸与偏移,它们在上面被Border 运算符放大并移位了。“[-trim](https://imagemagick.org/command-line-options/#trim)”操作本身正确地保留了图像位置。如你所见,这是一种相当笨拙的调整。或者,如果你不在乎画布尺寸(在分层图像中很典型),你可以使用更简单得多的相对 Repage,仅调整图像在放大画布上的位置。 |
magick stripes.gif -bordercolor red -border 1x1 -trim \
-repage -1-1\! stripes_trim_red_fix2.gif
仅 Trim 图像的一侧
如你在上面所见,“[-trim](https://imagemagick.org/command-line-options/#trim)”会尽可能地 trim 多个侧面。甚至会去到从不同侧面移除两种不同颜色的地步(或者如果安排得非常巧妙,本可移除四种颜色)。当你想把 trim 限制到只有一侧时,这就使事情更困难一些。为了保证我们只 trim 一侧,我们需要在其他侧添加一些彩色条纹来保护另外三侧。这里是只 trim 我们之前创建的“border”图像“左”侧或“西”侧的逐步过程。我用了比必要厚得多的条纹,以便你能在此示例中更清楚地看到它们。通常单个像素的宽度就够了。
magick border.gif -gravity East \
-background white -splice 5x0 \
-background black -splice 5x0 trim_protect.gif
magick trim_protect.gif -trim +repage trim_oneside.gif
magick trim_oneside.gif -gravity East -chop 5x0 trim_west.gif
请注意,我添加了两种不同颜色的条纹!这样一来,如果其中一种颜色恰好与图像四周已有的边框颜色匹配,另一种颜色仍会继续起作用来保护那三条边缘。此外,也只有其中一种颜色会被 trim,留下一道颜色条纹需要清理。这里是把整个单侧 trim 作为单条命令,不过是 trim 顶部边缘(条纹被添加到底部即“South”边缘)。
![[IM Output]](../static/img/crop/trim_west.gif)
|
magick border.gif -gravity South \
-background white -splice 0x1 -background black -splice 0x1 \
-trim +repage -chop 0x1 trim_north.gif
![[IM Output]](../static/img/crop/trim_north.gif)
这里是只 trim 底部边缘。当然,前一个示例中所用的“[-gravity](https://imagemagick.org/command-line-options/#gravity)”设置并不需要,对于图像该设置默认为“North-West”设置。 |
magick border.gif \
-background white -splice 0x1 -background black -splice 0x1 \
-trim +repage -chop 0x1 trim_south.gif
![[IM Output]](../static/img/crop/trim_south.gif)
当然,与之前的 border 一样,向图像 splice 额外的颜色同样会改变虚拟图像画布尺寸与图层图像的偏移。同样,这可以用我们在前一节展示的相同方法来修正,但这取决于你为了保留那些边缘而把额外的颜色添加到了哪一侧。
使用模糊颜色选择进行 Trim -- 低质量 JPEG 图像
因为 JPEG 是“有损”的,图像中的颜色通常并非单一颜色,而是略有变化的不同颜色的带状区。正因为如此,“[-trim](https://imagemagick.org/command-line-options/#trim)”对 JPEG 或真实世界图像往往会失败。未来:此处放失败示例 因此,你需要告诉 ImageMagick:那些并非完全相同、但相当接近的颜色应被视为相同。添加一个很小的“[-fuzz](https://imagemagick.org/command-line-options/#fuzz)”设置就能做到这一点。
magick image.jpg -fuzz 1% -trim +repage image_fuzzy_trim.jpg
指定你想让那个 fuzz 相对于哪个具体颜色也是一个非常好的主意。这可以通过使用“[-border](https://imagemagick.org/command-line-options/#border)”运算符专门添加一道该颜色的边框来加上。这道边框当然总会匹配要被 trim 的颜色,因此总会被“[-trim](https://imagemagick.org/command-line-options/#trim)”移除。未来:此处放模糊边框 trim 示例
Trim“噪点”图像 -- 扫描图像
扫描图像面临着类似的问题,扫描仪常常产生由灰尘、污垢、扫描仪的细微差异,或仅仅是读取器拾取的电子噪声所引起的单像素小错误。然而在这种情况下,这些像素错误通常太大,以至于一个小的fuzz factor无法克服,所以需要不同的技术来 trim 这类图像。最简单的解决方案(尽管往往最不实用)是对同一图像进行多次扫描,或在视频静止序列中取多帧,然后对结果取平均以减少干扰。然而这无法移除扫描仪上的灰尘斑点,在只有单张图像或单帧可用时也无济于事,使该方法在多数情况下不切实际。一个实用的解决方案是分两步进行。用图像的一份副本,以某种方式处理它,以淡化单像素错误或扫描仪灰尘,同时增强大块高对比度颜色的效果。然后通过对这份副本使用“[-trim](https://imagemagick.org/command-line-options/#trim)”,并检查它究竟做了什么,你就可以按相同的量对未经修改的原始图像执行“[-crop](https://imagemagick.org/command-line-options/#crop)”。淡化单像素错误的方法有若干种。这些方法包括“[-blur](https://imagemagick.org/command-line-options/#blur)”“[-median](https://imagemagick.org/command-line-options/#median)”,乃至使用基本形态学运算符来移除特定细节,例如文本与细线。这种“blur”方法给出两个主要的控制项:
- “
[-blur](https://imagemagick.org/command-line-options/#blur)”的 sigma 半径,或“[-median](https://imagemagick.org/command-line-options/#mediam)”的卷积半径,它决定你想忽略的灰尘斑点的大小。请注意,这两个值都可以是浮点数,因此你可以对所施加模糊的量进行精细控制。有关模糊的更多信息,请参见模糊图像。 - 第二个控制项是“
[-fuzz](https://imagemagick.org/command-line-options/#fuzz)”颜色因子,它控制“[-trim](https://imagemagick.org/command-line-options/#trim)”运算符所匹配的颜色变化量。也就是说,你想让 trim 贴近所需图像到什么程度。
例如,让我们使用一张较小的“logo:”图像。 |
magick logo: -resize 30% noisy.jpg
在这张小图像中,我们可以把图像中的星星与标题视为我们想让 trim 忽略的噪点。上面的星星大约横跨 5 像素,所以我们想用大约其两倍的值,让 trim 基本上忽略它们。 ![[IM Output]](../static/img/crop/noisy.jpg)
这里是结果。请注意,在这种情况下我们不想要图像,只想要图像中的画布信息。
magick noisy.jpg -virtual-pixel edge -blur 0x15 -fuzz 15% -trim info:
| _你可能需要检查虚拟像素设置,以确保你在模糊时得到正确的“边缘效果”。
或者,你可以在模糊之前向图像添加一道同样背景色的宽边框,并相应地调整偏移结果。这对于从“[-blur](https://imagemagick.org/command-line-options/#blur)”与“[-trim](https://imagemagick.org/command-line-options/#trim)”运算符获得更准确的结果可能更好。_
---|---
从上面的结果,我们可以确定“[-trim](https://imagemagick.org/command-line-options/#trim)”内部使用了一个“89x121+78+23”的“[-crop](https://imagemagick.org/command-line-options/#crop)”参数。这是被 trim 图像的实际尺寸及其在虚拟画布上的偏移,大概也是我们在图像中所寻找的那个主要(单个)对象的位置。然后这就可以用在尚未被模糊的原始图像上。 |
magick noisy.jpg -crop 89x121+78+23 +repage noisy_trimmed.jpg
这里我们就把图像 trim 成只剩巫师了! ![[IM Output]](../static/img/crop/noisy_trimmed.jpg)
这可以用单行完成,稍微借助一些额外的“UNIX shell 脚本”,并对第一条命令的结果做一些格式化。 |
magick noisy.jpg -crop \
`magick noisy.jpg -virtual-pixel edge -blur 0x15 -fuzz 15% \
-trim -format '%wx%h%O' info:` +repage noisy_trimmed_2.jpg
有关用于控制“[info:](files.html#info)”输出的“[-format](https://imagemagick.org/command-line-options/#format)”设置的更多信息,请参见图像属性转义。 ![[IM Output]](../static/img/crop/noisy_trimmed_2.jpg)
| _上面使用了 UNIX 命令行 shell 的“命令替换”特性,用反引号“...”把所生成的“[-crop](https://imagemagick.org/command-line-options/#crop)”参数插入到外层的“magick”命令中。
你可以在Windows 批处理脚本中用一个特殊的 FOR..DO 结构来做这件事。详情请按上面的链接。_
---|---
请注意,虽然巫师的手完全可见,但帽子的尖端却不可见。这是该方法的缺点,它会忽略尖锐的点与精细的细节。但话说回来,那本来就是我们一开始要求它忽略的东西。这个方法可以通过将被 trim 的区域略微扩大一点(在 4 个方向各 10 像素)来改进,用一些FX 转义来做这些数学计算…… |
magick noisy.jpg -crop \
`magick noisy.jpg -virtual-pixel edge -blur 0x15 -fuzz 15% -trim \
-format '%[fx:w+20]x%[fx:h+20]+%[fx:page.x-10]+%[fx:page.y-10]' \
info:` +repage noisy_trimmed_3.jpg
![[IM Output]](../static/img/crop/noisy_trimmed_3.jpg)
如果计算出的边界扩展到超出原始图像,crop 运算符会自动将其限制到图像边界内。在 IMv7 中(使用“magick”命令),你可以在单条命令中全部完成,把计算出的 trim 尺寸保存到一个设置中供以后使用。 |
magick noisy.jpg \
\( +clone -virtual-pixel edge -blur 0x15 -fuzz 15% -trim \
-set option:fuzzy_trim \
'%[fx:w+20]x%[fx:h+20]+%[fx:page.x-10]+%[fx:page.y-10]'\
+delete \) \
-crop %[fuzzy_trim] noisy_trimmed_4.jpg
![[IM Output]](../static/img/crop/noisy_trimmed_4.jpg)
模糊 trim 的其他方法是使用各种形态学方法来移除图像中不想要的部分,然后再 trim,以找到原始图像中所需区域的边界。用户HugoRune需要为扫描目的,把一张图像 trim 到一个对比度差异极大的区域。详情请参见IM 论坛上的讨论。
![[IM Output]](../static/img/crop/rose.gif)
![[IM Output]](../static/img/crop/crop.gif)
![[IM Output]](../static/img/crop/crop_br.gif)
![[IM Output]](../static/img/crop/crop_tl.gif)
![[IM Output]](../static/img/crop/crop_all.gif)
![[IM Output]](../static/img/crop/crop_miss.gif)
![[IM Text]](../static/img/crop/crop_indent.txt.gif)
![[IM Text]](../static/img/crop/crop_error.txt.gif)
![[IM Text]](../static/img/crop/crop_miss_ident.txt.gif)
![[IM Text]](../static/img/crop/crop_miss_data.txt.gif)
![[IM Output]](../static/img/crop/paged.gif)
![[IM Output]](../static/img/crop/crop_page.gif)
![[IM Output]](../static/img/crop/crop_page_tl.gif)
![[IM Output]](../static/img/crop/crop_page_br.gif)
![[IM Output]](../static/img/crop/crop_page_all.gif)
![[IM Output]](../static/img/crop/crop_page_miss.gif)
![[IM Text]](../static/img/crop/crop_page_ident.txt.gif)
![[IM Output]](../static/img/crop/crop_area_br.png)
![[IM Output]](../static/img/crop/repage.gif)
![[IM Output]](../static/img/crop/repage_br.gif)
![[IM Output]](../static/img/crop/repage_tl.gif)
![[IM Output]](../static/img/crop/repage_all.gif)
![[IM Output]](../static/img/crop/repage_miss.gif)
![[IM Output]](../static/img/crop/crop_vp.gif)
![[IM Output]](../static/img/crop/crop_vp_br.gif)
![[IM Output]](../static/img/crop/crop_vp_tl.gif)
![[IM Output]](../static/img/crop/crop_vp_all.gif)
![[IM Output]](../static/img/crop/crop_vp_miss.gif)
![[IM Text]](../static/img/crop/crop_vp_ident.txt.gif)
![[IM Output]](../static/img/crop/tiles_0.gif)
![[IM Output]](../static/img/crop/tiles_1.gif)
![[IM Output]](../static/img/crop/tiles_2.gif)
![[IM Output]](../static/img/crop/tiles_3.gif)
![[IM Text]](../static/img/crop/tiles_ident.txt.gif)
![[IM Output]](../static/img/crop/tiles_layered.gif)
![[IM Output]](../static/img/crop/rose_tiles_00.gif)
![[IM Output]](../static/img/crop/rose_tiles_01.gif)
![[IM Output]](../static/img/crop/rose_tiles_02.gif)
![[IM Output]](../static/img/crop/rose_tiles_03.gif)
![[IM Output]](../static/img/crop/rose_tiles_04.gif)
![[IM Output]](../static/img/crop/rose_tiles_05.gif)
![[IM Output]](../static/img/crop/rose_tiles_06.gif)
![[IM Output]](../static/img/crop/rose_tiles_07.gif)
![[IM Output]](../static/img/crop/rose_tiles_08.gif)
![[IM Output]](../static/img/crop/rose_tiles_09.gif)
![[IM Output]](../static/img/crop/rose_tiles_10.gif)
![[IM Output]](../static/img/crop/rose_tiles_11.gif)
![[IM Output]](../static/img/crop/rose_rejoined.gif)
![[IM Output]](../static/img/crop/rose_tile_1_1.gif)
![[IM Output]](../static/img/crop/rose_tile_2_1.gif)
![[IM Output]](../static/img/crop/rose_tile_3_1.gif)
![[IM Output]](../static/img/crop/rose_tile_4_1.gif)
![[IM Output]](../static/img/crop/rose_tile_1_2.gif)
![[IM Output]](../static/img/crop/rose_tile_2_2.gif)
![[IM Output]](../static/img/crop/rose_tile_3_2.gif)
![[IM Output]](../static/img/crop/rose_tile_4_2.gif)
![[IM Output]](../static/img/crop/rose_tile_1_3.gif)
![[IM Output]](../static/img/crop/rose_tile_2_3.gif)
![[IM Output]](../static/img/crop/rose_tile_3_3.gif)
![[IM Output]](../static/img/crop/rose_tile_4_3.gif)
![[IM Output]](../static/img/crop/rose_30x20_00.gif)
![[IM Output]](../static/img/crop/rose_30x20_01.gif)
![[IM Output]](../static/img/crop/rose_30x20_02.gif)
![[IM Output]](../static/img/crop/rose_30x20_03.gif)
![[IM Output]](../static/img/crop/rose_30x20_04.gif)
![[IM Output]](../static/img/crop/rose_30x20_05.gif)
![[IM Output]](../static/img/crop/rose_30x20_06.gif)
![[IM Output]](../static/img/crop/rose_30x20_07.gif)
![[IM Output]](../static/img/crop/rose_30x20_08.gif)
![[IM Output]](../static/img/crop/rose_30x20_09.gif)
![[IM Output]](../static/img/crop/rose_30x20_10.gif)
![[IM Output]](../static/img/crop/rose_30x20_11.gif)
![[IM Output]](../static/img/crop/rose_30x20_12.gif)
![[IM Output]](../static/img/crop/rose_30x20_13.gif)
![[IM Output]](../static/img/crop/rose_30x20_14.gif)
![[IM Output]](../static/img/crop/rose_30x20_15.gif)
![[IM Output]](../static/img/crop/rose_ctiles_0.gif)
![[IM Output]](../static/img/crop/rose_ctiles_1.gif)
![[IM Output]](../static/img/crop/rose_ctiles_2.gif)
![[IM Output]](../static/img/crop/rose_ctiles_3.gif)
![[IM Output]](../static/img/crop/rose_ctiles2_0.gif)
![[IM Output]](../static/img/crop/rose_ctiles2_1.gif)
![[IM Output]](../static/img/crop/rose_ctiles2_2.gif)
![[IM Output]](../static/img/crop/rose_ctiles2_3.gif)
![[IM Output]](../static/img/crop/strip_column.gif)
![[IM Output]](../static/img/crop/strip_row.gif)
![[IM Output]](../static/img/crop/strips_0.gif)
![[IM Output]](../static/img/crop/strips_1.gif)
![[IM Output]](../static/img/crop/strips_2.gif)
![[IM Output]](../static/img/crop/strips_3.gif)
![[IM Output]](../static/img/crop/quadrant_tl.gif)
![[IM Output]](../static/img/crop/quadrant_tr.gif)
![[IM Output]](../static/img/crop/quadrant_bl.gif)
![[IM Output]](../static/img/crop/quadrant_br.gif)
![[IM Output]](../static/img/crop/neg_offset_1.gif)
![[IM Output]](../static/img/crop/neg_offset_2.gif)
![[IM Output]](../static/img/crop/neg_offset_3.gif)
![[IM Output]](../static/img/crop/neg_offset_4.gif)
![[IM Output]](../static/img/crop/neg_offset_5.gif)
![[IM Output]](../static/img/crop/rose_23x15_00.gif)
![[IM Output]](../static/img/crop/rose_23x15_01.gif)
![[IM Output]](../static/img/crop/rose_23x15_02.gif)
![[IM Output]](../static/img/crop/rose_23x15_03.gif)
![[IM Output]](../static/img/crop/rose_23x15_04.gif)
![[IM Output]](../static/img/crop/rose_23x15_05.gif)
![[IM Output]](../static/img/crop/rose_23x15_06.gif)
![[IM Output]](../static/img/crop/rose_23x15_07.gif)
![[IM Output]](../static/img/crop/rose_23x15_08.gif)
![[IM Output]](../static/img/crop/rose_23x15_09.gif)
![[IM Output]](../static/img/crop/rose_23x15_10.gif)
![[IM Output]](../static/img/crop/rose_23x15_11.gif)
![[IM Output]](../static/img/crop/rose_23x15_12.gif)
![[IM Output]](../static/img/crop/rose_23x15_13.gif)
![[IM Output]](../static/img/crop/rose_23x15_14.gif)
![[IM Output]](../static/img/crop/rose_23x15_15.gif)
![[IM Output]](../static/img/crop/rose_3x3@_0.gif)
![[IM Output]](../static/img/crop/rose_3x3@_1.gif)
![[IM Output]](../static/img/crop/rose_3x3@_2.gif)
![[IM Output]](../static/img/crop/rose_3x3@_3.gif)
![[IM Output]](../static/img/crop/rose_3x3@_4.gif)
![[IM Output]](../static/img/crop/rose_3x3@_5.gif)
![[IM Output]](../static/img/crop/rose_3x3@_6.gif)
![[IM Output]](../static/img/crop/rose_3x3@_7.gif)
![[IM Output]](../static/img/crop/rose_3x3@_8.gif)
![[IM Output]](../static/img/crop/rose_2x2+20+20@_0.gif)
![[IM Output]](../static/img/crop/rose_2x2+20+20@_1.gif)
![[IM Output]](../static/img/crop/rose_2x2+20+20@_2.gif)
![[IM Output]](../static/img/crop/rose_2x2+20+20@_3.gif)
![[IM Output]](../static/img/crop/montage.gif)
![[IM Output]](../static/img/crop/montage_0.gif)
![[IM Output]](../static/img/crop/montage_1.gif)
![[IM Output]](../static/img/crop/montage_2.gif)
![[IM Output]](../static/img/crop/montage_3.gif)
![[IM Output]](../static/img/crop/montage_4.gif)
![[IM Output]](../static/img/crop/montage-3_0.gif)
![[IM Output]](../static/img/crop/montage-3_1.gif)
![[IM Output]](../static/img/crop/montage-3_2.gif)
![[IM Output]](../static/img/crop/montage-3_3.gif)
![[IM Output]](../static/img/crop/montage-3_4.gif)
![[IM Output]](../static/img/crop/edged.gif)
![[IM Output]](../static/img/crop/edged+6_0.gif)
![[IM Output]](../static/img/crop/edged+6_1.gif)
![[IM Output]](../static/img/crop/edged+6_2.gif)
![[IM Output]](../static/img/crop/edged+6_3.gif)
![[IM Output]](../static/img/crop/edged+6_4.gif)
![[IM Output]](../static/img/crop/edged-6_0.gif)
![[IM Output]](../static/img/crop/edged-6_1.gif)
![[IM Output]](../static/img/crop/edged-6_2.gif)
![[IM Output]](../static/img/crop/edged-6_3.gif)
![[IM Output]](../static/img/crop/edged-6_4.gif)
![[IM Output]](../static/img/crop/edged-8_0.gif)
![[IM Output]](../static/img/crop/edged-8_1.gif)
![[IM Output]](../static/img/crop/edged-8_2.gif)
![[IM Output]](../static/img/crop/edged-8_3.gif)
![[IM Output]](../static/img/crop/edged-8_4.gif)
![[IM Output]](../static/img/crop/tile-shave.gif)
![[IM Output]](../static/img/crop/spaced.gif)
![[IM Output]](../static/img/crop/spaced+6_0.gif)
![[IM Output]](../static/img/crop/spaced+6_1.gif)
![[IM Output]](../static/img/crop/spaced+6_2.gif)
![[IM Output]](../static/img/crop/spaced+6_3.gif)
![[IM Output]](../static/img/crop/spaced+6_4.gif)
![[IM Output]](../static/img/crop/spaced-6_0.gif)
![[IM Output]](../static/img/crop/spaced-6_1.gif)
![[IM Output]](../static/img/crop/spaced-6_2.gif)
![[IM Output]](../static/img/crop/spaced-6_3.gif)
![[IM Output]](../static/img/crop/spaced-6_4.gif)
![[IM Output]](../static/img/crop/border_default.gif)
![[IM Output]](../static/img/crop/border_sides.gif)
![[IM Output]](../static/img/crop/border_topbot.gif)
![[IM Output]](../static/img/crop/border_none.gif)
![[IM Output]](../static/img/images/star.gif)
![[IM Output]](../static/img/crop/star_background.gif)
![[IM Output]](../static/img/crop/border_compose.jpg)
![[IM Output]](../static/img/crop/paged_border.gif)
![[IM Output]](../static/img/crop/frame.gif)
![[IM Output]](../static/img/crop/frame_wierd.gif)
![[IM Output]](../static/img/crop/frame_blue.gif)
![[IM Output]](../static/img/crop/frame_red.gif)
![[IM Output]](../static/img/crop/frame_rasied.gif)
![[IM Output]](../static/img/crop/frame_rasied_part.gif)
![[IM Output]](../static/img/crop/frame_sunken_part.gif)
![[IM Output]](../static/img/crop/frame_sunken.gif)
![[IM Output]](../static/img/crop/frame_normal.gif)
![[IM Output]](../static/img/crop/frame_popped.gif)
![[IM Output]](../static/img/crop/frame_pressed.gif)
![[IM Output]](../static/img/crop/frame_inverted.gif)
![[IM Output]](../static/img/crop/frame_compose.jpg)
![[IM Output]](../static/img/crop/paged_framed.gif)
![[IM Output]](../static/img/crop/shave.gif)
![[IM Output]](../static/img/crop/shave_sides.gif)
![[IM Output]](../static/img/crop/shave_topbot.gif)
![[IM Output]](../static/img/crop/paged_frame.gif)
![[IM Output]](../static/img/crop/paged_shave.gif)
![[IM Output]](../static/img/crop/paged_tile_shave.gif)
![[IM Output]](../static/img/crop/extent_enlarge.gif)
![[IM Output]](../static/img/crop/extent_shrink.gif)
![[IM Output]](../static/img/crop/extent_wider.gif)
![[IM Output]](../static/img/crop/extent_taller.gif)
![[IM Output]](../static/img/crop/extent_north.gif)
![[IM Output]](../static/img/crop/extent_south.gif)
![[IM Output]](../static/img/crop/extent_east.gif)
![[IM Output]](../static/img/crop/extent_west.gif)
![[IM Output]](../static/img/crop/extent_center.gif)
![[IM Output]](../static/img/crop/extent_center2.gif)
![[IM Output]](../static/img/crop/splice.gif)
![[IM Output]](../static/img/crop/splice_column.gif)
![[IM Output]](../static/img/crop/splice_row.gif)
![[IM Output]](../static/img/crop/splice_topleft.gif)
![[IM Output]](../static/img/crop/splice_top.gif)
![[IM Output]](../static/img/crop/splice_bottom.gif)
![[IM Output]](../static/img/crop/splice_left.gif)
![[IM Output]](../static/img/crop/splice_right.gif)
![[IM Output]](../static/img/crop/splice_botright.gif)
![[IM Output]](../static/img/crop/splice_label.gif)
![[IM Output]](../static/img/crop/splice_chop.gif)
![[IM Output]](../static/img/crop/chop.gif)
![[IM Output]](../static/img/crop/chop_splice.gif)
![[IM Output]](../static/img/crop/chop_top.gif)
![[IM Output]](../static/img/crop/chop_left.gif)
![[IM Output]](../static/img/crop/chop_right.gif)
![[IM Output]](../static/img/crop/chop_bottom.gif)
![[IM Output]](../static/img/crop/crop_edge_top.gif)
![[IM Output]](../static/img/crop/crop_edge_left.gif)
![[IM Output]](../static/img/crop/crop_edge_right.gif)
![[IM Output]](../static/img/crop/crop_edge_bottom.gif)
![[IM Text]](../static/img/crop/trim_info.txt.gif)
![[IM Output]](../static/img/crop/stripes.gif)
![[IM Output]](../static/img/crop/stripes_trimmed.gif)
![[IM Output]](../static/img/crop/stripes_trim_red.gif)
![[IM Output]](../static/img/crop/stripes_trim_red_fix2.gif)
![[IM Text]](../static/img/crop/blur_trim_info.txt.gif)