imagemagick: Выделение по цвету со сглаживанием

Работа с различными видами графики, изображений, решение проблем

Модератор: Модераторы разделов

nick87720z
Сообщения: 169
ОС: Gentoo / Calculate

imagemagick: Выделение по цвету со сглаживанием

Сообщение nick87720z »

Для чего: недавно открыл для себя тему Reflektions, из которой решил сделать аналог гномьего ACYL (Any Color You Like). Сделал скрипт, который с помощью imagemagick (у самого стоит graphicsmagick) перекашивает абсолютно черные и белые области, оставляя цветные и серые нетронутыми.

Сейчас используется такая последовательность:
1. Создаются маски путем копирования "серого канала" - для черной и белой областей.
2. На их основе создаются цветные слои, которые затем накладываются на исходное изображение.

Проблема в том, что цветные и серые области частично закрашиваются, т.к. соответствующие области слоев полупрозрачны.
Перед этим я пробовал использовать -mask, который согласно `man gm` должен пропускать только чисто черные области (то что надо), но вне зависимости от того, как это достигается (он вообще брал все не-белые области, решил путем правки самой маски), в результате обе маски оставляют нетронутыми промежуточные пикселы на границах цветных областей, что совсем нехорошо при инвертировании исходных цветов (например, black->LightBlue & white->black).
Использование -sharpen на этапе создания масок частично решило проблему, но некоторые отдельные пикселы все равно "бъются" (по аналогии с мониторами :) ).
Из за этого и решил попробовать вариант со слоями, но те же грабли все-равно мешаются.

Пример иконки media-zip:
Оригинальная Изображение
С использованием слоев, black->DarkBlue white->LightGreen Изображение

Предыдущий алгоритм с использованием -mask, -sharpen и дополнительного обрезания серых пикселов маски
доп. иконки Akregator, KMag - эту раскраску я сейчас использую (что происходит без -sharpen - лучше 100 раз услышать или прочитать %) ).
ИзображениеИзображениеИзображение

p.s. Еще раз присмотрелся к Akregator, похоже там проблемные пикселы вообще прозрачные.
Спасибо сказали:

nick87720z
Сообщения: 169
ОС: Gentoo / Calculate

Re: imagemagick: Выделение по цвету со сглаживанием

Сообщение nick87720z »

Собственно скрипты:

Предыдущий вариант:

Код: Выделить всё

#!/bin/bash

img_src="$1"
img_dest="$2"
color_dark="$3"
color_light="$4"

tmpdir="/tmp/colorize_reflektion_$UID"
if ! test -d "$tmpdir" ; then
    test -e "$tmpdir" && rm -rf "$tmpdir"
    mkdir "$tmpdir"
fi

# Implementation 1: simple color replacement
#convert $img -fill "#302015" -opaque white -fill "#ffe0a0" -opaque black ./icon-out-opaque.png
#composite -compose In ./icon-out-opaque.png $img_src $img_dest

# Implementation 2: more complex, using masks
img_size=$( identify -format '%w,%h' "$img_src" )

# Mask creation
convert "$img_src" -channel gray -sharpen 3 $tmpdir/icon-mask-b.png
convert "$img_src" -channel gray -sharpen 3 -negate $tmpdir/icon-mask-w.png

# Mask fix - imagemagick treats gray mask parts as black
cp $tmpdir/icon-mask-b.png $tmpdir/icon-mask-b-tmp.png
convert $tmpdir/icon-mask-b.png \
    -fill white -mask $tmpdir/icon-mask-w.png -draw "rectangle 0,0 $img_size" \
    $tmpdir/icon-mask-b.png

convert $tmpdir/icon-mask-w.png \
    -fill white -mask $tmpdir/icon-mask-b-tmp.png -draw "rectangle 0,0 $img_size" \
    $tmpdir/icon-mask-w.png

convert $img_src \
    -fill "$color_dark"  -mask $tmpdir/icon-mask-b.png -draw "rectangle 0,0 $img_size" \
    -fill "$color_light" -mask $tmpdir/icon-mask-w.png -draw "rectangle 0,0 $img_size" \
    $tmpdir/icon-out-opaque.png

composite -compose In $tmpdir/icon-out-opaque.png $img_src $img_dest


Последний вариант:

Код: Выделить всё

# Implementation 2: more complex, using masks
img_size=$( identify -format '%w,%h' "$img_src" )

# Mask creation
convert "$img_src" -channel gray -negate $tmpdir/icon-mask-b.png
convert "$img_src" -channel gray $tmpdir/icon-mask-w.png

# Coloration layers
convert $tmpdir/icon-mask-b.png \
    -fill "$color_dark" -draw "rectangle 0,0 $img_size" \
    $tmpdir/black-part.png
composite -compose CopyOpacity $tmpdir/icon-mask-b.png $tmpdir/black-part.png $tmpdir/black-part.png

convert $tmpdir/icon-mask-w.png \
    -fill "$color_light" -draw "rectangle 0,0 $img_size" \
    $tmpdir/white-part.png
composite -compose CopyOpacity $tmpdir/icon-mask-w.png $tmpdir/white-part.png $tmpdir/white-part.png

# Extract original color parts
convert "$img_src" \
    -preview Saturation \
    $tmpdir/color-part.png

convert "$img_src" \
    -draw "image Over 0,0 $img_size $tmpdir/white-part.png" \
    -draw "image Over 0,0 $img_size $tmpdir/black-part.png" \
    $tmpdir/icon-out-opaque.png

composite -compose In $tmpdir/icon-out-opaque.png $img_src $img_dest
Спасибо сказали: