Подтвердить что ты не робот

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

Сценарий

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

4b9b3361

Ответ 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?//'
}