【问题标题】:Detect Alpha Channel with ImageMagick使用 ImageMagick 检测 Alpha 通道
【发布时间】:2011-02-04 14:31:40
【问题描述】:

场景

我想将具有 alpha 透明度的图像保存为 .png,将没有 alpha 透明度的图像保存为 .jpg(即使它们的原始格式是 .png.gif)。如何使用 ImageMagick 检测图像是否具有 Alpha 透明度?

【问题讨论】:

    标签: image png imagemagick jpeg alpha


    【解决方案1】:

    ImageMagik 命令:

    identify -format '%[channels]' foo.png 
    

    将分别打印rgbargb(如果有或没有 Alpha 通道)。

    可能存在一个 alpha 通道,其中没有数据,实际上没有任何透明度,但这有点复杂。

    【讨论】:

    • 存在没有数据的 Alpha 通道是否常见?如果是这样,我能找出来吗?
    • 根据我的经验,人们只在希望它们不为空时才创建 Alpha 通道,但通常发生的情况和可能发生的情况之间存在差异。除非你发现它弹出,否则我不会担心它。我只是想通过注意到 alpha 通道的存在并不一定意味着透明度的存在来完成。
    • 啊,是的。永远不要低估用户。谢谢!
    • 可以肯定,这是一个非常古老的问题,但是没有 alpha 通道并不意味着没有 alpha 像素。可以有一个索引 RGB png,其中一些索引条目完全透明。请参阅 png 文档中的 tRNS。
    【解决方案2】:

    检查图像是否有 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],谢谢
    【解决方案3】:

    如果您想检查图片是否真正透明...(不仅仅是可能未使用的 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 也很低。似乎图像的很大一部分使用了透明度。

    根据您想要实现的检查类型(完全不透明、“几乎不透明”等),如果您的请求有点棘手,您应该检查minmeanstandard deviation

    注意:您可能想检查minmean 和其他的整数值,就像我一开始那样。毕竟,处理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 快得多。

    【讨论】:

    • 对于许多用户来说,只想查看是否需要 alpha 通道的人,抓住 alpha min 行并检查它是否以“(1)”结尾就足够了。
    • 感谢您的详细解答。这实际上提供了对访问图像属性的更深入了解,并且不仅回答了 OP 的问题,而且还对其进行了扩展。
    【解决方案4】:
    identify -format %A some_pic.png
    

    如果图像包含 Alpha 通道,将返回 True

    【讨论】:

      【解决方案5】:

      如果您想确保真正使用了 alpha 透明度,我看到的唯一解决方案是迭代所有像素并获取颜色信息以检查它是否透明。对于大图像,这将非常慢,因此,作为优化,您可以先制作图像的缩略图(比如说 20x20),然后检查缩略图像素。这对我来说是一个很好的解决方案。

      【讨论】:

        【解决方案6】:

        这里有几个 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?//'
        }
        

        【讨论】:

          猜你喜欢
          • 2021-07-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-09
          • 2022-12-05
          • 1970-01-01
          • 1970-01-01
          • 2019-12-17
          相关资源
          最近更新 更多