Blender  V2.93
ocio_impl.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2012 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 #include <cassert>
21 #include <iostream>
22 #include <math.h>
23 #include <sstream>
24 #include <string.h>
25 
26 #ifdef _MSC_VER
27 # pragma warning(push)
28 # pragma warning(disable : 4251 4275)
29 #endif
30 #include <OpenColorIO/OpenColorIO.h>
31 #ifdef _MSC_VER
32 # pragma warning(pop)
33 #endif
34 
35 using namespace OCIO_NAMESPACE;
36 
37 #include "MEM_guardedalloc.h"
38 
39 #include "BLI_math.h"
40 #include "BLI_math_color.h"
41 #include "BLI_math_matrix.h"
42 
43 #include "ocio_impl.h"
44 
45 #if !defined(WITH_ASSERT_ABORT)
46 # define OCIO_abort()
47 #else
48 # include <stdlib.h>
49 # define OCIO_abort() abort()
50 #endif
51 
52 #if defined(_MSC_VER)
53 # define __func__ __FUNCTION__
54 #endif
55 
56 static void OCIO_reportError(const char *err)
57 {
58  std::cerr << "OpenColorIO Error: " << err << std::endl;
59 
60  OCIO_abort();
61 }
62 
63 static void OCIO_reportException(Exception &exception)
64 {
65  OCIO_reportError(exception.what());
66 }
67 
68 OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
69 {
70  ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
71 
72  try {
73  *config = GetCurrentConfig();
74 
75  if (*config)
76  return (OCIO_ConstConfigRcPtr *)config;
77  }
78  catch (Exception &exception) {
79  OCIO_reportException(exception);
80  }
81 
82  OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
83 
84  return NULL;
85 }
86 
87 void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config)
88 {
89  try {
90  SetCurrentConfig(*(ConstConfigRcPtr *)config);
91  }
92  catch (Exception &exception) {
93  OCIO_reportException(exception);
94  }
95 }
96 
97 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
98 {
99  ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
100 
101  try {
102  *config = Config::CreateFromEnv();
103 
104  if (*config)
105  return (OCIO_ConstConfigRcPtr *)config;
106  }
107  catch (Exception &exception) {
108  OCIO_reportException(exception);
109  }
110 
111  OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
112 
113  return NULL;
114 }
115 
116 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
117 {
118  ConstConfigRcPtr *config = OBJECT_GUARDED_NEW(ConstConfigRcPtr);
119 
120  try {
121  *config = Config::CreateFromFile(filename);
122 
123  if (*config)
124  return (OCIO_ConstConfigRcPtr *)config;
125  }
126  catch (Exception &exception) {
127  OCIO_reportException(exception);
128  }
129 
130  OBJECT_GUARDED_DELETE(config, ConstConfigRcPtr);
131 
132  return NULL;
133 }
134 
135 void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config)
136 {
137  OBJECT_GUARDED_DELETE((ConstConfigRcPtr *)config, ConstConfigRcPtr);
138 }
139 
140 int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config)
141 {
142  try {
143  return (*(ConstConfigRcPtr *)config)->getNumColorSpaces();
144  }
145  catch (Exception &exception) {
146  OCIO_reportException(exception);
147  }
148 
149  return 0;
150 }
151 
152 const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
153 {
154  try {
155  return (*(ConstConfigRcPtr *)config)->getColorSpaceNameByIndex(index);
156  }
157  catch (Exception &exception) {
158  OCIO_reportException(exception);
159  }
160 
161  return NULL;
162 }
163 
164 OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config,
165  const char *name)
166 {
167  ConstColorSpaceRcPtr *cs = OBJECT_GUARDED_NEW(ConstColorSpaceRcPtr);
168 
169  try {
170  *cs = (*(ConstConfigRcPtr *)config)->getColorSpace(name);
171 
172  if (*cs)
173  return (OCIO_ConstColorSpaceRcPtr *)cs;
174  }
175  catch (Exception &exception) {
176  OCIO_reportException(exception);
177  }
178 
179  OBJECT_GUARDED_DELETE(cs, ConstColorSpaceRcPtr);
180 
181  return NULL;
182 }
183 
184 int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
185 {
186  try {
187  return (*(ConstConfigRcPtr *)config)->getIndexForColorSpace(name);
188  }
189  catch (Exception &exception) {
190  OCIO_reportException(exception);
191  }
192 
193  return -1;
194 }
195 
196 const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config)
197 {
198  try {
199  return (*(ConstConfigRcPtr *)config)->getDefaultDisplay();
200  }
201  catch (Exception &exception) {
202  OCIO_reportException(exception);
203  }
204 
205  return NULL;
206 }
207 
208 int OCIOImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr *config)
209 {
210  try {
211  return (*(ConstConfigRcPtr *)config)->getNumDisplays();
212  }
213  catch (Exception &exception) {
214  OCIO_reportException(exception);
215  }
216 
217  return 0;
218 }
219 
220 const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index)
221 {
222  try {
223  return (*(ConstConfigRcPtr *)config)->getDisplay(index);
224  }
225  catch (Exception &exception) {
226  OCIO_reportException(exception);
227  }
228 
229  return NULL;
230 }
231 
232 const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display)
233 {
234  try {
235  return (*(ConstConfigRcPtr *)config)->getDefaultView(display);
236  }
237  catch (Exception &exception) {
238  OCIO_reportException(exception);
239  }
240 
241  return NULL;
242 }
243 
244 int OCIOImpl::configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display)
245 {
246  try {
247  return (*(ConstConfigRcPtr *)config)->getNumViews(display);
248  }
249  catch (Exception &exception) {
250  OCIO_reportException(exception);
251  }
252 
253  return 0;
254 }
255 
256 const char *OCIOImpl::configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index)
257 {
258  try {
259  return (*(ConstConfigRcPtr *)config)->getView(display, index);
260  }
261  catch (Exception &exception) {
262  OCIO_reportException(exception);
263  }
264 
265  return NULL;
266 }
267 
268 const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config,
269  const char *display,
270  const char *view)
271 {
272  try {
273  return (*(ConstConfigRcPtr *)config)->getDisplayViewColorSpaceName(display, view);
274  }
275  catch (Exception &exception) {
276  OCIO_reportException(exception);
277  }
278 
279  return NULL;
280 }
281 
282 void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb)
283 {
284  try {
285  double rgb_double[3];
286  (*(ConstConfigRcPtr *)config)->getDefaultLumaCoefs(rgb_double);
287  rgb[0] = rgb_double[0];
288  rgb[1] = rgb_double[1];
289  rgb[2] = rgb_double[2];
290  }
291  catch (Exception &exception) {
292  OCIO_reportException(exception);
293  }
294 }
295 
296 static bool to_scene_linear_matrix(ConstConfigRcPtr &config,
297  const char *colorspace,
298  float to_scene_linear[3][3])
299 {
300  ConstProcessorRcPtr processor;
301  try {
302  processor = config->getProcessor(colorspace, ROLE_SCENE_LINEAR);
303  }
304  catch (Exception &exception) {
305  OCIO_reportException(exception);
306  return false;
307  }
308 
309  if (!processor) {
310  return false;
311  }
312 
313  ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
314  if (!cpu_processor) {
315  return false;
316  }
317 
318  unit_m3(to_scene_linear);
319  cpu_processor->applyRGB(to_scene_linear[0]);
320  cpu_processor->applyRGB(to_scene_linear[1]);
321  cpu_processor->applyRGB(to_scene_linear[2]);
322  return true;
323 }
324 
325 void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rgb[3][3])
326 {
327  ConstConfigRcPtr config = (*(ConstConfigRcPtr *)config_);
328 
329  /* Default to ITU-BT.709 in case no appropriate transform found.
330  * Note XYZ is defined here as having a D65 white point. */
332 
333  /* Get from OpenColorO config if it has the required roles. */
334  if (!config->hasRole(ROLE_SCENE_LINEAR)) {
335  return;
336  }
337 
338  if (config->hasRole("aces_interchange")) {
339  /* Standard OpenColorIO role, defined as ACES2065-1. */
340  const float xyz_E_to_aces[3][3] = {{1.0498110175f, -0.4959030231f, 0.0f},
341  {0.0f, 1.3733130458f, 0.0f},
342  {-0.0000974845f, 0.0982400361f, 0.9912520182f}};
343  const float xyz_D65_to_E[3][3] = {
344  {1.0521111f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.9184170f}};
345 
346  float aces_to_rgb[3][3];
347  if (to_scene_linear_matrix(config, "aces_interchange", aces_to_rgb)) {
348  mul_m3_series(xyz_to_rgb, aces_to_rgb, xyz_E_to_aces, xyz_D65_to_E);
349  }
350  }
351  else if (config->hasRole("XYZ")) {
352  /* Custom role used before the standard existed. */
353  to_scene_linear_matrix(config, "XYZ", xyz_to_rgb);
354  }
355 }
356 
357 int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
358 {
359  try {
360  return (*(ConstConfigRcPtr *)config)->getNumLooks();
361  }
362  catch (Exception &exception) {
363  OCIO_reportException(exception);
364  }
365 
366  return 0;
367 }
368 
369 const char *OCIOImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
370 {
371  try {
372  return (*(ConstConfigRcPtr *)config)->getLookNameByIndex(index);
373  }
374  catch (Exception &exception) {
375  OCIO_reportException(exception);
376  }
377 
378  return NULL;
379 }
380 
381 OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, const char *name)
382 {
383  ConstLookRcPtr *look = OBJECT_GUARDED_NEW(ConstLookRcPtr);
384 
385  try {
386  *look = (*(ConstConfigRcPtr *)config)->getLook(name);
387 
388  if (*look)
389  return (OCIO_ConstLookRcPtr *)look;
390  }
391  catch (Exception &exception) {
392  OCIO_reportException(exception);
393  }
394 
395  OBJECT_GUARDED_DELETE(look, ConstLookRcPtr);
396 
397  return NULL;
398 }
399 
400 const char *OCIOImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
401 {
402  return (*(ConstLookRcPtr *)look)->getProcessSpace();
403 }
404 
405 void OCIOImpl::lookRelease(OCIO_ConstLookRcPtr *look)
406 {
407  OBJECT_GUARDED_DELETE((ConstLookRcPtr *)look, ConstLookRcPtr);
408 }
409 
410 int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
411 {
412  ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *)cs_;
413  const char *family = (*cs)->getFamily();
414 
415  if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
416  /* assume display and rrt transformations are not invertible in fact some of them could be,
417  * but it doesn't make much sense to allow use them as invertible. */
418  return false;
419  }
420 
421  if ((*cs)->isData()) {
422  /* data color spaces don't have transformation at all */
423  return true;
424  }
425 
426  if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
427  /* if there's defined transform to reference space,
428  * color space could be converted to scene linear. */
429  return true;
430  }
431 
432  return true;
433 }
434 
435 int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
436 {
437  return (*(ConstColorSpaceRcPtr *)cs)->isData();
438 }
439 
440 static float compare_floats(float a, float b, float abs_diff, int ulp_diff)
441 {
442  /* Returns true if the absolute difference is smaller than abs_diff (for numbers near zero)
443  * or their relative difference is less than ulp_diff ULPs. Based on:
444  * https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ */
445  if (fabsf(a - b) < abs_diff) {
446  return true;
447  }
448 
449  if ((a < 0.0f) != (b < 0.0f)) {
450  return false;
451  }
452 
453  return (abs((*(int *)&a) - (*(int *)&b)) < ulp_diff);
454 }
455 
456 void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
457  OCIO_ConstColorSpaceRcPtr *cs_,
458  bool &is_scene_linear,
459  bool &is_srgb)
460 {
461  ConstConfigRcPtr *config = (ConstConfigRcPtr *)config_;
462  ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *)cs_;
463  ConstProcessorRcPtr processor;
464 
465  try {
466  processor = (*config)->getProcessor((*cs)->getName(), "scene_linear");
467  }
468  catch (Exception &) {
469  /* Silently ignore if no conversion possible, then it's not scene linear or sRGB. */
470  is_scene_linear = false;
471  is_srgb = false;
472  return;
473  }
474 
475  ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
476 
477  is_scene_linear = true;
478  is_srgb = true;
479  for (int i = 0; i < 256; i++) {
480  float v = i / 255.0f;
481 
482  float cR[3] = {v, 0, 0};
483  float cG[3] = {0, v, 0};
484  float cB[3] = {0, 0, v};
485  float cW[3] = {v, v, v};
486  cpu_processor->applyRGB(cR);
487  cpu_processor->applyRGB(cG);
488  cpu_processor->applyRGB(cB);
489  cpu_processor->applyRGB(cW);
490 
491  /* Make sure that there is no channel crosstalk. */
492  if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
493  fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f) {
494  is_scene_linear = false;
495  is_srgb = false;
496  break;
497  }
498  /* Make sure that the three primaries combine linearly. */
499  if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
500  !compare_floats(cB[2], cW[2], 1e-6f, 64)) {
501  is_scene_linear = false;
502  is_srgb = false;
503  break;
504  }
505  /* Make sure that the three channels behave identically. */
506  if (!compare_floats(cW[0], cW[1], 1e-6f, 64) || !compare_floats(cW[1], cW[2], 1e-6f, 64)) {
507  is_scene_linear = false;
508  is_srgb = false;
509  break;
510  }
511 
512  float out_v = (cW[0] + cW[1] + cW[2]) * (1.0f / 3.0f);
513  if (!compare_floats(v, out_v, 1e-6f, 64)) {
514  is_scene_linear = false;
515  }
516  if (!compare_floats(srgb_to_linearrgb(v), out_v, 1e-6f, 64)) {
517  is_srgb = false;
518  }
519  }
520 }
521 
522 void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
523 {
524  OBJECT_GUARDED_DELETE((ConstColorSpaceRcPtr *)cs, ConstColorSpaceRcPtr);
525 }
526 
527 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
528  const char *srcName,
529  const char *dstName)
530 {
531  ConstProcessorRcPtr *processor = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
532 
533  try {
534  *processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName);
535 
536  if (*processor)
537  return (OCIO_ConstProcessorRcPtr *)processor;
538  }
539  catch (Exception &exception) {
540  OCIO_reportException(exception);
541  }
542 
543  OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr);
544 
545  return 0;
546 }
547 
548 void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
549 {
550  OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr);
551 }
552 
553 OCIO_ConstCPUProcessorRcPtr *OCIOImpl::processorGetCPUProcessor(
554  OCIO_ConstProcessorRcPtr *processor)
555 {
556  ConstCPUProcessorRcPtr *cpu_processor = OBJECT_GUARDED_NEW(ConstCPUProcessorRcPtr);
557  *cpu_processor = (*(ConstProcessorRcPtr *)processor)->getDefaultCPUProcessor();
558  return (OCIO_ConstCPUProcessorRcPtr *)cpu_processor;
559 }
560 
561 void OCIOImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
562  OCIO_PackedImageDesc *img)
563 {
564  try {
565  (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*(PackedImageDesc *)img);
566  }
567  catch (Exception &exception) {
568  OCIO_reportException(exception);
569  }
570 }
571 
572 void OCIOImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
573  OCIO_PackedImageDesc *img_)
574 {
575  try {
576  PackedImageDesc *img = (PackedImageDesc *)img_;
577  int channels = img->getNumChannels();
578 
579  if (channels == 4) {
580  assert(img->isFloat());
581  float *pixels = (float *)img->getData();
582 
583  int width = img->getWidth();
584  int height = img->getHeight();
585 
586  for (int y = 0; y < height; y++) {
587  for (int x = 0; x < width; x++) {
588  float *pixel = pixels + 4 * (y * width + x);
589 
590  cpuProcessorApplyRGBA_predivide(cpu_processor, pixel);
591  }
592  }
593  }
594  else {
595  (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*img);
596  }
597  }
598  catch (Exception &exception) {
599  OCIO_reportException(exception);
600  }
601 }
602 
603 void OCIOImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
604 {
605  (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGB(pixel);
606 }
607 
608 void OCIOImpl::cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
609 {
610  (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
611 }
612 
613 void OCIOImpl::cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
614  float *pixel)
615 {
616  if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
617  (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
618  }
619  else {
620  float alpha, inv_alpha;
621 
622  alpha = pixel[3];
623  inv_alpha = 1.0f / alpha;
624 
625  pixel[0] *= inv_alpha;
626  pixel[1] *= inv_alpha;
627  pixel[2] *= inv_alpha;
628 
629  (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
630 
631  pixel[0] *= alpha;
632  pixel[1] *= alpha;
633  pixel[2] *= alpha;
634  }
635 }
636 
637 void OCIOImpl::cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
638 {
639  OBJECT_GUARDED_DELETE(cpu_processor, ConstCPUProcessorRcPtr);
640 }
641 
642 const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
643 {
644  return (*(ConstColorSpaceRcPtr *)cs)->getName();
645 }
646 
647 const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs)
648 {
649  return (*(ConstColorSpaceRcPtr *)cs)->getDescription();
650 }
651 
652 const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
653 {
654  return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
655 }
656 
657 OCIO_ConstProcessorRcPtr *OCIOImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr *config_,
658  const char *input,
659  const char *view,
660  const char *display,
661  const char *look,
662  const float scale,
663  const float exponent)
664 
665 {
666  ConstConfigRcPtr config = *(ConstConfigRcPtr *)config_;
667  GroupTransformRcPtr group = GroupTransform::Create();
668 
669  /* Exposure. */
670  if (scale != 1.0f) {
671  /* Always apply exposure in scene linear. */
672  ColorSpaceTransformRcPtr ct = ColorSpaceTransform::Create();
673  ct->setSrc(input);
674  ct->setDst(ROLE_SCENE_LINEAR);
675  group->appendTransform(ct);
676 
677  /* Make further transforms aware of the color space change. */
678  input = ROLE_SCENE_LINEAR;
679 
680  /* Apply scale. */
681  MatrixTransformRcPtr mt = MatrixTransform::Create();
682  const double matrix[16] = {
683  scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, 1.0};
684  mt->setMatrix(matrix);
685  group->appendTransform(mt);
686  }
687 
688  /* Add look transform. */
689  bool use_look = (look != nullptr && look[0] != 0);
690  if (use_look) {
691  const char *look_output = LookTransform::GetLooksResultColorSpace(
692  config, config->getCurrentContext(), look);
693 
694  if (look_output != nullptr && look_output[0] != 0) {
695  LookTransformRcPtr lt = LookTransform::Create();
696  lt->setSrc(input);
697  lt->setDst(look_output);
698  lt->setLooks(look);
699  group->appendTransform(lt);
700 
701  /* Make further transforms aware of the color space change. */
702  input = look_output;
703  }
704  else {
705  /* For empty looks, no output color space is returned. */
706  use_look = false;
707  }
708  }
709 
710  /* Add view and display transform. */
711  DisplayViewTransformRcPtr dvt = DisplayViewTransform::Create();
712  dvt->setSrc(input);
713  dvt->setLooksBypass(use_look);
714  dvt->setView(view);
715  dvt->setDisplay(display);
716  group->appendTransform(dvt);
717 
718  /* Gamma. */
719  if (exponent != 1.0f) {
720  ExponentTransformRcPtr et = ExponentTransform::Create();
721  const double value[4] = {exponent, exponent, exponent, 1.0};
722  et->setValue(value);
723  group->appendTransform(et);
724  }
725 
726  /* Create processor from transform. This is the moment were OCIO validates
727  * the entire transform, no need to check for the validity of inputs above. */
728  ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
729 
730  try {
731  *p = config->getProcessor(group);
732 
733  if (*p)
734  return (OCIO_ConstProcessorRcPtr *)p;
735  }
736  catch (Exception &exception) {
737  OCIO_reportException(exception);
738  }
739 
740  OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr);
741  return NULL;
742 }
743 
744 OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data,
745  long width,
746  long height,
747  long numChannels,
748  long chanStrideBytes,
749  long xStrideBytes,
750  long yStrideBytes)
751 {
752  try {
753  void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
754  PackedImageDesc *id = new (mem) PackedImageDesc(data,
755  width,
756  height,
757  numChannels,
758  BIT_DEPTH_F32,
759  chanStrideBytes,
760  xStrideBytes,
761  yStrideBytes);
762 
763  return (OCIO_PackedImageDesc *)id;
764  }
765  catch (Exception &exception) {
766  OCIO_reportException(exception);
767  }
768 
769  return NULL;
770 }
771 
772 void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
773 {
774  OBJECT_GUARDED_DELETE((PackedImageDesc *)id, PackedImageDesc);
775 }
776 
777 const char *OCIOImpl::getVersionString(void)
778 {
779  return GetVersion();
780 }
781 
782 int OCIOImpl::getVersionHex(void)
783 {
784  return GetVersionHex();
785 }
float srgb_to_linearrgb(float c)
Definition: math_color.c:434
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
#define mul_m3_series(...)
static AppView * view
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
static CCL_NAMESPACE_BEGIN const double alpha
static FT_Error err
Definition: freetypefont.c:52
CCL_NAMESPACE_BEGIN ccl_device float3 xyz_to_rgb(KernelGlobals *kg, float3 xyz)
Definition: kernel_color.h:24
#define fabsf(x)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
Definition: ocio_capi.cc:276
static const float OCIO_XYZ_TO_LINEAR_SRGB[3][3]
Definition: ocio_capi.h:51
static void OCIO_reportException(Exception &exception)
Definition: ocio_impl.cc:63
static bool to_scene_linear_matrix(ConstConfigRcPtr &config, const char *colorspace, float to_scene_linear[3][3])
Definition: ocio_impl.cc:296
static void OCIO_reportError(const char *err)
Definition: ocio_impl.cc:56
static float compare_floats(float a, float b, float abs_diff, int ulp_diff)
Definition: ocio_impl.cc:440
#define OCIO_abort()
Definition: ocio_impl.cc:46
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186