documentation bugs: color-management.php says IM treats all gray images as linear

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

documentation bugs: color-management.php says IM treats all gray images as linear

Post by Dabrosny »

The document www.imagemagick.org/script/color-management.php still states that IM "treats any grayscale image as linear rather than non-linear", which may have been true at one time, but not in IM7 (nor in late versions of IM6 I believe).

Much of the rest of that html page seems based on this obsolete assumption that grayscale is always treated as linear, and it even provides workarounds for how to deal with grayscale data when it's actually nonlinear.

In fact, IM(7) creates and treats Gray images as nonlinear by default, and in fact such nonlinear Gray is nicely-supported and behaves consistently like sRGB, and converts easily back and forth with sRGB and the other (non-Gray) colorspaces without any large brightness shifts (just some moderate perceptual brightness shifts due to the use of the non-perceptually-based "Luma" video formulas themselves), so long as we don't use -grayscale Rec709Luminance or Rec601Luminance, nor -intensity, nor of course use the -set colorspace operation (except when the current colorspace is actually wrong for some reason).
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by magick »

The documentation is right. Gray is assumed linear. Likely a bug. We are investigating a fix to the problem and documentation now.
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by Dabrosny »

magick wrote: 2017-09-12T08:40:04-07:00 The documentation is right. Gray is assumed linear. Likely a bug. We are investigating a fix to the problem and documentation now.
"-colorspace Gray" seems to create a nonlinear grayscale (in fact same as -grayscale rec709luma) by default in IM7. Under what circumstances is gray assumed linear?
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by Dabrosny »

Dabrosny wrote: 2017-09-12T08:49:51-07:00 "-colorspace Gray" seems to create a nonlinear grayscale (in fact same as -grayscale rec709luma) by default in IM7. Under what circumstances is gray assumed linear?
In fact I've documented what I've observed to be the behavior of grayscale images with respect to "-intensity" as a proposed update to the "-intensity" documentation in this other bugs topic: viewtopic.php?p=149319#p149319 as follows. (I've also drafted an update to "-grayscale" but it has a lot of overlap with this one and I haven't posted it yet.)
Dabrosny wrote: 2017-08-30T16:05:42-07:00 In order to understand what -intensity does and how it replaces the old nonlinear and linear grayscale colorspaces, I did some experimentation and this "-intensity" documentation entry is based on what I believe is the actual behavior of IM 7 (at least in 7.0.6 x64 q16 HDRI).

See my preceding post on this thread for a list of questions that I felt this needed to answer.

I included a form of Snibgo's idea related to the possible use of sRGB and RGB colorspaces even for single-channel grayscale images.

I don't know whether perhaps some of what I'm documenting here is unintended behavior.

(I haven't yet tried to change the documentation for the -grayscale operation because its behavior has an inconsistency that I'll probably submit as a bug report later, rather than merely documenting its current behavior.)

This isn't formatted like the actual documentation, but you get the idea.

------------------------------------------------------------------------------
-intensity method

set image attribute specifying the method to generate intensity values from a non-Gray image or pixel, and that identifies a Gray image as linear or nonlinear

This sets the intensity attribute of the current image(s), and also sets a global default for any further images lacking this attribute themselves. The form +intensity unassigns the intensity.

On a color image (non-Gray colorspace), this attribute determines the formula that will be used by -colorspace Gray to convert to grayscale, and in other situations where an operator needs to calculate a single grayscale value for some purpose, from the image's red, green, and blue pixel components.

The following methods are available (R,G,B indicate linear channels while R',G',B' indicate nonlinear):

Rec709Luminance converts to RGB and then uses 0.212656R + 0.715158G + 0.072186B to get a linear grayscale (equal to luminance Y as in XYZ colorspace)

Rec601Luminance converts to RGB and then uses 0.298839R + 0.586811G + 0.114350B to get a linear grayscale

Rec709Luma converts to sRGB and then uses 0.212656R' + 0.715158G' + 0.072186B' to get a nonlinear grayscale

Rec601Luma converts to sRGB and then uses 0.298839R' + 0.586811G'+ 0.114350B' to get a nonlinear grayscale

If the image has no intensity attribute, the global intensity set by the most recent -intensity is used. If there is no global intensity assigned, then the Rec709Luma nonlinear grayscale formula is currently used by default.

The -colorspace Gray conversion on an existing non-Gray image will set an appropriate gamma of 1 (linear) or 0.454545 (nonlinear) as well as retaining the intensity attribute on the resulting Gray image, so that further operations on this Gray image will know whether to treat it as linear or nonlinear. (Note: if a nonlinear image were ever treated as linear or vice-versa, then conversion back to a non-Gray colorspace would be incorrect, and conversion to an external file format (such as JPEG) would create an image file that would be too dark or too light when viewed.)

Whereas a non-Gray image is treated by IM as having nonlinear or linear values based solely on its colorspace irrespective of gamma (or of intensity), a Gray image will be treated as having linear values only if its intensity attribute is Rec709Luminance (or Rec601Luminance) and its Gamma attribute is exactly 1. For all other combinations of intensity and gamma value (or lacking one or both), the Gray image will be treated as nonlinear (like sRGB).

Using -intensity (or +intensity) on an existing Gray image can change the interpretation of the image's values (as linear vs. nonlinear) without a corresponding change in those values themselves, much like -set colorspace changes the interpretation of a non-Gray image's values without changing those values. You should also -set gamma (1 for linear or 0.454545 for nonlinear) to be consistent with the new intensity, because, unlike -set colorspace, setting the intensity does not change gamma. If you set a linear intensity on a Gray image but don't also set the gamma to precisely 1, then IM will continue to treat the image as nonlinear. But if you set a nonlinear intensity (or remove the intensity) for a Gray image, it will be treated as nonlinear (like sRGB) irrespective of gamma.

While there is no operator that will convert between linear and nonlinear Gray images, an alternative is to use -colorspace RGB or -colorspace sRGB, which will keep the image as a single channel initially (and replicate it into three channels when needed by a further operation), although no longer identified as Gray colorspace. For many output file formats such as JPEG and PNG, the image will (for default settings) automatically be saved as a single-channel grayscale image if all three color channels are equal throughout the image, and if read back into IM this will become Gray colorspace and threfore subject to the behavior documented here for Gray rather than that of sRGB or RGB.

The following intensity methods are mathematical in nature and will use the current value in the image's respective r,g,b channel regardless of its colorspace or whether these channels are linear or nonlinear.

Brightness max(r, g, b )

Lightness (min(r, g, b) + max(r, g, b)) / 2.0

Average (r + g + b) / 3.0

MS (r^2 + g^2 + b^2) / 3.0

RMS sqrt( (r^2 + g^2 + g^2) / 3.0 )

These methods are often used for other purposes, such as generating a grayscale difference image between two color images (using -compose 'Difference' composition.

For example The 'MS' (Mean Squared) setting is good for minimizing color error comparisions. While... The method 'RMS' (Root Mean Squared) for example is appropriate for calculating color vector distance, from a color difference image. This is equivalent to the color only component of the -fuzz factor color compare setting.

See also -grayscale which applies one of the above formulas directly to convert an image to Gray without setting the global default intensity.

To print a complete list of possible pixel intensity setting methods, use -list intensity.

Operators affected by the -intensity setting of a non-Gray image include:

-adaptive-blur
-adaptive-sharpen
-black-threshold
-clut (when mapping grayscale CLUT image to alpha channel if set by -channels)
-colors for gray colorspace
-compose {LightenIntensity, DarkenIntensity, CopyOpacity, CopyBlack}
-contrast-stretch
-distort {ErodeIntensity, DilateIntensity}
-normalize
-random-threshold
-selective-blur
-shade
-threshold
-tint
-white-threshold
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by magick »

Use -intensity Rec709Luminance to return linear grayscale, e.g. convert rose: -intensity Rec709Luminance -colorspace gray image.pgm. Internally grayscale can be linear or non-linear. However, as mentioned, pushing the pixels to an image format is problematic since most formats do not have sufficient metadata to decide if the grayscale is linear or non-linear (excepting MIFF and MPC). That is why the user typically has to track the linearity of the colorspace and declare it when they leverage the command-line utilities, for example, convert rose.jpg -set intensity Rec709Luminance -gamma 1 .... We will take a look at the color management docs and update where needed.
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by Dabrosny »

magick wrote: 2017-09-12T09:58:41-07:00 However, as mentioned, pushing the pixels to an image format is problematic since most formats do not have sufficient metadata to decide if the grayscale is linear or non-linear (excepting MIFF and MPC).
It shouldn't be any more problematic for Gray (*Luma vs *Luminance intensity) than it is for color images (sRGB vs RGB).
magick wrote: 2017-09-12T09:58:41-07:00 That is why the user typically has to track the linearity of the colorspace and declare it when they leverage the command-line utilities
For color images everything already "just works" in IM so long as we accept the default interpretation of JPEG as nonlinear (sRGB), which is what all image viewers and pretty much all other software tools assume.*
In this case there is no need for the user to have to track nonlinearity. (PNG or Tiff shouldn't be a problem anyway since they have gamma to indicate it.)

As in the other bug report, we just want it to work similarly for grayscale as it does for color! Which means when writing to jpeg, anything marked as a linear image (whether by RGB colorspace or a *luminance intensity) should automatically be converted to nonlinear before writing it.

Similarly, just as -colorspace sRGB is safe to do even if it turns out that the image was already sRGB, there should be a way to create a linear and nonlinear grayscale image that doesn't mess anything up if the image just so happens to already be grayscale. (-grayscale rec* on an already-Gray image does not necessarily change the image's intensity attribute to match the data that it transformed to, and -colorspace Gray cannot be used to convert a linear to nonlinear gray or vice-versa)

Having a colorspace (or an intensity in the case of Gray since for some reason IM doesn't have both a linear and nonlinear gray colorspace like LinearGray vs Adobe sGray) literally defines a specification of how the numbers should ultimately be transformed into the physical amount of light (for any given set of display primaries) to be displayed to humans, which means the image should be saved to a given format in the way that will (most likely) be displayed to humans in that way. If one simply wanted to copy numeric values without interpretation then one shouldn't be using a colorspace at all (perhaps -set colorspace Undefined accomplishes this -- I haven't tried).
[/quote]

*(Frankly, anyway, I can't figure out why anyone would intentionally store an image as linear in jpg or any other 8-bit integer format, since doing so produces a large and unnecessary loss of dynamic range and low-end tonal resolution.)
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by magick »

Most image processing algorithms require a linear colorspace for optimal results. Only when an image is displayed to a monitor or printer does it make sense to utilize gamma. So the ideal workflow would be to store your image in a linear colorspace, apply your image processing options, and only on display, convert it to sRGB. If you choose to store your image in sRGB, you are encouraged to first convert to linear RGB such as 'convert image.tif -colorspace RGB -resize 50% -colorspace sRGB show:'. There is a similar caveat for JPEG. JPEG is lossless so its use is only encouraged at the end of your workflow-- that is don't use JPEG as your input image or for any intermediate steps. The same can be said for sRGB.
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: documentation bugs: color-management.php says IM treats all gray images as linear

Post by Dabrosny »

magick wrote: 2017-09-12T11:08:36-07:00 Most image processing algorithms require a linear colorspace for optimal results. Only when an image is displayed to a monitor or printer does it make sense to utilize gamma. So the ideal workflow would be to store your image in a linear colorspace,
Good discussion!
Absolutely, let's store it as linear floating point as IM HDRI does (In fact I wish there were an option to convert it back into linear RGB automatically before or after every operation that might change the colorspace -- i.e. use linear RGB as a persistent working colorspace like Photoshop etc.)

And yes, if you have enough disk storage available to store it losslessly as-is in the same floating point format in a file on disk then of course you should keep it linear because then there is no loss whatsoever when you write and read it back in.

On the other hand, if you want to store it to, say, an 8-bit integer (maybe even 16-bit) encoding in a file on disk, you are going to have tonal quantization loss no matter how you encode it.

But you will have more loss of human-perceptible tonal resolution (at the low end) and dynamic range if you quantize it into 256 linearly-spaced buckets in the 8-bit integer than if you encode it in certain appropriately-nonlinearly-spaced buckets (say using gamma between 2 and 4 which is close to the ideal human Gamma~3 of Luminance in CIELab, or even logarithmically as in LOGLUV Tiff is a good encoding).

A floating-point format has a dynamic range of a couple dozen orders of magnitude (admittedly much more than is needed except for HDRI images) precisely because it is not using a linear encoding -- it actually has an exponential/logarithmic part.
magick wrote: 2017-09-12T11:08:36-07:00 that is don't use JPEG as your input image or for any intermediate steps.
Absolutely.
magick wrote: 2017-09-12T11:08:36-07:00 The same can be said for sRGB.
Again, that fact that a linear colorspace with floating-point dynamic range and precision is a good way to store an image does not mean that a linear integer encoding is a good way to store it at low bit depth. There are a couple of really good articles on this, if I can find them.

If I were using Q8 NON-hdri (8-bit integer storage only) then I'm not so sure linear would be a good idea even during processing -- the benefit of linear operations might be more than outweighed by the loss of perceptible resolution at such a low bit depth.
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
Post Reply