Search code examples
imagecolorsimagemagickimagemagick-convert

ImageMagick - How to change saturation of a targeted color?


With ImageMagick convert, how to adjust the saturation of a specific hue of colors? (in degrees)

e.g. I increase the saturation of the red (0 degree hue). The bluish colors will not be affected, but the orange will be saturated a little bit as well since it is next to the red.

Of course I'd like to be able to configure the width of colors affected.

NOTE: please use convert commands, not redirect to a script.

PS: to clarify after emcconville's answer:

The saturation would be progressive: the closer we are to the matching color, the more the filter applies. Basically the way it is done in Photoshop. See screenshot - sorry it's in french, Teinte means Hue. You can see and adjust the range of matching color in degrees in the bottom bar, between 8 and 90 (and 318 to 255) the filter is progressive.

 Photoshop Saturation Screenshot


Solution

  • The Color Modification guide offers a few examples

    Here's an example that will drop the saturation by half if the hue is close to red (0°)

    convert rose: \( +clone -modulate 100,50 \) \
            -fx '(u.hue < 0.1 || u.hue > 0.9)? v : u' out.png
    

    Change saturation of a targeted color

    This works by copying the first image (+clone), and alter the saturation (-modulate) of the copied image. For the -fx part, u is the first image, and v is the second. If the hue of the first image matches our color, return the second image, else return the first.

    Note: Red is 0°, so we need a logical OR (||), but if we're attempting to match another color, not overlapping zero, use the logical AND (&&).

    example with blue

    -fx '(u.hue < 0.69 && u.hue > 0.63) ? v : u'
    

    Additional Answer

    The same -fx approach can be used by calculating the linear scale -- like this answer, or here. Below is a similar (but not accurate) equation, and shows how to isolate the saturation channel.

    convert rose: -colorspace HSL \
      \( +clone -colorspace sRGB \
         -fx '(hue < 0.1)?saturation+((1-(hue+0.1)*10%1)/10):(hue > 0.9)?saturation+(((hue-0.1) * 10)%1):saturation-(abs(0.5-hue))' \
      \) \
      -compose CopyGreen -composite \
      -colorspace sRGB \
      out.png
    

    More change saturation of a targeted color

    The -compose CopyGreen -composite seems odd, but what that is really doing is taking the image generated with -fx, and applying that as the second color channel (saturation).

    Also experiment with -color-matrix, -contrast-stretch, & -linear-stretch.