ImageMagick 示例 -
裁剪和加边框

索引
ImageMagick 示例前言和索引
裁剪(以自由形式裁剪图像)
添加/移除图像边缘
添加/移除行、列和边缘
高级裁剪技术
修剪,'自动裁剪' 操作符
在这里,我们探索了 ImageMagick 的操作,这些操作允许您对图像进行裁剪,并在图像周围添加边框。也就是说,我们着眼于那些不缩放图像内容而改变图像大小的操作。您可能会认为这是一个简单的操作,它确实是。如此简单,以至于 IM 提供了大量的方法和方法来实际完成这项任务。如此之多,以至于我需要专门给它一个示例页面,来演示它们。

裁剪(将图像裁剪成所需大小)

裁剪和画布页面

"-crop" 图像操作符将简单地裁剪掉当前序列中所有图像的指定尺寸和位置的部分,由它的几何参数指定。

  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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
为了方便您检查发生了什么,以下是 "magick identify" 对上述裁剪结果的输出。

  magick identify rose: crop.gif crop_br.gif crop_tl.gif \
                 crop_all.gif crop_miss.gif
[IM Text]
请注意,显示图像的大小(它的 虚拟画布)并没有受到 "-crop" 操作的影响。实际图像本身已经被裁剪,可能变小了,但显示 GIF 图像的画布仍然与原始画布一样大。您还会注意到,实际图像的大小可能与您从裁剪中请求的实际大小不符。它可能远小于您的预期,因为裁剪本身要么部分地,要么完全地位于被裁剪的实际图像区域之外。您还会注意到,图像在 虚拟画布 上的 '偏移量' 在许多情况下也会发生改变,以便裁剪图像的像素仍然与它们在原始图像中的位置完全相同。也就是说,图像内容本身不会移动,即使实际图像本身变小了。这意味着,如果您现在修改较小的图像,然后将图像(使用 图像图层操作符)叠加到原始图像上,它将精确地回到子图像最初所在的的位置。也就是说,IM 保留了图像的 '虚拟画布'、'页面' 或 '图层' 信息,以便将其保留以供以后使用。这对 GIF 动画处理的正确工作尤其重要。有关更多信息,请参阅 解构 GIF 动画
GIF 图像积极地利用了 '页面' 或 '虚拟画布' 的大小和偏移量信息,这些信息是通过 IM 裁剪图像而得到的。如果您不想要此信息,请在 "-crop" 之后立即使用 "+repage" 来移除它。

请注意,许多图像格式不会保存此虚拟页面/画布信息,因此保存到此类格式会自动移除它。JPEG 是一个典型的移除此信息的格式示例。

PNG 格式不太使用页面/画布信息(除了在多 PNG(MNG)格式中),但它确实保存了页面偏移量信息(即使是负偏移量)。IM 还将添加少量元数据,以保留虚拟画布大小,以便 IM 的其他命令稍后使用。

由于存在这种保留,我强烈建议您即使在保存到 JPEG 或其他无页面图像格式时也要应用 "+repage",作为一种预防措施,并使它明显地表明您不想要它。

注意,裁剪的行为可能会受到这些定义的影响

trim:percent-background=X% 设置在边缘中允许的背景量。它以百分比指定。0% 表示不允许任何背景。50% 表示一个边缘可以包含最多 50% 的根据模糊因子的背景像素。
trim:edges={north,east,south,west} 只修剪图像的指定边缘。
trim:minSize=geometry 将修剪限制到指定的大小。
type:features=string 添加一个字体特征,在复杂文本布局期间由 RAQM 代理使用。这通常用于打开默认情况下未启用的可选字体特征,但也可以用于关闭默认字体特征。特征包括控制字距、连字和阿拉伯语的特征。
type:hinting=false 禁用字体提示。正确的字形渲染需要缩放后的点与目标设备像素网格对齐,这通常称为提示。它的主要目的之一是确保整个字体中都尊重重要的宽度和高度。(例如,非常希望 'I' 和 'T' 字形具有相同的像素宽度的中心垂直线。提示还管理字杆和超伸等特征,这些特征在较小的像素尺寸下会导致问题。

错过的图像(来自错误的裁剪)

上面示例中的最后一个图像(例如:"crop_miss.gif")也生成了一个特殊的空图像。此类图像可以通过 裁剪修剪图层比较 甚至 GIF 动画优化 等操作生成,这些操作会生成空或无意义的结果。例如,在上面的先前示例中,"-crop" 操作错过了它要裁剪的实际图像,因此它生成了这个特殊的 '错过的' 图像,以及一些信息性警告消息...
[IM Text]
输出图像或 '错过的' 图像是一个最小图像,大小为一个像素,偏移量为 0,但具有原始图像的页面或画布大小,以及图像可能关联的任何其他元数据。在这里,它代表了应该由 "-crop" 返回的 '空' 或 '零尺寸' 图像,但由于任何图像格式都不能输出 '零' 维度的图像,因此改为使用单个透明像素图像。为了让您更清楚地看到,这里展示了 '错过的' 图像的 "identify" 输出,以及该单个像素图像的 'IM 像素枚举',显示它只包含一个单个透明像素。

  magick identify crop_miss.gif
[IM Text]

  magick crop_miss.gif  crop_miss_data.txt
[IM Text]
此 '错过的' 图像基本上与创建 "null:" 图像相同,但设置了原始源图像的页面或虚拟画布大小(但没有设置它的偏移量),以及所有其他图像元数据,例如 GIF 动画定时延迟。然而,GIF 处置方法可能会被修改,以确保动画在裁剪后仍然正确。基本上,您需要记住 "-crop" 和其他类似的操作符可能会生成一个特殊的 '错过的' 图像。因此,在使用 IM 编写脚本时,您应该计划寻找警告消息,或这种特殊的 '错过的图像',如果这种最小图像是可能的,并且可能会导致问题。如果您不想要警告消息(例如,您期望并处理偶尔出现的 '错过的' 图像),您可以在命令行中添加 "-quiet" 操作控制设置。这告诉 IM 不要输出信息性警告消息,只输出真正的错误。目前还没有方法可以从当前图像序列中移除任何 '错过的' 图像或 "null:" 图像。但是,这种方法已在 IM 的未来版本中提出。如果您发现需要这种方法,请给我发邮件。

裁剪带有现有虚拟画布的图像

如果一个图像已经有一个现有的 虚拟画布(例如 GIF 动画的帧),那么 "-crop" 操作将相对于虚拟画布应用,而不是相对于实际图像。也就是说,它将尝试保留裁剪图像的实际像素数据在画布上的偏移量。也就是说,裁剪之前的特定像素在裁剪之后仍然应该位于相对于虚拟画布的相同偏移量位置。这样,即使 '画布' 本身没有被裁剪,图层图像或 GIF 动画的裁剪仍然可以正常工作。在这里,我们创建一个居中于页面画布的图像,然后以各种方式裁剪它。与之前一样,画布大小本身不会受到操作的影响。

  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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
[IM Text]
上面的最后一个示例当然是特殊的 错过的图像。请注意,我使用 "-quiet" 设置抑制了 IM 的正常警告消息。为了让您更清楚地了解发生了什么,让我们仔细看看图像右下角的分页裁剪。在这里,我在裁剪区域上绘制了一个半透明的正方形。

  magick paged.gif -page 64x64+32+32 -size 32x32 xc:'#fff8' \
          -alpha set  -background none  -mosaic    crop_area_br.png
[IM Output] ==> [IM Output] ==> [IM Output]
由此您可以看到正在发生的事情。即使裁剪完全包含在页面画布中,裁剪也没有完全覆盖实际图像。结果是,实际图像比用户可能打算的要小,但仍然位于更大的画布或页面上。

移除结果中的虚拟画布

如果此 虚拟画布 信息不需要,那么您可以使用特殊的 "+repage" 操作符来重置页面画布和位置,使其与实际裁剪的图像匹配。

  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 Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
当然,这是 IM 新用户通常期望从“-crop” 运算符获得的结果。实际上,这是一种非常常见的操作,以至于可以称之为经验法则。
在任何类似“裁剪”的操作之后,始终使用“+repage”。
除非你确实需要保留这些信息。
上面最后一张图像是特殊 的裁剪未命中图像,但我使用“-quiet” 操作设置抑制了警告消息。
对于 IM 5 版及更早版本,“+repage” 操作由“-page +0+0” 参数序列处理,通常在保存到使用虚拟画布和偏移信息(如 GIF)的格式之前。但这仅在将图像读入或写入文件时才可用,阻止了它在多个图像处理操作之间使用。随着 IM 6 版,命令行重构,“-page” 选项变成了纯粹的图像读取/创建设置,用于创建 GIF 动画图像图层。因此,添加了单独的“-repage” 和 “-set page” 运算符,以允许用户设置或更改虚拟画布信息。

使用虚拟画布调整进行视口裁剪

从 ImageMagick 6.2.4-5 版开始,你可以向 “-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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
[IM Text]
字符 '!' 对某些 UNIX shell(如“csh”)具有特殊意义,即使放在引号内也必须用反斜杠转义。
注意返回图像的画布大小现在与图像被裁剪的区域匹配。对于完全位于实际图像内的图像裁剪,结果将等同于在裁剪之后使用 “+repage”。但是,对于图像的任何部分或未命中的裁剪,结果将是一个更大的画布,并且可能对结果图像进行偏移。因此,这不能替代在裁剪后执行 “+repage” 以重置页面/画布信息。但是,你可以在“视口裁剪”之后使用 扁平化 来用真实像素“填充”图像的新虚拟画布。也就是说,你将得到一个保证是请求裁剪大小的图像,任何“未命中”区域将用当前“-background” 颜色“视口”填充。
例如,当 填充图像 时。

  magick rose: -crop 100x100-15-25\! -background skyblue -flatten \
          crop_viewport.gif
[IM Output]
在视口裁剪后扁平化图像实际上等同于使用 Extent 运算符(见下文)来提供“填充裁剪”。在裁剪 GIF 动画时,“视口裁剪”标志也非常重要,因为它不仅调整画布大小,而且还确保所有图像帧在裁剪区域内仍然正确定位。如果没有此选项,裁剪 GIF 动画非常困难,需要外部校正图像画布大小和偏移。有关此的示例,请参阅 动画裁剪,以及画布。在许多方面,“视口裁剪”与特殊的 视口扭曲设置 密切相关,因为它们都像“窗口”一样作用于结果图像。两者都可以用作“裁剪”方法。
在生成多图像 平铺裁剪 或使用等面积平铺裁剪时,不能使用 '!' 标志,因为它具有不同的含义。请参阅下面的相应部分。

相对于重力的裁剪

默认情况下,“-crop” 的偏移位置相对于图像的左上角。但是,通过设置 “-gravity” 设置,你可以告诉 “-crop” 相对于图像的中心、角点或边缘裁剪图像。重力裁剪最常见的用途是裁剪图像的“center”。

  magick rose: -gravity Center  -crop 32x32+0+0 +repage  crop_center.gif
[IM Output]
-gravity” 设置不仅影响裁剪的初始“零”位置,还会影响裁剪偏移的方向。例如,如果你使用 'South' 的 “-gravity”,则 '+0+5' 的偏移将向上偏移裁剪区域,而不是像通常那样向下偏移。

  magick rose: -gravity South  -crop 20x20+0+5   crop_south.gif
[IM Output]
注意上面裁剪示例的位置。我故意省略了“+repage” 操作,这样你就可以看到裁剪区域是如何从图像的底部边缘偏移的。还要注意,裁剪区域不仅相对于底部(南部)边缘,而且区域是中心“对齐”的,位于底部边缘的中间。这是对所有受重力影响的操作执行的。

裁剪图像的百分比

-crop” 运算符还了解如何将图像裁剪到其原始大小的百分比。例如,这将使图像的大小减半。

  magick rose:  -crop 50%x+0+0      crop_half.gif
[IM Output]
如果只给出一个尺寸数字,则该值将用于宽度和高度百分比,并且正在裁剪的区域的最终尺寸将四舍五入到最接近的整数。偏移是可选的。
请注意,虽然尺寸可以是百分比,但偏移始终以像素为单位。你不能将偏移提供为图像大小的百分比。

  magick rose:  -crop 50%x+30+20      crop_percent.gif
[IM Output]
当裁剪给出偏移时,你必须在参数中提供一个 'x' 符号,以便参数可以被正确解释。这在仅为裁剪区域的宽度和高度提供单个数字时尤其重要。

因此,你不能使用像 '50%+30+20 这样的参数,这是一个错误,将导致裁剪静默地不执行任何操作。
更常见的是,从图像的中心进行百分比裁剪。

  magick rose: -gravity Center -crop 50x80%+0+0  crop_percent_center.gif
[IM Output]
百分比符号 '%' 可以出现在参数中的任何位置,如果给出,将引用宽度和高度数字。它是一个标志,仅声明“图像大小”部分是图像虚拟画布或页面大小的百分比分数。偏移始终以像素为单位给出。
你也可以对百分比裁剪使用“视口裁剪”标志,以自动将裁剪的画布大小和偏移设置为正在裁剪的区域。

  magick rose: -gravity Center -crop 50%\!  crop_percent_vp.gif
[IM Output]
你不能对平铺裁剪使用百分比大小(见下文)。因此,如果没有提供偏移,并且给出了百分比大小(如上所述),则假设偏移为 +0+0。

标志 '!' 表示不需要“+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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
[IM Text]
如果你只是想从图像中提取特定数量的平铺,请查看下面的 裁剪成大致等大小的分割
最好确保使用 “+gravity” 关闭重力。这是因为在一种特殊情况下(居中的百分比裁剪),重力设置可以关闭平铺裁剪。重力对平铺裁剪的其他影响也是未定义的。
通过使用 “-mosaic” 或 “-flatten” 图像分层运算符(参见 图层扁平化),你可以将这些图像叠加在一起,恢复原始图像。

  magick tiles_[0-3].gif -background white -mosaic  tiles_mosaic.gif
[IM Output]
但是,如你所见,图像的虚拟画布已由 “-mosaic” 用背景颜色填充。另一种方法是使用 “-layers merge”(参见 图层合并),它将多个图层图像合并到一个足够大的新图层图像中,以容纳所有给定的图像。也就是说,虚拟画布不会被填充,就像 “-mosaic” 或 “-flatten” 分层方法那样。

  magick tiles_[0-3].gif -background none -layers merge  tiles_layered.gif
  magick identify tiles_layered.gif
[IM Output]
  [IM Text]
如果你已使用 “+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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
==> [IM Output]
请注意,各个图像的名称从 “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"
[IM Output] ==> ==> [IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
将生成平铺图像文件名 “rose_tile_1_1.gif” 到 “rose_tile_4_3.gif”,这是一个更好的文件名方案。很巧妙,但它确实有效。不幸的是,你无法格式化由 百分比转义 生成的数字,以包括用零填充或指定确切的浮点数位数。至少现在还不行。

居中平铺裁剪

IM 论坛讨论中,有人请求将瓷砖裁剪居中,以便将“剩余图像”均匀分布在边缘周围。通过这样做,我们通过将完整瓷砖放置在图像的中心来最大限度地发挥完整瓷砖的效果。当然,您最终也会有更多不完整的边缘瓷砖。解决方案是在虚拟画布上居中输入图像,该画布是所需的瓷砖大小的倍数。例如,要将“rose:”图像(大小为70x46像素)裁剪成最大数量的完整30x20瓷砖,并将它们放置在图像的中心(并被剩余瓷砖包围),您可以执行以下操作。
  1. 首先,通过将图像大小相除来计算您可以从图像中获得的完整瓷砖数量...
    70x46 / 30x20 => 2x2 full tiles + remainder
  2. 现在添加两行和两列以容纳剩余图像(如果需要)
    2x2 + 2x2 => 4x4 tile images
  3. 将瓷砖大小乘以该数字以获得虚拟画布大小。
    30x20 * 4x4 => 120x80 canvas size
  4. 减去原始图像大小,然后除以二以获得居中偏移量。
    ( 120x80 - 70x46 ) / 2 => +25+17
因此,虚拟画布和居中偏移量为120x80+25+17。在这里,我们使用上述计算执行居中瓷砖裁剪...

  magick rose: -repage 120x80+25+17 -crop 30x20 +repage rose_30x20_%02d.gif
[IM Output] ==> ==> [IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
如果您想保留瓷砖的原始偏移位置,但删除居中偏移量,则可以使用“-repage -25-17\!”(将上述内容中的“+repage”替换掉)进行相对偏移调整。如果您没有在瓷砖数量中添加两列和两行,从而产生负偏移量,则可以有效地忽略剩余边缘瓷砖,并且只输出图像中存在的完整瓷砖。

  magick rose: -repage 60x40-5-3 -crop 30x20 +repage rose_ctiles_%d.gif
[IM Output] ==> ==> [IM Output] [IM Output]
[IM Output] [IM Output]
基本上,由于剩余部分现在位于计算出的虚拟画布“外部”,因此“-crop”运算符不知道它们在那里,并忽略了它们。再次将上述内容中的“+repage”替换为使用负偏移值“-repage +5+3\!”的相对偏移调整,将恢复裁剪瓷砖的原始偏移位置。另一种居中瓷砖裁剪并忽略剩余部分的方法是简单地将虚拟画布设置替换为适当的裁剪。

  magick rose: -gravity center -crop 60x40+0+0 +gravity +repage \
          -crop 30x20 +repage rose_ctiles2_%d.gif
[IM Output] ==> ==> [IM Output] [IM Output]
[IM Output] [IM Output]
上面的方法更容易理解,但速度也略慢,因为您现在执行两次裁剪。但是,所需的计算更少。但是,如果您想恢复原始瓷砖偏移量,您仍然需要计算所需的相对偏移量,在这种情况下,您也可以使用图像虚拟画布使用更快的先前方法来完成任务。

条带裁剪,裁剪掉行和列

在 IM 版本 6.1.1 中,“-crop”得到了增强,因此如果其中一个大小参数丢失或设置为零,则丢失的大小参数将设置为图像画布/页面的大小。在大多数情况下,这足够大以覆盖位于画布上的图像,如果相关的偏移量也设置为零。这种细微的改变允许您轻松地从图像中裁剪出一行或一列,而无需像“999999”那样使用一个巨大的数字来覆盖图像的大小。例如,这里我们从“分页”玫瑰图像中提取了一行和一列。


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 Output] ==> [IM Output] [IM Output]
  [IM Text]
如果您同时删除了两个偏移量和一个大小参数,则可以将图像分成一系列条带或列,而不是瓷砖。


magick rose: -crop 40x30+10+10 crop.gif
magick crop.gif -quiet -crop 20x strips_%d.gif
magick identify crop.gif strips_?.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
  [IM Text]
请注意,瓷砖裁剪(条带或其他方式)跨越图像的整个页面画布,因此与该画布对齐,而不仅仅是实际图像。这就是为什么上面示例中生成的第一个和最后一个实际图像只有 10 像素宽的原因。当然,如果某个特定的瓷砖(在本例中为“列”)错过了虚拟画布上的实际图像(例如,上面示例中的最后一个图像),则会生成一个裁剪错过的图像。使用“-quiet”设置抑制了 IM 通常会产生的警告。除非您预计会发生此类事件,并且为此做好了准备(例如,在脚本中),否则不建议这样做。
图像可能处于这样的位置,即它甚至没有出现在它自己的页面或虚拟画布上,或者图像太大,以至于页面画布只能包含图像的一小部分窗口或部分。

在这种罕见的情况下,没有大小参数的条带裁剪会使图像细分错误,并分别产生错过的图像,或者仅包含虚拟画布边界内部分的较小瓷砖。

然而,“-crop”运算符不会被修复以处理这些罕见的特殊情况,因为这样做会阻止它在其他情况下使用,例如下面示例的那些情况。

如果这对您来说是个问题,请在裁剪之前使用“+repage”清除图像的页面偏移量,以删除虚拟画布,然后再尝试生成瓷砖图像。
作为将图像分成单独行的一种替代方法,请查看特殊脚本“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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
当然,如果您裁剪的点错过了实际图像,那么两个甚至三个生成的象限图像将是特殊的裁剪错过的错误图像。

使用负偏移量,移除底部或左边缘

没有理由不能将负偏移量与“-crop”一起使用。事实上,有时它可能具有非常明确的优势。例如,让我们使用我们的分页玫瑰图像,并使用更大的负偏移量逐步裁剪它。我们不会为“-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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
正如您所看到的,将偏移量稳定地减小到更大的负值会导致底部和右侧边缘被“切掉”,最后一个示例几乎错过了实际图像。如果我们再进行一步,将生成一个错过的图像。这有点像使用“-chop”运算符,但没有“-gravity”设置。参见Chop,移除边缘。当然,通过使用“-crop”,您可能需要使用“+repage”运算符来调整画布/页面信息,而“-chop”会自动执行此类调整。这就是生活。

裁剪成大致等尺寸的分割

使用瓷砖裁剪的最大问题是您只能定义每个瓷砖的最终大小。当图像大小是所需瓷砖大小的精确倍数时,这非常有用,但正如您所看到的,如果不是这种情况,您最终可能会在右侧和底部边缘出现“短”瓷砖。例如,让我们再次分割内置的玫瑰图像,但尝试将其分割成 3x3 的瓷砖。原始图像为 70x46 像素,因此除以 3 使每个瓷砖为 23x15 像素...

  magick rose: -crop 23x15  +repage  +adjoin  rose_23x15_%02d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
正如您所看到的,这不起作用,因为玫瑰图像不能精确地分成 3 个大小相同的瓷砖。在这种情况下,您最终会得到一个 1 像素的“短”瓷砖。即使您将瓷砖大小扩展到 24x16 像素,您最终仍然会得到一个比其他瓷砖“短” 2 像素的瓷砖。随着所需瓷砖数量的增大,这种情况会变得更糟。例如,尝试将 100 的长度细分为 30 个瓷砖。这是不可能的。您可以使用长度 3 并获得 34 个瓷砖,或者使用 4 并获得 25 个瓷砖。获得正好 30 个大小相同的瓷砖是不可能的!从 IM v6.5.8-9 开始,您现在可以在“-crop”参数中添加特殊的“@”标志。此标志告诉“-crop”运算符尽力将图像平均分成给定的瓷砖数量。例如...

  magick rose: -crop 3x3@  +repage  +adjoin  rose_3x3@_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]
结果是,图像被分割成大小略有不同的瓷砖。但是,瓷砖大小最多相差 1 像素!查看一下!作为奖励,您还可以分割图像,以便每个瓷砖都与其相邻的瓷砖“重叠”。您不仅使用“@”标志,还可以指定所需的重叠像素数量。例如,让我们将玫瑰分成四个象限,但重叠 20 像素。

  magick rose: -crop 2x2+20+20@  +repage  +adjoin  rose_2x2+20+20@_%d.gif
[IM Output] ==> [IM Output] [IM Output]
[IM Output] [IM Output]
同样,所有部分的大小最多只相差一个像素!虽然在这种情况下,生成的图像大小相同,因为玫瑰可以除以 2,但大小相同。然而,如果重叠或图像的大小是奇数,则不会是这种情况。在这种情况下,较大的元素将位于顶部和左侧边缘。但是,使用三个瓷砖,较大的(或较小的)元素将被放置在中间!您甚至可以使用负重叠来精确地“跳过”瓷砖之间的那些像素!您应该如何应用运算符取决于您想要“重叠”或“跳过”哪些像素。这取决于图像的“边缘”特征(参见下面的分离间隔开来的平铺图像)。与使用“-crop”运算符一样,建议您使用“+repage”来删除“页面”偏移量(如果不需要)。但是,裁剪后的图像偏移信息非常有用,这就是为什么它被保留的原因。例如,您可以使用它来命名输出文件,或者找出 IM 计算的瓷砖的大小和位置。请注意,大小相等的瓷砖裁剪是“-crop”运算符在确定要裁剪的图像部分时忽略图像的实际虚拟画布的唯一情况。也就是说,瓷砖裁剪的计算基于实际图像大小,而不是虚拟画布大小。即使这样,最终的瓷砖偏移量仍然相对于原始虚拟画布。此裁剪选项也可以用作修边运算符的替代方法,用于“分页”图像。
在 IM 版本 v6.6.1-0 之前,具有虚拟画布偏移量的图像的大小相等的瓷砖裁剪是无效的。

分离间隔开的平铺图像

通常,您会有一个图像,它包含固定大小的图块,这些图块之间用固定数量的空白隔开。新的“@”标志裁剪运算符将使您更轻松地裁剪出这些图块,可以选择包含或跳过周围的空白。然而,主要问题是,虽然“图块”图像周围有固定数量的空白,但边缘周围的空白通常并不固定。这会对一组“间隔”图像产生三种基本的边缘特征样式,每种类型都需要略微不同的处理方式。 拼贴图块在这里,原始图像在拼接在一起之前只是被赋予了一个固定大小的边框。结果是,您将始终在图块之间有偶数像素的间距。更重要的是,“边缘间距”恰好是图块之间间距的一半。这实际上是“montage”对平铺“单元格”进行间距的方式,并且正是使用此命令生成了下面显示的示例图像。由于图像只是简单地平铺在一起,您可以使用正常的 图块裁剪(如果您知道图块大小),或者使用 等大小裁剪(如果您知道图块数量),来分离子图像和周围的边框。图块之间基本上没有重叠,简单的 削边运算符 就可以用来从结果图块中删除该边框。

  magick montage.gif -crop 5x1@ +repage +adjoin montage_%d.gif
  magick montage_?.gif -shave 3x3 montage-3_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
边缘周围的相同间距在这里,子图像不仅“间隔”了 6 个像素,而且在边缘周围也有 6 个像素的间距,使其看起来相当整齐。这可以通过使用默认的 等大小裁剪 以及适当数量的像素“重叠”来处理。例如…

  magick edged.gif -crop 5x1+6+6@ +repage +adjoin edged+6_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
请注意,运算符是如何分离图像的,使它们保持相同的大小,但有 6 个像素的重叠。这正是它被设计用来做的。通过使用负偏移量,您告诉 IM 不要在最终结果中包含重叠区域(间距部分)。

  magick edged.gif -crop 5x1-6-6@ +repage +adjoin edged-6_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
如果我再进一步,减去更多的像素,我甚至可以从上面的数字中修剪一些白色边框。

  magick edged.gif -crop 5x1-8-8@ +repage +adjoin edged-8_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
您甚至可以使用此方法作为 削边运算符 的替代方法,只需指定 1 个图块裁剪…

  magick edged+6_0.gif -crop 1x1-6-6@ +repage tile-shave.gif
[IM Output] ==> [IM Output]
简单间隔图块最简单的间隔平铺图像没有边缘间距,或者已经从图像中 修剪 了边缘间距。但是,为了处理这种情况,您需要通过包含“@”和“!”这两个标志来告诉 IM 这种特殊情况。

  magick spaced.gif -crop 5x1+6+6@\! +repage +adjoin spaced+6_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
请注意,此细分的边缘上的图像略短于中间的图像。这就是为什么这种特殊的运行模式不是默认模式的原因,即使它实际上比前面的间隔平铺类别更简单。另外请注意,当同时使用“@”和“!”标志时,单个图块裁剪(在本例中为垂直裁剪)没有任何效果,因为图块的顶部和底部都是“边缘”,因此没有“边缘空间”可以删除。同样,通过使用重叠的负值,您可以告诉 IM 不要在图块裁剪结果中包含重叠(间距)区域。

  magick spaced.gif -crop 5x1-6-6@\! +repage +adjoin spaced-6_%d.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
字符 '!' 对某些 UNIX shell(如“csh”)具有特殊意义,即使放在引号内也必须用反斜杠转义。
有了这些公式,您现在应该能够裁剪形成网格的图像,即使图像重叠或间隔。即使您遇到的特定问题没有完全符合上述情况,您也应该能够适当地添加或删除边缘像素,以使图像符合上述间隔图像类别之一。

添加/删除图像边缘

边框,在图像周围添加空白

通常,您只想在图像边缘周围添加一些工作空间,但您不想依赖于知道图像的大小才能做到这一点。现在有很多方法可以在图像周围添加额外空间,除了直接添加空间之外,包括 追加空白图像或标签组合“Src”叠加层,甚至只是 将图像定位在一个更大的画布上。但是这些方法通常至少需要知道您正在处理的图像有多大。最简单的图像空间添加方式之一是“-border”操作。添加的空白的颜色是“-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
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
注意上面最后一个示例图像。边框颜色被设置为透明颜色“none”,但为了使其按预期工作,我们需要确保图像实际上包含一个“遮罩”或“alpha”通道。另外请注意,如果垂直和水平边框大小相同,则可以使用单个数字省略第二个数字。
如上所示,“-border”运算符使用的默认颜色是浅灰色,因为它与 WWW 上网页的默认灰色页面颜色完美匹配。
您可以将边框指定为图像大小的百分比…

  magick rose: -border 10%x10%  border_percent.jpg
[IM Output]
实际上,“-border”操作是在内部创建一个正确大小的新图像,然后将原始源图像叠加到这个新背景上。这本身是 ImageMagick 中一个非常有用的操作,用于设置透明和半透明图像的背景。也就是说,看似无用的“-border 0”操作在 IM 版本 6 中是一个非常有用的操作。例如…

  magick star.gif -bordercolor LimeGreen -border 0  star_background.gif
[IM Output] ==> [IM Output]
当然,还有很多其他方法可以 删除 Alpha 透明度
为包含透明度的图像添加边框的事实,也默认情况下会填充图像的透明背景,这在 IM 用户和开发团队中引发了一些争议。关于此争议的总结见 边框、框架和边框颜色的使用

边框和 Alpha 合成

图像到边框颜色画布的叠加受“-compose”设置控制,该设置默认情况下设置为“Over” alpha 合成。如果它被设置为其他设置,“-border”操作可能会产生意想不到的结果。例如,以下是一些“-compose”与“-border”图像运算符一起使用时的更有趣的用例,当应用于包含一些透明区域的图像时。

  magick star.gif -bordercolor LimeGreen \
                   -compose {operation} -border 5  {result}
[IM Output]
在使用“Over”和“Copy”之间进行选择,实质上是决定您是否要保留图像中的透明度。例如,这里是用透明度显示的相同的“星形”图像,但这次添加了边框,并没有破坏图像的透明度。

  magick star.gif  -bordercolor LimeGreen   -compose Copy \
                     -border 5     star_border_copy.gif
[IM Output]
Src”合成将为图像添加一个透明边框(如果它有 alpha 通道),而不管当前的“-bordercolor”设置如何。基本上,“-border”生成的背景画布被忽略了。“Dst”可能看起来不是很有用,但可以用来生成一个与原始图像相同大小(或略大)的画布。原始图像仅用于确定画布的最终大小。有关更多示例,请参见 根据现有图像调整大小的画布。有关各种“-compose”方法的更多信息,请参见 Alpha 合成示例

边框和虚拟画布

当“-border”应用于包含虚拟画布的图像时,它仍然会在该虚拟画布上的实际图像周围添加边框,而不是在整个画布周围添加边框。


magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -border 5x5 paged_border.gif
[IM Output] ==> [IM Output]
请注意,虚拟画布的大小也增加了边框厚度的两倍,以适应添加的边框。当然,这意味着您不能简单地直接为典型的 GIF 动画添加 边框,除非您想实际识别动画的各个子帧(例如,参见脚本 动画帧拼贴,它使用此作为“框定”叠加图像的选项)。如果您想添加边框,您应该先 合并 动画,以删除它可能先有的任何 帧优化

框架,添加 3D 风格的边框

-frame”运算符与“-border”非常相似,如果您查看下面生成的第一个示例图像,您会发现它将产生完全相同的结果,只是它使用了“-mattecolor”而不是“-bordercolor”。请注意,在生成框架图像时,仍然使用“-bordercolor”,请参见下文。要正确使用“-frame”,您需要为命令提供四个参数,而不是两个。额外的参数指定了所生成框架的“外部”和“内部”斜面的宽度。以下是一些使用“-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
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
使用多个框架操作也可以产生更奇怪的框架样式。

  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
[IM Output] [IM Output] [IM Output] [IM Output]
默认的“-mattecolor”比“-bordercolor”的默认设置略暗。这也使其能够与 WWW 上网页的默认灰色颜色匹配(早期的浏览器如“mosaic”和“netscape”使用)。(见下文)
虽然“-frame”实际上可能使用“-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]
您甚至可以使用半透明的“-mattecolor”作为框架“-frame”,然后“覆盖”一个有趣的图案(如 分形等离子画布),以产生更彩色的框架。


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]
或者,您可以分别为框架着色(使用特殊的“Dst”合成设置生成),然后将图片覆盖到框架中,一旦您为其着色。但这确实非常棘手。有关使用框架的更高级技巧,请参见 框架技巧

框架和 Alpha 合成

框架与“-border”操作符密切相关。框架不仅使用“-mattecolor”绘制,该操作符还将使用“-bordercolor”设置来定义最初绘制框架的背景。对于没有透明度的图像,“-bordercolor”将不可见,因为它被图像本身覆盖。但对于包含一些透明区域的图像,背景颜色将变得可见。

  magick star.gif  -frame 6x6+2+2 star_framed.gif
[IM Output]
换句话说,“-frame”的作用就像您将图像叠加在具有纯色背景的相框上一样。因此,图像中任何透明的部分将被“-bordercolor”替换,默认情况下为浅灰色。
将框架添加到具有透明度的图像时,默认情况下还会用边框颜色填充图像的透明背景,这一事实引发了 IM 用户和开发团队之间的一些争议。关于此争议的总结在 边框、框架和边框颜色使用 中给出。
如果您希望在加框的同时保留图像的透明度,您有两种解决方案。第一种是使用透明的“-bordercolor”,例如 'none'。

  magick star.gif -bordercolor none  -frame 6x6+2+2  star_framed_none.gif
[IM Output]
另一种解决方案,也是首选方法,是确保将图像添加到框架时保留透明像素。这可以通过使用名为 'Copy' 的特殊“-compose”方法来完成。

  magick star.gif -compose Copy  -frame 6x6+2+2  star_framed_copy.gif
[IM Output]
将“-bordercolor”用作“-border”和“-frame”的背景图像是在 IM 版本 6.1.4 中添加的。在此之前,生成的背景画布由一个黑色画布组成,边框或框架绘制在其上。

这种使用黑色的方式对于“magick montage”命令尤其糟糕,该命令在其内部处理中大量使用内部的“-frame”功能。(参见 蒙太奇背景和透明度处理
您可以看到,“-frame”操作符与“-border”类似,也使用“-compose”设置来定义源图像如何叠加到背景框架上。

  magick star.gif -bordercolor LimeGreen \
          -compose {operation} -frame 6x6+2+2  {result}
[IM Output]
如果您还想在“magick montage”框架中使用“-bordercolor”设置,那么使用 'Copy' 的“-compose”设置变得非常重要。有关更多详细信息,请参见 蒙太奇背景和透明度处理

框架和虚拟画布

边框和虚拟画布 一样,框架也应用在该虚拟画布上的实际图像周围,而不是整个画布周围。


magick rose: -shave 12x0 -repage 64x64+9+9 paged.gif
magick paged.gif -frame 5x5+2+2 paged_framed.gif
[IM Output] ==> [IM Output]
请注意,虚拟画布的大小也增加了边框厚度的两倍,以容纳添加的框架。这当然意味着您不能简单地直接将 框架 添加到典型的 GIF 动画,除非您想实际识别动画的各个子帧(例如,参见 动画帧蒙太奇)。如果您想添加边框,您应该先 合并 动画,以删除它可能首先具有的任何 框架优化

修剪,从图像中删除边缘

-border”或“-frame”操作符的逆操作是“-shave”,如果给出相同的参数,它将删除这些命令添加的空间。

  magick border.gif -shave 10x10 shave.gif
  magick border.gif -shave 10x0  shave_sides.gif
  magick border.gif -shave  0x20 shave_topbot.gif
[IM Output] ==> [IM Output] [IM Output] [IM Output]
关于这三个操作符,主要需要注意的是,它们在图像的相反侧添加和删除空间,而不仅仅是单侧或相邻侧。如果您只想删除图像的一个边缘,那么您需要使用“-chop”操作符。(参见下面的 修剪示例)。与之前一样,所有操作符“-border”、“-frame”和“-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
[IM Output] ==> [IM Output] ==> [IM Output] ==> [IM Output]
使用修剪的替代方法是使用新的 等尺寸切片裁剪 操作符。该操作符的优势在于,与“-shave”不同,它不会修改生成的图像的画布大小。

  magick paged_frame.gif   -crop  1x1-10-10@     paged_tile_shave.gif
[IM Output] ==> [IM Output]
在 IM 版本 v6.6.1-0 之前,对于具有画布偏移(如上所述)的图像,等尺寸切片裁剪是无效的。

范围,直接图像大小调整

经过一些讨论,一个直接调整图像大小的最终大小的操作符被添加到 IM 版本 6.2.4 中。该操作符为“-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
[IM Output] [IM Output] [IM Output] [IM Output]
如您所见,它将用添加到图像的任何新区域的“-background”颜色填充任何新区域。
在 IM 版本 v6.3.2 之前,“-extent”只是将任何新区域的内存清零或直接清为黑色。它没有用“-background”颜色填充这些区域。
此外,在 IM v6.3.2 之后,“-extent”将使用“-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
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
上面最后一个示例表明范围也可以进行居中裁剪,但不需要“-repage”,尽管它确实用当前的“-background”颜色“扁平化”了图像。
您甚至可以使用偏移量,这基本上意味着 范围操作符 仅仅是一个简单的 裁剪,带有背景填充,无论位置如何。

  magick rose: -background skyblue -extent 100x100-15-25 extent.png
[IM Output]
这种根据重力裁剪和扩展图像的能力使得该操作符非常适合填充或裁剪图像,以使其适合特定大小的区域,例如参见 填充/填充缩略图以使其适合 请注意,“-extent”通过使用与 边框框架 操作符相同的“覆盖”技术来工作。因此,默认情况下,将其与包含透明度的图像一起使用将用当前的“-background”颜色替换透明度。

  magick star.gif  -background LimeGreen  -extent 80x80-10-10  star_extent.gif
[IM Output]
再次,解决此问题的办法是设置适当的“-compose”方法,或者将“-background”颜色设置为 'None'。

添加/删除行、列和边缘

拼接,添加行、列和边缘

-splice”操作符是 IM 版本 6 中的新功能,参见 拼接,新的图像操作符创建示例。它基本上提供了将行、列空间添加到图像中间或一个边缘的急需功能。插入的空间颜色来自“-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 Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
如果未设置背景颜色,IM 将尝试从图像本身确定此值。这意味着对于某些图像,它可能是白色(正常的默认值),对于其他图像,它可能是黑色,或者对于 GIF 格式,它可能是保存该图像时设置的任何背景颜色。

这基本上意味着,如果您没有设置“-background”颜色,它的默认值取决于图像,您可能会得到任何东西。

在使用使用它的操作符之前,始终设置“-background”。
现在,虽然将行和列添加到图像中很好,但“-splice”操作符非常适合将空间添加到图像的某个边缘。使用“-gravity”选项和拼接几何设置来确定哪个边缘。

  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
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
拼接最常见的用途之一是在其中添加空间以绘制标签。(参见 标注图像

  magick rose: -gravity South  -background LimeGreen  -splice 0x15 \
           -annotate 0x0 'Rose'    splice_label.gif
[IM Output]

修剪,删除行、列和边缘

-splice”的自然逆操作是更古老的“-chop”操作符。如果给出与“-splice”相同的参数和相同的“-gravity”设置,“-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
[IM Output] ==> [IM Output] ==> [IM Output] ==> [IM Output]
我继续处理最后一个示例,以展示如何反转“-splice”和“-chop”的顺序,以便在不使用绘制或覆盖的情况下从图像的中间“清除”一行或一列(或两者)。修剪更常用于从图像中剪切单个边缘,使用重力选择该边缘。例如...

  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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
作为使用“-chop”删除单个边缘的替代方案,您实际上可以使用更通用的“-crop”操作符。这不需要使用“-gravity”来获取底部或右侧边缘,但需要您在之后“+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
[IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
这依赖于这样一个事实,即如果“-crop”没有给出要移除的图像区域,它将默认使用图像画布的大小(不是实际图像,而是图像的虚拟画布)。这意味着你可以(对于简单的图像)通过仅仅偏移要裁剪的区域来移除图像边缘。使用“-crop”来“砍掉”图像边缘的方法,是由 Don Sheythe 发现并发布的,经过一些讨论,被认为是 IM 的一个“特性”,因此包含在这里。

高级裁剪技术

裁剪到给定的纵横比

您可以裁剪图像以适应特定纵横比,但这很棘手,需要使用一些 DIY 数学技巧。例如,您可以编写一个脚本进行计算,然后进行 裁剪。或者在 IM v6 中,您可以使用 Distort Viewport 进行计算,以在 No-Op Distortion 期间提取图像的所需部分,如 Centered Square Crop 中所述。然而,在 ImageMagick 版本 7 中,您现在可以在像“-crop”和“-extent”这样的命令中直接进行数学计算,从而绕过对“-distort”的误用。这在 IM 开发者论坛 Crop to Aspect Ratio 中有详细讨论。

Trim,'自动裁剪' 操作符

-trim”操作符与上面讨论的非常通用的“-crop”操作符有很密切的关系。但是,它不是提供一个参数,而是尝试移除图像中颜色或透明度没有变化的任何边框或边缘。换句话说,它移除了围绕图像的“无聊”部分。
请注意,在 ImageMagick 版本 5 及更早版本中,自动裁剪操作是通过使用“-crop”操作符的 '0x0' 参数实现的。现在情况不再如此,因为裁剪中的“零”大小参数现在表示“无限”或“图像大小的极限”。

因此,现在对裁剪使用 '0x0' 参数实际上意味着将图像裁剪成瓦片,大小为原始图像画布的大小。换句话说,使用 IM v6,结果将与原始图像相同,或者说是一个“无操作”。

例如,这里我们使用 IM logo,对其进行调整大小,并“修剪”或“自动裁剪”logo 周围所有额外的空间。

    magick logo: -resize 30%    -trim     trim.gif
从上面应该注意到两点。首先,与“-crop”类似,“-trim”将保留图像的画布大小。这意味着可以提取 trim 的数字参数,以允许进一步处理或调整图像处理(参见 Trimming "Noisy" Images,以了解如何执行此操作的示例)。
[IM Output]
这里我们修剪图像,但只列出关于图像修剪部分的结果,而不是实际修剪后的图像。

  magick logo: -resize 30%   -trim  info:-
[IM Text]
但是,如果您不关心这些信息,可以通过使用“+repage”操作符重置图像的页面信息,或者保存为不保存画布信息的格式(例如 JPEG 格式)来丢弃它们。这里我们同时做这两件事,以明确说明我们正在丢弃画布信息。

  magick logo: -resize 30%    -trim +repage    trim_repage.jpg
[IM Output]
需要注意的第二件事是,trim 并没有真正修剪到最终图像的最边缘。这在 logo 图像的右下角尤为明显,在那里我们可以看到脚和阴影与修剪边缘之间有明显的间隙。在这个角落,这里的颜色在数值上与图像的背景颜色不同。因此,即使我们看不到任何实际的图像变化,“-trim”操作符看到了很小的颜色变化,所以它没有像我们预期的那样紧贴图像进行修剪。如果图像全部为单一颜色,那么“-trim”将把图像修剪到一个最小尺寸的单像素透明 Missed Image。这是合乎逻辑的,并防止在图像保持原样时出现更严重的问题。

用特定颜色修剪

-trim”最令人担忧的问题之一,尤其是在自动图像处理脚本中,是 trim 有点不可预测。例如,它不会限制自己只使用一种特定颜色,甚至不会限制自己只使用一种颜色。因此,您应该很容易修剪比您预期的更多内容。例如,让我们对一个简单的条纹颜色图像进行简单的修剪。

  magick -size 32x32 xc:red xc:green xc:blue +append stripes.gif
  magick stripes.gif  -trim +repage   stripes_trimmed.gif
如您所见,“-trim”不仅修剪了一种颜色,而是修剪了两种颜色!在自动脚本中,这可能非常糟糕,会导致意想不到的结果。如果您知道要从图像中修剪的颜色,那么更好的方法是在图像中添加一个宽度为一个像素的“-border”,颜色为该颜色。在本例中,我们将使用 '红色'。

  magick stripes.gif -bordercolor red -border 1x1 \
          -trim +repage   stripes_trim_red.gif
当然,像这样使用“-border”也会改变“-trim”费尽心思保留的画布偏移。因此,如果您查看结果而不移除虚拟画布信息,您会看到图像发生了偏移。
[IM Output] ==> [IM Output] [IM Output] ==> [IM Output]

  magick stripes.gif -bordercolor red -border 1x1  -trim  \
           stripes_trim_red_shifted.gif
[IM Output]
所以,让我们尝试在修剪特定颜色时校正虚拟画布大小(减去 border_widthx2)和偏移量(减去 border_width)。

  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]
请注意,我正在恢复原始图像的画布大小和偏移量,Border Operator 在上面将其放大并移动了。而“-trim”操作本身正确地保留了图像位置。如您所见,这是一个相当笨拙的调整。或者,如果您不关心画布大小(在分层图像中很常见),您可以使用一个更简单的 Relative Repage 来调整图像在放大画布上的位置。

  magick stripes.gif -bordercolor red -border 1x1  -trim  \
           -repage -1-1\! stripes_trim_red_fix2.gif
[IM Output]

只修剪图像的一侧

如您在上面所见,“-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
请注意,我添加了两种不同颜色的条纹!这样一来,如果其中一种颜色与围绕图像的现有边框颜色匹配,那么另一种颜色将继续起作用,以保护另外三条边。另外,只有一种颜色也会被修剪,只留下一个彩色条纹需要清理。以下是将整条边的修剪作为一个命令进行的操作,但对于修剪顶部边缘(条纹添加到底部或“南”边缘)。
[IM Output] ==> [IM Output] ==> [IM Output] ==> [IM Output]

  magick border.gif -gravity South \
          -background white -splice 0x1  -background black -splice 0x1 \
          -trim  +repage -chop 0x1   trim_north.gif
[IM Output]
这里是一个只修剪底部边缘的例子。当然,在前面的示例中使用的“-gravity”设置是不需要的,并且设置默认值为图像的“西北”设置。

  magick border.gif \
          -background white -splice 0x1  -background black -splice 0x1 \
          -trim  +repage -chop 0x1   trim_south.gif
[IM Output]
当然,与边框一样,将额外的颜色拼接到图像上也会改变虚拟图像画布的大小和图层图像的偏移量。同样,这可以使用我们在上一节中展示的相同方法来解决,但这取决于您将额外的颜色添加到哪一侧以保留这些边。

使用模糊颜色选择进行修剪-- 低质量 JPEG 图像

由于 JPEG 是“有损”的,因此图像中的颜色通常不是单一颜色,而是略微变化的不同颜色的色带。因此,“-trim”通常无法用于 JPEG 或真实世界的图像。未来:这里有一个失败的例子因此,您需要告诉 ImageMagick,那些不完全相同但相当接近的颜色应该被视为相同。添加一个很小的“-fuzz”设置将实现这一点。

  magick image.jpg  -fuzz 1% -trim +repage  image_fuzzy_trim.jpg
指定您希望模糊相对于其的特定颜色也是一个好主意。这可以通过使用“-border”操作符专门添加一个该颜色的边框来实现。当然,边框将始终与要修剪的颜色匹配,因此将始终被“-trim”移除。未来:这里有一个模糊边框修剪的例子

修剪“噪声”图像-- 扫描图像

扫描图像也面临着类似的问题,扫描仪通常会产生小的单像素错误,这些错误是由灰尘、污垢、扫描仪的细微变化,或者仅仅是读取器拾取的电子噪声造成的。然而,在这种情况下,像素错误通常太大,以至于一个小 fuzz factor 无法克服,因此需要不同的技术来修剪这些图像。最简单的解决方案,尽管通常最不实际,是对同一图像进行多次扫描,或者对视频静止序列中的多帧进行扫描),然后对结果进行平均以减少干扰。但是,这并不能去除扫描仪上的灰尘斑点,也不能在只有一张图像或一帧可用时提供帮助,这使得这种方法在大多数情况下不切实际。一个实际的解决方案是一个两步解决方案。使用图像的副本,对它进行某种处理,以淡化单像素错误或扫描仪灰尘,同时增强高度对比色块的影响。然后,使用“-trim”处理此副本,并检查它做了什么,然后您可以使用相同的方式“-crop”处理未修改的原始图像。有很多方法可以淡化单像素错误。其中包括“-blur”、“-median”,甚至使用 Basic Morphology Operators 来移除特定的细节,例如文本和细线。这种“模糊”方法提供了两个主要控制
  • -blur”的 sigma 半径,或“-median”的卷积半径,它决定了您要忽略的灰尘斑点的大小。请注意,这两个值都可以是浮点数,因此您可以精细控制应用的模糊量。有关模糊的更多信息,请参见 Blurring Images
  • 第二个控制是“-fuzz”颜色因子,它控制“-trim”操作符匹配的颜色变化量。也就是说,您希望修剪与所需图像的接近程度。
例如,让我们使用一个更小的“logo:”图像。

  magick logo:   -resize 30%   noisy.jpg
在这个小图像中,我们可以将图像中的星星和标题视为我们想要忽略的噪声。上面图像中的星星大约 5 个像素宽,所以我们想使用大约两倍的值,让 trim 基本上忽略它们。
[IM Output]
以下是结果。请注意,在这种情况下,我们不需要图像,只需要图像的画布信息。

  magick noisy.jpg  -virtual-pixel edge -blur 0x15 -fuzz 15% -trim  info:
[IM Text]
您可能需要检查 Virtual Pixel 设置,以确保您使用模糊获得了正确的“边缘效果”。

或者,您可以在模糊图像之前添加一个与背景颜色相同的宽边框,并相应地调整偏移结果。这可能对来自“-blur”和“-trim”运算符的更准确的结果更有利。
从以上结果可以看出,“-trim”在内部使用了“-crop”参数 '89x121+78+23'。这是修剪后的图像的实际大小,以及它在虚拟画布上的偏移量,据推测也是图像中我们寻找的主要(单个)对象的所在位置。
然后,这可以应用于原始图像,该图像尚未被模糊。

  magick noisy.jpg   -crop 89x121+78+23 +repage   noisy_trimmed.jpg
现在我们已经将图像修剪到只有巫师了!
[IM Output]
这可以通过使用一些额外的“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:”输出的“-format”设置的更多信息,请参见图像属性转义
[IM Output]
以上使用 UNIX 命令行 shell 功能的“命令替换”方法,使用反引号 '`...`' 将生成的“-crop”参数插入外部“magick”命令中。

您可以在 Windows 批处理脚本 中执行此操作,使用特殊的 FOR..DO 结构。有关详细信息,请参阅上面的链接。
请注意,虽然巫师的手完全可见,但帽子的尖端并不可见。这是此方法的缺点,它会忽略尖锐的点和精细的细节。但这正是我们最初要求它忽略的内容。
可以通过使用一些FX 转义 来进行数学运算,通过少量扩展(四个方向各 10 像素)来改善修剪区域的方法……

  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]
如果计算出的边界扩展到原始图像之外,裁剪运算符 会自动将其限制在图像边界内。
在 IMv7(使用“magick”命令)中,您可以在一个命令中完成所有操作,将计算出的修剪尺寸保存在设置中供以后使用。

  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]
模糊修剪的另一种方法是使用各种形态学方法 删除图像中不需要的部分,然后修剪以找到原始图像中所需区域的边界。用户HugoRune 需要将图像修剪到高度不同的对比度区域以进行扫描。有关详细信息,请参见IM 论坛讨论