Minor. Removed commented out code.
[OpenColorIO-Configs.git] / aces_1.0.0 / python / create_aces_config.py
index 88701f0..5e6793c 100755 (executable)
@@ -49,6 +49,13 @@ import OpenImageIO as oiio
 import PyOpenColorIO as OCIO
 
 import process
+from util import *
+
+import generateLUT as genlut
+import createREDColorSpaces as red
+import createCanonColorSpaces as canon
+import createSonyColorSpaces as sony
+import createARRIColorSpaces as arri
 
 #
 # Utility functions
@@ -74,8 +81,6 @@ def setConfigDefaultRoles( config,
     if reference: config.setRole( OCIO.Constants.ROLE_REFERENCE, reference )
     if scene_linear: config.setRole( OCIO.Constants.ROLE_SCENE_LINEAR, scene_linear )
     if texture_paint: config.setRole( OCIO.Constants.ROLE_TEXTURE_PAINT, texture_paint )
-    
-    
 
 # Write config to disk
 def writeConfig( config, configPath, sanityCheck=True ):
@@ -92,254 +97,6 @@ def writeConfig( config, configPath, sanityCheck=True ):
     fileHandle.write( config.serialize() )
     fileHandle.close()
 
-#
-# Functions used to generate LUTs using CTL transforms
-#
-def generate1dLUTImage(ramp1dPath, resolution=1024, minValue=0.0, maxValue=1.0):
-    #print( "Generate 1d LUT image - %s" % ramp1dPath)
-
-    # open image
-    format = os.path.splitext(ramp1dPath)[1]
-    ramp = oiio.ImageOutput.create(ramp1dPath)
-
-    # set image specs
-    spec = oiio.ImageSpec()
-    spec.set_format( oiio.FLOAT )
-    #spec.format.basetype = oiio.FLOAT
-    spec.width = resolution
-    spec.height = 1
-    spec.nchannels = 3
-
-    ramp.open (ramp1dPath, spec, oiio.Create)
-
-    data = array.array("f", "\0" * spec.width * spec.height * spec.nchannels * 4)
-    for i in range(resolution):
-        value = float(i)/(resolution-1) * (maxValue - minValue) + minValue
-        data[i*spec.nchannels +0] = value
-        data[i*spec.nchannels +1] = value
-        data[i*spec.nchannels +2] = value
-
-    ramp.write_image(spec.format, data)
-    ramp.close()
-
-# Credit to Alex Fry for the original single channel version of the spi1d writer
-def WriteSPI1D(filename, fromMin, fromMax, data, entries, channels):
-    f = file(filename,'w')
-    f.write("Version 1\n")
-    f.write("From %f %f\n" % (fromMin, fromMax))
-    f.write("Length %d\n" % entries)
-    f.write("Components %d\n" % (min(3, channels)) )
-    f.write("{\n")
-    for i in range(0, entries):
-        entry = ""
-        for j in range(0, min(3, channels)):
-            entry = "%s %s" % (entry, data[i*channels + j])
-        f.write("        %s\n" % entry)
-    f.write("}\n")
-    f.close()
-
-def generate1dLUTFromImage(ramp1dPath, outputPath=None, minValue=0.0, maxValue=1.0):
-    if outputPath == None:
-        outputPath = ramp1dPath + ".spi1d"
-
-    # open image
-    ramp = oiio.ImageInput.open( ramp1dPath )
-
-    # get image specs
-    spec = ramp.spec()
-    type = spec.format.basetype
-    width = spec.width
-    height = spec.height
-    channels = spec.nchannels
-
-    # get data
-    # Force data to be read as float. The Python API doesn't handle half-floats well yet.
-    type = oiio.FLOAT
-    data = ramp.read_image(type)
-
-    WriteSPI1D(outputPath, minValue, maxValue, data, width, channels)
-
-def generate3dLUTImage(ramp3dPath, resolution=32):
-    args = ["--generate", "--cubesize", str(resolution), "--maxwidth", str(resolution*resolution), "--output", ramp3dPath]
-    lutExtract = process.Process(description="generate a 3d LUT image", cmd="ociolutimage", args=args)
-    lutExtract.execute()    
-
-def generate3dLUTFromImage(ramp3dPath, outputPath=None, resolution=32):
-    if outputPath == None:
-        outputPath = ramp3dPath + ".spi3d"
-
-    args = ["--extract", "--cubesize", str(resolution), "--maxwidth", str(resolution*resolution), "--input", ramp3dPath, "--output", outputPath]
-    lutExtract = process.Process(description="extract a 3d LUT", cmd="ociolutimage", args=args)
-    lutExtract.execute()    
-
-def applyCTLToImage(inputImage, 
-    outputImage, 
-    ctlPaths=[], 
-    inputScale=1.0, 
-    outputScale=1.0, 
-    globalParams={},
-    acesCTLReleaseDir=None):
-    if len(ctlPaths) > 0:
-        ctlenv = os.environ
-        if acesCTLReleaseDir != None:
-            ctlModulePath = "%s/utilities" % acesCTLReleaseDir
-            ctlenv['CTL_MODULE_PATH'] = ctlModulePath
-
-        args = []
-        for ctl in ctlPaths:
-            args += ['-ctl', ctl]
-        args += ["-force"]
-        #args += ["-verbose"]
-        args += ["-input_scale", str(inputScale)]
-        args += ["-output_scale", str(outputScale)]
-        args += ["-global_param1", "aIn", "1.0"]
-        for key, value in globalParams.iteritems():
-            args += ["-global_param1", key, str(value)]
-        args += [inputImage]
-        args += [outputImage]
-
-        #print( "args : %s" % args )
-
-        ctlp = process.Process(description="a ctlrender process", cmd="ctlrender", args=args, env=ctlenv )
-
-        ctlp.execute()
-
-def convertBitDepth(inputImage, outputImage, depth):
-    args = [inputImage, "-d", depth, "-o", outputImage]
-    convert = process.Process(description="convert image bit depth", cmd="oiiotool", args=args)
-    convert.execute()    
-
-def generate1dLUTFromCTL(lutPath, 
-    ctlPaths, 
-    lutResolution=1024, 
-    identityLutBitDepth='half', 
-    inputScale=1.0, 
-    outputScale=1.0,
-    globalParams={},
-    cleanup=True,
-    acesCTLReleaseDir=None,
-    minValue=0.0,
-    maxValue=1.0):
-    #print( lutPath )
-    #print( ctlPaths )
-
-    lutPathBase = os.path.splitext(lutPath)[0]
-
-    identityLUTImageFloat = lutPathBase + ".float.tiff"
-    generate1dLUTImage(identityLUTImageFloat, lutResolution, minValue, maxValue)
-
-    if identityLutBitDepth != 'half':
-        identityLUTImage = lutPathBase + ".uint16.tiff"
-        convertBitDepth(identityLUTImageFloat, identityLUTImage, identityLutBitDepth)
-    else:
-        identityLUTImage = identityLUTImageFloat
-
-    transformedLUTImage = lutPathBase + ".transformed.exr"
-    applyCTLToImage(identityLUTImage, transformedLUTImage, ctlPaths, inputScale, outputScale, globalParams, acesCTLReleaseDir)
-
-    generate1dLUTFromImage(transformedLUTImage, lutPath, minValue, maxValue)
-
-    if cleanup:
-        os.remove(identityLUTImage)
-        if identityLUTImage != identityLUTImageFloat:
-            os.remove(identityLUTImageFloat)
-        os.remove(transformedLUTImage)
-
-def correctLUTImage(transformedLUTImage, correctedLUTImage, lutResolution):
-    # open image
-    transformed = oiio.ImageInput.open( transformedLUTImage )
-
-    # get image specs
-    transformedSpec = transformed.spec()
-    type = transformedSpec.format.basetype
-    width = transformedSpec.width
-    height = transformedSpec.height
-    channels = transformedSpec.nchannels
-
-    # rotate or not
-    if width != lutResolution * lutResolution or height != lutResolution:
-        print( "Correcting image as resolution is off. Found %d x %d. Expected %d x %d" % (width, height, lutResolution * lutResolution, lutResolution) )
-        print( "Generating %s" % correctedLUTImage)
-
-        #
-        # We're going to generate a new correct image
-        #
-
-        # Get the source data
-        # Force data to be read as float. The Python API doesn't handle half-floats well yet.
-        type = oiio.FLOAT
-        sourceData = transformed.read_image(type)
-
-        format = os.path.splitext(correctedLUTImage)[1]
-        correct = oiio.ImageOutput.create(correctedLUTImage)
-
-        # set image specs
-        correctSpec = oiio.ImageSpec()
-        correctSpec.set_format( oiio.FLOAT )
-        correctSpec.width = height
-        correctSpec.height = width
-        correctSpec.nchannels = channels
-
-        correct.open (correctedLUTImage, correctSpec, oiio.Create)
-
-        destData = array.array("f", "\0" * correctSpec.width * correctSpec.height * correctSpec.nchannels * 4)
-        for j in range(0, correctSpec.height):
-            for i in range(0, correctSpec.width):
-                for c in range(0, correctSpec.nchannels):
-                    #print( i, j, c )
-                    destData[correctSpec.nchannels*correctSpec.width*j + correctSpec.nchannels*i + c] = sourceData[correctSpec.nchannels*correctSpec.width*j + correctSpec.nchannels*i + c]
-
-        correct.write_image(correctSpec.format, destData)
-        correct.close()
-    else:
-        #shutil.copy(transformedLUTImage, correctedLUTImage)
-        correctedLUTImage = transformedLUTImage
-
-    transformed.close()
-
-    return correctedLUTImage
-
-def generate3dLUTFromCTL(lutPath, 
-    ctlPaths, 
-    lutResolution=64, 
-    identityLutBitDepth='half', 
-    inputScale=1.0,
-    outputScale=1.0, 
-    globalParams={},
-    cleanup=True,
-    acesCTLReleaseDir=None):
-    #print( lutPath )
-    #print( ctlPaths )
-
-    lutPathBase = os.path.splitext(lutPath)[0]
-
-    identityLUTImageFloat = lutPathBase + ".float.tiff"
-    generate3dLUTImage(identityLUTImageFloat, lutResolution)
-
-
-    if identityLutBitDepth != 'half':
-        identityLUTImage = lutPathBase + "." + identityLutBitDepth + ".tiff"
-        convertBitDepth(identityLUTImageFloat, identityLUTImage, identityLutBitDepth)
-    else:
-        identityLUTImage = identityLUTImageFloat
-
-    transformedLUTImage = lutPathBase + ".transformed.exr"
-    applyCTLToImage(identityLUTImage, transformedLUTImage, ctlPaths, inputScale, outputScale, globalParams, acesCTLReleaseDir)
-
-    correctedLUTImage = lutPathBase + ".correct.exr"
-    correctedLUTImage = correctLUTImage(transformedLUTImage, correctedLUTImage, lutResolution)    
-
-    generate3dLUTFromImage(correctedLUTImage, lutPath, lutResolution)
-
-    if cleanup:
-        os.remove(identityLUTImage)
-        if identityLUTImage != identityLUTImageFloat:
-            os.remove(identityLUTImageFloat)
-        os.remove(transformedLUTImage)
-        if correctedLUTImage != transformedLUTImage:
-            os.remove(correctedLUTImage)
-        #os.remove(correctedLUTImage)
-
 def generateOCIOTransform(transforms):
     #print( "Generating transforms")
 
@@ -432,9 +189,6 @@ def createConfig(configData, nuke=False):
     #
     # Create the rest of the color spaces
     #
-    #sortedColorspaces = sorted(configData['colorSpaces'], key=lambda x: x.name)
-    #print( sortedColorspaces )
-    #for colorspace in sortedColorspaces:
     for colorspace in sorted(configData['colorSpaces']):
         print( "Creating new color space : %s" % colorspace.name)
 
@@ -523,39 +277,6 @@ def createConfig(configData, nuke=False):
 #
 # Functions to generate color space definitions and LUTs for transforms for a specific ACES release
 #
-class ColorSpace:
-    "A container for data needed to define an OCIO 'Color Space' "
-
-    def __init__(self, 
-        name, 
-        description=None, 
-        bitDepth=OCIO.Constants.BIT_DEPTH_F32,
-        equalityGroup=None,
-        family=None,
-        isData=False,
-        toReferenceTransforms=[],
-        fromReferenceTransforms=[],
-        allocationType=OCIO.Constants.ALLOCATION_UNIFORM,
-        allocationVars=[0.0, 1.0]):
-        "Initialize the standard class variables"
-        self.name = name
-        self.bitDepth=bitDepth
-        self.description = description
-        self.equalityGroup=equalityGroup
-        self.family=family 
-        self.isData=isData
-        self.toReferenceTransforms=toReferenceTransforms
-        self.fromReferenceTransforms=fromReferenceTransforms
-        self.allocationType=allocationType
-        self.allocationVars=allocationVars
-
-# Create a 4x4 matrix (list) based on a 3x3 matrix (list) input
-def mat44FromMat33(mat33):
-    return [mat33[0], mat33[1], mat33[2], 0.0, 
-            mat33[3], mat33[4], mat33[5], 0.0, 
-            mat33[6], mat33[7], mat33[8], 0.0, 
-            0,0,0,1.0]
-
 
 # Output is a list of colorspaces and transforms that convert between those
 # colorspaces and reference color space, ACES
@@ -614,7 +335,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             '%s/ACEScg/ACEScsc.ACES_to_ACEScg.a1.0.0.ctl' % acesCTLReleaseDir
         ]
         lut = "%s_to_ACES.spi1d" % name
-        generate1dLUTFromCTL( lutDir + "/" + lut, 
+        genlut.generate1dLUTFromCTL( lutDir + "/" + lut, 
             ctls, 
             lutResolution1d, 
             'float', 
@@ -665,7 +386,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             '%s/ACEScg/ACEScsc.ACES_to_ACEScg.a1.0.0.ctl' % acesCTLReleaseDir
         ]
         lut = "%s_to_aces.spi1d" % name
-        generate1dLUTFromCTL( lutDir + "/" + lut, 
+        genlut.generate1dLUTFromCTL( lutDir + "/" + lut, 
             ctls, 
             lutResolution1d, 
             'uint16', 
@@ -818,7 +539,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
                 data.append(cid_to_rle(x))
 
             lut = 'ADX_CID_to_RLE.spi1d'
-            WriteSPI1D(lutDir + "/" + lut, RANGE[0], RANGE[1], data, NUM_SAMPLES, 1)
+            genlut.writeSPI1D(lutDir + "/" + lut, RANGE[0], RANGE[1], data, NUM_SAMPLES, 1)
 
             return lut
 
@@ -857,588 +578,29 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
     ADX16 = createADX(bitdepth=16)
     configData['colorSpaces'].append(ADX16)
 
-
     #
-    # REDlogFilm to ACES
+    # Camera Input Transforms
     #
-    def createREDlogFilm(gamut, transferFunction, name='REDlogFilm'):
-        name = "%s - %s" % (transferFunction, gamut)
-        if transferFunction == "":
-            name = "Linear - %s" % gamut
-        if gamut == "":
-            name = "%s" % transferFunction
-
-        cs = ColorSpace(name)
-        cs.description = name
-        cs.equalityGroup = ''
-        cs.family = 'RED'
-        cs.isData=False
-
-        def cineonToLinear(codeValue):
-            nGamma = 0.6
-            blackPoint = 95.0
-            whitePoint = 685.0
-            codeValueToDensity = 0.002
-
-            blackLinear = pow(10.0, (blackPoint - whitePoint) * (codeValueToDensity / nGamma))
-            codeLinear = pow(10.0, (codeValue - whitePoint) * (codeValueToDensity / nGamma))
-
-            return (codeLinear - blackLinear)/(1.0 - blackLinear)
-
-        cs.toReferenceTransforms = []
-
-        if transferFunction == 'REDlogFilm':
-            data = array.array('f', "\0" * lutResolution1d * 4)
-            for c in range(lutResolution1d):
-                data[c] = cineonToLinear(1023.0*c/(lutResolution1d-1))
-
-            lut = "CineonLog_to_linear.spi1d"
-            WriteSPI1D(lutDir + "/" + lut, 0.0, 1.0, data, lutResolution1d, 1)
-
-            cs.toReferenceTransforms.append( {
-                'type':'lutFile', 
-                'path':lut, 
-                'interpolation':'linear', 
-                'direction':'forward'
-            } )
-
-        if gamut == 'DRAGONcolor':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.532279,  0.376648,  0.091073, 
-                                         0.046344,  0.974513, -0.020860, 
-                                        -0.053976, -0.000320, 1.054267]),
-                'direction':'forward'
-            })
-        elif gamut == 'DRAGONcolor2':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.468452,  0.331484,  0.200064, 
-                                         0.040787,  0.857658,  0.101553, 
-                                        -0.047504, -0.000282, 1.047756]),
-                'direction':'forward'
-            })
-        elif gamut == 'REDcolor2':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.480997, 0.402289, 0.116714, 
-                                        -0.004938, 1.000154, 0.004781, 
-                                        -0.105257, 0.025320, 1.079907]),
-                'direction':'forward'
-            })
-        elif gamut == 'REDcolor3':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.512136, 0.360370, 0.127494, 
-                                         0.070377, 0.903884, 0.025737, 
-                                        -0.020824, 0.017671, 1.003123]),
-                'direction':'forward'
-            })
-        elif gamut == 'REDcolor4':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.474202, 0.333677, 0.192121, 
-                                         0.065164, 0.836932, 0.097901, 
-                                        -0.019281, 0.016362, 1.002889]),
-                'direction':'forward'
-            })
-
-        cs.fromReferenceTransforms = []
-        return cs
-
-    # Full conversion
-    REDlogFilmDRAGON = createREDlogFilm("DRAGONcolor", "REDlogFilm", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmDRAGON)
-
-    REDlogFilmDRAGON2 = createREDlogFilm("DRAGONcolor2", "REDlogFilm", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmDRAGON2)
-
-    REDlogFilmREDcolor2 = createREDlogFilm("REDcolor2", "REDlogFilm", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmREDcolor2)
-
-    REDlogFilmREDcolor3 = createREDlogFilm("REDcolor3", "REDlogFilm", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmREDcolor3)
 
-    REDlogFilmREDcolor4 = createREDlogFilm("REDcolor4", "REDlogFilm", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmREDcolor4)
-
-    # Linearization only
-    REDlogFilmDRAGON = createREDlogFilm("", "REDlogFilm", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmDRAGON)
-
-    # Primaries only
-    REDlogFilmDRAGON = createREDlogFilm("DRAGONcolor", "", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmDRAGON)
-
-    REDlogFilmDRAGON2 = createREDlogFilm("DRAGONcolor2", "", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmDRAGON2)
-
-    REDlogFilmREDcolor2 = createREDlogFilm("REDcolor2", "", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmREDcolor2)
-
-    REDlogFilmREDcolor3 = createREDlogFilm("REDcolor3", "", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmREDcolor3)
-
-    REDlogFilmREDcolor4 = createREDlogFilm("REDcolor4", "", name="REDlogFilm")
-    configData['colorSpaces'].append(REDlogFilmREDcolor4)
+    # RED color spaces to ACES
+    redColorSpaces = red.createColorSpaces(lutDir, lutResolution1d)
+    for cs in redColorSpaces:
+        configData['colorSpaces'].append(cs)
 
-    #
     # Canon-Log to ACES
-    #
-    def createCanonLog(gamut, transferFunction, name='Canon-Log'):
-        name = "%s - %s" % (transferFunction, gamut)
-        if transferFunction == "":
-            name = "Linear - %s" % gamut
-        if gamut == "":
-            name = "%s" % transferFunction
-
-        cs = ColorSpace(name)
-        cs.description = name
-        cs.equalityGroup = ''
-        cs.family = 'Canon'
-        cs.isData=False
-
-        def legalToFull(codeValue):
-            return (codeValue - 64.0)/(940.0 - 64.0)
-
-        def canonLogToLinear(codeValue):
-            # log = fullToLegal(c1 * log10(c2*linear + 1) + c3)
-            # linear = (pow(10, (legalToFul(log) - c3)/c1) - 1)/c2
-            c1 = 0.529136
-            c2 = 10.1596
-            c3 = 0.0730597
-
-            linear = (pow(10.0, (legalToFull(codeValue) - c3)/c1) -1.0)/c2
-            linear = 0.9 * linear
-            #print( codeValue, linear )
-            return linear
-
-        cs.toReferenceTransforms = []
-
-        if transferFunction == "Canon-Log":
-            data = array.array('f', "\0" * lutResolution1d * 4)
-            for c in range(lutResolution1d):
-                data[c] = canonLogToLinear(1023.0*c/(lutResolution1d-1))
-
-            lut = "%s_to_linear.spi1d" % transferFunction
-            WriteSPI1D(lutDir + "/" + lut, 0.0, 1.0, data, lutResolution1d, 1)
-
-            cs.toReferenceTransforms.append( {
-                'type':'lutFile', 
-                'path':lut, 
-                'interpolation':'linear', 
-                'direction':'forward'
-            } )
-
-        if gamut == 'Rec. 709 Daylight':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':[0.561538969, 0.402060105, 0.036400926, 0.0, 
-                            0.092739623, 0.924121198, -0.016860821, 0.0, 
-                            0.084812961, 0.006373835, 0.908813204, 0.0, 
-                            0,0,0,1.0],
-                'direction':'forward'
-            })
-        elif gamut == 'Rec. 709 Tungsten':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':[0.566996399, 0.365079418, 0.067924183, 0.0, 
-                            0.070901044, 0.880331008, 0.048767948, 0.0, 
-                            0.073013542, -0.066540862, 0.99352732, 0.0, 
-                            0,0,0,1.0],
-                'direction':'forward'
-            })
-        elif gamut == 'DCI-P3 Daylight':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':[0.607160575, 0.299507286, 0.093332140, 0.0, 
-                            0.004968120, 1.050982224, -0.055950343, 0.0, 
-                            -0.007839939, 0.000809127, 1.007030813, 0.0, 
-                            0,0,0,1.0],
-                'direction':'forward'
-            })
-        elif gamut == 'DCI-P3 Tungsten':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':[0.650279125, 0.253880169, 0.095840706, 0.0, 
-                            -0.026137986, 1.017900530, 0.008237456, 0.0, 
-                            0.007757558, -0.063081669, 1.055324110, 0.0, 
-                            0,0,0,1.0],
-                'direction':'forward'
-            })
-        elif gamut == 'Cinema Gamut Daylight':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':[0.763064455, 0.149021161, 0.087914384, 0.0, 
-                            0.003657457, 1.10696038, -0.110617837, 0.0, 
-                            -0.009407794,-0.218383305, 1.227791099, 0.0, 
-                            0,0,0,1.0],
-                'direction':'forward'
-            })
-        elif gamut == 'Cinema Gamut Tungsten':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':[0.817416293, 0.090755698, 0.091828009, 0.0, 
-                            -0.035361374, 1.065690585, -0.030329211, 0.0, 
-                            0.010390366, -0.299271107, 1.288880741, 0.0, 
-                            0,0,0,1.0],
-                'direction':'forward'
-            })
-
-        cs.fromReferenceTransforms = []
-        return cs
-
-    # Full conversion
-    CanonLog1 = createCanonLog("Rec. 709 Daylight", "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog1)
-
-    CanonLog2 = createCanonLog("Rec. 709 Tungsten", "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog2)
-
-    CanonLog3 = createCanonLog("DCI-P3 Daylight", "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog3)
-
-    CanonLog4 = createCanonLog("DCI-P3 Tungsten", "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog4)
-
-    CanonLog5 = createCanonLog("Cinema Gamut Daylight", "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog5)
-
-    CanonLog6 = createCanonLog("Cinema Gamut Tungsten", "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog6)
-
-    # Linearization only
-    CanonLog7 = createCanonLog('', "Canon-Log", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog7)
-
-    # Primaries only
-    CanonLog8 = createCanonLog("Rec. 709 Daylight", "", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog8)
-
-    CanonLog9 = createCanonLog("Rec. 709 Tungsten", "", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog9)
-
-    CanonLog10 = createCanonLog("DCI-P3 Daylight", "", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog10)
-
-    CanonLog11 = createCanonLog("DCI-P3 Tungsten", "", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog11)
-
-    CanonLog12 = createCanonLog("Cinema Gamut Daylight", "", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog12)
-
-    CanonLog13 = createCanonLog("Cinema Gamut Tungsten", "", name="Canon-Log")
-    configData['colorSpaces'].append(CanonLog13)
+    canonColorSpaces = canon.createColorSpaces(lutDir, lutResolution1d)
+    for cs in canonColorSpaces:
+        configData['colorSpaces'].append(cs)
 
-    #
     # SLog to ACES
-    #
-    def createSlog(gamut, transferFunction, name='S-Log3'):
-        name = "%s - %s" % (transferFunction, gamut)
-        if transferFunction == "":
-            name = "Linear - %s" % gamut
-        if gamut == "":
-            name = "%s" % transferFunction
-
-        cs = ColorSpace(name)
-        cs.description = name
-        cs.equalityGroup = ''
-        cs.family = 'Sony'
-        cs.isData=False
-
-        def sLog1ToLinear(SLog):
-            b = 64.
-            ab = 90.
-            w = 940.
-
-            if (SLog >= ab):
-                lin = ( pow(10., ( ( ( SLog - b) / ( w - b) - 0.616596 - 0.03) / 0.432699)) - 0.037584) * 0.9
-            else:
-                lin = ( ( ( SLog - b) / ( w - b) - 0.030001222851889303) / 5.) * 0.9 
-            return lin
-
-        def sLog2ToLinear(SLog):
-            b = 64.
-            ab = 90.
-            w = 940.
-
-            if (SLog >= ab):
-                lin = ( 219. * ( pow(10., ( ( ( SLog - b) / ( w - b) - 0.616596 - 0.03) / 0.432699)) - 0.037584) / 155.) * 0.9
-            else:
-                lin = ( ( ( SLog - b) / ( w - b) - 0.030001222851889303) / 3.53881278538813) * 0.9
-            return lin
-
-        def sLog3ToLinear(codeValue):
-            if codeValue >= (171.2102946929):
-                linear = pow(10.0, ((codeValue - 420.0) / 261.5)) * (0.18 + 0.01) - 0.01
-            else:
-                linear = (codeValue - 95.0)*0.01125000/(171.2102946929 - 95.0)
-            #print( codeValue, linear )
-            return linear
-
-        cs.toReferenceTransforms = []
-
-        if transferFunction == "S-Log1":
-            data = array.array('f', "\0" * lutResolution1d * 4)
-            for c in range(lutResolution1d):
-                data[c] = sLog1ToLinear(1023.0*c/(lutResolution1d-1))
-
-            lut = "%s_to_linear.spi1d" % transferFunction
-            WriteSPI1D(lutDir + "/" + lut, 0.0, 1.0, data, lutResolution1d, 1)
-
-            #print( "Writing %s" % lut)
-
-            cs.toReferenceTransforms.append( {
-                'type':'lutFile', 
-                'path':lut, 
-                'interpolation':'linear', 
-                'direction':'forward'
-            } )
-        elif transferFunction == "S-Log2":
-            data = array.array('f', "\0" * lutResolution1d * 4)
-            for c in range(lutResolution1d):
-                data[c] = sLog2ToLinear(1023.0*c/(lutResolution1d-1))
-
-            lut = "%s_to_linear.spi1d" % transferFunction
-            WriteSPI1D(lutDir + "/" + lut, 0.0, 1.0, data, lutResolution1d, 1)
-
-            #print( "Writing %s" % lut)
-
-            cs.toReferenceTransforms.append( {
-                'type':'lutFile', 
-                'path':lut, 
-                'interpolation':'linear', 
-                'direction':'forward'
-            } )
-        elif transferFunction == "S-Log3":
-            data = array.array('f', "\0" * lutResolution1d * 4)
-            for c in range(lutResolution1d):
-                data[c] = sLog3ToLinear(1023.0*c/(lutResolution1d-1))
-
-            lut = "%s_to_linear.spi1d" % transferFunction
-            WriteSPI1D(lutDir + "/" + lut, 0.0, 1.0, data, lutResolution1d, 1)
-
-            #print( "Writing %s" % lut)
-
-            cs.toReferenceTransforms.append( {
-                'type':'lutFile', 
-                'path':lut, 
-                'interpolation':'linear', 
-                'direction':'forward'
-            } )
-
-        if gamut == 'S-Gamut':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.754338638, 0.133697046, 0.111968437,
-                                        0.021198141, 1.005410934, -0.026610548, 
-                                        -0.009756991, 0.004508563, 1.005253201]),
-                'direction':'forward'
-            })
-        elif gamut == 'S-Gamut Daylight':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.8764457030, 0.0145411681, 0.1090131290,
-                                        0.0774075345, 0.9529571767, -0.0303647111, 
-                                        0.0573564351, -0.1151066335, 1.0577501984]),
-                'direction':'forward'
-            })
-        elif gamut == 'S-Gamut Tungsten':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([1.0110238740, -0.1362526051, 0.1252287310, 
-                            0.1011994504, 0.9562196265, -0.0574190769,
-                            0.0600766530, -0.1010185315, 1.0409418785]),
-                'direction':'forward'
-            })
-        elif gamut == 'S-Gamut3.Cine':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.6387886672, 0.2723514337, 0.0888598992, 
-                                        -0.0039159061, 1.0880732308, -0.0841573249, 
-                                        -0.0299072021, -0.0264325799, 1.0563397820]),
-                'direction':'forward'
-            })
-        elif gamut == 'S-Gamut3':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.7529825954, 0.1433702162, 0.1036471884, 
-                            0.0217076974, 1.0153188355, -0.0370265329, 
-                            -0.0094160528, 0.0033704179, 1.0060456349]),
-                'direction':'forward'
-            })
-
-        cs.fromReferenceTransforms = []
-        return cs
-
-    # SLog1
-    SLog1SGamut = createSlog("S-Gamut", "S-Log1", name="S-Log")
-    configData['colorSpaces'].append(SLog1SGamut)
-
-    # SLog2
-    SLog2SGamut = createSlog("S-Gamut", "S-Log2", name="S-Log2")
-    configData['colorSpaces'].append(SLog2SGamut)
-
-    SLog2SGamutDaylight = createSlog("S-Gamut Daylight", "S-Log2", name="S-Log2")
-    configData['colorSpaces'].append(SLog2SGamutDaylight)
-
-    SLog2SGamutTungsten = createSlog("S-Gamut Tungsten", "S-Log2", name="S-Log2")
-    configData['colorSpaces'].append(SLog2SGamutTungsten)
-
-    # SLog3
-    SLog3SGamut3Cine = createSlog("S-Gamut3.Cine", "S-Log3", name="S-Log3")
-    configData['colorSpaces'].append(SLog3SGamut3Cine)
-
-    SLog3SGamut3 = createSlog("S-Gamut3", "S-Log3", name="S-Log3")
-    configData['colorSpaces'].append(SLog3SGamut3)
-
-    # Linearization only
-    SLog1 = createSlog("", "S-Log1", name="S-Log")
-    configData['colorSpaces'].append(SLog1)
-
-    SLog2 = createSlog("", "S-Log2", name="S-Log2")
-    configData['colorSpaces'].append(SLog2)
-
-    SLog3 = createSlog("", "S-Log3", name="S-Log3")
-    configData['colorSpaces'].append(SLog3)
-
-    # Primaries only
-    SGamut = createSlog("S-Gamut", "", name="S-Log")
-    configData['colorSpaces'].append(SGamut)
-
-    SGamutDaylight = createSlog("S-Gamut Daylight", "", name="S-Log2")
-    configData['colorSpaces'].append(SGamutDaylight)
-
-    SGamutTungsten = createSlog("S-Gamut Tungsten", "", name="S-Log2")
-    configData['colorSpaces'].append(SGamutTungsten)
-
-    SGamut3Cine = createSlog("S-Gamut3.Cine", "", name="S-Log3")
-    configData['colorSpaces'].append(SGamut3Cine)
-
-    SGamut3 = createSlog("S-Gamut3", "", name="S-Log3")
-    configData['colorSpaces'].append(SGamut3)
+    sonyColorSpaces = sony.createColorSpaces(lutDir, lutResolution1d)
+    for cs in sonyColorSpaces:
+        configData['colorSpaces'].append(cs)
 
-    #
     # LogC to ACES
-    #
-    def createLogC(gamut, transferFunction, exposureIndex, name='LogC'):
-        name = "%s (EI%s) - %s" % (transferFunction, exposureIndex, gamut)
-        if transferFunction == "":
-            name = "Linear - %s" % gamut
-        if gamut == "":
-            name = "%s (EI%s)" % (transferFunction, exposureIndex)
-
-        cs = ColorSpace(name)
-        cs.description = name
-        cs.equalityGroup = ''
-        cs.family = 'ARRI'
-        cs.isData=False
-
-        # Globals
-        IDT_maker_version = "0.08"
-
-        nominalEI = 400.0
-        blackSignal = 0.003907
-        midGraySignal = 0.01
-        encodingGain = 0.256598
-        encodingOffset = 0.391007
-
-        def gainForEI(EI) :
-            return (math.log(EI/nominalEI)/math.log(2) * (0.89 - 1) / 3 + 1) * encodingGain
-
-        def LogCInverseParametersForEI(EI) :
-            cut = 1.0 / 9.0
-            slope = 1.0 / (cut * math.log(10))
-            offset = math.log10(cut) - slope * cut
-            gain = EI / nominalEI
-            gray = midGraySignal / gain
-            # The higher the EI, the lower the gamma
-            encGain = gainForEI(EI)
-            encOffset = encodingOffset
-            for i in range(0,3) :
-                nz = ((95.0 / 1023.0 - encOffset) / encGain - offset) / slope
-                encOffset = encodingOffset - math.log10(1 + nz) * encGain
-            # Calculate some intermediate values
-            a = 1.0 / gray
-            b = nz - blackSignal / gray
-            e = slope * a * encGain
-            f = encGain * (slope * b + offset) + encOffset
-            # Manipulations so we can return relative exposure
-            s = 4 / (0.18 * EI)
-            t = blackSignal
-            b = b + a * t
-            a = a * s
-            f = f + e * t
-            e = e * s
-            return { 'a' : a,
-                     'b' : b,
-                     'cut' : (cut - b) / a,
-                     'c' : encGain,
-                     'd' : encOffset,
-                     'e' : e,
-                     'f' : f }
-
-        def logCtoLinear(codeValue, exposureIndex):
-            p = LogCInverseParametersForEI(exposureIndex)
-            breakpoint = p['e'] * p['cut'] + p['f']
-            if (codeValue > breakpoint):
-                linear = (pow(10,(codeValue/1023.0 - p['d']) / p['c']) - p['b']) / p['a']
-            else:
-                linear = (codeValue/1023.0 - p['f']) / p['e']
-
-            #print( codeValue, linear )
-            return linear
-
-
-        cs.toReferenceTransforms = []
-
-        if transferFunction == "V3 LogC":
-            data = array.array('f', "\0" * lutResolution1d * 4)
-            for c in range(lutResolution1d):
-                data[c] = logCtoLinear(1023.0*c/(lutResolution1d-1), int(exposureIndex))
-
-            lut = "%s_to_linear.spi1d" % ("%s_%s" % (transferFunction, exposureIndex))
-            WriteSPI1D(lutDir + "/" + lut, 0.0, 1.0, data, lutResolution1d, 1)
-
-            #print( "Writing %s" % lut)
-            cs.toReferenceTransforms.append( {
-                'type':'lutFile', 
-                'path':lut, 
-                'interpolation':'linear', 
-                'direction':'forward'
-            } )
-
-        if gamut == 'Wide Gamut':
-            cs.toReferenceTransforms.append( {
-                'type':'matrix',
-                'matrix':mat44FromMat33([0.680206, 0.236137, 0.083658, 
-                            0.085415, 1.017471, -0.102886, 
-                            0.002057, -0.062563, 1.060506]),
-                'direction':'forward'
-            })
-
-        cs.fromReferenceTransforms = []
-        return cs
-
-    transferFunction = "V3 LogC"
-    gamut = "Wide Gamut"
-    #EIs = [160.0, 200.0, 250.0, 320.0, 400.0, 500.0, 640.0, 800.0, 1000.0, 1280.0, 1600.0, 2000.0, 2560.0, 3200.0]
-    EIs = [160, 200, 250, 320, 400, 500, 640, 800, 1000, 1280, 1600, 2000, 2560, 3200]
-    defaultEI = 800
-
-    # Full conversion
-    for EI in EIs:
-        LogCEIfull = createLogC(gamut, transferFunction, EI, name="LogC")
-        configData['colorSpaces'].append(LogCEIfull)
-
-    # Linearization only
-    for EI in [800]:
-        LogCEIlinearization = createLogC("", transferFunction, EI, name="LogC")
-        configData['colorSpaces'].append(LogCEIlinearization)
-
-    # Primaries
-    LogCEIprimaries = createLogC(gamut, "", defaultEI, name="LogC")
-    configData['colorSpaces'].append(LogCEIprimaries)
+    arriColorSpaces = arri.createColorSpaces(lutDir, lutResolution1d)
+    for cs in arriColorSpaces:
+        configData['colorSpaces'].append(cs)
 
     #
     # Generic log transform
@@ -1458,12 +620,11 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
         cs.isData=False
 
         ctls = [
-            #'%s/logShaper/logShaper16i_to_aces_param.ctl' % acesCTLReleaseDir
             '%s/utilities/ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl' % acesCTLReleaseDir
         ]
         lut = "%s_to_aces.spi1d" % name
 
-        generate1dLUTFromCTL( lutDir + "/" + lut, 
+        genlut.generate1dLUTFromCTL( lutDir + "/" + lut, 
             ctls, 
             lutResolution1d, 
             'float', 
@@ -1518,7 +679,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             ctls = [
                 shaperToACESCTL % acesCTLReleaseDir
             ]
-            generate1dLUTFromCTL( lutDir + "/" + shaperLut, 
+            genlut.generate1dLUTFromCTL( lutDir + "/" + shaperLut, 
                 ctls, 
                 lutResolution1d, 
                 'float', 
@@ -1547,7 +708,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             ]
             lut = "%s.%s.spi3d" % (shaperName, lmtName)
 
-            generate3dLUTFromCTL( lutDir + "/" + lut, 
+            genlut.generate3dLUTFromCTL( lutDir + "/" + lut, 
                 ctls, 
                 lutResolution3d, 
                 'float', 
@@ -1577,7 +738,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             ]
             lut = "Inverse.%s.%s.spi3d" % (odtName, shaperName)
 
-            generate3dLUTFromCTL( lutDir + "/" + lut, 
+            genlut.generate3dLUTFromCTL( lutDir + "/" + lut, 
                 ctls, 
                 lutResolution3d, 
                 'half', 
@@ -1628,8 +789,6 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
         lmtShaperName, 
         '%s/utilities/ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl',
         '%s/utilities/ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl',
-        #'%s/logShaper/logShaper16i_to_aces_param.ctl',
-        #'%s/logShaper/aces_to_logShaper16i_param.ctl',
         shaperInputScale_genericLog2,
         lmtParams
     ]
@@ -1681,7 +840,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             ctls = [
                 shaperToACESCTL % acesCTLReleaseDir
             ]
-            generate1dLUTFromCTL( lutDir + "/" + shaperLut, 
+            genlut.generate1dLUTFromCTL( lutDir + "/" + shaperLut, 
                 ctls, 
                 lutResolution1d, 
                 'float', 
@@ -1726,7 +885,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             ]
             lut = "%s.RRT.a1.0.0.%s.spi3d" % (shaperName, odtName)
 
-            generate3dLUTFromCTL( lutDir + "/" + lut, 
+            genlut.generate3dLUTFromCTL( lutDir + "/" + lut, 
                 #shaperLUT,
                 ctls, 
                 lutResolution3d, 
@@ -1774,7 +933,7 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
             ]
             lut = "InvRRT.a1.0.0.%s.%s.spi3d" % (odtName, shaperName)
 
-            generate3dLUTFromCTL( lutDir + "/" + lut, 
+            genlut.generate3dLUTFromCTL( lutDir + "/" + lut, 
                 #None,
                 ctls, 
                 lutResolution3d, 
@@ -1823,8 +982,6 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
         log2ShaperName, 
         '%s/utilities/ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl',
         '%s/utilities/ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl',
-        #'%s/logShaper/logShaper16i_to_aces_param.ctl',
-        #'%s/logShaper/aces_to_logShaper16i_param.ctl',
         shaperInputScale_genericLog2,
         log2Params
     ]
@@ -1851,24 +1008,12 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
     #
     # Choose your shaper
     #
-    # XXX
-    # Shaper name. Should really be automated or made a user choice
-    #
-    # Options: aceslogShaper, aceslogScaledShaper, log2Shaper
-    #shaperName = 'log2Shaper'
-
-    #if shaperName in shaperData:
-    #    rrtShaperName = shaperName
-    #    rrtShaper = shaperData[shaperName]
-    #else:
-
     rrtShaperName = log2ShaperName
     rrtShaper = log2ShaperData
 
     #
     # RRT + ODT Combinations
     #
-    #for odtName, odtValues in odtInfo.iteritems():
     sortedOdts = sorted(odtInfo.iteritems(), key=lambda x: x[1])
     print( sortedOdts )
     for odt in sortedOdts:
@@ -1999,7 +1144,6 @@ def generateLUTs(odtInfo, lmtInfo, shaperName, acesCTLReleaseDir, lutDir, lutRes
     return configData
 
 def generateBakedLUTs(odtInfo, shaperName, bakedDir, configPath, lutResolution1d, lutResolution3d, lutResolutionShaper=1024):
-
     # Add the legal and full variations into this list
     odtInfoC = dict(odtInfo)
     for odtCTLName, odtValues in odtInfo.iteritems():