Page 1 of 1

Replace all colours in image using another image

Posted: 2018-10-15T17:35:00-07:00
by jono20-imagk
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?


Re: Replace all colours in image using another image

Posted: 2018-10-15T19:31:10-07:00
by fmw42
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 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

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

# 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

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

Re: Replace all colours in image using another image

Posted: 2018-10-16T08:48:10-07:00
by snibgo
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 ^
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.

Re: Replace all colours in image using another image

Posted: 2018-10-19T02:18:49-07:00
by snibgo
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% ^