Обнаружение альфа-канала с помощью ImageMagick

сценарий

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

6 ответов

Решение

Команда ImageMagik:

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

распечатает rgba или же rgb если есть или нет альфа-канал, соответственно.

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

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

использование -format %A в соответствии с ответом serhiy.h. Из документации:

% Канал прозрачности изображения включен (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] побег производит true в одном случае и false в другом из-за одного прозрачного пикселя:

$ identify -format '%[opaque]' a.png
true
$ identify -format '%[opaque]' b.png
false

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

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

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,

identify -format %A some_pic.png

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

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

Вот пара функций 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?//'
}
Другие вопросы по тегам