⚠️ 这是一个非官方翻译网站,与 ImageMagick Studio LLC 无关。准确信息请参阅原文(https://usage.imagemagick.org/annotating/index.html)

ImageMagick 示例 -- 为图像添加标注

ImageMagick 示例 前言与索引
标注图像 (标注图像的技巧)

本文介绍在大图像上用文字或其他图像进行标注的多种方法。标注既可以醒目而显眼,也可以含蓄而隐蔽。为图像添加标注的原因多种多样,但通常是出于以下目的:

  • 在图像上标记关于该图像内容的信息。
  • 指出或突出图像的某个方面。
  • 作为版权保护的一种形式,为图像添加版权信息或徽标。

ImageMagick 提供了很多方法来完成这些工作,但并非所有方法都能自己轻松地从手册中找到。本页试图介绍常用的方法。许多具体的手法在其他示例页面中有更详尽的讨论。如果你有兴趣为 GIF 动画添加标注或水印,建议你先通读本文,然后跳到 为 GIF 动画添加标注 作为起步。


标注图像

为图像添加标签的基本问题在于,无论图像是什么样子,都要让文字清晰可读。下面展示了许多方法,其中一些可以扩展以完成更复杂的任务。在这些示例中,我只使用 ImageMagick 的默认字体。建议你根据想要达到的效果,使用不同的字体和点数大小。

在图像下方(或上方)添加标签

连接标签并居中,从 IM v6.4.7-1 起已成为可能,因为 图像连接 现在会为对齐目的而遵循 gravity 设置。 |

  magick dragon.gif   -background Khaki  label:'Faerie Dragon' \
          -gravity Center -append    anno_label.jpg

[IM Output]
通过重新排列图像的顺序,你可以把标签连接到图像上方。 |

  magick dragon.gif   -background Orange  label:'Faerie Dragon' \
          +swap  -gravity Center -append    anno_label2.jpg

[IM Output]
Splice 与 Draw 是一种非常简单的方法:为图像增加额外空间,让我们得以把标签绘制/标注到图像中。 |

  magick dragon.gif \
          -gravity South   -background Plum   -splice 0x18 \
          -annotate +0+2 'Faerie Dragon'   anno_splice.gif

[IM Output]
同样的方法也可以用来在图像上方绘制标签,只需把 gravity 设置的 'South' 换成 'North' 即可。很简单! |

  magick dragon.gif \
          -gravity North   -background YellowGreen  -splice 0x18 \
          -annotate +0+2 'Faerie Dragon'   anno_splice2.gif

[IM Output]
除非作为更复杂的绘图功能的一部分,否则不再推荐使用 "[-draw](https://imagemagick.org/command-line-options/#draw)" 运算符直接在图像上绘制。有关其他文字绘制方法与技巧的更多细节,请参阅 文字的图像处理 一节。 用 Montage 添加标签 ImageMagick 的 montage 命令常被用户忽视,以为它只适合把整个目录的图像展示出来。其实它也提供了一种为图像添加标签的非常简单的手段。 |

  montage -label "Faerie Dragon"  dragon.gif \
          -geometry +0+0 -background Gold anno_montage.jpg

[IM Output]
montage 还能为你给图像添加边框及其他内容,因此这种标签形式在简单标注图像之外还有很多额外的可能性。 |

  montage -label "Faerie Dragon" dragon.gif \
          -font Candice -pointsize 15 \
          -frame 5  -geometry +0+0 anno_montage2.jpg

有关使用 montage 的更多信息,请参阅 Montage,图像阵列[IM Output]
用 Polaroid 添加标签 使用 montage 的一种替代方案,是使用 Polaroid 图像变换 来生成一幅相当花哨的带注释图像。 |

  magick -caption "Faerie Dragon" dragon.gif -gravity center \
           -background black +polaroid anno_polaroid.png

警告:此图像带有一定随机性地被扭曲(弯曲并旋转),因此除非禁用旋转,否则最终图像尺寸会有所不同。它还包含复杂的阴影与透明度效果,因此使用了 PNG 格式的图像来保存结果。 [IM Output]
你可以使用“超级采样(Super Sampling)”技巧来减少旋转在结果图像中造成的“模糊”。相关示例请参阅 Polaroid 图像变换

在图像本身之上添加标签……

直接在图片上写文字的问题在于,你无法确定所选颜色的文字是否清晰可读。绘制的目标图像可能是黑色、白色,也可能是五颜六色。 带轮廓的标签:最简单的方法是给字符串描一圈轮廓,把文字与图像分隔开。不过,由于 "[-stroke](https://imagemagick.org/command-line-options/#stoke)" 字体设置会同时向内和向外为字体增加粗细,会削弱其效果(详见 Stroke 与 StrokeWidth)。为字体绘制背景轮廓更好的办法是把文字绘制两次。 |

  magick dragon.gif -gravity south \
          -stroke '#000C' -strokewidth 2 -annotate 0 'Faerie Dragon' \
          -stroke  none   -fill white    -annotate 0 'Faerie Dragon' \
          anno_outline.jpg

[IM Output]
如你所见,它是有效的,但效果不太好。相比默认的 'Times' 或 'Arial' 字体,使用较粗的字体效果会更好。此技巧的更多细节请参阅 粗描边合成字体绘制暗色框:让标注文字更醒目的更经典的方法,是把要添加文字的区域“调暗”,再用相反的颜色绘制文字。例如…… |

  magick dragon.gif \
          -fill '#0008' -draw 'rectangle 5,128,114,145' \
          -fill white   -annotate +10+141 'Faerie Dragon' \
          anno_dim_draw.jpg

[IM Output]
此方法效果很好,但如你所见,本例中我决定不使用 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 来放置文字,因为调暗的矩形无法用 gravity 定位(这在将来可能会改变)。此外,其尺寸和位置可能取决于图像和最终文字尺寸,这可能需要一些额外的数学计算。 下色框(Undercolor Box):与其自己去绘制背景框,你可以让 ImageMagick 在框上使用“下色(undercolor)”。请参阅 文字下色框。文字的“下色”(如库 API 中所用),在命令行上可以用 "[-undercolor](https://imagemagick.org/command-line-options/#undercolor)" 选项来指定。 |

  magick dragon.gif  -fill white  -undercolor '#00000080'  -gravity South \
          -annotate +0+5 ' Faerie Dragon '     anno_undercolor.jpg

[IM Output]
如你所见,这比自己绘制暗色框简单得多,不过建议在绘制文字的开头和结尾各加一个额外的空格,把框稍微撑大一点。 合成标签:更理想的方案是预先准备好一幅文字图像,再把它作为图像叠加上去。这里我们在半透明背景上创建一个简单的标签,然后叠加它。 |

  magick -background '#00000080' -fill white label:'Faerie Dragon' miff:- |\
    magick composite -gravity south -geometry +0+3 \
              -   dragon.gif   anno_composite.jpg

[IM Output]
最后这种技巧有一些明显的优势。暗色框可以按标签大小来调整尺寸,并且可以用 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 正确地定位它,而无需了解它所添加到的图像、或所用绘制字体的任何具体信息。
而且,你并不局限于只使用简单的暗色框。你可以准备非常复杂的字体图像,既可以预先准备好以便多次应用,也可以针对每幅图像即时生成。几乎所有的 合成字体效果 样式你都能使用,从而让你添加的文字非常出彩、显得专业。自动调整尺寸的标题(Caption):随着 IM v6.3.2 的发布,"[caption:](text.html#caption)" 现在可以自动调整文字尺寸,使其最好地适配特定尺寸的框。 但要在叠加中恰当地利用这一点,你确实需要知道被标注图像的宽度。这里我先获取该信息,然后创建并叠加一个标题,使文字自动调整尺寸以最好地适配所提供的空间,并进行自动换行。 |

  width=`identify -format %w dragon.gif`; \
  magick -background '#0008' -fill white -gravity center -size ${width}x30 \
          caption:"Faerie Dragons love hot apple pies\!" \
          dragon.gif +swap -gravity south -composite  anno_caption.jpg

[IM Output]
这种技巧非常适合把图像评注叠加到图像上,不过在命令行上这么做有其自身的问题,因为你创建的是一幅新图像,而不是在标注一幅旧图像。此问题的解决方案请参阅 用户自定义选项转义 花哨的标签:作为最后一个示例,我将叠加一个用花哨的 柔和轮廓字体 创建的文字字符串,以确保它保持可见,同时又不为该标注创建矩形框。 |

  magick -size 100x14 xc:none -gravity center \
          -stroke black -strokewidth 2 -annotate 0 'Faerie Dragon' \
          -background none -shadow 100x3+0+0 +repage \
          -stroke none -fill white     -annotate 0 'Faerie Dragon' \
          dragon.gif  +swap -gravity south -geometry +0-3 \
          -composite  anno_fancy.jpg

[IM Output]
如果你打算把同一个标签(比如一条版权信息)合成到大量图像上,那么最好单独生成标签,再用 "mogrify" 命令把该标签合成到每幅图像上。上面的 "-geometry +0-3" 偏移用于把合成叠加放得更靠近边缘,因为这幅图像柔和模糊的轮廓往往比所需的更大。
上述所有示例当然都应根据你自己的需求进行调整。不要像绵羊一样随大流。大胆尝试,让你自己的网站或程序拥有与众不同的独特风味。更重要的是,把它告诉 IM 社区。

FUTURE: select the black or white color based on the images relative
intensity.  This uses a number if very advanced techniques.

  magick input.jpg  -font myfont -pointsize 25 \
      \( +clone -resize 1x1  -fx 1-intensity -threshold 50% \
         -scale 32x32 -write mpr:color +delete \)  -tile mpr:color \
       -annotate +10+26 'My Text'              output.jpg

Explanation:  Copy of image is resized to 1 pixel to find the images
average color.  This is then inverted and greyscaled using -fx, then
thresholded to either black or white, (as appropriate).
This single color pixel is now scaled to a larger tiling image, and
saved into a named memory register (mpr:).

The image is then used to set the fill tile, for the annotated text.
Their is however no simple method (at this time) to set the outline -stroke
color of the draw text to its inverse.

Other techniques are to use some text as a 'negate image' mask, or even a color
burn or color dodge compose operation, to distort the image with the text.

叠加图像 ImageMagick 中的 "magick composite" 命令和 "[-composite](https://imagemagick.org/command-line-options/#composite)" 图像运算符,提供了以各种方式把图像放到其他图像之上的主要手段。这些方法的细节在 Alpha 合成 示例页面中给出。不过,还有一些更高层的运算符同样利用了图像的 alpha 合成。它们包括 图像分层,以及本示例页面更靠下的 用 Gravity 定位图像。compose 的默认合成方法是 "Over",它只是把叠加图像叠加到背景图像上,并如你所料地处理透明度。背景图像还决定了结果的最终尺寸,无论叠加图像放在哪里(使用 "[-geometry](https://imagemagick.org/command-line-options/#geometry)" 选项)。无论叠加图像位于中间、半出背景图像之外,还是远在天边,输出图像的尺寸都与背景图像相同。图像的 geometry 位置也会受 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 影响,因此叠加图像的定位可以相对于九(9)个不同位置中的任意一个来定义。请参阅下面的 "定位图像与文字"。除了合成叠加的 "[-geometry](https://imagemagick.org/command-line-options/#geometry)" 之外,单个图像还可以带有页面或画布信息(使用 "[-page](https://imagemagick.org/command-line-options/#page)" 和 "[-repage](https://imagemagick.org/command-line-options/#repage)" 选项设置),这会影响图像的最终位置。不过,这种图像专有信息不受 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 影响。那么进入示例……叠加大概是最常见的图像标注形式,而且做起来非常简单。这里我把一个 32x32 的城堡图标叠加到已准备好的按钮框中央。

  magick composite -gravity center  castle.gif  frame.gif  castle_button.gif

[IM Output] [IM Output] [IM Output]

你也可以精确地定位子图像。这里我们放置一只手,指出妖精龙的小爪子。

  magick composite -geometry +31+105  hand_point.gif dragon.gif \
            dragon_claw_pointed.jpg

[IM Output] [IM Output] [IM Output]

图像具体如何绘制到背景上,由 "[-compose](https://imagemagick.org/command-line-options/#compose)" 设置控制。上面所用的默认值是 "-compose over",它只是把图像叠加到背景上。所提供的其他大多数合成方法,除了在非常特定的情形下都不太好用,但这里介绍其中一些。有关此设置及其效果的更多细节,请参阅 Alpha 合成Bumpmap 是一种颇为微妙的合成方法,它基本上按照叠加图像的亮度来调暗背景图像。叠加图像中凡是白色的部分都会被当作透明处理,而凡是黑色的部分则会在输出图像中变成黑色。这有点像把叠加图像当作墨水印章来使用,这是想象此操作的一种好方式。提示一下,用 bumpmap 叠加在浅色图像上效果最好。因此你可能需要在使用前先准备好 bumpmap 图像。这里我们在使用 "-compose bumpmap" 把龙图像画到纸卷图像上之前,先把它调整尺寸。

  magick composite \( dragon.gif -resize 50% \) scroll.gif \
            -compose bumpmap -gravity center   dragon_scroll.gif

[IM Output] [IM Output] [IM Output]

Bumpmap 也可以用来为图像设置整体效果,在这个例子中,我们把浅色的背景图案平铺到龙的上面。请记住,bumpmap 图像会被当作灰度图像处理,因此我们叠加图像中的任何颜色都会丢失。

  magick composite -compose bumpmap  -tile rings.jpg \
            dragon.gif  dragon_rings.jpg

[IM Output] [IM Output] [IM Output]

| 上面的 "[-tile](https://imagemagick.org/command-line-options/#tile)" 选项只对使用 "magick composite" 命令的合成操作有效。在 "magick" 中,你必须使用 "[tile:](canvas.html#tile)" 图像生成器并配合 "[-size](https://imagemagick.org/command-line-options/#size)" 来指定范围。当然,你可以让作为叠加的源图像比所叠加的背景图像更大,因为结果的尺寸将是背景(即目标)图像的尺寸。
---|---
Multiply 合成方法最为人所知的是它能合并两幅带白色背景的图像(比如叠到一页文字上)。与 'bumpmap' 合成方法不同,它不会预先把叠加图像转成灰度。

  mesgs PictureWords |\
      magick -pointsize 18 text:-  -trim +repage \
              -bordercolor white -border 10x5   text.gif
  magick composite -compose multiply -geometry +400+3 \
            paint_brush.gif  text.gif  text_multiply.gif

[IM Output] [IM Output] [IM Output]

旁注:上面生成 "text.gif" 的复杂命令只是为了创建一幅典型的纯文字图像,"mesgs" 命令只是输出某条特定的引文,就像 "fortune" 那样,但控制更精细。这种方法在很多情形下都很好用,但一般只在其中一幅(任一)图像基本上是白色背景上的黑色(或灰度)时才行。如果两幅图像都包含彩色区域,你可能会得到异常的结果。换句话说,这种技巧非常适合把线条画、图表或文字图像叠加到白色(或相当浅色)的图像上,例如打印或扫描页面的图像。


水印

水印是一项重要的工作,因为它提供了一种把图像标记为属于某个公司或网站的方式。遗憾的是,这会以某种方式破坏图像,对图像本身不利。水印的基本目标是:

  • 无论图像颜色是浅是深,标记都应清晰可见。
  • 它应该难以擦除。
  • 而且它不应让观看者太过厌烦。

这些因素全都相互冲突,这也是水印之所以难以做好的一个原因。

用符号添加水印

最简单也最恼人的水印形式之一,就是在被加水印的图像上某处放置一幅非常小但很特定的图像。这里我们生成了一幅想要加水印的图像(使用 "logo:"),并使用一个小小的“眼睛”符号。

  magick logo: -resize x180  -gravity center  -crop 180x180+0+0  logo.jpg
  magick composite -geometry +160+13 eyes.gif   logo.jpg  wmark_symbol.jpg

[IM Output] [IM Output] [IM Output]

放置这幅小图像最好的思路,是把它添加得看起来真的像是原图的一部分。在上面的例子中,我添加了“眼睛”图像,让它看起来几乎像是巫师帽子的一部分(你也不希望它过度融入图像)。因此,这种技巧需要人工的处理,这使它无法完全自动化。这幅小图像也可能非常难以去除,因为它彻底破坏了所覆盖的那部分图像。而且如果做得好,除非专门去找,否则几乎察觉不到。我在网上很多地方见过它被用得很有效果。某个网站用了一个小小的匕首状符号。当我在其他网站找到的图像上发现同样的匕首符号时,从那个网站盗走的图像就变得非常明显了。 用文字添加水印 只是在图像上绘制文字,也是一种简单的加水印方式,上面 图像上的标签 的任何示例都可以用作一种水印。不过要做好这件事,你应该使用两种不同的颜色,以防文字在不同颜色的背景上绘制时消失。为此,应当使用某种 合成字体效果。 |

  magick logo.jpg  -font Arial -pointsize 20 \
          -draw "gravity south \
                 fill black  text 0,12 'Copyright' \
                 fill white  text 1,11 'Copyright' " \
          wmark_text_drawn.jpg

这样效果很好并且可以自动化,但作为好水印来说太醒目了,因为它从图像中太过突出。 [IM Output]
但通过做一些准备,可以创建一幅透明背景的图像,使其不那么扎眼。有关生成水印文字所用步骤的细节,请参阅 字体遮罩。此外,图像遮罩 中的遮罩示例可能也有助于你的理解。

  magick -size 300x50 xc:grey30 -font Arial -pointsize 20 -gravity center \
          -draw "fill grey70  text 0,0  'Copyright'" \
          stamp_fgnd.png
  magick -size 300x50 xc:black -font Arial -pointsize 20 -gravity center \
          -draw "fill white  text  1,1  'Copyright'  \
                             text  0,0  'Copyright'  \
                 fill black  text -1,-1 'Copyright'" \
          -alpha off stamp_mask.png
  magick composite -compose CopyOpacity  stamp_mask.png  stamp_fgnd.png  stamp.png
  magick mogrify -trim +repage stamp.png

[IM Output]

现在我们有了水印字体,可以把它应用到图像上…… |

  magick composite -gravity south -geometry +0+10 stamp.png  logo.jpg \
            wmark_text_stamped.jpg

如你所见,水印不像之前那么醒目,甚至使用了灰色的浓淡而非纯白和纯黑。即便如此,无论背景是什么,它仍然清晰可见。合成字体效果 页面详细介绍了许多可以这样使用、又不会压过被加水印图像的字体样式。 [IM Output]
你也可以把文字平铺到整幅图像上。这里我们还通过使用命令的“管道”,把一个命令的输出馈送给下一个,从而避免了对中间图像的需要。 |

  magick -size 140x80 xc:none -fill grey \
          -gravity NorthWest -draw "text 10,10 'Copyright'" \
          -gravity SouthEast -draw "text 5,15 'Copyright'" \
          miff:- |\
    magick composite -tile - logo.jpg  wmark_text_tiled.jpg

这利用了这样一个事实:图像(比如照片,而不是图表)通常会有一些区域,其中平铺的文字字符串是可见的。你也许想在自己的水印中把文字做成半透明(比如使用像 "'#80808080'" 这样的半透明灰色)。在下面正规的水印技巧中,你也不妨记着这种平铺技巧。 [IM Output]

用图像添加水印

ImageMagick 还提供了若干选项,特别适合在更大范围内进行更微妙的水印处理。当你说给图像“加水印”时,通常更常指的就是这个。右边是一幅“水龙”图像,我将用它进行这些演示。它带有一些透明度,我用它来检查 IM 在透明度方面是否处理正确,避免结果出现难看的“方块”外观。 [IM Output]
在 IM 版本 6 之前,"-watermark" 和 "-dissolve" 选项在处理叠加图像的 alpha 通道(透明度)方面存在缺陷,会产生一些非常奇怪的效果。
--- ---
Watermark 合成本是为给图像加水印而设计的,虽然它有效,但往往只对纯白和纯黑的叠加图像有效,并会产生难看的边缘伪影。
  magick composite -watermark 30% -gravity south \
            wmark_image.png  logo.jpg    wmark_watermark.jpg

有关此选项的更详细信息,请参阅 Watermark 选项用法 页面。 [IM Output]
Dissolve 被我和其他人发现效果更好。 |

  magick composite -dissolve 25% -gravity south \
            wmark_image.png   logo.jpg  wmark_dissolve.jpg

这效果非常好,但在带有纯白和纯黑像素的图像上,水印的一部分会消失。也就是说,把白色溶入白色、黑色溶入黑色,在最终图像中都不会可见。由于这两种颜色非常常见,最好对水印做一些额外的预处理,让它使用各种灰色浓淡而非纯白和纯黑。(参见下面的“灰化 Dissolve”) [IM Output]
有关此选项的更详细信息,请参阅 Dissolve 选项用法 页面。 平铺(Tiled): 你也可以把水印平铺到整个背景图像上,而不只是加在一个位置。只需把你的 gravity 位置换成 "[-tile](https://imagemagick.org/command-line-options/#tile)" 即可。当然,那样的话你可能想让水印更不显眼。 |

  magick composite -dissolve 15 -tile \
            wmark_image.png   logo.jpg  wmark_tiled.jpg

[IM Output]
灰化 Bumpmap: 要把 bumpmap 恰当地用作水印,需要对图像做一些准备,使用 灰度调整 技巧把白色和黑色都变成较浅的灰色范围。如果不这么做,结果会非常非常醒目。 |

  magick wmark_image.png  -fill Gray91 -colorize 80  miff:- |\
  magick composite -compose bumpmap -gravity south \
            -  logo.jpg    wmark_bumpmap.jpg

[IM Output]
把 bumpmap 用作水印最大的问题在于,此操作只会调暗图像。因此这种技巧对非常暗的图像相当无用。 灰化 Dissolve: 同样的预处理技巧也可以配合 dissolve 方法使用,让水印图像的白色部分在白色背景上略微变暗,同样地,让水印在图像黑色部分上的黑色区域变亮。 |

  magick wmark_image.png  -fill grey50 -colorize 40  miff:- |\
  magick composite -dissolve 30 -gravity south -  logo.jpg wmark_dissolve_grey.jpg

[IM Output]
我要说,作为水印这几乎是理想的,满足了所有要求。不过我会进一步调整最终的 dissolve,让水印更不易察觉。 平铺的灰化 Dissolve: 这与上面完全相同,只是以更低的 dissolve 值平铺到图像上。 |

  magick wmark_image.png  -fill grey50 -colorize 40  miff:- |\
  magick composite -dissolve 15 -tile  -  logo.jpg wmark_dissolve_tile.jpg

[IM Output]
| "magick composite" 命令不知道如何处理动画之类的多图像文件。不过,其他方法确实可以让你做到这一点。有关标注和叠加多图像文件的示例,请参阅 修改动画、标注
---|---


用 Gravity 定位图像与文字

关于“Gravity(重力)”的种种

如你在上面所见,能够在更大的图像中定位图像和文字,与其他任何事情同等重要。自然地,"[-gravity](https://imagemagick.org/command-line-options/#gravity)" 设置是这方面最重要的方面之一。

在 ImageMagick 邮件列表上,Tim Hunter 如此宣称。
“ 在你掌握它的窍门之前,Gravity 会把你逼疯。 ”

这是我由衷赞同的一种感受。 Gravity 只会在以下情况中被应用……

  • 任何涉及类似 'geometry' 设置的操作,例如 "[-crop](https://imagemagick.org/command-line-options/#crop)",以及为 Alpha 合成(包括 多图像分层合成)定位图像的 "[-geometry](https://imagemagick.org/command-line-options/#geometry)"。
  • 它还被用作指定文字对齐的手段,供 "[label:](text.html#label)" 等各种文字生成图像的生成器使用,以及供 "[caption:](text.html#caption)" 等各种文字生成图像的生成器指定文字对齐。
  • "[-annotate](https://imagemagick.org/command-line-options/#annotate)" 文字绘制运算符也用它来进行文字定位和对齐。
  • 最后,"[-draw](https://imagemagick.org/command-line-options/#draw)" 方法在其 'text' 和 "image' 方法中使用它,而且仅在这些方法中使用。

然而,"[-gravity](https://imagemagick.org/command-line-options/#gravity)" 用于以下情形:

  • 任何图像列表或分层运算符,例如 "[-mosaic](https://imagemagick.org/command-line-options/#mosaic)"、"[-flatten](https://imagemagick.org/command-line-options/#flatten)" 以及大多数 "[-layers](https://imagemagick.org/command-line-options/#layers)" 方法,尤其不用于 GIF 动画。所有这些操作都使用更大的虚拟画布上的图像偏移(用 "[-page](https://imagemagick.org/command-line-options/#page)"、"[-repage](https://imagemagick.org/command-line-options/#repage)" 元数据设置来设置)来定位图像。这类偏移始终相对于图像虚拟画布的左上角。此方法中完全不使用对 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 的理解。
  • 其他任何 "[-draw](https://imagemagick.org/command-line-options/#draw)" 方法都不使用 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 进行定位。今后也不太可能这样做,因为在 IM 用于这些低层功能所遵循的 SVG 草案中,"[-gravity](https://imagemagick.org/command-line-options/#gravity)" 并未定义。

这一切意味着什么呢?首先也是最重要的,它定义了 "[-geometry](https://imagemagick.org/command-line-options/#geometry)" 用来相对于图像的边缘、侧边和中心定位叠加文字和图像的原点,而用户无需知道图像的实际尺寸。这是它的主要功能。其次,它定义了叠加对象(文字或图像)相对于所定义的 gravity 点的水平和垂直对齐。例如,在 'East' gravity 下,文字或图像会被放置在所定义点的右侧(右对齐)。从技术上讲,对齐应当是独立于 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 的设置,尽管两者密切相关,但 IM 目前把两者合并为单一设置。目前有一种呼声要把这两个方面分开,使得当 "justification" 设置未定义时,回退到使用当前的 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 设置。如果你发现自己需要这个功能,请(通过邮件列表)向 Cristy 提出请求。如果有足够多的用户提出要求,我相信它终将被实现。

使用 Gravity 定位图像

这是一个使用 gravity 把图像定位到背景上的示例。

  magick composite label:Default                      rings.jpg gravity_default.jpg
  magick composite label:Center    -gravity center    rings.jpg gravity_center.jpg
  magick composite label:South     -gravity south     rings.jpg gravity_south.jpg
  magick composite label:East      -gravity east      rings.jpg gravity_east.jpg
  magick composite label:NorthEast -gravity northeast rings.jpg gravity_northeast.jpg

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

注意,图像的实际位置也会根据 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 设置进行对齐。也就是说,"South" 的 gravity 会把图像居中于更大图像的底部,但在该 gravity 点之上。这一点稍后在文字旋转时会变得更重要。另一件要记住的事是,任何 "[-geometry](https://imagemagick.org/command-line-options/#geometry)" 设置所指定的位置,都是相对于 gravity 放置图像的位置而言的。不仅如此,位置的方向也会被修改,使得位置方向朝内。例如 "-gravity South -geometry +10+10" 会把标签图像更往背景内部移动。也就是说,geometry 位置的 Y 方向被反转了,而 X 方向保持不变。

  magick composite label:Default   -geometry +10+10 \
            rings.jpg gravity_default_pos.jpg
  magick composite label:South     -geometry +10+10 -gravity south \
            rings.jpg gravity_south_pos.jpg
  magick composite label:NorthEast -geometry +10+10 -gravity northeast \
            rings.jpg gravity_northeast_pos.jpg

[IM Output] [IM Output] [IM Output]

你也可以把 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 与 "-draw image" 结合使用,用单条命令放置多幅图像。 |

  magick rings.jpg \
          -gravity Center     -draw "image Over     0,0 0,0 'castle.gif'" \
          -gravity NorthEast  -draw "image Bumpmap  0,0 0,0 'castle.gif'" \
          -gravity SouthWest  -draw "image Multiply 0,0 0,0 'castle.gif'" \
          gravity_image.jpg

[IM Output]
而且,你现在也可以使用 "[-composite](https://imagemagick.org/command-line-options/#composite)" 把图像叠加到背景上…… |

  magick rings.jpg \
          -gravity Center     castle.gif  -compose Over     -composite \
          -gravity NorthWest  castle.gif  -compose Bumpmap  -composite \
          -gravity SouthEast  castle.gif  -compose Multiply -composite \
          gravity_image2.jpg

[IM Output]
有关上面所用 "[-compose](https://imagemagick.org/command-line-options/#compose)" 设置的更多细节,请参阅 Alpha 合成。有关把多幅图像叠加、合并并叠加到单幅图像中的其他方法,请参阅 IM 示例中的 多图像分层 一节。

使用 Gravity 定位文字

对图像来说这一切都很好,但直接在图像上绘制文字又如何呢?其实,与图像相同的基本效果同样适用。如上所述,无论是使用 "[-draw](https://imagemagick.org/command-line-options/#draw)" 的 'text' 方法,还是更好的 "[-annotate](https://imagemagick.org/command-line-options/#annotate)" 文字绘制运算符,gravity 都会影响文字的定位。 |

  magick rings.jpg -resize 120x120  \
          -gravity northwest  -annotate 0 'NorthWest' \
          -gravity east       -annotate 0 'East' \
          -gravity center     -annotate 0 'Center' \
          -gravity south      -annotate 0 'South' \
          -gravity northeast  -annotate 0 'NorthEast' \
          gravity_text.jpg

[IM Output]
定位图像和文字之间有一个非常重要的区别。如果你绘制一个文字字符串,而没有定义任何形式的 "[-gravity](https://imagemagick.org/command-line-options/#gravity)",该字符串将相对于字体的“基线(baseline)”绘制。 例如,我们实际来做一下…… |

  magick rings.jpg -annotate 0 'String' gravity_text_none.jpg

[IM Output]
如果你仔细看,只会看到 'String' 中 'g' 那个小小的环状尾巴出现在结果图像的上边缘。字符串的其余部分被绘制到了背景图像之外。但如果你把 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 设置为 'NorthWest',文字就会像图像一样被定位。也就是说,相对于字体所定义的 边界框或下色框。 例如…… |

  magick rings.jpg -gravity NorthWest -annotate 0 'String'  gravity_text_nw.jpg

[IM Output]
作出这种区分的原因,是为了确保 IM 的文字绘制与 "SVG" 等其他矢量绘图图像格式保持兼容。这些格式不使用 gravity,因此开启 gravity 就是告诉 IM 在绘制文字时遵循与图像放置相同的规则,而不是涉及字体“基线”和文字“起始”点的矢量图形规则。如果你开启了 gravity,之后又想关闭它,可以使用 "[-gravity](https://imagemagick.org/command-line-options/#gravity) none" 或 "[+gravity](https://imagemagick.org/command-line-options/#gravity)" 把它重置回默认的“无 gravity”设置。 让我们施加一个文字偏移,并把 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 的默认 'None' 和 'NorthWest' 两个参数都绘制出来,好让你看到这两种形式关系有多么密切。 |

  magick rings.jpg \
          -gravity NorthWest -annotate +10+20 'NorthWest' \
          -gravity None      -annotate +10+20 'None' \
          gravity_text_pos.jpg

[IM Output]
虽然在这个例子里可能看不出来,但这两个字符串是可能重叠的,尤其是在 'g'、'p' 等字母的下伸部分方面。也就是说,这两个字符串并未按 'pointsize' 单位妥善分隔,而只是按字体的基线高度分隔。最好的做法是不要在你自己的图像处理中混用这两种模式。要么用 gravity,要么不用。选择在你。 使用 Gravity 在左边缘放置文字 作为最后一个示例,这里介绍如何真正沿图像左边缘居中进行标注。这里的问题是,当你旋转文字时,它会围绕文字的“手柄(handle)”旋转。遗憾的是,这个手柄是在文字旋转之前由 gravity 设置的,因此除非你把自己限制在“居中文字”上,否则效果不太好。 [IM Output] 例如,这是一次典型的“初次尝试”,试图把文字定位成沿图像左边缘的中央。当然,它相当出人意料地失败了! |

  magick rings.jpg \
          -gravity West -annotate 90x90+10+0 'String' \
          gravity_text_left_fail.jpg

如你所见,文字被放在了左边缘,但只是让起始点(旋转前“手柄”所在之处)居中而已。这个问题的原因在于,在 IMv7 中,"-gravity" 设置还被直接用来设置文字的“对齐”(它设置用于定位文字的“手柄”)。有一些用 PerlMagick API 编写的、关于 gravity 对旋转文字之影响的动画演示(下载 "[**im_annotation.pl**](../static/img/scripts/im_annotation.pl)")。我还创建了同一程序的 shell 脚本版本 "[**im_annotation**](../static/img/scripts/im_annotation)" 和 "[**im_annotation_2**](../static/img/scripts/im_annotation_2)"。 让这一切奏效的诀窍是:先把整幅图像旋转,然后使用 center south!这是个荒唐的解决办法,但它确实有效。 |

  magick rings.jpg -rotate -90 \
          -gravity South -annotate +0+2 'String' \
          -rotate 90  gravity_text_left.jpg

[IM Output]
另一种方法在下面的 使用 Distort 定位文字 中展示。

使用 Draw 定位文字

虽然在上面我用“文字偏移”相对于 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 点来定位文字,但那并不是唯一的方法。另一种方法是使用 "-draw translate" 选项来定位文字。它的优点在于,你可以在不受 gravity 效果影响的情况下安排文字的位置,同时仍然使用 gravity 来“对齐”文字内部的定位“手柄”。在这些示例中,我添加了一些额外的辅助线(它们同样不受 gravity 影响),以展示位置是如何从图像的中心点施加的。带偏移的文字…… |

  magick -size 100x100 xc:white -gravity Center \
          -fill cyan  -draw 'line 50,50 70,70' \
          -fill red   -draw 'line 68,70 72,70 line 70,68 70,72' \
          -fill blue  -draw "text 20,20 'Offset'" \
          text_offset.jpg

[IM Output]
带平移(translation)的文字…… |

  magick -size 100x100 xc:white -gravity Center \
          -fill cyan -draw 'line 50,50 70,70' \
          -fill red  -draw 'line 68,70 72,70  line 70,68 70,72' \
          -fill blue -draw "translate 20,20 text 0,0 'Translate'" \
          text_translate.jpg

[IM Output]
如你所见,两者产生的实际结果相同。但由于 "-draw text" 要求你给出一个作为其参数之一的偏移,它更常用于从命令行定位所绘制的文字。然而,尽管这两种方法产生相同的结果,但当同时施加文字旋转时,它们会产生完全不同的结果。基本上,这是由于各动作被施加的顺序不同。

绘制旋转文字

定位所绘制文字有两种不同的方式:使用“文字偏移”,或把文字“平移”到最终位置。这两种定位方法的效果,在同时施加旋转时会产生截然不同的结果。原因很复杂,但本质上涉及 IM 如何进行 绘图表面变形。话虽如此,让我们看看用这两种不同的位置来旋转一些文字会发生什么。只有偏移、没有旋转…… |

  magick -size 100x100 xc:white -gravity Center \
          -fill cyan -draw 'line 50,50 70,70' \
          -fill red  -draw 'line 68,70 72,70  line 70,68 70,72' \
          -fill blue -draw "text 20,20 'None'" \
          rotate_none.jpg

[IM Output]
带偏移地旋转文字…… |

  magick -size 100x100 xc:white -gravity Center \
          -fill cyan -draw 'line 50,50 50,78' \
          -fill red  -draw 'line 48,78 52,78  line 50,76 50,80' \
          -fill blue -draw "rotate 45 text 20,20 'Offset'" \
          rotate_offset.jpg

[IM Output]
带平移地旋转文字…… |

  magick -size 100x100 xc:white -gravity Center \
          -fill cyan -draw 'line 50,50 70,70' \
          -fill red  -draw 'line 68,70 72,70  line 70,68 70,72' \
          -fill blue -draw "translate 20,20 rotate 45 text 0,0 'Translate'" \
          rotate_translate.jpg

[IM Output]
这实际上是大多数人想要的。不过偏移旋转对某些特殊效果也可能有用。注意这些 绘图表面变形 的执行顺序与给出的顺序是相反的。旋转先执行,平移后执行。如果你把 'rotate' 和 'translate' 方法调换,你会得到与普通“文字偏移”相同的结果,即一个旋转过的偏移。"[-annotate](https://imagemagick.org/command-line-options/#annotate)" 运算符是专门设计来让定位旋转文字更容易的,它明确要求 IM 带旋转地绘制文字,而不是“进行表面变形”。带旋转和偏移的 annotate…… |

  magick -size 100x100 xc:white -gravity Center \
          -fill cyan -draw 'line 50,50 70,70' \
          -fill red  -draw 'line 68,70 72,70  line 70,68 70,72' \
          -fill blue -annotate 45x45+20+20 'Annotate' \
          rotate_annotate.jpg

[IM Output]
上述示例的问题在于,IMv7 的 "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 设置不仅指背景图像上的位置,也指要绘制的叠加图像中的位置。IMv7 将添加“文字对齐(Text Justification)”,它指的是叠加位置,作为独立于 gravity(背景位置)但与之相关的设置。

使用 Distort 定位文字

Using SRT Distortion with Layering Images, is particularly good method for placing images (or text in images). Basically it allows you complete low level control over both the point at which the image is placed, as well as how the image is to be arranged at relative to that point. To start with here we create a 'text image' with a transparent background and simply 'layer' the image onto the background image. |

  magick rings.jpg -background none label:'Some Text' \
          -flatten  layer_simple.jpg

[IM Output]
As you can see the text simply added to image at top left corner. Lets rotate it using distort (layers variant) -- Not the use of parenthesis to limit what image we distort! |

  magick rings.jpg \( -background none label:'Some Text' \
             +distort SRT 70 \
          \) -flatten  layer_rotate.jpg

[IM Output]
Note that the text position was NOT changed! All that happens was that the distort rotated the text around the center point (the handle), but so that relative to the 'virtual canvas' that point did not move. Thus when the now larger image is Flattened its point of rotation 'the center of the text image' did not move. The next step is to move that handle, but for this we need to use almost the full set of SRT Distortion arguments. Because we want to continue to use the 'center handle' as well we need to use some Image Property Percent Escapes, or more specifically FX Percent Escapes. So lets place the center at '+60+60' in the background image |

  magick rings.jpg \( -background none label:'Some Text' \
             +distort SRT '%[fx:w/2],%[fx:h/2] 1 70 60,60' \
          \) -flatten  layer_translate.jpg

[IM Output]
Another way of moving a 'layer image' is using the Repage Operator. Especially a relative move using a '!' flag. The 'handle' for this is by the nature of layer images, the top left corner. The SRT Distortion Operator will not only translate the image using the handle specified, but can use sub-pixel (floating point) positions for both of those handles. That is, it can distort the text by sub-pixel increments to any location, without the integer restrictions most other operations have. The final example is placing the 90 degree rotated text on the left edge. The handle of the text to rotate around and position will this time be at the be the center bottom of the text, before it was rotated. That is, a calculated position of '%[fx:w/2],%h'. Position on the background image must also now be calculated to be the center left edge, ('0,%[fx:h/2]'). The problem is the SRT Distortion Operator does not have access to the background image when it is distorting the text image. The solution is to do this position calculation when the background image available, and save it into some 'personal setting' which can then be added to the distort arguments. This technique is looked more closely in Extract Information from Other Images. So here is the result. First calculate the position on the background image. Then distort the text image so its 'handle' is also moved to that pre-calculated position. |

  magick rings.jpg -set option:my:left_edge '0,%[fx:h/2]' \
          \( -background none label:'Some Text' \
             +distort SRT '%[fx:w/2],%h 1 90 %[my:left_edge]' \
          \) -flatten  layer_on_left.jpg

[IM Output]
The 'my:' string can be anything that does not clash with existing prefixes. That is, I use it to hold MY settings, separate to any other settings ImageMagick may use for coders or specific options. Prefixing 'my:' is a good choice for this. Percent escapes are handled purely as string substitutions, and in fact we could generate the whole Distort option as a string. The only problem is you can not do math on your 'my:' settings, after they have been set. So any mathematics must be done before hand. This is something that will be looked at for IMv7, so that FX expresions use % escape variables.