Обнаружение альфа-канала с помощью ImageMagick - PullRequest
25 голосов
/ 06 апреля 2010

Сценарий

Я хочу сохранить изображения с альфа-прозрачностью как .png и изображения без альфа-прозрачности как .jpg (даже если их исходный формат .png или .gif). Как я могу определить, имеет ли изображение альфа-прозрачность, используя ImageMagick?

Ответы [ 6 ]

27 голосов
/ 06 апреля 2010

Команда ImageMagik:

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

выведет rgba или rgb, если есть или нет альфа-канал, соответственно.

Может присутствовать альфа-канал без данных, который на самом деле не будет прозрачным, но это немного сложнее.

22 голосов
/ 20 сентября 2013

Если вы хотите убедиться, что изображение действительно прозрачное ... (не только альфа-канал, который может быть не использован)

Используйте эту команду:

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:
    min: 255 (1)
    max: 255 (1)
    mean: 255 (1)
    standard deviation: 0 (0)
    kurtosis: 0
    skewness: 0
(...)

В этом примере альфа говорит, что изображение непрозрачное: min = max = 1 (1 = непрозрачное, 0 = прозрачное). Таким образом, даже если изображение имеет альфа-канал, пользователь видит непрозрачную картинку.

Вы также можете получить это:

(...)
  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. Если вы выбираете этот маршрут, остерегайтесь глубины альфа-канала. Если это 8 битов, то максимум 255 и означает «непрозрачный». Если оно составляет 16 бит, то максимальное значение теперь равно 65535, а 255 означает «почти прозрачный». Лучше проверять числа в скобках, которые всегда находятся в диапазоне от 0 до 1.

Если вы подозреваете, что многие изображения, которые вы будете обрабатывать, вообще не имеют альфа-канала, может быть полезно сначала запустить:

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

Если он сбрасывает:

rgba

есть альфа-канал (a на выходе), и convert следует использовать для проверки min и т. Д. Но если его нет, запускать convert не нужно. Хотя я не тестировал эти две команды, identify должен быть намного быстрее, чем convert.

19 голосов
/ 02 января 2016

Проверьте, имеет ли изображение альфа-канал

Используйте -format %A, согласно serhiy.h's answer . Из документации :

% Включен канал прозрачности изображения (true / false)

Проверьте, нет ли на изображении прозрачных или полупрозрачных пикселей

Используйте -format %[opaque]. Из документации :

% [непрозрачный] РАСЧЕТ: изображение полностью непрозрачное?


Пример

Чтобы продемонстрировать, давайте создадим изображение a.png, которое имеет альфа-канал, но полностью непрозрачный, и изображение b.png, которое является таким же, за исключением одного полупрозрачного пикселя:

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

Как и ожидалось, экранирование %A создает True для обоих изображений, поскольку оба имеют альфа-канал:

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

Тогда как %[opaque] escape дает true в одном случае и false в другом из-за одного прозрачного пикселя:

$ identify -format '%[opaque]' a.png
true
$ identify -format '%[opaque]' b.png
false
7 голосов
/ 05 декабря 2013
identify -format %A some_pic.png

Вернет True, если изображение содержит альфа-канал.

2 голосов
/ 24 января 2012

Если вы хотите быть уверены, что альфа-прозрачность действительно используется, я вижу единственное решение - перебрать все пиксели и получить информацию о цвете, чтобы проверить, прозрачна она или нет. Для больших изображений это будет очень медленно, поэтому в качестве оптимизации вы можете сначала сделать миниатюру изображения (скажем, 20x20), а затем проверить пиксели миниатюр. Это было хорошее решение для меня.

1 голос
/ 12 января 2016

Вот пара функций bash, чтобы проверить, имеет ли png прозрачность или нет, используя ImageMagick.

Быстрая проверка, которая просто проверяет наличие альфа-канала:

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

Медленная проверка, проверяет сами пиксели (даже при наличии альфа-канала):

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?//'
}
...