Detectar canal Alfa con ImageMagick


Escenario

Me gustaría guardar las imágenes con transparencia alfa como .png e imágenes sin transparencia alfa como .jpg (incluso si su formato original es .png o .gif). ¿Cómo puedo detectar si una imagen tiene transparencia alfa usando ImageMagick?

Author: brad, 2010-04-06

6 answers

El comando ImageMagik:

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

Imprimir rgba o rgb si hay o no un canal alfa, respectivamente.

Podría haber un canal alfa presente sin datos en él que en realidad no tendría ninguna transparencia, pero eso es un poco más complicado.

 25
Author: msw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-05 22:24:33

Si desea comprobar que una imagen es realmente transparente... (no solo un canal alfa que podría estar sin usar)

Use este comando:

convert some_pic.png -verbose info:

(sí, hay un : al final del comando)

Es bastante detallado. Busca la lista de canales:

(...)
Channel depth:
  red: 16-bit
  green: 16-bit
  blue: 16-bit
Channel statistics:
(...)

En este ejemplo, hay tres canales, uno para cada color primario. Pero no para alfa. Así que esta imagen no es transparente.

Pero también puedes obtener este tipo de salida:

(...)
Channel depth:
  red: 16-bit
  green: 16-bit
  blue: 16-bit
  alpha: 1-bit
Channel statistics:
(...)

Aquí, hay un canal alfa. Sin embargo, esto no prueba que la imagen sea transparente. Solo dice que podría ser. En las salidas del comando, busque la información sobre el canal alfa:

(...)
  Alpha:
    min: 255 (1)
    max: 255 (1)
    mean: 255 (1)
    standard deviation: 0 (0)
    kurtosis: 0
    skewness: 0
(...)

En este ejemplo, el alfa dice que la imagen es opaca: min = max = 1 (1 = opaco, 0 = transparente). Así que incluso si la imagen tiene un canal alfa, el usuario ve una imagen opaca.

También puede obtener esto:

(...)
  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
(...)

Esta vez, min = 0.372549. Esto significa que algunos píxeles son parcialmente transparentes. mean también es bajo. Parece que gran parte de la imagen utiliza transparencia.

Dependiendo del tipo de comprobación que se desee lograr (opacidad total, "casi opaco", etc.), usted debe comprobar min, mean y tal vez standard deviation si su solicitud es un poco difícil.

Nota: usted podría estar tentado a comprobar los valores enteros para min, mean y otros, como hice en primer lugar. Después de todo, es más fácil tratar con 95 que 0.372549. Si elige esta ruta, tenga cuidado con la profundidad del canal alfa. Si es de 8 bits, entonces 255 es el máximo y significa "opaco". Si es de 16 bits, el máximo es ahora 65535 y 255 significa "casi transparente". Es mejor comprobar los flotadores entre paréntesis, que siempre van de 0 a 1.

Si sospecha que muchas imágenes que procesará no tienen ningún canal alfa, podría ser útil ejecutar primero:

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

Si vertederos:

rgba

Hay un canal alfa (el a en la salida) y convert debe usarse para verificar min, etc.. Pero si no lo hay, no hay necesidad de ejecutar convert. Aunque no hice referencia a estos dos comandos, identify debería ser mucho más rápido que convert.

 22
Author: philippe_b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-07 08:06:06

Compruebe si la imagen tiene un canal alfa

Uso -format %A, según serhiy.respuesta de h . De la documentación :

% Un canal de transparencia de imagen habilitado (true/false)

Compruebe si la imagen no tiene píxeles transparentes o translúcidos

Uso -format %[opaque]. De la documentación :

%[opaco] CALCULADO: es la imagen totalmente opaco?


Ejemplo

Para demostrar, vamos a crear una imagen a.png que tiene un canal alfa pero es totalmente opaco, y una imagen b.png que es la misma excepto por un píxel translúcido:

$ convert rose: PNG32:a.png
$ convert rose: -fill '#0008' -draw "matte 10,10 point" PNG32:b.png

Como era de esperar, el escape %A produce True para ambas imágenes, ya que ambas tienen un canal alfa:

$ identify -format '%A' a.png
True
$ identify -format '%A' b.png  
True

Mientras que el escape %[opaque] produce true en un caso, y false en el otro debido al píxel transparente:

$ identify -format '%[opaque]' a.png
true
$ identify -format '%[opaque]' b.png
false
 15
Author: smls,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:32:33
identify -format %A some_pic.png

Devolverá True si la imagen contiene el canal alfa.

 7
Author: serhiy.h,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-04 20:17:56

Si desea asegurarse de que la transparencia alfa se utiliza realmente, la única solución que veo es iterar todos los píxeles y obtener la información de color para comprobar si es transparente o no. Para imágenes grandes, esto será muy lento, por lo que, como optimización, primero puede hacer una miniatura de la imagen (digamos 20x20) y luego verificar los píxeles de la miniatura. Esta fue una buena solución para mí.

 2
Author: Igor Butuc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-24 11:00:22

Aquí hay un par de funciones bash para comprobar si un png tiene transparencia o no, usando ImageMagick.

Comprobación rápida, que solo comprueba la presencia de un canal alfa:

checkAlphaFast() {
    test $(identify -format %A "$1") == True
}

Comprobación lenta, verifica los píxeles mismos (incluso si el canal alfa está presente):

checkAlphaSlow() {
    test $(identify -format '%[opaque]' "$1") == false
}

Solo debe considerar el uso de la comprobación rápida si está haciendo esto mucho, porque es bastante rápido de cualquier manera. Gracias a las otras personas que respondieron, de las que hice estos funciones :)

Como bono: No hice ningún benchmarking, pero esto puede ser casi tan rápido como el modo rápido y tan preciso como el modo lento:

checkAlpha() {
    checkAlphaFast "$1" && checkAlphaSlow "$1"
}

Utilice estas funciones de esta manera:

if checkAlpha "$myPNG"; then
    # is transparent
else
    # is opaque
fi

Y esto le dará la opacidad de la imagen, donde 0 es totalmente transparente y 1 es totalmente opaco:

checkOpaqueness() {
    if checkAlphaFast "$1"; then
        convert "$1" -verbose info: | grep -A3 Alpha: | tail +4 | head -n1 | sed -r 's/.*\(|\)//g'
    else
        echo 1
    fi
}

Y este sale como un porcentaje redondeado, porque los enteros son mucho más naturales para bash:

checkPercentage() {
    printf %3.2f $(checkOpaqueness "$1") | tr -d . | sed -r 's/^0?0?//'
}
 1
Author: Camilo Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-12 09:04:37