Color Management @ ImageMagick
Author: ImageMagick Studio LLC
Description: ImageMagick® is a software suite to create, edit, compose, or convert bitmap images. It can read and write images in a variety of formats (over 200) including PNG, JPEG, JPEG-2000, GIF, WebP, Postscript, PDF, and SVG. Use ImageMagick to resize, flip, mirror, rotate, distort, shear and transform images, adjust image colors, apply various special effects, or draw text, lines, polygons, ellipses and Bézier curves.
Keywords: color, management, ImageMagick, PerlMagick, image processing, image, photo, software, Magick++, OpenMP, convert

Color management has changed significantly between ImageMagick version 6.7.5-5 and 6.8.0-3 in order to better conform to color and grayscale standards.

The first major change was to swap -colorspace RGB and -colorspace sRGB. In earlier versions, RGB really meant non-linear sRGB. With the completion of the changes, RGB now means linear color and sRGB means non-linear color in terms of their respective colorspaces.

ImageMagick supports color profiles, however, for images without a profile or a declaration of colorspace, ImageMagick assumes non-linear sRGB. Most image processing algorithms assume a linear colorspace, therefore it might be prudent to convert to linear color or remove the gamma function before certain image processing algorithms are applied. For example,

    convert myimage.jpg -colorspace RGB -resize 200% -colorspace sRGB mybigimage.jpg

To declare that an image is linear RGB rather than sRGB, you can use the set option:

    convert myimage.png -set colorspace RGB myRGBimage.png

Afterwards, the verbose information for the output file lists the colorspace as RGB. This only works on image types containing meta data that distinguishes between linear RGB and non-linear sRGB, such as PNG and GIF. Therefore, if the above command is run with a JPG or TIF output format, the verbose information for the colorspace still shows sRGB. In order to properly have the JPG output know that it is linear RGB, include an appropriate color profile.

The second major change treats any grayscale image as linear rather than non-linear, as it was previously. This change is appropriate, since many types of processing requires a linear colorspace. This means that the conversion of a color image to grayscale via `-colorspace gray` looks darker relative to previous versions of ImageMagick (note that desaturating to convert to grayscale does not convert the image to linear grayscale). If you prefer to keep the conversion to non-linear grayscale, set the colorspace of the input to linear RGB so that `-colorspace gray` does not apply the gamma correction during the conversion process. For example, the following produces a non-linear grayscale result.

    convert myimage.png -set colorspace RGB -colorspace gray myRGBimage.png

The same concept is needed when separating channels. Normally, the conversion to separate each channel of an sRGB color image produces separate linear grayscale images. However the same concept can be applied, if it is desired to keep the separate channels as non-linear grayscale. For example, the following produces non-linear grayscale channels.

    convert myimage.png -set colorspace RGB -separate myimage_channels_%d.png

When separating and recombining channels, with potential intermediate processing, it is important to identify the colorspace used, especially during the recombination. For example,

    convert myimage.png -separate myimage_channels_%d.png
    convert myimage_channels_*.png -combine myimage2.png

In the above example, the result is darker than the original, because the channels were separate as linear gray and subsequently combined as linear color. In order to return the channels back to sRGB, one must change the colorspace from RGB back to sRGB after the `-combine` step.

    convert myimage.png -separate myimage_channels_%d.png
    convert myimage_channels_*.png -combine -colorspace sRGB myimage2.png

If one desires to separate to non-linear grayscale channels, recombine them later, perhaps after some processing, then use the same concept as above for maintaining non-linear grayscale:

    convert myimage.png -set colorspace RGB -separate myimage_channels_%d.png
    convert myimage_channels_*.png -combine -colorspace RGB -set colorspace sRGB myimage2.png

When converting to another colorspace and back, such as between sRGB and HSL, the following two commands handle the first case of linear channels and the second case of non-linear channels:

    convert myimage.png -colorspace HSL -separate myimage_channels_%d.png
    convert myimage_channels_*.png -set colorspace HSL -combine -colorspace sRGB myimage2.png

    convert myimage.png -set colorspace RGB -colorspace HSL -separate myimage_channels_%d.png
    convert myimage_channels_*.png -set colorspace HSL -combine -colorspace RGB -set colorspace sRGB myimage2.png

A majority of the image formats assume an sRGB colorspace (e.g. JPEG, PNG, etc.). A few support only linear RGB (e.g. EXR, DPX, CIN, HDR) or only linear GRAY (e.g. PGM). A few formats support CMYK. For example JPG does, but PNG does not. Then there is the occasional format that also supports LAB (that is CieLAB) (e.g. TIFF, PSD, JPG, JP2). For additional information, see the Colorspace and Supported Formats pages.

When specifying individual colors as `rgb(...)` or hex, these colors will still be interpreted as non-linear, that is, as sRGB colors. However if one wants to create linear colors, use `icc-color(rgb,r,g,b)"`, where `r`, `g`, and `b` are in the range 0 to 1. See the Color page.

There are now also distinctions between linear and non-linear shades of gray. Any named shade of gray, such as black, white or numbered grays like `gray50` are non-linear gray. However, `gray(...)` is now linear gray. Hex grayscale values are non-linear.

This means that you need to be careful when you create grayscale gradients. For example, `gradient:`, `gradient:"white-black"`, `gradient:"gray100-gray0"` generates non-linear gradients, however `gradient:"gray(255)-gray(0)"` or `gradient:"gray(100%)-gray(0%)"` generates linear gradients.