【发布时间】:2011-02-04 14:31:40
【问题描述】:
场景
我想将具有 alpha 透明度的图像保存为 .png,将没有 alpha 透明度的图像保存为 .jpg(即使它们的原始格式是 .png 或 .gif)。如何使用 ImageMagick 检测图像是否具有 Alpha 透明度?
【问题讨论】:
标签: image png imagemagick jpeg alpha
我想将具有 alpha 透明度的图像保存为 .png,将没有 alpha 透明度的图像保存为 .jpg(即使它们的原始格式是 .png 或 .gif)。如何使用 ImageMagick 检测图像是否具有 Alpha 透明度?
【问题讨论】:
标签: image png imagemagick jpeg alpha
ImageMagik 命令:
identify -format '%[channels]' foo.png
将分别打印rgba 或rgb(如果有或没有 Alpha 通道)。
可能存在一个 alpha 通道,其中没有数据,实际上没有任何透明度,但这有点复杂。
【讨论】:
按照serhiy.h's answer 使用-format %A。来自documentation:
%A 图像透明度通道已启用(真/假)
使用 -format %[opaque]。来自documentation:
%[opaque] 计算:图像是否完全不透明?
为了演示,让我们创建一个具有 Alpha 通道但完全不透明的图像 a.png,以及一个除了一个半透明像素外相同的图像 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
【讨论】:
if $(identify -format '%[opaque]' "$file"); then ...; fi
%[opaque],谢谢
如果您想检查图片是否真正透明...(不仅仅是可能未使用的 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
如果图像包含 Alpha 通道,将返回 True。
【讨论】:
如果您想确保真正使用了 alpha 透明度,我看到的唯一解决方案是迭代所有像素并获取颜色信息以检查它是否透明。对于大图像,这将非常慢,因此,作为优化,您可以先制作图像的缩略图(比如说 20x20),然后检查缩略图像素。这对我来说是一个很好的解决方案。
【讨论】:
这里有几个 bash 函数可以使用 ImageMagick 检查 png 是否具有透明度。
快速检查,仅检查 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?//'
}
【讨论】: