ImageMagick 示例 --
颜色量化和抖动
- 索引
- ImageMagick 示例前言和索引
- 颜色缩减简介 (涉及的内容)
- 图像中的颜色 (图像使用的颜色)
- 颜色量化 (减少图像中的颜色数量)
- 错误校正抖动 (或伪随机抖动)
- 阈值抖动方法
- 有序模式抖动 (使用平铺阈值映射)
- DIY 抖动模式和阈值映射 (以您自己的方式抖动图像)
颜色缩减简介
颜色缩减是 ImageMagick 的一个非常重要的方面。例如,要将包含数百万种颜色的 JPEG 或 PNG 图像转换为包含最多 256 种颜色的 GIF 图像,您确实需要能够以高效且有效的方式缩减颜色。在图像格式转换过程中,这通常会在后台自动发生,但也有一些情况下您需要手动执行此操作。减少图像中的颜色数量通常是一个三步过程。- 首先,您通常需要调查图像使用的颜色。不仅要查看实际使用了多少种颜色,还要查看特定颜色使用了多少次。如果只使用一个像素使用了一种特定颜色,那么保留该颜色是没有意义的,尽管有时您仍然需要这样做。
- 接下来,您需要以某种方式决定要将图像限制到的最终颜色集。您可能希望 IM 尝试确定特定图像的“最佳”颜色集。在其他情况下,您可能希望使用更通用且全局的东西,该东西可以应用于任何图像。您甚至可能希望专门从将使用的颜色集中添加或删除一种颜色。
- 最后,您需要修改图像以仅使用您选择的颜色。最好是希望结果看起来不错,或者您可能希望它压缩、比较或优化效果很好。
颜色调查
这可能是最不重要的,虽然 IM 为您提供了执行调查的方法,但用户很少出于颜色缩减的目的而这样做。我将把进一步的讨论留给相关部分,提取图像颜色。颜色选择(量化)
有关良好的初始概述,请参阅 维基百科,颜色量化。有四种基本方法可以选择颜色。这四种颜色控制方法:量化、预定义颜色映射、均匀颜色 和 阈值;它们都有自己的局限性,正如您将看到的。以下是如何使用这四种方法的示例...
magick colorwheel.png +dither -colors 32 color_quantize.gif magick colorwheel.png +dither -remap colortable.gif color_predefined.gif magick colorwheel.png +dither -posterize 3 color_uniform.gif magick colorwheel.png \ -separate -threshold 50% -combine color_threshold.gif |
-colors
”)将实际根据当前图像内容选择颜色。由于测试图像主要是白色,因此选择了许多较浅的颜色。它使用一种称为“自适应空间细分”的技术(使用八叉树)来调查图像中的颜色。然后尝试选择一组特定颜色来最佳匹配特定图像,在给定限制内。请参阅下面的 颜色量化操作符。“-remap
” 允许您为 IM 提供自己的预定义颜色集(请参阅 用户定义颜色映射)。上面使用的颜色映射“colortable.gif
” 是一组 32 种颜色,专门为在旧的 X 窗口图标库 中使用而挑选,并且专为卡通图标而设计。(请参阅 AIcon 库,X 图标颜色选择 获取详细信息)。使用“-posterize
” 还可以通过数学方式将每个颜色通道划分为一组颜色级别或强度,从而产生“均匀颜色映射”。也就是说,颜色映射中的每个通道都设置为一组恒定的值或强度。最后,可以对图像的所有颜色通道或特定颜色通道进行“-threshold
”,实质上使每个颜色通道纯粹是布尔值或开/关。也就是说,每个颜色通道可以被赋予 0 或 MaxRGB(IM 的“Q”级别相关)的值。但是,这只会产生约 8 种颜色的最小集合。一种非常有限的颜色集。阈值也等效于“-posterize
” 级别“1”,它会选择 2 种颜色。应用颜色集
一旦您拥有了一组颜色,下一个问题就是将颜色应用于图像,以便用所选颜色集替换现有颜色。这被称为“抖动”,之所以这样命名是因为它具有“我应该选择这个还是那个?”的非此即彼特性。基本上,抖动的想法是将不同颜色的像素放置在彼此附近,以欺骗人眼看到图像中实际使用的颜色比实际更多的颜色。也就是说,由于人眼“融合”了相邻的颜色,因此图像中该区域的颜色更接近图像的原始颜色。关于抖动的最佳介绍之一是在 维基百科 上,尽管您需要跳过开头关于“音频抖动”的部分。这展示了一组出色的示例,说明在颜色集有限的情况下使用抖动像素模式的好处。颜色替换的基本样式包括...- 直接颜色映射(阈值和海报化)
- 随机抖动(纯粹随机放置像素)
- 错误校正抖动(像素的伪随机模式)
- 有序扩散像素抖动(像素的规则模式)
- 数字半色调(不同大小的点)
所有这些色彩还原方面的技术都很重要,通过理解它们,你可以改善图像操作的结果,超越 IM 提供的通用默认值。 值得学习。
图像中的颜色
有关图像的信息,例如使用的颜色数量和整体分布,对于试图决定最佳技术的使用方法的程序和脚本来说非常重要。 在这里,我将介绍一些你可以用来确定此类信息的方法,而不仅仅是用于颜色还原。提取图像颜色
提取调色板
你可以使用冗长的“identify
”从图像中提取调色板,使用以下任何方法,这些方法本质上都执行完全相同的事情。
magick identify -verbose image.png magick image.png miff:- | identify -verbose - magick image.png -verbose -identify null: magick image.png -verbose info: |
如果颜色超过 1024 种,则以上任何冗长的识别方法都不会返回调色板或直方图! 因此,对于大型彩色图像,这是一种碰运气的做法,不建议使用,尽管它仍然可能有用。 |
histogram:
”,并提取结果中包含的注释。
|
|||
|
“info: ”输出格式是在 IM v6.2.4 中添加的。 对于此版本之前的 IM 版本,请使用...
|
-unique-colors
”操作符会将图像转换为更小的图像,其中包含在原始图像中找到的每种唯一颜色的一个像素,所有像素都在一行中。 这意味着你可以将图像转换为更简单的调色板图像,列出每个存在的颜色。 图像的宽度返回颜色数量,如果你需要实际列出颜色,可以将其输出到“txt:
”图像格式。 例如,以下是树图像的调色板。
|
-remap
”颜色还原操作符特别重要。(参见下面 预定义颜色映射)如果你想获得一个包含图像中颜色以及颜色数量的图像,以下是一个颜色直方图解决方案,它是在 IM 论坛讨论中开发的。
|
rose:
”图像包含 3020 种唯一颜色,这将花费很长时间并生成非常长的图像。 上面显示的玫瑰的 GIF 图像包含相同的颜色还原集。 结果图像仍然包含相同数量的像素,尽管用额外的透明像素填充,并且正如你所看到的,它显示了绿色灰色的优势、强烈的红色,以及非常强的纯白色峰值。 这可能不是最好的通用颜色直方图方法,但它对这幅图像效果很好。对于“histogram: ”和“-unique-colors ”操作符,颜色的顺序是未定义的,但似乎是按照红色、绿色,最后是蓝色通道值进行排序的。 这可能不是特定图像的最佳方法,但无法将三维颜色普遍排序为一维顺序。 |
提取平均颜色
可以使用“-scale
”将图像缩减为单个像素,从而快速找到图像的平均颜色。 例如,以下是内置“rose:
”图像的平均颜色。 我使用 FX 转义格式输出颜色,该格式返回一个可以直接在 IM 中使用的颜色字符串,无需更改。使用“%[pixel:...]
”FX 转义 的问题在于,它可能会返回颜色名称,例如 'white
' 或 'silver
',而不是 RGB 值。 但是,你可以通过使用三个 FX 转义 来模拟这一点,以返回所需的位深度的实际 RGB 值。 例如...
|
-format
”转义,它们可以用于提取有关图像的更具体信息,而无需解析冗长的“identify
”或“info:
”输出。 例如,你可以通过获取图像红色通道图像的 '%[mean]
' 灰度值来获取平均红色通道颜色。
提取特定颜色
从命令行,有两种基本方法可以从图像中提取特定的像素颜色。 或者使用 FX 转义,例如“%[pixel:...]
”或“%[fx:...]
”(见上文)在特定像素位置...或者,你可以使用“-crop
”简化图像,以剪切出你可能感兴趣的单个像素,并使用前面提到的任何方法。 例如...
特定(或接近)颜色的数量
这可以用来获取特定颜色的像素数量或百分比。 你所做的是将不是该颜色的任何东西都变成黑色,然后将该颜色变成白色。 例如,让我们获取 'tree' 图像中“yellow
”太阳的颜色数量。
|
-print
”选项等效于使用“-format ... -write info:
”,并且可以在图像处理中的任何地方使用。 然后,我使用特殊的“null:
”文件格式丢弃了不需要的图像。 你也可以保存图像以供以后使用作为蒙版。 请注意,虽然这对于小图像来说效果很好,但对于更大的图像(如高分辨率数字照片),'mean' 的精度不足以获得准确的像素数量! 本质上,上面使用 'mean' 适合生成比率,但不适合精确的像素数量。 要获得精确的像素数量,最好使用具有精确像素数量的直方图 'comment' 输出(见上文)。 上面的方法还可以使用 模糊因子 选项“-fuzz
”,在“-opaque
”操作符之前指定 '接近' 的颜色。比较两种颜色
所以你有两种特定的颜色,你想比较它们。 你可以使用“magick compare
”获取 RMSE(标准误差)...这很好,因为它可以让你获得两种颜色之间的距离,包括值方面的距离,以及从黑色到白色的距离的标准化百分比。 但是,此方法不能正确处理透明度。 例如,比较 '完全透明的黑色' 与 '完全透明的白色'。透明颜色实际上应该有零距离,因为完全透明是相同的,无论底层颜色如何。 相反,我们得到了一个 4 维超立方体距离)。 因此,上述颜色距离方法只适合比较完全不透明的颜色。除了获取实际距离,你还可以使用 模糊因子 来检查两种颜色是否接近。
|
1
'。 要获得实际的 '模糊' 因子距离,该距离将分离值,可以使用 'FUZZ' 度量。“标准化”值表明实际距离为 28.7%。 使用 模糊因子 与计算透明度涉及的 RMSE 不同。 也就是说,因为模糊因子是设计的,所以任何两种完全透明的颜色都被视为相等。 因此,'完全透明的黑色' 和 '完全透明的白色' 是完全等价的(产生 0 或没有错误像素的值)...另一种颜色比较方法是尝试使用适当的 模糊因子 百分比来 替换颜色。 例如...由于 'Navy
' 没有更改为 'Blue
',因此它与 'Blue
' 的差异大于 20%。 然而这确实将颜色更改为 'Blue
',因此我们现在知道 'Navy
' 与 'Blue
' 之间的距离介于 20% 到 30% 之间。 要在脚本中执行此操作,请使用类似以下内容...
fuzz=%1 color1="red" color2="#e00" color2=`magick xc:"$color2" -format '%[pixel:s]' info:` result=`magick xc:"$color1" -alpha set -channel RGBA -fuzz $fuzz \ -fill $color2 -opaque $color2 -format '%[pixel:s]' info:` if [ "$result" = "$color2" ]; then echo "Colors match according to Fuzz Factor" else echo "Colors DO NOT match" fi |
-alpha set -channel RGBA
”对于允许我们对透明和接近透明的颜色进行模糊匹配非常重要。颜色量化
颜色量化操作符
颜色量化最主要的工具,也是所有自动颜色还原内部使用的是“-colors
”操作符。 它实现了“自适应空间细分”颜色还原算法,并且是一个非常好的颜色还原算法。 以下是一个典型的示例,我有一个 'colorwheel' 图像,它包含很多颜色,我们要求 IM 将颜色数量减少到只有 64 种颜色,使用各种 抖动方法.
magick colorwheel.png -dither None -colors 64 colors_64_no.gif magick colorwheel.png -dither Riemersma -colors 64 colors_64_rm.gif magick colorwheel.png -dither FloydSteinberg \ -colors 64 colors_64_fs.gif |
None
' 或“+dither
”设置),你可以清楚地看到哪些颜色合并在一起,以生成 IM 认为最适合该特定图像的颜色集。 你还可以看到,如果未进行抖动,颜色渐变会导致突然的颜色变化。 当然,这张图像使用的颜色比大多数图像使用的颜色要多得多。 因此,虽然 64 种颜色的限制对于许多图像来说通常是可以接受的,但对于这张图像来说完全不可接受。 换句话说,颜色量化试图找到最适合特定图像的颜色集。 以下是使用极少的颜色对 IM 标志一部分进行颜色量化的示例。
magick logo: -resize 40% -crop 100x100+105+50\! -normalize logo.png magick logo.png +dither -colors 8 colors_8_no.gif magick logo.png -dither Riemersma -colors 8 colors_8_rm.gif magick logo.png -dither FloydSteinberg \ -colors 8 colors_8_fs.gif |
rose:
”照片图像的一些结果进行比较。
magick rose: +dither -colors 16 colors_16_no.gif magick rose: -dither Riemersma -colors 16 colors_16_rm.gif magick rose: -dither FloydSteinberg \ -colors 16 colors_16_fs.gif |
IM 目前只实现了一种颜色量化算法,“自适应空间细分”,并且由于它效果很好,因此很少需要添加其他算法。 但是,随着反馈的不断增加,该算法正在稳步改进。 旁白:作为参考,“ Gifsicle ”程序列出了许多其他颜色量化方法(使用它的“--color-method ”选项)。 我不知道这些颜色量化方法与 IM 相比如何。 如果你找到了关于不同颜色量化方法的良好参考,请给我发邮件。 |
颜色量化内部机制
选择图像中要使用的有限数量的颜色称为颜色量化,这是一个非常复杂的过程,涉及许多因素。 ImageMagick 网站上给出了它的完整技术描述 颜色还原算法。 但是,我将尝试在这里举例说明其中一些更重要的方面。 也许最大的因素是图像中实际使用的颜色。 如果你在图像中很少有像素 '接近' 某种特定颜色,那么选择这种特定颜色是没有意义的。 因此,颜色选择不仅取决于图像中使用的颜色,还取决于 '接近' 该颜色的像素数量。 我可以通过尝试将两幅不同的双色图像还原为一种共同的颜色来轻松地展示这一点。
magick -size 4x1 xc:blue -draw 'fill red point 0,0' \ -scale 20 colors_rb.gif magick -size 4x1 xc:red -draw 'fill blue point 3,0' \ -scale 20 colors_br.gif magick colors_rb.gif -colors 1 colors_rb2.gif magick colors_br.gif -colors 1 colors_br2.gif |
magick -size 20x640 gradient: -rotate 90 gradient.png magick gradient.png +dither -colors 5 colors_gradient.gif |
FUTURE: Just what are the effects of the "-treedepth
" setting?
Mail me if you know
颜色量化和颜色空间
选择颜色的另一个重要影响因素是准确地定义“接近”或“附近”的颜色。这是由用于量化(颜色选择)的颜色空间定义的,并且(截至 IM v6.2.8-6)由 "-quantize
" 颜色空间设置控制。当选择非常少的颜色时,"-quantize
" 设置变得尤为重要。为了演示,让我们使用各种不同的颜色空间并定义不同的“颜色距离”来减少一个标准的 'colorwheel' 图像。
|
CMYK 颜色空间(未显示)也产生相同的结果,但原因不同。由于内部“K”通道和图像“颜色映射”使用相同的数据指针(参见 调色板通道),IM 在量化之前将其转换回 CMY。 |
在撰写本文时,IM 使用的颜色距离算法没有考虑颜色空间“色调”的循环性质。这个算法非常不同。因此,“红色”路径上会出现一个强烈的间断,色调在那里环绕,导致颜色量化过程中选择的红色很少。 |
在较旧版本的 IM(特别是 IM 版本 5)中,用于量化的颜色空间是使用 "-colorspace " 选项设置的。但是,在 IM 版本 6 中,此运算符用于修改图像在内存中的存储方式,因此它不是颜色量化的设置。因此,在 IM v6.2.8-6 中," -quantize " 设置被提供来执行这项工作。但是,它仅仅是 "-colors ",颜色量化过程的设置。它不会对使用 "-remap " 和 "-posterize " 等运算符进行的颜色替换和抖动,或者各种抖动技术有任何影响。 |
-colorspace
" 运算符。你可以通过查看 随机的纯色斑点 上的示例,看到颜色空间对颜色选择的影响。颜色量化用于使用各种颜色空间减少随机图像中的颜色数量。 量化不会保留颜色
请注意,在以上所有图像中,纯黑色从未被颜色量化实际选中。请记住,图像中只有一个纯黑色像素,而且几乎没有近黑色像素。因此,最终图像中出现的唯一黑色是在图像标记过程中稍后添加的。即使是“GRAY
”颜色空间图像也没有产生纯黑色。实际上,所有图像都不包含任何主色或次色,例如:红、蓝、绿、青、洋红!唯一的例外是白色,因为图像包含相当多的纯白色,使其成为“首选颜色”(见下文)。但是,这种情况不是错误!首先,“black
”颜色通常不会在上面的示例中被选中,通常是因为原始图像中只有很少的黑色,因此颜色量化通常不关心深色。实际上,它生成了更多更浅的颜色,因为这些颜色在图像中更常见。请参见上一节以了解具体示例。其次,由于量化正在尝试选择与图像中最大数量的现有颜色像素接近的颜色,因此最好的方法是不要匹配“纯”主色或次色,因为这些颜色始终位于所用颜色空间的极端位置。“偏色”往往比“主色”更匹配更多颜色,因此这些颜色更容易被选中。所以让我明确一点… 颜色量化(“
-colors") 通常会避免选择主色!white
”),该颜色通常将包含在最终颜色映射中。这在一定程度上改善了情况,特别是对于“卡通”图像或具有纯色背景的图像。通常会选择“纯色”,以帮助避免 抖动斑点,我们将在下面介绍。颜色映射中的特定颜色解决方案目前,只有一些方法可以确保“特定颜色”被包含在为后续抖动选择的颜色中。一种方法是按正常方式对图像进行量化,但随后输出生成的色图(使用 "-unique-colors
")。现在你可以调整色图,使你的特定颜色真正变成那个颜色。最后,你可以使用 重新映射颜色 运算符使用提供的色图对图像进行抖动。色图可能不再是图像的最佳颜色,并且某些其他颜色可能也应该调整,但它将接近你想要的色图。或者,在使用 "-colors
" 之前,将想要保留在图像中的特定颜色的大块色块附加(放大图像)。添加特定颜色的大“色块”将使该颜色更有可能在最终色图中被选中。此外,所有其他颜色将自动调整以更好地适应该色图)。如果这有效,则你添加的色块应该保持不变(不进行抖动)。之后,你可以 裁剪 图像以删除添加的色块。如果它不起作用,则 IM 至少应该添加一个接近所需“特定颜色”的颜色,因此在将 重新映射颜色 应用于原始图像之前,只需要稍微调整一下生成的色图即可。如果你尝试这样做,无论成功或失败,请告诉我你的结果。理想情况下,我希望看到一种方法来指定少量特定颜色,这些颜色必须是最终色图的一部分,然后以某种方式要求 IM 为色图中剩余的颜色选择最佳颜色,针对特定图像。 颜色量化和透明度
ImageMagick 默认情况下不仅会生成完全不透明的颜色,还会尝试生成半透明的颜色。通过这种方式,包含透明阴影或其他叠加效果的图像不会丢失这些效果。然而,截至 IM v6.2.6,涉及透明度的颜色量化进行了修改,以便将所有完全透明的颜色视为相同颜色。这是一个线性修改,因此只有半透明的颜色被认为彼此更接近,而不是完全不透明的颜色。由于这种修改,IM 颜色量化仍然会生成半透明颜色,但会更多地关注图像中的不透明颜色,而更少地关注完全透明的颜色。例如,这里我生成一个 彩虹渐变,图像顶部完全不透明,底部完全透明。我在背景图案上显示了图像,这样你就可以看到图像的透明度。
magick xc:red xc:yellow xc:green1 xc:cyan xc:blue \ +append -filter Cubic -resize 100x100\! -size 100x100 \ gradient: -alpha off -compose CopyOpacity -composite alpha_gradient.png magick alpha_gradient.png +dither -colors 256 alpha_colors_256.png magick alpha_gradient.png +dither -colors 64 alpha_colors_64.png magick alpha_gradient.png +dither -colors 15 alpha_colors_15.png |
当涉及透明度时,IM 颜色量化
可能不会选择任何完全不透明的颜色,甚至不会选择完全透明的颜色!
当然,从 IM v6.3 开始,以及“常见颜色”错误修复(见上面的 量化不会保留颜色),如果图像包含大量不透明和完全透明的颜色,这种情况发生的可能性较小,这很常见。由于某些图像可能包含大量半透明颜色,例如包含烟雾或阴影效果的图像,你可能希望进行试运行,以确保为最终图像中包含的图像选择完全透明的颜色。然后,你可以将最透明的颜色映射到完全透明,并自己进行 重新映射颜色。如果你确实想确保最终图像中包含完全不透明和完全透明的颜色,你可以 规范化或对比度拉伸 Alpha 通道。例如,这里我确保使用 "可能不会选择任何完全不透明的颜色,甚至不会选择完全透明的颜色!
-contrast-stretch
" 使主色选择变得不透明。尽管这对于更正常的情况来说可能有点过于粗暴。
magick alpha_gradient.png +dither -colors 15 \ -channel A -contrast-stretch 10% alpha_colors_15n.png |
-quantize
" 颜色空间设置 'transparent
' 来实现这一点。请注意,颜色量化完全忽略了颜色的透明度,并且完全没有触及图像的 Alpha 通道。这意味着您可以以更适合您的图像的方式处理 Alpha 通道,完全独立于其他颜色。实际上,您可以在使用 "-colors
" 之前或之后进行处理,都不会有任何问题。结果不会有任何差异。因此,当您要将图像缩减为带有布尔值或没有透明度的格式(例如 GIF 或 XPM 图像格式)时,建议使用这种量化颜色空间。如果您计算生成的颜色的数量,您还会发现它恰好生成了您请求的颜色的数量。因此,如果您还需要一个完全透明的颜色(可能需要),则需要将 "-colors
" 的参数至少减少一个,以便在图像的最终颜色表中为它留出空间。因此,要处理 GIF 文件格式 256 色颜色表限制,您需要将颜色缩减到 255,而不是 256,为完全透明的颜色索引留出额外的空间,如 "-transparent-color
" 设置定义。对于更小的颜色表大小,请进行相应的调整。当 IM 保存到 GIF 文件格式时,这种量化行为是自动的,但在您需要在生成全局或共享颜色表时自己进行量化时非常重要。当然,您仍然需要处理半透明像素,这样它们才能符合您希望图像的外观。FUTURE: This last part will probably move to a new section on 'Dithering Alpha Channel' to be created in the near future. And a reference to this section added here.以下是一些仅对 Alpha 通道进行抖动以将其转换为布尔值或开/关设置的示例,而不会影响图像中其他颜色通道。
magick alpha_gradient.png \ -channel A -threshold 50% alpha_dither_threshold.gif magick alpha_gradient.png \ -channel A -ordered-dither checks alpha_dither_checks.gif magick alpha_gradient.png \ -channel A -ordered-dither o8x8 alpha_dither_ordered.gif magick alpha_gradient.png \ -channel A -ordered-dither h8x8a alpha_dither_halftone.gif magick alpha_gradient.png -channel RGBA -separate \ \( +clone -monochrome \) \ +swap +delete -combine alpha_dither_monochrome.gif magick alpha_gradient.png -channel RGBA -separate \ \( +clone -dither FloydSteinberg -monochrome \) \ +swap +delete -combine alpha_dither_monochrome_fs.gif magick alpha_gradient.png -channel RGBA -separate \ \( +clone -remap pattern:gray50 \) \ +swap +delete -combine alpha_dither_map.gif magick alpha_gradient.png -channel RGBA -separate \ \( +clone -dither FloydSteinberg -remap pattern:gray50 \) \ +swap +delete -combine alpha_dither_map_fs.gif |
当对 Alpha 通道的副本进行抖动时,您可以使用 "-monochrome " 或 "-remap " 进行抖动,请确保图像是一个纯灰度图像,而不是包含透明度的形状蒙版。如果您没有这样做,您可能会遇到 Alpha 通道仍然存在导致的非线性效果。有多种方法可以从图像中提取和恢复 Alpha 通道,作为灰度蒙版,以便您可以对其进行抖动。上述方法使用 通道分离 和 合并 来实现。其他方法使用 Alpha 提取 结合 CopyOpacity 合成。 |
误差校正抖动
正如引言中所述,误差校正抖动通常被认为是生成具有缩减颜色集的原始图像最真实表示的最佳选择。它还将自身限制在任何预定义的颜色调色板中,无论它是用户提供的,还是由 IM 颜色量化例程确定的。因此,它是在 IM 运算符 "-colors
"、"-remap
"、"-posterize
" 和 "-monochrome
" 提供的一般颜色缩减中合乎逻辑的默认选择。 E-抖动方法
从 6.4.2-9 版本开始,IM 现在提供了多种抖动样式或方法,可以使用 "-dither
" 设置进行选择。在此之前,IM 仅限于 Riemersma 抖动 或 希尔伯特曲线抖动 的变体,您可以使用 "-dither Riemersma
" 进行设置。现在,您还可以使用 "-dither FloydSteinberg
" 选择 Floyd-Steiberg 抖动。您可以使用以下方法查看您的 IM 版本中已实现的抖动方法类型...例如,以下是使用不同抖动方法进行抖动的色轮。
magick colorwheel.png -dither Riemersma -colors 16 dither_riemersma.gif magick colorwheel.png -dither FloydSteinberg -colors 16 dither_floyd.gif |
E-抖动的工作原理
正在重新编写
IM 用于一般抖动的具体方法是 "希尔伯特曲线误差校正抖动" 的变体。这实际上是一种非常好的抖动技术,定义明确且速度合理。有关完整描述(以及非常相似的变体),请参阅... Riemersma 抖动。基本上,图像中的每个像素都以一种称为 '希尔伯特曲线' 的非常复杂的路径进行查看。像素被分配给最接近该像素值的颜色,并且像素原始颜色与所选颜色之间存在的任何差异都会被保存并添加到下一个像素的颜色值(始终是相邻像素)中,然后再次选择新的颜色。通过这种方式,任何选定颜色与图像原始颜色之间的颜色变化都会分布到同一区域中的其他像素。结果是,虽然最终图像中只会分配特定颜色,但该区域的基本整体颜色将与原始图像非常匹配。例如,以下是一个小灰度图像,我要求 IM 使用一组不包含原始颜色的颜色对其进行抖动。结果图像被放大,以便您可以看到分配的单个彩色像素。
|
|
E-Dither 问题 - 变化敏感
使用误差校正抖动时遇到的最大问题之一是,您将获得一个基本上随机的像素模式,并且对变化非常敏感。例如,以下是用原始灰度图像替换一个像素,使其成为不同的颜色,然后对其再次进行抖动。结果是希尔伯特曲线抖动所遵循的路径中每个更远像素的抖动模式都会发生完全转变。
|
原始抖动 |
一个像素变化 |
变化对比 |
magick compare
" 图像还显示了抖动模式变化的程度。在本例中,大约 80% 的像素被分配了完全不同的颜色。在希尔伯特曲线抖动中,单个像素变化实际上会导致每个后续像素可能不同,这意味着抖动模式可能会发生 0% 到 100% 的变化。这取决于变化发生在复杂的希尔伯特曲线的哪个位置。但是,Floyd-Steinberg 抖动只以一个方向遍历图像,因此单个像素变化只会修改该变化一侧的模式。
magick -size 10x10 xc:'#999999' -draw 'fill #C28 point 2,2' \ -dither FloydSteinberg -remap colortable.gif \ -scale 80x80 dither_fs_modified.gif magick compare dither_fs.gif dither_fs_modified.gif dither_fs_difference.gif |
FS 抖动 |
一个像素变化 |
变化对比 |
|
与其他抖动方法(如 阈值 和 有序抖动)不同,"-channel " 设置不会影响颜色量化或错误校正抖动。基本上,它在这些图像操作的运作方式中没有作用。 |
E-抖动像素斑点
E-抖动另一个问题是,它们可能会在原本颜色相当均匀的区域产生偶尔的奇异颜色像素。例如,在灰度图像中偶尔会出现绿色像素。或者,如以下示例所示,在一个原本平坦的蓝色区域中会出现白色像素。这在包含大量颜色对象的图像以及其他平坦的、不变的纯色区域的图像中尤其常见。在将彩色物体叠加到平坦的彩色背景上的图像中,这尤其常见,因为你经常会在图表和图纸中看到这样的情况。你可以在上面测试示例的放大图中看到这样的奇异颜色像素,其中一个额外的浅紫色像素被添加到距离小单像素更改相当远的距离。然而,添加到上面的奇异颜色像素并不容易看到,并且色图相当好地覆盖了图像,因此奇异像素相当接近用于抖动图像的正常三种颜色。为了更极端的例子,这里我有一个模糊的渐变背景,我将其大幅降色到 64 种颜色,以真正地强调错误校正抖动。
|
这是一个小区域的放大图,这样你就可以更清楚地看到这些像素……
|
|
以及与之前相同的区域的放大图。
|
|
除了添加额外的颜色之外,更通用的方法是尝试从最终的抖动图像中去除点状分布。也就是说,以某种方式清理图像。但是,这本身就是一个棘手的问题,因为你不知道要删除哪些像素是正常抖动模式的一部分。我们需要的是找到颜色像素,这些像素在某种程度上与周围的所有颜色都非常不同,但同时也与所有其他类似颜色保持一定距离。 你有没有更好的图像滤波器解决方案?总结对我来说,点状分布是一个非常令人讨厌的问题,尤其是对于使用非常有限的颜色表的桌面图标图像。我经常编辑较小的“图标”图像以去除点状分布或修复一些其他抖动效果,例如垂直条带。如果你知道其他更好的解决方案,请告诉我。
单色抖动位图图像
"-monochrome
" 运算符是 "-colors
" 运算符的专用形式,用于生成位图图像。因此,它是展示“希尔伯特曲线抖动”以及更仔细地观察颜色选择的理想运算符。这是一个典型的示例。
|
-monochrome
" 运算符抖动。感谢伊万诺娃 -remap
" 运算符,使用纯黑白色图(由内置模式图像提供)。
|
-remap
" 选择颜色,你可以有效地产生与 "-monochrome
" 运算符使用的相同“阈值”范围,或你喜欢的任何其他阈值范围。
|
-monochrome
" 实际上是先将给定图像转换为灰度图像,然后执行双色 '颜色量化',以确定用于抖动图像的阈值颜色。这是下一部分示例将探讨的内容。"+dither " 设置目前对 "-monochrome " 的结果没有影响。然而,这在未来可能会改变,因此请确保在使用此运算符时,你的脚本中没有将其关闭。 |
双色量化
与其自己选择两个控制颜色,不如使用颜色量化,通过使用 "-colors " 运算符来选择图像中最好的两种颜色。
|
-monochrome
" 不一样,因为我们没有先将图像转换为灰度图像。相反,图像直接在选定的两个非灰色颜色值之间进行抖动。也就是说,选择最好的两种颜色来抖动图像,而不是两种灰度亮度级别。因此,它将为只有大约相同灰度“级别”的颜色图像产生更好的结果。例如,这里我们使用 "-colors
" 以及 "-monochrome
" 位图抖动运算符,作用于红蓝色渐变。如你所见,结果并不相同。
magick -size 20x640 gradient:red-blue -rotate 90 gradient_rb.png magick gradient_rb.png -colors 2 -colorspace gray \ -normalize colors_threshold.gif magick gradient_rb.png -monochrome mono_threshold.gif |
-monochrome
" 运算符无法找到任何与位图抖动不同的差异,因为蓝色和红色几乎具有相同的强度。然而,使用 "-colors
" 量化方法却可以轻松找到可接受的颜色来进行抖动。你还可以看到,只有中间部分的颜色被抖动了。这是因为颜色量化在它选择的两个颜色“簇”的中间选择颜色。因此,在选定颜色“外部”的颜色实际上被直接阈值化为该颜色,而没有进行抖动。这表明颜色量化颜色空间外部的颜色不会被抖动,虽然这个事实很难在实践中使用。通过在量化之前将 "-colorspace " 设置为灰度,你将复制 "-monochrome " 运算符的内部操作。
|
最后,通过关闭抖动,你可以产生比使用固定 "-threshold " 设置更自动的颜色分离。
|
请记住 "-monochrome " 目前忽略 "+dither " 设置,因此你不能只使用该运算符来进行“智能阈值”。 |
如果你删除图像处理颜色量化阶段的 "-colorspace ",你可以根据图像可能实现的最佳颜色分离(而不是灰度颜色分离)对图像进行阈值处理。
|
使用预定义颜色映射抖动
如上所示,"-colors
" 尝试选择最优的有限颜色集来表示图像。使用 "-remap
",您可以为 IM 提供要用于图像的最终颜色集,无论您计划抖动这些颜色,还是只是用其最近的邻居替换它们。参数以包含要使用的所有颜色的图像形式给出。如果您想将大量颜色图像简化为其颜色列表,您可以使用 "-unique-colors
",在保存之前,用于 "-remap
" 的后续使用。请注意,虽然 "-remap " 运算符将接受任何图像以供使用,但不要为此图像使用 JPEG 图像,否则由于其“有损压缩”会生成额外的颜色,您将获得大量额外颜色。另一方面,使用 JPEG 生成额外颜色可能有助于解决之前看到的“斑点”问题! |
Riemersma
" 抖动,但从 IM v6.4.4 开始,"-dither
" 已扩展为允许选择其他抖动方法,例如 "FloydSteinberg
"。您当然仍然可以使用 "+dither
" 选项关闭抖动。
magick logo.png -dither None -remap colortable.gif remap_logo_no.gif magick logo.png -dither Riemersma -remap colortable.gif remap_logo_rm.gif magick logo.png -dither FloydSteinberg \ -remap colortable.gif remap_logo_fs.gif |
colortable.gif
" 图像从未设计用于抖动图像,而是一个用于为更原始的 X 窗口颜色显示器设计卡通风格的彩色图标的颜色集(有关详细信息,请参阅 Anthony 的 X 窗口图标库 和 AIcons 颜色选择)。还要注意,最终图像没有使用此映射提供的全部 32 种颜色,尽管在启用某种抖动时,映射中的更多颜色将被使用( 和 分别),而不是在禁用它时 ()。最后一个示例表明选择一个好的颜色映射是多么重要。因此,我建议您让 IM 使用 "-colors
" 运算符优化图像中使用的颜色选择,并根据您的需要进行修改,除非您有更迫切的理由不这样做。最后一点,虽然您可以在 "-colors
" 将找到最佳颜色集的颜色空间中指定一个颜色空间,但您目前无法为颜色映射或抖动阶段定义一个颜色空间。我的所有实验似乎都表明,颜色集是基于 RGB 空间应用的(包括误差校正抖动和最近颜色替换)。"-quantize
" 颜色空间设置仅用于选择颜色,而不是映射。那么,如果使用颜色映射是一个糟糕的主意,为什么您会想要使用它呢?通常有几个常见原因,通常是因为您需要更多地控制图像中使用的特定颜色调色板。另一位用户还将颜色映射分离出来,以便他可以在 Risograph(一种数字印刷系统)上使用它。如果您知道其他原因要使用 "-remap
" 运算符,而我尚未在下面介绍 - 请给我发邮件。 常用或“最佳”颜色映射
在处理多个图像时,另一种技术是为所有涉及的图像生成一个公共颜色表。基本上,您将所有图像附加在一起形成一个大型图像,然后使用 "-colors
" 运算符找出适合所有图像的良好颜色映射。获得该颜色映射图像后,您可以使用它重新对每个原始图像进行着色,使用此刚刚生成的 预定义颜色映射。或者,您可以使用特殊的 "+remap
" 运算符,它对 255 色颜色映射执行相同操作。它计算颜色,执行颜色量化以形成良好的公共颜色映射,然后在需要时抖动图像以使用该映射。然而,"-remap
" 和 "+remap
" 两种形式都具有 GIF 动画的一个非常重要的功能。它将所有图像转换为 "-type
" 为 "Palette
" 的图像,所有图像都使用相同的颜色调色板。原因是,当写入 GIF 图像时,第一个图像的调色板将用于文件格式的“全局调色板”。然后,在写入每个图像时,它会注意到这些图像使用相同的颜色集,因此它不会创建“局部调色板”。这可以为最终 GIF 文件中的每个图像节省高达 256 × 3 或 768 字节的调色板空间。只有 "-remap
" 运算符可以做到这一点。因此,在处理 GIF 时,特别是 GIF 动画时,这将是一个重要的要点。有关更多详细信息和示例,请参阅 Gif 动画,全局颜色表。 网络安全着色
当 WWW 首次创建时,计算机显示器提供的颜色范围有限,而网络浏览器通常使用更简单的颜色集来显示图像。因此,通常会将图像重新着色为此颜色集,以使图像更小,并确保它们在用户的浏览器上看起来不错。有关更多详细信息,请参阅 网络样式指南,抖动。为了帮助解决此问题,IM 提供了一个内置颜色映射图像,它包含此特殊的 216 色表,称为 "netscape:
"。因此,让我们看看我们的测试图像在使用这些颜色的旧 Web 浏览器显示器上的显示效果。
magick logo.png -remap netscape: remap_netscape.gif magick logo.png +dither -remap netscape: remap_netscape_nd.gif |
生成颜色映射
确定任何图像或特定图像集的良好颜色映射非常重要。当您处理将用于 GIF 动画的图像序列时,这一点尤其重要。基本上,您希望使其能够只使用一个颜色表,用于动画的所有帧,而不是为每个帧使用一个单独的颜色表。换句话说,您希望所有图像都使用一个单一颜色映射。在这种情况下,您实际上只有两种选择。您可以尝试创建一个适合任何图像的颜色映射,或者尝试针对您应用它的特定图像集优化颜色映射。网络安全颜色映射
第一种方法通常是数学生成的色图,例如 IM 内置的 "netscape:
" 色图。这提供了 216 种颜色,这些颜色可以很好地适应 GIF 格式的 256 种颜色限制,并且仍然有空间用于处理图像透明度,甚至为特殊目的添加一些额外颜色,如阴影或文本叠加。此颜色映射是通过为三个颜色通道中的每一个创建 6 个颜色级别生成的,产生 6×6×6 个颜色或 216 个颜色。野兽的数量。由于仅使用 219 种颜色,因此它仍然有空间(用于 GIF 图像)为特定目的向颜色映射中添加更多颜色。例如,透明颜色以及更多灰度色调。Macintosh 的旧版网络安全地图实际上就是这样做的,以试图改善其整体结果,但它仅在 Macintosh 网络客户端上使用。这可能是最常见的“统一” (或数学推导)颜色映射,得益于其简单性和在万维网上的一般使用。 统一 332 色图
另一个常用的统一颜色映射是“332 RGB 颜色映射”。该数字指的是在 8 位颜色索引中表示每种颜色所使用的位数。也就是说,3 位(或 8 个级别)红色,3 位绿色,以及 2 位(或 4 个颜色级别)蓝色,因为我们的眼睛对蓝色没有很好的反应。这提供了 3+3+2 位或 8 位颜色索引,或 256 种颜色。非常适合有限的 GIF 颜色表。但是,它不会为 GIF 透明颜色或其他特殊用途颜色留出任何空间。以下是一种让 IM 生成此颜色映射的方法…
|
在 IM 6.2.9-2 版本之前,"-fx " 运算符中缺少位移运算符 ">> " 和 "<< "。 |
-ordered-dither threshold,8,8,4
" (请参阅该示例区域)。与以上 DIY FX 方法 相比,这是一种更轻松、更快的技术,甚至允许您使用其他内置抖动映射来更好地处理渐变。此映射的唯一缺点是它实际上根本没有提供任何“灰色”颜色。但是,此缺点在使用抖动时可能成为优势,因为轻微的颜色差异会减少灰度渐变中颜色边界变化的影响,使其看起来更加平滑。 真彩色 16 位颜色映射
X 窗口在很少使用的 16 位视觉类别中使用的“332 色图”类似的统一色图。在这种情况下,16 位用于颜色索引,该颜色索引被划分为 5 位红色,5 位绿色,以及 6 位蓝色。换句话说,此颜色映射更像是“556 颜色映射”,最好使用 使用统一颜色级别的有序抖动 使用“阈值”抖动映射来实现。具体来说是操作 "-ordered-dither threshold,32,32,64
"。但是,16 位颜色映射很少见,因为使用颜色映射的图像通常需要 8 位颜色表。因此,我不会进一步提及它。 伽马校正统一颜色映射
目前 IM 无法直接处理伽马校正颜色映射。相反,您应该使用 magick 对您的图像进行处理(假设您拥有 Q16 或更高版本的 IM 编译时 质量 版本),从 sRGB 或图像具有的任何伽马级别转换为线性 RGB 模型,然后再进行抖动。 这也适用于许多其他图像处理操作,例如调整大小、模糊等。有关示例,请参见 使用伽马校正调整大小。海报化,使用统一颜色映射重新着色
该操作符的最初用途(使用 '2' 的参数)是使用仅 8 种基本颜色重新着色图像,就好像该图像使用简单的廉价海报打印方法使用仅基本颜色生成一样。 因此该操作符得名。 实际上,“-posterize
” 操作符是一种特殊的颜色缩减操作符,它根据给定的每个颜色通道的“级别”数量生成颜色映射,并使用误差校正抖动对图像进行抖动。
magick netscape: -scale 50% +dither -posterize 2 posterize_2_ns.gif magick netscape: -scale 50% +dither -posterize 3 posterize_3_ns.gif magick netscape: -scale 50% +dither -posterize 6 posterize_6_ns.gif |
-posterize
” 参数 '2
' 意味着每个颜色通道仅提供 2 种颜色,为 3 通道 RGB 图像生成仅 8 种颜色的映射,例如上面所示。 它基本上会使用 8 种颜色的阈值集对图像进行重新着色。 参数 '3
' 将根据 27 种颜色的颜色映射映射图像颜色,包括中间色调颜色。 而参数 '4
' 将生成 64 色颜色表,而 '5
' 将生成 125 色颜色映射。 当然,如上所述,参数 '6
' 将复制与内置“netscape:
” 图像中提供的相同 216 色集。 请注意,“-posterize
” 参数 '0
' 或 '1
' 没有意义,并且在最新的 IM 版本中只是将图像转换为纯黑色(虽然合乎逻辑,但非常无用)。 结果是图像已使用数学推导的或“统一”的颜色映射重新着色。 您可以在渐变图像上更清楚地看到这一点,它会生成均匀分布的海报化灰度级。
|
magick logo.png +dither -posterize 2 posterize_logo.gif magick logo.png -posterize 2 posterize_logo_dither.gif magick logo.png -posterize 6 posterize_6_logo.gif |
magick colorwheel.png +dither -posterize 2 posterize_2_cw.gif magick colorwheel.png +dither -posterize 3 posterize_3_cw.gif magick colorwheel.png +dither -posterize 6 posterize_6_cw.gif |
-posterize
” 生成的伪随机抖动更多的样式选择。 将这些与上面显示的抖动“-posterize
” 版本进行比较。
magick colorwheel.png -ordered-dither o8x8,2 posterize_2_od.gif magick colorwheel.png -ordered-dither o8x8,3 posterize_3_od.gif magick colorwheel.png -ordered-dither o8x8,6 posterize_6_od.gif |
threshold
” 抖动映射(而不是上面使用的 'o8x8
')有效地将“-ordered-dither
” 转换为未抖动的海报化方法。 最后,有序抖动 允许您为每个单独的颜色通道指定不同的颜色级别数量。 “-posterize
” 操作符目前尚不支持此功能。阈值抖动方法
阈值图像
将图像转换为黑白位图(彩色)图像的最简单方法是使用“-threshold
”。 这实际上是一个简单的数学运算符,它只提供一个截止值。 等于或低于该值的任何值将变为黑色,而大于该值的任何值将变为白色。
magick logo.png -threshold -1 threshold_0.gif magick logo.png -threshold 25% threshold_25.gif magick logo.png -threshold 50% threshold_50.gif magick logo.png -threshold 75% threshold_75.gif magick logo.png -threshold 100% threshold_100.gif |
-1
' 的值会将所有颜色 magick 为白色,而 '100%
' 会将所有颜色转换为黑色。 '50%
' 当然是使用最常见的 value。'0 ' 的值是一种特殊情况,它会将所有非纯黑色变为白色。 当然,如果图像中没有纯黑色,那么您只会得到一个纯白色图像!
|
如果您实际上要将所有非纯白色 magick 为黑色,那么我建议您对 反转 的图像进行阈值处理,而不是尝试计算出要使用的正确阈值(比 IM 当前的“MaxRGB”小一),该值取决于您特定 IM 的 质量或“Q” 设置的编译时。
|
-threshold
” 操作符可以归类为终极“对比度”操作符,通过阈值级别最大限度地提高颜色差异。 但是它是一个灰度操作符,这意味着“-channel
” 设置可以用于调整将应用操作符的颜色通道。 例如,您可以对图像的每个单独通道进行阈值处理,以产生与未抖动的 2 级“-posterize
” 操作相同的效果。
|
请注意,“-threshold ” 将图像中的任何透明度视为蒙版通道,而不是 alpha 通道(就像它在 IM 中的内部存储一样)。 因此,如果您计划将此操作符应用于 alpha 通道,则需要谨慎。 有关更多详细信息,请参见 蒙版通道。 |
例如,这将根据图像中找到的最佳两种颜色对图像进行阈值处理。 这些颜色不一定必须是灰度色或甚至是相反色,只是最能代表整个图像的两种颜色。 然后使用“-normalize ” 将这两种颜色映射到纯黑色和白色。
|
随机抖动和阈值
“-random-threshold
” 操作符是一种特殊的位图图像转换形式。 在这种情况下,它使用非常简单的“随机抖动”来确定特定像素是否变为白色像素或黑色像素。 与“-threshold
” 或“-monochrome
” 操作符,甚至上一节中的变体不同,“-random-threshold
” 在每个选定通道上完全独立地工作,彼此之间没有任何关系。当然,直接使用该操作符将导致使用随机抖动对图像进行 2 级海报化。
|
转换为灰度级将使图像中的所有通道均衡化,然后进行抖动。 但是由于每个通道都是独立地且随机地进行抖动的,因此结果不是预期的位图图像。 相反,您将获得彩色像素的飞溅,特别是对于中间色调颜色。
|
以下是生成正确的随机抖动位图图像的正确方法。
|
-separate
” 通道操作符将该通道提取为最终的位图图像。 技巧但有效。作为该操作符的特殊功能,IM 将确保在“-channels ” 选项为 'All ' 时生成位图图像。
|
|
-random-threshold
” 设置为 '0x100%
' 将产生图像的纯粹“随机抖动”。 如果两个边界设置为相同的值(甚至超过彼此),它只会产生纯“-threshold
” 图像。 使用任何其他边界集(通常使用百分比指定)将在给定范围内对位图进行阈值处理,同时为给定范围内的值生成随机抖动模式。最佳结果可以通过使用略小的范围来获得,就像使用“-monochrome ” 操作符一样。 大约 '30x80% ' 的值可能是大多数情况下的最佳结果。
|
有序抖动
虽然随机抖动会产生随机的像素块,而各种错误修正抖动会产生基本上随机的点状图案,但有序抖动基本上是相反的。它被设计成尽可能地数学确定。确定性如此之高,以至于您实际上需要指定要在抖动图像时使用的图案。“-ordered-dither
” 操作符将对图像中每个选定的“-channels
” 进行给定预定义图案的抖动。参数定义要使用的图案(称为阈值图)。这些阈值图分为三种基本样式。分散像素抖动,其中像素尽可能地彼此远离放置,以避免“聚集”和平铺伪像。或者将它们聚集在一起形成紧密的点,这使得它们更容易在称为数字半色调的技术中进行机械打印。还有一些我们将要介绍的专门的艺术阈值图,甚至可以设计我们自己的抖动图案或阈值图。在每种情况下,阈值图中开启或关闭的像素数量取决于被抖动到位图中的图像(或单个颜色通道)的灰度强度。该图以一致的方式添加像素阈值级别,因此一旦像素在特定“阈值”处打开,它将保持打开状态以供任何更浅的灰色。这种一致性非常重要,否则会在抖动图案变化边界处产生伪像。关于这一点的重要一点是,图像中每个像素的结果纯粹由数学确定,独立于图像中任何其他像素。因此,对原始图像的任何微小更改都不会对图像的任何其他区域产生影响,这是错误校正抖动所面临的问题,如上所述。这一点对于视频图像的一致抖动和优化动画至关重要。 扩散像素抖动
有序抖动的最初目的,以及大多数图形程序员在使用有序抖动时所期望获得的结果,有时更准确地称为“分散像素有序抖动”。这意味着当阈值强度增加时,像素被添加到平铺图中,因此它们尽可能地彼此远离并均匀分布。这会产生一个高度一致的图案,在大多数现代显示器上看起来非常平滑且几乎不可见。此类图案已针对 2 的幂的平铺大小而计算得出,即 2、4 和 8 的平铺大小。虽然 IM 也为 3x3 阈值图平铺提供了一个合理的阈值图案。以下是 IM 目前提供的内置有序抖动的当前集合。请记住,参数反映有序抖动的平铺大小。
magick logo.png -ordered-dither o2x2 logo_o2x2.gif magick logo.png -ordered-dither o3x3 logo_o3x3.gif magick logo.png -ordered-dither o4x4 logo_o4x4.gif magick logo.png -ordered-dither o8x8 logo_o8x8.gif |
“o8x8 ” 有序抖动是 IM 核心代码的一部分,但一直没有使用。它只是作为 IM v6.2.9 中“-ordered-dither ” 操作符的选项添加的,当时 IM 示例开始详细介绍此操作符的使用。此时,这些地图被赋予了更明确的名称,以便进一步扩展“ -ordered-dither ” 操作符,尽管保留了较旧的向后兼容的“平铺大小”名称作为新名称的别名。此外,生成“o3x3” 和“o4x4” 的“地图”已被彻底修改,以产生更好的“分散像素”抖动图案。在此之前,地图会生成不同的像素“块”。 请参阅有序抖动升级说明页面,了解旧图案在修复之前的示例,以及在 IM v6.3.0 中升级的官方发布开发过程中进行的其他更改。 |
magick logo.png -colorspace Gray -ordered-dither o2x2 logo_bw_o2x2.gif magick logo.png -colorspace Gray -ordered-dither o3x3 logo_bw_o3x3.gif magick logo.png -colorspace Gray -ordered-dither o4x4 logo_bw_o4x4.gif magick logo.png -colorspace Gray -ordered-dither o8x8 logo_bw_o8x8.gif |
-ordered-dither
” “分散像素”图案应用于灰度渐变的效果,因此您可以清楚地看到它们的样子。
# Threshold Non-Dither / Minimal Checkerboard Dither magick gradient.png -ordered-dither threshold od_threshold.gif magick gradient.png -ordered-dither checks od_checks.gif # Diffused Pixel Dither magick gradient.png -ordered-dither o2x2 od_o2x2.gif magick gradient.png -ordered-dither o3x3 od_o3x3.gif magick gradient.png -ordered-dither o4x4 od_o4x4.gif magick gradient.png -ordered-dither o8x8 od_o8x8.gif |
o3x3
” 有序抖动将在结果图像中产生 3x3+1 或 10 个有效灰度级别(黑色、白色和 8 种人造灰色图案)。上面还显示了两个特殊的最小抖动阈值图- 一个直的“50% 阈值”非抖动,它不会产生任何额外的灰度级别,以及
- 一个“棋盘格”或棋盘格抖动图案,它只插入一个图案以在结果渐变中添加一个额外的“伪级别”。
数字半色调抖动
“-ordered-dither
” 在 IM v6.2.8-6 中进行了扩展,包含一组数字半色调抖动图案(感谢 Glenn Randers-Pehrson)。所有这些都被设置为产生一个简单的 45 度点图案。在 IM v6.3.0 中,它被进一步扩展了,包含一组类似的较大无角度半色调。在 IM v6.3.0 发布之前,半色调屏幕是通过使用形式为“{number}x1 ” 的参数来选择的。通过有序抖动的重新开发,此限制被解除,选择了更好的命名,并添加了额外的半色调屏幕(正交形式)(请参阅下面的示例参数)。 |
# Halftone Screen (45 degree angle) magick logo.png -ordered-dither h4x4a logo_h4x4a.gif magick logo.png -ordered-dither h6x6a logo_h6x6a.gif magick logo.png -ordered-dither h8x8a logo_h8x8a.gif # Halftone Screen (orthogonal) magick logo.png -ordered-dither h4x4o logo_h4x4o.gif magick logo.png -ordered-dither h6x6o logo_h6x6o.gif magick logo.png -ordered-dither h8x8o logo_h8x8o.gif |
-colorspace
” 操作符来生成图像的真实位图抖动。
# Halftone Screen (45 degree angle) magick logo.png -colorspace Gray -ordered-dither h4x4a logo_bw_h4x4a.gif magick logo.png -colorspace Gray -ordered-dither h6x6a logo_bw_h6x6a.gif magick logo.png -colorspace Gray -ordered-dither h8x8a logo_bw_h8x8a.gif # Halftone Screen (orthogonal) magick logo.png -colorspace Gray -ordered-dither h4x4o logo_bw_h4x4o.gif magick logo.png -colorspace Gray -ordered-dither h6x6o logo_bw_h6x6o.gif magick logo.png -colorspace Gray -ordered-dither h8x8o logo_bw_h8x8o.gif |
# Halftone Screen (45 degree angle) magick gradient.png -ordered-dither h4x4a od_h4x4a.gif magick gradient.png -ordered-dither h6x6a od_h6x6a.gif magick gradient.png -ordered-dither h8x8a od_h8x8a.gif # Halftone Screen (orthogonal) magick gradient.png -ordered-dither h4x4o od_h4x4o.gif magick gradient.png -ordered-dither h6x6o od_h6x6o.gif magick gradient.png -ordered-dither h8x8o od_h8x8o.gif magick gradient.png -ordered-dither h16x16o od_h16x16o.gif # Circle Halftones (black and white) magick gradient.png -ordered-dither c7x7b od_c7x7b.gif magick gradient.png -ordered-dither c7x7w od_c7x7w.gif |
偏移半色调抖动
上述半色调抖动的唯一问题是,完全相同的阈值图(平铺)以相同的方式应用于所有颜色通道。这意味着相同的颜色集以具有相同“中心”的点排列。为了获得所谓的“偏移印刷”,阈值图案以特定模式旋转,使得颜色形成小型的“玫瑰花图案”,从而破坏了您可能出现的更可怕的干扰(摩尔)图案。该图基本上解释了该过程,并在维基百科页面半色调上进行了详细解释。但是请注意,旋转的屏幕无法很好地平铺,因此最好的方法是直接生成旋转的图案,而不是使用平铺的阈值图案。以下是一种使用小的旋转 2x2 像素棋盘格图案,让图像呈现偏移半色调印刷效果的方法,这大约是最小的可使用的“屏幕”。
|
-combine
”步骤实际上从屏幕图像中提取了 4 种不同的颜色通道。此外,最后一个“黑色”通道的“无操作”扭曲很重要,因为它会根据在其他通道旋转期间使用的高斯滤波器对输入棋盘格图案进行模糊,即使该屏幕本身没有被旋转。这里我使用SRT 扭曲 的缩放功能来生成旋转的平铺,以创建稍微更大且更模糊的“屏幕图案”。
magick parrots_med.png -set option:distort:viewport '%wx%h+0+0' \ -colorspace CMYK -separate null: \ \( -size 2x2 xc: \( +clone -negate \) \ +append \( +clone -negate \) -append \) \ -virtual-pixel tile -filter gaussian \ \( +clone -distort SRT 2,60 \) +swap \ \( +clone -distort SRT 2,30 \) +swap \ \( +clone -distort SRT 2,45 \) +swap \ \( +clone -distort SRT 2,0 -blur 0x0.7 \) +swap +delete \ -compose Overlay -layers composite \ -set colorspace CMYK -combine -colorspace RGB \ offset_parrots.png |
需要注意的是,这实际上并不是像真正的胶印那样生成彩色点,而是通过简单地将彩色网点与原始图像相乘来模拟。你可以看到,红色鹦鹉与绿色背景交界处的颜色急剧变化,就是这种情况。使用纯色点进行的真正胶印不会出现点中间的颜色变化。只有纯色点的尺寸会根据源图像中该区域的平均颜色而改变。要真正生成一个只包含每个颜色通道中适当大小的圆点的胶印图像,还需要做更多工作。需要确定每个颜色通道中每个点的平均颜色,并由此生成适当大小的彩色点(抗锯齿圆圈)。有人愿意尝试一下吗? 以上内容来自 IM 论坛讨论 CMYK 半色调效果 中的讨论,该讨论着眼于 Photoshop 如何“模拟”以及 ImageMagick 如何实现相同的效果。该讨论也与 黑白半色调抖动 相关,后者更详细地介绍了如何使用适当大小的实际点生成真正的半色调网点。然而,该讨论并没有将它扩展到使用偏移(旋转)网点的下一步。此类网点可能需要旋转图像以生成点,然后为该特定颜色通道再次旋转点模式。
XML 阈值映射
从 IM 6.3.0 版本开始,不再使用内置于 IM 源代码中的固定映射集(如前所示),而是从程序本身外部的一组 XML 数据文件中读取映射。作为此更改的一部分,你现在可以列出 "-ordered-dither
" 运算符可使用的可用“阈值映射”。上面的列表不仅显示了可用的阈值映射,还显示了为向后兼容性或备用命名提供的别名,以及在我自己的个人 "thresholds.xml
" XML 数据文件(保存到我的主目录的 ".magick
" 子目录中)中定义的别名。当 "-ordered-dither
" 查找映射时,将使用在上面列表中找到的第一个映射。因此,你不能覆盖系统定义的阈值模式。系统文件 "thresholds.xml
"(其路径由上面的 "-list
" 选项给出)包含 XML 文件格式的完整摘要。该格式足够简单(IM 进行错误检查),允许用户定义和创建自己的有序抖动阈值映射。例如,这是我在个人 "threshold.xml
" 文件中定义的“diag5x5
”阈值映射的副本。如果你仔细观察,它会创建一个简单的 5x5 映射,其中包含一条单一的对角线,随着阈值水平的升高,对角线会变粗。映射中的级别编号从 0 到 5,比除数少 1,除数声明它需要将颜色渐变划分为多少个“灰色”。以下是使用此个人阈值映射抖动的渐变。以下是一个使用该阈值对简单阴影图像的 alpha 通道进行抖动的示例,这是我设计它的目的。
magick -size 70x60 xc:none -font Candice -pointsize 50 \ -fill black -annotate +10+45 'A' -channel RGBA -blur 0x5 \ -fill white -stroke black -draw "text 5,40 'A'" shadow.png magick shadow.png -channel A -ordered-dither diag shadow_diag.gif |
-ordered-dither
" 运算符的颜色功能。 使用均匀颜色级别的有序抖动
随着 IM v6.3.0 的发布,不仅 "-ordered-dither
" 使用的阈值映射已更改为从外部文件读取,而且内部操作也得到了增强,使其能够使用数学定义的“分层”颜色映射。这意味着你可以生成比使用“误差校正抖动”所能实现的更确定的图像抖动。这对于涉及动画的颜色减少尤其重要,因为你不会遇到帧之间颜色差异的问题。分层级别通过使用附加到要使用的阈值映射名称的额外逗号分隔的数字列表传递给 "-ordered-dither
" 参数。如果未提供数字,则运算符将回退到正常的 2 色(或分层级别 1)颜色映射。例如,参数“checks,6
”将使用经典的 网络安全颜色映射(分层级别 6)颜色映射(也由 "netscape:
" 内置颜色映射图像定义)。但是,由于使用了“checks
”的最小抖动映射,因此在 6 个颜色级别之间添加了一个额外的抖动级别,在图像的每个通道中创建了 11 个伪级别颜色。换句话说,即使每个通道只使用了 6 个颜色级别(生成 6^3 或 216 种颜色),但级别之间的单个抖动模式也会将抖动增加到有效的 11 个级别(生成有效的 11^3 或 1331 种颜色)。例如,以下是使用 6 个灰色级别和各种阈值映射抖动的灰度渐变。第一个映射“threshold
”是一个特殊的非抖动有序抖动阈值映射,只显示了所使用的颜色。
magick gradient.png -ordered-dither threshold,6 od_threshold_6.gif magick gradient.png -ordered-dither checks,6 od_checks_6.gif magick gradient.png -ordered-dither o2x2,6 od_o2x2_6.gif magick gradient.png -ordered-dither o4x4,6 od_o4x4_6.gif magick gradient.png -ordered-dither o8x8,6 od_o8x8_6.gif |
-posterize
" 误差校正抖动选项不同,你可以为每个通道指定级别。根据 "-channels
" 设置,将数字分配给通道。例如,这里我们使用一个特殊的 332 色映射(8 个红色和绿色级别,4 个蓝色级别)对渐变进行抖动,该映射定义了总共 256 种颜色。由于每个通道的颜色级别数不同,因此上面的图像不只包含纯灰色,还包含一些蓝色和黄色的像素,它们相互抵消,从而产生额外的灰色级别。现在将 O 抖动 版本与使用 2 和 6 的分层级别以及“332 色映射”(8 个红色和绿色级别,4 个蓝色级别)的误差校正抖动版本进行比较。
magick logo.png -ordered-dither o8x8 logo_o8x8_2.gif magick logo.png -posterize 2 logo_posterize_2.gif magick logo.png -ordered-dither o8x8,6 logo_o8x8_6.gif magick logo.png -posterize 6 logo_posterize_6.gif magick logo.png -ordered-dither o8x8,8,8,4 logo_o8x8_332.gif magick logo.png -remap colormap_332.png logo_remap_332.gif |
-ordered-dither
" 运算符才包含了为每个颜色通道指定单独级别的能力。 更好的有序抖动结果
让我们仔细看看我们刚刚生成的级别 6 O 抖动。如你所见,对于此图像,我们甚至没有接近填充 GIF 颜色表(256 个限制)。基本上,由于图像通常主要由蓝色组成,因此甚至没有使用来自级别 6 均匀颜色映射的红色或绿色的阴影。但是,通过增加分层级别数,我们可以更好地填充 GIF 颜色表,从而生成更好的 O 抖动 图像。这会生成足够多的颜色,使其略小于 GIF 颜色表限制。随着颜色数量的增加,结果看起来比简单标准均匀颜色映射的结果好得多。
|
-ordered-dither
" 可以生成与颜色量化的图像相当的图像,与颜色量化和误差校正抖动生成的特定颜色选择相当。这些图像的主要要点不在于它们的质量很高。毕竟,完整的 颜色量化 可以更轻松地为图像生成更好的颜色映射。但是,图像中的低级别抖动模式是固定的,无论发生任何细微变化都无关紧要。只有区域变化会在有序抖动图像中发生改变。也就是说,它们不会对 帧优化 中的 GIF 动画造成问题的 E 抖动敏感性。(参见 优化问题)当然,对于动画,你需要使用 "-append
" 将所有图像连接在一起,然后再检查实际上使用了多少种颜色。你需要使用特殊的 "+remap
" 选项,在使用 "-ordered-dither
" 后,强制 IM 为所有图像生成“通用全局颜色映射”,即使你已经执行了颜色减少和抖动。这种确定颜色级别数的方法并不简单,但它确实有效。我希望找到一种方法让 IM 自动确定最佳级别,尤其是对于 GIF 动画。DIY 抖动模式和阈值映射
之前,我向你展示了新的 "-ordered-dither
" 运算符可以接受用户定义的抖动模式。这里,我将向你展示如何创建自己的抖动模式。具体来说,我发现的一种对于生成由水平线组成的阴影非常有用的特殊模式。 多图像抖动模式
首先,你需要创建一组图像来定义你想要创建的模式。模式应该以一个大小正确的纯黑色图像(所有像素都关闭)作为第一张图像,并在另一端以一个纯白色图像(所有像素都打开)作为结尾。下一张图像应该是中间 50% 灰色模式,定义了你试图实现的抖动基本样式。例如,这是我最初的 DIY 抖动模式。我将其保存到一个多图像 GIF 文件(不是 GIF 动画)中……
magick -size 2x2 xc:black \ \( +clone -draw 'fill white line 0,0 1,0' \) \ xc:white dpat_hlines2x2.gif montage dpat_hlines2x2.gif -tile x1 -background none -frame 2 \ -filter box -geometry 32x32+5+0 dpat_hlines2x2_imgs.gif |
magick gradient.png dpat_hlines2x2.gif \ -virtual-pixel tile -fx 'u[(floor((n-1)*u)+1) % n]' dgrad_hlines2x2.gif |
-fx
” 函数是 颜色查找表 函数的变体,即 IM Dither Lookup Patterns 类型的函数。 并使用 "-virtual-pixel
" 设置为 'tile
',该函数甚至不需要知道您使用的抖动模式图像的大小。在 IM 版本 6.2.9-2 之前,"-fx " 操作符使用像这样计算的索引使用 "-virtual-pixel " 是有问题的。 |
magick shadow.png dpat_hlines2x2.gif -channel A \ -virtual-pixel tile -fx 'u[floor((n-1)*u)+1].g' \ shadow_dpat_hlines2x2.gif |
DIY 有序抖动阈值映射
上面的 DIY 抖动模式尽可能简单,因此我们可以直接将其转换为 XML 阈值映射,以便快速内置的 "-ordered-dither
" 操作符可以使用它。 这是最终的 XML 定义,我将其保存在我个人阈值映射文件 "~/.magick/thresholds.xml
" 中,该文件位于我的 "$HOME" 目录中。XML 格式非常简单,定义了一个 2x2 像素映射。 第一张黑色图像的值为零,没有像素,因此没有零值存在。 中间图像中开启的像素(变为白色)设置为 '1
',其余或第二张图像像素的值为 '2
'。 'divisor=
' 定义了图像的数量或伪彩色级别(假彩色级别),该抖动模式表示,因此它的值为 '3
'。 它将像素值除以定义像素开启的颜色级别。 因此,对于大于 1/3 的颜色,最上面的两个像素被开启,而最下面的两个像素被开启,用于大于 2/3 的颜色值。 也就是说,每个像素值代表一个“阈值”级别,这就是为什么抖动模式也被称为阈值映射。 定义的其余部分定义了您可以用于有序抖动操作符的阈值映射的名称(和可选别名)。 所以让我们试试...
magick gradient.png -ordered-dither hlines2x2 od_hlines2x2.gif magick shadow.png -channel A \ -ordered-dither hlines2x2 shadow_hlines2x2.gif |
10
',以便将颜色级别划分为十个相等的部分。 然后我更改了阈值设置,使模式从透明端(黑色)的 30% 阈值开始,到完全不透明(白色)的 90% 结束。 这是更改阈值映射的结果。
magick gradient.png -ordered-dither hlines2x2a od_hlines2x2a.gif magick shadow.png -channel A \ -ordered-dither hlines2x2a shadow_hlines2x2a.gif |
DIY 水平线抖动
在这里,我将上面创建的简单水平线抖动模式扩展成一组模式,以产生从“关闭”到“开启”的更平滑的渐变。 这是结果。
montage dpat_hlines.gif -filter box -geometry 60x20+2+0 \ -tile x1 -background none -frame 2 dpat_hlines_images.gif magick gradient.png dpat_hlines.gif \ -virtual-pixel tile -fx 'u[(floor((n-1)*u)+1) % n]' \ dgrad_dpat_hlines.gif magick shadow.png dpat_hlines.gif -channel A \ -virtual-pixel tile -fx 'u[floor((n-1)*u)+1].g' \ shadow_dpat_hlines.gif |
magick -size 120x55 xc:white -draw 'fill #777 ellipse 50,43 30,5 0,360' \ -motion-blur 0x15+180 -blur 0x2 sphere_shadow.png magick sphere_shadow.png dpat_hlines.gif \ -virtual-pixel tile -fx 'u[(floor((n-1)*u)+1) % n]' \ sphere_shadow_dither.gif magick sphere_shadow_dither.gif -fill red -stroke firebrick \ -draw 'circle 35,25 35,5' sphere_shadow_hlines.gif |
|
||
|
10
' 比抖动模式中图像的数量多 1,而 "-scale 12x4\!
" 是要转换为阈值映射的抖动模式的大小。 结果是灰度映射,没有纯黑色或白色颜色。 用于像素的灰度级别意味着如果颜色级别等于或高于该灰度值,则应开启该像素。 也就是说,每个灰度级别是颜色值从黑色变为白色的“阈值”级别。 如果你喜欢以另一种方式看待图像,那么暗像素通常会导致这些像素在更多颜色级别时被开启。 而亮像素只有在图像颜色变得非常亮时才会被开启。 这几乎是对图像实际外观的否定,但如果你仔细想想,这是有道理的。 我还使用 PNG 图像而不是 GIF 图像作为映射,因为只需要保存一张图像,更重要的是,尝试为阈值保留 16 位质量级别。 GIF 只能处理 8 位颜色级别。 现在我们可以使用单个图像和对每个像素直接与抖动阈值图像(或映射)进行简单的阈值比较来抖动我们的图像。看看阈值映射是多么简单。 您只有一张图像,并且每个通道都对每个像素进行一次直接比较。 这使得使用阈值映射进行抖动非常快。 比全彩色量化快得多。 这种简单性是 ImageMagick 和大多数图形软件使用阈值映射来保存各种抖动模式的原因。直到 IM 版本 6.2.9-2,大于或等于('>= ')测试才添加到 "-fx " 操作符中。 如果这是一个问题,请在上面使用反向测试 'v<u '。 |
-ordered-dither
" 操作符可以使用它。 为此,我们需要将我们的图像输出为表示其代表的 9 个灰度级别的数字。 最好使用 NetPBM 或 PBMplus 图像格式,并使用 "NetPbm" 图像处理软件进行深度调整。 这个软件包通常是标准的 Linux 安装,所以大多数人已经拥有它,或者可以从他们通常的软件发行版中安装它。 "pnmdepth
" 数字再次是阈值图像包含的灰度级别数量。上面所有数字(除了 'P2
' 图像魔法标识符)都是生成适当“阈值映射”所需的数字,您可以将其添加到您的个人 "thresholds.xml
" 文件中。 例如,以下是根据上面创建的结果阈值映射条目。以下是如何使用此阈值映射的示例。这就是如何从一系列图像生成复杂的阈值映射。 使用符号模式抖动
现在,虽然您可以使用单个阈值映射或阈值图像,而不是用于大多数抖动操作的多图像模式集,但这并不意味着多图像映射没有其自身的用途。 您可以使用一组查找图像来一次性平铺多个区域,而不是一次一个。 例如,通过缩放一个简单的图像,然后用特定符号替换图像中的每个像素。 例如,在这里我使用非常小的“眼睛”图像 并用各种符号替换单个像素,为原始图像中的每个像素生成这样的图案。
montage dpat_symbols.gif -geometry +5+0 \ -tile x1 -background none -mattecolor blue -frame 3 \ dpat_syms_images.gif magick eyes.gif -alpha off -colorspace sRGB -grayscale Average \ -alpha off -scale 1600% -negate \ dpat_symbols.gif -virtual-pixel tile -fx 'u[floor(15.9999*u)+1]' \ eyes_syms.gif |
Rec709Luminance
' 到更暗的 'Rec709Luma
' 来调整要使用的“-grayscale
” 强度方法,或者使用非线性 'sRGB
' 颜色空间或线性 'RGB
' 颜色空间的“average
”。 您甚至可以调整值的“-gamma
” 缩放比例,以获得最佳的颜色分布。 可能性很多,什么好取决于您的符号排列而不是实际选择的方法。 上述的关键是确保输入图像中的每种颜色都产生一个独特的符号,而这可能很难实现。 此示例可用于创建爱好者可以遵循的十字绣或编织指南,从较小的计算机图像生成更大规模的艺术作品。 您可以使用此技术用一组平铺颜色图像来平铺灰度图像。 结果有点像在许多旧的电脑战争游戏中看到的景观地图。
montage dpat_map.gif -geometry +5+0 -tile x1 -background none \ dpat_map_images.gif magick -seed 100 \ -size 200x200 plasma:'gray(50%)-gray(50%)' -blur 0x15 \ -channel G -auto-level +channel -set colorspace sRGB \ dpat_map.gif -virtual-pixel tile -fx 'u[floor(5.999*u.g)+1]' \ map.gif |
有序抖动随机笔记和未来可能性
正在建设中