ImageMagick 使用部分透明像素的背景颜色转换为 png8(带有二进制 alpha 的调色板 PNG)

ImageMagick convert to png8 (paletted PNG with binary alpha) using background color for partially transparent pixels

我有一个像这样的 32 位 PNG 图片:

此处显示的是棋盘格背景以提高可见性,但图像实际上是透明的而不是棋盘格(供您参考:the original 32-bit image)。如您所见,在边缘和右侧,红色像素逐渐从不透明淡出到透明。

如果我将此 32 位图像显示在蓝色背景之上,边缘周围和右侧的像素将从红色逐渐淡化为蓝色。

现在我需要将此图像转换为具有二进制 alpha 的 8 位 PNG。我希望完全透明的区域保持完全透明,但部分透明的像素逐渐与预期的 background/matte 颜色 混合,在本例中为蓝色。

所以像这样:

但是,我似乎无法弄清楚如何使用 ImageMagick 执行此操作(在 Mac 上使用 ImageMagick 7.0.8-26)。我尝试如下:

magick original.png -background 'rgba(0,0,255,0)' png8:output.png

但这会导致:

似乎完全忽略了蓝色背景颜色,只是将透明度转换为二进制(可能对 ≥128 采取完全不透明或对 <128 完全透明)。

此外,如果我将 rgb(0,0,255) 指定为背景颜色(即没有 alpha),结果是相同的。

ImageMagick 是否有一些我不知道的智能 'background blending for partially transparent pixels' 选项?

否则,我猜我应该以某种方式提取二进制位图,其中原始图像是完全透明的(即具有 alpha 值或不透明度为 0),然后在我选择的背景上展平图像,然后重新再次应用布尔 alpha 位图。但不太确定该怎么做。

我能想到两种技术,但我相信人们有更好的答案。

第一个选项

合成蓝色背景,然后从原始来源复制 alpha 通道。

magick original.png \( \
  +clone \( +clone -fill BLUE -draw 'color 0,0 reset' \) \
  -compose DstOver -composite \) \
  -swap 0,1 -compose CopyAlpha -composite  PNG8:output.png

第二个选项

用蓝色替换透明,然后调用 -transparent 而不进行任何 -fuzz 操作。

magick original.png \( \
  +clone -fill BLUE -draw 'color 0,0 reset' \) \
  -compose DstOver -composite -transparent BLUE \
  PNG8:output.png

同样,我确信上面的示例可以改进。 YMMV

使用 ImageMagick 实现此目的的一种方法是提取 alpha 通道,对除完全透明像素以外的所有内容进行着色,然后在结果上合成原始图像。

convert input.png \( +clone -alpha extract -transparent black -fill blue \
   -channel RGB -colorize 100 +channel \) +insert -composite output.png

读取输入图像,将其克隆到括号内,并将 alpha 通道提取为黑白蒙版。

纯黑用“-透明黑”变透明。

白色,除了纯黑色之外的所有东西,都用“-colorize 100”变成了蓝色。设置“-channel RGB”仅将填充颜色应用于蒙版的白色部分并忽略透明部分。

然后在括号后,“+insert”将 blue-on-transparent 图像移到后面,“-composite”将输入图像放在蓝色透明图像上。

如果您使用的是 ImageMagick 版本 7,请使用 "magick" 而不是 "convert"。如果您在 Windows 上 运行,请将行尾反斜杠“\”更改为脱字符“^”,并删除转义圆括号“\(...\)”的反斜杠以简单地“(...)”。

感谢发布的建议,但问题是我不想将任何特定颜色(如黑色或蓝色)屏蔽为透明。 non-transparent 部分也可能出现完全相同的颜色。

经过一些调整,我得到了我需要的确切结果:

magick original.png -write MPR:foo -background 'rgb(0,0,255)' -flatten \( MPR:foo -alpha extract -threshold 0 \) -compose copy_opacity -composite png8:result.png

解释:

  • 我从 original.png 开始并使用 -write MPR:foo 在内存中保存一个名为 'foo'
  • 的临时副本
  • 然后我在蓝色背景上展平图像,在各处提供正确的颜色值(包括与部分透明像素的背景混合)但丢失不透明度数据。
  • 然后我 side-process 第二层,打开相同的原始输入图像(使用 MPR:foo 从内存中恢复)并提取其 alpha 通道,现在变成灰度图像,包含原始 alpha 数据.
  • 我在该图层上应用 -threshold 0,这会将所有 >0 的通道值更改为最大值(即 alpha 255 或完全不透明)并且≤0 保持为 0(完全透明)。所以现在这是我的 'binary alpha' 频道。
  • 然后最后我通过使用 copy_opacity 复合来合并这两层,它只复制第二层(二进制 alpha)并将其写入结果层的 alpha 数据。
  • 保存最终结果可以得到我需要的准确图像。

这是 ImageMagick 中的另一种方法。

convert img.png \
\( -clone 0 -alpha extract -channel rgba \
    \( xc:none xc:blue +append \) -clut +channel \
        -channel alpha -threshold 0 +channel \) \
+swap -compose over -composite PNG8:result.png


或者对于 Imagemgick 7

magick img.png \
\( -clone 0 -alpha extract -alpha copy -channel rgba \
\( xc:none xc:blue +append \) -clut \
-channel alpha -threshold 0 +channel \) \
+swap -compose over -composite PNG8:result.png

Read the image.

Clone it, extract the alpha channel, create transparent blue color map and apply to the alpha channel, then threshold the alpha channel.

Swap the two images and composite the original over the processed alpha channel.

Save the output.