Search code examples
filtercolorsimagemagickrgbpixel

imagmagick: selectively fill pixels based on r/g/b condition?


Is there a way to selectively replace colors, based on an arithmetic expression using a pixel's R or G or B value?

Example: say I have an RGB image "foobar.png" and I want to change all pixels whose Red channel is <100 into white.

In pseudocode:

for (all pixels in image) { if (pixel.red < 100) then pixel = 0xffffff; }

Is there a way to pull this off with ImageMagick?


Solution

  • You can use FX expressions.

    Say I create a test image...

    convert -size 400x400 gradient:red-blue input.png
    

    input

    Replace any pixel with a red value < 100 (assuming max-value is a 8bit quantum of 255), can be expressed by..

    convert input.png -fx 'r < (100/255) ? #FFFFFF : u' output.png
    

    output

    Update

    FX is powerful, but slow. It'll also draw harsh edges. Another approach is to separate the RED channel, convert it to a mask, and composite over the other channels. This can be done with -evaluate-sequance MAX, or set the alpha channel & compose over a white background.

    Create an example input image.

    convert -size 400x400 xc:white \
        -sparse-color shepards '0 0 red 400 0 blue 400 400 green 0 400 yellow ' \
        input.png
    

    input

    convert -size 400x400 xc:white \
        \( input.png \
            \( +clone  -separate -delete 1,2 \
               -negate -level 39% -negate \
            \) \
            -compose CopyOpacity -composite \
        \) -compose Atop -composite  output.png
    

    output