Replace all colours in image using another image

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
jono20-imagk
Posts: 1
Joined: 2018-10-15T17:23:35-07:00
Authentication code: 1152

Replace all colours in image using another image

Post by jono20-imagk » 2018-10-15T17:35:00-07:00

Hello all

I have 2 images:
1. sourceImage.png
2. colorPalette.png

I would like to replace all colours in sourceImage.png where they exist in colorPalette.png with RED. Is this possible in ImageMagick?

Thanks!
Jon

User avatar
fmw42
Posts: 23997
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Replace all colours in image using another image

Post by fmw42 » 2018-10-15T19:31:10-07:00

I am not sure I understand. Imagemagick can replace the input colors with the nearest colors from the palette image. I am not sure where the red comes in. In any event please always provide your IM version and platform, if you already use it and your images. You may post to some free image hosting service such as dropbox.com that won't change your image format and put the URLs here.

Correct me if I am wrong. If your image contains exactly the same colors as in the palette, you want to write red to the image, no matter what the palette color is. Is that correct?

You could do that as follows, but it needs a bit of scripting. Here is a unix script:

# create image of several colors
convert -size 100x100 xc:black xc:red xc:yellow xc:green1 xc:cyan xc:blue xc:magenta +append image.png
Image

# create palette from only red, green1 and blue
convert -size 10x10 xc:red xc:green1 xc:blue +append palette_rgb.png
Image

# just to show the results of -unique-colors txt:

Code: Select all

convert palette_rgb.png -unique-colors txt:

Code: Select all

# ImageMagick pixel enumeration: 3,1,65535,srgb
0,0: (65535,0,0)  #FF0000  red
1,0: (0,65535,0)  #00FF00  lime
2,0: (0,0,65535)  #0000FF  blue
#So the next line filters that output to just retain the hex values in the colorList

Code: Select all

colorList=$(convert palette_rgb.png -unique-colors txt: | tail -n +2 | sed 's/[ ][ ]*/ /g' | cut -d\  -f 3)
convert image.png new_image.png
for color in $colorList; do 
convert new_image.png -fill red -opaque "$color" new_image.png
done
Image

If you want nearby colors that are slightly different from your palette colors to be red, then add -fuzz XX% before the -fill red.

snibgo
Posts: 10820
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Replace all colours in image using another image

Post by snibgo » 2018-10-16T08:48:10-07:00

Doing this with a shell loop that reads "txt:" is the obvious method. The loop might build a command with many "-opaque" operations. But it can be done in a single magick command. Windows BAT syntax:

Code: Select all

magick ^
  image.png +write mpr:ORIG ^
  -set option:SIZE %%wx%%h ^
  NULL: ^
  ( palette_rgb.png ^
    -unique-colors ^
    -crop 1x1 +repage ^
    -scale "%%[SIZE]^!" ^
  ) ^
  -compose Difference -layers composite ^
  +transparent Black ^
  -fill Red -colorize 100 ^
  -background None ^
  -layers Flatten ^
  mpr:ORIG ^
  -compose DstOver -composite ^
  out.png
With large inputs and large palettes, this eats memory. We chop the palette into many 1x1 images and scale them all up to the image size. We find the difference of each of these with the main image. Each difference is black where the colour matches, so we make the others transparent, and change black to red. Lay all these over the original, and the job is done.
snibgo's IM pages: im.snibgo.com

snibgo
Posts: 10820
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Replace all colours in image using another image

Post by snibgo » 2018-10-19T02:18:49-07:00

Another possibility is to crop the palette image into 1x1 images, and use "%[pixel:]" to create "-opaque" operations. Then include those operations in the main command.

This doesn't eat memory, runs "magick" only twice, and reads each input only once each.

Windows BAT syntax:

Code: Select all

for /F "usebackq tokens=*" %%L in (`%IMG7%magick ^
  palette_rgb.png ^
  -unique-colors ^
  -crop 1x1 +repage ^
  -format "-opaque %%[pixel:p{0,0}] " ^
  info:`) do set OPAQ=%%L

%IMG7%magick ^
  image.png ^
  -fill Red ^
  %OPAQ% ^
  out.png
snibgo's IM pages: im.snibgo.com

Post Reply