converting The Right Way™ from linear -> custom log -> monitor

Jeremy Selan <jeremy...@...>


So you shouldnt have to muck around with any of the specific underlying Transforms (you mention the log transform, and the file transform).  The typical use case with OCIO is that these are all abstracted away inside the OCIO configuration, and that clients of the library treat the color transformation stack as a 'black box'.  (The reason we expose these *.Transforms at all in python is that so it's possible to script the creation of Configs using the python API.)

I.e., if you wanted to convert pixels from colorspace "A" to colorspace "B"...

config.getProcessor("A","B") would suffice.  (either the names, or roles)

The client would *not* need to know whether the definitions of A and B involved 1-D LUTs, 3-D LUTs, log converts, etc.

So can you confirm your facility already has a show-level OCIO config with the colorspace definitions already setup?  (If you're using Katana or Nuke or Mari with OCIO functionality, it's likely you already have one setup).  Also note that I see you're calling  OCIO.GetCurrentConfig().  That reads from $OCIO, so if you're not seeing a warning in the shell then you're probably good to go.

The one exception where you DO need to use a Transform in a client app is the DisplayTransform, which is the simplest way to create a "canonical viewing transform".

So say you wanted to convert colors, from log space, to something suitable for image display.   As this is for image display, the DisplayTransform is most appropriate:

config = OCIO.GetCurrentConfig()

t = OCIO.DisplayTransform()
t.setDisplay( config.getDefaultDisplay() )
t.setView( config.getDefaultView( config.getDefaultDisplay() ) )

And then you get the processor,
processor = config.getProcessor(t)

And then you use the processor to process pixels.

For extra credit... Note that if you're drawing a gradient and having the user pick colors, a log space gradient - while much better than scene-linear - may not be ideal.  I.e., you may find that the distribution of colors along the gradient is not to your liking.    One of the OCIO pre-defined roles is ROLE_COLOR_PICKER.  The intent is that this would be the alias to the color space most suitable for use in a color-picker.  (The Katana color picker makes use of this role, for example).  And the default OCIO configs we publish have this defined in a manner suitable for color picking.

Let me know if you have any further questions along these lines. This color picker stuff is both complicated, and fun. :)

-- Jeremy

On Mon, Mar 18, 2013 at 8:12 AM, <sor...@...> wrote:

I'm writing a fairly simple Python based color-managed color picker. OCIO seems like a good tool for the job, and it's an opportunity for me to learn a new API. Beyond hacking something together that "just works" I'd like to understand The Correct Way To Do Things According To The OCIO Python API. At the moment I'm not sure how my problem fits into the OCIO abstraction of roles, Displays, ColorSpaces, Transforms, Processors, Looks, Views, and Configs.

Our studio maintains monitor-specific Truelight Cube v2.0 files, which OCIO seems capable of reading. But we use these TrueLight files to map colors in log space into the final display color space. And each show's definition of "log space" depends on show-specific variables such as these, for use in a Josh Pines lin-to-log transform:

# log reference
LOGLIN_LOGREF:                   445 445 445
# linear reference
LOGLIN_LINREF:                   0.18 0.18 0.18
# negative gamma
LOGLIN_NGAMMA:                   0.6 0.6 0.6
# black level
LOGLIN_BLACKLEVEL:               0.0 0.0 0.0
# negative density per 10 bit log code value
LOGLIN_DENSPERCV:                0.002 0.002 0.002

The following code runs, but it's not producing correct output because 'color_in' hasn't been converted from scene linear to log. Where do I add that conversion? I suppose that would be another Processor, generated from a Transform between Constants.ROLE_SCENE_LINEAR and the show-specific log colorspace, but is it possible to create a log color space defined in this way? I could kludge together some math that produces the correct result, but it feels like I'm cheating.

import PyOpenColorIO as OCIO
ocio_config = OCIO.GetCurrentConfig()
ft = OCIO.FileTransform(path,
log_to_display = self.ocio_config.getProcessor(ft)
# oops - color_in is not log!
color_out = log_to_display.applyRGB(color_in)