Обнаружение альфа-канала с помощью ImageMagick
Сценарий
Я хотел бы сохранить изображения с альфа-прозрачностью как .png
и изображения без альфа-прозрачности как .jpg
(даже если их исходный формат .png
или .gif
). Как определить, имеет ли изображение альфа-прозрачность с помощью ImageMagick?
Ответы
Ответ 1
Команда ImageMagik:
identify -format '%[channels]' foo.png
будет печатать rgba
или rgb
, если есть или нет альфа-канала, соответственно.
Может существовать альфа-канал, в котором нет данных, которые фактически не имели бы прозрачности, но это немного сложнее.
Ответ 2
Если вы хотите проверить, что изображение действительно прозрачно... (а не только альфа-канал, который может не использоваться)
Используйте эту команду:
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
.
Ответ 3
Проверьте, имеет ли изображение альфа-канал
Используйте -format %A
, согласно serhiy.h answer. Из документа :
% A канал прозрачности изображения (true/false)
Убедитесь, что изображение не имеет прозрачных или полупрозрачных пикселей
Используйте -format %[opaque]
. Из документа :
% [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
Ответ 4
identify -format %A some_pic.png
Вернет True
, если изображение содержит альфа-канал.
Ответ 5
Если вы хотите быть уверенным в том, что альфа-прозрачность действительно используется, единственное решение, которое я вижу, это перебрать все пиксели и получить информацию о цвете, чтобы проверить, прозрачна она или нет. Для больших изображений это будет очень медленно, поэтому в качестве оптимизации вы можете сначала создать эскиз изображения (допустим, 20x20), а затем проверить пиксели эскизов. Это было хорошим решением для меня.
Ответ 6
Здесь несколько функций 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?//'
}