Add docstrings skeletons.
[OpenColorIO-Configs.git] / aces_1.0.0 / python / aces_ocio / createARRIColorSpaces.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import array
5 import math
6
7 import aces_ocio.generateLUT as genlut
8 from aces_ocio.util import ColorSpace, mat44FromMat33
9
10
11 __author__ = 'ACES Developers'
12 __copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers'
13 __license__ = ''
14 __maintainer__ = 'ACES Developers'
15 __email__ = 'aces@oscars.org'
16 __status__ = 'Production'
17
18 __all__ = ['createLogC',
19            'createColorSpaces']
20
21
22 def createLogC(gamut,
23                transferFunction,
24                exposureIndex,
25                name,
26                lutDir,
27                lutResolution1d):
28     """
29     Object description.
30
31     LogC to ACES.
32
33     Parameters
34     ----------
35     parameter : type
36         Parameter description.
37
38     Returns
39     -------
40     type
41          Return value description.
42     """
43
44     name = "%s (EI%s) - %s" % (transferFunction, exposureIndex, gamut)
45     if transferFunction == "":
46         name = "Linear - %s" % gamut
47     if gamut == "":
48         name = "%s (EI%s)" % (transferFunction, exposureIndex)
49
50     cs = ColorSpace(name)
51     cs.description = name
52     cs.equalityGroup = ''
53     cs.family = 'ARRI'
54     cs.isData = False
55
56     # Globals
57     IDT_maker_version = "0.08"
58
59     nominalEI = 400.0
60     blackSignal = 0.003907
61     midGraySignal = 0.01
62     encodingGain = 0.256598
63     encodingOffset = 0.391007
64
65     def gainForEI(EI):
66         return (math.log(EI / nominalEI) / math.log(2) * (
67             0.89 - 1) / 3 + 1) * encodingGain
68
69     def LogCInverseParametersForEI(EI):
70         cut = 1.0 / 9.0
71         slope = 1.0 / (cut * math.log(10))
72         offset = math.log10(cut) - slope * cut
73         gain = EI / nominalEI
74         gray = midGraySignal / gain
75         # The higher the EI, the lower the gamma
76         encGain = gainForEI(EI)
77         encOffset = encodingOffset
78         for i in range(0, 3):
79             nz = ((95.0 / 1023.0 - encOffset) / encGain - offset) / slope
80             encOffset = encodingOffset - math.log10(1 + nz) * encGain
81         # Calculate some intermediate values
82         a = 1.0 / gray
83         b = nz - blackSignal / gray
84         e = slope * a * encGain
85         f = encGain * (slope * b + offset) + encOffset
86         # Manipulations so we can return relative exposure
87         s = 4 / (0.18 * EI)
88         t = blackSignal
89         b = b + a * t
90         a = a * s
91         f = f + e * t
92         e = e * s
93         return {'a': a,
94                 'b': b,
95                 'cut': (cut - b) / a,
96                 'c': encGain,
97                 'd': encOffset,
98                 'e': e,
99                 'f': f}
100
101     def logCtoLinear(codeValue, exposureIndex):
102         p = LogCInverseParametersForEI(exposureIndex)
103         breakpoint = p['e'] * p['cut'] + p['f']
104         if (codeValue > breakpoint):
105             linear = ((pow(10, (codeValue / 1023.0 - p['d']) / p['c']) -
106                        p['b']) / p['a'])
107         else:
108             linear = (codeValue / 1023.0 - p['f']) / p['e']
109
110         # print(codeValue, linear)
111         return linear
112
113
114     cs.toReferenceTransforms = []
115
116     if transferFunction == "V3 LogC":
117         data = array.array('f', "\0" * lutResolution1d * 4)
118         for c in range(lutResolution1d):
119             data[c] = logCtoLinear(1023.0 * c / (lutResolution1d - 1),
120                                    int(exposureIndex))
121
122         lut = "%s_to_linear.spi1d" % (
123             "%s_%s" % (transferFunction, exposureIndex))
124
125         # Remove spaces and parentheses
126         lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_')
127
128         genlut.writeSPI1D(lutDir + "/" + lut,
129                           0.0,
130                           1.0,
131                           data,
132                           lutResolution1d,
133                           1)
134
135         # print("Writing %s" % lut)
136         cs.toReferenceTransforms.append({
137             'type': 'lutFile',
138             'path': lut,
139             'interpolation': 'linear',
140             'direction': 'forward'
141         })
142
143     if gamut == 'Wide Gamut':
144         cs.toReferenceTransforms.append({
145             'type': 'matrix',
146             'matrix': mat44FromMat33([0.680206, 0.236137, 0.083658,
147                                       0.085415, 1.017471, -0.102886,
148                                       0.002057, -0.062563, 1.060506]),
149             'direction': 'forward'
150         })
151
152     cs.fromReferenceTransforms = []
153     return cs
154
155
156 def createColorSpaces(lutDir, lutResolution1d):
157     """
158     Generates the colorspace conversions.
159
160     Parameters
161     ----------
162     parameter : type
163         Parameter description.
164
165     Returns
166     -------
167     type
168          Return value description.
169     """
170
171     colorspaces = []
172
173     transferFunction = "V3 LogC"
174     gamut = "Wide Gamut"
175     # EIs = [160.0, 200.0, 250.0, 320.0, 400.0, 500.0, 640.0, 800.0,
176     # 1000.0, 1280.0, 1600.0, 2000.0, 2560.0, 3200.0]
177     EIs = [160, 200, 250, 320, 400, 500, 640, 800,
178            1000, 1280, 1600, 2000, 2560, 3200]
179     defaultEI = 800
180
181     # Full conversion
182     for EI in EIs:
183         LogCEIfull = createLogC(
184             gamut, transferFunction, EI, "LogC", lutDir, lutResolution1d)
185         colorspaces.append(LogCEIfull)
186
187     # Linearization only
188     for EI in [800]:
189         LogCEIlinearization = createLogC(
190             "", transferFunction, EI, "LogC", lutDir, lutResolution1d)
191         colorspaces.append(LogCEIlinearization)
192
193     # Primaries
194     LogCEIprimaries = createLogC(
195         gamut, "", defaultEI, "LogC", lutDir, lutResolution1d)
196     colorspaces.append(LogCEIprimaries)
197
198     return colorspaces