HDR, color management, krita, luts and other apps

Boudewijn Rempt boud at valdyas.org
Wed Jun 6 13:31:22 UTC 2012


Here are some notes I prepared today. It's a long read, but please help me 
out by pointing out mistakes and options I've forgotten. I've got a 
feeling we might have to refactor our display code quite a bit to make 
this work correctly, and fast -- especially because in git master there's quite a
bit of brokenness.

Contents:

* color management in Nuke
* color management in Mari
* color management in Krita
** Master
** Lut branch
** With Ocio

The goal is to make Krita function correctly again with all HDR colorspaces and make opengl and
qpainter canvas support the following for HDR colorspaces:

* exposure
* gamma
* lut selection
* painting
* color selection (didn't check how this is done in Nuke and Mari yet, 
probably not in the same way as in Krita, where you use the ordinary 
colors selectors to select a 8bit  int rgba that gets converted using the 
exposure settng).

-----------------------------------------
* Color Management in Nuke

"The gain and gamma sliders let you adjust the displayed image, without
affecting your final output. These controls are useful for tasks like 
spotting
holes in mattes."

"Press the Zebra Stripe button to apply stripes to all pixels outside the 
range
0.0 to 1.0."

"Input Process and Viewer Process operations can be used to modify the
image from the viewed node before it is displayed on your monitor."

Note: the getting started says Input Process is deprecated.

"There are two predefined Viewer Processes, sRGB and rec709,"

" Viewer Process are executed on the GPU. 1D LUT and 3D LUT (Vectorfield) 
have GPU implementations, so the built-in Viewer Processes will run on the 
GPU (unless gl buffer depth has been set to byte in the Viewer settings, 
in which case all processing is done on the CPU). "

"Nuke includes the following predefined Viewer Process gizmos: sRGB and
rec709. By default, sRGB is used because it is a best-guess default for a
typical computer monitor."

*Conclusion*: Nuke is pretty simple-minded. It doesn't care that the 
monitor might be calibrated or not, it just allows users to select 
"profiles" that change the look, without any care for whether the same 
project would look the same with a different monitor.

------------------------------------------------------------------------------

* Color Management in Mari

Mari has both a dialog and a color magement toolbar. The color management 
toolbar seems identical with the list of features in the ocio manual, down 
to showing only luminance or individual rgb components.

The toolbar has the following items:

Set how colors are displayed using the ColorSpace toolbar:
1. Toggle to enable Enable Color Management in the Color Manager
2. Select a custom OpenColorIO (.ocio) configuration file by clicking
3. Select the colorspace of the current scene using Input ColorSpace
dropdown.
4. Set the display device used to view the scene using the Display Device
dropdown menu.
5. Select the colorspace transform to apply to the scene from the View
Transform dropdown menu.
6. Use the Component dropdown menu to see the individual color
components in the scene.
7. Use the Gain controls to set the amount of exposure adjustment applied
before the display transform by either entering a multiplier (exposure
value), dragging on the slider, or adjusting the F-Stop value.
8. Finally, set the amount of Gamma correction applied after the display
transform by entering a gamma level or by dragging the gamma slider.

There are also some things called "display filters" That sounds like it is 
a way to do color correction similar to GIMP -- but I might be confused 
about the way they mean "color correction" in the Mari manual.

The mari color management toolbar is included in the ocio distribution, so 
it's pretty easy to study.

Conclusion: we can implement, probably, the entire set of Mari 
functionality in the Lut docker with some changes to our canvas code. 
Enabling OCIO would then _disable_ what I think of as "real" color 
management.

------------------------------------------------------------------------------

* Color Management in Krita

Krita currently follows a traditional icc-based colormanagement model. It 
uses lcms2 and ctlcs. Krita used to support lcms1 and a kubelka-munk 
(spectral) color engine. Krita can convert pixels between all the color 
engines it supports. Krita doesn't have an ocio-based color engine yet.

Quick glossary:

Colormodel : pixel arrangement (rgb, bgr, yuv etc, so many bytes per 
component)
Profile    : icc, ctlcs or other profile that describes what the pixel
              values mean and thus allows conversion
Colorspace : combination of model and profile
Engine     : a plugin that provides colorspace and profile 
implementations.

  + Krita doesn't support spot channels (yet)
  + Every layer has a working colorspace. Layers in an image can all have 
different colorspaces.
  + The image has a working colorspace: on composition, all layers are 
converted to the working colorspace and combined together
  + The monitor has a profile: this describes the way the monitor deviates 
from other monitors and is necessary to make sure the same image looks the 
same on two systems.
  + a colorspace can be marked to support HDR
  + we want to be able to have a natural-feeling color selection method for 
HDR colorspaces

** In Master

  + ctlcs colorspaces are not marked as HDR: here exposure is applied 
during image recomposition by embedding the exposure information in the 
profile.
  + the new lcms float colorspaces are marked as HDR, but the exposure 
shader is broken.
  + ctlcs colorspaces show exposure even in the qpainter canvas (because 
exposure is applied during composition)
  + painting on ctlcs float colorspaces works through converting the 
selected fg/bg color to float using exposure embedded in the ctlcs 
profile.

** In the lut-docker branch

** Display

+ exposure and gamma are stored in KisCanvasResourceProvider

*** OpenGL

In the lut branch (master is broken for opengl as far as HDR is concerned, 
it is not used at all):

if (image colorspace is integer):
   1. convert the image to 8 or 16 bit integer rgba textures using the 
monitor profile. Currently broken.
   2. show the textures

elif (float):
   1. convert the image to 16 or 32 bit float rgba textures. This doesn't 
use the monitor profile (since that often isn't compatible with float), 
but the default profile given by the image colorspace. I.e., no real 
conversion.
   2. apply the exposure/gamma shader to the textures
   3. show the textures

*** QPainter
  1. convert the image to 8 bit integer using the monitor profile
  2. scale the image
  3. display the image


** OCIO

  + Ocio has ocio2icc so, command line tool to generate an ICC “proofing” 
profile from a color space transform, which can be used in applications 
such as Photoshop. We don't use proofing transforms in Krita, do we?

  + Ocio can be used in the display part of Krita, it can generate 
corrected textures or pixels. We could use Ocio in the lut-docker and if 
enabled make it replace the final step of conversion from the projection 
to the display, or we could make it a step in between.

  + ocio can use the cpu or gpu to perform its transformations.

This situation would make Krita function optionally like Mari for all 
practical purposes.

** Possible Refactoring of Krita's display architecture

  * create the ocio-based lut docker, which is only active for float images
  * the lut docker allows the user to select any of the configured luts; 
this transformation will be applied on the projection. Then another 
transformation should be applied to correct the result for the monitor 
idiosyncracies.
  * create a step in both canvases where the image is filtered using ocio.

** OpenGL

   This depends a lot on where we'll go with the opengl2 canvas. But ocio 
can proably replace our home-grown exposure shader.

   We want to:

     * make it faster
     * support high channel depth monitors and cards
     * apply the monitor profile

   if (ocio and float):
     1. make ocio generate textures from the image with all settings
     2. how the deuce do we apply the monitor calibration profile? I don't 
know yet... (DisplayTransform?)
   elif (not ocio):
     1. convert image to the right texture format for the monitor 
capabilities using lcms
     2. upload the textures
     3. show the textures


** QPainter

   if (not ocio):
     1. convert the image to 8 bit integer using the monitor profile
     2. scale the image
     3. display the image
   elif (ocio):
     if (float):
       1. convert image pixels using lcms to a known good space for ocio, 
if necessary.
       2. convert image pixels using ocio (exposure, gamma, other ocio 
tricks) to      8 bit rRGB rgba. Use the ocio cpu path.
       2a. make sure the ocio configuration is available as icc so we can 
create
       a correct Krita lmcs2-based colorspace
       3. convert converted pixels using lcms2 and the monitor profile to 
image
       4. pre-scale image
       5. show image


NOTES:

* rendering intent and blackpoint are now disregarded when converting to 
the monitor colorspace. https://bugs.kde.org/show_bug.cgi?id=301235.


More information about the kimageshop mailing list