场景
我希望把带有alpha透明度的图片保存为.png
格式,不带alpha透明度的图片则保存为.jpg
格式,即使它们的原始格式是.png
或.gif
。如何使用ImageMagick检测一张图片是否具有alpha透明度?
我希望把带有alpha透明度的图片保存为.png
格式,不带alpha透明度的图片则保存为.jpg
格式,即使它们的原始格式是.png
或.gif
。如何使用ImageMagick检测一张图片是否具有alpha透明度?
使用-format %A
,如serhiy.h的答案所述。从文档中得知:
%A
图像透明度通道。值包括未定义(无透明度通道)、混合、复制或更新。
使用-format %[opaque]
。从文档中得知:
%[opaque]
计算:图像是否完全不透明?
为了演示,让我们创建一个带有 alpha 通道但完全不透明的图像 a.png
,以及一个相同但只有一个半透明像素的图像 b.png
:
$ convert rose: PNG32:a.png
$ convert rose: -fill '#0008' -draw "matte 10,10 point" PNG32:b.png
正如预期的那样,%A
转义字符对于两个图像都生成了 Blend
,因为它们都有一个 alpha 通道:
$ identify -format '%A' a.png
Blend
$ identify -format '%A' b.png
Blend
而 %[opaque]
转义在一个情况下产生 true
,在另一个情况下产生 false
,这是由于一个透明像素的存在:
$ identify -format '%[opaque]' a.png
true
$ identify -format '%[opaque]' b.png
false
ImageMagick的命令:
identify -format '%[channels]' foo.png
如果有alpha通道,则会打印rgba
,如果没有alpha通道,则会打印rgb
。
可能存在一个alpha通道,但其中没有任何数据,这实际上并不具有任何透明度,但这有点复杂。
如果您想要确认一张图片是否真正透明...(而不仅仅是可能未使用的 Alpha 通道)
请使用以下命令:
convert some_pic.png -verbose info:
(是的,在命令的末尾有一个:
)
它非常冗长。查找频道列表:
(...)
Channel depth:
red: 16-bit
green: 16-bit
blue: 16-bit
Channel statistics:
(...)
在这个例子中,有三个通道,分别对应每种主要颜色。但没有透明度通道。因此,这个图像不是透明的。(...)
Channel depth:
red: 16-bit
green: 16-bit
blue: 16-bit
alpha: 1-bit
Channel statistics:
(...)
这里有一个 alpha 通道。然而,这并不能证明这个图像是透明的,它只是表示它可能是透明的。在命令的输出中,寻找关于 alpha 通道的信息:
(...)
Alpha:
min: 255 (1)
max: 255 (1)
mean: 255 (1)
standard deviation: 0 (0)
kurtosis: 0
skewness: 0
(...)
在这个例子中,alpha 值表示图片是不透明的: min
= max
= 1 (1 表示不透明, 0 表示透明)。因此,即使图像具有 alpha 通道,用户也会看到一个不透明的图片。
你也可以获得这个:
(...)
Alpha:
min: 95 (0.372549)
max: 212 (0.831373)
mean: 111.187 (0.436028)
standard deviation: 19.5635 (0.0767196)
kurtosis: 7.52139
skewness: -2.80445
(...)
这次,min
= 0.372549。这意味着一些像素是部分透明的。 mean
也很低。似乎图像的很大一部分使用了透明度。
根据所需检查的类型(完全不透明、"几乎不透明"等),您应该检查 min
、mean
和可能的 standard deviation
(标准偏差),如果您的请求有点棘手。
注意:您可能会想检查整数值的 min
、mean
和其他值,就像我一开始所做的那样。毕竟,处理 95
比处理 0.372549
更容易。如果你选择这个方法,请注意 alpha 通道深度。如果它是 8 位,则 255 是最大值,表示 "不透明"。如果它是 16 位,则最大值现在是 65535,而 255 表示 "几乎透明"。最好检查括号中的小数,它们始终从 0 到 1 范围内。
如果您怀疑将要处理的许多图片根本没有 alpha 通道,可以先运行:
identify -format '%[channels]' some_pic.png
如果它(指某物)倾倒:
rgba
存在一个alpha通道(输出中的a
),应使用convert
来检查min
等。但如果不存在,则无需运行convert
。虽然我没有对这两个命令进行基准测试,但identify
应该比convert
快得多。
identify -format %A some_pic.png
如果图片包含透明通道,则返回True
。
checkAlphaFast() {
test $(identify -format %A "$1") == True
}
缓慢的检查,验证像素本身(即使存在 alpha 通道):
checkAlphaSlow() {
test $(identify -format '%[opaque]' "$1") == false
}
checkAlpha() {
checkAlphaFast "$1" && checkAlphaSlow "$1"
}
使用以下函数:
if checkAlpha "$myPNG"; then
# is transparent
else
# is opaque
fi
这将为您提供图像的不透明度,其中0表示完全透明,1表示完全不透明:
checkOpaqueness() {
if checkAlphaFast "$1"; then
convert "$1" -verbose info: | grep -A3 Alpha: | tail +4 | head -n1 | sed -r 's/.*\(|\)//g'
else
echo 1
fi
}
这个输出结果是一个四舍五入的百分数,因为整数在bash中更加自然:
checkPercentage() {
printf %3.2f $(checkOpaqueness "$1") | tr -d . | sed -r 's/^0?0?//'
}
如果你想确保使用了alpha透明度,我唯一看到的解决方案就是迭代所有像素并获取颜色信息,以检查它是否透明。对于大型图像来说,这将非常缓慢,因此作为一种优化,您可以首先制作图像的缩略图(比如20x20),然后检查缩略图像素。这对我来说是一个很好的解决方案。
if $(identify -format '%[opaque]' "$file"); then ...; fi
- Camilo Martin%[opaque]
,谢谢! - forresthopkinsamagick identify -format '%[opaque]' file.png
- undefined