Usage

Most likely you’ll use cdl_convert as a script, instead of a python package itself. Indeed, even the name is formatted more like a script (with an underscore) than the more common all lowercase of python modules.

Script Usage

If you just want to convert to a .cc XML file, the only required argument is an input file, like so:

$ cdl_convert ./di_v001.flex

You can override the default .cc output, or provide multiple outputs with the -o flag.

$ cdl_convert ./di_v001.flex -o cc,cdl

Sometimes it might be necessary to disable cdl_convert’s auto-detection of the input file format. This can be done with the -i flag.

$ cdl_convert ./ca102_x34.cdl -i cdl

Note

You should not normally need to do this, but it is possible especially since there are multiple formats sharing the same file extension. In this case, .cdl could have indicated either a space separated cdl, or an XML cdl. cdl_convert does it’s best to try and guess which one the file is, but if you’re running into trouble, it might help to indicate to cdl_convert what the input file type is.

Full help is available using the standard --help command:

$ cdl_convert --help
usage: cdl_convert [-h] [-i INPUT] [-o OUTPUT] input_file

positional arguments:
  input_file            the file to be converted

optional arguments:
  -h, --help            show this help message and exit
  -i INPUT, --input INPUT
                        specify the filetype to convert from. Use when
                        CDLConvert cannot determine the filetype
                        automatically. Supported input formats are: ['cc',
                        'cdl', 'ale', 'flex']
  -o OUTPUT, --output OUTPUT
                        specify the filetype to convert to, comma separated
                        lists are accepted. Defaults to a .cc XML. Supported
                        output formats are: ['cc', 'cdl']

Python Usage

Once installed with pip, importing cdl_convert works like importing any other python module.

>>> import cdl_convert as cdl

Creating an ColorCorrection

Once imported, you have two choices. You can either instantiate a new, blank cdl directly, or you can parse a file on disk.

Direct Creation

If you want to create a new instance of ColorCorrection, you have to provide an id, for the unique cdl identifier and a source filename to cdl_file.

>>> cc = cdl.ColorCorrection(id='cc1', cdl_file='./myfirstcdl.cc')

Warning

When an instance of ColorCorrection is first created, the id provided is checked against a class level dictionary variable named members to ensure that no two ColorCorrection share the same id , as this is required by the specification.

Warning

It’s not possible to change the file_in attribute once it has been set.

Warning

cdl_file is likely to not be a required attribute in the future.

An ColorCorrection is created with the 10 required values (RGB values for slope, offset and power, and a single float for saturation) set to their defaults.

>>> cc.slope
(1.0, 1.0, 1.0)
>>> cc.offset
(0.0, 0.0, 0.0)
>>> cc.power
(1.0, 1.0, 1.0)
>>> cc.sat
1.0

Note

slope, offset, power and sat are convenience properties that actually reference two child objects of ColorCorrection , a SopNode and a SatNode . Calling them via cc.power is the same as calling cc.sop_node.power.

The ColorCorrection class inherits from both the AscColorSpaceBase class, and the AscDescBase class, giving it the additional attributes of input_desc (to describe the colorspace entering the correction, viewing_desc (to describe the colorspace conversions that must occur for viewing, and what type of monitor was used), and desc (which can be an infinitely long list of shot descriptions, gripes, notes and ramblings).

Parsing a CDL file

Instead of creating a blank CDL object, you can parse a file from disk, and it will return a list of ColorCorrection found in the file. For some formats like cc, this list will be one member long. For others like flex or ale, this list could contain hundreds of cdls.

>>> cdl.parse_cc('./myfirstcdl.cc')
[<cdl_convert.ColorCorrection object at 0x1004a5590>]
>>> cdl.parse_ale('/myfirstedl.ale')
[
    <cdl_convert.ColorCorrection object at 0x100633b90>,
    <cdl_convert.ColorCorrection object at 0x100633c50>,
    <cdl_convert.ColorCorrection object at 0x100633cd0>,
    <cdl_convert.ColorCorrection object at 0x100633b50>,
    <cdl_convert.ColorCorrection object at 0x100633d90>,
    <cdl_convert.ColorCorrection object at 0x100633b10>,
    <cdl_convert.ColorCorrection object at 0x100633ad0>,
]

Once you have an ColorCorrection from a parser, you’ll find that whatever values it found on the file now exist on the instance of ColorCorrection.

>>> cc = cdl.parse_cc('./xf/015.cc')[0]
>>> cc.slope
(1.02401, 1.00804, 0.89562)
>>> cc.offset
(-0.00864, -0.00261, 0.03612)
>>> cc.power
(1.0, 1.0, 1.0)
>>> cc.sat
1.2
>>> cc.id
'015_xf_seqGrade_v01'
>>> cc.file_in
'/Users/sean/cdls/xf/015.cc'

Note

When parsing, the id attribute is set in a variety of ways depending on how much information is available. Some formats, like cc, have an explicitly tagged id field that is always used. Other formats, like flex, have no such field and the parser tries to grab any scene/take metadata it can find to construct one. The last fallback is always the filename. For formats that can export multiple ColorCorrection , the id has a created instance number after it.

Working with ColorCorrection

Slope, Offset and Power

Setting the CDL slope, offset and power (SOP) values is as easy as passing them any list or tuple with three values. Integers and strings will be automatically converted to floats, while slope and power will also truncate at zero.

>>> cc.slope = ('1.234', 5, 273891.37823)
>>> cc.slope
(1.234, 5.0, 273891.37823)
>>> cc.offset = (-0.0013, 0.097, 0.001)
>>> cc.offset
(-0.0013, 0.097, 0.001)
>>> cc.power = (-0.01, 1.0, 1.0)
>>> cc.power
(0.0, 1.0, 1.0)
>>> cc.power = (1.01, 1.007)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cdl_convert/cdl_convert.py", line 336, in power
    raise ValueError("Power must be set with all three RGB values")
ValueError: Power must be set with all three RGB values

It’s also possible to set the SOP values with a single value, and have it copy itself across all three colors. Setting SOP values this way mimics how color corrections typically start out.

>>> cc.slope = 1.2
>>> cc.slope
(1.2, 1.2, 1.2)

Saturation

Saturation is a positive float values, and the same checks and conversions that we do on SOP values happen for saturation as well.

>>> cc.sat = 1.1
>>> cc.sat
1.1
>>> cc.sat = '1.2'
>>> cc.sat
1.2
>>> cc.sat = 1
>>> cc.sat
1.0
>>> cc.sat = -0.1
>>> cc.sat
0.0

Warning

If it’s desired to have negative values raise an exception instead of truncating to zero, set the global module variable HALT_ON_ERROR to be True.

>>> cdl.HALT_ON_ERROR = True
>>> cc.power = (-0.01, 1.0, 1.0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cdl_convert/cdl_convert.py", line 352, in power
    raise ValueError("Power values must not be negative")
ValueError: Power values must not be negative

Description

Certain formats of the cdl will contain multiple description entries. Each description entry is added to the desc attribute, which returns a list of the entries.

>>> cc.desc
['John enters the room', '5.6 ISO 800', 'bad take']

You can append to list by setting the description field like normal.

>>> cc.desc = 'final cc'
>>> cc.desc
['John enters the room', '5.6 ISO 800', 'bad take', 'final cc]

Setting the value to a new list or tuple will replace the list.

>>> cc.desc
['John enters the room', '5.6 ISO 800', 'bad take', 'final cc]
>>> cc.desc = ['first comment', 'second comment']
>>> cc.desc
['first comment', 'second comment']

Id and Files

When creating a ColorCorrection, the id field is checked against a global list of ColorCorrection ids, and creation fails if the id is not unique.

You can change the id after creation, but it will perform the same check.

>>> cc = cdl.ColorCorrection(id='cc1', cdl_file='./myfirstcdl.cc')
>>> cc2 = cdl.ColorCorrection(id='cc2', cdl_file='./mysecondcdl.cc')
>>> cc.id
Out[6]: 'cc1'
>>> cc2.id
Out[7]: 'cc2'
>>> cc2.id = 'cc1'
Traceback (most recent call last):
  File "<ipython-input-8-b2b5487dbc63>", line 1, in <module>
    cc2.id = 'cc1'
  File "cdl_convert/cdl_convert.py", line 362, in id
    self._set_id(value)
  File "cdl_convert/cdl_convert.py", line 430, in _set_id
    cc_id=cc_id
ValueError: Error setting the id to "cc1". This id is already a registered id.

At the current time, filepaths cannot be changed after ColorCorrection instantiation. file_out is determined by using the class method determine_dest, which takes the file_in directory, the id and figures out the output path.

>>> cc.file_in
'/Users/sean/cdls/xf/015.cc'
>>> cc.file_out
>>> cc.determine_dest('cdl')
>>> cc.id
'015_xf_seqGrade_v01'
>>> cc.file_out
'/Users/sean/cdls/xf/015_xf_seqGrade_v01.cdl'

Writing CDLs

When you’re done tinkering with the ColorCorrection instance, you might want to write it out to a file. Currently the output file is written the same directory as the input file. We need to give ColorCorrection the file extension we plan to write to, then call a write function with our ColorCorrection instance, which will actually convert the values on the ColorCorrection into the format desired, then write that format to disk.

>>> cc.determine_dest('cdl')
>>> cc.file_out
'/Users/sean/cdls/xf/015_xf_seqGrade_v01.cdl'
>>> cdl.write_cdl(cc)

Warning

It is highly likely that in the future, these will be methods on the ColorCorrection class itself, and that instead of writing the file directly, they will instead return a string formatted for writing.