3f5591cefd77c6c9cfa9f6be2c0f3405d98030e2
[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 #
12 # LogC to ACES
13 #
14 def createLogC(gamut,
15                transferFunction,
16                exposureIndex,
17                name,
18                lutDir,
19                lutResolution1d):
20     name = "%s (EI%s) - %s" % (transferFunction, exposureIndex, gamut)
21     if transferFunction == "":
22         name = "Linear - %s" % gamut
23     if gamut == "":
24         name = "%s (EI%s)" % (transferFunction, exposureIndex)
25
26     cs = ColorSpace(name)
27     cs.description = name
28     cs.equalityGroup = ''
29     cs.family = 'ARRI'
30     cs.isData = False
31
32     # Globals
33     IDT_maker_version = "0.08"
34
35     nominalEI = 400.0
36     blackSignal = 0.003907
37     midGraySignal = 0.01
38     encodingGain = 0.256598
39     encodingOffset = 0.391007
40
41     def gainForEI(EI):
42         return (math.log(EI / nominalEI) / math.log(2) * (
43             0.89 - 1) / 3 + 1) * encodingGain
44
45     def LogCInverseParametersForEI(EI):
46         cut = 1.0 / 9.0
47         slope = 1.0 / (cut * math.log(10))
48         offset = math.log10(cut) - slope * cut
49         gain = EI / nominalEI
50         gray = midGraySignal / gain
51         # The higher the EI, the lower the gamma
52         encGain = gainForEI(EI)
53         encOffset = encodingOffset
54         for i in range(0, 3):
55             nz = ((95.0 / 1023.0 - encOffset) / encGain - offset) / slope
56             encOffset = encodingOffset - math.log10(1 + nz) * encGain
57         # Calculate some intermediate values
58         a = 1.0 / gray
59         b = nz - blackSignal / gray
60         e = slope * a * encGain
61         f = encGain * (slope * b + offset) + encOffset
62         # Manipulations so we can return relative exposure
63         s = 4 / (0.18 * EI)
64         t = blackSignal
65         b = b + a * t
66         a = a * s
67         f = f + e * t
68         e = e * s
69         return {'a': a,
70                 'b': b,
71                 'cut': (cut - b) / a,
72                 'c': encGain,
73                 'd': encOffset,
74                 'e': e,
75                 'f': f}
76
77     def logCtoLinear(codeValue, exposureIndex):
78         p = LogCInverseParametersForEI(exposureIndex)
79         breakpoint = p['e'] * p['cut'] + p['f']
80         if (codeValue > breakpoint):
81             linear = ((pow(10, (codeValue / 1023.0 - p['d']) / p['c']) -
82                        p['b']) / p['a'])
83         else:
84             linear = (codeValue / 1023.0 - p['f']) / p['e']
85
86         # print(codeValue, linear)
87         return linear
88
89
90     cs.toReferenceTransforms = []
91
92     if transferFunction == "V3 LogC":
93         data = array.array('f', "\0" * lutResolution1d * 4)
94         for c in range(lutResolution1d):
95             data[c] = logCtoLinear(1023.0 * c / (lutResolution1d - 1),
96                                    int(exposureIndex))
97
98         lut = "%s_to_linear.spi1d" % (
99             "%s_%s" % (transferFunction, exposureIndex))
100
101         # Remove spaces and parentheses
102         lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_')
103
104         genlut.writeSPI1D(lutDir + "/" + lut,
105                           0.0,
106                           1.0,
107                           data,
108                           lutResolution1d,
109                           1)
110
111         # print("Writing %s" % lut)
112         cs.toReferenceTransforms.append({
113             'type': 'lutFile',
114             'path': lut,
115             'interpolation': 'linear',
116             'direction': 'forward'
117         })
118
119     if gamut == 'Wide Gamut':
120         cs.toReferenceTransforms.append({
121             'type': 'matrix',
122             'matrix': mat44FromMat33([0.680206, 0.236137, 0.083658,
123                                       0.085415, 1.017471, -0.102886,
124                                       0.002057, -0.062563, 1.060506]),
125             'direction': 'forward'
126         })
127
128     cs.fromReferenceTransforms = []
129     return cs
130
131
132 def createColorSpaces(lutDir, lutResolution1d):
133     colorspaces = []
134
135     transferFunction = "V3 LogC"
136     gamut = "Wide Gamut"
137     # EIs = [160.0, 200.0, 250.0, 320.0, 400.0, 500.0, 640.0, 800.0,
138     # 1000.0, 1280.0, 1600.0, 2000.0, 2560.0, 3200.0]
139     EIs = [160, 200, 250, 320, 400, 500, 640, 800,
140            1000, 1280, 1600, 2000, 2560, 3200]
141     defaultEI = 800
142
143     # Full conversion
144     for EI in EIs:
145         LogCEIfull = createLogC(
146             gamut, transferFunction, EI, "LogC", lutDir, lutResolution1d)
147         colorspaces.append(LogCEIfull)
148
149     # Linearization only
150     for EI in [800]:
151         LogCEIlinearization = createLogC(
152             "", transferFunction, EI, "LogC", lutDir, lutResolution1d)
153         colorspaces.append(LogCEIlinearization)
154
155     # Primaries
156     LogCEIprimaries = createLogC(
157         gamut, "", defaultEI, "LogC", lutDir, lutResolution1d)
158     colorspaces.append(LogCEIprimaries)
159
160     return colorspaces