nuke_default:updated linear gpu allocations to use -15 to 6 stops range
[OpenColorIO-Configs.git] / nuke-default / make.py
1 #!/usr/bin/env python
2
3 """
4 env
5 PYTHONPATH=/net/soft_scratch/users/jeremys/git/ocio.js/build/src/pyglue/
6 LD_LIBRARY_PATH=/net/soft_scratch/users/jeremys/git/ocio.js/build/src/core/
7 """
8
9 import math, os, sys
10 import PyOpenColorIO as OCIO
11
12 print "OCIO",OCIO.version
13
14 outputfilename = "config.ocio"
15
16 def WriteSPI1D(filename, fromMin, fromMax, data):
17     f = file(filename,'w')
18     f.write("Version 1\n")
19     f.write("From %s %s\n" % (fromMin, fromMax))
20     f.write("Length %d\n" % len(data))
21     f.write("Components 1\n")
22     f.write("{\n")
23     for value in data:
24         f.write("        %s\n" % value)
25     f.write("}\n")
26     f.close()
27
28 def Fit(value, fromMin, fromMax, toMin, toMax):
29     if fromMin == fromMax:
30         raise ValueError("fromMin == fromMax")
31     return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin
32
33
34 ###############################################################################
35
36
37 config = OCIO.Config()
38 config.setSearchPath('luts')
39
40 config.setRole(OCIO.Constants.ROLE_SCENE_LINEAR, "linear")
41 config.setRole(OCIO.Constants.ROLE_REFERENCE, "linear")
42 config.setRole(OCIO.Constants.ROLE_COLOR_TIMING, "Cineon")
43 config.setRole(OCIO.Constants.ROLE_COMPOSITING_LOG, "Cineon")
44 config.setRole(OCIO.Constants.ROLE_DATA,"raw")
45 config.setRole(OCIO.Constants.ROLE_DEFAULT,"raw")
46 config.setRole(OCIO.Constants.ROLE_COLOR_PICKING,"sRGB")
47 config.setRole(OCIO.Constants.ROLE_MATTE_PAINT,"sRGB")
48 config.setRole(OCIO.Constants.ROLE_TEXTURE_PAINT,"sRGB")
49
50
51 ###############################################################################
52
53 cs = OCIO.ColorSpace(name='linear')
54 cs.setDescription("Scene-linear, high dynamic range. Used for rendering and compositing.")
55 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
56 cs.setAllocation(OCIO.Constants.ALLOCATION_LG2)
57 cs.setAllocationVars([-15.0, 6.0])
58 config.addColorSpace(cs)
59
60
61 ###############################################################################
62
63 def toSRGB(v):
64     if v<0.04045/12.92:
65         return v*12.92
66     return 1.055 * v**(1.0/2.4) - 0.055
67
68 def fromSRGB(v):
69     if v<0.04045:
70         return v/12.92
71     return ((v + .055) / 1.055) ** 2.4
72
73 # These samples and range have been chosen to write out this colorspace with
74 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
75 # crossings
76
77 NUM_SAMPLES = 2**12+5
78 RANGE = (-0.125, 1.125)
79 data = []
80 for i in xrange(NUM_SAMPLES):
81     x = i/(NUM_SAMPLES-1.0)
82     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
83     data.append(fromSRGB(x))
84
85 # Data is srgb->linear
86 WriteSPI1D('luts/srgb.spi1d', RANGE[0], RANGE[1], data)
87
88 cs = OCIO.ColorSpace(name='sRGB')
89 cs.setDescription("Standard RGB Display Space")
90 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
91 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
92 cs.setAllocationVars([RANGE[0], RANGE[1]])
93
94 t = OCIO.FileTransform('srgb.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
95 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
96 config.addColorSpace(cs)
97
98
99 ###############################################################################
100
101 def toRec709(v):
102     if v<0.018:
103         return v*4.5
104     return 1.099 * v**0.45 - 0.099
105
106 def fromRec709(v):
107     if v<0.018*4.5:
108         return v/4.5
109     return ((v + .099) / 1.099) ** (1.0/0.45)
110
111 # These samples and range have been chosen to write out this colorspace with
112 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
113 # crossings
114
115 NUM_SAMPLES = 2**12+5
116 RANGE = (-0.125, 1.125)
117 data = []
118 for i in xrange(NUM_SAMPLES):
119     x = i/(NUM_SAMPLES-1.0)
120     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
121     data.append(fromRec709(x))
122
123 # Data is srgb->linear
124 WriteSPI1D('luts/rec709.spi1d', RANGE[0], RANGE[1], data)
125
126 cs = OCIO.ColorSpace(name='rec709')
127 cs.setDescription("Rec. 709 (Full Range) Display Space")
128 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
129 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
130 cs.setAllocationVars([RANGE[0], RANGE[1]])
131
132 t = OCIO.FileTransform('rec709.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
133 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
134 config.addColorSpace(cs)
135
136
137 ###############################################################################
138
139 cineonBlackOffset = 10.0 ** ((95.0 - 685.0)/300.0)
140
141 def fromCineon(x):
142     return (10.0**((1023.0 * x - 685.0) / 300.0) - cineonBlackOffset) / (1.0 - cineonBlackOffset)
143
144 # These samples and range have been chosen to write out this colorspace with
145 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
146 # crossings
147
148 NUM_SAMPLES = 2**12+5
149 RANGE = (-0.125, 1.125)
150 data = []
151 for i in xrange(NUM_SAMPLES):
152     x = i/(NUM_SAMPLES-1.0)
153     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
154     data.append(fromCineon(x))
155
156 # Data is srgb->linear
157 WriteSPI1D('luts/cineon.spi1d', RANGE[0], RANGE[1], data)
158
159 cs = OCIO.ColorSpace(name='Cineon')
160 cs.setDescription("Cineon (Log Film Scan)")
161 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
162 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
163 cs.setAllocationVars([RANGE[0], RANGE[1]])
164
165 t = OCIO.FileTransform('cineon.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
166 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
167 config.addColorSpace(cs)
168
169
170
171 ###############################################################################
172
173 cs = OCIO.ColorSpace(name='Gamma1.8')
174 cs.setDescription("Emulates a idealized Gamma 1.8 display device.")
175 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
176 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
177 cs.setAllocationVars([0.0, 1.0])
178
179 t = OCIO.ExponentTransform(value=(1.8,1.8,1.8,1.0))
180 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
181 config.addColorSpace(cs)
182
183 cs = OCIO.ColorSpace(name='Gamma2.2')
184 cs.setDescription("Emulates a idealized Gamma 2.2 display device.")
185 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
186 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
187 cs.setAllocationVars([0.0, 1.0])
188
189 t = OCIO.ExponentTransform(value=(2.2,2.2,2.2,1.0))
190 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
191 config.addColorSpace(cs)
192
193
194 ###############################################################################
195
196
197 # Log to Linear light conversions for Panalog
198 # WARNING: these are estimations known to be close enough.
199 # The actual transfer functions are not published
200
201 panalogBlackOffset = 10.0 ** ((64.0 - 681.0) / 444.0)
202
203 def fromPanalog(x):
204     return (10.0**((1023 * x - 681.0) / 444.0) - panalogBlackOffset) / (1.0 - panalogBlackOffset)
205
206 # These samples and range have been chosen to write out this colorspace with
207 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
208 # crossings
209
210 NUM_SAMPLES = 2**12+5
211 RANGE = (-0.125, 1.125)
212 data = []
213 for i in xrange(NUM_SAMPLES):
214     x = i/(NUM_SAMPLES-1.0)
215     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
216     data.append(fromPanalog(x))
217
218 # Data is srgb->linear
219 WriteSPI1D('luts/panalog.spi1d', RANGE[0], RANGE[1], data)
220
221 cs = OCIO.ColorSpace(name='Panalog')
222 cs.setDescription("Sony/Panavision Genesis Log Space")
223 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
224 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
225 cs.setAllocationVars([RANGE[0], RANGE[1]])
226
227 t = OCIO.FileTransform('panalog.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
228 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
229 config.addColorSpace(cs)
230
231
232
233 ###############################################################################
234
235
236
237 redBlackOffset = 10.0 ** ((0.0 - 1023.0) / 511.0)
238
239 def fromREDLog(x):
240     return ((10.0 ** ((1023.0 * x - 1023.0) / 511.0)) - redBlackOffset) / (1.0 - redBlackOffset)
241
242 # These samples and range have been chosen to write out this colorspace with
243 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
244 # crossings
245
246
247 NUM_SAMPLES = 2**12+5
248 RANGE = (-0.125, 1.125)
249 data = []
250 for i in xrange(NUM_SAMPLES):
251     x = i/(NUM_SAMPLES-1.0)
252     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
253     data.append(fromREDLog(x))
254
255 # Data is srgb->linear
256 WriteSPI1D('luts/redlog.spi1d', RANGE[0], RANGE[1], data)
257
258 cs = OCIO.ColorSpace(name='REDLog')
259 cs.setDescription("RED Log Space")
260 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
261 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
262 cs.setAllocationVars([RANGE[0], RANGE[1]])
263
264 t = OCIO.FileTransform('redlog.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
265 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
266 config.addColorSpace(cs)
267
268
269
270 ###############################################################################
271
272 def fromViperLog(x):
273     return 10.0**((1023.0 * x - 1023.0) / 500.0)
274
275 # These samples and range have been chosen to write out this colorspace with
276 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
277 # crossings
278
279
280 NUM_SAMPLES = 2**12+5
281 RANGE = (-0.125, 1.125)
282 data = []
283 for i in xrange(NUM_SAMPLES):
284     x = i/(NUM_SAMPLES-1.0)
285     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
286     data.append(fromViperLog(x))
287
288 # Data is srgb->linear
289 WriteSPI1D('luts/viperlog.spi1d', RANGE[0], RANGE[1], data)
290
291 cs = OCIO.ColorSpace(name='ViperLog')
292 cs.setDescription("Viper Log Space")
293 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
294 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
295 cs.setAllocationVars([RANGE[0], RANGE[1]])
296
297 t = OCIO.FileTransform('viperlog.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
298 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
299 config.addColorSpace(cs)
300
301
302
303 ###############################################################################
304
305
306 alexav3logc_a = 5.555556
307 alexav3logc_b = 0.052272
308 alexav3logc_c = 0.247190
309 alexav3logc_d = 0.385537
310 alexav3logc_e = 5.367655
311 alexav3logc_f = 0.092809
312 alexav3logc_cut = 0.010591
313 alexav3logc_eCutF = alexav3logc_e*alexav3logc_cut + alexav3logc_f
314
315 # This corresponds to EI800 per Arri Doc
316 # http://www.arridigital.com/forum/index.php?topic=6372.0
317 # http://www.arri.com/?eID=registration&file_uid=7775
318 def fromAlexaV3LogC(x):
319     if x > alexav3logc_eCutF:
320         return (10.0 **((x - alexav3logc_d) / alexav3logc_c) - alexav3logc_b) / alexav3logc_a
321     else:
322         return (x - alexav3logc_f) / alexav3logc_e
323
324
325 # These samples and range have been chosen to write out this colorspace with
326 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
327 # crossings
328
329
330 NUM_SAMPLES = 2**12+5
331 RANGE = (-0.125, 1.125)
332 data = []
333 for i in xrange(NUM_SAMPLES):
334     x = i/(NUM_SAMPLES-1.0)
335     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
336     data.append(fromAlexaV3LogC(x))
337
338 # Data is srgb->linear
339 WriteSPI1D('luts/alexalogc.spi1d', RANGE[0], RANGE[1], data)
340
341 cs = OCIO.ColorSpace(name='AlexaV3LogC')
342 cs.setDescription("Alexa Log C")
343 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
344 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
345 cs.setAllocationVars([RANGE[0], RANGE[1]])
346
347 t = OCIO.FileTransform('alexalogc.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
348 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
349 config.addColorSpace(cs)
350
351
352 ###############################################################################
353
354 'PLogLin'
355
356 # Josh Pines style pivoted log/lin conversion
357 minLinValue = 1e-10
358 linReference = 0.18
359 logReference = 445.0
360 negativeGamma = 0.6
361 densityPerCodeValue = 0.002
362 ngOverDpcv = negativeGamma/densityPerCodeValue
363 dpcvOverNg = densityPerCodeValue/negativeGamma
364
365 def fromPLogLin(x):
366     return (10.0**((x*1023.0 - logReference)*dpcvOverNg ) * linReference)
367
368
369 # These samples and range have been chosen to write out this colorspace with
370 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
371 # crossings
372
373 NUM_SAMPLES = 2**12+5
374 RANGE = (-0.125, 1.125)
375 data = []
376 for i in xrange(NUM_SAMPLES):
377     x = i/(NUM_SAMPLES-1.0)
378     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
379     data.append(fromPLogLin(x))
380
381 # Data is srgb->linear
382 WriteSPI1D('luts/ploglin.spi1d', RANGE[0], RANGE[1], data)
383
384 cs = OCIO.ColorSpace(name='PLogLin')
385 cs.setDescription("Josh Pines style pivoted log/lin conversion. 445->0.18")
386 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
387 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
388 cs.setAllocationVars([RANGE[0], RANGE[1]])
389
390 t = OCIO.FileTransform('ploglin.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
391 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
392 config.addColorSpace(cs)
393
394
395 ###############################################################################
396
397 def fromSLog(x):
398     return (10.0 ** (((x - 0.616596 - 0.03) / 0.432699)) - 0.037584)
399
400 # These samples and range have been chosen to write out this colorspace with
401 # a limited over/undershoot range, which also exactly samples the 0.0,1.0
402 # crossings
403
404 NUM_SAMPLES = 2**12+5
405 RANGE = (-0.125, 1.125)
406 data = []
407 for i in xrange(NUM_SAMPLES):
408     x = i/(NUM_SAMPLES-1.0)
409     x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
410     data.append(fromSLog(x))
411
412 # Data is srgb->linear
413 WriteSPI1D('luts/slog.spi1d', RANGE[0], RANGE[1], data)
414
415 cs = OCIO.ColorSpace(name='SLog')
416 cs.setDescription("Sony SLog")
417 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
418 cs.setAllocation(OCIO.Constants.ALLOCATION_UNIFORM)
419 cs.setAllocationVars([RANGE[0], RANGE[1]])
420
421 t = OCIO.FileTransform('slog.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR)
422 cs.setTransform(t, OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE)
423 config.addColorSpace(cs)
424
425
426 ###############################################################################
427
428 'REDSpace'
429
430
431
432 ###############################################################################
433
434 cs = OCIO.ColorSpace(name='raw')
435 cs.setDescription("Raw Data. Used for normals, points, etc.")
436 cs.setBitDepth(OCIO.Constants.BIT_DEPTH_F32)
437 cs.setIsData(True)
438 config.addColorSpace(cs)
439
440
441 ###############################################################################
442
443 display = 'default'
444 config.addDisplay(display, 'None', 'raw')
445 config.addDisplay(display, 'sRGB', 'sRGB')
446 config.addDisplay(display, 'rec709', 'rec709')
447
448 config.setActiveDisplays('default')
449 config.setActiveViews('sRGB')
450
451
452 ###############################################################################
453
454
455
456 try:
457     config.sanityCheck()
458 except Exception,e:
459     print e
460
461 f = file(outputfilename,"w")
462 f.write(config.serialize())
463 f.close()
464 print "Wrote",outputfilename
465
466 # Core/LUT/include/LUT/fnLUTConversions.h
467