Replacing Multiple specific color to the specified color

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
JalpaBhavsar
Posts: 3
Joined: 2012-04-10T02:57:27-07:00
Authentication code: 8675308

Replacing Multiple specific color to the specified color

Post by JalpaBhavsar »

I had original image that is Image
which is having color red and white
i changed the color of red to pink but some pixel at the border section remains unchanged to pink
and same while changing white to some other color

I tried alot to achieve the result like Image

I tried to color entire image to pink color - saved as logo1.png
than another image i create which makes red transparent - saved as logo2.png
and than composite logo1.png logo2.png to logo3.png (Where logo3.png shows the result with some red pixel)

ANY Solution or discussion which i can refer at to achieve the above thing. :(
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Replacing Multiple specific color to the specified color

Post by fmw42 »

What was your complete command line? What version of IM are you using and what platform.

I assume you used something like:

convert image -fill pink -opaque red result

To make it allow for near-red add -fuzz


convert image -fuzz XX% -fill pink -opaque red result

XX=0 is perfect red, the larger the XX value the more different colors will be included with the red and turned to pink.

see
http://www.imagemagick.org/Usage/color_basics/#replace
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Replacing Multiple specific color to the specified color

Post by anthony »

WARNING: color replacement destroys anti-aliasing pixels and it best avoided if possible!!!

The image has three colors: transparent, inside and border. (not counting anti-aliasing edge color mixes.
The transparency can remain as it, it is already its own channel, so we can mostly ignore it for colouring.
https://dl.dropbox.com/u/9500683/love_gnome_red.png

What I would do is grayscale and -auto-level the image. This will convert the border to black, and the inside to white.
Form that image ANY color for inside or outside can then be set using +level-colors WITHOUT loosing anti-aliasing.

This does NOT work...

Code: Select all

convert logo.png -colorspace Gray -auto-level love_gnome_gray.png
Image

The problem is -auto-level currently does not ignore transparency (at least in default channel settings) :-(
-- I have it on my todo list, but it will be a long time before I get to it!

So we need to set the color of transparent pixels to something between the extreme colors wanted.
See Alpha Background
http://www.imagemagick.org/Usage/maskin ... background

Code: Select all

convert logo.png -background Gray -alpha background  -colorspace Gray -auto-level love_gnome_bw_bad.png
Image
THIS FAILED

It looks like some almost-but-not-quite fully transparent pixels have a 'black' color instead of the proper anti-aliasing color of the 'red region' You can see the few bad black pixels around the edges when you turn off transparency after setting transparent colors to gray.

Code: Select all

convert logo.png -background Gray -alpha background -alpha off love_gnome_bad_pixels.png
Image

There are is ways to fix this.
For example -level-colors with EXACTLY the right colors (difficult without using a script, OR features planned for IMv7)

But I'll use some trickery... Extracting a non-red channel (preserving transparency) to generate a true grayscale image.

Code: Select all

convert logo.png -background Gray -alpha background \
           -alpha off  -channel B -separate +channel -alpha on \
           love_gnome_bw.png
Image

Phew! now we have the 'clean' black-white-transparent image (with anti-aliasing) -- well almost clean - the problem is still there.
With this image we can now color it with any set of colors you like -- By name or Values!

Code: Select all

convert love_gnome_bw.png +level-colors purple,violet  love_gnome_purple.png
Image

The other technique for recoloring simple images with a 'single' basic color and shades (with or without transparency) is to make the single color 'red' then use Hue Rotations to change the color. See Modulate
http://www.imagemagick.org/Usage/color_mods/#modulate
And especially see a application of this... Pins in a Map
http://www.imagemagick.org/Usage/layers/#layer_pins

However be warned that module does not preserve color intensity properly during hue rotations. This is an artefact of using a highly non-linear HSL colorspace for its hue rotation.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
JalpaBhavsar
Posts: 3
Joined: 2012-04-10T02:57:27-07:00
Authentication code: 8675308

Re: Replacing Multiple specific color to the specified color

Post by JalpaBhavsar »

Thanks to fmw and antony

Antony, what you mention solve my problem of pixel, but How come i will come to know that red is the color only which i want to change, what is the image has other channel apart from "R" if it is G or B than

and what if image has more than three colors ??

Please Help
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Replacing Multiple specific color to the specified color

Post by anthony »

Then your better to try and create a mask of each color, that you can color and overlay. And example of colring and overlaying such masks is in
Masking and Background Removal, Masks as Colored Shapes
http://www.imagemagick.org/Usage/masking/#shapes

The tricky part is extracting each of the color areas. You have two solutions I can see for this.

The first is much like the above, but concentrating on extracting just one color area 'mask' at a time. Depending on the order you will overlay the mask shapes, you can remove the inside parts of a specific colored area to simplify the overlay. In fact I recommend this.

For example
Image Image
Now overlay each with appropriate color. (order of overlay is important!

Code: Select all

convert \( love_gnome_heart.png -background hotpink -alpha shape \) \
            \( love_gnome_foot.png  -background firebrick -alpha shape \) \
            -background none -flatten  gnome_love_colored.png
Image

NOTE you can pack 3 masks in an image, one in each channel, 4 is you include alpha channel. (IMv7 can handle even more channels per image). The image will not look 'nice' but will pack into image files nicely.



The other method (which I don't really like) is to remove all anti-aliasing pixels (shades), and leave just the pure colors wanted. (-remap with +dither can do this). Then filter the image through a raster to vector program, like autotrace. The resulting SVG image will have vector drawing paths for each color, that you can then extract and either draw individually, OR draw to generate each colored mask.

The major problem in the result is that it may not be a exact 'fit', but may also be even smoother. On the other hand a 'vector path' can also be scaled to any size you want without loss of quality! That is the beauty of a vector image.

See Edging using a Raster to Vector Converter
http://www.imagemagick.org/Usage/transform/#edge_vector
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
JalpaBhavsar
Posts: 3
Joined: 2012-04-10T02:57:27-07:00
Authentication code: 8675308

Re: Replacing Multiple specific color to the specified color

Post by JalpaBhavsar »

Hi Anthony,

I think i am reaching to the goal what i want to achieve, but as you mention that mask will be created for each color. The link which you provided was helpful. But after trying and referring all the things ( i.e. alpha extracting ) for each color.
I am not getting it
it always give me result as below:
Image

Can you please explain how I can tell a command that only red color must be extract and white must be extract separately
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Replacing Multiple specific color to the specified color

Post by anthony »

First it is not just 'white' you want to preserve, but all the white-red border colors (anti-alising). As such you need to be careful.

In my images I sort of cheated and used "love_gnome_bw.png" which had already been cleaned. I simply overalys that image on 'black' and presto just the center white part was kept. Already a mask. The heart as you know was just a alpha extract.

Rememin you want to preserve the edge, so you don't want to modify those pixels (except when you do global modification of all pixels).

Their are basically two methods of getting a area of color while preserving the 'thin' anti-aliasing edge.

One is just load it in an image editor and manuall make all the non-white colors (transparency in this case) the same 'red' as everthing else. A greyscale and -auto-level should then convert it to a mask, while preserving the anti-alias.

The second assumes each color is cleaning surrounded by another color (red). We get a mask, 'dilate it' and then use it to wipe out everything else.

Hmmm

Code: Select all

   convert logo.png +transparent white \
               -channel A -morphology dilate square:2 +channel \
               -background '#c71807' -alpha remove \
               -type grayscale -auto-level \
               love_gnome_foot.png
first line wipes all non -pure white colors. -- this is VERY aliased.
second dilate the alpha. channel enough to cover all anti-aliasing pixels.
Flatten that onto the surrounding color '#c71807' - yes this step is horrible - a better method needed
and turn result into a mask. -- complete with anti-aliasing.

DAMN -- this image is so unclean the auto-level still fails to make the surrounding background pure black! Seems their are some ringing effects in the anti-aliasing pixels around the foot. Either from 'sharpening' or from having been saved using JPEG at some point in its past. This image is ok buit you may need to watch for 'negative ringing' inside the shape as well as outside.
See Ringing Artifacts
http://www.imagemagick.org/Usage/resize/#ringing

You will need to use -normalization or -contrast-stretch to fix this,
http://www.imagemagick.org/Usage/color_mods/#normalize
though it will modify anti-aliasing slightly.

OR better still extract the new 'not quite black' result and use -level-colors

Code: Select all

   convert logo.png +transparent white \
               -channel A -morphology dilate square:2 +channel \
               -background '#c71807' -alpha remove \
               -type grayscale -auto-level \
               -level-colors '#0b0e0b0e0b0e',white \
               love_gnome_foot.png
Image

NOTE in IMv7 IM will be able to directly extract that horible '#0b0e0b0e0b0e' color -- IMv6 can not!

Note we probably could probably have merged -auto-level and -level-colors together. They essentually do similar operations onto the image
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Replacing Multiple specific color to the specified color

Post by anthony »

JalpaBhavsar wrote:it always give me result as below:
Image

Can you please explain how I can tell a command that only red color must be extract and white must be extract separately
What is wrong with that? The foot is completely inside, you can just overlay it's colors on top. and get it right!

If you have the foot, you can negate the image and multiply (compose) the images together to 'cut a foot shaped hole' in the middle of the heart!

Warning: better to layer the foot after the heart (withotu a hole). The problem is that mixing 'anti-aliased colors' can be tricky, and unless you know what you are doing you can get it wrong. See 'Mask Alinement'
http://www.imagemagick.org/Usage/masking/#aligning

Essentually if the color masks are completely seperate (like jigsaw puzzle pieces), then if you 'add' them all together you should get pure white (without going over or clipping). When joining colors or shaped areas. then you also need to 'add' or 'plus' the indivudual color pieces together to get it right! Overlaying them, and you normally would, will result in transparent join lines along the anti-aliased edges.

It is far better to not have any 'holes' and simply 'over' the inside colors after the outside colors. That is what 'over' compostion is designed to do, overlay shapes ONTO solid colors.

Even the 'SVG autotrace' generates it's SVG vector results without 'holes' for the same reason. Just 'layer' the inside colors on top of sourrounding outside colors.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply