Blender V4.3
ocio_impl.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cassert>
6#include <iostream>
7#include <math.h>
8#include <sstream>
9#include <string.h>
10
11#ifdef _MSC_VER
12# pragma warning(push)
13# pragma warning(disable : 4251 4275)
14#endif
15#include <OpenColorIO/OpenColorIO.h>
16#ifdef _MSC_VER
17# pragma warning(pop)
18#endif
19
20using namespace OCIO_NAMESPACE;
21
22#include "MEM_guardedalloc.h"
23
24#include "BLI_math_color.h"
25#include "BLI_math_color.hh"
26#include "BLI_math_matrix.h"
27#include "BLI_math_matrix.hh"
28
29#include "ocio_impl.h"
30
31#if !defined(WITH_ASSERT_ABORT)
32# define OCIO_abort()
33#else
34# include <stdlib.h>
35# define OCIO_abort() abort()
36#endif
37
38#if defined(_MSC_VER)
39# define __func__ __FUNCTION__
40#endif
41
43using blender::float3;
45
46static void OCIO_reportError(const char *err)
47{
48 std::cerr << "OpenColorIO Error: " << err << std::endl;
49
50 OCIO_abort();
51}
52
53static void OCIO_reportException(Exception &exception)
54{
55 OCIO_reportError(exception.what());
56}
57
58OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
59{
60 ConstConfigRcPtr *config = MEM_new<ConstConfigRcPtr>(__func__);
61
62 try {
63 *config = GetCurrentConfig();
64
65 if (*config) {
66 return (OCIO_ConstConfigRcPtr *)config;
67 }
68 }
69 catch (Exception &exception) {
70 OCIO_reportException(exception);
71 }
72
73 MEM_delete(config);
74
75 return NULL;
76}
77
78void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config)
79{
80 try {
81 SetCurrentConfig(*(ConstConfigRcPtr *)config);
82 }
83 catch (Exception &exception) {
84 OCIO_reportException(exception);
85 }
86}
87
88OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
89{
90 ConstConfigRcPtr *config = MEM_new<ConstConfigRcPtr>(__func__);
91
92 try {
93 *config = Config::CreateFromEnv();
94
95 if (*config) {
96 return (OCIO_ConstConfigRcPtr *)config;
97 }
98 }
99 catch (Exception &exception) {
100 OCIO_reportException(exception);
101 }
102
103 MEM_delete(config);
104
105 return NULL;
106}
107
108OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
109{
110 ConstConfigRcPtr *config = MEM_new<ConstConfigRcPtr>(__func__);
111
112 try {
113 *config = Config::CreateFromFile(filename);
114
115 if (*config) {
116 return (OCIO_ConstConfigRcPtr *)config;
117 }
118 }
119 catch (Exception &exception) {
120 OCIO_reportException(exception);
121 }
122
123 MEM_delete(config);
124
125 return NULL;
126}
127
128void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config)
129{
130 MEM_delete((ConstConfigRcPtr *)config);
131}
132
133int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config)
134{
135 try {
136 return (*(ConstConfigRcPtr *)config)->getNumColorSpaces();
137 }
138 catch (Exception &exception) {
139 OCIO_reportException(exception);
140 }
141
142 return 0;
143}
144
145const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
146{
147 try {
148 return (*(ConstConfigRcPtr *)config)->getColorSpaceNameByIndex(index);
149 }
150 catch (Exception &exception) {
151 OCIO_reportException(exception);
152 }
153
154 return NULL;
155}
156
157OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config,
158 const char *name)
159{
160 ConstColorSpaceRcPtr *cs = MEM_new<ConstColorSpaceRcPtr>(__func__);
161
162 try {
163 *cs = (*(ConstConfigRcPtr *)config)->getColorSpace(name);
164
165 if (*cs) {
166 return (OCIO_ConstColorSpaceRcPtr *)cs;
167 }
168 }
169 catch (Exception &exception) {
170 OCIO_reportException(exception);
171 }
172
173 MEM_delete(cs);
174
175 return NULL;
176}
177
178int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
179{
180 try {
181 return (*(ConstConfigRcPtr *)config)->getIndexForColorSpace(name);
182 }
183 catch (Exception &exception) {
184 OCIO_reportException(exception);
185 }
186
187 return -1;
188}
189
190const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config)
191{
192 try {
193 return (*(ConstConfigRcPtr *)config)->getDefaultDisplay();
194 }
195 catch (Exception &exception) {
196 OCIO_reportException(exception);
197 }
198
199 return NULL;
200}
201
202int OCIOImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr *config)
203{
204 try {
205 return (*(ConstConfigRcPtr *)config)->getNumDisplays();
206 }
207 catch (Exception &exception) {
208 OCIO_reportException(exception);
209 }
210
211 return 0;
212}
213
214const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index)
215{
216 try {
217 return (*(ConstConfigRcPtr *)config)->getDisplay(index);
218 }
219 catch (Exception &exception) {
220 OCIO_reportException(exception);
221 }
222
223 return NULL;
224}
225
226const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display)
227{
228 try {
229 return (*(ConstConfigRcPtr *)config)->getDefaultView(display);
230 }
231 catch (Exception &exception) {
232 OCIO_reportException(exception);
233 }
234
235 return NULL;
236}
237
238int OCIOImpl::configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display)
239{
240 try {
241 return (*(ConstConfigRcPtr *)config)->getNumViews(display);
242 }
243 catch (Exception &exception) {
244 OCIO_reportException(exception);
245 }
246
247 return 0;
248}
249
250const char *OCIOImpl::configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index)
251{
252 try {
253 return (*(ConstConfigRcPtr *)config)->getView(display, index);
254 }
255 catch (Exception &exception) {
256 OCIO_reportException(exception);
257 }
258
259 return NULL;
260}
261
262const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config,
263 const char *display,
264 const char *view)
265{
266 try {
267 const char *name = (*(ConstConfigRcPtr *)config)->getDisplayViewColorSpaceName(display, view);
268 /* OpenColorIO does not resolve this token for us, so do it ourselves. */
269 if (strcasecmp(name, "<USE_DISPLAY_NAME>") == 0) {
270 return display;
271 }
272 return name;
273 }
274 catch (Exception &exception) {
275 OCIO_reportException(exception);
276 }
277
278 return NULL;
279}
280
281void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb)
282{
283 try {
284 double rgb_double[3];
285 (*(ConstConfigRcPtr *)config)->getDefaultLumaCoefs(rgb_double);
286 rgb[0] = rgb_double[0];
287 rgb[1] = rgb_double[1];
288 rgb[2] = rgb_double[2];
289 }
290 catch (Exception &exception) {
291 OCIO_reportException(exception);
292 }
293}
294
295static bool to_scene_linear_matrix(ConstConfigRcPtr &config,
296 const char *colorspace,
297 float to_scene_linear[3][3])
298{
299 ConstProcessorRcPtr processor;
300 try {
301 processor = config->getProcessor(colorspace, ROLE_SCENE_LINEAR);
302 }
303 catch (Exception &exception) {
304 OCIO_reportException(exception);
305 return false;
306 }
307
308 if (!processor) {
309 return false;
310 }
311
312 ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
313 if (!cpu_processor) {
314 return false;
315 }
316
317 unit_m3(to_scene_linear);
318 cpu_processor->applyRGB(to_scene_linear[0]);
319 cpu_processor->applyRGB(to_scene_linear[1]);
320 cpu_processor->applyRGB(to_scene_linear[2]);
321 return true;
322}
323
324void OCIOImpl::configGetXYZtoSceneLinear(OCIO_ConstConfigRcPtr *config_,
325 float xyz_to_scene_linear[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. */
331 memcpy(xyz_to_scene_linear, OCIO_XYZ_TO_REC709, sizeof(OCIO_XYZ_TO_REC709));
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 ACES AP0 (ACES2065-1). */
340 float aces_to_scene_linear[3][3];
341 if (to_scene_linear_matrix(config, "aces_interchange", aces_to_scene_linear)) {
342 float xyz_to_aces[3][3];
343 invert_m3_m3(xyz_to_aces, OCIO_ACES_TO_XYZ);
344
345 mul_m3_m3m3(xyz_to_scene_linear, aces_to_scene_linear, xyz_to_aces);
346 }
347 }
348 else if (config->hasRole("XYZ")) {
349 /* Custom role used before the standard existed. */
350 to_scene_linear_matrix(config, "XYZ", xyz_to_scene_linear);
351 }
352}
353
354int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
355{
356 try {
357 return (*(ConstConfigRcPtr *)config)->getNumLooks();
358 }
359 catch (Exception &exception) {
360 OCIO_reportException(exception);
361 }
362
363 return 0;
364}
365
366const char *OCIOImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
367{
368 try {
369 return (*(ConstConfigRcPtr *)config)->getLookNameByIndex(index);
370 }
371 catch (Exception &exception) {
372 OCIO_reportException(exception);
373 }
374
375 return NULL;
376}
377
378OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, const char *name)
379{
380 ConstLookRcPtr *look = MEM_new<ConstLookRcPtr>(__func__);
381
382 try {
383 *look = (*(ConstConfigRcPtr *)config)->getLook(name);
384
385 if (*look) {
386 return (OCIO_ConstLookRcPtr *)look;
387 }
388 }
389 catch (Exception &exception) {
390 OCIO_reportException(exception);
391 }
392
393 MEM_delete(look);
394
395 return NULL;
396}
397
398const char *OCIOImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
399{
400 return (*(ConstLookRcPtr *)look)->getProcessSpace();
401}
402
403void OCIOImpl::lookRelease(OCIO_ConstLookRcPtr *look)
404{
405 MEM_delete((ConstLookRcPtr *)look);
406}
407
408int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
409{
410 ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *)cs_;
411 const char *family = (*cs)->getFamily();
412
413 if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
414 /* assume display and rrt transformations are not invertible in fact some of them could be,
415 * but it doesn't make much sense to allow use them as invertible. */
416 return false;
417 }
418
419 if ((*cs)->isData()) {
420 /* data color spaces don't have transformation at all */
421 return true;
422 }
423
424 if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
425 /* if there's defined transform to reference space,
426 * color space could be converted to scene linear. */
427 return true;
428 }
429
430 return true;
431}
432
433int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
434{
435 return (*(ConstColorSpaceRcPtr *)cs)->isData();
436}
437
438static float compare_floats(float a, float b, float abs_diff, int ulp_diff)
439{
440 /* Returns true if the absolute difference is smaller than abs_diff (for numbers near zero)
441 * or their relative difference is less than ulp_diff ULPs. Based on:
442 * https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ */
443 if (fabsf(a - b) < abs_diff) {
444 return true;
445 }
446
447 if ((a < 0.0f) != (b < 0.0f)) {
448 return false;
449 }
450
451 return (abs((*(int *)&a) - (*(int *)&b)) < ulp_diff);
452}
453
454void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
455 OCIO_ConstColorSpaceRcPtr *cs_,
456 bool &is_scene_linear,
457 bool &is_srgb)
458{
459 ConstConfigRcPtr *config = (ConstConfigRcPtr *)config_;
460 ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *)cs_;
461 ConstProcessorRcPtr processor;
462
463 try {
464 processor = (*config)->getProcessor((*cs)->getName(), "scene_linear");
465 }
466 catch (Exception &) {
467 /* Silently ignore if no conversion possible, then it's not scene linear or sRGB. */
468 is_scene_linear = false;
469 is_srgb = false;
470 return;
471 }
472
473 ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
474
475 is_scene_linear = true;
476 is_srgb = true;
477 for (int i = 0; i < 256; i++) {
478 float v = i / 255.0f;
479
480 float cR[3] = {v, 0, 0};
481 float cG[3] = {0, v, 0};
482 float cB[3] = {0, 0, v};
483 float cW[3] = {v, v, v};
484 cpu_processor->applyRGB(cR);
485 cpu_processor->applyRGB(cG);
486 cpu_processor->applyRGB(cB);
487 cpu_processor->applyRGB(cW);
488
489 /* Make sure that there is no channel crosstalk. */
490 if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
491 fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f)
492 {
493 is_scene_linear = false;
494 is_srgb = false;
495 break;
496 }
497 /* Make sure that the three primaries combine linearly. */
498 if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
499 !compare_floats(cB[2], cW[2], 1e-6f, 64))
500 {
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-4f, 64)) {
517 is_srgb = false;
518 }
519 }
520}
521
522void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
523{
524 MEM_delete((ConstColorSpaceRcPtr *)cs);
525}
526
527OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
528 const char *srcName,
529 const char *dstName)
530{
531 ConstProcessorRcPtr *processor = MEM_new<ConstProcessorRcPtr>(__func__);
532
533 try {
534 *processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName);
535
536 if (*processor) {
537 return (OCIO_ConstProcessorRcPtr *)processor;
538 }
539 }
540 catch (Exception &exception) {
541 OCIO_reportException(exception);
542 }
543
544 MEM_delete(processor);
545
546 return 0;
547}
548
549void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
550{
551 MEM_delete(processor);
552}
553
554OCIO_ConstCPUProcessorRcPtr *OCIOImpl::processorGetCPUProcessor(
555 OCIO_ConstProcessorRcPtr *processor)
556{
557 ConstCPUProcessorRcPtr *cpu_processor = MEM_new<ConstCPUProcessorRcPtr>(__func__);
558 *cpu_processor = (*(ConstProcessorRcPtr *)processor)->getDefaultCPUProcessor();
559 return (OCIO_ConstCPUProcessorRcPtr *)cpu_processor;
560}
561
562void OCIOImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
563 OCIO_PackedImageDesc *img)
564{
565 try {
566 (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*(PackedImageDesc *)img);
567 }
568 catch (Exception &exception) {
569 OCIO_reportException(exception);
570 }
571}
572
573void OCIOImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
574 OCIO_PackedImageDesc *img_)
575{
576 try {
577 PackedImageDesc *img = (PackedImageDesc *)img_;
578 int channels = img->getNumChannels();
579
580 if (channels == 4) {
581 /* Convert from premultiplied alpha to straight alpha. */
582 assert(img->isFloat());
583 float *pixel = (float *)img->getData();
584 size_t pixel_count = img->getWidth() * img->getHeight();
585 for (size_t i = 0; i < pixel_count; i++, pixel += 4) {
586 float alpha = pixel[3];
587 if (alpha != 0.0f && alpha != 1.0f) {
588 float inv_alpha = 1.0f / alpha;
589 pixel[0] *= inv_alpha;
590 pixel[1] *= inv_alpha;
591 pixel[2] *= inv_alpha;
592 }
593 }
594 }
595
596 (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*img);
597
598 if (channels == 4) {
599 /* Back to premultiplied alpha. */
600 assert(img->isFloat());
601 float *pixel = (float *)img->getData();
602 size_t pixel_count = img->getWidth() * img->getHeight();
603 for (size_t i = 0; i < pixel_count; i++, pixel += 4) {
604 float alpha = pixel[3];
605 if (alpha != 0.0f && alpha != 1.0f) {
606 pixel[0] *= alpha;
607 pixel[1] *= alpha;
608 pixel[2] *= alpha;
609 }
610 }
611 }
612 }
613 catch (Exception &exception) {
614 OCIO_reportException(exception);
615 }
616}
617
618bool OCIOImpl::cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
619{
620 return (*(ConstCPUProcessorRcPtr *)cpu_processor)->isNoOp();
621}
622
623void OCIOImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
624{
625 (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGB(pixel);
626}
627
628void OCIOImpl::cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
629{
630 (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
631}
632
633void OCIOImpl::cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
634 float *pixel)
635{
636 if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
637 (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
638 }
639 else {
640 float alpha, inv_alpha;
641
642 alpha = pixel[3];
643 inv_alpha = 1.0f / alpha;
644
645 pixel[0] *= inv_alpha;
646 pixel[1] *= inv_alpha;
647 pixel[2] *= inv_alpha;
648
649 (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
650
651 pixel[0] *= alpha;
652 pixel[1] *= alpha;
653 pixel[2] *= alpha;
654 }
655}
656
657void OCIOImpl::cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
658{
659 MEM_delete(cpu_processor);
660}
661
662const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
663{
664 return (*(ConstColorSpaceRcPtr *)cs)->getName();
665}
666
667const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs)
668{
669 return (*(ConstColorSpaceRcPtr *)cs)->getDescription();
670}
671
672const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
673{
674 return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
675}
676
677int OCIOImpl::colorSpaceGetNumAliases(OCIO_ConstColorSpaceRcPtr *cs)
678{
679 return (*(ConstColorSpaceRcPtr *)cs)->getNumAliases();
680}
681const char *OCIOImpl::colorSpaceGetAlias(OCIO_ConstColorSpaceRcPtr *cs, const int index)
682{
683 return (*(ConstColorSpaceRcPtr *)cs)->getAlias(index);
684}
685
686OCIO_ConstProcessorRcPtr *OCIOImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr *config_,
687 const char *input,
688 const char *view,
689 const char *display,
690 const char *look,
691 const float scale,
692 const float exponent,
693 const float temperature,
694 const float tint,
695 const bool use_white_balance,
696 const bool inverse)
697
698{
699 ConstConfigRcPtr config = *(ConstConfigRcPtr *)config_;
700 GroupTransformRcPtr group = GroupTransform::Create();
701
702 /* Linear transforms. */
703 if (scale != 1.0f || use_white_balance) {
704 /* Always apply exposure and/or white balance in scene linear. */
705 ColorSpaceTransformRcPtr ct = ColorSpaceTransform::Create();
706 ct->setSrc(input);
707 ct->setDst(ROLE_SCENE_LINEAR);
708 group->appendTransform(ct);
709
710 /* Make further transforms aware of the color space change. */
711 input = ROLE_SCENE_LINEAR;
712
713 /* Apply scale. */
714 MatrixTransformRcPtr mt = MatrixTransform::Create();
715 float3x3 matrix = float3x3::identity() * scale;
716
717 /* Apply white balance. */
718 if (use_white_balance) {
719 /* Compute white point of the scene space in XYZ.*/
720 float3x3 xyz_to_scene;
721 configGetXYZtoSceneLinear(config_, xyz_to_scene.ptr());
722 float3x3 scene_to_xyz = blender::math::invert(xyz_to_scene);
723 float3 target = scene_to_xyz * float3(1.0f);
724
725 /* Add operations to the matrix.
726 * Note: Since we're multiplying from the right, the operations here will be performed in
727 * reverse list order (scene-to-XYZ, then adaption, then XYZ-to-scene, then exposure). */
728 matrix *= xyz_to_scene;
730 blender::math::whitepoint_from_temp_tint(temperature, tint), target);
731 matrix *= scene_to_xyz;
732 }
733
734 mt->setMatrix(double4x4(blender::math::transpose(matrix)).base_ptr());
735 group->appendTransform(mt);
736 }
737
738 /* Add look transform. */
739 bool use_look = (look != nullptr && look[0] != 0);
740 if (use_look) {
741 const char *look_output = LookTransform::GetLooksResultColorSpace(
742 config, config->getCurrentContext(), look);
743
744 if (look_output != nullptr && look_output[0] != 0) {
745 LookTransformRcPtr lt = LookTransform::Create();
746 lt->setSrc(input);
747 lt->setDst(look_output);
748 lt->setLooks(look);
749 group->appendTransform(lt);
750
751 /* Make further transforms aware of the color space change. */
752 input = look_output;
753 }
754 else {
755 /* For empty looks, no output color space is returned. */
756 use_look = false;
757 }
758 }
759
760 /* Add view and display transform. */
761 DisplayViewTransformRcPtr dvt = DisplayViewTransform::Create();
762 dvt->setSrc(input);
763 dvt->setLooksBypass(use_look);
764 dvt->setView(view);
765 dvt->setDisplay(display);
766 group->appendTransform(dvt);
767
768 /* Gamma. */
769 if (exponent != 1.0f) {
770 ExponentTransformRcPtr et = ExponentTransform::Create();
771 const double value[4] = {exponent, exponent, exponent, 1.0};
772 et->setValue(value);
773 group->appendTransform(et);
774 }
775
776 if (inverse) {
777 group->setDirection(TRANSFORM_DIR_INVERSE);
778 }
779
780 /* Create processor from transform. This is the moment were OCIO validates
781 * the entire transform, no need to check for the validity of inputs above. */
782 ConstProcessorRcPtr *p = MEM_new<ConstProcessorRcPtr>(__func__);
783
784 try {
785 *p = config->getProcessor(group);
786
787 if (*p) {
788 return (OCIO_ConstProcessorRcPtr *)p;
789 }
790 }
791 catch (Exception &exception) {
792 OCIO_reportException(exception);
793 }
794
795 MEM_delete(p);
796 return NULL;
797}
798
799OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data,
800 long width,
801 long height,
802 long numChannels,
803 long chanStrideBytes,
804 long xStrideBytes,
805 long yStrideBytes)
806{
807 try {
808 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
809 PackedImageDesc *id = new (mem) PackedImageDesc(data,
810 width,
811 height,
812 numChannels,
813 BIT_DEPTH_F32,
814 chanStrideBytes,
815 xStrideBytes,
816 yStrideBytes);
817
818 return (OCIO_PackedImageDesc *)id;
819 }
820 catch (Exception &exception) {
821 OCIO_reportException(exception);
822 }
823
824 return NULL;
825}
826
827void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
828{
829 MEM_delete((PackedImageDesc *)id);
830}
831
832const char *OCIOImpl::getVersionString(void)
833{
834 return GetVersion();
835}
836
837int OCIOImpl::getVersionHex(void)
838{
839 return GetVersionHex();
840}
float srgb_to_linearrgb(float c)
void unit_m3(float m[3][3])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
static AppView * view
struct OCIO_ConstCPUProcessorRc * OCIO_ConstCPUProcessorRcPtr
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
ATTR_WARN_UNUSED_RESULT const BMVert * v
btMatrix3x3 inverse() const
Return the inverse of the matrix.
local_group_size(16, 16) .push_constant(Type b
#define NULL
#define fabsf(x)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
float3 whitepoint_from_temp_tint(float temperature, float tint)
CartesianBasis invert(const CartesianBasis &basis)
float3x3 chromatic_adaption_matrix(const float3 &from_XYZ, const float3 &to_XYZ)
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
MatBase< double, 4, 4 > double4x4
static const float OCIO_XYZ_TO_REC709[3][3]
Definition ocio_capi.h:35
static const float OCIO_ACES_TO_XYZ[3][3]
Definition ocio_capi.h:40
static void OCIO_reportException(Exception &exception)
Definition ocio_impl.cc:53
static bool to_scene_linear_matrix(ConstConfigRcPtr &config, const char *colorspace, float to_scene_linear[3][3])
Definition ocio_impl.cc:295
static void OCIO_reportError(const char *err)
Definition ocio_impl.cc:46
static float compare_floats(float a, float b, float abs_diff, int ulp_diff)
Definition ocio_impl.cc:438
#define OCIO_abort()
Definition ocio_impl.cc:32
const c_style_mat & ptr() const
ccl_device_inline int abs(int x)
Definition util/math.h:120