def create_transfer_colorspace(name='transfer',
                               transfer_function_name='transfer_function',
                               transfer_function=lambda x: x,
                               lut_directory='/tmp',
                               lut_resolution_1d=1024,
                               aliases=[]):
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    # Sample the transfer function
    data = array.array('f', '\0' * lut_resolution_1d * 4)
    for c in range(lut_resolution_1d):
        data[c] = transfer_function(c / (lut_resolution_1d - 1))

    # Write the sampled data to a LUT
    lut = '%s_to_linear.spi1d' % transfer_function_name
    genlut.write_SPI_1d(
        os.path.join(lut_directory, lut),
        0,
        1,
        data,
        lut_resolution_1d,
        1)

    # Create the 'to_reference' transforms
    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    # Create the 'from_reference' transforms
    cs.from_reference_transforms = []

    return cs
def create_matrix_colorspace(name='matrix',
                             from_reference_values=None,
                             to_reference_values=None,
                             aliases=None):
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    cs.to_reference_transforms = []
    if to_reference_values:
        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type': 'matrix',
                'matrix': mat44_from_mat33(matrix),
                'direction': 'forward'})

    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type': 'matrix',
                'matrix': mat44_from_mat33(matrix),
                'direction': 'forward'})

    return cs
def create_ACES():
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    # Defining the reference colorspace.
    aces2065_1 = ColorSpace('ACES2065-1')
    aces2065_1.description = (
        'The Academy Color Encoding System reference color space')
    aces2065_1.equality_group = ''
    aces2065_1.aliases = ['lin_ap0', 'aces']
    aces2065_1.family = 'ACES'
    aces2065_1.is_data = False
    aces2065_1.allocation_type = ocio.Constants.ALLOCATION_LG2
    aces2065_1.allocation_vars = [-8, 5, 0.00390625]

    return aces2065_1
def create_Dolby_PQ_scaled(aces_ctl_directory,
                           lut_directory,
                           lut_resolution_1d,
                           cleanup,
                           name='pq',
                           aliases=None,
                           min_value=0.0,
                           max_value=1.0,
                           input_scale=1.0,
                           middle_grey=0.18,
                           min_exposure=-6.0,
                           max_exposure=6.5):
    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    ctls = [os.path.join(
        aces_ctl_directory,
        'utilities',
        'ACESlib.OCIOShaper_to_lin_param.a1.0.0.ctl')]
    lut = '%s_to_linear.spi1d' % name

    lut = sanitize(lut)

    generate_1d_LUT_from_CTL(
        os.path.join(lut_directory, lut),
        ctls,
        lut_resolution_1d,
        'float',
        input_scale,
        1.0,
        {'middleGrey': middle_grey,
         'minExposure': min_exposure,
         'maxExposure': max_exposure},
        cleanup,
        aces_ctl_directory,
        min_value,
        max_value)

    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_ACEScg(aces_ctl_directory,
                  lut_directory,
                  lut_resolution_1d,
                  cleanup,
                  name='ACEScg'):
    """
    Creates the *ACEScg* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ACEScg* colorspace.
    """

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = ["lin_ap1"]
    cs.equality_group = ''
    cs.family = 'ACES'
    cs.is_data = False
    cs.allocation_type = ocio.Constants.ALLOCATION_LG2
    cs.allocation_vars = [-8, 5, 0.00390625]

    cs.to_reference_transforms = []

    # *AP1* primaries to *AP0* primaries.
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
Beispiel #6
0
def create_dolbypq_scaled(
    aces_CTL_directory,
    lut_directory,
    lut_resolution_1d,
    cleanup,
    name="pq",
    aliases=[],
    min_value=0.0,
    max_value=1.0,
    input_scale=1.0,
    middle_grey=0.18,
    min_exposure=-6.0,
    max_exposure=6.5,
):
    cs = ColorSpace(name)
    cs.description = "The %s color space" % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = "Utility"
    cs.is_data = False

    ctls = [os.path.join(aces_CTL_directory, "utilities", "ACESlib.DolbyPQ_to_lin_param.a1.0.0.ctl")]
    lut = "%s_to_linear.spi1d" % name

    lut = sanitize(lut)

    generate_1d_LUT_from_CTL(
        os.path.join(lut_directory, lut),
        ctls,
        lut_resolution_1d,
        "float",
        input_scale,
        1.0,
        {"middleGrey": middle_grey, "minExposure": min_exposure, "maxExposure": max_exposure},
        cleanup,
        aces_CTL_directory,
        min_value,
        max_value,
    )

    cs.to_reference_transforms = []
    cs.to_reference_transforms.append(
        {"type": "lutFile", "path": lut, "interpolation": "linear", "direction": "forward"}
    )

    cs.from_reference_transforms = []
    return cs
def create_dolbypq(aces_CTL_directory,
                    lut_directory,
                    lut_resolution_1d,
                    cleanup,
                    name='pq',
                    aliases=[],
                    min_value=0.0,
                    max_value=1.0,
                    input_scale=1.0):
    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    ctls = [os.path.join(
                         aces_CTL_directory,
                         'utilities',
                         'ACESlib.OCIO_shaper_dolbypq_to_lin.a1.0.0.ctl')]
    lut = '%s_to_linear.spi1d' % name

    lut = sanitize(lut)

    generate_1d_LUT_from_CTL(
        os.path.join(lut_directory, lut),
        ctls,
        lut_resolution_1d,
        'float',
        input_scale,
        1.0,
        {},
        cleanup,
        aces_CTL_directory,
        min_value,
        max_value)

    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_raw():
    # *Raw* utility space
    name = "Raw"
    raw = ColorSpace(name)
    raw.description = 'The %s color space' % name
    raw.aliases = []
    raw.equality_group = name
    raw.family = 'Utility'
    raw.is_data = True

    return raw
Beispiel #9
0
def create_raw():
    """
    Creates the *raw* colorspace.

    Returns
    -------
    ColorSpace
         *raw* and all its identifying information.
    """

    # *Raw* utility space
    name = 'Raw'
    raw = ColorSpace(name)
    raw.description = 'The {0} color space'.format(name)
    raw.aliases = ['raw']
    raw.equality_group = name
    raw.family = 'Utility'
    raw.is_data = True

    return raw
def create_raw():
    """
    Creates the *raw* color space

    Parameters
    ----------
    None

    Returns
    -------
    ColorSpace
         *raw* and all its identifying information
    """
    # *Raw* utility space
    name = 'Raw'
    raw = ColorSpace(name)
    raw.description = 'The %s color space' % name
    raw.aliases = ['raw']
    raw.equality_group = name
    raw.family = 'Utility'
    raw.is_data = True

    return raw
def create_c_log(gamut,
                 transfer_function,
                 lut_directory,
                 lut_resolution_1d,
                 aliases):
    """
    Object description.

    Canon-Log to ACES.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - Canon %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Canon'
    cs.is_data = False

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def legal_to_full(code_value):
        return (code_value - 64) / (940 - 64)

    def c_log_to_linear(code_value):
        # 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, (legal_to_full(code_value) - c3) / c1) - 1) / c2
        linear *= 0.9

        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'Canon-Log':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = c_log_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'Rec. 709 Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.561538969, 0.402060105, 0.036400926, 0,
                       0.092739623, 0.924121198, -0.016860821, 0,
                       0.084812961, 0.006373835, 0.908813204, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Rec. 709 Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.566996399, 0.365079418, 0.067924183, 0,
                       0.070901044, 0.880331008, 0.048767948, 0,
                       0.073013542, -0.066540862, 0.99352732, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'DCI-P3 Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.607160575, 0.299507286, 0.093332140, 0,
                       0.004968120, 1.050982224, -0.055950343, 0,
                       -0.007839939, 0.000809127, 1.007030813, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'DCI-P3 Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.650279125, 0.253880169, 0.095840706, 0,
                       -0.026137986, 1.017900530, 0.008237456, 0,
                       0.007757558, -0.063081669, 1.055324110, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Cinema Gamut Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.763064455, 0.149021161, 0.087914384, 0,
                       0.003657457, 1.10696038, -0.110617837, 0,
                       -0.009407794, -0.218383305, 1.227791099, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Cinema Gamut Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.817416293, 0.090755698, 0.091828009, 0,
                       -0.035361374, 1.065690585, -0.030329211, 0,
                       0.010390366, -0.299271107, 1.288880741, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_matrix_colorspace(name='matrix',
                             from_reference_values=None,
                             to_reference_values=None,
                             aliases=None):
    """
    Creates a ColorSpace that only uses *Matrix Transforms*

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace
    from_reference_values : list of matrices
        List of matrices to convert from the reference colorspace to this space        
    to_reference_values : list of matrices
        List of matrices to convert to the reference colorspace from this space
    aliases : list of str, optional
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A *Matrix Transform*-based ColorSpace
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_LG2
    cs.allocation_vars = [-8, 5, 0.00390625]

    cs.to_reference_transforms = []
    if to_reference_values:
        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type': 'matrix',
                'matrix': mat44_from_mat33(matrix),
                'direction': 'forward'})

    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type': 'matrix',
                'matrix': mat44_from_mat33(matrix),
                'direction': 'forward'})

    return cs
Beispiel #13
0
def create_red_log_film(gamut,
                        transfer_function,
                        lut_directory,
                        lut_resolution_1d,
                        aliases=None):
    """
    Creates colorspace covering the conversion from RED spaces to ACES, with various 
    transfer functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.
    """

    if aliases is None:
        aliases = []

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/RED'
    cs.is_data = False

    # A linear space needs allocation variables
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def cineon_to_linear(code_value):
        n_gamma = 0.6
        black_point = 95
        white_point = 685
        code_value_to_density = 0.002

        black_linear = pow(10, (black_point - white_point) * (
            code_value_to_density / n_gamma))
        code_linear = pow(10, (code_value - white_point) * (
            code_value_to_density / n_gamma))

        return (code_linear - black_linear) / (1 - black_linear)

    cs.to_reference_transforms = []

    if transfer_function == 'REDlogFilm':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = cineon_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = 'CineonLog_to_linear.spi1d'
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'DRAGONcolor':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.532279, 0.376648, 0.091073,
                                        0.046344, 0.974513, -0.020860,
                                        -0.053976, -0.000320, 1.054267]),
            'direction': 'forward'})
    elif gamut == 'DRAGONcolor2':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.468452, 0.331484, 0.200064,
                                        0.040787, 0.857658, 0.101553,
                                        -0.047504, -0.000282, 1.047756]),
            'direction': 'forward'})
    elif gamut == 'REDcolor':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.451464, 0.388498, 0.160038,
                                        0.062716, 0.866790, 0.070491,
                                        -0.017541, 0.086921, 0.930590]),
            'direction': 'forward'})
    elif gamut == 'REDcolor2':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.480997, 0.402289, 0.116714,
                                        -0.004938, 1.000154, 0.004781,
                                        -0.105257, 0.025320, 1.079907]),
            'direction': 'forward'})
    elif gamut == 'REDcolor3':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.512136, 0.360370, 0.127494,
                                        0.070377, 0.903884, 0.025737,
                                        -0.020824, 0.017671, 1.003123]),
            'direction': 'forward'})
    elif gamut == 'REDcolor4':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.474202, 0.333677, 0.192121,
                                        0.065164, 0.836932, 0.097901,
                                        -0.019281, 0.016362, 1.002889]),
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_log_c(gamut,
                 transfer_function,
                 exposure_index,
                 name,
                 lut_directory,
                 lut_resolution_1d,
                 aliases):
    """
    Object description.

    LogC to ACES.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    name = '%s (EI%s) - %s' % (transfer_function, exposure_index, gamut)
    if transfer_function == '':
        name = 'Linear - ARRI %s' % gamut
    if gamut == '':
        name = '%s (EI%s)' % (transfer_function, exposure_index)

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/ARRI'
    cs.is_data = False

    # A linear space needs allocation variables
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    # Globals.
    IDT_maker_version = '0.08'

    nominal_EI = 400
    black_signal = 0.003907
    mid_gray_signal = 0.01
    encoding_gain = 0.256598
    encoding_offset = 0.391007

    def gain_for_EI(EI):
        return (math.log(EI / nominal_EI) / math.log(2) * (
            0.89 - 1) / 3 + 1) * encoding_gain

    def log_c_inverse_parameters_for_EI(EI):
        cut = 1 / 9
        slope = 1 / (cut * math.log(10))
        offset = math.log10(cut) - slope * cut
        gain = EI / nominal_EI
        gray = mid_gray_signal / gain
        # The higher the EI, the lower the gamma.
        enc_gain = gain_for_EI(EI)
        enc_offset = encoding_offset
        for i in range(0, 3):
            nz = ((95 / 1023 - enc_offset) / enc_gain - offset) / slope
            enc_offset = encoding_offset - math.log10(1 + nz) * enc_gain

        a = 1 / gray
        b = nz - black_signal / gray
        e = slope * a * enc_gain
        f = enc_gain * (slope * b + offset) + enc_offset

        # Ensuring we can return relative exposure.
        s = 4 / (0.18 * EI)
        t = black_signal
        b += a * t
        a *= s
        f += e * t
        e *= s

        return {'a': a,
                'b': b,
                'cut': (cut - b) / a,
                'c': enc_gain,
                'd': enc_offset,
                'e': e,
                'f': f}

    def log_c_to_linear(code_value, exposure_index):
        p = log_c_inverse_parameters_for_EI(exposure_index)
        breakpoint = p['e'] * p['cut'] + p['f']
        if code_value > breakpoint:
            linear = ((pow(10, (code_value / 1023 - p['d']) / p['c']) -
                       p['b']) / p['a'])
        else:
            linear = (code_value / 1023 - p['f']) / p['e']
        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'V3 LogC':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = log_c_to_linear(1023 * c / (lut_resolution_1d - 1),
                                      int(exposure_index))

        lut = '%s_to_linear.spi1d' % (
            '%s_%s' % (transfer_function, exposure_index))

        lut = sanitize(lut)

        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'Wide Gamut':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33([0.680206, 0.236137, 0.083658,
                                        0.085415, 1.017471, -0.102886,
                                        0.002057, -0.062563, 1.060506]),
            'direction': 'forward'
        })

    cs.from_reference_transforms = []
    return cs
def create_ACES_RRT_plus_ODT(odt_name,
                             odt_values,
                             shaper_info,
                             aces_ctl_directory,
                             lut_directory,
                             lut_resolution_3d=64,
                             cleanup=True,
                             aliases=None):
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    if aliases is None:
        aliases = []

    cs = ColorSpace('%s' % odt_name)
    cs.description = '%s - %s Output Transform' % (
        odt_values['transformUserNamePrefix'], odt_name)
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Output'
    cs.is_data = False

    cs.aces_transform_id = odt_values['transformID']

    pprint.pprint(odt_values)

    # Generating the *shaper* transform.
    (shaper_name,
     shaper_to_aces_ctl,
     shaper_from_aces_ctl,
     shaper_input_scale,
     shaper_params) = shaper_info

    if 'legalRange' in odt_values:
        shaper_params['legalRange'] = odt_values['legalRange']
    else:
        shaper_params['legalRange'] = 0

    shaper_lut = '%s_to_linear.spi1d' % shaper_name
    shaper_lut = sanitize(shaper_lut)

    shaper_ocio_transform = {
        'type': 'lutFile',
        'path': shaper_lut,
        'interpolation': 'linear',
        'direction': 'inverse'}

    # Generating the *forward* transform.
    cs.from_reference_transforms = []

    if 'transformLUT' in odt_values:
        transform_lut_file_name = os.path.basename(
            odt_values['transformLUT'])
        lut = os.path.join(lut_directory, transform_lut_file_name)
        shutil.copy(odt_values['transformLUT'], lut)

        cs.from_reference_transforms.append(shaper_ocio_transform)
        cs.from_reference_transforms.append({
            'type': 'lutFile',
            'path': transform_lut_file_name,
            'interpolation': 'tetrahedral',
            'direction': 'forward'})
    elif 'transformCTL' in odt_values:
        ctls = [
            shaper_to_aces_ctl % aces_ctl_directory,
            os.path.join(aces_ctl_directory,
                         'rrt',
                         'RRT.a1.0.0.ctl'),
            os.path.join(aces_ctl_directory,
                         'odt',
                         odt_values['transformCTL'])]
        lut = '%s.RRT.a1.0.0.%s.spi3d' % (shaper_name, odt_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            ctls,
            lut_resolution_3d,
            'float',
            1 / shaper_input_scale,
            1,
            shaper_params,
            cleanup,
            aces_ctl_directory)

        cs.from_reference_transforms.append(shaper_ocio_transform)
        cs.from_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'tetrahedral',
            'direction': 'forward'})

    # Generating the *inverse* transform.
    cs.to_reference_transforms = []

    if 'transformLUTInverse' in odt_values:
        transform_lut_inverse_file_name = os.path.basename(
            odt_values['transformLUTInverse'])
        lut = os.path.join(lut_directory, transform_lut_inverse_file_name)
        shutil.copy(odt_values['transformLUTInverse'], lut)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': transform_lut_inverse_file_name,
            'interpolation': 'tetrahedral',
            'direction': 'forward'})

        shaper_inverse = shaper_ocio_transform.copy()
        shaper_inverse['direction'] = 'forward'
        cs.to_reference_transforms.append(shaper_inverse)
    elif 'transformCTLInverse' in odt_values:
        ctls = [os.path.join(aces_ctl_directory,
                             'odt',
                             odt_values['transformCTLInverse']),
                os.path.join(aces_ctl_directory,
                             'rrt',
                             'InvRRT.a1.0.0.ctl'),
                shaper_from_aces_ctl % aces_ctl_directory]
        lut = 'InvRRT.a1.0.0.%s.%s.spi3d' % (odt_name, shaper_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            ctls,
            lut_resolution_3d,
            'half',
            1,
            shaper_input_scale,
            shaper_params,
            cleanup,
            aces_ctl_directory)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'tetrahedral',
            'direction': 'forward'})

        shaper_inverse = shaper_ocio_transform.copy()
        shaper_inverse['direction'] = 'forward'
        cs.to_reference_transforms.append(shaper_inverse)

    return cs
def create_v_log(gamut,
                 transfer_function,
                 lut_directory,
                 lut_resolution_1d,
                 aliases):
    """
    Object description.

    Panasonic V-Log to ACES.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Panasonic'
    cs.is_data = False

    # A linear space needs allocation variables
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def v_log_to_linear(x):
        cut_inv = 0.181
        b = 0.00873
        c = 0.241514
        d = 0.598206

        if x <= cut_inv:
            return (x - 0.125) / 5.6
        else:
            return pow(10, (x - d) / c) - b

    cs.to_reference_transforms = []

    if transfer_function == 'V-Log':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = v_log_to_linear(float(c) / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0.0,
            1.0,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'V-Gamut':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.724382758, 0.166748484, 0.108497411, 0.0,
                       0.021354009, 0.985138372, -0.006319092, 0.0,
                       -0.009234278, -0.00104295, 1.010272625, 0.0,
                       0, 0, 0, 1.0],
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
Beispiel #17
0
def create_VLog(gamut, transfer_function, lut_directory, lut_resolution_1D,
                aliases):
    """
    Creates colorspace covering the conversion from *VLog* to *ACES*, with various
    transfer functions and encoding gamuts covered.

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use.
    lut_directory : str or unicode 
        The directory to use when generating LUTs.
    lut_resolution_1D : int
        The resolution of generated 1D LUTs.
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and
         identifying information for the requested colorspace.
    """

    name = '{0} - {1}'.format(transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - {0}'.format(gamut)
    if gamut == '':
        name = 'Curve - {0}'.format(transfer_function)

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Panasonic'
    cs.is_data = False

    # A linear space needs allocation variables
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def VLog_to_linear(x):
        cut_inv = 0.181
        b = 0.00873
        c = 0.241514
        d = 0.598206

        if x <= cut_inv:
            return (x - 0.125) / 5.6
        else:
            return pow(10, (x - d) / c) - b

    cs.to_reference_transforms = []

    if transfer_function == 'V-Log':
        data = array.array('f', b'\0' * lut_resolution_1D * 4)
        for c in range(lut_resolution_1D):
            data[c] = VLog_to_linear(float(c) / (lut_resolution_1D - 1))

        lut = '{0}_to_linear.spi1d'.format(transfer_function)
        genlut.write_SPI_1D(os.path.join(lut_directory, lut), 0.0, 1.0, data,
                            lut_resolution_1D, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'V-Gamut':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.724382758, 0.166748484, 0.108497411, 0.0, 0.021354009,
                0.985138372, -0.006319092, 0.0, -0.009234278, -0.00104295,
                1.010272625, 0.0, 0, 0, 0, 1.0
            ],
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs
def create_ACES_LMT(lmt_name,
                    lmt_values,
                    shaper_info,
                    aces_ctl_directory,
                    lut_directory,
                    lut_resolution_3d=64,
                    cleanup=True,
                    aliases=None):
    """
    Creates the *ACES LMT* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ACES LMT* colorspace.
    """

    if aliases is None:
        aliases = []

    cs = ColorSpace('%s' % lmt_name)
    cs.description = 'The ACES Look Transform: %s' % lmt_name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Look'
    cs.is_data = False
    cs.allocation_type = ocio.Constants.ALLOCATION_LG2
    cs.allocation_vars = [-8, 5, 0.00390625]
    cs.aces_transform_id = lmt_values['transformID']

    pprint.pprint(lmt_values)

    # Generating the *shaper* transform.
    (shaper_name,
     shaper_to_aces_ctl,
     shaper_from_aces_ctl,
     shaper_input_scale,
     shaper_params) = shaper_info

    shaper_lut = '%s_to_linear.spi1d' % shaper_name
    shaper_lut = sanitize(shaper_lut)

    shaper_ocio_transform = {
        'type': 'lutFile',
        'path': shaper_lut,
        'interpolation': 'linear',
        'direction': 'inverse'}

    # Generating the forward transform.
    cs.from_reference_transforms = []

    if 'transformCTL' in lmt_values:
        ctls = [shaper_to_aces_ctl % aces_ctl_directory,
                os.path.join(aces_ctl_directory,
                             lmt_values['transformCTL'])]
        lut = '%s.%s.spi3d' % (shaper_name, lmt_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            ctls,
            lut_resolution_3d,
            'float',
            1 / shaper_input_scale,
            1,
            shaper_params,
            cleanup,
            aces_ctl_directory)

        cs.from_reference_transforms.append(shaper_ocio_transform)
        cs.from_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'tetrahedral',
            'direction': 'forward'})

    # Generating the inverse transform.
    cs.to_reference_transforms = []

    if 'transformCTLInverse' in lmt_values:
        ctls = [os.path.join(aces_ctl_directory,
                             lmt_values['transformCTLInverse']),
                shaper_from_aces_ctl % aces_ctl_directory]
        lut = 'Inverse.%s.%s.spi3d' % (lmt_name, shaper_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            ctls,
            lut_resolution_3d,
            'half',
            1,
            shaper_input_scale,
            shaper_params,
            cleanup,
            aces_ctl_directory,
            0)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'tetrahedral',
            'direction': 'forward'})

        shaper_inverse = shaper_ocio_transform.copy()
        shaper_inverse['direction'] = 'forward'
        cs.to_reference_transforms.append(shaper_inverse)

    return cs
Beispiel #19
0
def create_c_log(gamut, transfer_function, lut_directory, lut_resolution_1d,
                 aliases):
    """
    Creates a colorspace covering the conversion from CLog to ACES, with
    various transfer functions and encoding gamuts covered.

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and
         identifying information for the requested colorspace.
    """

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - Canon %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Canon'
    cs.is_data = False

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def legal_to_full(code_value):
        return (code_value - 64) / (940 - 64)

    def c_log_to_linear(code_value):
        # 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, (legal_to_full(code_value) - c3) / c1) - 1) / c2
        linear *= 0.9

        return linear

    def c_log2_to_linear(code_value):
        # log = fullToLegal(c1 * log10(c2*linear + 1) + c3)
        # linear = (pow(10, (legalToFul(log) - c3)/c1) - 1)/c2
        c1 = 0.281863093
        c2 = 87.09937546
        c3 = 0.035388128

        linear = (pow(10, (legal_to_full(code_value) - c3) / c1) - 1) / c2
        linear *= 0.9

        return linear

    def c_log3_to_linear(code_value):
        # if(clog3_ire < 0.04076162)
        #     out = -( pow( 10, ( 0.07623209 - clog3_ire ) / 0.42889912 )
        #     - 1 ) / 14.98325;
        # else if(clog3_ire <= 0.105357102)
        #     out = ( clog3_ire - 0.073059361 ) / 2.3069815;
        # else
        #     out = ( pow( 10, ( clog3_ire - 0.069886632 ) / 0.42889912 )
        #     - 1 ) / 14.98325;

        c1 = 0.42889912
        c2 = 14.98325
        c3 = 0.069886632

        c4 = 0.04076162
        c5 = 0.07623209

        c6 = 0.105357102
        c7 = 0.073059361
        c8 = 2.3069815

        clog3_ire = legal_to_full(code_value)

        if clog3_ire < c4:
            linear = -(pow(10, (c5 - clog3_ire) / c1) - 1) / c2
        elif clog3_ire <= c6:
            linear = (clog3_ire - c7) / c8
        else:
            linear = (pow(10, (clog3_ire - c3) / c1) - 1) / c2
        linear *= 0.9

        return linear

    cs.to_reference_transforms = []

    if transfer_function:
        if transfer_function == 'Canon-Log':
            data = array.array('f', '\0' * lut_resolution_1d * 4)
            for c in range(lut_resolution_1d):
                data[c] = c_log_to_linear(1023 * c / (lut_resolution_1d - 1))
        elif transfer_function == 'Canon-Log2':
            data = array.array('f', '\0' * lut_resolution_1d * 4)
            for c in range(lut_resolution_1d):
                data[c] = c_log2_to_linear(1023 * c / (lut_resolution_1d - 1))
        elif transfer_function == 'Canon-Log3':
            data = array.array('f', '\0' * lut_resolution_1d * 4)
            for c in range(lut_resolution_1d):
                data[c] = c_log3_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'Rec. 709 Daylight':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.561538969, 0.402060105, 0.036400926, 0, 0.092739623,
                0.924121198, -0.016860821, 0, 0.084812961, 0.006373835,
                0.908813204, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'Rec. 709 Tungsten':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.566996399, 0.365079418, 0.067924183, 0, 0.070901044,
                0.880331008, 0.048767948, 0, 0.073013542, -0.066540862,
                0.99352732, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'DCI-P3 Daylight':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.607160575, 0.299507286, 0.093332140, 0, 0.004968120,
                1.050982224, -0.055950343, 0, -0.007839939, 0.000809127,
                1.007030813, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'DCI-P3 Tungsten':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.650279125, 0.253880169, 0.095840706, 0, -0.026137986,
                1.017900530, 0.008237456, 0, 0.007757558, -0.063081669,
                1.055324110, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'Cinema Gamut Daylight':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.763064455, 0.149021161, 0.087914384, 0, 0.003657457,
                1.10696038, -0.110617837, 0, -0.009407794, -0.218383305,
                1.227791099, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'Cinema Gamut Tungsten':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.817416293, 0.090755698, 0.091828009, 0, -0.035361374,
                1.065690585, -0.030329211, 0, 0.010390366, -0.299271107,
                1.288880741, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'Rec. 2020 Daylight':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.678891151, 0.158868422, 0.162240427, 0, 0.045570831,
                0.860712772, 0.093716397, 0, -0.000485710, 0.025060196,
                0.975425515, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })
    elif gamut == 'Rec. 2020 Tungsten':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.724488568, 0.115140904, 0.160370529, 0, 0.010659276,
                0.839605344, 0.149735380, 0, 0.014560161, 0.028562057,
                1.014001897, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs
Beispiel #20
0
def create_log_c(gamut, transfer_function, exposure_index, lut_directory,
                 lut_resolution_1d, aliases):
    """
    Creates a colorspace covering the conversion from LogC to ACES, with
    various transfer functions and encoding gamuts covered.

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use.
    exposure_index : str
        The exposure index to use.
    lut_directory : str or unicode 
        The directory to use when generating LUTs.
    lut_resolution_1d : int
        The resolution of generated 1D LUTs.
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and
         identifying information for the requested colorspace.
    """

    name = '%s (EI%s) - %s' % (transfer_function, exposure_index, gamut)
    if transfer_function == '':
        name = 'Linear - ALEXA %s' % gamut
    if gamut == '':
        name = 'Curve - %s (EI%s)' % (transfer_function, exposure_index)

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/ARRI'
    cs.is_data = False

    if gamut and transfer_function:
        cs.aces_transform_id = ('IDT.ARRI.Alexa-v3-logC-EI%s.a1.v1' %
                                exposure_index)

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    IDT_maker_version = '0.09'

    nominal_exposure_index = 400
    black_signal = 16 / 4095  # 0.003907
    mid_gray_signal = 0.01
    encoding_gain = 500 / 1023 * 0.525  # 0.256598
    encoding_offset = 400 / 1023  # 0.391007

    def gain_for_EI(ei):
        return (math.log(ei / nominal_exposure_index) / math.log(2) *
                (0.89 - 1) / 3 + 1) * encoding_gain

    def hermite_weights(x, x1, x2):
        d = x2 - x1
        s = (x - x1) / d
        s2 = 1 - s
        return [(1 + 2 * s) * s2 * s2, (3 - 2 * s) * s * s, d * s * s2 * s2,
                -d * s * s * s2]

    def normalized_sensor_to_relative_exposure(ns, ei):
        return (ns - black_signal) * (
            0.18 / (mid_gray_signal * nominal_exposure_index / ei))

    def normalized_log_c_to_linear(code_value, exposure_index):
        cut = 1 / 9
        slope = 1 / (cut * math.log(10))
        offset = math.log10(cut) - slope * cut
        gain = exposure_index / nominal_exposure_index
        gray = mid_gray_signal / gain
        # The higher the EI, the lower the gamma.
        enc_gain = (math.log(gain) / math.log(2) *
                    (0.89 - 1) / 3 + 1) * encoding_gain
        enc_offset = encoding_offset
        for i in range(0, 3):
            nz = ((95 / 1023 - enc_offset) / enc_gain - offset) / slope
            enc_offset = encoding_offset - math.log10(1 + nz) * enc_gain
        # see if we need to bring the hermite spline into play
        xm = math.log10((1 - black_signal) / gray + nz) * enc_gain + enc_offset
        if xm > 1.0:
            if code_value > 0.8:
                hw = hermite_weights(code_value, 0.8, 1)
                d = 0.2 / (xm - 0.8)
                v = [0.8, xm, 1.0, 1 / (d * d)]
                # reconstruct code value from spline
                code_value = 0
                for i in range(0, 4):
                    code_value += (hw[i] * v[i])
        code_value = (code_value - enc_offset) / enc_gain
        # compute normalized sensor value
        ns = pow(10, code_value) if (code_value - offset) / slope > cut else (
            code_value - offset) / slope
        ns = (ns - nz) * gray + black_signal
        return normalized_sensor_to_relative_exposure(ns, exposure_index)

    cs.to_reference_transforms = []

    if transfer_function == 'V3 LogC':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = normalized_log_c_to_linear(c / (lut_resolution_1d - 1),
                                                 int(exposure_index))

        lut = '%s_to_linear.spi1d' % ('%s_%s' %
                                      (transfer_function, exposure_index))

        lut = sanitize(lut)

        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'Wide Gamut':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.680206, 0.236137, 0.083658, 0.085415, 1.017471, -0.102886,
                0.002057, -0.062563, 1.060506
            ]),
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs
Beispiel #21
0
def create_s_log(gamut, transfer_function, lut_directory, lut_resolution_1d,
                 aliases):
    """
    Creates colorspace covering the conversion from Sony spaces to ACES, with various 
    transfer functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.
    """

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Sony'
    cs.is_data = False

    if gamut and transfer_function:
        cs.aces_transform_id = 'IDT.Sony.%s_%s_10i.a1.v1' % (
            transfer_function.replace('-', ''), gamut.replace('-', '').replace(
                ' ', '_'))

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def s_log1_to_linear(s_log):
        b = 64.
        ab = 90.
        w = 940.

        if s_log >= ab:
            linear = ((pow(10., (
                ((s_log - b) /
                 (w - b) - 0.616596 - 0.03) / 0.432699)) - 0.037584) * 0.9)
        else:
            linear = (((s_log - b) /
                       (w - b) - 0.030001222851889303) / 5.) * 0.9
        return linear

    def s_log2_to_linear(s_log):
        b = 64.
        ab = 90.
        w = 940.

        if s_log >= ab:
            linear = ((219. * (pow(10., (
                ((s_log - b) /
                 (w - b) - 0.616596 - 0.03) / 0.432699)) - 0.037584) / 155.) *
                      0.9)
        else:
            linear = (
                ((s_log - b) /
                 (w - b) - 0.030001222851889303) / 3.53881278538813) * 0.9
        return linear

    def s_log3_to_linear(code_value):
        if code_value >= 171.2102946929:
            linear = (pow(10,
                          ((code_value - 420) / 261.5)) * (0.18 + 0.01) - 0.01)
        else:
            linear = (code_value - 95) * 0.01125000 / (171.2102946929 - 95)

        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'S-Log1':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = s_log1_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })
    elif transfer_function == 'S-Log2':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = s_log2_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })
    elif transfer_function == 'S-Log3':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = s_log3_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'S-Gamut':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                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.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                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.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                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.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                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.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.7529825954, 0.1433702162, 0.1036471884, 0.0217076974,
                1.0153188355, -0.0370265329, -0.0094160528, 0.0033704179,
                1.0060456349
            ]),
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs
Beispiel #22
0
def create_matrix_colorspace(name='matrix',
                             from_reference_values=None,
                             to_reference_values=None,
                             aliases=None):
    """
    Creates a ColorSpace that only uses *Matrix Transforms*

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace
    from_reference_values : list of matrices
        List of matrices to convert from the reference colorspace to this space        
    to_reference_values : list of matrices
        List of matrices to convert to the reference colorspace from this space
    aliases : list of str, optional
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A *Matrix Transform*-based ColorSpace
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_LG2
    cs.allocation_vars = [-8, 5, 0.00390625]

    cs.to_reference_transforms = []
    if to_reference_values:
        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

    return cs
Beispiel #23
0
def create_matrix_plus_transfer_colorspace(
        name='matrix_plus_transfer',
        transfer_function_name='transfer_function',
        transfer_function=lambda x: x,
        lut_directory='/tmp',
        lut_resolution_1d=1024,
        from_reference_values=None,
        to_reference_values=None,
        aliases=None):
    """
    Creates a ColorSpace that uses transfer functions encoded as 1D LUTs and
    matrice

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace
    transfer_function_name : str, optional
        The name of the transfer function
    transfer_function : function, optional
        The transfer function to be evaluated
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    from_reference_values : list of matrices
        List of matrices to convert from the reference colorspace to this space        
    to_reference_values : list of matrices
        List of matrices to convert to the reference colorspace from this space
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A *Matrx and LUT1D Transform*-based ColorSpace representing a transfer 
         function and matrix
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    # Sampling the transfer function.
    data = array.array('f', '\0' * lut_resolution_1d * 4)
    for c in range(lut_resolution_1d):
        data[c] = transfer_function(c / (lut_resolution_1d - 1))

    # Writing the sampled data to a *LUT*.
    lut = '%s_to_linear.spi1d' % transfer_function_name
    genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                        lut_resolution_1d, 1)

    # Creating the *to_reference* transforms.
    cs.to_reference_transforms = []
    if to_reference_values:
        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

    # Creating the *from_reference* transforms.
    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

        cs.from_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'inverse'
        })

    return cs
Beispiel #24
0
def create_ODTs(
    aces_ctl_directory,
    lut_directory,
    lut_resolution_1d,
    lut_resolution_3d,
    odt_info,
    shaper_name,
    cleanup,
    linear_display_space,
    log_display_space,
):
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    colorspaces = []
    displays = {}

    # -------------------------------------------------------------------------
    # *RRT / ODT* Shaper Options
    # -------------------------------------------------------------------------
    shaper_data = {}

    # Defining the *Log 2* shaper.
    log2_shaper_name = shaper_name
    log2_shaper_name_aliases = ["crv_%s" % compact(log2_shaper_name)]
    log2_params = {"middleGrey": 0.18, "minExposure": -6, "maxExposure": 6.5}

    log2_shaper_colorspace = create_generic_log(
        aces_ctl_directory,
        lut_directory,
        lut_resolution_1d,
        cleanup,
        name=log2_shaper_name,
        middle_grey=log2_params["middleGrey"],
        min_exposure=log2_params["minExposure"],
        max_exposure=log2_params["maxExposure"],
        aliases=log2_shaper_name_aliases,
    )
    colorspaces.append(log2_shaper_colorspace)

    shaper_input_scale_generic_log2 = 1

    # *Log 2* shaper name and *CTL* transforms bundled up.
    log2_shaper_data = [
        log2_shaper_name,
        os.path.join("%s", "utilities", "ACESlib.Log2_to_Lin_param.a1.0.0.ctl"),
        os.path.join("%s", "utilities", "ACESlib.Lin_to_Log2_param.a1.0.0.ctl"),
        shaper_input_scale_generic_log2,
        log2_params,
    ]

    shaper_data[log2_shaper_name] = log2_shaper_data

    # Space with a more user-friendly name. Direct copy otherwise.
    log2_shaper_copy_name = "Log2 Shaper"
    log2_shaper_copy_colorspace = ColorSpace(log2_shaper_copy_name)
    log2_shaper_copy_colorspace.description = "The %s color space" % log2_shaper_copy_name
    log2_shaper_copy_colorspace.aliases = ["crv_%s" % compact(log2_shaper_copy_name)]
    log2_shaper_copy_colorspace.equality_group = log2_shaper_copy_name
    log2_shaper_copy_colorspace.family = log2_shaper_colorspace.family
    log2_shaper_copy_colorspace.is_data = log2_shaper_colorspace.is_data
    log2_shaper_copy_colorspace.to_reference_transforms = list(log2_shaper_colorspace.to_reference_transforms)
    log2_shaper_copy_colorspace.from_reference_transforms = list(log2_shaper_colorspace.from_reference_transforms)
    colorspaces.append(log2_shaper_copy_colorspace)

    # Defining the *Log2 shaper that includes the AP1* primaries.
    log2_shaper_api1_name = "%s - AP1" % "Log2 Shaper"
    log2_shaper_api1_colorspace = ColorSpace(log2_shaper_api1_name)
    log2_shaper_api1_colorspace.description = "The %s color space" % log2_shaper_api1_name
    log2_shaper_api1_colorspace.aliases = ["%s_ap1" % compact(log2_shaper_copy_name)]
    log2_shaper_api1_colorspace.equality_group = log2_shaper_api1_name
    log2_shaper_api1_colorspace.family = log2_shaper_colorspace.family
    log2_shaper_api1_colorspace.is_data = log2_shaper_colorspace.is_data
    log2_shaper_api1_colorspace.to_reference_transforms = list(log2_shaper_colorspace.to_reference_transforms)
    log2_shaper_api1_colorspace.from_reference_transforms = list(log2_shaper_colorspace.from_reference_transforms)

    # *AP1* primaries to *AP0* primaries.
    log2_shaper_api1_colorspace.to_reference_transforms.append(
        {"type": "matrix", "matrix": mat44_from_mat33(ACES_AP1_TO_AP0), "direction": "forward"}
    )
    colorspaces.append(log2_shaper_api1_colorspace)

    # Defining the *Log2 shaper that includes the AP1* primaries.
    # Named with 'shaper_name' variable. Needed for some LUT baking steps.
    shaper_api1_name = "%s - AP1" % shaper_name
    shaper_api1_colorspace = ColorSpace(shaper_api1_name)
    shaper_api1_colorspace.description = "The %s color space" % shaper_api1_name
    shaper_api1_colorspace.aliases = ["%s_ap1" % compact(shaper_name)]
    shaper_api1_colorspace.equality_group = shaper_api1_name
    shaper_api1_colorspace.family = log2_shaper_colorspace.family
    shaper_api1_colorspace.is_data = log2_shaper_colorspace.is_data
    shaper_api1_colorspace.to_reference_transforms = list(log2_shaper_api1_colorspace.to_reference_transforms)
    shaper_api1_colorspace.from_reference_transforms = list(log2_shaper_api1_colorspace.from_reference_transforms)
    colorspaces.append(shaper_api1_colorspace)

    # Define the base *Dolby PQ Shaper*
    #
    dolbypq_shaper_name = "Dolby PQ 10000"
    dolbypq_shaper_name_aliases = ["crv_%s" % "dolbypq_10000"]

    dolbypq_shaper_colorspace = create_dolbypq(
        aces_ctl_directory,
        lut_directory,
        lut_resolution_1d,
        cleanup,
        name=dolbypq_shaper_name,
        aliases=dolbypq_shaper_name_aliases,
    )
    colorspaces.append(dolbypq_shaper_colorspace)

    # *Dolby PQ* shaper name and *CTL* transforms bundled up.
    dolbypq_shaper_data = [
        dolbypq_shaper_name,
        os.path.join("%s", "utilities", "ACESlib.DolbyPQ_to_Lin.a1.0.0.ctl"),
        os.path.join("%s", "utilities", "ACESlib.Lin_to_DolbyPQ.a1.0.0.ctl"),
        1.0,
        {},
    ]

    shaper_data[dolbypq_shaper_name] = dolbypq_shaper_data

    # Define the *Dolby PQ Shaper that considers a fixed linear range*
    #
    dolbypq_scaled_shaper_name = "Dolby PQ Scaled"
    dolbypq_scaled_shaper_name_aliases = ["crv_%s" % "dolbypq_scaled"]

    dolbypq_scaled_shaper_colorspace = create_dolbypq_scaled(
        aces_ctl_directory,
        lut_directory,
        lut_resolution_1d,
        cleanup,
        name=dolbypq_scaled_shaper_name,
        aliases=dolbypq_scaled_shaper_name_aliases,
    )
    colorspaces.append(dolbypq_scaled_shaper_colorspace)

    # *Dolby PQ* shaper name and *CTL* transforms bundled up.
    dolbypq_scaled_shaper_data = [
        dolbypq_scaled_shaper_name,
        os.path.join("%s", "utilities", "ACESlib.DolbyPQ_to_Lin_param.a1.0.0.ctl"),
        os.path.join("%s", "utilities", "ACESlib.Lin_to_DolbyPQ_param.a1.0.0.ctl"),
        1.0,
        log2_params,
    ]

    shaper_data[dolbypq_scaled_shaper_name] = dolbypq_scaled_shaper_data

    #
    # Pick a specific shaper
    #
    rrt_shaper = log2_shaper_data
    # rrt_shaper = dolbypq_scaled_shaper_data

    # *RRT + ODT* combinations.
    sorted_odts = sorted(odt_info.iteritems(), key=lambda x: x[1])
    print(sorted_odts)
    for odt in sorted_odts:
        (odt_name, odt_values) = odt

        # Generating only full range transform for *ODTs* that can generate
        # either *legal* or *full* output.

        # Uncomment these lines and the lower section and flip the 'legalRange' value to 1
        # to recover the old behavior, where both legal and full range LUTs were generated
        if odt_values["transformHasFullLegalSwitch"]:
            # odt_name_legal = '%s - Legal' % odt_values['transformUserName']
            odt_legal["legalRange"] = 0
        # else:
        #    odt_name_legal = odt_values['transformUserName']

        odt_name_legal = odt_values["transformUserName"]

        odt_legal = odt_values.copy()

        odt_aliases = ["out_%s" % compact(odt_name_legal)]

        cs = create_ACES_RRT_plus_ODT(
            odt_name_legal,
            odt_legal,
            rrt_shaper,
            aces_ctl_directory,
            lut_directory,
            lut_resolution_1d,
            lut_resolution_3d,
            cleanup,
            odt_aliases,
        )
        colorspaces.append(cs)

        displays[odt_name_legal] = {"Raw": linear_display_space, "Log": log_display_space, "Output Transform": cs}

        """
        # Generating full range transform for *ODTs* that can generate 
        # either *legal* or *full* output.
        if odt_values['transformHasFullLegalSwitch']:
            print('Generating full range ODT for %s' % odt_name)

            odt_name_full = '%s - Full' % odt_values['transformUserName']
            odt_full = odt_values.copy()
            odt_full['legalRange'] = 0

            odt_full_aliases = ["out_%s" % compact(odt_name_full)]

            cs_full = create_ACES_RRT_plus_ODT(
                odt_name_full,
                odt_full,
                rrt_shaper,
                aces_ctl_directory,
                lut_directory,
                lut_resolution_1d,
                lut_resolution_3d,
                cleanup,
                odt_full_aliases)
            colorspaces.append(cs_full)

            displays[odt_name_full] = {
                'Raw': linear_display_space,
                'Log': log_display_space,
                'Output Transform': cs_full}
        """

    return (colorspaces, displays)
def create_ACEScc(aces_ctl_directory,
                  lut_directory,
                  lut_resolution_1d,
                  cleanup,
                  name='ACEScc',
                  min_value=0,
                  max_value=1,
                  input_scale=1):
    """
    Creates the *ACEScc* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ACEScc* colorspace.
    """

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = ["acescc_ap1"]
    cs.equality_group = ''
    cs.family = 'ACES'
    cs.is_data = False
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [min_value, max_value]

    ctls = [os.path.join(aces_ctl_directory,
                         'ACEScc',
                         'ACEScsc.ACEScc_to_ACES.a1.0.0.ctl')]
    lut = '%s_to_linear.spi1d' % name

    lut = sanitize(lut)

    generate_1d_LUT_from_CTL(
        os.path.join(lut_directory, lut),
        ctls,
        lut_resolution_1d,
        'float',
        input_scale,
        1,
        {'transferFunctionOnly':1},
        cleanup,
        aces_ctl_directory,
        min_value,
        max_value,
        1)

    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    # *AP1* primaries to *AP0* primaries.
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
Beispiel #26
0
def create_matrix_plus_gamma_colorspace(name='matrix_plus_gamma',
                                        gamma_value=1.0,
                                        from_reference_values=None,
                                        to_reference_values=None,
                                        aliases=None):
    """
    Creates a colorspace expressed as a single or multiple *MatrixTransform*
    and an *ExponentTransform* transformations.

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace.
    gamma_value : function, optional
        The gamma value.
    from_reference_values : list of matrices
        List of matrices to convert from the reference colorspace to this
        colorspace.
    to_reference_values : list of matrices
        List of matrices to convert to the reference colorspace from this
        colorspace.
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
        A colorspace expressed as a single or multiple *MatrixTransform* and an
        *ExponentTransform* transformations.
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The {0} color space'.format(name)
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    # Creating the *to_reference* transforms.
    cs.to_reference_transforms = []
    if to_reference_values:
        cs.to_reference_transforms.append({
            'type':
            'exponent',
            'value': [gamma_value, gamma_value, gamma_value, 1]
        })

        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

    # Creating the *from_reference* transforms.
    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

        cs.from_reference_transforms.append({
            'type':
            'exponent',
            'value':
            [1.0 / gamma_value, 1.0 / gamma_value, 1.0 / gamma_value, 1]
        })

    return cs
Beispiel #27
0
def create_ACES_LMT(
    lmt_name,
    lmt_values,
    shaper_info,
    aces_ctl_directory,
    lut_directory,
    lut_resolution_1d=1024,
    lut_resolution_3d=64,
    cleanup=True,
    aliases=None,
):
    """
    Creates the *ACES LMT* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ACES LMT* colorspace.
    """

    if aliases is None:
        aliases = []

    cs = ColorSpace("%s" % lmt_name)
    cs.description = "The ACES Look Transform: %s" % lmt_name
    cs.aliases = aliases
    cs.equality_group = ""
    cs.family = "Look"
    cs.is_data = False
    cs.allocation_type = ocio.Constants.ALLOCATION_LG2
    cs.allocation_vars = [-8, 5, 0.00390625]
    cs.aces_transform_id = lmt_values["transformID"]

    pprint.pprint(lmt_values)

    # Generating the *shaper* transform.
    (shaper_name, shaper_to_ACES_CTL, shaper_from_ACES_CTL, shaper_input_scale, shaper_params) = shaper_info

    # Add the shaper transform
    shaper_lut = "%s_to_linear.spi1d" % shaper_name
    shaper_lut = sanitize(shaper_lut)

    shaper_OCIO_transform = {"type": "lutFile", "path": shaper_lut, "interpolation": "linear", "direction": "inverse"}

    # Generating the forward transform.
    cs.from_reference_transforms = []

    if "transformCTL" in lmt_values:
        ctls = [shaper_to_ACES_CTL % aces_ctl_directory, os.path.join(aces_ctl_directory, lmt_values["transformCTL"])]
        lut = "%s.%s.spi3d" % (shaper_name, lmt_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            ctls,
            lut_resolution_3d,
            "float",
            1 / shaper_input_scale,
            1,
            shaper_params,
            cleanup,
            aces_ctl_directory,
        )

        cs.from_reference_transforms.append(shaper_OCIO_transform)
        cs.from_reference_transforms.append(
            {"type": "lutFile", "path": lut, "interpolation": "tetrahedral", "direction": "forward"}
        )

    # Generating the inverse transform.
    cs.to_reference_transforms = []

    if "transformCTLInverse" in lmt_values:
        ctls = [
            os.path.join(aces_ctl_directory, lmt_values["transformCTLInverse"]),
            shaper_from_ACES_CTL % aces_ctl_directory,
        ]
        lut = "Inverse.%s.%s.spi3d" % (odt_name, shaper_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            ctls,
            lut_resolution_3d,
            "half",
            1,
            shaper_input_scale,
            shaper_params,
            cleanup,
            aces_ctl_directory,
            0,
            1,
            1,
        )

        cs.to_reference_transforms.append(
            {"type": "lutFile", "path": lut, "interpolation": "tetrahedral", "direction": "forward"}
        )

        shaper_inverse = shaper_OCIO_transform.copy()
        shaper_inverse["direction"] = "forward"
        cs.to_reference_transforms.append(shaper_inverse)

    return cs
Beispiel #28
0
def create_gamma_colorspace(name='gamma', gamma_value=1.0, aliases=None):
    """
    Creates a colorspace expressed as an *ExponentTransform* transformation.

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace.
    gamma_value : function, optional
        The gamma value.
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
         A colorspace expressed as an *ExponentTransform* transformation.
    """

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The {0} color space'.format(name)
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    # Creating the *to_reference* transforms.
    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type':
        'exponent',
        'value': [gamma_value, gamma_value, gamma_value, 1]
    })

    # Creating the *from_reference* transforms.
    cs.from_reference_transforms = []

    return cs
Beispiel #29
0
def create_s_log(gamut,
                 transfer_function,
                 lut_directory,
                 lut_resolution_1d,
                 aliases):
    """
    Creates colorspace covering the conversion from Sony spaces to ACES, with various 
    transfer functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.
    """

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Sony'
    cs.is_data = False

    if gamut and transfer_function:
        cs.aces_transform_id = 'IDT.Sony.%s_%s_10i.a1.v1' % (
            transfer_function.replace('-', ''),
            gamut.replace('-', '').replace(' ', '_'))

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def s_log1_to_linear(s_log):
        b = 64.
        ab = 90.
        w = 940.

        if s_log >= ab:
            linear = ((pow(10.,
                           (((s_log - b) /
                             (w - b) - 0.616596 - 0.03) / 0.432699)) -
                       0.037584) * 0.9)
        else:
            linear = (((s_log - b) / (
                w - b) - 0.030001222851889303) / 5.) * 0.9
        return linear

    def s_log2_to_linear(s_log):
        b = 64.
        ab = 90.
        w = 940.

        if s_log >= ab:
            linear = ((219. * (pow(10.,
                                   (((s_log - b) /
                                     (w - b) - 0.616596 - 0.03) / 0.432699)) -
                               0.037584) / 155.) * 0.9)
        else:
            linear = (((s_log - b) / (
                w - b) - 0.030001222851889303) / 3.53881278538813) * 0.9
        return linear

    def s_log3_to_linear(code_value):
        if code_value >= 171.2102946929:
            linear = (pow(10, ((code_value - 420) / 261.5)) *
                      (0.18 + 0.01) - 0.01)
        else:
            linear = (code_value - 95) * 0.01125000 / (171.2102946929 - 95)

        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'S-Log1':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = s_log1_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})
    elif transfer_function == 'S-Log2':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = s_log2_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})
    elif transfer_function == 'S-Log3':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = s_log3_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'S-Gamut':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33(
                [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.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33(
                [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.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33(
                [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.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33(
                [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.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': mat44_from_mat33(
                [0.7529825954, 0.1433702162, 0.1036471884,
                 0.0217076974, 1.0153188355, -0.0370265329,
                 -0.0094160528, 0.0033704179, 1.0060456349]),
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_c_log(gamut,
                 transfer_function,
                 lut_directory,
                 lut_resolution_1d,
                 aliases):
    """
    Creates colorspace covering the conversion from CLog to ACES, with various transfer 
    functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.    
    """

    name = '%s - %s' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - Canon %s' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/Canon'
    cs.is_data = False

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def legal_to_full(code_value):
        return (code_value - 64) / (940 - 64)

    def c_log_to_linear(code_value):
        # 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, (legal_to_full(code_value) - c3) / c1) - 1) / c2
        linear *= 0.9

        return linear

    def c_log2_to_linear(code_value):
        # log = fullToLegal(c1 * log10(c2*linear + 1) + c3)
        # linear = (pow(10, (legalToFul(log) - c3)/c1) - 1)/c2
        c1 = 0.281863093
        c2 = 87.09937546
        c3 = 0.035388128

        linear = (pow(10, (legal_to_full(code_value) - c3) / c1) - 1) / c2
        linear *= 0.9

        return linear

    cs.to_reference_transforms = []

    if transfer_function:
        if transfer_function == 'Canon-Log':
            data = array.array('f', '\0' * lut_resolution_1d * 4)
            for c in range(lut_resolution_1d):
                data[c] = c_log_to_linear(1023 * c / (lut_resolution_1d - 1))
        elif transfer_function == 'Canon-Log2':
            data = array.array('f', '\0' * lut_resolution_1d * 4)
            for c in range(lut_resolution_1d):
                data[c] = c_log2_to_linear(1023 * c / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'Rec. 709 Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.561538969, 0.402060105, 0.036400926, 0,
                       0.092739623, 0.924121198, -0.016860821, 0,
                       0.084812961, 0.006373835, 0.908813204, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Rec. 709 Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.566996399, 0.365079418, 0.067924183, 0,
                       0.070901044, 0.880331008, 0.048767948, 0,
                       0.073013542, -0.066540862, 0.99352732, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'DCI-P3 Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.607160575, 0.299507286, 0.093332140, 0,
                       0.004968120, 1.050982224, -0.055950343, 0,
                       -0.007839939, 0.000809127, 1.007030813, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'DCI-P3 Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.650279125, 0.253880169, 0.095840706, 0,
                       -0.026137986, 1.017900530, 0.008237456, 0,
                       0.007757558, -0.063081669, 1.055324110, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Cinema Gamut Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.763064455, 0.149021161, 0.087914384, 0,
                       0.003657457, 1.10696038, -0.110617837, 0,
                       -0.009407794, -0.218383305, 1.227791099, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Cinema Gamut Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.817416293, 0.090755698, 0.091828009, 0,
                       -0.035361374, 1.065690585, -0.030329211, 0,
                       0.010390366, -0.299271107, 1.288880741, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Rec. 2020 Daylight':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.678891151, 0.158868422, 0.162240427, 0,
                       0.045570831, 0.860712772, 0.093716397, 0,
                       -0.000485710, 0.025060196, 0.975425515, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})
    elif gamut == 'Rec. 2020 Tungsten':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.724488568, 0.115140904, 0.160370529, 0,
                       0.010659276, 0.839605344, 0.149735380, 0,
                       0.014560161, 0.028562057, 1.014001897, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
Beispiel #31
0
def create_REDLog_film(gamut,
                       transfer_function,
                       lut_directory,
                       lut_resolution_1D,
                       aliases=None):
    """
    Creates colorspace covering the conversion from *RED* spaces to *ACES*,
    with various transfer functions and encoding gamuts covered.

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use.
    lut_directory : str or unicode 
        The directory to use when generating LUTs.
    lut_resolution_1D : int
        The resolution of generated 1D LUTs.
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and
         identifying information for the requested colorspace.
    """

    if aliases is None:
        aliases = []

    name = '{0} - {1}'.format(transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - {0}'.format(gamut)
    if gamut == '':
        name = 'Curve - {0}'.format(transfer_function)

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/RED'
    cs.is_data = False

    # A linear space needs allocation variables
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def Cineon_to_linear(code_value):
        n_gamma = 0.6
        black_point = 95
        white_point = 685
        code_value_to_density = 0.002

        black_linear = pow(10, (black_point - white_point) *
                           (code_value_to_density / n_gamma))
        code_linear = pow(10, (code_value - white_point) *
                          (code_value_to_density / n_gamma))

        return (code_linear - black_linear) / (1 - black_linear)

    def Log3G10_to_linear(code_value):
        a = 0.224282
        b = 155.975327
        c = 0.01

        normalized_log = code_value / 1023.0

        mirror = 1.0
        if normalized_log < 0.0:
            mirror = -1.0
            normalized_log = -normalized_log

        linear = (pow(10.0, normalized_log / a) - 1) / b
        linear = linear * mirror - c

        return linear

    cs.to_reference_transforms = []

    if transfer_function:
        if transfer_function == 'REDlogFilm':
            lut_name = "CineonLog"
            data = array.array('f', b'\0' * lut_resolution_1D * 4)
            for c in range(lut_resolution_1D):
                data[c] = Cineon_to_linear(1023 * c / (lut_resolution_1D - 1))
        elif transfer_function == 'REDLog3G10':
            lut_name = "REDLog3G10"
            data = array.array('f', b'\0' * lut_resolution_1D * 4)
            for c in range(lut_resolution_1D):
                data[c] = Log3G10_to_linear(1023 * c / (lut_resolution_1D - 1))

        lut = '{0}_to_linear.spi1d'.format(lut_name)
        genlut.write_SPI_1D(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1D, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'DRAGONcolor':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.532279, 0.376648, 0.091073, 0.046344, 0.974513, -0.020860,
                -0.053976, -0.000320, 1.054267
            ]),
            'direction':
            'forward'
        })
    elif gamut == 'DRAGONcolor2':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.468452, 0.331484, 0.200064, 0.040787, 0.857658, 0.101553,
                -0.047504, -0.000282, 1.047756
            ]),
            'direction':
            'forward'
        })
    elif gamut == 'REDcolor':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.451464, 0.388498, 0.160038, 0.062716, 0.866790, 0.070491,
                -0.017541, 0.086921, 0.930590
            ]),
            'direction':
            'forward'
        })
    elif gamut == 'REDcolor2':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.480997, 0.402289, 0.116714, -0.004938, 1.000154, 0.004781,
                -0.105257, 0.025320, 1.079907
            ]),
            'direction':
            'forward'
        })
    elif gamut == 'REDcolor3':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.512136, 0.360370, 0.127494, 0.070377, 0.903884, 0.025737,
                -0.020824, 0.017671, 1.003123
            ]),
            'direction':
            'forward'
        })
    elif gamut == 'REDcolor4':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.474202, 0.333677, 0.192121, 0.065164, 0.836932, 0.097901,
                -0.019281, 0.016362, 1.002889
            ]),
            'direction':
            'forward'
        })
    elif gamut == 'REDWideGamutRGB':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.785043, 0.083844, 0.131118, 0.023172, 1.087892, -0.111055,
                -0.073769, -0.314639, 1.388537
            ]),
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs
Beispiel #32
0
def create_protune(gamut,
                   transfer_function,
                   lut_directory,
                   lut_resolution_1d,
                   aliases):
    """
    Creates colorspace covering the conversion from ProTune to ACES, with various transfer 
    functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.
    """

    # The gamut should be marked as experimental until  matrices are fully
    # verified.
    name = '%s - %s - Experimental' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s - Experimental' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/GoPro'
    cs.is_data = False

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def protune_to_linear(normalized_code_value):
        c1 = 113.0
        c2 = 1.0
        c3 = 112.0
        linear = ((pow(c1, normalized_code_value) - c2) / c3)

        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'Protune Flat':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = protune_to_linear(float(c) / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        lut = sanitize(lut)
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'Protune Native':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.533448429, 0.32413911, 0.142412421, 0,
                       -0.050729924, 1.07572006, -0.024990416, 0,
                       0.071419661, -0.290521962, 1.219102381, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_ODTs(aces_ctl_directory,
                lut_directory,
                lut_resolution_1d,
                lut_resolution_3d,
                odt_info,
                shaper_name,
                cleanup,
                linear_display_space,
                log_display_space):
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    colorspaces = []
    displays = {}

    # -------------------------------------------------------------------------
    # *RRT / ODT* Shaper Options
    # -------------------------------------------------------------------------
    shaper_data = {}

    # Defining the *Log 2* shaper.
    log2_shaper_name = shaper_name
    log2_shaper_name_aliases = ['crv_%s' % compact(log2_shaper_name)]
    log2_params = {
        'middleGrey': 0.18,
        'minExposure': -6,
        'maxExposure': 6.5}

    log2_shaper_colorspace = create_generic_log(
        aces_ctl_directory,
        lut_directory,
        lut_resolution_1d,
        cleanup,
        name=log2_shaper_name,
        middle_grey=log2_params['middleGrey'],
        min_exposure=log2_params['minExposure'],
        max_exposure=log2_params['maxExposure'],
        aliases=log2_shaper_name_aliases)
    colorspaces.append(log2_shaper_colorspace)

    shaper_input_scale_generic_log2 = 1

    # *Log 2* shaper name and *CTL* transforms bundled up.
    log2_shaper_data = [
        log2_shaper_name,
        os.path.join('%s',
                     'utilities',
                     'ACESlib.Log2_to_Lin_param.a1.0.0.ctl'),
        os.path.join('%s',
                     'utilities',
                     'ACESlib.Lin_to_Log2_param.a1.0.0.ctl'),
        shaper_input_scale_generic_log2,
        log2_params]

    shaper_data[log2_shaper_name] = log2_shaper_data

    # Space with a more user-friendly name. Direct copy otherwise.
    log2_shaper_copy_name = 'Log2 Shaper'
    log2_shaper_copy_colorspace = ColorSpace(log2_shaper_copy_name)
    log2_shaper_copy_colorspace.description = (
        'The %s color space' % log2_shaper_copy_name)
    log2_shaper_copy_colorspace.aliases = [
        'crv_%s' % compact(log2_shaper_copy_name)]
    log2_shaper_copy_colorspace.equality_group = log2_shaper_copy_name
    log2_shaper_copy_colorspace.family = log2_shaper_colorspace.family
    log2_shaper_copy_colorspace.is_data = log2_shaper_colorspace.is_data
    log2_shaper_copy_colorspace.to_reference_transforms = list(
        log2_shaper_colorspace.to_reference_transforms)
    log2_shaper_copy_colorspace.from_reference_transforms = list(
        log2_shaper_colorspace.from_reference_transforms)
    colorspaces.append(log2_shaper_copy_colorspace)

    # Defining the *Log2 shaper that includes the AP1* primaries.
    log2_shaper_api1_name = '%s - AP1' % 'Log2 Shaper'
    log2_shaper_api1_colorspace = ColorSpace(log2_shaper_api1_name)
    log2_shaper_api1_colorspace.description = (
        'The %s color space' % log2_shaper_api1_name)
    log2_shaper_api1_colorspace.aliases = [
        '%s_ap1' % compact(log2_shaper_copy_name)]
    log2_shaper_api1_colorspace.equality_group = log2_shaper_api1_name
    log2_shaper_api1_colorspace.family = log2_shaper_colorspace.family
    log2_shaper_api1_colorspace.is_data = log2_shaper_colorspace.is_data
    log2_shaper_api1_colorspace.to_reference_transforms = list(
        log2_shaper_colorspace.to_reference_transforms)
    log2_shaper_api1_colorspace.from_reference_transforms = list(
        log2_shaper_colorspace.from_reference_transforms)

    # *AP1* primaries to *AP0* primaries
    log2_shaper_api1_colorspace.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
        'direction': 'forward'
    })
    colorspaces.append(log2_shaper_api1_colorspace)

    # Defining the *Log2* shaper that includes the *AP1* primaries.
    # Named with `shaper_name` variable and needed for some *LUT* baking steps.
    shaper_api1_name = '%s - AP1' % shaper_name
    shaper_api1_colorspace = ColorSpace(shaper_api1_name)
    shaper_api1_colorspace.description = (
        'The %s color space' % shaper_api1_name)
    shaper_api1_colorspace.aliases = ['%s_ap1' % compact(shaper_name)]
    shaper_api1_colorspace.equality_group = shaper_api1_name
    shaper_api1_colorspace.family = log2_shaper_colorspace.family
    shaper_api1_colorspace.is_data = log2_shaper_colorspace.is_data
    shaper_api1_colorspace.to_reference_transforms = list(
        log2_shaper_api1_colorspace.to_reference_transforms)
    shaper_api1_colorspace.from_reference_transforms = list(
        log2_shaper_api1_colorspace.from_reference_transforms)
    colorspaces.append(shaper_api1_colorspace)

    # Define the base *Dolby PQ Shaper*
    #
    dolby_pq_shaper_name = 'Dolby PQ 10000'
    dolby_pq_shaper_name_aliases = ['crv_%s' % 'dolbypq_10000']

    dolby_pq_shaper_colorspace = create_Dolby_PQ(
        aces_ctl_directory,
        lut_directory,
        lut_resolution_1d,
        cleanup,
        name=dolby_pq_shaper_name,
        aliases=dolby_pq_shaper_name_aliases)
    colorspaces.append(dolby_pq_shaper_colorspace)

    # *Dolby PQ* shaper name and *CTL* transforms bundled up.
    dolby_pq_shaper_data = [
        dolby_pq_shaper_name,
        os.path.join('%s',
                     'utilities',
                     'ACESlib.DolbyPQ_to_Lin.a1.0.0.ctl'),
        os.path.join('%s',
                     'utilities',
                     'ACESlib.Lin_to_DolbyPQ.a1.0.0.ctl'),
        1.0,
        {}]

    shaper_data[dolby_pq_shaper_name] = dolby_pq_shaper_data

    # Define the *Dolby PQ Shaper that considers a fixed linear range*
    dolby_pq_scaled_shaper_name = 'Dolby PQ Scaled'
    dolby_pq_scaled_shaper_name_aliases = ['crv_%s' % 'dolbypq_scaled']

    dolby_pq_scaled_shaper_colorspace = create_Dolby_PQ_scaled(
        aces_ctl_directory,
        lut_directory,
        lut_resolution_1d,
        cleanup,
        name=dolby_pq_scaled_shaper_name,
        aliases=dolby_pq_scaled_shaper_name_aliases)
    colorspaces.append(dolby_pq_scaled_shaper_colorspace)

    # *Dolby PQ* shaper name and *CTL* transforms bundled up.
    dolby_pq_scaled_shaper_data = [
        dolby_pq_scaled_shaper_name,
        os.path.join('%s',
                     'utilities',
                     'ACESlib.OCIOShaper_to_Lin_param.a1.0.0.ctl'),
        os.path.join('%s',
                     'utilities',
                     'ACESlib.Lin_to_OCIOShaper_param.a1.0.0.ctl'),
        1.0,
        log2_params]

    shaper_data[dolby_pq_scaled_shaper_name] = dolby_pq_scaled_shaper_data

    rrt_shaper = log2_shaper_data
    # rrt_shaper = dolby_pq_scaled_shaper_data

    # *RRT + ODT* combinations.
    sorted_odts = sorted(odt_info.iteritems(), key=lambda x: x[1])
    print(sorted_odts)
    for odt in sorted_odts:
        (odt_name, odt_values) = odt

        # Defining full range transform for *ODTs* that can generate either
        # *legal* or *full* output.

        # Uncomment these lines and the lower section and
        # flip the `legalRange` value to 1 to restore the old behavior,
        # where both *legal* or *full* range *LUTs* were generated.
        if odt_values['transformHasFullLegalSwitch']:
            # odt_name_legal = '%s - Legal' % odt_values['transformUserName']
            odt_legal['legalRange'] = 0
        # else:
        #    odt_name_legal = odt_values['transformUserName']

        odt_name_legal = odt_values['transformUserName']

        odt_legal = odt_values.copy()

        odt_aliases = ['out_%s' % compact(odt_name_legal)]

        cs = create_ACES_RRT_plus_ODT(
            odt_name_legal,
            odt_legal,
            rrt_shaper,
            aces_ctl_directory,
            lut_directory,
            lut_resolution_3d,
            cleanup,
            odt_aliases)
        colorspaces.append(cs)

        displays[odt_name_legal] = {
            'Raw': linear_display_space,
            'Log': log_display_space,
            'Output Transform': cs}

        """
        # Generating full range transform for *ODTs* that can generate 
        # either *legal* or *full* output.
        if odt_values['transformHasFullLegalSwitch']:
            print('Generating full range ODT for %s' % odt_name)

            odt_name_full = '%s - Full' % odt_values['transformUserName']
            odt_full = odt_values.copy()
            odt_full['legalRange'] = 0

            odt_full_aliases = ['out_%s' % compact(odt_name_full)]

            cs_full = create_ACES_RRT_plus_ODT(
                odt_name_full,
                odt_full,
                rrt_shaper,
                aces_ctl_directory,
                lut_directory,
                lut_resolution_1d,
                lut_resolution_3d,
                cleanup,
                odt_full_aliases)
            colorspaces.append(cs_full)

            displays[odt_name_full] = {
                'Raw': linear_display_space,
                'Log': log_display_space,
                'Output Transform': cs_full}
        """

    return colorspaces, displays
Beispiel #34
0
def create_matrix_plus_transfer_colorspace(
        name='matrix_plus_transfer',
        transfer_function_name='transfer_function',
        transfer_function=lambda x: x,
        lut_directory='/tmp',
        lut_resolution_1D=1024,
        from_reference_values=None,
        to_reference_values=None,
        aliases=None):
    """
    Creates a colorspace expressed as a single or multiple *MatrixTransform*
    and 1D LUT *FileTransform* transformations.

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace.
    transfer_function_name : str, optional
        The name of the transfer function.
    transfer_function : function, optional
        The transfer function to be evaluated.
    lut_directory : str or unicode 
        The directory to use when generating LUTs.
    lut_resolution_1D : int
        The resolution of generated 1D LUTs.
    from_reference_values : list of matrices
        List of matrices to convert from the reference colorspace to this
        colorspace.
    to_reference_values : list of matrices
        List of matrices to convert to the reference colorspace from this
        colorspace.
    aliases : list of str
        Aliases for this colorspace.

    Returns
    -------
    ColorSpace
         A colorspace expressed as a single or multiple *MatrixTransform* and
         1D LUT *FileTransform* transformations.
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The {0} color space'.format(name)
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    # Sampling the transfer function.
    data = array.array('f', b'\0' * lut_resolution_1D * 4)
    for c in range(lut_resolution_1D):
        data[c] = transfer_function(c / (lut_resolution_1D - 1))

    # Writing the sampled data to a *LUT*.
    lut = 'linear_to_{0}.spi1d'.format(transfer_function_name)
    genlut.write_SPI_1D(os.path.join(lut_directory, lut), 0, 1, data,
                        lut_resolution_1D, 1)

    # Creating the *to_reference* transforms.
    cs.to_reference_transforms = []
    if to_reference_values:
        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'inverse'
        })

        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

    # Creating the *from_reference* transforms.
    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type':
                'matrix',
                'matrix':
                mat44_from_mat33(matrix),
                'direction':
                'forward'
            })

        cs.from_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    return cs
def create_ACESproxy(aces_ctl_directory,
                     lut_directory,
                     lut_resolution_1d,
                     cleanup,
                     name='ACESproxy'):
    """
    Creates the *ACESproxy* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ACESproxy* colorspace.
    """

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = ['acesproxy', 'acesproxy_ap1']
    cs.equality_group = ''
    cs.family = 'ACES'
    cs.is_data = False

    cs.aces_transform_id = 'ACEScsc.ACESproxy10i_to_ACES.a1.0.0'

    ctls = [os.path.join(aces_ctl_directory,
                         'ACESproxy',
                         'ACEScsc.ACESproxy10i_to_ACES.a1.0.0.ctl'),
            # This transform gets back to the *AP1* primaries.
            # Useful as the 1d LUT is only covering the transfer function.
            # The primaries switch is covered by the matrix below:
            os.path.join(aces_ctl_directory,
                         'ACEScg',
                         'ACEScsc.ACES_to_ACEScg.a1.0.0.ctl')]
    lut = '%s_to_linear.spi1d' % name

    lut = sanitize(lut)

    generate_1d_LUT_from_CTL(
        os.path.join(lut_directory, lut),
        ctls,
        lut_resolution_1d,
        'float',
        1,
        1,
        {},
        cleanup,
        aces_ctl_directory,
        0,
        1,
        1)

    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    # *AP1* primaries to *AP0* primaries
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_protune(gamut, transfer_function, lut_directory, lut_resolution_1d,
                   aliases):
    """
    Creates colorspace covering the conversion from ProTune to ACES, with various transfer 
    functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.
    """

    # The gamut should be marked as experimental until  matrices are fully
    # verified.
    name = '%s - %s - Experimental' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s - Experimental' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/GoPro'
    cs.is_data = False

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def protune_to_linear(normalized_code_value):
        c1 = 113.0
        c2 = 1.0
        c3 = 112.0
        linear = ((pow(c1, normalized_code_value) - c2) / c3)

        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'Protune Flat':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = protune_to_linear(float(c) / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        lut = sanitize(lut)
        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'Protune Native':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix': [
                0.533448429, 0.32413911, 0.142412421, 0, -0.050729924,
                1.07572006, -0.024990416, 0, 0.071419661, -0.290521962,
                1.219102381, 0, 0, 0, 0, 1
            ],
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs
def create_ACEScg():
    """
    Creates the *ACEScg* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ACEScg* colorspace.
    """

    name = 'ACEScg'

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = ['acescg', 'lin_ap1']
    cs.equality_group = ''
    cs.family = 'ACES'
    cs.is_data = False
    cs.allocation_type = ocio.Constants.ALLOCATION_LG2
    cs.allocation_vars = [-8, 5, 0.00390625]

    cs.aces_transform_id = 'ACEScsc.ACEScg_to_ACES.a1.0.0'

    cs.to_reference_transforms = []

    # *AP1* primaries to *AP0* primaries
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
        'direction': 'forward'})

    cs.from_reference_transforms = []

    # *AP1* primaries to *AP0* primaries
    cs.from_reference_transforms.append({
        'type': 'matrix',
        'matrix': mat44_from_mat33(ACES_AP0_TO_AP1),
        'direction': 'forward'})

    return cs
def create_matrix_plus_transfer_colorspace(
        name='matrix_plus_transfer',
        transfer_function_name='transfer_function',
        transfer_function=lambda x: x,
        lut_directory='/tmp',
        lut_resolution_1d=1024,
        from_reference_values=None,
        to_reference_values=None,
        aliases=None):
    """
    Creates a ColorSpace that uses transfer functions encoded as 1D LUTs and
    matrice

    Parameters
    ----------
    name : str, optional
        Aliases for this colorspace
    transfer_function_name : str, optional
        The name of the transfer function
    transfer_function : function, optional
        The transfer function to be evaluated
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    from_reference_values : list of matrices
        List of matrices to convert from the reference colorspace to this space        
    to_reference_values : list of matrices
        List of matrices to convert to the reference colorspace from this space
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A *Matrx and LUT1D Transform*-based ColorSpace representing a transfer 
         function and matrix
    """

    if from_reference_values is None:
        from_reference_values = []

    if to_reference_values is None:
        to_reference_values = []

    if aliases is None:
        aliases = []

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    # A linear space needs allocation variables.
    cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
    cs.allocation_vars = [0, 1]

    # Sampling the transfer function.
    data = array.array('f', '\0' * lut_resolution_1d * 4)
    for c in range(lut_resolution_1d):
        data[c] = transfer_function(c / (lut_resolution_1d - 1))

    # Writing the sampled data to a *LUT*.
    lut = '%s_to_linear.spi1d' % transfer_function_name
    genlut.write_SPI_1d(
        os.path.join(lut_directory, lut),
        0,
        1,
        data,
        lut_resolution_1d,
        1)

    # Creating the *to_reference* transforms.
    cs.to_reference_transforms = []
    if to_reference_values:
        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

        for matrix in to_reference_values:
            cs.to_reference_transforms.append({
                'type': 'matrix',
                'matrix': mat44_from_mat33(matrix),
                'direction': 'forward'})

    # Creating the *from_reference* transforms.
    cs.from_reference_transforms = []
    if from_reference_values:
        for matrix in from_reference_values:
            cs.from_reference_transforms.append({
                'type': 'matrix',
                'matrix': mat44_from_mat33(matrix),
                'direction': 'forward'})

        cs.from_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'inverse'})

    return cs
def create_ADX(lut_directory,
               bit_depth=10,
               name='ADX'):
    """
    Creates the *ADX* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *ADX* colorspace.
    """

    name = '%s%s' % (name, bit_depth)
    cs = ColorSpace(name)
    cs.description = '%s color space - used for film scans' % name
    cs.aliases = ['adx%s' % str(bit_depth)]
    cs.equality_group = ''
    cs.family = 'ADX'
    cs.is_data = False

    if bit_depth == 10:
        cs.aces_transform_id = 'ACEScsc.ADX10_to_ACES.a1.0.0'

        cs.bit_depth = ocio.Constants.BIT_DEPTH_UINT10
        ADX_to_CDD = [1023 / 500, 0, 0, 0,
                      0, 1023 / 500, 0, 0,
                      0, 0, 1023 / 500, 0,
                      0, 0, 0, 1]
        offset = [-95 / 500, -95 / 500, -95 / 500, 0]
    elif bit_depth == 16:
        cs.aces_transform_id = 'ACEScsc.ADX16_to_ACES.a1.0.0'

        cs.bit_depth = ocio.Constants.BIT_DEPTH_UINT16
        ADX_to_CDD = [65535 / 8000, 0, 0, 0,
                      0, 65535 / 8000, 0, 0,
                      0, 0, 65535 / 8000, 0,
                      0, 0, 0, 1]
        offset = [-1520 / 8000, -1520 / 8000, -1520 / 8000, 0]

    cs.to_reference_transforms = []

    # Converting from *ADX* to *Channel-Dependent Density*.
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': ADX_to_CDD,
        'offset': offset,
        'direction': 'forward'})

    # Converting from *Channel-Dependent Density* to
    # *Channel-Independent Density*.
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': [0.75573, 0.22197, 0.02230, 0,
                   0.05901, 0.96928, -0.02829, 0,
                   0.16134, 0.07406, 0.76460, 0,
                   0, 0, 0, 1],
        'direction': 'forward'})

    # Copied from *Alex Fry*'s *adx_cid_to_rle.py*
    def create_CID_to_RLE_LUT():

        def interpolate_1d(x, xp, fp):
            return numpy.interp(x, xp, fp)

        LUT_1D_XP = [-0.190000000000000,
                     0.010000000000000,
                     0.028000000000000,
                     0.054000000000000,
                     0.095000000000000,
                     0.145000000000000,
                     0.220000000000000,
                     0.300000000000000,
                     0.400000000000000,
                     0.500000000000000,
                     0.600000000000000]

        LUT_1D_FP = [-6.000000000000000,
                     -2.721718645000000,
                     -2.521718645000000,
                     -2.321718645000000,
                     -2.121718645000000,
                     -1.921718645000000,
                     -1.721718645000000,
                     -1.521718645000000,
                     -1.321718645000000,
                     -1.121718645000000,
                     -0.926545676714876]

        REF_PT = ((7120 - 1520) / 8000 * (100 / 55) -
                  math.log(0.18, 10))

        def cid_to_rle(x):
            if x <= 0.6:
                return interpolate_1d(x, LUT_1D_XP, LUT_1D_FP)
            return (100 / 55) * x - REF_PT

        def fit(value, from_min, from_max, to_min, to_max):
            if from_min == from_max:
                raise ValueError('from_min == from_max')
            return (value - from_min) / (from_max - from_min) * (
                to_max - to_min) + to_min

        num_samples = 2 ** 12
        domain = (-0.19, 3)
        data = []
        for i in xrange(num_samples):
            x = i / (num_samples - 1)
            x = fit(x, 0, 1, domain[0], domain[1])
            data.append(cid_to_rle(x))

        lut = 'ADX_CID_to_RLE.spi1d'
        write_SPI_1d(os.path.join(lut_directory, lut),
                     domain[0],
                     domain[1],
                     data,
                     num_samples, 1)

        return lut

    # Converting *Channel Independent Density* values to
    # *Relative Log Exposure* values.
    lut = create_CID_to_RLE_LUT()
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    # Converting *Relative Log Exposure* values to
    # *Relative Exposure* values.
    cs.to_reference_transforms.append({
        'type': 'log',
        'base': 10,
        'direction': 'inverse'})

    # Convert *Relative Exposure* values to *ACES* values.
    cs.to_reference_transforms.append({
        'type': 'matrix',
        'matrix': [0.72286, 0.12630, 0.15084, 0,
                   0.11923, 0.76418, 0.11659, 0,
                   0.01427, 0.08213, 0.90359, 0,
                   0, 0, 0, 1],
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
def create_generic_log(aces_ctl_directory,
                       lut_directory,
                       lut_resolution_1d,
                       cleanup,
                       name='log',
                       aliases=[],
                       min_value=0,
                       max_value=1,
                       input_scale=1,
                       middle_grey=0.18,
                       min_exposure=-6,
                       max_exposure=6.5):
    """
    Creates the *Generic Log* colorspace.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    Colorspace
         *Generic Log* colorspace.
    """

    cs = ColorSpace(name)
    cs.description = 'The %s color space' % name
    cs.aliases = aliases
    cs.equality_group = name
    cs.family = 'Utility'
    cs.is_data = False

    ctls = [os.path.join(
        aces_ctl_directory,
        'utilities',
        'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl')]
    lut = '%s_to_linear.spi1d' % name

    lut = sanitize(lut)

    generate_1d_LUT_from_CTL(
        os.path.join(lut_directory, lut),
        ctls,
        lut_resolution_1d,
        'float',
        input_scale,
        1,
        {'middleGrey': middle_grey,
         'minExposure': min_exposure,
         'maxExposure': max_exposure},
        cleanup,
        aces_ctl_directory,
        min_value,
        max_value,
        1)

    cs.to_reference_transforms = []
    cs.to_reference_transforms.append({
        'type': 'lutFile',
        'path': lut,
        'interpolation': 'linear',
        'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
Beispiel #41
0
def create_ACES_RRT_plus_ODT(
    odt_name,
    odt_values,
    shaper_info,
    aces_ctl_directory,
    lut_directory,
    lut_resolution_1d=1024,
    lut_resolution_3d=64,
    cleanup=True,
    aliases=None,
):
    """
    Object description.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    if aliases is None:
        aliases = []

    cs = ColorSpace("%s" % odt_name)
    cs.description = "%s - %s Output Transform" % (odt_values["transformUserNamePrefix"], odt_name)
    cs.aliases = aliases
    cs.equality_group = ""
    cs.family = "Output"
    cs.is_data = False

    cs.aces_transform_id = odt_values["transformID"]

    pprint.pprint(odt_values)

    # Generating the *shaper* transform.
    (shaper_name, shaper_to_ACES_CTL, shaper_from_ACES_CTL, shaper_input_scale, shaper_params) = shaper_info

    if "legalRange" in odt_values:
        shaper_params["legalRange"] = odt_values["legalRange"]
    else:
        shaper_params["legalRange"] = 0

    # Add the shaper transform
    shaper_lut = "%s_to_linear.spi1d" % shaper_name
    shaper_lut = sanitize(shaper_lut)

    shaper_OCIO_transform = {"type": "lutFile", "path": shaper_lut, "interpolation": "linear", "direction": "inverse"}

    # Generating the *forward* transform.
    cs.from_reference_transforms = []

    if "transformLUT" in odt_values:
        transform_LUT_file_name = os.path.basename(odt_values["transformLUT"])
        lut = os.path.join(lut_directory, transform_LUT_file_name)
        shutil.copy(odt_values["transformLUT"], lut)

        cs.from_reference_transforms.append(shaper_OCIO_transform)
        cs.from_reference_transforms.append(
            {"type": "lutFile", "path": transform_LUT_file_name, "interpolation": "tetrahedral", "direction": "forward"}
        )
    elif "transformCTL" in odt_values:
        ctls = [
            shaper_to_ACES_CTL % aces_ctl_directory,
            os.path.join(aces_ctl_directory, "rrt", "RRT.a1.0.0.ctl"),
            os.path.join(aces_ctl_directory, "odt", odt_values["transformCTL"]),
        ]
        lut = "%s.RRT.a1.0.0.%s.spi3d" % (shaper_name, odt_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            # shaperLUT,
            ctls,
            lut_resolution_3d,
            "float",
            1 / shaper_input_scale,
            1,
            shaper_params,
            cleanup,
            aces_ctl_directory,
        )

        cs.from_reference_transforms.append(shaper_OCIO_transform)
        cs.from_reference_transforms.append(
            {"type": "lutFile", "path": lut, "interpolation": "tetrahedral", "direction": "forward"}
        )

    # Generating the *inverse* transform.
    cs.to_reference_transforms = []

    if "transformLUTInverse" in odt_values:
        transform_LUT_inverse_file_name = os.path.basename(odt_values["transformLUTInverse"])
        lut = os.path.join(lut_directory, transform_LUT_inverse_file_name)
        shutil.copy(odt_values["transformLUTInverse"], lut)

        cs.to_reference_transforms.append(
            {
                "type": "lutFile",
                "path": transform_LUT_inverse_file_name,
                "interpolation": "tetrahedral",
                "direction": "forward",
            }
        )

        shaper_inverse = shaper_OCIO_transform.copy()
        shaper_inverse["direction"] = "forward"
        cs.to_reference_transforms.append(shaper_inverse)
    elif "transformCTLInverse" in odt_values:
        ctls = [
            os.path.join(aces_ctl_directory, "odt", odt_values["transformCTLInverse"]),
            os.path.join(aces_ctl_directory, "rrt", "InvRRT.a1.0.0.ctl"),
            shaper_from_ACES_CTL % aces_ctl_directory,
        ]
        lut = "InvRRT.a1.0.0.%s.%s.spi3d" % (odt_name, shaper_name)

        lut = sanitize(lut)

        generate_3d_LUT_from_CTL(
            os.path.join(lut_directory, lut),
            # None,
            ctls,
            lut_resolution_3d,
            "half",
            1,
            shaper_input_scale,
            shaper_params,
            cleanup,
            aces_ctl_directory,
        )

        cs.to_reference_transforms.append(
            {"type": "lutFile", "path": lut, "interpolation": "tetrahedral", "direction": "forward"}
        )

        shaper_inverse = shaper_OCIO_transform.copy()
        shaper_inverse["direction"] = "forward"
        cs.to_reference_transforms.append(shaper_inverse)

    return cs
def create_protune(gamut,
                   transfer_function,
                   lut_directory,
                   lut_resolution_1d,
                   aliases):
    """
    Object description.

    Protune to ACES.

    Parameters
    ----------
    parameter : type
        Parameter description.

    Returns
    -------
    type
         Return value description.
    """

    # The gamut should be marked as experimental until  matrices are fully
    # verified.
    name = '%s - %s - Experimental' % (transfer_function, gamut)
    if transfer_function == '':
        name = 'Linear - %s - Experimental' % gamut
    if gamut == '':
        name = 'Curve - %s' % transfer_function

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/GoPro'
    cs.is_data = False

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    def protune_to_linear(normalized_code_value):
        c1 = 113.0
        c2 = 1.0
        c3 = 112.0
        linear = ((pow(c1, normalized_code_value) - c2) / c3)

        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'Protune Flat':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = protune_to_linear(float(c) / (lut_resolution_1d - 1))

        lut = '%s_to_linear.spi1d' % transfer_function
        lut = sanitize(lut)
        genlut.write_SPI_1d(
            os.path.join(lut_directory, lut),
            0,
            1,
            data,
            lut_resolution_1d,
            1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'})

    if gamut == 'Protune Native':
        cs.to_reference_transforms.append({
            'type': 'matrix',
            'matrix': [0.533448429, 0.32413911, 0.142412421, 0,
                       -0.050729924, 1.07572006, -0.024990416, 0,
                       0.071419661, -0.290521962, 1.219102381, 0,
                       0, 0, 0, 1],
            'direction': 'forward'})

    cs.from_reference_transforms = []
    return cs
Beispiel #43
0
def create_log_c(gamut, transfer_function, exposure_index, lut_directory,
                 lut_resolution_1d, aliases):
    """
    Creates colorspace covering the conversion from LogC to ACES, with various transfer 
    functions and encoding gamuts covered

    Parameters
    ----------
    gamut : str
        The name of the encoding gamut to use.
    transfer_function : str
        The name of the transfer function to use
    exposure_index : str
        The exposure index to use
    lut_directory : str or unicode 
        The directory to use when generating LUTs
    lut_resolution_1d : int
        The resolution of generated 1D LUTs
    aliases : list of str
        Aliases for this colorspace

    Returns
    -------
    ColorSpace
         A ColorSpace container class referencing the LUTs, matrices and identifying
         information for the requested colorspace.
    """

    name = '%s (EI%s) - %s' % (transfer_function, exposure_index, gamut)
    if transfer_function == '':
        name = 'Linear - ARRI %s' % gamut
    if gamut == '':
        name = 'Curve - %s (EI%s)' % (transfer_function, exposure_index)

    cs = ColorSpace(name)
    cs.description = name
    cs.aliases = aliases
    cs.equality_group = ''
    cs.family = 'Input/ARRI'
    cs.is_data = False

    if gamut and transfer_function:
        cs.aces_transform_id = ('IDT.ARRI.Alexa-v3-logC-EI%s.a1.v1' %
                                exposure_index)

    # A linear space needs allocation variables.
    if transfer_function == '':
        cs.allocation_type = ocio.Constants.ALLOCATION_LG2
        cs.allocation_vars = [-8, 5, 0.00390625]

    IDT_maker_version = '0.08'

    nominal_EI = 400
    black_signal = 0.003907
    mid_gray_signal = 0.01
    encoding_gain = 0.256598
    encoding_offset = 0.391007

    def gain_for_EI(EI):
        return (math.log(EI / nominal_EI) / math.log(2) *
                (0.89 - 1) / 3 + 1) * encoding_gain

    def log_c_inverse_parameters_for_EI(EI):
        cut = 1 / 9
        slope = 1 / (cut * math.log(10))
        offset = math.log10(cut) - slope * cut
        gain = EI / nominal_EI
        gray = mid_gray_signal / gain
        # The higher the EI, the lower the gamma.
        enc_gain = gain_for_EI(EI)
        enc_offset = encoding_offset
        for i in range(0, 3):
            nz = ((95 / 1023 - enc_offset) / enc_gain - offset) / slope
            enc_offset = encoding_offset - math.log10(1 + nz) * enc_gain

        a = 1 / gray
        b = nz - black_signal / gray
        e = slope * a * enc_gain
        f = enc_gain * (slope * b + offset) + enc_offset

        # Ensuring we can return relative exposure.
        s = 4 / (0.18 * EI)
        t = black_signal
        b += a * t
        a *= s
        f += e * t
        e *= s

        return {
            'a': a,
            'b': b,
            'cut': (cut - b) / a,
            'c': enc_gain,
            'd': enc_offset,
            'e': e,
            'f': f
        }

    def normalized_log_c_to_linear(code_value, exposure_index):
        p = log_c_inverse_parameters_for_EI(exposure_index)
        breakpoint = p['e'] * p['cut'] + p['f']
        if code_value > breakpoint:
            linear = ((pow(10,
                           (code_value - p['d']) / p['c']) - p['b']) / p['a'])
        else:
            linear = (code_value - p['f']) / p['e']
        return linear

    cs.to_reference_transforms = []

    if transfer_function == 'V3 LogC':
        data = array.array('f', '\0' * lut_resolution_1d * 4)
        for c in range(lut_resolution_1d):
            data[c] = normalized_log_c_to_linear(c / (lut_resolution_1d - 1),
                                                 int(exposure_index))

        lut = '%s_to_linear.spi1d' % ('%s_%s' %
                                      (transfer_function, exposure_index))

        lut = sanitize(lut)

        genlut.write_SPI_1d(os.path.join(lut_directory, lut), 0, 1, data,
                            lut_resolution_1d, 1)

        cs.to_reference_transforms.append({
            'type': 'lutFile',
            'path': lut,
            'interpolation': 'linear',
            'direction': 'forward'
        })

    if gamut == 'Wide Gamut':
        cs.to_reference_transforms.append({
            'type':
            'matrix',
            'matrix':
            mat44_from_mat33([
                0.680206, 0.236137, 0.083658, 0.085415, 1.017471, -0.102886,
                0.002057, -0.062563, 1.060506
            ]),
            'direction':
            'forward'
        })

    cs.from_reference_transforms = []
    return cs