Композиция предварительно умноженных изображений с использованием ImageMagick
У меня есть два изображения. Одним из них является фон без альфа. Другое белое облако. Альфа-изображение облака предварительно умножается на черный. Когда я объединяю их, в белом облаке есть черное, поэтому оно выглядит серым, а не белым, как должно. Я делаю:
convert -gravity Center bg.tga whitecloud.tga -composite comp.tga
Есть ли способ сложения предварительно умноженных изображений в ImageMagick, или изображение должно быть без предварительного умножения? Можно ли сделать предварительно умноженное изображение без предварительного умножения с помощью ImageMagick?
Обновить:
Хорошо, вот изображения в формате TGA для скачивания:
http://acatysmoof.com/posting/problems/imagemagick/premultiplication/bg.tga http://acatysmoof.com/posting/problems/imagemagick/premultiplication/whitecloud.tga http://acatysmoof.com/posting/problems/imagemagick/premultiplication/aftereffects.tga http://acatysmoof.com/posting/problems/imagemagick/premultiplication/imagemagick.tga
и в том же порядке, что и jpgs для просмотра в вашем браузере:
Я перепробовал все предоставленные режимы, но ни один из них не дал того же результата, что и After Effects.
5 ответов
Было бы проще, если бы вы показали свои изображения, но попробуйте добавить -compose lighten
до -composite
в вашей команде, вот так:
convert a.tga b.tga -compose lighten -composite out.tga
По сути, это заставит ImageMagick выбрать более светлый пиксель двух изображений в каждой точке.
Если это не сработает, попробуйте другие режимы наложения
for b in $(identify -list compose); do
convert -label "$b" bg.tga whitecloud.tga -compose $b -composite miff:-
done | montage - -tile 5x out.png
Я вроде думаю Atop
, Dissolve
, SrcAtop
а также SrcOver
может быть ваши друзья, но посмотрите в натуральную величину и посмотрите, что плавает на вашей лодке. Это было бы
convert a.tga b.tga -compose Atop -composite out.tga
Обычная операция альфа-смешивания ( оператор Duff-Porter Over ) делает это:
output.rgb = src.rgb * src.a + (1-src.a) * dst.rgb
Когда альфа предварительно умножается, это просто означает, что цвет источника ужеsrc.rgb * src.a
, поэтому вам нужно только добавить(1-src.a) * dst.rgb
.
В шейдере это очень быстро. Но в ImageMagick это, похоже, сбивает с толку, потому что, похоже, нет прямого оператора, который бы это делал.
Однако вы можете вычислить его, если разобьете его на несколько шагов:
# extract alpha channel from cloud
convert whitecloud.tga -auto-orient -alpha extract -colorspace gray alpha.png
# invert alpha channel
convert alpha.jpg -negate alpha-inv.png
# (1-cloud.a) * bg.rgb
composite -compose Multiply alpha-inv.png bg.tga bg-pre.png
# remove alpha channel to obtain cloud.rgb
convert whitecloud.tga -auto-orient -alpha off whitecloud-rgb.png
# cloud.rgb * cloud.a + (1-cloud.a) * bg.rgb
composite -compose plus whitecloud-rgb.png bg-pre.png output.png
Вот результат:
Для справки, вот пара промежуточных изображений:
- альфа-канал облака
- фон, умноженный на обратную альфу облака
Преимущество разделения его на несколько этапов заключается в том, что его легче отлаживать, если ваше изображение имеет неправильный альфа-канал или что-то в этом роде.
Я понимаю, что вы просили решение imagemagick, но если возможны другие библиотеки, libvips поддерживает композицию porter-duff с предварительно умноженной альфой.
Я создал PNG для вашего изображения облака (в браузере это будет выглядеть странно, поскольку альфа умножается заранее):
Затем побежал:
$ vips composite2 bg.jpg white-cloud.png x.png over --premultiplied
Делать:
Что, я думаю, соответствует последствиям.
Вот документы для составного оператора:
https://www.libvips.org/API/current/libvips-conversion.html#vips-composite
Вот команда Imagemagick, которая делает то, что вы хотите:
convert -gravity Center whitecloud.tga -fx "u/max(u.a, 1/255)" bg.tga +swap -composite -fx "u*u.a" comp.tga
Что тут происходит?
-fx
команда №1: преобразовать whitecloud.tga из предварительно умноженного альфа-канала в "нормальный". Вmax()
Оператор - это особый случай, позволяющий избежать деления на ноль.+swap
команда: Сделатьbg.tga
первое изображение и исправленноеwhitecloud.tga
секунда.-composite
эти два обычных изображения без предварительного умножения.-fx
команда №2: взять результат и вернуться к предварительно умноженному альфа-формату.
Это дает точно такой же результат, как и After Effects.
Обратите внимание, что, как я писал, это работает только для непрозрачных
bg.tga
. Вам нужно будет проделать дополнительную работу, чтобы обработать прозрачное фоновое изображение.
Если вы хотите продублировать результат After Effects, то я считаю, что вы хотите сделать в ImageMagick следующее - объединить фоновое изображение с белым изображением, используя облако в качестве маски:
convert bg.tga \( -clone 0 -fill white -colorize 100 \) whitecloud.tga -compose over -composite cloud_blue.tga
Я опубликовал результат в формате JPG, но мой результат в формате.tga такой же.