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