Apply "PEP8" naming convention on most objects.
[OpenColorIO-Configs.git] / aces_1.0.0 / python / aces_ocio / create_arri_colorspaces.py
diff --git a/aces_1.0.0/python/aces_ocio/create_arri_colorspaces.py b/aces_1.0.0/python/aces_ocio/create_arri_colorspaces.py
new file mode 100644 (file)
index 0000000..be56c9d
--- /dev/null
@@ -0,0 +1,219 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Implements support for *ARRI* colorspaces conversions and transfer functions.
+"""
+
+import array
+import math
+
+import aces_ocio.generate_lut as genlut
+from aces_ocio.utilities import ColorSpace, mat44_from_mat33
+
+
+__author__ = 'ACES Developers'
+__copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers'
+__license__ = ''
+__maintainer__ = 'ACES Developers'
+__email__ = 'aces@oscars.org'
+__status__ = 'Production'
+
+__all__ = ['create_log_c',
+           'create_colorspaces']
+
+
+def create_log_c(gamut,
+                 transfer_function,
+                 exposure_index,
+                 name,
+                 lut_directory,
+                 lut_resolution_1d):
+    """
+    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 - %s" % gamut
+    if gamut == "":
+        name = "%s (EI%s)" % (transfer_function, exposure_index)
+
+    cs = ColorSpace(name)
+    cs.description = name
+    cs.equality_group = ''
+    cs.family = 'ARRI'
+    cs.is_data = False
+
+    # Globals
+    IDT_maker_version = "0.08"
+
+    nominal_EI = 400.0
+    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.0 / 9.0
+        slope = 1.0 / (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.0 / 1023.0 - enc_offset) / enc_gain - offset) / slope
+            enc_offset = encoding_offset - math.log10(1 + nz) * enc_gain
+        # Calculate some intermediate values
+        a = 1.0 / gray
+        b = nz - black_signal / gray
+        e = slope * a * enc_gain
+        f = enc_gain * (slope * b + offset) + enc_offset
+        # Manipulations so 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.0 - p['d']) / p['c']) -
+                       p['b']) / p['a'])
+        else:
+            linear = (code_value / 1023.0 - p['f']) / p['e']
+
+        # print(codeValue, linear)
+        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.0 * c / (lut_resolution_1d - 1),
+                                      int(exposure_index))
+
+        lut = "%s_to_linear.spi1d" % (
+            "%s_%s" % (transfer_function, exposure_index))
+
+        # Remove spaces and parentheses
+        lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_')
+
+        genlut.write_SPI_1d(lut_directory + "/" + lut,
+                            0.0,
+                            1.0,
+                            data,
+                            lut_resolution_1d,
+                            1)
+
+        # print("Writing %s" % lut)
+        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_colorspaces(lut_directory, lut_resolution_1d):
+    """
+    Generates the colorspace conversions.
+
+    Parameters
+    ----------
+    parameter : type
+        Parameter description.
+
+    Returns
+    -------
+    type
+         Return value description.
+    """
+
+    colorspaces = []
+
+    transfer_function = "V3 LogC"
+    gamut = "Wide Gamut"
+
+    # EIs = [160.0, 200.0, 250.0, 320.0, 400.0, 500.0, 640.0, 800.0,
+    # 1000.0, 1280.0, 1600.0, 2000.0, 2560.0, 3200.0]
+    EIs = [160, 200, 250, 320, 400, 500, 640, 800,
+           1000, 1280, 1600, 2000, 2560, 3200]
+    default_EI = 800
+
+    # Full conversion
+    for EI in EIs:
+        log_c_EI_full = create_log_c(
+            gamut,
+            transfer_function,
+            EI,
+            "LogC",
+            lut_directory,
+            lut_resolution_1d)
+        colorspaces.append(log_c_EI_full)
+
+    # Linearization only
+    for EI in [800]:
+        log_c_EI_linearization = create_log_c(
+            "",
+            transfer_function,
+            EI,
+            "LogC",
+            lut_directory,
+            lut_resolution_1d)
+        colorspaces.append(log_c_EI_linearization)
+
+    # Primaries
+    log_c_EI_primaries = create_log_c(
+        gamut,
+        "",
+        default_EI,
+        "LogC",
+        lut_directory,
+        lut_resolution_1d)
+    colorspaces.append(log_c_EI_primaries)
+
+    return colorspaces