2

I am aware of Replace a color using Wand and Change color of specific pixels [Wand] but both of these use a line like

    draw.color(192,84,'replace')

In which you need to pass the location of a pixel of the relevant color. What if you know the color you want to replace but not its location? I want to replace the color of pixels in an image without passing a reference to the location of a pixel of that color. Do you really have to scan the entire image looking for something you already know is there?

The imagemagick equivalent would be

convert balloon.gif -fill white -opaque blue balloon_white.gif
Belasco
  • 23
  • 4
  • You could try PythonMagick from the developers of ImageMagick. – fmw42 Feb 22 '18 at 01:14
  • I'll try and look at PythonMagick. [Seems you have to look to the C++ documentation](https://stackoverflow.com/questions/2445985/where-can-i-find-pythonmagick-documentation) to understand it though. To tell the truth, I'm a little confused about what module to go with to manipulate images in python. – Belasco Feb 23 '18 at 11:26

2 Answers2

1

If you want to match -opaque functionality, then you'll need to implement the MagickOpaquePaintImage C method.

import ctypes
from wand.api import library
from wand.image import Image
from wand.color import Color
from wand.compat import nested

# Map C-API to Python
library.MagickOpaquePaintImage.argtypes = (ctypes.c_void_p,  # Wand
                                           ctypes.c_void_p,  # target
                                           ctypes.c_void_p,  # fill
                                           ctypes.c_double,  # fuzz
                                           ctypes.c_bool)    # invert

with Image(filename='rose:') as img:
    with nested(Color('#E93A43'), Color('ORANGE')) as (target, fill):
        library.MagickOpaquePaintImage(img.wand,
                                       target.resource,
                                       fill.resource,
                                       img.quantum_range * 0.10, # -fuzz 10%
                                       False)
    img.save(filename='output.png')

output.png

emcconville
  • 23,800
  • 4
  • 50
  • 66
  • Thanks @emcconville, that absolutely works. I'm curious to know what resources you used to craft that answer so that I might be able to do that for myself one day ;) – Belasco Feb 23 '18 at 11:41
  • Happy to help. If this answered your original question, please mark this as "Accepted" so other readers know your problem was solved. As for resources to help understand: That's the beauty of OpenSource, there's nothing stoping you from reading the source code, and once you have a basic understanding of the authors intended design, all ported language bindings become perfectly clear. – emcconville Feb 23 '18 at 14:09
1

Since wand 0.5.4 the method opaque_paint is available so the clever hack @emcconville proposed is not required anymore. You can do just:

from wand.image import Image
with Image(filename='rose:') as im:
  im.opaque_paint(target='#E93A43', fill='Orange', fuzz=0.10)
  im.save(filename='output.png')
vokimon
  • 1,602
  • 1
  • 12
  • 9