设想
我想将具有 alpha 透明度的.png
图像保存为,将没有 alpha 透明度的图像保存为.jpg
(即使它们的原始格式是.png
or .gif
)。如何使用 ImageMagick 检测图像是否具有 alpha 透明度?
我想将具有 alpha 透明度的.png
图像保存为,将没有 alpha 透明度的图像保存为.jpg
(即使它们的原始格式是.png
or .gif
)。如何使用 ImageMagick 检测图像是否具有 alpha 透明度?
ImageMagik 命令:
identify -format '%[channels]' foo.png
将分别打印rgba
或rgb
是否有 Alpha 通道。
可能存在一个 alpha 通道,其中没有数据,实际上没有任何透明度,但这有点复杂。
-format %A
根据serhiy.h 的回答使用。从文档中:
%启用图像透明度通道(真/假)
使用-format %[opaque]
. 从文档中:
%[opaque] CALCULATED: 图像是完全不透明的吗?
为了演示,让我们创建一个a.png
具有 alpha 通道但完全不透明的图像,以及一个b.png
除了一个半透明像素之外相同的图像:
$ convert rose: PNG32:a.png
$ convert rose: -fill '#0008' -draw "matte 10,10 point" PNG32:b.png
正如预期的那样,两个图像都%A
产生了转义True
,因为它们都有一个 alpha 通道:
$ identify -format '%A' a.png
True
$ identify -format '%A' b.png
True
而%[opaque]
逃逸true
在一种情况下产生,而false
在另一种情况下,由于一个透明像素:
$ identify -format '%[opaque]' a.png
true
$ identify -format '%[opaque]' b.png
false
如果您想检查图片是否真正透明...(不仅是可能未使用的 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
如果图像包含 alpha 通道,将返回。
如果您想确保真正使用了 alpha 透明度,我看到它的唯一解决方案是迭代所有像素并获取颜色信息以检查它是否透明。对于大图像,这将非常慢,因此,作为一种优化,您可以首先制作图像的缩略图(比如说 20x20),然后检查缩略图像素。这对我来说是一个很好的解决方案。
这里有几个 bash 函数来检查 png 是否具有透明度,使用 ImageMagick。
快速检查,仅检查是否存在Alpha 通道:
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?//'
}