Example #1
0
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
Example #2
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
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
Example #8
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
Example #9
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
Example #10
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
Example #11
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
Example #12
0
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.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
Example #13
0
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
Example #14
0
def create_log_c(gamut, transfer_function, exposure_index, 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 = "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
Example #15
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_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
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_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
Example #19
0
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
Example #20
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