2 # -*- coding: utf-8 -*-
5 Implements support for general colorspaces conversions and transfer functions.
8 from __future__ import division
13 import PyOpenColorIO as ocio
15 import aces_ocio.generate_lut as genlut
16 from aces_ocio.colorspaces import aces
17 from aces_ocio.utilities import ColorSpace, mat44_from_mat33
20 __author__ = 'ACES Developers'
21 __copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers'
23 __maintainer__ = 'ACES Developers'
24 __email__ = 'aces@oscars.org'
25 __status__ = 'Production'
27 __all__ = ['create_matrix_colorspace',
30 # -------------------------------------------------------------------------
32 # -------------------------------------------------------------------------
33 def create_matrix_colorspace(name='matrix',
34 from_reference_values=None,
35 to_reference_values=None,
43 Parameter description.
48 Return value description.
51 if from_reference_values is None:
52 from_reference_values = []
54 if to_reference_values is None:
55 to_reference_values = []
58 cs.description = 'The %s color space' % name
60 cs.equality_group = name
64 # A linear space needs allocation variables
65 cs.allocation_type = ocio.Constants.ALLOCATION_LG2
66 cs.allocation_vars = [-8, 5, 0.00390625]
68 cs.to_reference_transforms = []
69 if to_reference_values:
70 for matrix in to_reference_values:
71 cs.to_reference_transforms.append({
73 'matrix': mat44_from_mat33(matrix),
74 'direction': 'forward'})
76 cs.from_reference_transforms = []
77 if from_reference_values:
78 for matrix in from_reference_values:
79 cs.from_reference_transforms.append({
81 'matrix': mat44_from_mat33(matrix),
82 'direction': 'forward'})
86 # -------------------------------------------------------------------------
88 # -------------------------------------------------------------------------
89 def create_matrix_plus_transfer_colorspace(name='matrix_plus_transfer',
90 transfer_function_name='transfer_function',
91 transfer_function=lambda x: x,
93 lut_resolution_1d=1024,
94 from_reference_values=None,
95 to_reference_values=None,
103 Parameter description.
108 Return value description.
111 if from_reference_values is None:
112 from_reference_values = []
114 if to_reference_values is None:
115 to_reference_values = []
117 cs = ColorSpace(name)
118 cs.description = 'The %s color space' % name
120 cs.equality_group = name
121 cs.family = 'Utility'
124 # A linear space needs allocation variables
125 cs.allocation_type = ocio.Constants.ALLOCATION_LG2
126 cs.allocation_vars = [-8, 5, 0.00390625]
128 # Sample the transfer function
129 data = array.array('f', '\0' * lut_resolution_1d * 4)
130 for c in range(lut_resolution_1d):
131 data[c] = transfer_function(c / (lut_resolution_1d - 1))
133 # Write the sampled data to a LUT
134 lut = '%s_to_linear.spi1d' % transfer_function_name
136 os.path.join(lut_directory, lut),
143 # Create the 'to_reference' transforms
144 cs.to_reference_transforms = []
145 cs.to_reference_transforms.append({
148 'interpolation': 'linear',
149 'direction': 'forward'})
151 if to_reference_values:
152 for matrix in to_reference_values:
153 cs.to_reference_transforms.append({
155 'matrix': mat44_from_mat33(matrix),
156 'direction': 'forward'})
158 # Create the 'from_reference' transforms
159 cs.from_reference_transforms = []
160 if from_reference_values:
161 for matrix in from_reference_values:
162 cs.from_reference_transforms.append({
164 'matrix': mat44_from_mat33(matrix),
165 'direction': 'forward'})
167 cs.from_reference_transforms.append({
170 'interpolation': 'linear',
171 'direction': 'inverse'})
175 # Transfer functions for standard color spaces
176 def transfer_function_sRGB_to_linear(v):
184 return pow(((v + (a - 1)) / a), g)
186 def transfer_function_Rec709_to_linear(v):
195 return pow(((v + (a - 1)) / a), g)
197 def transfer_function_Rec2020_10bit_to_linear(v):
206 return pow(((v + (a - 1)) / a), g)
208 def transfer_function_Rec2020_12bit_to_linear(v):
217 return pow(((v + (a - 1)) / a), g)
219 def transfer_function_Rec1886_to_linear(v):
224 # Ignoring legal to full scaling for now
225 #v = (1023.0*v - 64.0)/876.0
227 t = pow(Lw, 1.0/g) - pow(Lb, 1.0/g)
231 return a*pow(max((v + b), 0.0), g)
233 def create_colorspaces(lut_directory,
237 Generates the colorspace conversions.
242 Parameter description.
247 Return value description.
255 cs = create_matrix_colorspace('XYZ',
256 to_reference_values=[aces.ACES_XYZ_TO_AP0],
257 from_reference_values=[aces.ACES_AP0_TO_XYZ],
259 colorspaces.append(cs)
264 cs = create_matrix_colorspace(
266 to_reference_values=[aces.ACES_AP1_TO_AP0],
267 from_reference_values=[aces.ACES_AP0_TO_AP1],
269 colorspaces.append(cs)
274 # *ACES* to *Linear*, *P3D60* primaries.
275 XYZ_to_P3D60 = [2.4027414142, -0.8974841639, -0.3880533700,
276 -0.8325796487, 1.7692317536, 0.0237127115,
277 0.0388233815, -0.0824996856, 1.0363685997]
279 cs = create_matrix_colorspace(
281 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_P3D60],
282 aliases=["lin_p3d60"])
283 colorspaces.append(cs)
288 # *ACES* to *Linear*, *P3DCI* primaries.
289 XYZ_to_P3DCI = [2.7253940305, -1.0180030062, -0.4401631952,
290 -0.7951680258, 1.6897320548, 0.0226471906,
291 0.0412418914, -0.0876390192, 1.1009293786]
293 cs = create_matrix_colorspace(
295 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_P3DCI],
296 aliases=["lin_p3dci"])
297 colorspaces.append(cs)
302 # *ACES* to *Linear*, *Rec. 709* primaries.
303 XYZ_to_Rec709 = [3.2409699419, -1.5373831776, -0.4986107603,
304 -0.9692436363, 1.8759675015, 0.0415550574,
305 0.0556300797, -0.2039769589, 1.0569715142]
307 cs = create_matrix_colorspace(
309 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec709],
310 aliases=["lin_rec709"])
311 colorspaces.append(cs)
313 # *Linear* to *Rec. 709* Transfer Function*
314 cs = create_matrix_plus_transfer_colorspace(
317 transfer_function_Rec709_to_linear,
320 aliases=["crv_rec709"])
321 colorspaces.append(cs)
323 # *ACES* to *Rec. 709* Primaries + Transfer Function*
324 cs = create_matrix_plus_transfer_colorspace(
327 transfer_function_Rec709_to_linear,
330 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec709],
332 colorspaces.append(cs)
337 # *ACES* to *Linear*, *Rec. 709* primaries.
338 # sRGB and Rec 709 use the same gamut
339 XYZ_to_Rec709 = [3.2409699419, -1.5373831776, -0.4986107603,
340 -0.9692436363, 1.8759675015, 0.0415550574,
341 0.0556300797, -0.2039769589, 1.0569715142]
343 cs = create_matrix_colorspace(
345 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec709],
346 aliases=["lin_sRGB"])
347 colorspaces.append(cs)
349 # *Linear* to *sRGB* Transfer Function*
350 cs = create_matrix_plus_transfer_colorspace(
353 transfer_function_sRGB_to_linear,
356 aliases=["crv_sRGB"])
357 colorspaces.append(cs)
359 # *ACES* to *sRGB* Primaries + Transfer Function*
360 cs = create_matrix_plus_transfer_colorspace(
363 transfer_function_sRGB_to_linear,
366 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec709],
368 colorspaces.append(cs)
373 # *ACES* to *Linear*, *Rec. 709* primaries.
374 # Rec 1886 and Rec 709 use the same gamut
375 XYZ_to_Rec709 = [3.2409699419, -1.5373831776, -0.4986107603,
376 -0.9692436363, 1.8759675015, 0.0415550574,
377 0.0556300797, -0.2039769589, 1.0569715142]
379 cs = create_matrix_colorspace(
381 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec709],
382 aliases=["lin_rec1886"])
383 colorspaces.append(cs)
385 # *Linear* to *sRGB* Transfer Function*
386 cs = create_matrix_plus_transfer_colorspace(
389 transfer_function_Rec1886_to_linear,
392 aliases=["crv_rec1886"])
393 colorspaces.append(cs)
395 # *ACES* to *sRGB* Primaries + Transfer Function*
396 cs = create_matrix_plus_transfer_colorspace(
399 transfer_function_Rec1886_to_linear,
402 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec709],
404 colorspaces.append(cs)
409 # *ACES* to *Linear*, *Rec. 2020* primaries.
410 XYZ_to_Rec2020 = [1.7166511880, -0.3556707838, -0.2533662814,
411 -0.6666843518, 1.6164812366, 0.0157685458,
412 0.0176398574, -0.0427706133, 0.9421031212]
414 cs = create_matrix_colorspace(
416 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec2020],
417 aliases=["lin_rec2020"])
418 colorspaces.append(cs)
420 # *Linear* to *Rec. 2020 10 bit* Transfer Function*
421 cs = create_matrix_plus_transfer_colorspace(
422 'Curve - Rec.2020 - 10 bit',
424 transfer_function_Rec2020_10bit_to_linear,
427 aliases=["crv_rec202010bit"])
428 colorspaces.append(cs)
430 # *ACES* to *Rec. 2020 10 bit* Primaries + Transfer Function*
431 cs = create_matrix_plus_transfer_colorspace(
432 'Rec.2020 10 bit - Rec.2020',
434 transfer_function_Rec2020_10bit_to_linear,
437 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec2020],
438 aliases=["rec202010bit"])
439 colorspaces.append(cs)
441 # *Linear* to *Rec. 2020 10 bit* Transfer Function*
442 cs = create_matrix_plus_transfer_colorspace(
443 'Curve - Rec.2020 - 12 bit',
445 transfer_function_Rec2020_12bit_to_linear,
448 aliases=["crv_rec202012bit"])
449 colorspaces.append(cs)
451 # *ACES* to *Rec. 2020 10 bit* Primaries + Transfer Function*
452 cs = create_matrix_plus_transfer_colorspace(
453 'Rec.2020 12 bit - Rec.2020',
455 transfer_function_Rec2020_12bit_to_linear,
458 from_reference_values=[aces.ACES_AP0_TO_XYZ, XYZ_to_Rec2020],
459 aliases=["rec202012bit"])
460 colorspaces.append(cs)
465 # *ACES* to *Linear*, *Pro Photo* primaries.
466 AP0_to_RIMM = [1.2412367771, -0.1685692287, -0.0726675484,
467 0.0061203066, 1.083151174, -0.0892714806,
468 -0.0032853314, 0.0099796402, 0.9933056912]
470 cs = create_matrix_colorspace(
471 'Linear - RIMM ROMM (ProPhoto)',
472 from_reference_values=[AP0_to_RIMM],
473 aliases=["lin_prophoto", "lin_rimm"])
474 colorspaces.append(cs)
479 # *ACES* to *Linear*, *Adobe RGB* primaries.
480 AP0_to_ADOBERGB = [1.7245603168, -0.4199935942, -0.3045667227,
481 -0.2764799142, 1.3727190877, -0.0962391734,
482 -0.0261255258, -0.0901747807, 1.1163003065]
484 cs = create_matrix_colorspace(
485 'Linear - Adobe RGB',
486 from_reference_values=[AP0_to_ADOBERGB],
487 aliases=["lin_adobergb"])
488 colorspaces.append(cs)
491 # Adobe Wide Gamut RGB
494 # *ACES* to *Linear*, *Adobe Wide Gamut RGB* primaries.
495 AP0_to_ADOBERGB = [1.3809814778, -0.1158594573, -0.2651220205,
496 0.0057015535, 1.0402949043, -0.0459964578,
497 -0.0038908746, -0.0597091815, 1.0636000561]
499 cs = create_matrix_colorspace(
500 'Linear - Adobe Wide Gamut RGB',
501 from_reference_values=[AP0_to_ADOBERGB],
502 aliases=["lin_adobewidegamutrgb"])
503 colorspaces.append(cs)
509 # *Raw* utility space
511 raw = ColorSpace(name)
512 raw.description = 'The %s color space' % name
514 raw.equality_group = name
515 raw.family = 'Utility'