ImageMagick 示例 --
画布创建

索引
ImageMagick 示例前言和索引
纯色画布
颜色渐变
稀疏的色点
等离子体图像  
随机图像  
平铺画布
ImageMagick 将画布用作绘图的起始图像、覆盖具有透明区域的图像的背景,甚至只是作为一般图像处理的一部分。它们可以是纯色、一系列颜色,甚至是一个较小图像的平铺。在这里,我们仅介绍一些可用于生成各种画布图像的方法。

纯色画布

直接生成

生成特定颜色和大小的画布非常简单。您只需指定“-size”(如果未指定大小,则默认为“1x1”),然后使用“canvas:”生成给定颜色的画布。如果未指定颜色,则生成'白色'画布。
例如...这里我生成一个'卡其色'的画布。

  magick -size 100x100 canvas:khaki  canvas_khaki.gif
[IM Output]
更常见的是“xc:”(表示“X 常量图像”)的简写(也是更传统的格式)。这通常是我使用的。例如,这是一张使用 X 窗口颜色'小麦色'的图像。

  magick -size 100x100 xc:wheat  canvas_wheat.gif
[IM Output]
使用一些花哨的图像读取修改器,我们可以将纯色画布图像作为单个参数指定。此技术意味着您可以将特定大小和颜色的'xc'画布图像作为单个'输入图像'参数传递给许多 ImageMagick 脚本。

  magick 'xc:Salmon[100x100!]'  canvas_salmon.gif
由于数字是调整大小的值,因此需要'!',否则如果它不是正方形,则不会获得请求的大小。
[IM Output]
如果您已经创建了一个画布,但需要使用其他颜色,则可以使用“-opaque”操作符替换该颜色。

  magick canvas_khaki.gif -fill tomato -opaque khaki canvas_tomato.gif
[IM Output]
您甚至可以从现有图像中获取单个像素,并将其扩展到所需的画布大小。我们使用“-scale”来简单快速地调整单个像素的大小。
这里我们从内置的“rose:”图像中获取玫瑰色。

  magick rose: -crop 1x1+40+30 +repage -scale 100x100\! canvas_rose_red.gif
[IM Output]

创建相同大小的图像

使用 ImageMagick 时,最基本的技术之一是生成与某个现有图像大小相同的画布。这可以通过将现有图像转换为所需的画布来完成,但保留图像的原始大小。通常,不仅需要保留图像的大小,还需要保留所有图像的元数据。例如标签、注释、颜色配置文件、时间延迟,以及保存压缩和深度。如果要将此类信息注释到新清空的画布上,或者计划将原始图像叠加到新画布上,并且需要保留该信息,则元数据可能非常重要。当然,IM 提供了许多方法来做到这一点,通常作为使用各种图像操作的副作用。只有少数方法非常明显地表明它们用于将图像清除为纯色。
左侧是一个测试图像...不用担心我实际上是如何生成此图像的,这对于练习来说并不重要。我确实设计了它以包含一系列颜色、透明度和其他功能,特别是为了在使用时为 IM 提供良好的锻炼。如果您真的对用于生成此图像的命令感兴趣,您可以查看我用来创建它的特殊脚本“generate_test”。 [IM Output]

覆盖特定颜色

从 IM v6.4.2-1 开始,您可以使用“+level-colors”并使用单个颜色且没有逗号来设置所有颜色。

  magick test.png  -alpha Opaque +level-colors Sienna  color_levelc.gif
[IM Output]
请注意“-alpha”操作符的使用,以在添加颜色之前(或之后)将透明度设置为有用的值。或者,您可以使用“-channel All”来确保颜色重置操作也设置透明度通道。另一种较旧的技术是使用“-colorize”来叠加填充颜色,但使用完全不透明的值。但是,在 IM v6.7.9 之前,它不会更改原始图像的 alpha 通道,因此最好先禁用 alpha 通道,使用“-alpha Off”,或者使用“-alpha Opaque”使其不透明,即使您无需它也能获得相同的结果。

  magick test.png -alpha off -fill Chocolate -colorize 100%  
color_colorize.gif
请注意,“-alpha Off”(或旧的等效项“-alpha off”)仅禁用 alpha 通道。如果之后再次将其打开,则会恢复原始 alpha 通道(已保留)。在 IM v6.7.9 之前,使用“-colorize”时会保留 alpha。
[IM Output]
从 IM v6.4.3-0 开始,您可以使用“-sparse-color”操作符将某些点设置为所需的颜色,并使其扩展以覆盖整个图像,使用它提供的任何着色方法(请参见下面的稀疏的色点)。

  magick test.png  -alpha Off \
          -sparse-color Voronoi '0,0 Peru' color_sparse.gif
[IM Output]
一种更通用的方法是使用“-draw”直接将当前图像中的所有颜色重置为当前“-fill”颜色。

  magick test.png -fill Tan -draw 'color 0,0 reset' color_reset.gif
[IM Output]
这是 ImageMagick 版本 5 中推荐的方法。
上述所有“简单”方法的主要缺点是,没有一个简单地将图像重置为当前“-background”颜色。下一组方法利用Alpha 合成来强制各种操作符用所需的颜色替换图像。这些多图像技术与使用“-compose”的操作符一起使用。
例如,您可以使用“-flatten”(请参阅展平到背景示例),它使用“-background”颜色创建画布。

  magick test.png   -background Wheat \
            -compose Dst   -flatten   color_flatten.gif
[IM Output]
上述内容使用'Dst'合成方法仅读取背景画布,并忽略原始图像的像素颜色。
如果您只想获取原始图像的元数据(例如注释或标签数据),但用特定颜色和大小的画布图像替换图像本身,则“-extent”操作符(请参阅Extent,直接图像大小调整)可能是最佳解决方案。同样,使用'Dst'合成方法使其忽略原始图像像素数据,以便仅使用“-background”颜色。

  magick test.png   -background LemonChiffon \
            -compose Dst   -extent 100x100   color_extent.gif
[IM Output]
或者,您可以使用“-border”(请参阅添加边框),使用“-bordercolor”作为颜色源。

  magick test.png   -bordercolor Khaki \
            -compose Dst   -border 0   color_border.gif
[IM Output]
此最后一种方法还具有允许您稍微放大图像画布(相对于原始图像大小)的额外优势。
在 IM 版本 6.1.4 之前的版本中,“-border”生成画布的方法不起作用。在此之前,“-border”操作符生成的背景不是简单的纯色,而是由边框颜色包围的黑色画布。这不太有用。
FX,DIY 操作符”操作符提供了一种更灵活(但非常慢)的画布生成方法。您还需要关闭输入图像的透明度通道,因为默认情况下“-fx”不会触及透明度通道。

  magick test.png -alpha off -fx Gold  color_fx_constant.gif
[IM Output]
-fx”操作符甚至允许您进行一些颜色数学运算。例如,70% 更暗的金黄色...

  magick test.png -alpha off -fx "Gold*.7"  color_fx_math.gif
[IM Output]
上述所有方法不仅可以使用完全不透明的颜色进行填充,还可以使用半透明颜色进行填充。但是,最好确保您的图像事先具有透明度通道。
例如,这里我们创建了一个带有半透明红色的画布。但是,当将其叠加在网页的“蓝色”背景上时,我们会得到一种偏紫红色的颜色。

  magick test.png -alpha set -fill '#FF000040' -draw 'color 0,0 reset' \
            color_semitrans.png
[IM Output]
另请注意,当将“-fx”操作符与透明度一起使用时,您需要将“-channel”设置为修改所有四个'RGBA'颜色通道。

使用选定颜色清空图像

使用原始图像中的颜色来清空图像也是可能的,尽管可能有点棘手。当您想要使用特定像素作为“背景颜色”时,这是一种有用的技术。例如,像素 0,0 是一个常见的选项。[IM 输出]在下面的示例中,我将从内置的玫瑰图像(左侧显示)中的各个像素中选择颜色,同时清空图像。最明显(但速度较慢)的方法是简单地使用“FX,DIY 操作符”来选择要用于颜色清空的像素。

  magick rose: -fx 'p{0,0}'  color_pick_fx.png
[IM Output]
但是,可以通过仅选择一次像素来加快速度。这可以通过使用 fx 公式作为 稀疏颜色 的参数来实现。它可能看起来不太简单,但速度要快得多。

  magick rose: -sparse-color voronoi '0,0 %[pixel:p{40,30}]' 
color_pick_sparse.png
[IM Output]
另一种更复杂的方法是裁剪出那个像素并将其平铺到整个图像上,使用后面在 使用已在内存中的图像平铺 中详细描述的技术。

  magick rose: \( +clone -crop 1x1+64+22 -write MPR:pixel +delete \) \
          -fill mpr:pixel  -draw 'color 0,0 reset' \
          color_pick_draw.png
[IM Output]

  magick rose: -set option:distort:viewport '%wx%h+0+0' \
          -crop 1x1+10+25 +repage     -distort SRT 0 \
          color_pick_distort.png
[IM Output]

其他画布技巧

还有很多其他方法可以生成具有非常特定颜色的画布,但它们都比较晦涩。因此,如果没有一些详细的注释,当您在几个月或几年后查看您的 IM 脚本时,可能不清楚您实际上在做什么。我不推荐这些技术,但如果您使用的是较旧且灵活性较差的 IM 版本,则了解它们很有用。

黑色画布

-threshold”,然后关闭透明通道。
传统上,您可以使用“
 magick test.png -threshold 100% -alpha off black_threshold.png 
[IM 输出]
-level”操作符,对“黑色”和“白色”点使用相同的参数将具有相同的效果。
提供“
 magick test.png -level 100%,100% -alpha off black_level.png 
[IM 输出]
-fx”操作符提供了一种更明显的方法来创建黑色画布,方法是将所有像素清除为零。但是,您还需要重置 alpha 通道以使其完全不透明。
 magick test.png -fx 0 -alpha off black_fx.png 
[IM 输出]
-evaluate”版本应该更快,尤其是在较大的图像上。
但是“
 magick test.png -evaluate set 0 -alpha off black_evaluate.png 
[IM 输出]
-gamma”操作符使图像全部变为黑色。
您还可以误用“
 magick test.png -gamma 0 -alpha off black_gamma.png 
[IM 输出]
[IM 输出]
一种不太明显的方法是使用过少的颜色级别“色调分离”图像,导致仅使用一种颜色,即黑色。
 magick test.png -posterize 1 -alpha off black_posterize.png 
Alpha 操作符
您可以确保图像完全透明,然后使用“extract”提取图像蒙版,使用
 magick test.png -alpha transparent -alpha extract black_alpha.png 
[IM 输出]

白色画布

-threshold”。但是,该值必须为负数,以确保在所有 IM 版本中所有颜色都映射到白色。
传统方法是再次使用“
 magick test.png -threshold -1 -alpha off white_threshold.png 
[IM 输出]
-level”操作符,对“黑色”和“白色”点使用相同的参数将具有相同的效果。
提供“
 magick test.png -level -1,-1 -alpha off white_level.png 
[IM 输出]
-fx”操作符。
当然,您可以使用“
 magick test.png -fx 1.0 -alpha off white_fx.png 
[IM 输出]
-evaluate”版本应该更快,尤其是在较大的图像上。
但是“
 magick test.png -evaluate set 100% -alpha off white_evaluate.png 
[IM 输出]
[IM 输出]
或者取反其他一些黑色画布生成方法。
 magick test.png -posterize 1 -alpha off -negate white_posterize.png 
Alpha 操作符
您可以确保图像完全不透明(没有透明度),然后使用“extract”提取图像蒙版,使用
 magick test.png -alpha opaque -alpha extract white_alpha.png 
[IM 输出]

透明画布

可能您最希望从现有图像中生成的画布是透明画布。然后,您可以绘制和添加内容到此画布,使其符合您的要求,然后将其覆盖到原始图像上。-alphatransparent”操作符(在 IM v6.4.3-7 中添加)。
最快捷的方法是让 IM 直接将图像清除为透明,使用“
 magick test.png -alpha transparent trans_alpha.png 
但是,由于这是一个非常新的添加,因此可能尚未广泛使用。[IM 输出]
Clear' alpha 合成操作符,以及任何覆盖图像(在这种情况下为单个像素“null:”,因为它将被忽略)。
我们可以使用“
 magick test.png null: -alpha set -compose Clear -composite -compose Over \ trans_compose.png 
[IM 输出]
-fill”颜色设置。在这种情况下,使其完全透明。
这里我们使用“-draw matte”操作符用当前“
 magick test.png -alpha set -fill none -draw 'matte 0,0 reset' color_matte.png 
[IM 输出]
-fx”操作符。
我们也可以使用“
 magick test.png -alpha set -channel A -fx 0 +channel trans_fx.png 
[IM 输出]
-evaluate”版本应该更快,尤其是在较大的图像上。
当然,“
 magick test.png -alpha set -channel A -evaluate set 0 +channel \ trans_evaluate.png 
[IM 输出]
-threshold”,但再次将其效果限制在透明通道上。
另一种使图像完全透明的方法是使用“
 magick test.png -channel A -threshold -1 +channel trans_threshold.png 
[IM 输出]
实际上,在这种情况下,我们在数学上处理的是“蒙版”通道,使用阈值将其设置为最大值,而不是像我们对“
-fx”操作符那样设置为零。这就是为什么上面使用“-1”而不是类似于101%' 的值。在上述许多图像结果中,原始图像的原始 RGB 颜色仍然存在,它们只是被设置为透明。例如,这里我们读取上述图像之一,并要求 IM 关闭图像中的蒙版/alpha 通道以使颜色再次可见。

  magick trans_fx.png -alpha off  trans_fx_alpha_off.jpg
但是请注意,并非所有图像文件格式以及极少数图像操作会保留结果图像中仍然存在的半透明 RGB 颜色。
[IM Output]
如前所述,并且值得重复,上述许多方法依赖于图像已经具有 Alpha 通道。如果没有,请使用“-alpha On”添加一个,但在这种情况下,您也可以直接使用“-alpha Transparent”操作符。请参阅控制图像透明度中的示例。

杂项画布着色

除了使用特定颜色外,只有“
-gamma”操作符真正灵活到足以生成任何主/次要颜色的画布。您基本上使用0将通道清零,使用-1将通道值最大化。
例如,这里我生成一个黄色画布...

  magick test.png  -gamma -1,-1,0  -alpha off  yellow_gamma.png
[IM Output]
从 IM v6.4.2 开始,您还可以使用“+level”操作符为所有颜色通道设置特定的灰度级别。

  magick test.png  +level 40%,40%  -alpha off  grey_level.png
[IM Output]

颜色渐变

如您在上面看到的,您可以轻松地创建纯色画布。但有时您需要更有趣的东西。
一个非常有用的图像创建操作符是“gradient:”。例如...

  magick -size 100x100 gradient:  gradient.jpg
[IM Output]
如您所见,默认情况下“gradient:”将创建一个图像,顶部为白色,底部为黑色,并在图像高度上进行平滑的灰色阴影。但它不一定是灰度渐变,您还可以通过指定一种颜色或两种颜色来生成不同颜色的渐变。

  magick -size 100x100  gradient:blue              gradient_range1.jpg
  magick -size 100x100  gradient:yellow            gradient_range2.jpg
  magick -size 100x100  gradient:green-yellow      gradient_range3.jpg
  magick -size 100x100  gradient:red-blue          gradient_range4.jpg
  magick -size 100x100  gradient:tomato-steelblue  gradient_range5.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
请注意,当给定单一颜色时,第二种颜色将是“white”或“black”,无论哪种颜色与给定颜色产生的颜色距离最大。因此,“blue”产生“blue-white”渐变,而“yellow”生成“yellow-black”渐变。“red-blue”渐变在中间显示出一条更深的紫色色带。这种变暗是由正在使用的较暗的非线性 sRGB 色彩空间引起的,尤其是在使用强烈的原色时。有关更多详细信息,请参阅处理真实图像
gradient:”目前仅理解 sRGB 色彩空间颜色表示。因此,您无法使用它在线性 LAB 色彩空间中使用“red-blue”颜色生成更亮、更正确的“紫色”渐变。

这也意味着您无法使用 HSV 色彩空间生成多色“彩虹”渐变。

但是,您可以相对简单地“伪造”此类渐变。请参阅下面的其他色彩空间中的渐变
目前无法以其他角度或涉及两种以上颜色来指定渐变。但是,由于此功能是 SVG 渐变的组成部分,因此这种情况可能会发生变化,并且渐变选项将得到重大改进。
一些特别漂亮的渐变包括...

  magick -size 10x120  gradient:snow-navy          gradient_ice-sea.jpg
  magick -size 10x120  gradient:gold-firebrick     gradient_burnished.jpg
  magick -size 10x120  gradient:yellow-limegreen   gradient_grassland.jpg
  magick -size 10x120  gradient:khaki-tomato       gradient_sunset.jpg
  magick -size 10x120  gradient:darkcyan-snow      gradient_snow_scape.jpg
  [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
从 IM v6.3.1 开始,用于生成渐变的算法现在生成水平均匀的颜色,使得图像中每一行的所有像素都被分配相同的颜色。也就是说,每一行一种颜色。

在此版本之前,“gradient:”操作符的工作方式是忽略图像的宽度,并仅分配下一个颜色增量,从左上角到图像的右下角逐行进行。

结果,渐变主要是一个垂直渐变,就像现在一样,但不是完美的渐变。通常,这一事实仅在特殊情况下(例如测试图像)以及在图像映射中使用时才重要。

请注意,渐变的行为可能会受到以下定义的影响

gradient:angle=角度(以度为单位) 对于线性渐变,这指定了从颜色 1 到颜色 2 的渐变方向,相对于北(向上)以顺时针方向为正。对于径向渐变,这指定了渐变相对于其正常的 X-Y 方向的顺时针方向旋转。在 Imagemagick 6.9.2-5 中受支持。
gradient:bounding-box=WxH+X+Y 将渐变限制在比图像尺寸更大或更小的区域。如果边界框定义的区域小于图像,则颜色 1 将是背景的颜色。在 Imagemagick 6.9.2-5 中受支持。
gradient:center=x,y 指定径向渐变中心点的坐标。默认值为图像的中心。在 Imagemagick 6.9.2-5 中受支持。
gradient:direction= 指定线性渐变的方向朝向顶部/底部/左侧/右侧或对角线角。选项包括:西北、北、东北、西、东、西南、南、东南。在 Imagemagick 6.9.2-5 中受支持。
gradient:extent= 指定以图像为中心的径向渐变的形状。选项包括:圆形、对角线、椭圆形、最大、最小。圆形和最大即使对于半径等于图像半宽和半高较大者的矩形图像,也会绘制圆形径向渐变。圆形和最大选项都等效于默认径向渐变。最小选项即使对于半径等于图像半宽和半高较小者的矩形图像,也会绘制圆形径向渐变。对角线选项即使对于半径等于图像半对角线的矩形图像,也会绘制圆形径向渐变。椭圆选项为矩形图像绘制椭圆径向渐变,其半径等于图像的半宽和半高。在 Imagemagick 6.9.2-5 中受支持。
gradient:radii=x,y 指定渐变的 x 和 y 半径。如果 x 半径和 y 半径相等,则径向渐变的形状将为圆形。如果它们不同,则形状将为椭圆形。默认值为图像半宽和半高的最大值。在 Imagemagick 6.9.2-5 中受支持。
gradient:vector=x1,y1,x2,y2 指定线性渐变的方向,从矢量 1 (x1,y1) 到矢量 2 (x2,y2)。颜色 1 (fromColor) 将位于矢量位置 x1,y1,颜色 2 (toColor) 将位于矢量位置 x2,y2。在 Imagemagick 6.9.2-5 中受支持。

径向渐变

从 IM v6.4.4 开始,您还可以以类似的方式生成径向渐变图像。

  magick -size 100x100 radial-gradient:  rgradient.jpg
[IM Output]
请注意,渐变位于生成图像的中间,并且直径设置为适合图像 X 或 Y 尺寸较大者。因此,如果图像的大小不是正方形,您将获得“裁剪”的径向渐变。

  magick -size 100x60 radial-gradient:  rgradient_clip.jpg
[IM Output]
这使您可以轻松地从中心到角生成正方形径向渐变,方法是使一个边长为 1.42(2 的平方根)倍,然后裁剪它。

  magick -size 100x142 radial-gradient: \
          -gravity center -crop 100x100+0+0 rgradient_crop.jpg
[IM Output]
渐变本身的颜色遵循与旧的线性“gradient:”图像生成器相同的约定。

  magick -size 100x100  radial-gradient:blue              rgradient_range1.jpg
  magick -size 100x100  radial-gradient:yellow            rgradient_range2.jpg
  magick -size 100x100  radial-gradient:green-yellow      rgradient_range3.jpg
  magick -size 100x100  radial-gradient:red-blue          rgradient_range4.jpg
  magick -size 100x100  radial-gradient:tomato-steelblue  rgradient_range5.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

带透明度的渐变

从 IM v6.2.9-8 开始,“gradient:”(以及之后的“radial-gradient:”)图像创建操作符理解透明和半透明颜色的使用。

  magick -size 100x100 gradient:none-firebrick gradient_transparent.png
[IM Output]
在 ImageMagick 6.5.4-7 之前,涉及完全透明的渐变(如最后一个示例)通常会产生黑色光晕。

发生的情况是从给定颜色到特殊颜色“none”或透明黑色生成渐变。结果,颜色会向半透明黑色渐变,然后变得完全透明。

解决此问题的方法是生成透明度渐变,然后使用所需的颜色对其进行着色

  magick -size 100x100 gradient:none-black \
          -fill firebrick -colorize 100% gradient_trans_colorize.png
[IM Output]

直方图调整渐变

您可以通过对线性渐变应用某种形式的直方图调整来创建非线性渐变。例如,您可以使用S 形对比度函数来创建更自然的外观渐变。

  magick -size 100x100 gradient: -sigmoidal-contrast 6,50% \
            gradient_sigmoidal.jpg
[IM Output]
这种类型的渐变尤其适合生成重叠照片,因为它消除了重叠区域开始处的急剧渐变变化。

评估/函数渐变

您还可以使用评估操作符和相关的函数操作符来修改简单的线性渐变。

  magick -size 100x100 gradient: -evaluate cos 0.5 -negate \
            gradient_cosine.jpg
[IM Output]
或者更进一步,在线性渐变的中心创建一个平滑的抛物线峰值。

  magick -size 100x100 gradient: -function Polynomial -4,4,0 \
            gradient_peak.jpg
[IM Output]
或者带状或波纹图案...

  magick -size 100x100 gradient: -function sinusoid 4,-90  \
            gradient_bands.jpg
[IM Output]
这两个密切相关的操作符允许您根据正弦曲线、多项式、对数和幂数学函数修改图像和渐变。有关更多示例,请参阅评估数学函数函数,多参数评估

扭曲渐变

旋转渐变

虽然稀疏颜色方法“重心”(见下文)提供了一种方便的方法来生成任意角度的渐变,但如果您的 IM 版本早于 6.4.3-0,则可能需要使用其他方法来生成对角线或旋转渐变。例如,通过增加渐变图像的大小(乘以 2 的平方根或 1.42),然后将其旋转 45 度,并将图像裁剪到其最终大小,您可以制作对角线渐变。

  magick -size 142x142 gradient: -rotate -45 \
          -gravity center -crop 100x100+0+0 +repage \
          gradient_diagonal.jpg
[IM Output]
从 IM v6.3.5 开始,您可以使用SRT 扭曲以更快、更简单的方式生成旋转渐变。例如,这是一个在 100x100 像素图像中旋转 60 度的 100 像素渐变。

  magick -size 100x100 gradient: -distort SRT 60 gradient_srt.jpg
[IM Output]
这使用了默认的虚拟像素,边缘设置来确保整个图像都被请求的渐变覆盖。您还可以使用专家扭曲视口设置,将渐变映射到更大的图像上,例如在重叠照片中使用。

扭曲渐变

但是您可以使用相同的扭曲方法来执行比简单旋转更多的事情。
渐变也可以扭曲...

  magick -size 100x100 gradient: -swirl 180 gradient_swirl.jpg
[IM Output]
您可以将渐变重新映射到梯形形状。

  magick -size 100x100 gradient: -rotate -90 \
          -distort Perspective '0,0 40,0  99,0 59,0  0,99 -10,99 99,99 109,99' \
          gradient_trapezoid.jpg
[IM Output]
或者使用通用扭曲操作符将渐变包裹成弧线和圆圈...

  magick -size 100x100 gradient: -distort Arc '180 0 50 0' \
          gradient_arc.jpg
[IM Output]

  magick -size 100x100 gradient: -distort Arc '360 0 50 0' \
          gradient_circle.jpg
[IM Output]
尽管新的“radial-gradient:”可能是生成这些渐变的更简单方法。一个非常有用但难以生成的渐变是极角渐变。此渐变的确切形式取决于渐变是否应以偶数尺寸图像或奇数尺寸图像为中心。例如,弧线扭曲可用于生成具有偶数像素尺寸的图像,在本例中为 76 像素。

  magick -size 1x1000 gradient: -rotate 90 \
          -distort Arc '360 -90 50 0' +repage \
          -gravity center -crop 76x76+0+0 +repage  gradient_angle_even.png
[IM Output]
上述中的“-90”设置了“不连续性”的角度,其中“零”和“最大”环绕到相同的值。“50”的值应大于最终裁剪图像大小的一半。请注意我如何使用更长的渐变来生成较小的图像。这提高了结果的整体正确性,尤其是在图像变大时。密切相关的极坐标扭曲也可以生成此类渐变,但由于它可以控制扭曲“中心”的确切位置,因此您可以确保它正确生成奇数像素大小的极坐标渐变图像。在本例中,一个 75 像素的图像(半径 =“36.5”)


  magick -size 1x1000 gradient: -rotate 90 \
          +distort Polar '36.5,0,.5,.5' +repage \
          -transverse  gradient_angle_odd.png
[IM Output]
最后两张图片看起来非常相似,除了大小不同外,但中心像素的处理方式略有不同。仔细观察你会发现,最后一个例子有一个完美的灰色中心像素,而前面的例子没有单个中心像素,而是四个。图像的最终大小由值“36.5”决定,它是所需“75”像素的一半。“.5”偏移量是正确处理极坐标中心的重要方面。请注意,默认情况下,扭曲将不连续点放置在图像顶部,因此横向扭曲会校正不连续点的角度和位置,使其与弧形扭曲产生的不连续点相匹配。这是一个略有不同的变体,它生成一个角度渐变,但带有一个透明的圆形蒙版。

  magick -size 50x1000 gradient: -rotate 90 -alpha set \
          -virtual-pixel Transparent +distort Polar 49 +repage \
          -transverse  gradient_angle_masked.png
[IM Output]
值“49”是半径减 1,因为默认情况下,扭曲会在生成的图像周围添加一个 1 像素的反锯齿缓冲区。因此,最终图像为 100x100 像素。
圆形和渐变可以进行扭曲以产生一些有趣的非线性渐变。例如,使用波浪扭曲使其成弧形可以生成大致呈三角形的渐变。

  magick -size 100x100 radial-gradient: \
          -background black -wave -28x200 -crop 100x100+0+0 +repage \
          gradient_triangle.jpg
[IM Output]
或者是一个非常奇怪的类似鸟类的形状,由圆形顶部边缘的极坐标扭曲生成。

  magick -size 100x100 radial-gradient: \
          +distort Polar '49' +repage \
          gradient_bird.jpg
[IM Output]

通过合成创建渐变

您还可以通过使用各种合成方法组合渐变来修改渐变。例如,您可以使用模加合成方法来生成百叶窗类型的渐变。

  magick -size 100x100 gradient: \( +clone +clone \) \
          -background gray50 -compose ModulusAdd -flatten \
          gradient_venetian.jpg
[IM Output]
甚至可以斜着这样做。

  magick -size 100x100 gradient: \( gradient: -rotate -90 \) \
          \( -clone 0--1 -clone 0--1 \) \
          -background gray50 -compose ModulusAdd -flatten \
          gradient_vent_diag.jpg
[IM Output]
或者通过使用通道复制数学混合合成方法混合两种纯色渐变,可以生成彩色的二维颜色映射渐变。

  magick -size 100x100 gradient:yellow-blue \
          \( gradient:black-lime -rotate -90 \) \
          -compose CopyGreen -composite  gradient_colormap.jpg
[IM Output]

其他颜色空间中的渐变

虽然“gradient:”生成器目前无法在其他一些颜色空间中直接生成渐变(仅创建非线性 sRGB 渐变图像),但您可以将渐变传输到不同的颜色空间以生成有趣的效果。例如……

  magick -size 30x600 xc:red -colorspace HSB \
          gradient: -compose CopyRed -composite \
          -colorspace RGB -rotate 90  gradient_rainbow.jpg
[IM Output]
这首先将高饱和度颜色(“red”)转换为 HSL 颜色空间,可以使用任何饱和度颜色。这会将图像的饱和度和亮度通道正确设置为相应的值。在此之后,生成一个渐变并将其复制到此 HSL 颜色空间图像的“色相”(相当于“红色”)通道中。然后,当我们将 HSL 图像转换回 RGB 时,我们得到了一个完全饱和颜色的完整彩虹渐变。另一种方法是为这些颜色空间之一生成具有正确值的渐变,然后更改图像的颜色空间(使用“-set”)。这会更改颜色空间,而不会更改我们在图像中创建的颜色值。现在,当我们转换回 RGB 时,我们将获得相同的彩虹值。

  magick -size 30x600 gradient:'#FFF-#0FF' -rotate 90 \
          -set colorspace HSB -colorspace RGB \
          gradient_rainbow_2.jpg
[IM Output]
结果实际上与之前的方法完全相同,只是更直接一些,因为我们为所需的色彩空间生成了正确的值,然后设置了这些值所属的色彩空间。在这里,我们采用蒙版的角度渐变(见上文),并将其重新映射到 HSB 颜色空间以生成圆形色相颜色。红色(色相=0)向右旋转,它传统上放置在那里(极坐标角度 0)。

  magick -size 100x300 gradient:'#FFF-#0FF' -rotate 90 \
          -alpha set -virtual-pixel Transparent +distort Polar 49 +repage \
          -rotate 90 -set colorspace HSB -colorspace RGB \
          gradient_hue_polar.png
[IM Output]
与上述类似的示例是色轮,它是通过组合通道图像以及色相和亮度渐变生成的。

调整大小的渐变

Glenn Randers-Pehrson 提出的一个技巧是创建一个非常小的图像,宽两个像素,然后使用“-resize”将其扩展到所需的图像大小。调整大小运算符尝试使放大的图像平滑,使其在更大的比例下看起来更好。我们使用这种平滑来生成非线性渐变。
例如,这里我们使用“便携式位图”(或 PBM 格式)图像生成小图像,并将其馈送到 IM 进行放大。

  echo "P1 1 2   0  1 " | \
  magick - -resize 100x100\!   gradient_resize.jpg
[IM Output]
某些 shell(如“csh”及其变体)无法很好地处理上述调整大小几何设置中的“!”字符,即使在引号中也不行。因此,可能需要使用反斜杠“\”字符。建议谨慎操作。
生成的渐变不是线性的,给定颜色的开始和结束都很平滑,使这些颜色比使用普通渐变时更加突出。渐变遵循的实际函数取决于(并且接近于)调整大小使用的精确重采样滤镜
生成初始两像素图像的一种简单方法实际上是使用渐变本身!这允许您直接指定颜色。当然,这会将您限制在垂直渐变上,除非您也旋转结果。

  magick -size 1x2  gradient:khaki-tomato \
          -resize 100x100\!   gradient_resize2.jpg
[IM Output]
当然,使用此技术您不仅限于一个维度。在这里,我使用一个四像素“便携式灰度图”(或 PGM 图像格式)来生成二维渐变。

  echo "P2 2 2 2   2 1 1 0 " | \
  magick - -resize 100x100\!   gradient_resize3.jpg
[IM Output]
如您所见,与上面的旋转渐变相比,此对角线渐变不是非常线性。
网络便携式位图图像格式非常适合从脚本生成图像。作为一种生成或操作图像数据的方法,它是一个非常值得了解的格式。
如果仔细观察,您还会发现渐变也从放大像素的中心开始,并且没有覆盖从边缘到边缘的整个图像。如果我们使用三角形调整大小滤镜,这一点会变得更加清晰。

  magick \( xc:red xc:blue +append \) \
          \( xc:yellow xc:cyan +append \) -append \
          -filter triangle -resize 100x100\!   gradient_resize4.jpg
[IM Output]
调整大小运算符根据“重采样滤镜”设置平滑这些像素之间的颜色。通过调整滤镜,您可以使调整大小渐变生成更边缘到边缘的效果。

  magick -size 1x2  gradient: \
          -filter Cubic  -resize 100x100\!    gradient_resize5.jpg
[IM Output]
这是一个使用“调整大小”技术创建的粗略“彩虹渐变”。

  magick xc:black xc:red xc:yellow xc:green1 xc:cyan xc:blue xc:black \
          +append -filter Cubic -resize 600x30\! gradient_rs_rainbow.jpg
[IM Output]
使用此方法,您可以为渐变生成使用任何颜色组合和顺序。这使其非常适合生成颜色查找表

插值查找渐变

有关“-interpolate”设置的更多信息,请参见插值设置。生成渐变的另一种方法是使用特殊的插值设置。此设置用于确定当像素查找不是整数时返回的像素颜色,因此不完全匹配特定像素。然后,插值根据包围查找点的像素确定颜色。例如,默认设置“bilinear”将线性地确定落在两个像素之间的查找的颜色。

  magick -size 600x30 xc:   \( +size xc:gold xc:firebrick +append \)  \
          -fx 'v.p{i/(w-1),0}'    gradient_interpolated.jpg
[IM Output]
这里查找 X 位置“i/(w-1)”在第二个两像素图像上从“0.0”到“1.0”。浮点数产生一个完美的线性渐变,就像“gradient:”一样。上面实际上几乎等效于(请参阅完美渐变以了解差异)使用Clut 重新着色图像重新着色渐变图像,使用两个颜色图像的插值查找。

  magick -size 30x600 gradient: -rotate 90 \
          \( +size xc:gold xc:firebrick +append \) -clut \
          gradient_clut_recolored.jpg
[IM Output]
使用此方法还可以生成多色渐变。

  magick -size 30x600 gradient: -rotate 90  -interpolate Bicubic \
          \( +size xc:black xc:tomato xc:wheat +append \) -clut \
          gradient_clut.jpg
[IM Output]
但是,限制是颜色只能以相等间距定义。您不能简单地移动中间颜色的位置,除非大致将输入渐变修改为某种非线性形式,以便移动该中心。对于三个以上颜色的情况,情况变得更糟。以上也是使用双色调对灰度图像进行着色的好方法,并保证精确定义中间色调颜色(与使用色调运算符不同)。
插值查找渐变也可以扩展到二维,并像纯一维渐变一样轻松地生成方形线性渐变(双线性插值)。

  magick \( xc:red xc:blue +append \) \
          \( xc:yellow xc:cyan +append \) -append \
          -size 100x100 xc: +swap  -fx 'v.p{i/(w-1),j/(h-1)}' \
          gradient_bilinear.jpg
[IM Output]
这是相同的示例,但使用Catrom 插值,并使用扭曲运算符而不是非常慢的 FX 运算符生成。

  magick \( xc:red xc:blue +append \) \
          \( xc:yellow xc:cyan +append \) -append \
          -filter point -interpolate catrom \
          -define distort:viewport=100x100 \
          -distort Affine '.5,.5 .5,.5   1.5,1.5 99.5,99.5' \
          gradient_catrom.jpg
[IM Output]
理解上述内容的关键在于,我们正在根据像素的中心放大小图像。有关详细信息,请参阅图像坐标与像素坐标。请注意,大多数插值方法都有等效的插值调整大小滤镜。但是,视口和像素坐标的使用消除了先前调整大小渐变中显示的由非常小图像的极端上采样引起的边缘效应。
网格插值设置不可用作调整大小滤镜。这是一种特殊的二维插值,它将像素内区域划分为两个平坦的线性三角形,以连接具有最小颜色差的角点的对角线为铰链。因此,通过使两种颜色相同,并使用“-interpolate mesh”,您可以生成非常不同的二维渐变。

  magick \( xc:red xc:gold +append \) \
          \( xc:gold xc:green +append \) -append \
          -filter point -interpolate mesh \
          -define distort:viewport=100x100 \
          -distort Affine '.5,.5 .5,.5   1.5,1.5 99.5,99.5' \
          gradient_mesh.jpg
[IM Output]
由于两个对角线上的黄色角点相同,因此使用黄色对角线将它们连接起来。其他颜色线性映射到这些三角形。如果两个对角线颜色不同,则可能会得到不同的对角线划分。

自己制作渐变

FX DIY 运算符允许您根据当前像素位置定义自己的渐变或其他图像生成。由于此运算符需要一个图像才能工作,因此您可以生成自己的渐变或其他图像以匹配该图像。也就是说,您不必知道图像的大小才能为其生成渐变!例如,您可以轻松生成线性渐变,该渐变的大小适合您可能正在处理的图像。

  magick rose: -channel G -fx 'i/w' -separate   gradient_fx_linear.gif
[IM Output]
在生成灰度渐变时,您可以使 -fx 运算符的速度提高 3 倍,只需要求它仅生成一个颜色通道,例如上面示例中的“G”或绿色通道。然后,可以分离此通道以形成所需的灰度图像。这可以表示非常大的速度提升,尤其是在使用非常复杂的“-fx”公式时。
您甚至可以生成一些漂亮的非线性渐变。

  magick rose: -channel G -fx '(i/w)^4' -separate   gradient_fx_x4.gif
[IM Output]

  magick rose: -channel G -fx 'cos(pi*(i/w-.5))' \
           -separate   gradient_fx_cos.gif
[IM Output]
二维圆形线性径向渐变(锥体)怎么样?

  magick -size 100x100 xc: -channel G \
          -fx 'rr=hypot(i/w-.5, j/h-.5); 1-rr*1.42' \
          -separate gradient_fx_radial.gif
[IM Output]
-fx”函数“rr=hypot(xx,yy)”已添加到 IM v6.3.6 中,以加快非常常用的表达式“rr=sqrt(xx*xx+yy*yy)”的速度。这也意味着我们不再需要在创建径向渐变时进行额外的赋值,例如“xx=i/w-.5”。
上面“1.42”(或sqrt(2))的值控制渐变相对于图像尺寸的整体大小。这样,渐变的半径(黑色距中心的距离)就是到角的对角线距离。
您甚至可以从表达式中删除“sqrt()”(内置于“hypot()”函数中)以生成更有趣的球形渐变,这对于3D 着色效果很有用。

  magick -size 100x100 xc: -channel G \
          -fx 'xx=i/w-.5; yy=j/h-.5; rr=xx*xx+yy*yy; 1-rr*4' \
          -separate gradient_fx_spherical.gif
[IM Output]
请注意,我如何使用一些赋值表达式来简化图像中心距离的计算,然后将其转换为渐变。此功能是在 IM v6.3.0 中添加的。
使用高次幂函数,您可以使照片在图像的矩形边缘周围产生淡出效果。调整幂值“4”以控制褪色的量。

  magick -size 100x100 xc: -channel G \
          -fx '(1-(2*i/w-1)^4)*(1-(2*j/h-1)^4)' \
          -separate  gradient_fx_quad2.gif
[IM Output]
这是一个使用直接数学生成的角渐变。

  magick -size 100x100 xc:  -channel G \
          -fx '.5 - atan2(j-h/2,w/2-i)/pi/2' \
          -separate  gradient_fx_angular.gif
[IM Output]
请注意,“atan2(y,x)”函数返回从 -PI 到 +PI 的弧度角(请参阅其手册页),因此其输出需要进行缩放和平移以正确适应 0.0 到 1.0 的颜色范围。这就是为什么上面看起来比实际复杂得多的原因。最后一个示例可以通过扭曲渐变更快地生成。

更复杂的DIY渐变

旁注:此部分是在添加稀疏颜色点之前创建的,并且对它的创建产生了直接影响。当然,FX 函数可以生成颜色渐变。例如,以下是一个基于距离比率的渐变,使用了一个极其复杂的 FX 表达式。

  magick -size 100x100 xc: +size xc:red xc:yellow -colorspace RGB \
          -fx 'ar=hypot( i/w-.8, j/h-.3 )*4;
               br=hypot( i/w-.3, j/h-.7 )*4;
               u[1]*br/(ar+br) + u[2]*ar/(ar+br)' \
          -colorspace RGB gradient_dist_ratio.gif
[IM Output]
图像处理是在线性颜色空间(RGB)中执行的,以避免在混合这种强烈的原色时出现“sRGB 变暗”。有关更多详细信息,请参阅处理真实图像
当从两点变为三点时,每个“控制点”提供多少颜色的比率会稍微复杂一些,并使用一种称为反距离加权 (IDW) 插值的技巧。您可以在维基百科,IDW中查看此方法的更多数学细节。这是一个三点反距离示例。

  magick -size 100x100 xc: +size xc:red xc:yellow xc:lime -colorspace RGB \
          -fx 'ar=1/max(1, hypot(i-50,j-10)  );
               br=1/max(1, hypot(i-10,j-70)  );
               cr=1/max(1, hypot(i-90,j-90)  );
               ( u[1]*ar + u[2]*br + u[3]*cr )/( ar+br+cr )' \
          -colorspace sRGB gradient_inverse.gif
[IM Output]
在这里,我使用了反距离平方,这是 IDW 插值中更常用的方法。这也被称为 Shepard 插值法。

  magick -size 100x100 xc: +size xc:red xc:yellow xc:lime -colorspace RGB \
          -fx 'ar=1/max(1,  (i-50)*(i-50)+(j-10)*(j-10)  );
               br=1/max(1,  (i-10)*(i-10)+(j-70)*(j-70)  );
               cr=1/max(1,  (i-90)*(i-90)+(j-90)*(j-90)  );
               ( u[1]*ar + u[2]*br + u[3]*cr )/( ar+br+cr )' \
          -colorspace sRGB gradient_shepards.gif
[IM Output]
请注意,上述代码中未使用“hypot()”函数,因为不需要生成距离的平方根。现在,上述内容已使用稀疏颜色方法“Inverse”和“Shepard's”实现了。因此,现在可以使用以下方法更简单地完成上述操作……

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color  Inverse '50,10 red  10,70 yellow  90,90 lime' \
          -colorspace sRGB  gradient_inverse_alt.gif
  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color  Shepards '50,10 red  10,70 yellow  90,90 lime' \
          -colorspace sRGB  gradient_shepards_alt.gif
[IM Output] [IM Output]
使用“反距离”或“Shepard 方法”(反平方距离)的问题在于,所有“控制点”都对整个图像产生全局影响。结果,您会在点之间,尤其是在远离所有控制点的大距离处,获得一种底层的“平均颜色”。这反过来会导致颜色“斑点”,而不是平滑的颜色渐变。

DIY渐变和色调
-- (色调难以处理)

旁注:这是一种尝试生成有趣的彩虹效果的失败尝试。它失败了,但我从这次失败中学到了很多东西,现在我将它们呈现给您。上述方法运行良好,但我希望尝试做得更好。我以为也许我可以在点之间生成明亮的彩虹色渐变,而不是生成融合成平均颜色的斑点。因此,为了生成色调渐变,我尝试在 HSB 颜色空间中执行反距离加权插值,尽管我将黄色切换为蓝色,以使颜色在色调周围更加均匀分布,并希望提供另一种生成色轮的方法(参见上文其他颜色空间中的渐变)。

  magick -size 100x100 xc: +size xc:red xc:blue xc:lime -colorspace HSB \
          -fx 'ar=1/max(1,  (i-50)*(i-50)+(j-10)*(j-10)  );
               br=1/max(1,  (i-10)*(i-10)+(j-70)*(j-70)  );
               cr=1/max(1,  (i-90)*(i-90)+(j-90)*(j-90)  );
               ( u[1]*ar + u[2]*br + u[3]*cr )/( ar+br+cr )' \
          -colorspace sRGB   gradient_shepards_HSB.gif
[IM Output]
如您所见,所有颜色都非常明亮,因为我们只生成色调渐变。但是它看起来也很奇怪,这是由“色调”颜色通道的“循环”性质引起的。因此,蓝色和红色之间的区域会通过绿色色调绕很长的路走,而不是通过紫色色调走较短的“模数”路径。经过大量研究,我最终发现了如何通过使用圆形平均值来正确执行上述操作所需的模数数学运算,以计算距离的加权平均值。这涉及将色调作为极角转换为 X 和 Y 矩形坐标。这允许您执行线性数学运算,从而让我们能够适当地执行值的线性加权。然后,结果将转换回角度色调。

  magick -size 100x100 xc: +size xc:red xc:blue xc:lime \
          -colorspace HSB -channel R \
          -fx 'aa=u[1]*2*pi; ba=u[2]*2*pi; ca=u[3]*2*pi;
               ar=1/max(1, hypot(i-50,j-10) );
               br=1/max(1, hypot(i-10,j-70) );
               cr=1/max(1, hypot(i-90,j-90) );
               nr=ar+br+cr;
               mod(atan2( ( sin(aa)*ar + sin(ba)*br + sin(ca)*cr )/nr,
                         ( cos(aa)*ar + cos(ba)*br + cos(ca)*cr )/nr
                       )/(2*pi)+1, 1)' \
          -separate -background white -combine +channel \
          -set colorspace HSB -colorspace sRGB  gradient_circular_mean_hue.gif
[IM Output]
注意:上述操作仅在其色调通道上执行。对于真实图像,我们仍然需要(像往常一样)对饱和度和亮度通道进行操作。如您所见,我们现在得到了红色和蓝色之间正确的渐变,尽管该方法在应用于仅具有较大角度分离的原色时,往往会在中间生成非常突然的渐变变化。也就是说,虽然结果是正确的,但对于色调变化很大的情况,角度色调变化不是线性的。它适用于平均许多接近的色调,但不适用于这些间隔较大的原色。我甚至切换到使用更强的“反向加权”,而不是更常用的“反平方”或“Shepard”方法(见上文),虽然它改进了某些情况,但由于非线性效应,色调变化在中心仍然在压缩。由于输入颜色是恒定的,因此将它们预先转换为色调-x 和色调-y 坐标,在这些通道上执行 Shepard 加权,然后转换回来实际上会使过程更快。也就是说,将颜色从 HSB 颜色空间转换为 Hx、Hy、S、B 颜色空间,以应用该技术。如果这样做,那么中心点以及点之间的渐变将渐变为白色(HSB 颜色空间的中心点)。如果在 HSL 颜色空间中执行此操作,则该区域将渐变为中间色调的灰色。
这种从极坐标色调到 X-Y 坐标的转换在某些方面类似于在非极性 RGB 空间中执行计算,这显示了相同的渐变为灰色的效果(参见前面的示例)。因此,如果通过使用圆形平均值,我们实际上只是将 HSB 颜色空间转换为高度扭曲的 RGB 变体,为什么不直接在线性 RGB 颜色空间中执行任务,并使颜色饱和以生成色调呢!

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color  Inverse '50,10 red  10,70 blue  90,90 lime' \
           -colorspace sRGB gradient_inverse_RGB.png
  magick gradient_inverse_RGB.png -colorspace HSB \
          -channel GB -evaluate set 100% +channel \
          -colorspace sRGB gradient_inverse_RGB_Hue.gif
[IM Output] => [IM Output]
图像处理是在线性颜色空间(RGB)中执行的,以避免在混合这种强烈的原色时出现“sRGB 变暗”。有关更多详细信息,请参阅处理真实图像
如您所见,我们得到了与之前几乎完全相同的结果,但去除了所有复杂的“模数数学”。但是我仍然无法获得起始颜色点之间更线性的色调扩展。所有这一切的寓意是,处理色调很困难,不仅因为“红色不连续性”,还因为颜色间隔很大时发生的非线性效应。最终,结果与我在线性 RGB 空间中直接执行任务并使颜色饱和相同。从本质上讲,虽然 HSB 和 HSL 颜色空间很有趣,但它们不是线性的、真实的或实用的颜色空间。这可能也是为什么很少有操作直接使用色调的原因。

生成完美的渐变(数学上)

生成完美的数学渐变,例如用于傅里叶变换(它是循环的)、图像映射,甚至渐变数学;需要与我们迄今为止看到的渐变不同的特殊渐变。
我的意思是?好吧,这是一个小的 1x5 像素“gradient:”图像,我已缩放,以便您可以看到各个像素的颜色。

  magick -size 1x5 gradient:  -scale 2000% gradient.png
[IM Output]
此图像创建了一个渐变,从最顶行完全“白色”的颜色渐变到最底行的完全“黑色”的颜色。它是一个“理想化”的渐变,通常正是用户想要的,因为它实际上包含用户指定的实际颜色。但是,虽然这是用户期望的,但它不是数学上正确的渐变。如图像坐标与像素坐标中所述,像素实际上具有一个区域,因此图像顶部白色像素表示该像素的中心,而黑色像素表示最底部像素的中心。也就是说,不是图像的边缘,而是距边缘 1/2 像素。从数学上讲,图像从边缘开始。因此,要生成完美的数学渐变,您需要在图像边缘指定像素坐标处的颜色位置。因此,在图像坐标中,位置偏移了 1/2 个像素,并且图像大小恰好是图像中像素的数量(距离),而不是比图像大小小 1 个像素的位置。生成数学上完美渐变的一种方法是使用重心稀疏颜色(将在下一节中详细介绍)来生成完美的边缘到边缘渐变……

  magick -size 1x5 xc: \
          -sparse-color Barycentric '0,-0.5 white  0,%[fx:h-.5] black' \
          -scale 2000%  gradient_math.png
[IM Output]
请注意,使用的坐标从-0.5到图像高度减去0.5,即图像实际边缘的像素坐标。如果您仔细查看结果,您会发现最顶部和最底部的像素不是白色或黑色。像素是渐变在像素中心的颜色。因为此渐变在数学上是正确的,所以在特殊“平铺”或“循环”情况下,此渐变将正确“平铺”。之前的渐变图像将无法正确“平铺”。您会得到一个纯白色像素,旁边是一个纯黑色像素,从而在数学循环中产生一个像素间隙或“不连续”,在纯白色和纯黑色通常被视为等效值的情况下。一个更简单的方法是生成一个“gradient:”图像,该图像长一个像素,然后根据当前的“-gravity”设置从任一端剪切一个像素。
例如,这里剪切了最顶部的白色像素,因为在最终结果中黑色像素(或零值)通常更理想。

  magick -size 1x6 gradient: -chop 0x1 -scale 2000%  gradient_chopped.png
[IM Output]
然后可以根据需要旋转生成的渐变图像,以生成以后图像处理所需的图像。但是,虽然此渐变将正确“循环”,但颜色的实际位置并不完全正确。但在许多情况下,这已经足够好了。如果您需要“完美的渐变”,我建议您使用稀疏颜色渐变。**总之...** 对您想要从渐变中获得的内容进行一些思考,可以极大地提高最终结果的准确性。但如果无关紧要,那么不必担心,使用最适合手头任务的方法即可。

稀疏颜色点

IM v6.4.3-0 中添加的“-sparse-color”运算符将获取一个图像,并在给定的每个浮点“x,y”坐标处设置给定的颜色。也就是说,格式如下所示……
-sparse-color {method}  'x,y color   x,y color   x,y color ...' 
然后,其余像素(根据“-channel”设置限制)将根据它们与这些孤立颜色点之间的关系进行映射,以便在这些点之间平滑颜色。方法定义了该关系将是什么。当然,定义中间颜色应该是什么以及选择哪种方法有很多方法,您选择哪种方法实际上取决于您想要实现的目标。它实际上也可以被归类为二维插值(参见插值,维基百科)的完全自由形式版本。图像放大或调整大小实际上是它的一个专门的子集,但您从一个完整的固定像素网格开始进行放大。不幸的是,很少有专门设计用于处理点网格的调整大小过滤器插值方法可以直接转换为一组自由形式的稀疏分离颜色点。也就是说,调整大小涉及不完整的网格根本不起作用。这也与“地理信息系统 (GIS)”方法相关,在这些方法中,景观是使用稀疏分离的高度点(很少位于严格的网格中)测量的,其余的景观由这些孤立点确定。在类似的情况下,气象学通常具有孤立的气压和温度点,然后需要对其进行插值。通常,在插值之后,地图将被进一步处理以生成显示等值点(高度、压力、温度)的“等值线”,从而生成几乎每个人都熟悉的各种天气图。在这种情况下,您可以将生成的图像视为输入数据的简单灰度“高度图”,或者甚至所有三个变量同时生成,每个变量对应一个单独的图像“通道”。

重心(三角形渐变)

Barycentric” 方法将仅三个点映射到一个线性的彩色三角形中。三角形外的颜色与之前保持一致。我已经用一个小圆圈标记了输入点,因此您看到的颜色都是由稀疏颜色运算符生成的插值结果。

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color  Barycentric '30,10 red   10,80 blue   90,90 lime' \
          -colorspace sRGB  -fill white -stroke black \
          -draw 'circle 30,10 30,12  circle 10,80 10,82  circle 90,90 90,92' \
          sparse_barycentric.png
[IM Output]
图像处理是在线性颜色空间(RGB)中执行的,以避免在混合这种强烈的原色时出现“sRGB 变暗”。有关更多详细信息,请参阅处理真实图像
如果给定四个或更多点,将对所有给定点执行“最佳拟合”,因此实际点可能无法获得为这些点指定的精确颜色。但是要注意,渐变不会“停止”,而是在这些点之外继续变化。传统上,重心渐变将限制在用于生成它的点的包络三角形内。例如…

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color Barycentric '30,10 red   10,80 blue   90,90 lime' \
          -colorspace sRGB  -fill white -stroke black \
          \( -size 100x100 xc:black -draw 'polygon 30,10  10,80  90,90' \) \
          -alpha off -compose CopyOpacity -composite \
          -draw 'circle 30,10 30,12  circle 10,80 10,82  circle 90,90 90,92' \
          sparse_bary_triangle.png
[IM Output]
这是 Fred Weinhaus 提供的一个更快版本,它在 alpha 通道中创建了一个三角形蒙版,默认情况下,稀疏颜色运算符不会更新该蒙版(由于默认通道设置)。但是,所有颜色,包括完全透明的像素,都仍然填充了颜色,只是 alpha 蒙版。

  magick -size 100x100 xc:none -draw "polygon 30,10  10,80  90,90" \
          -colorspace RGB \
          -sparse-color Barycentric '30,10 red   10,80 blue   90,90 lime' \
          -colorspace sRGB   sparse_bary_triangle_2.png
[IM Output]
上面使用的三角形蒙版由于 draw 绘制形状周围的额外线条的方式,导致大小超出 1/2 个像素。有关详细信息,请参阅Draw 填充边界。在生成渐变的三角形网格时,这可能是一个问题。
barycentric” 方法实际上是将线性仿射方程分别映射到三个颜色通道中的每一个。因此,如果我分离上面三个点示例的每个颜色通道,您将在每个颜色通道中获得三个简单的线性渐变。

  magick sparse_barycentric.png -separate sparse_bary_%d.gif
[IM Output] => [IM Output] [IM Output] [IM Output]
只有因为使用了原色,上述渐变才全部平行于三角形的某一条边映射。这并不是典型的情况。但是,您始终会在图像的每个单独通道中获得一个简单的线性渐变,以及在 3D 颜色空间中获得一个平坦的值平面。

重心坐标和双色渐变

三角形重心渐变的这种平行效果实际上非常有用。如果将两个点设置为相同的颜色,则这两个点将定义它们与另一个彩色点之间的渐变“角度”。例如,通过使两个点为“red”,渐变将平行于这两个“red”点…

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color  Barycentric '30,10 red   10,80 red   90,90 lime' \
          -colorspace sRGB  -fill white -stroke black \
          -draw 'circle 30,10 30,12  circle 10,80 10,82  circle 90,90 90,92' \
          sparse_bary_gradient.png
[IM Output]
这是同一个示例,但其中一个角度控制点已移动,以显示它是如何设置渐变角度的。

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color  Barycentric '50,70 red   10,80 red   90,90 lime' \
          -colorspace sRGB  -fill white -stroke black \
          -draw 'circle 50,70 50,72  circle 10,80 10,82  circle 90,90 90,92' \
          sparse_bary_gradient_2.png
[IM Output]

对角线渐变

这提供了一种简单的方法,可以使用两种颜色生成任何线性对角渐变。例如,这是一种非常好的创建对角渐变的方法,从一个角到另一个角,适用于任何大小的输入图像。

  magick -size 600x60 xc: -colorspace RGB \
          -sparse-color barycentric '0,0 skyblue  -%w,%h skyblue  %w,%h black' \
          -colorspace sRGB diagonal_gradient.jpg
[IM Output]
并与另外两个角对齐…

  magick -size 600x60 xc: -colorspace RGB \
          -sparse-color barycentric '0,%h black  -%w,0 black  %w,0 skyblue' \
          -colorspace sRGB diagonal_gradient_2.jpg
[IM Output]
即使对于像上面这样的长图像,这些“对角渐变”也会产生自然美观的渐变。研究三个颜色点的位置,特别是定义两个角之间渐变角度的两个相同颜色的点。请注意,在这两种情况下,其中一个点甚至不位于图像本身内!还要注意使用百分比转义使位置自动调整到正在绘制渐变的图像的大小。

两点渐变

如果只给定两个颜色点,IM 将为您生成第三个点,以便两个原始点之间的角度垂直。结果是在您有很大控制权的简单线性渐变。

  magick -size 100x100 xc:  -colorspace RGB \
          -sparse-color  Barycentric '30,10 red  90,90 lime' \
          -colorspace sRGB  -fill white -stroke black \
          -draw 'circle 30,10 30,12  circle 90,90 90,92' \
          sparse_bary_two_point.png
[IM Output]
但是,当应用于非常“宽”或“高”图像(高纵横比)的角时,两点渐变的效果并不好。基本上,渐变没有对角线对齐,这与上面的三点渐变不同。它是倾斜的,但倾斜程度不足以使其“有趣”。

  magick -size 600x60 xc: -colorspace RGB \
          -sparse-color barycentric '0,0 skyblue  %w,%h black' \
          -colorspace sRGB  sparse_bary_two_point_wide.jpg
[IM Output]

双线性(4 点渐变)

此方法将一个方程拟合到 4 个点,跨越所有三个颜色通道,以在点之间以及之外产生均匀的颜色渐变。

  magick -size 100x100 xc:  -colorspace RGB \
    -sparse-color Bilinear '30,10 red  10,80 blue  70,60 lime  80,20 yellow' \
    -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_bilinear.png
[IM Output]
您可以通过获取上面的图像并分离各个颜色通道渐变来查看此“4 点拟合”。

  magick sparse_bilinear.png -separate sparse_bilin_%d.gif
[IM Output] => [IM Output] [IM Output] [IM Output]
请注意,该方程如何产生曲线(实际上是二次曲线)。但是,如果 4 个点形成平行线,则生成的渐变将变为线性。当 4 个点与正交(矩形)网格对齐时,此方法实际上等效于双线性插值方法(请参阅下面的插值查找渐变)。如果给定的点少于 4 个,则上述函数将被 3 点“Barycentric”方法(请参阅上文)替换。如果给定的点超过四个,它将对所有点进行最佳拟合,因此可能实际上不会匹配指定点处的给定颜色。不建议这样做。

Voronoi(最近颜色)

Voronoi” 方法只是将每个像素映射到您提供的最近颜色点。这基本上将图像划分为每个点周围的一组多边形“单元格”。例如…

  magick -size 100x100 xc:  -colorspace RGB \
    -sparse-color  Voronoi '30,10 red  10,80 blue  70,60 lime  80,20 yellow' \
    -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_voronoi.gif
[IM Output]
如您所见,没有尝试对每个点周围的彩色“单元格”进行抗锯齿处理。每个单元格的边缘实际上正好位于每个点最近邻居的中间。例如,这可以用来生成蒙版,以各种方式分割图像。只需将一个点指定为白色,其余所有点指定为黑色,即可从图像中提取单个“单元格”。如果要平滑(抗锯齿)结果,则可以使用某种形式的超级采样来平滑图像。例如,生成一个 4 倍大的图像,然后“-scale”将其缩小到所需的大小。

  magick -size 400x400 xc: -colorspace RGB \
    -sparse-color Voronoi '120,40 red 40,320 blue 270,240 lime 320,80 yellow' 
\
    -scale 25%  -colorspace sRGB -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_voronoi_ssampled.png
[IM Output]
所有图像处理都在线性颜色空间(RGB)中执行,以避免在混合如此强烈的原色期间发生“sRGB 变暗”。有关更多详细信息,请参阅处理真实图像
更简单的方法(虽然不太好)是简单地稍微模糊图像…

  magick -size 100x100 xc: -colorspace RGB \
    -sparse-color Voronoi '30,10 red  10,80 blue  70,60 lime  80,20 yellow' \
    -blur 1x0.7  -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_voronoi_smoothed.png
[IM Output]
通过大量模糊生成的图像,您可以在生成的“单元格”之间设置一些非线性渐变。

  magick -size 100x100 xc:  -colorspace RGB \
    -sparse-color  Voronoi '30,10 red  10,80 blue  70,60 lime  80,20 yellow' \
    -blur 0x15  -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_voronoi_blur.png
[IM Output]
-blur”越大,各个“单元格”之间的渐变越大。但是要注意,这可能无法保留小的彩色单元格,或者无法确保原始点保持给定的颜色,如果它靠近不同颜色的边缘(以及另一个点)。通过使用 Fred Weinhaus 开发的一种特殊的“线性模糊”技术,您可以生成单元格之间固定宽度的线性渐变。

  magick -size 100x100 xc: -colorspace RGB \
    -sparse-color  Voronoi '30,10 red  10,80 blue  70,60 lime  80,20 yellow' \
    -blur 10x65535  -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_voronoi_gradient.png
[IM Output]
未模糊的输出也可以传递到各种边缘检测技术以生成各种有界边缘。您可以通过光栅到矢量转换器重新映射图像以生成矢量线。但是我发现默认的“autotrace”设置可能需要使用“-corner-threshold 120”进行调整,以便更好地检测角点。

Shepards(彩色斑点)

Shepards” 方法使用到每个给定点的距离的平方反比的比率来确定画布上每个点的颜色。有关数学运算方式的示例,请参阅上面的更复杂的 DIY 渐变。这有点像在每个点上都有彩色聚光灯,这些聚光灯相互作用,因为光线扩散到无穷远处所有给定颜色的均匀平均值。

  magick -size 100x100 xc: -colorspace RGB \
    -sparse-color  Shepards '30,10 red  10,80 blue  70,60 lime  80,20 yellow' 
\
    -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_shepards.png
[IM Output]
图像处理是在线性颜色空间(RGB)中执行的,以避免在混合这种强烈的原色时出现“sRGB 变暗”。有关更多详细信息,请参阅处理真实图像
通过用类似的颜色包围特定区域,您可以生成该特定颜色的平台,尽管边缘点之间的边界可能会“泄漏”,并且“平台”的中心可能会下陷形成浅碗(取决于到其他颜色点的距离)。此方法也用于生成位移场,例如Shepards 图像扭曲中使用的位移场。在这种情况下,映射的是 X 和 Y 位移矢量,而不是颜色 R、G、B 值。

Inverse(清晰的彩色点)

Inverse” 方法实际上与“Shepards” 相同,只是它使用了给定点的更直接的反距离加权。有关数学运算方式的示例,请参阅上面的更复杂的 DIY 渐变。这是 ImageMagick 版本 6.6.9-7 中的一个后期添加。例如…

  magick -size 100x100 xc: -colorspace RGB \
    -sparse-color  Inverse '30,10 red  10,80 blue  70,60 lime  80,20 yellow' \
    -colorspace sRGB  -fill white -stroke black \
    -draw 'circle 30,10 30,12  circle 10,80 10,82' \
    -draw 'circle 70,60 70,62  circle 80,20 80,22' \
    sparse_inverse.png
[IM Output]
如您所见,它生成清晰的彩色点,这些点迅速融合到背景“平均颜色”中。与生成圆形斑点(颜色点周围颜色“平坦”)的Shepards 方法相比。但是,它在生成所有控制点形成一条线的线性渐变时效果更好。也就是说,用于沿图像中特定线生成一维渐变。但是还有一点需要说明。这些彩色点的下降速度到接近“平均”水平的速度由它们的接近程度控制。将两个点光源放置在一起,它们下降得很快,它们之间的距离越远,各个颜色的影响结果就越大。

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color Inverse '45,45 red  55,55 lime' \
          -colorspace sRGB  -fill white -stroke black \
          -draw 'circle 45,45 45,47  circle 55,55 55,57' \
          sparse_inverse_near.png
  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color Inverse '30,30 red  70,70 lime' \
          -colorspace sRGB  -fill white -stroke black \
          -draw 'circle 30,30 30,32  circle 70,70 70,72' \
          sparse_inverse_far.png
[IM Output] [IM Output]
此外,如果您“重复”特定点(完全在或靠近彼此)并使用相同或相似的颜色,您将使该颜色点强度加倍。

  magick -size 100x100 xc: -colorspace RGB \
          -sparse-color Inverse '30,30 red  75,65 lime  65,75 lime' \
          -colorspace sRGB -fill white -stroke black \
          -draw 'circle 30,30 30,32  circle 75,65 75,67  circle 65,75 65,77 ' 
\
          sparse_inverse_stronger.png
[IM Output]
这些效果也适用于“Shepards” 方法!

Shepards 幂因子

ShepardsInverse 稀疏颜色方法实际上是相同的,但对反距离权重应用了不同的“幂级”(分别为 2.0 和 1.0)。从 IM v6.8.0-10 开始,您可以使用操作定义shepards:power”设置此幂级,该定义将由“Shepards” 方法使用。例如

  magick -size 100x100 xc: -colorspace RGB -define shepards:power=0.5 \
     -sparse-color Shepards '30,10 red  10,80 blue  70,60 lime  80,20 yellow' 
\
     -colorspace sRGB -fill white -stroke black \
     -draw 'circle 30,10 30,12  circle 10,80 10,82' \
     -draw 'circle 70,60 70,62  circle 80,20 80,22' \
     sparse_shepards_pow0.5.png
  magick -size 100x100 xc: -colorspace RGB -define shepards:power=1 \
     -sparse-color Shepards '30,10 red  10,80 blue  70,60 lime  80,20 yellow' 
\
     -colorspace sRGB -fill white -stroke black \
     -draw 'circle 30,10 30,12  circle 10,80 10,82' \
     -draw 'circle 70,60 70,62  circle 80,20 80,22' \
     sparse_shepards_pow1.png
  magick -size 100x100 xc: -colorspace RGB -define shepards:power=2 \
     -sparse-color Shepards '30,10 red  10,80 blue  70,60 lime  80,20 yellow' 
\
     -colorspace sRGB -fill white -stroke black \
     -draw 'circle 30,10 30,12  circle 10,80 10,82' \
     -draw 'circle 70,60 70,62  circle 80,20 80,22' \
     sparse_shepards_pow2.png
  magick -size 100x100 xc: -colorspace RGB -define shepards:power=3 \
     -sparse-color Shepards '30,10 red  10,80 blue  70,60 lime  80,20 yellow' 
\
     -colorspace sRGB -fill white -stroke black \
     -draw 'circle 30,10 30,12  circle 10,80 10,82' \
     -draw 'circle 70,60 70,62  circle 80,20 80,22' \
     sparse_shepards_pow3.png
magick -size 100x100 xc: -colorspace RGB -define shepards:power=8 \
     -sparse-color Shepards '30,10 red  10,80 blue  70,60 lime  80,20 yellow' 
\
     -colorspace sRGB -fill white -stroke black \
     -draw 'circle 30,10 30,12  circle 10,80 10,82' \
     -draw 'circle 70,60 70,62  circle 80,20 80,22' \
     sparse_shepards_pow8.png
[IM Output]
power 0.5
[IM Output]
power 1.0
(inverse)
[IM Output]
power 2.0
(shepards)
[IM Output]
power 3.0
[IM Output]
power 8.0
如您所见,“彩色斑点”从非常清晰的点扩展到圆形斑点,再到较大的彩色区域。在非常高的幂级下,它最终将再现与Voronoi 稀疏颜色方法相同的模式。此-define 不仅影响Shepards 稀疏颜色,而且还会对基于稀疏颜色方法生成的计算位移图的Shepards 扭曲方法产生类似的影响。但是,它不影响Inverse 稀疏颜色方法,该方法始终使用 1.0 的幂级。

稀疏颜色方法总结

以下是各种 4 点“-sparse-color” 图像,以便进行比较。
[IM Output]
Voronoi
[IM Output]
Voronoi(模糊)
[IM Output]
Shepards
[IM Output]
Inverse
[IM Output]
双线性
以下是各种 3 点方法的总结。
[IM Output]
Voronoi
[IM Output]
Voronoi(模糊)
[IM Output]
Shepards
[IM Output]
Inverse
[IM Output]
重心
目前,只有“Voronoi”、“Shepards” 和“Inverse” 方法适用于四个以上的点。计划添加更多“-sparse-color” 方法。如果您有任何想法,请给我发邮件。

通道和稀疏颜色

-sparse-color” 运算符受 “-channel” 设置的影响,这意味着您可以使用该设置将其效果限制为单个通道,或扩展到透明通道。您还可以使用 “-channel” 设置通过仅对一个通道进行操作来加速灰度图像的处理,然后 “-separate” 该通道(有关更多详细信息,请参阅 通道处理)。例如..

  magick -size 100x100 xc: -channel G -sparse-color Shepards \
              '30,10 gray70  10,80 black  70,60 white  80,20 gray(33.3333%)' \
          -separate +channel    -fill white -stroke black \
          -draw 'circle 30,10 30,12  circle 10,80 10,82' \
          -draw 'circle 70,60 70,62  circle 80,20 80,22' \
          sparse_shepards_gray.gif
[IM Output]
从 IM v6.6.8-5 开始,未修改的通道将被保留,因此您现在可以使用 稀疏颜色 和 “-channel” 设置快速轻松地为任何图像添加透明渐变。例如,这里我添加了一个透明的 对角线渐变,它与内置的 “rose:” 图像的对角线对齐,使 50% 的透明度位于对角线上。

  magick rose: -alpha set -channel A \
          -sparse-color Barycentric \
                 '0,0 opaque   %w,-%h opaque    %w,%h transparent' \
          rose_alpha_gradient.png
[IM Output]
颜色 'Opaque' 只是 'Black' 的另一个名称。基本上,当您真正只对指定完全不透明的颜色感兴趣时,而实际颜色本身并不重要时,就会使用它。颜色 'Transparent' 也是如此。我本可以分别使用 'White' 和 'None'。
在 IM v6.6.8-5 之前,任何未被 “-channel” 设置选择的通道都将重置为零(黑色)值。这严重限制了它的有效用途。
稀疏颜色 还接受标准化的浮点数而不是颜色名称。需要提供多少个值来替换颜色名称取决于当前的 “-channel” 设置,以及该通道在正在处理的图像中是否“活动”。最简单的方法是将处理限制在一个通道上。另请注意,当使用原始数字而不是颜色名称时,透明度值是“遮罩”值(0=不透明),而不是“alpha”值(1=不透明)(对于 IMv7)。因此,在上面,我本可以使用数字而不是颜色名称...

  -channel A  -sparse-color Bilinear '0,0 1.0   -%w,%h 1.0    %w,%h 0.0'
这在编程脚本和 API 中可能更容易处理,这些脚本和 API 可能无法访问“颜色名称”转换器。

稀疏颜色作为填充操作符

创建 稀疏颜色运算符 的最初原因之一是,您可以提供一个仅包含少量固定颜色点的图像,并据此“填充”其余未定义的颜色。例如,这里我绘制了一些像素。“+antialias” 设置被专门关闭,因此没有绘制半透明或混合颜色,因此图像仅包含指定的四个确切颜色,而没有其他颜色。

  magick -size 100x100 xc:none +antialias -fill none -strokewidth 0.5 \
          -stroke Gold        -draw "path 'M 20,70  A 1,1 0 0,1 80,50'" \
          -stroke DodgerBlue  -draw "line 30,10  50,80" \
          -stroke Red         -draw "circle 80,60  82,60" \
          sparse_source.gif
[IM Output]
现在,我们可以提取此图像中存在的少量非透明像素,然后使用多点稀疏颜色方法“Shepards”填充所有其他颜色。

  magick sparse_source.gif txt:- |\
    sed '1d; / 0) /d; s/:.* /,/;' |\
      magick sparse_source.gif -alpha off \
              -sparse-color shepards '@-' sparse_fill.png
[IM Output]
上面的 “sed” 命令采用 枚举文本文件格式,删除第一行标题和任何包含透明度的行,然后将其重新格式化为像素坐标和颜色的列表。然后,该列表通过 “稀疏颜色运算符” 使用特殊的 “@-” 参数进行“管道传输”。是的,上面非常棘手,但有效。至少对于少量点来说。但是,提供的点越多,操作速度就越慢。这是因为 稀疏颜色 在其处理中是“点”导向的,而不是图像或 形态学 导向的。最终,我希望能够提供一组形态学导向的“填充孔”方法,您可以在其中按原样提供上述图像并使其自动填充透明区域。这种点提取技术可以与 EdgeIn 形态学方法 结合使用,以提取对象或孔边缘周围的像素,以便您可以“填充”缺失的背景或孔(如 形态学和通道 中所示)。例如...

  magick figure.gif -channel A -morphology EdgeIn Diamond 
shape_edge_pixels.gif
  magick shape_edge_pixels.gif txt:- |\
    sed '1d; / 0) /d; s/:.* /,/;' | \
     magick shape_edge_pixels.gif -alpha off \
             -sparse-color shepards '@-' shape_edge_in_lights.png
  magick shape_edge_in_lights.png figure.gif -composite shape_in_lights.png
[IM Output] => [IM Output] => [IM Output] => [IM Output]
请注意,生成的图像与输入图像完全相同,但透明背景被距离模糊的“边缘颜色”替换了。这就是图像边缘变得不清晰的原因。此图像是专门开发的,用于尝试生成更好的“边缘羽化”技术。有关其他羽化技术,请参阅 模糊羽化距离羽化

稀疏颜色 Shepards,模糊替代方案

使用 “-sparse-color” 的另一种方法是获取透明背景上的像素图像,并 模糊 它。之后,透明度将被丢弃。

  magick sparse_source.gif   -channel RGBA -blur 0x15 \
          -alpha off  sparse_blur_simple.png
[IM Output] => [IM Output]
问题在于原始颜色没有保留,并且您还面临着应使用什么“sigma”值的难题。此外,它没有考虑每种颜色的“接近”程度,因此两个靠近的颜色像素(小于“sigma”值)会互相淹没,并变得模糊在一起。
更好的方法是生成多层模糊图像,这些图像具有逐渐减小的“sigma”值,以及顶部的原始未模糊图像。

  for sigma in  64 32 16 8 4 2 1 0;  do
    magick sparse_source.gif -depth 16 \
            -channel RGBA -blur 0x$sigma miff:-
  done |
    magick - -background none -flatten -alpha off sparse_blur_layered.png
[IM Output] => [IM Output]
这种分层模糊技术等效于对同一图像使用“Shepards”方法的结果,虽然不完全一样,但非常接近。但是,当涉及大量输入像素时,它可能快得多,因为它面向图像(形态学),而不是使用单个点进行计算。另一种分层模糊方法是使用 调整大小 生成模糊图像的“金字塔”。此技术在 使用调整大小进行大模糊 中有详细说明。

  magick sparse_source.gif \
          \( +clone -resize 50% \) \
          \( +clone -resize 50% \) \
          \( +clone -resize 50% \) \
          \( +clone -resize 50% \) \
          \( +clone -resize 50% \) \
          \( +clone -resize 50% \) \
          \( +clone -resize 50% \) \
          -layers RemoveDups -filter Gaussian -resize 100x100\! -reverse \
          -background None -flatten -alpha off    sparse_blur_pyramid.png
[IM Output]
这对于非常大的图像来说速度非常快,无需为每个模糊步骤使用大的“sigma”值(因此非常慢)。从本质上讲,它使用更快的图像调整大小技术来生成先前示例中的模糊图层。它不那么精确,但会生成正确结果的良好近似值。但是,它最适合方形图像,并且大小为 2 的幂,否则精度会降低。上面特殊的运算符 “-layers RemoveDups” 将删除由多个“克隆-调整大小”操作生成的任何额外的“单个平均像素”图像。然后,使用 高斯调整大小滤镜(相当于模糊)将图像调整回原始大小。然后反转图像顺序,以便将原始图像放在顶部,并将更模糊的图层放在下面,然后像以前一样合并在一起。它具有仅需读取一次图像的优点,所有工作都在单个命令中完成。它即使对于大型图像也能非常快速地工作,尤其是在调整大小每次只将图像减半时,从而避免了使用非常大的 sigma 的缓慢模糊。此方法的唯一缺点是,您需要大致了解图像的原始大小以恢复“模糊”图像,并至少大致了解要生成多少调整大小的克隆(Log2 最大尺寸,加 1)。但是,过度调整大小的克隆不会对性能造成重大影响,因为当输入图像已被调整大小到最小的 1 像素图像时,调整大小只会变成“无操作”。然后,使用 “-layers RemoveDups” 自动处理额外且无用的“调整大小的图像图层”。唯一真正的问题是,当处理大小不是 2 的幂的图像时,调整大小的图像可能会“不同步”。这个问题的严重程度尚不清楚,但应该不会太大,因为这些图像也是最模糊的。当然,它仍然存在“Shepards”方法的“泄漏”问题,所以让我们更详细地了解一下这个问题。

Shepards 方法“泄漏”

Shepards” 方法不了解“边界”,因此某些“颜色线”远端的颜色会泄漏或“渗透”到该线后面。最终在较大的距离处,您将获得所有像素的纯平均颜色。这并不总是期望的结果(尽管在某些情况下是期望的结果)。在此示例中,“Red” 曲线越接近“White” 线,颜色就越会穿过这两条线到远端,产生粉红色。

  magick -size 100x100 xc:none +antialias -fill none -strokewidth 0.5 \
          -stroke Red    -draw "path 'M 26,0  A 55,61 0 0,1 26,100'" \
          -stroke White  -draw "line 50,0  50,100" \
          sparse_lines_near_source.gif
[IM Output]

  magick sparse_lines_near_source.gif txt:- |\
    sed '1d; / 0) /d; s/:.* /,/;' |\
      magick -size 100x100 xc: -sparse-color shepards '@-' \
              sparse_lines_near.png
[IM Output]
颜色的这种泄漏是使用 Shepards 方法 进行“填充孔”的主要问题,尤其是在涉及多个孔时,因为一个孔涉及的颜色可以并且会泄漏到完全不同的孔中并影响其颜色。反之亦然。对边界的理解构成了 Shepards 方法 与另一种形式的颜色“填充孔”即“颜色扩散”之间的区别。基本上,对于“颜色扩散”,颜色不能穿过某些其他已定义颜色的线。这是通过将效果限制在“视线”中的颜色或围绕边缘泄漏的颜色来实现的。这需要使用到最近颜色的距离来限制哪些颜色会影响像素。“颜色扩散” 的一个主要用途在 扩散曲线 网站上介绍。这不仅大量使用了颜色扩散,还包含了快速生成扩散的技术信息。我希望将来能够将其应用到 ImageMagick 中。

等离子体图像

等离子体渐变

虽然渐变提供了平滑的颜色范围,但另一个图像创建运算符“plasma:”提供了不同类型的渐变。一种非常适合为图像生成随机颜色背景的渐变。首先,我应该指出“plasma:”是一个随机图像。因此,它可以在每次运行时生成不同的图像。例如,这里我们生成三个单独的“标准”等离子体图像,并且每个图像都彼此不同,即使使用相同的命令生成它们。

  magick -size 100x100  plasma:  plasma1.jpg
  magick -size 100x100  plasma:  plasma2.jpg
  magick -size 100x100  plasma:  plasma3.jpg
[IM Output] [IM Output] [IM Output]
您还可以看到,等离子体图像也是一种随机颜色渐变,并且像“gradient:”一样,从顶部的白色开始,底部为黑色。没有很好地记录的是,您可以像上面线性渐变一样为等离子体渐变指定颜色。

  magick -size 100x100  plasma:blue              plasma_range1.jpg
  magick -size 100x100  plasma:yellow            plasma_range2.jpg
  magick -size 100x100  plasma:green-yellow      plasma_range3.jpg
  magick -size 100x100  plasma:red-blue          plasma_range4.jpg
  magick -size 100x100  plasma:tomato-steelblue  plasma_range5.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
您还可以看到,诸如“tomato”和“steelblue”之类的中间色调比“red”和“blue”之类的纯色效果更好。通过对等离子体使用相同的颜色两次,您可以生成一个主要为该颜色的背景,但带有接近原始颜色的随机色斑。

  magick -size 100x100  plasma:black-black          plasma_black.jpg
  magick -size 100x100  plasma:grey-grey            plasma_grey.jpg
  magick -size 100x100  plasma:white-white          plasma_white.jpg
  magick -size 100x100  plasma:yellow-yellow        plasma_yellow.jpg
  magick -size 100x100  plasma:tomato-tomato        plasma_tomato.jpg
  magick -size 100x100  plasma:steelblue-steelblue  plasma_steelblue.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
同样,正如您所看到的,中间色调会在生成的图像中生成更多种类的颜色,而不是极端颜色,如黑色、白色或黄色。上面“grey” 等离子体特别不错,呈现出彩虹色的“珍珠母”效果,基本上因为灰色在“plasma:”将生成的色彩方面具有完全的自由度。

将一个完美的50%灰度等离子体进行标准化处理,会产生一个特别均匀的多色等离子体图像,覆盖全色域,包括白色和黑色。

  magick -size 100x100  plasma:grey50-grey50 -auto-level plasma_grey_norm.jpg
[IM Output]
或者,您也可以只扩展颜色的对比度,使其更鲜明,但不要过度。

  magick -size 100x100  plasma:grey50-grey50 \
                       -sigmoidal-contrast 8x50%   plasma_grey_contrast.jpg
[IM Output]
将此图像与下面的“分形等离子体”图像进行比较。

分形等离子体

等离子体生成器还具有特殊的分形模式,可以产生色彩丰富的效果。生成的色彩得到增强,以产生更夸张的色彩变化。

  magick -size 100x100  plasma:fractal  plasma_fractal1.jpg
  magick -size 100x100  plasma:fractal  plasma_fractal2.jpg
  magick -size 100x100  plasma:fractal  plasma_fractal3.jpg
[IM Output] [IM Output] [IM Output]
事实上,这与我们已经看到的恒定颜色等离子体图像非常相似,实际上,它们是通过相同的方式生成的,但颜色变化更加明显。
我经常发现等离子体图像有点“噪点”。因此,它们通常会受益于使用“-blur”进行一些平滑处理。
在这里,我已经消除了上面中间等离子体图像的噪点。

  magick plasma_fractal2.jpg  -blur 0x2  plasma_smooth.jpg
[IM Output]
您可以使用“-paint”创建随机的彩色斑点。

  magick plasma_fractal2.jpg  -blur 0x1 -paint 8  plasma_paint.jpg
[IM Output]
或者使用“-emboss”图像操作符使颜色更鲜明和圆形,在使用“-blur”去除低水平噪点之后。

  magick plasma_fractal2.jpg  -blur 0x5 -emboss 2 plasma_emboss.jpg
[IM Output]
通过使用“-blur”然后使用“-sharpen”,您可以产生比使用“-emboss”产生的更柔和的色彩图案。

  magick plasma_fractal2.jpg  -blur 0x5 -sharpen 0x15 plasma_sharp.jpg
[IM Output]
我发现生成螺旋等离子体渐变作为背景图案特别漂亮。

  magick -size 160x140  plasma:fractal \
          -blur 0x2  -swirl 180  -shave 20x20  plasma_swirl.jpg
[IM Output]

灰度等离子体

现在,等离子体生成器总是会生成颜色,即使是在纯黑色实色上。但是,生成纯灰度等离子体通常很有用。嗯,有两种简单的方法可以做到这一点。
最简单的方法是获取等离子体图像并将其转换为灰度。

  magick -size 100x100 plasma:fractal -blur 0x2 \
          -colorspace Gray   plasma_greyscale.jpg
[IM Output]
另一种方法是将其中一个颜色通道复制到其他两个通道上,以获得更强烈的单层效果。

  magick -size 100x100 plasma:fractal -blur 0x2 \
          -channel G -separate   plasma_grey_copy.jpg
[IM Output]
最后一种技术是在等离子体上使用“-shade”。

  magick -size 100x100 plasma:fractal -blur 0x5 \
          -shade 120x45  -auto-level  plasma_grey_shade.jpg
[IM Output]
您可能会认为会得到很多明暗效果,但原始等离子体是如此随机,以至于“-shade”似乎只能产生更多“斑驳的等离子体”效果。您可以使用恒定颜色等离子体方法创建灰度等离子体,而不是使用具有高度夸张颜色变化的分形等离子体。作为副作用,此方法还可以控制生成的灰度等离子体图像的整体亮度。

  magick -size 100x100 plasma:black-black \
           -blur 0x2 -colorspace Gray plasma_grey0.jpg
  magick -size 100x100 plasma:grey25-grey25 \
           -blur 0x2 -colorspace Gray plasma_grey1.jpg
  magick -size 100x100 plasma:grey50-grey50 \
           -blur 0x2 -colorspace Gray plasma_grey2.jpg
  magick -size 100x100 plasma:grey75-grey75 \
           -blur 0x2 -colorspace Gray plasma_grey3.jpg
  magick -size 100x100 plasma:white-white   \
           -blur 0x2 -colorspace Gray plasma_grey4.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
如果这还不够鲜明,请使用通道复制方法将等离子体图像灰度化。

  magick -size 100x100 plasma:black-black   \
          -blur 0x2  -channel G  -separate   plasma_grey5.jpg
  magick -size 100x100 plasma:grey25-grey25 \
          -blur 0x2  -channel G  -separate   plasma_grey6.jpg
  magick -size 100x100 plasma:grey50-grey50 \
          -blur 0x2  -channel G  -separate   plasma_grey7.jpg
  magick -size 100x100 plasma:grey75-grey75 \
          -blur 0x2  -channel G  -separate   plasma_grey8.jpg
  magick -size 100x100 plasma:white-white   \
          -blur 0x2  -channel G  -separate   plasma_grey9.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
这些灰度等离子体图像对于进一步处理非常有用,允许您生成其他图像效果。例如,查看有关背景图像的页面,其中包含大量使用等离子体分形产生许多有趣效果的示例。

播种或重复等离子体图像

请记住,“plasma:”可以生成近乎纯黑色或纯白色或任何其他颜色的区域(尽管不太可能是纯色)。虽然不太可能得到全部为一种颜色的图像,但这也是可能的结果。因此,当您获得良好的结果时,您可能希望保存它以备后用。因此,使用等离子体图像的脚本可能希望包含生成和重复使用此类随机图像的选项。也就是说,您可能希望将等离子体图像生成与使用该图像的其他部分分开,以允许重复使用。
然而,一个更简单的技术是“播种”或初始化IM随机数生成器,以便“plasma:”生成相同的“随机”图像。这样,您可以调整脚本或程序以反复产生良好或有趣的颜色或效果。

  magick -size 100x100 -seed 4321  plasma:    plasma_seeded.jpg
[IM Output]
上图永远不会改变,因此,除非我更改“-seed”数字,否则我将始终在右下角有一个“红色”区域。有趣的是,使用相同的种子和不同的初始化颜色渐变可以生成一组图像,虽然是随机的,但在其内部图案上是相似的。

  magick -size 100x100 -seed 4321 plasma:grey-grey         plasma_rnd1.jpg
  magick -size 100x100 -seed 4321 plasma:white-blue        plasma_rnd2.jpg
  magick -size 100x100 -seed 4321 plasma:green-yellow      plasma_rnd3.jpg
  magick -size 100x100 -seed 4321 plasma:red-blue          plasma_rnd4.jpg
  magick -size 100x100 -seed 4321 plasma:tomato-steelblue  plasma_rnd5.jpg
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
如您所见,所有上述图像中都存在相同的颜色模式,尽管底层颜色基底可以突出显示或隐藏共享模式的一部分。最后提醒一下。其他IM操作符也可以使用随机数生成器,例如“-fx”的“rand()”函数、“-virtual-pixel”的“random”设置、“-random-threshold”抖动操作符以及“-noise”操作符。因此,最好在您特定使用随机数生成器之前立即播种生成器。从IM v6.3.4-3开始,您还可以使用“+seed”重新随机化生成器。因此,将此设置放在您的“已播种等离子体”之后将确保任何后续操作符在需要时正确生成随机结果。默认情况下,IM启动时会随机化种子,因此您通常不需要使用“+seed”自己随机化它以获得随机结果。

使用等离子体的问题

使用“plasma:”图像时应避免的一个问题是使用高纵横比生成它们。它往往会扭曲正常的等离子体颜色效果,将颜色拉伸成针状条纹。

  magick -size 200x50 plasma:  plasma_high_aspect.jpg
[IM Output]
对此没有简单的解决方法,因此,除非这是您想要的,否则建议谨慎使用。等离子体图像中也存在明显的左上到右下的对角线扭曲,这是不应该存在的。也就是说,算法中存在某种“空间偏差”缺陷。例如,正如Thomas Maus <thomas.maus_AT_alumni.uni-karlsruhe.de> 指出的那样,如果您镜像并追加相同的等离子体图像,您将始终在生成的图像中看到一个明显的“V”……

  magick -size 60x60 plasma: \( +clone -flop \) +append plasma_flaw.jpg
[IM Output]
这种情况不应该发生。但是,这个问题似乎太深奥了,无法修复,除非基本上完全重写整个等离子体生成器函数。

随机图像

原始随机噪声

从IM v6.3.5开始,您可以使用噪声生成器“+noise”方法“Random”从现有图像生成纯随机图像。

  magick -size 100x100 xc:   +noise Random   random.png
[IM Output]
如果您的IM版本早于此版本,您仍然可以使用速度较慢的DIY FX操作符-fx”生成纯随机噪声图像。

  magick -size 100x100 xc: -fx 'rand()'   random_fx.png
[IM Output]
或者为了速度,您可以使用“-spread”操作符随机化渐变(三个颜色通道分别随机化)或使用其他一些图像。

  magick -size 100x100 gradient: -separate \
          -virtual-pixel tile   -spread 200   -combine  random_spread.png
[IM Output]
结果可能看起来非常随机,但它会产生更受控的颜色范围(或仅颜色值)。

随机斑点(像素尘埃)

生成散布的随机像素图像也可能非常有用。只需记住,随机图像的三个颜色通道中的每一个都可以被认为是单独的随机灰度图像,并且可以以各种方式将这些通道合并在一起。
例如,您可以通过首先阈值化颜色通道(“G”或绿色通道)并将其分离为灰度图像来生成随机点的蒙版。

  magick random.png  -channel G -threshold 5% -separate \
          +channel -negate    random_mask.png
[IM Output]
由于每种颜色都是线性随机值,因此上述使用的阈值百分比直接定义了所选像素的密度。您可以更进一步,使用一个颜色通道(“G”或绿色通道)从另一个颜色通道(“R”或红色通道)中选择随机值,方法是使用各种图像合成方法。

  magick random.png   -channel G -threshold 5% -negate \
          -channel RG -separate +channel \
          -compose Multiply    -composite   random_black.png
  magick random.png   -channel G -threshold 5% \
          -channel RG -separate +channel \
          -compose Screen      -composite   random_white.png
  magick random.png   -channel G -threshold 5% -negate \
          -channel RG -separate +channel \
          -compose CopyOpacity -composite   random_trans.png
[IM Output] => [IM Output] [IM Output] [IM Output]
这些类型的图像可以直接用于生成闪光动画。但是进一步的处理,尤其是在黑色背景版本上,将允许您根据其灰度强度放大点或从这些点生成条纹和/或星光。有关示例,请参见恒星生成器就像已播种等离子体图像一样,您也可以使用“-seed”设置来预初始化随机数生成器。这允许您针对特定机器重复生成相同的随机图像,就像您可以对等离子体图像一样。

模糊随机图像(随机斑点)

现在,虽然您可以直接使用随机图像来创建斑点效果,但纯随机图像通常不是很有用。但是,通过模糊纯随机图像,您将引入一些“邻域”顺序,使得附近的像素变得相关。例如,这里我只是模糊了一张随机图像,导致随机值产生更大的“斑点”或杂色颜色。

  magick random.png -virtual-pixel tile  -blur 0x1  -auto-level  random_1.png
  magick random.png -virtual-pixel tile  -blur 0x3  -auto-level  random_3.png
  magick random.png -virtual-pixel tile  -blur 0x5  -auto-level  random_5.png
  magick random.png -virtual-pixel tile  -blur 0x10 -auto-level  
random_10.png
  magick random.png -virtual-pixel tile  -blur 0x20 -auto-level  
random_20.png
[IM Output] => [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
但是请注意,如果没有虚拟像素设置,“-blur”操作符将具有很强的边缘效果,最好避免这种情况。作为奖励,通过将“-virtual-pixel”设置更改为“tile”,随机图像保持可平铺,颜色跨越图像边界。这种平铺能力是目前等离子体图像无法实现的,并且是纯随机图像一开始就如此随机的固有结果。 模糊随机色调
我发现特别令人愉悦的一种模糊随机噪声图像的特定转换是将值映射到HSB颜色色调。

  magick random_10.png -set colorspace HSB \
          -channel GB -evaluate set 100% +channel \
          -colorspace RGB random_hues_cyan.png
[IM Output]
上述问题在于,模糊往往会创建红色-黄色(低值)和红色-品红色(高值)的斑点,以及介于两者之间的绿色、青色和蓝色的条带。这仅仅是色调值模糊和均衡方式的结果。理想的解决方案是一种模数模糊,它将考虑色调值的循环特性。但是,此类操作符目前不可用,也许永远不会可用。
我所知道的最佳解决方案是简单地将图像中的所有三个随机通道相加(使用模数加法合成),以便扩展值的范围。这也会产生使模糊斑点更小的副作用,但至少您现在可以获得更多动态范围的彩虹色。有没有更好的主意?

  magick random_10.png -separate -background white \
          -compose ModulusAdd -flatten -channel R -combine +channel \
          -set colorspace HSB -colorspace RGB random_hues.png
[IM Output]
有关处理随机图像的更多方法,请参见上面的等离子体图像,以及生成背景 模糊随机灰度从上面您可以看到,您得到一个具有各种主要颜色斑点的图像。也就是说,因为每个通道都被完全独立地作为灰度图像进行处理。让我们提取上面每个图像的一个通道,以便您可以看到模糊图像的结构……

  magick random.png     -channel G  -separate   random_0_gray.png
  magick random_1.png   -channel G  -separate   random_1_gray.png
  magick random_3.png   -channel G  -separate   random_3_gray.png
  magick random_5.png   -channel G  -separate   random_5_gray.png
  magick random_10.png  -channel G  -separate   random_10_gray.png
  magick random_20.png  -channel G  -separate   random_20_gray.png
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
您首先应该注意的是,图像通常(但并非总是)包含大致相等数量的黑色和白色区域。如果我们在50%处阈值化随机图像,您就可以看到这一点


  magick random_0_gray.png   -threshold 50%   random_0_thres.png
  magick random_1_gray.png   -threshold 50%   random_1_thres.png
  magick random_3_gray.png   -threshold 50%   random_3_thres.png
  magick random_5_gray.png   -threshold 50%   random_5_thres.png
  magick random_10_gray.png  -threshold 50%   random_10_thres.png
  magick random_20_gray.png  -threshold 50%   random_20_thres.png
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
如你所见,你得到了大约 50% 的白色区域和 50% 的黑色区域,它们被一条弯曲的线分隔开来。此外,这条线的曲线会根据用于纯随机图像模糊的“sigma”值而变化。从生成黑白“雪花”的单个像素,到得到非常均匀(尽管仍然是随机的)的图像分成两个黑白区域。有关使用随机图像的更多示例,请参阅背景图像,或查看如何生成随机画布,请参阅纯色随机斑点

随机颗粒度(混沌中的秩序)

现在请记住,所有模糊的随机图像都是从相同的初始随机图像生成的,因此它们都是相关的。但是每个新生成的随机图像都将具有完全不同的图案,尽管这些图案在结构上或多或少看起来相似。
但首先让我们完整地展示一个从头开始生成“模糊随机图像”的示例…

  magick -size 100x100 xc:  -channel G +noise Random \
         -virtual-pixel Tile -blur 0x5 -auto-level \
          -separate +channel   random_5_gray.png
[IM Output]
大量使用“-channel”设置来将操作限制在图像的“绿色”通道非常重要,因为它可以将图像的整体生成速度提高 3 倍。通道分离 将确保我们获得纯灰度结果。如果需要,你可以省略两个“-channel”设置,这将导致生成 3 个完全独立且不同的“模糊随机图像”。该图像具有一些重要的特征,如果我们将图像分成三组相等的颜色(使用称为色调分离的技术),我们可以更清楚地看到这些特征,你会看到在每个黑色和白色区域内部,你都会得到更多圆形斑点或“颗粒”。
例如…

  magick random_5_gray.png  -ordered-dither threshold,3  random_5_blobs.png
[IM Output]
首先,我想指出我们如何在图像中获得大致相等的光暗区域,但这些区域通过形成在光暗区域之间的渐变的灰色“中间”颜色相互连接。现在,各个斑点或“颗粒”在图像中的不同区域有所不同,但它们都大致平均为直径约为初始随机图像模糊值的三到四倍。这个模糊值被称为图像的“颗粒度”,是一个非常重要的值,因为它基本上代表了随机图像生成的圆形结构的平均大小。有时它被称为图像的“弯曲度”。值越大,这些曲线在图像中的尺寸越大,速度越慢。这是描述模糊随机图像的最重要因素,所以让我们把它说得非常清楚…
随机图像的“颗粒度”(或模糊因子)
决定了内部圆形结构的大小
当然,“模糊因子”或“颗粒度”越小,曲线就越小或越紧密,直到达到“0”的值,此时,图像中所有聚集或“斑点”都消失了,你至少得到了一种纯随机的“噪声”、“雪花”或“像素尘埃”类型的效果。
附注:实际上,“颗粒”本身的实际大小可能会因用于生成它们的阈值因子而异。该因子真正描述的是白色和黑色区域中心之间的平均距离。值越大,距离越大,斑点必须越大,分布越广才能适应更大的距离。当我们开始查看下面的随机波纹时,这一点会变得更加明显。
你可能还想尝试使用 50% 的太阳化操作以及一些额外的色阶调整来从图像中提取分离良好的黑色和白色颗粒。
例如,这是一个完整的示例,颗粒度为“8”,斑点阈值为“25%”,从图像的黑色和白色部分生成白色斑点。

  magick -size 100x100 xc: -channel G +noise random \
          -virtual-pixel tile -blur 0x8 -auto-level  \
          -solarize 50% -separate +channel \
          -threshold 25% -negate   random_granules.png
[IM Output]
请注意,随着值的增大,生成模糊随机图像所需的时间也会大大增加。此外,当值达到最小图像尺寸大小的一半左右时,效果会停止增长,因为随机图像会稳定成一个白色和黑色斑点。不建议使用较大的值。[IM 输出]最后,左侧显示了一个巡逻循环动画,它是通过改变单个随机图像的“颗粒度”(随机模糊)产生的。该动画是使用 shell 脚本“animate_granularity”生成的,你可以下载、学习和使用它。请注意,由于使用相同的随机图像作为源,因此“颗粒”或斑点并没有真正移动,而只是融合或消失,从而产生随着颗粒度增加而变大的“颗粒”。还要记住,虽然我减少了动画中的颜色数量,但完整随机图像的结构实际上是在两组白色和黑色颗粒之间的平滑渐变。这种渐变使图像在其他技术中变得有用。

随机通量(动画循环)

现在如你所见,颗粒或斑点实际上并没有移动太多。但是对于动画效果,你需要一个随时间平滑移动的图案。此外,你也不希望该图案只是简单地来回移动。最后,你也不希望该运动模式在动画循环时突然跳动或抖动。因此,我们需要某种方法来生成平滑重复的随机图案。一个艰巨的任务。此外,由于你需要它平滑,因此你需要从相同的单个随机图像生成所有图案。这里有一个想法,它允许你生成这样的随机图案。与其将每个随机像素值视为随机强度,不如将该值视为定义该像素处于最大或最小强度时的“时间”值。也就是说,我们将该值转换为“波”上的一个位置。因此,每个像素都表示正弦曲线的某个“相位”。这听起来很复杂,但实际上并非如此。我们只需使用随机图像作为正弦函数的源图像。现在,对于时间序列中的每个图像,我们都会设置该时间循环中特定点的“相位”。

  magick random.png   -function Sinusoid 1,{time} \
          ... do granular blurring,  and other processing ...
其中“{time}”在完整的动画循环中从“0”到“360”。结果是,每个像素不再具有“静态”的随机值,而是随着时间的推移在黑色和白色之间循环。每个像素都将遵循相同的循环,但由于每个像素都具有完全不同的“相位”,并且将独立于所有其他像素循环。也就是说,图像仍然是随机的,但会随着提供的“时间”值平滑变化。对于有科学头脑的人来说,这有点像观察亚原子水平存在的“量子通量”,在那里,空间远非我们在正常尺度上看到的“静态”状态。因此得名“随机通量”。例如,让我们生成一个包含 12 个图像的时间序列…

  for i in `seq 0 30 359`; do
    magick random.png  -channel G  -function Sinusoid 1,${i} \
            -virtual-pixel tile -blur 0x8 -auto-level \
            -separate flux_${i}.png
  done
[IM Output] => [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
=> =>
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] => [IM Output]
现在你的一个随机图像可以生成一系列形成循环的图像。请注意,必须在任何其他处理(如模糊)之前进行“时间”提取,而模糊可能是整个生成过程中最慢的部分。需要注意的另一点是,在“180”相位(右下角),你实际上得到了第一个图像(左上角)的确切负片。也就是说,“白色”颗粒变成了“黑色”颗粒,反之亦然。实际上,动画的后半部分实际上是前半部分的负片。这可以用来减少简单“随机通量”动画的生成时间。因为图像在 180 度相位时是负片,所以你会发现每个“白色”颗粒会缓慢移动,以便与相邻的“黑色”颗粒交换位置。但是由于整个后半部分是前半部分的负片,因此它不能简单地来回移动,而必须继续向前移动才能返回到原始图像,或围绕一个循环循环,或简单地适当地淡入和淡出。换句话说,白色和黑色颗粒以更复杂的循环移动。 [IM 输出]右侧是上述帧的动画…波动的图案是完全随机的,但从一帧到下一帧平滑变化,并且在动画循环时也是如此。你看不到结果的开始或结束。有时你会得到漩涡状的运动,有时看起来所有“气体”状的斑点都被吸入一个黑暗区域,或者只是再次出现和消失。你还会遇到非常快的运动时期,以及非常慢的运动时期。它是完全随机的。总之模糊随机图像中存在的相同属性也存在于此动画中。该图像在白色和黑色片段之间保持大致相等的划分,并且形成大约三倍于图像模糊或颗粒度大小的斑点。但最重要的是,你保证图像的所有部分都将在较浅和较深的颜色之间形成某种循环,因为循环的一半是另一半的负片。你可能没有注意到的一件事是,由于将随机线性值转换为正弦波形,你将获得更清晰的白色和黑色颜色分离(对比度)。因此,你可能希望使用S形对比度运算符的反对比度方面,使生成的图像不那么像“斑点”,并增强颗粒之间的渐变,而不是颗粒本身。现在,这只是你可以使用循环随机动画做的事情的起点。你可以对随机图像执行的所有操作,例如生成背景中所述,也可以应用于“随机通量动画
例如,让我们只显示“白色”颗粒的运动…

  magick flux_anim.gif -threshold 70% flux_thres_anim.gif
[IM Output]
或生成缓慢地在图像上流动的变化的电丝。

  magick flux_anim.gif  \
          -sigmoidal-contrast 30x50% -solarize 50% -auto-level \
          -set delay 20 filaments_anim.gif
[IM Output]
请注意,由于循环的一半是前半部分的否定,并且我们使用太阳化将白色和黑色颜色对折,因此循环实际上在一个动画循环中重复了两次。它确实需要更多帧才能消除正在发生的一些非常快速的变化。
为了使更长的循环序列的运动更不可预测,你还可以使用一些渐变数学来组合来自多个随机图像的多个正弦循环,甚至只使用相同随机图像的其他颜色通道。

FUTURE: Create even less predictable, long time 'harmonic' cycles. 

随机波纹

通过向模糊随机图像添加另一个变体,我们可以增加另一个复杂度级别,这使得这些图像更加有用,并除了其粒度之外,给了我们另一个控制变量。但首先你需要记住,随机图像不仅由亮区和暗区组成,还包含这些区域之间的斜率。使用该斜率作为正弦函数的输入,你可以生成图像中斑点之间的波纹。请注意,这种正弦函数的使用与之前的随机通量示例的关键区别在于,这次函数是在使用模糊平滑图像**之后**应用的,而不是之前。此外,在这种情况下,更重要的是“频率”值,而不是第二个“相位”值。例如……

  magick random_10_gray.png  -function Sinusoid 1,90   ripples_1.png
  magick random_10_gray.png  -function Sinusoid 2,90   ripples_2.png
  magick random_10_gray.png  -function Sinusoid 3,90   ripples_3.png
  magick random_10_gray.png  -function Sinusoid 4,90   ripples_4.png
[IM Output] => [IM Output] [IM Output] [IM Output] [IM Output]
如你所见,正弦函数的“频率”越大,添加到“颗粒”之间渐变中的波纹就越多。“频率”为“1”基本上会将源图像中的亮和暗“斑点”都变成白色,并在它们之间留出一个黑暗的间隙。“频率”为“2”会在该黑暗间隙中挤压出一个额外的“脊”或“波纹”。随着频率的增加,你在原始图像的最亮和最暗区域之间会得到越来越多的“波纹”,使其变得越来越复杂。随着脊数的增加,你可能会看不见图像中原始的“斑点”或“颗粒”。你可以通过在添加波纹之前修改渐变来解决此问题,方法是使用色阶调整“剪切”渐变,或使用S型对比度压缩中间调。这将使“颗粒”具有一定的质量或面积,并在波纹之间提供“平静”区域。

  magick random_10_gray.png        -level 25%            random_enhanced.png
  magick random_enhanced.png  -function Sinusoid 4,90    ripples_4e.png
  magick random_10_gray.png   -sigmoidal-contrast 10,50% random_sigmoidal.png
  magick random_sigmoidal.png -function Sinusoid 4,90    ripples_4s.png
[IM Output] => [IM Output] => [IM Output]
[IM Output] => [IM Output]
这两种方法都有优点和缺点,但本质上它们都会放大颗粒,但不会放大白色和黑色颗粒集之间的距离。当然,这样做的副作用是压缩了这两组颗粒之间的波纹。
上面示例中使用的第二个值“90”是正弦函数的“相位”。它将决定源图像中“黑色”颗粒在“波纹”图像中变成的颜色。

  magick random_enhanced.png  -function Sinusoid 3,0     ripples_3e000.png
  magick random_enhanced.png  -function Sinusoid 3,90    ripples_3e090.png
  magick random_enhanced.png  -function Sinusoid 3,180   ripples_3e180.png
  magick random_enhanced.png  -function Sinusoid 3,270   ripples_3e270.png
[IM Output] => [IM Output] [IM Output] [IM Output] [IM Output]
“白色”颗粒的颜色将取决于“相位”和所应用“频率”的分数。整数“频率”值会导致白色和黑色颗粒的颜色一起变化(根据“相位”)。因此,当相位为“90”时,两者都将为白色。
但是,如果你应用一个分数“频率”值,例如“0.5”,“白色源”颗粒将是“黑色源”颗粒的反色(由“相位”确定)。

  magick random_enhanced.png  -function Sinusoid 3.5,90    ripples_3.5e.png
[IM Output]
请注意,对于“灰色”相位角,其中一个颗粒周围环绕着白色圆环,而另一个周围环绕着黑色圆环。如果使用具有“0.5”分数的“频率”值,则每个斑点周围的第一个波纹将全部为白色或全部为黑色,具体取决于使用的“相位”。
不建议使用除整数或“0.5”之外的其他“频率”,因为两组颗粒不会以某种方式同步。

类似地,除非生成“波纹动画”(见下文),否则不建议使用 90 度倍数以外的相位。

生成“色散图”(见下文)时,建议使用“0”的相位值,因为这会导致增强“颗粒”区域内的失真最小。
随机通量中的先前情况一样,你可以随时间修改“相位”,以便生成波纹从一组颗粒移动到另一组颗粒的动画。在没有任何对比度增强的情况下,这种方法特别有效。

  for i in `seq 0 30 359`; do
    magick random_10_gray.png -function Sinusoid 3.5,${i} miff:-
  done |
    magick miff:- -set delay 15 -loop 0 ripples_anim.gif
[IM Output]
旁注:上面使用的方法称为“流水线MIFF:”,并且是可能的,因为MIFF:文件格式可以简单地“连接”图像以生成多图像文件。其中一点是,动画的变化似乎比我们上面创建的通量动画慢得多。这是因为在一个动画周期内,波纹只会移动一小段距离,而在“通量”动画中,变化将在半个周期内从大尺度的白色到黑色颗粒传播,然后再返回。现在,你可以将上述波纹动画与来自相同随机图像源的底层“通量”动画结合起来,以生成更具动态和流动性的形式,但请注意动画速度的差异。
例如,这里我只是取上面创建的先前通量动画,并向其添加波纹。在这种情况下,波纹只会移动,因为通量动画中的渐变会移动。

  magick flux_anim.gif -function Sinusoid 3.5,0 flux_rippled_anim.gif
[IM Output]
你也可以在动画中设置波纹动画。尽管你可能需要为波纹本身使用更大的“相位循环速率”(“j = 5 * i”表达式)。此外,由于你在一个循环中生成一个循环,因此你需要生成一个更长的动画,在本例中为 60 帧。但是,这样做的好处是也减缓了更大的“通量”运动。

  for i in `seq 0 10 359`; do
    j=`expr $i \* 5`
    magick random.png -channel G \
            -function Sinusoid 1,${i} \
            -virtual-pixel tile -blur 0x8 -auto-level \
            -function Sinusoid 2.5,${j} \
            -separate +channel miff:-
  done |
    magick miff:- -set delay 15 -loop 0 ripples_flux_anim.gif
[IM Output]
请注意,在第二张图像中,波纹似乎首先从一个点发出,然后稍后开始返回到同一个点,尽管它们从未简单地反向。一个更好的多循环通量循环生成器应该通过去除底层通量动画中的“负”效果来消除这种轻微的怪异现象。
未来:使用波纹随机图像进行色散映射失真.

平铺画布

平铺图像可以非常大或非常小,旨在并排和垂直地拼接在一起以覆盖大面积的空间。由于万维网的出现,可供使用的平铺图像数量激增(找到你想要的内容是另一回事)。下面是一组我从Anthony 的图标库复制的平铺图像,在这些示例页面中使用。
[IM Output]
bg.gif
[IM Output]
tile_aqua.jpg
[IM Output]
tile_water.jpg
[IM Output]
rings.jpg
[IM Output]
tile_disks.jpg
[IM Output]
tile_weave.gif
目前,你可以通过多种方式在一个大区域内平铺图像。你可以“-tile”任何图像,以便完全替换原始背景图像(使用“Copy”合成运算符)。(有关更多详细信息,请参阅平铺合成)。

  magick composite -tile tile_weave.gif -size 60x60  xc:none   tile_copy.gif
[IM Output]
另一种方法是使用“tile:”编码器读取平铺图像,并将其平铺到特定大小。

  magick -size 60x60 tile:bg.gif  tile_size.gif
[IM Output]
请注意,“tile:”编码器会将图像中的任何透明度替换为当前背景颜色。这是因为在内部,它会生成一个请求大小的画布,并将平铺图像“叠加”到该画布上。

如果你想保留透明度,请设置“-background none”或“-compose SRC”(有关详细信息,请参阅Src 合成方法)。
你可以使用它生成一个比你需要的大得多的平铺图像,然后使用“-composite”将其覆盖到原始图像上。如果平铺图像部分透明,则需要指定“Over” “-compose”方法。这是一种非常缓慢的平铺方法,特别是对于大型图像,并且你需要确定需要创建多大的图像才能进行叠加。

  magick test.png -size 200x200 tile:tile_disks.jpg \
          -composite  tile_over.gif
[IM Output]
通过将平铺指定为“-draw”运算符的“平铺填充图案”,你可以将平铺图像绘制到另一个图像上,以创建任何你喜欢的形状或图形。这是因为“-tile”设置将覆盖“-fill”绘制使用的任何颜色设置。请参阅MVG 绘制设置

  magick -size 60x60 xc: -tile tile_aqua.jpg \
          -draw "circle 30,30 2,30"   tile_draw.gif
[IM Output]
这仅适用于“-draw”以及像“-annotate”这样的运算符,这些运算符也使用“-draw”来执行其功能。它不适用于直接使用“-fill”颜色的图像运算符,例如“label:”、“caption:”和“text:”。
但是,“-draw”在其内部内置了一些特殊的颜色原语,例如将图像中的所有像素完全重置为填充颜色或平铺图案(如果设置)。

  magick test.png   -tile tile_water.jpg  -draw "color 0,0 reset" \
          tile_reset.gif
[IM Output]
这实际上与使用特定颜色的一些纯色画布方法所使用的方法完全相同。只是这里我们使用了“-tile”而不是“-fill”颜色。
一种更高级的方法是使用扭曲运算符和一个特殊的扭曲视口设置,该设置被设置为原始图像的大小(使用定义的全局工件百分比转义)。这基本上将围绕小型平铺图像的较小型平铺的虚拟像素映射到生成较大型的平铺画布。

  magick rose: -set option:distort:viewport '%g' +delete  \
          tree.gif -virtual-pixel tile -filter point -distort SRT 0 \
          tile_distort_sized.gif
[IM Output]
请参阅通过扭曲平铺(下文),我们将研究相同的技术来平铺已在内存中的图像。

偏移平铺画布

有时你需要对背景纹理的确切位置进行更多控制,无论是为了使平铺图案与其他图像对齐,还是为了避免与最终图像的其他部分出现不良相关性。对于许多标准的平铺方法,这可以通过使用“-tile-offset”设置来实现。例如,这里我滚动正在使用的平铺图像,以使用“tile:”或“pattern:”直接创建平铺画布图像。

  magick -size 80x80 -tile-offset +30+30 tile:rose: offset_tile.gif
  magick -size 80x80 -tile-offset +20+20 \
                                 pattern:checkerboard offset_pattern.gif
[IM Output] [IM Output]
平铺偏移设置在 IM 版本 6.3.9-9 之前存在问题,即“X”偏移量被同时用于“X”和“Y”偏移量值(给定的“Y”值被忽略)。这意味着虽然上述示例可以工作(“X”和“Y”偏移量相同),但当这两个值不同时,你可能无法获得预期的结果。
这也适用于“magick montage”背景“-texture”设置。

  montage tree.gif     -geometry +24+24 \
          -tile-offset +30+30 -texture rose: offset_texture.gif
[IM Output]
你也可以通过在“-tile”或“-fill”设置之前定义它来使用该设置。例如……

  magick -tile-offset +30+30  -tile rose: \
          -size 80x80 xc: -draw 'color 30,20 reset'    offset_tile_fill.gif
[IM Output]
确保在定义“-tile”图像之前重置“-size”设置,但在读取任何其他图像之后。

  magick -size 80x80  xc: \
          -tile-offset +20+20 +size -tile pattern:checkerboard \
          -draw 'color 30,20 reset'  offset_pattern_good.gif
[IM Output]
无论如何,最好在第一次使用之前定义平铺偏移量和平铺图像,这与上述解决方案的结果相同。

使用已在内存中的图像进行平铺

对内存中已有的(创建或修改的)图像进行平铺并非易事,只有少数间接方法可用。

克隆并追加平铺图像

如果您不担心平铺图像的精确尺寸,只需将图像多次拼接在一起即可。例如,这里我们将图像以 3x3 阵列的方式平铺。

  magick tree.gif \
          \( +clone +clone \) +append \
          \( +clone +clone \) -append \
          tile_clone.gif
[IM Output]
这种平铺方法的优点是可以让您进行翻转平铺(镜像平铺)图像。

  magick tree.gif \
          \( +clone -flop +clone \) +append \
          \( +clone -flip +clone \) -append \
          tile_clone_flip.gif
[IM Output]
通常,只有在您对要平铺的图像大小有一定的了解时,此方法才实用。此外,由于克隆实际上非常快速高效,因此它是一种相当简单快速的平铺方法,尤其是在您使用结果进一步平铺更大的图像时。

使用 MPR 进行平铺:(内存程序寄存器)

更好的方法是将图像保存到特殊的“内存中”文件格式“mpr:”中,或称为“内存程序寄存器”。从该寄存器,您可以使用“-tile”设置,或使用特殊的“tile:”图像文件读取器,这两者都只能从“已保存”的图像文件格式中设置。
例如,使用“tile:”创建特定尺寸的平铺图像…

  magick tree.gif   -write mpr:tile +delete \
          -size 100x100 tile:mpr:tile    tile_mpr.gif
[IM Output]
请记住,“tile:”编码器会将图像中的任何透明度替换为当前的背景颜色。(见上文)
或者通过设置“-tile”或“-fill”填充图案,并使用“-draw”进行颜色重置(参见 颜色填充基元)…,在现有图像上进行平铺。

  magick tree.gif  -write mpr:tile +delete \
          granite: -fill mpr:tile  -draw 'color 0,0 reset' \
          tile_mpr_reset.gif
[IM Output]
如果使用包含透明度的图像进行平铺,请确保目标图像也具有透明度,方法是使用“-alpha set”。如果您不这样做,则生成的图像将显示平铺的“隐藏”透明颜色。
或者使用其他 绘图基元进行绘制,例如使用填充图案的圆形。

  magick tree.gif -write mpr:tile +delete \
          granite:  -tile mpr:tile  -draw 'circle 64,64 10,50' \
          tile_mpr_fill.gif
[IM Output]
在“mpr:”之后给出的名称可以是您喜欢的任何名称,它只是用于存储图像(在内存中)的“mpr”寄存器名称的标签。它甚至可以是标签、数字、颜色,甚至文件名。

使用虚拟像素通过扭曲进行平铺

在这种方法中,我们使用 虚拟像素设置 生成一个大型的平铺画布。此设置定义了实际图像周围区域(超出正常图像边界)的外观。提取虚拟像素的最简单方法是使用 扭曲操作符 和特殊的 扭曲视口 设置。

  magick tree.gif -set option:distort:viewport 100x100+0+0 \
          -virtual-pixel tile -filter point  -distort SRT 0 \
          tile_distort.gif
 
[IM Output]
您还可以访问其他样式的虚拟像素平铺设置,例如“镜像”或甚至“棋盘格平铺”,以及使用视口设置进行良好的偏移平铺控制。

  magick tree.gif -set option:distort:viewport 100x100-10-10 \
          -background firebrick  -virtual-pixel CheckerTile \
          -distort SRT 0 +repage    tile_distort_checks.gif
[IM Output]
通过这种方式使用 通用扭曲操作符,您还可以额外获得以非常复杂的方式扭曲平铺图像的优势。您可以在 仿射平铺扭曲 中看到此功能的示例。作为一个更复杂的例子,我在这里使用 弧形扭曲 将树木围绕位于视口中心的原点进行平铺。“45”指定树木宽度所覆盖的角度,而“50”定义树木平铺顶部边缘的半径。其余部分则以此为基础。

  magick tree.gif -set option:distort:viewport 100x100-50-50 \
          -virtual-pixel tile  -distort Arc '45 0 50' +repage \
          tile_distort_polar.gif
[IM Output]

修改内置的 IM 图案/平铺

请参阅 ImageMagick 内置图像和图案 的完整列表。有很多这样的图案,但这里我只介绍一两个。现在,内置图案通常是非常小的图像,可以平铺以覆盖大面积区域。但是,它们本身看起来非常单调,而且相当无用。例如,这里有一个提供的更大、更有趣的图案…

  magick pattern:checkerboard  pattern_default.gif
[IM Output]
图案图像通常平铺在更大的区域上,要么作为画布创建的一部分,通过设置“-size”,要么作为填充平铺(参见上面 平铺画布)。如果没有尺寸设置,则将使用图案的默认平铺尺寸,在本例中为 30x30 像素。现在您可能会注意到,IM 当前提供的所有图案都是纯黑白色,唯一的例外是我在上一个示例中使用的“棋盘格”图案。
这里有一个我特别喜欢用作平铺图案的图案…

  magick -size 60x60 pattern:hexagons  pattern_hexagons.gif
[IM Output]
如果您对这些颜色不满意,可以使用“-opaque”图像操作符替换它们。

  magick -size 60x60 pattern:hexagons \
          -fill blue -opaque black   -fill skyblue -opaque white \
          pattern_colored.gif
[IM Output]
如果您想为“棋盘格”图案着色,则最好先使用“-auto-level”将两个灰色映射到黑色和白色,然后再替换这两个颜色。这里我没有使用“-opaque”来替换颜色,而是使用了“+level-colors”操作符(添加 IM v6.2.4-1),它使用起来稍微简单一些。

  magick -size 60x60 pattern:checkerboard -auto-level \
          +level-colors red,blue     pattern_color_checks.gif
[IM Output]
您还可以使用“-floodfill”操作符为图案着色。但是,要使其正常工作,您需要在平铺修改后的图案之前执行此操作。在本例中,我还需要将平铺扩展三倍,才能用我想要的常规颜色图案对其进行着色。

  magick -size 30x54 pattern:hexagons \
          -fill tomato     -opaque white \
          -fill dodgerblue -draw 'color 10,10 floodfill' \
          -fill limegreen  -draw 'color 10,25 floodfill' \
          -roll +15+27 \
          -fill dodgerblue -draw 'color 10,10 floodfill' \
          -fill limegreen  -draw 'color 10,25 floodfill'   miff:- |\
    magick -size 100x100 tile:- pattern_color_hexagons.gif
[IM Output]
我在上面使用了一个由两个命令组成的管道,将彩色图案的创建与其实际使用分开。如果您想用单个命令执行此操作,请参见上面 在内存中平铺图像
您还可以扭曲和变形一个简单的平铺图案,以产生有趣的变化。例如,我对一个六边形图案上的“起皱”效果(技术来自 字体图像生成器 中的 IM 起皱效果)特别感兴趣。

  magick -size 160x100 pattern:hexagons \
          -wave 3x100 -background white -rotate 90 -wave 4x66 -rotate -87 \
          -gravity center -crop 120x90+0+0 +repage   pattern_distorted.gif
[IM Output]

修改平铺图像

人们在修改平铺时面临的最大问题是,无论是现有的平铺还是内置的图案,许多图像操作都会破坏图像的“可平铺性”。例如,这里我使用了内置的“六边形”图案,并尝试对其进行修改以生成宽六边形线条的阴影灰度图案。

  magick pattern:hexagons  -rotate 90 \
          -blur 0x1  -edge 1  -negate  -shade 120x45 \
          miff:- |\
    magick -size 100x100 tile:-   tile_mod_failure.jpg
[IM Output]
第一个命令生成“平铺图像”,第二个命令实际上对图像进行平铺,因此我们可以看到它们是如何组合在一起的。如您所见,生成的平铺图像无法正确平铺,在平铺图像中可以清楚地看到人工边缘扭曲。基本上,我们丢失了原始平铺沿图像边缘的均匀性。一种解决方案是使用特殊的 虚拟像素 设置,该设置用于使操作符在查找超出实际图像范围的颜色时认为图像环绕边缘。

  magick pattern:hexagons  -rotate 90  -virtual-pixel tile \
          -blur 0x1  -edge 1  -negate  -shade 120x45 \
          miff:- |\
     magick -size 100x100 tile:-   tile_mod_vpixels.jpg
[IM Output]
这是另一个示例,我将两个相关的平铺图案组合在一起,并使用各种效果创建不寻常的砖墙平铺。

  magick pattern:leftshingle pattern:rightshingle +append \
          -virtual-pixel tile  -blur 0x0.75 -resize 150% -shade 100x45 \
          -fill Peru  -tint 100%   miff:- |\
    magick -size 100x100 tile:-   tile_slanted_bricks.jpg
[IM Output]

替代方案

除了依赖 虚拟像素 之外,还有一种替代方案。基本上,我们在对图像进行操作之前自己提供“虚拟边缘像素”,以避免可能存在的任何边缘效果。这是通过首先在稍大的区域上平铺图像来完成的。修改图像后,我们可以重新提取平铺,避免引入的边缘失真。它不需要太大,具体取决于执行的图像操作的范围。我发现 15 到 40 个像素应该可以阻止最终结果中的所有边缘效果。要重新提取图像,我们可以“-shave”掉额外的像素,或者从处理后的图像中间“-crop”出原始平铺的大小。例如,这里我使用内置的“六边形”图案创建了 3d“-shade”效果。

  magick -size 60x60 tile:pattern:hexagons  -rotate 90 \
          -blur 0x1  -edge 1  -negate  -shade 120x45 \
          -gravity center -crop 18x30+0+0 +repage miff:- |\
    magick -size 100x100 tile:-   tile_mod_success.jpg
[IM Output]
请注意,提取的平铺的精确位置无关紧要。可平铺的图像可以从平铺图像的任何位置剪切,只要它远离扭曲的边缘,并且您使用平铺的原始大小即可。这里,我们没有在更大的区域上平铺图像,而是使用了“双克隆”技术来使平铺覆盖的区域加倍。完成后,我们只需将图像中心裁剪 50% 即可恢复修改后的平铺。这意味着我们无需知道正在处理的平铺的确切大小。

  magick pattern:circles \( +clone \) +append \( +clone \) -append \
          -fill grey -opaque black  -blur 0x0.5 -shade 120x45 \
          -gravity center -crop 50%  +repage    miff:- |\
    magick -size 100x100 tile:-   tile_circles.jpg
[IM Output]

生成平铺图像

在生成可以一起平铺的图像时,您面临的最大问题是尝试匹配图像的边缘和角点,以便它们能够无缝地拼接在一起。如果没有这样做,您得到的只是一组正方形框,每个框都包含图像的重复副本。这不是一件容易的事,而且可能会让人非常沮丧和抓狂。出现在平铺一侧边缘上的物体必须在图像的另一侧重新出现,以便在图像平铺时重新形成整体。虽然您可以使用计算机生成的图像相对轻松地做到这一点,但使用真实世界的照片生成良好的平铺图像几乎是不可能的。另一个主要问题是试图使平铺看起来不像是在重复。解决此问题的唯一真正方法是使您的平铺图像足够大,以包含足够相似但仍然不同的元素,从而难以看到重复的图案。因此,生成看起来不重复的小平铺尤其困难。
FUTURE:  Ideas and suggestions for generating tile patterns?  Anyone?

Or roll, add element, roll, add element, etc...

Any and all suggestions and examples accepted.

Suggestions for generating tile from real photos of repeating patterns,
such as water, fallen leaves, clouds, stucco, brickwork, etc...

Generating Escher-like tile patterns.

随机噪声平铺

由于原始随机噪声画布本身没有边缘特征(每个像素的颜色完全独立于其任何邻居),因此您可以对其进行平铺,而无需担心边缘失真。基本上,它在像素级别上非常随机,一开始就没有边缘匹配,因此我们不会在平铺时丢失任何东西。不幸的是,很少有情况会按原样使用原始随机噪声图像,用于任何实际目的。它太随机了,以至于毫无用处。但是,通过在保留其固有可平铺性的同时修改图像,我们可以创建几乎任何我们想要的随机平铺图案。
例如,让我们看看使用我们在上一个示例中使用的相同“修改平铺”技术对原始平铺进行基本的“-blur”。


magick -size 64x64 xc: +noise Random \ -virtual-pixel tile -blur 0x6 -auto-level tile_random.jpg magick -size 128x128 tile:tile_random.jpg tiled_random.jpg
[IM Output]
[IM Output]
使用此技术,您可以对原始随机噪声图像应用几乎任何转换。例如…


magick -size 64x64 xc: +noise Random \ -virtual-pixel tile -blur 0x6 -edge 1 -fx G \ -shade 280x45 -auto-level tile_random_pits.jpg magick -size 128x128 tile:tile_random_pits.jpg tiled_random_pits.jpg
[IM Output]
[IM Output]
如您所见,使用原始随机噪声图像创建随机平铺要简单得多,并且结果中不会有任何边缘失真。此特定图像转换在 背景图像 页面上列出,标题为“坑”。请参阅该页面以了解其他图像随机图像转换以及它们的示例。

六边形平铺

与其以方形方式进行平铺,不如“随机噪声”图像允许我们生成非常不同的平铺类型。通过将图像尺寸加倍并在额外空间中重新放置平铺,但偏移一半,我们可以生成基本的随机噪声六边形平铺图案。
当我们对 ImageMagick 的特殊“pattern:hexagons”内置进行平铺时,我们会得到相同类型的平铺效果。

  magick pattern:hexagons  tile_hexagons.gif

  magick -size 64x64  pattern:hexagons  tiled_hexagons.gif
[IM Output]
[IM Output]
但是请注意,要使此平铺看起来像“六边形”,平铺不能是正常的正方形,甚至不能是加倍的正方形。最终的平铺尺寸需要是矩形。此矩形的精确比例实际上涉及无理数,这对于具有像素数组的图像工作来说不是很好。但是,一个良好的工作比例是 4:3,大多数计算机和数码相机图像都使用此比例。

这里我们叠加了两次相同的“随机噪声”图像(一个长宽比为 2:3 的矩形)来生成基本的六边形图案(在一个 4:3 的矩形中)。然后使用 背景图像 页面中的“paint_3s”变换来转换六边形平铺的随机噪声图块,从而生成一个相当好看的六边形平铺图案。


magick -size 48x64 xc: +noise Random -write mpr:rand \ -extent 96x64 -page +48-32 mpr:rand -page +48+32 mpr:rand \ -flatten tile_hex_random.jpg magick tile_hex_random.jpg -virtual-pixel tile -blur 0x10 -paint 3 \ -shade 280x45 -auto-level tile_hex_layered.jpg magick -size 160x160 tile:tile_hex_layered.jpg tiled_hex_layered.jpg
[IM Output]
[IM Output]
如果你观察该图块生成的图案,你会发现任何特定的特征周围都会有 6 个相同的特征以圆形环绕。这就是该图块生成的“六边形”图案,即使它仍然像所有其他平铺图像一样以相同的“正方形”图案进行平铺。上述“六边形平铺”图案的一个变体是垂直加倍图块图像,而不是像我们上面那样水平加倍。结果是六边形图案将旋转 90 度。然而,它仍然是相同类型的图案。
从数学上讲,以上操作并不是从现有图块生成新的墙纸群。原始的“非六边形”图像和最终版本都属于相同的“p1”平铺群。

我们实际上在上面做的是将菱形“原型图块”平铺图案转换为相同平铺图案的更大的矩形正交对齐的“基本域”。这样,你就可以使用标准的平铺方法来平铺图像。
未来:翻转额外的图像以生成更大的平铺图案(pmg 平铺群)。 未来:如何从图像中裁剪(遮罩)出一个六边形,以便它可以完美地平铺,而不会出现间隙或重叠。

三重六边形平铺

就像我们在为内置的“hexagons”图案着色时所做的那样(参见上面修改内置 IM 图案/图块),你可以在重新映射它们以形成更大的图块之前,创建初始图块的三个不同变体(例如,使用旋转)。当然,就像我在为“hexagons”图案着色时所做的那样,最终的图块图像需要放大三倍,以便生成重复的矩形图块图案。三个生成的图块之间的差异不能太大,并且应该能够承受任何后处理,否则你将无法获得该技术的优势。这意味着初始图块也必须足够大,以便保留任何存在的独特特征。例如,这里我们采用非常简单的线条图,并将其旋转以生成 3 个类似的变体。然后将这些旋转后的图像在更大的画布上平铺七次(放大 6 倍),以生成三倍图像的六边形图案。

  magick -size 24x24 xc: -draw "rectangle 3,11 20,12"  tile_line.gif

  magick tile_line.gif   -gravity center\
          \( +clone -rotate    0 -crop 24x18+0+0 -write mpr:r1 +delete \) \
          \( +clone -rotate  120 -crop 24x18+0+0 -write mpr:r2 +delete \) \
                    -rotate -120 -crop 24x18+0+0 -write mpr:r3 +repage \
          -extent 72x36        -page  +0+0  mpr:r3 \
          -page +24+0  mpr:r1  -page +48+0  mpr:r2 \
          -page -12+18 mpr:r1  -page +12+18 mpr:r2 \
          -page +36+18 mpr:r3  -page +60+18 mpr:r1 \
          -flatten tile_hex_lines.jpg

  magick -size 120x120  tile:tile_hex_lines.jpg  tiled_hex_lines.jpg
[IM Output]
[IM Output]
[IM Output]
然而,以上方法仅适用于平铺原始图像中间的小形状。它不适用于通用图像。对于通用图像的六边形平铺,我们还需要遮罩出一个等边三角形。然后旋转这些片段,使等边三角形的边缘镜像。这不是一项简单的任务。

对角线镜像平铺

这是一种将任何正方形图像转换为围绕中心点的 8 个镜像图像的方法。具体来说,我们正在生成一个复杂的“p4m”平铺图案。我首先生成随机色调图像,并使用源图像的左下半部分将其沿对角线镜像,然后水平和垂直镜像。

  magick -size 50x50 xc: +noise Random -virtual-pixel Tile -blur 0x5 \
          -auto-level -separate -background white \
          -compose ModulusAdd -flatten -channel R -combine +channel \
          -set colorspace HSB -colorspace RGB   tile_diag_source.jpg

  magick tile_diag_source.jpg     \( +clone -transpose \) \
          \( +clone -sparse-color voronoi '%w,0 white 0,%h black' \) \
          -composite \
          \( +clone -flop -chop 1x0 \) +append \
          \( +clone -flip -chop 0x1 \) -append \
          tile_diag_mirror.jpg
[IM Output]
[IM Output]
对角线镜像是通过执行转置,然后使用使用Voronoi,稀疏颜色生成的遮罩来生成的。请注意,由于正方形的像素几何形状,此对角线镜像会自动沿镜像共享一行像素。在创建垂直和水平翻转和翻转之前,我还删除了一组边缘的像素。我还建议在使用此图像作为“图块”之前,删除顶部和左侧边缘的另一行和一列像素。你不必这样做,但我认为这样看起来更好。如果不删除一行和一列边缘像素,则会在图像连接处出现难看的“接缝”,出现像素加倍的情况。另一种方法是首先平铺原始随机图像,然后进行背景图案转换,你不太可能在镜像线上出现“裁剪外观”,而是会出现更平滑的过渡。

  magick -size 51x51 xc: +noise Random   \( +clone -transpose \) \
          \( +clone -sparse-color voronoi '%w,0 white 0,%h black' \) \
          -composite \
          \( +clone -flop -chop 1x0 \) +append \
          \( +clone -flip -chop 0x1 \) -append \
          -chop 1x1 \
          \
          -virtual-pixel Tile -blur 0x5 -auto-level \
          -separate -background white \
          -compose ModulusAdd -flatten -channel R -combine +channel \
          -set colorspace HSB -colorspace RGB    tile_p4m.jpg
[IM Output]
第一部分是“随机数据的平铺”的生成,后半部分我将随机数据转换为“色调”映射。我还向初始图像添加了额外的像素,这些像素稍后将根据需要进行裁剪以生成平铺图像。
有关图像平铺及其背后数学的更完整介绍,请参阅维基百科:墙纸群。我们上面探讨的只是你可以创建的众多平铺图案中的一小部分。
p4g”与上面的“p4m”平铺几乎完全相同,但使用镜像正方形的 180 度旋转而不是使用翻转来生成完整的平铺图像。但是,由于图像不是通过镜像连接的,因此你不能使用现有图像作为图块源,因为边缘将变得不连贯和不连续。但是,你可以先平铺原始随机数据,然后处理生成的图块图像,以产生平滑的结果。

  magick -size 50x50 xc: +noise Random   \( +clone -transpose \) \
          \( +clone -sparse-color voronoi '%w,0 white 0,%h black' \) \
          -composite \
          \( +clone -rotate -90 \) +append \
          \( +clone -rotate 180 \) -append \
          \
          -virtual-pixel Tile -blur 0x5 -auto-level \
          -separate -background white \
          -compose ModulusAdd -flatten -channel R -combine +channel \
          -set colorspace HSB -colorspace RGB    tile_p4g.jpg
[IM Output]
请注意,由于平铺的非镜像性质,你不需要在附加之前从边缘删除重复的行或列像素。尽管这样做不会造成伤害,如果你希望对这两种情况使用相同类型的过程。