Обнаружение альфа-канала с помощью 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?//'
}