Merged changes in the trunk up to revision 51448.
[blender.git] / intern / opencolorio / ocio_impl.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Xavier Thomas
22  *                 Lukas Toene,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <iostream>
29 #include <string.h>
30
31 #include <OpenColorIO/OpenColorIO.h>
32
33 using namespace OCIO_NAMESPACE;
34
35 #include "MEM_guardedalloc.h"
36
37 #include "ocio_impl.h"
38
39 #if !defined(WITH_ASSERT_ABORT)
40 #  define OCIO_abort()
41 #else
42 #  include <stdlib.h>
43 #  define OCIO_abort() abort()
44 #endif
45
46 #if defined(_MSC_VER)
47 #  define __func__ __FUNCTION__
48 #endif
49
50 #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
51 #define MEM_DELETE(what, type) if(what) { (what)->~type(); MEM_freeN(what); } (void)0
52
53 static void OCIO_reportError(const char *err)
54 {
55         std::cerr << "OpenColorIO Error: " << err << std::endl;
56
57         OCIO_abort();
58 }
59
60 static void OCIO_reportException(Exception &exception)
61 {
62         OCIO_reportError(exception.what());
63 }
64
65 OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void)
66 {
67         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
68
69         try {
70                 *config = GetCurrentConfig();
71
72                 if (*config)
73                         return (OCIO_ConstConfigRcPtr *) config;
74         }
75         catch (Exception &exception) {
76                 OCIO_reportException(exception);
77         }
78
79         MEM_DELETE(config, ConstConfigRcPtr);
80
81         return NULL;
82 }
83
84 void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config)
85 {
86         try {
87                 SetCurrentConfig(*(ConstConfigRcPtr *) config);
88         }
89         catch (Exception &exception) {
90                 OCIO_reportException(exception);
91         }
92 }
93
94 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void)
95 {
96         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
97
98         try {
99                 *config = Config::CreateFromEnv();
100
101                 if (*config)
102                         return (OCIO_ConstConfigRcPtr *) config;
103         }
104         catch (Exception &exception) {
105                 OCIO_reportException(exception);
106         }
107
108         MEM_DELETE(config, ConstConfigRcPtr);
109
110         return NULL;
111 }
112
113
114 OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename)
115 {
116         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
117
118         try {
119                 *config = Config::CreateFromFile(filename);
120
121                 if (*config)
122                         return (OCIO_ConstConfigRcPtr *) config;
123         }
124         catch (Exception &exception) {
125                 OCIO_reportException(exception);
126         }
127
128         MEM_DELETE(config, ConstConfigRcPtr);
129
130         return NULL;
131 }
132
133 void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config)
134 {
135         MEM_DELETE((ConstConfigRcPtr *) config, ConstConfigRcPtr);
136 }
137
138 int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config)
139 {
140         try {
141                 return (*(ConstConfigRcPtr *) config)->getNumColorSpaces();
142         }
143         catch (Exception &exception) {
144                 OCIO_reportException(exception);
145         }
146
147         return 0;
148 }
149
150 const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
151 {
152         try {
153                 return (*(ConstConfigRcPtr *) config)->getColorSpaceNameByIndex(index);
154         }
155         catch (Exception &exception) {
156                 OCIO_reportException(exception);
157         }
158
159         return NULL;
160 }
161
162 OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
163 {
164         ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr);
165
166         try {
167                 *cs = (*(ConstConfigRcPtr *) config)->getColorSpace(name);
168
169                 if (*cs)
170                         return (OCIO_ConstColorSpaceRcPtr *) cs;
171         }
172         catch (Exception &exception) {
173                 OCIO_reportException(exception);
174         }
175
176         MEM_DELETE(cs, ConstColorSpaceRcPtr);
177
178         return NULL;
179 }
180
181 int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
182 {
183         try {
184                 return (*(ConstConfigRcPtr *) config)->getIndexForColorSpace(name);
185         }
186         catch (Exception &exception) {
187                 OCIO_reportException(exception);
188         }
189
190         return -1;
191 }
192
193 const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config)
194 {
195         try {
196                 return (*(ConstConfigRcPtr *) config)->getDefaultDisplay();
197         }
198         catch (Exception &exception) {
199                 OCIO_reportException(exception);
200         }
201
202         return NULL;
203 }
204
205 int OCIOImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr* config)
206 {
207         try {
208                 return (*(ConstConfigRcPtr *) config)->getNumDisplays();
209         }
210         catch (Exception &exception) {
211                 OCIO_reportException(exception);
212         }
213
214         return 0;
215 }
216
217 const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index)
218 {
219         try {
220                 return (*(ConstConfigRcPtr *) config)->getDisplay(index);
221         }
222         catch (Exception &exception) {
223                 OCIO_reportException(exception);
224         }
225
226         return NULL;
227 }
228
229 const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display)
230 {
231         try {
232                 return (*(ConstConfigRcPtr *) config)->getDefaultView(display);
233         }
234         catch (Exception &exception) {
235                 OCIO_reportException(exception);
236         }
237
238         return NULL;
239 }
240
241 int OCIOImpl::configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display)
242 {
243         try {
244                 return (*(ConstConfigRcPtr *) config)->getNumViews(display);
245         }
246         catch (Exception &exception) {
247                 OCIO_reportException(exception);
248         }
249
250         return 0;
251 }
252
253 const char *OCIOImpl::configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index)
254 {
255         try {
256                 return (*(ConstConfigRcPtr *) config)->getView(display, index);
257         }
258         catch (Exception &exception) {
259                 OCIO_reportException(exception);
260         }
261
262         return NULL;
263 }
264
265 const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view)
266 {
267         try {
268                 return (*(ConstConfigRcPtr *) config)->getDisplayColorSpaceName(display, view);
269         }
270         catch (Exception &exception) {
271                 OCIO_reportException(exception);
272         }
273
274         return NULL;
275 }
276
277 int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
278 {
279         ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *) cs_;
280         const char *family = (*cs)->getFamily();
281
282         if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
283                 /* assume display and rrt transformations are not invertible
284                  * in fact some of them could be, but it doesn't make much sense to allow use them as invertible
285                  */
286                 return false;
287         }
288
289         if ((*cs)->isData()) {
290                 /* data color spaces don't have transformation at all */
291                 return true;
292         }
293
294         if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
295                 /* if there's defined transform to reference space, color space could be converted to scene linear */
296                 return true;
297         }
298
299         return true;
300 }
301
302 int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
303 {
304         return (*(ConstColorSpaceRcPtr *) cs)->isData();
305 }
306
307 void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
308 {
309         MEM_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr);
310 }
311
312 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
313 {
314         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
315
316         try {
317                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(srcName, dstName);
318
319                 if (*p)
320                         return (OCIO_ConstProcessorRcPtr *) p;
321         }
322         catch (Exception &exception) {
323                 OCIO_reportException(exception);
324         }
325
326         MEM_DELETE(p, ConstProcessorRcPtr);
327
328         return 0;
329 }
330
331 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform)
332 {
333         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
334
335         try {
336                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(*(ConstTransformRcPtr *) transform);
337
338                 if (*p)
339                         return (OCIO_ConstProcessorRcPtr *) p;
340         }
341         catch (Exception &exception) {
342                 OCIO_reportException(exception);
343         }
344
345         MEM_DELETE(p, ConstProcessorRcPtr);
346
347         return NULL;
348 }
349
350 void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
351 {
352         try {
353                 (*(ConstProcessorRcPtr *) processor)->apply(*(PackedImageDesc *) img);
354         }
355         catch (Exception &exception) {
356                 OCIO_reportException(exception);
357         }
358 }
359
360 void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img_)
361 {
362         try {
363                 PackedImageDesc *img = (PackedImageDesc *) img_;
364                 int channels = img->getNumChannels();
365
366                 if (channels == 4) {
367                         float *pixels = img->getData();
368
369                         int width = img->getWidth();
370                         int height = img->getHeight();
371
372                         for (int y = 0; y < height; y++) {
373                                 for (int x = 0; x < width; x++) {
374                                         float *pixel = pixels + 4 * (y * width + x);
375
376                                         processorApplyRGBA_predivide(processor, pixel);
377                                 }
378                         }
379                 }
380                 else {
381                         (*(ConstProcessorRcPtr *) processor)->apply(*img);
382                 }
383         }
384         catch (Exception &exception) {
385                 OCIO_reportException(exception);
386         }
387 }
388
389 void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
390 {
391         (*(ConstProcessorRcPtr *) processor)->applyRGB(pixel);
392 }
393
394 void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
395 {
396         (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
397 }
398
399 void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
400 {
401         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
402                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
403         }
404         else {
405                 float alpha, inv_alpha;
406
407                 alpha = pixel[3];
408                 inv_alpha = 1.0f / alpha;
409
410                 pixel[0] *= inv_alpha;
411                 pixel[1] *= inv_alpha;
412                 pixel[2] *= inv_alpha;
413
414                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
415
416                 pixel[0] *= alpha;
417                 pixel[1] *= alpha;
418                 pixel[2] *= alpha;
419         }
420 }
421
422 void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p)
423 {
424         p->~OCIO_ConstProcessorRcPtr();
425         MEM_freeN(p);
426 }
427
428 const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
429 {
430         return (*(ConstColorSpaceRcPtr *) cs)->getName();
431 }
432
433 const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs)
434 {
435         return (*(ConstColorSpaceRcPtr *) cs)->getDescription();
436 }
437
438 const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
439 {
440         return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
441 }
442
443 OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void)
444 {
445         DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
446
447         *dt = DisplayTransform::Create();
448
449         return (OCIO_DisplayTransformRcPtr *) dt;
450 }
451
452 void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name)
453 {
454         (*(DisplayTransformRcPtr *) dt)->setInputColorSpaceName(name);
455 }
456
457 void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name)
458 {
459         (*(DisplayTransformRcPtr *) dt)->setDisplay(name);
460 }
461
462 void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name)
463 {
464         (*(DisplayTransformRcPtr *) dt)->setView(name);
465 }
466
467 void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
468 {
469         (*(DisplayTransformRcPtr *) dt)->setDisplayCC(* (ConstTransformRcPtr *) t);
470 }
471
472 void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
473 {
474         (*(DisplayTransformRcPtr *) dt)->setLinearCC(*(ConstTransformRcPtr *) t);
475 }
476
477 void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
478 {
479         MEM_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr);
480 }
481
482 OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
483                                                  long chanStrideBytes, long xStrideBytes, long yStrideBytes)
484 {
485         try {
486                 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
487                 PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
488
489                 return (OCIO_PackedImageDesc *) id;
490         }
491         catch (Exception &exception) {
492                 OCIO_reportException(exception);
493         }
494
495         return NULL;
496 }
497
498 void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
499 {
500         MEM_DELETE((PackedImageDesc *) id, PackedImageDesc);
501 }
502
503 OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void)
504 {
505         ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
506
507         *et = ExponentTransform::Create();
508
509         return (OCIO_ExponentTransformRcPtr *) et;
510 }
511
512 void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent)
513 {
514         (*(ExponentTransformRcPtr *) et)->setValue(exponent);
515 }
516
517 void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
518 {
519         MEM_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr);
520 }
521
522 OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void)
523 {
524         MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
525
526         *mt = MatrixTransform::Create();
527
528         return (OCIO_MatrixTransformRcPtr *) mt;
529 }
530
531 void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
532 {
533         (*(MatrixTransformRcPtr *) mt)->setValue(m44, offset4);
534 }
535
536 void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
537 {
538         MEM_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr);
539 }
540
541 void OCIOImpl::matrixTransformScale(float * m44, float * offset4, const float *scale4f)
542 {
543         MatrixTransform::Scale(m44, offset4, scale4f);
544 }