Real fix for OSX CMake -- was a typo in build file generation file
[blender.git] / intern / opencolorio / ocio_capi.cpp
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 #include "MEM_guardedalloc.h"
34
35 #define OCIO_CAPI_IMPLEMENTATION
36 #include "ocio_capi.h"
37
38 #ifdef NDEBUG
39 #  define OCIO_abort()
40 #else
41 #  include <stdlib.h>
42 #  define OCIO_abort() abort()
43 #endif
44
45 #if defined(_MSC_VER)
46 #  define __func__ __FUNCTION__
47 #endif
48
49 #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
50 #define MEM_DELETE(what, type) { what->~type(); MEM_freeN(what); } (void)0
51
52 static void OCIO_reportError(const char *err)
53 {
54         std::cerr << "OpenColorIO Error: " << err << std::endl;
55
56         OCIO_abort();
57 }
58
59 static void OCIO_reportException(Exception &exception)
60 {
61         OCIO_reportError(exception.what());
62 }
63
64 ConstConfigRcPtr *OCIO_getCurrentConfig(void)
65 {
66         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
67
68         try {
69                 *config = GetCurrentConfig();
70
71                 if(*config)
72                         return config;
73         }
74         catch (Exception &exception) {
75                 OCIO_reportException(exception);
76         }
77
78         return NULL;
79 }
80
81 void OCIO_setCurrentConfig(const ConstConfigRcPtr *config)
82 {
83         try {
84                 SetCurrentConfig(*config);
85         }
86         catch (Exception &exception) {
87                 OCIO_reportException(exception);
88         }
89 }
90
91 ConstConfigRcPtr *OCIO_configCreateFromEnv(void)
92 {
93         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
94
95         try {
96                 *config = Config::CreateFromEnv();
97
98                 if (*config)
99                         return config;
100         }
101         catch (Exception &exception) {
102                 OCIO_reportException(exception);
103         }
104
105         return NULL;
106 }
107
108
109 ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename)
110 {
111         ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
112
113         try {
114                 *config = Config::CreateFromFile(filename);
115
116                 if (*config)
117                         return config;
118         }
119         catch (Exception &exception) {
120                 OCIO_reportException(exception);
121         }
122
123         return NULL;
124 }
125
126 void OCIO_configRelease(ConstConfigRcPtr *config)
127 {
128         MEM_DELETE(config, ConstConfigRcPtr);
129 }
130
131 int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config)
132 {
133         try {
134                 return (*config)->getNumColorSpaces();
135         }
136         catch (Exception &exception) {
137                 OCIO_reportException(exception);
138         }
139
140         return 0;
141 }
142
143 const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index)
144 {
145         try {
146                 return (*config)->getColorSpaceNameByIndex(index);
147         }
148         catch (Exception &exception) {
149                 OCIO_reportException(exception);
150         }
151
152         return NULL;
153 }
154
155 ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name)
156 {
157         ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr);
158
159         try {
160                 *cs = (*config)->getColorSpace(name);
161
162                 if (*cs)
163                         return cs;
164         }
165         catch (Exception &exception) {
166                 OCIO_reportException(exception);
167                 MEM_DELETE(cs, ConstColorSpaceRcPtr);
168         }
169
170         return NULL;
171 }
172
173 int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name)
174 {
175         try {
176                 return (*config)->getIndexForColorSpace(name);
177         }
178         catch (Exception &exception) {
179                 OCIO_reportException(exception);
180         }
181
182         return -1;
183 }
184
185 const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config)
186 {
187         try {
188                 return (*config)->getDefaultDisplay();
189         }
190         catch (Exception &exception) {
191                 OCIO_reportException(exception);
192         }
193
194         return NULL;
195 }
196
197 int OCIO_configGetNumDisplays(ConstConfigRcPtr* config)
198 {
199         try {
200                 return (*config)->getNumDisplays();
201         }
202         catch (Exception &exception) {
203                 OCIO_reportException(exception);
204         }
205
206         return 0;
207 }
208
209 const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index)
210 {
211         try {
212                 return (*config)->getDisplay(index);
213         }
214         catch (Exception &exception) {
215                 OCIO_reportException(exception);
216         }
217
218         return NULL;
219 }
220
221 const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display)
222 {
223         try {
224                 return (*config)->getDefaultView(display);
225         }
226         catch (Exception &exception) {
227                 OCIO_reportException(exception);
228         }
229
230         return NULL;
231 }
232
233 int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display)
234 {
235         try {
236                 return (*config)->getNumViews(display);
237         }
238         catch (Exception &exception) {
239                 OCIO_reportException(exception);
240         }
241
242         return 0;
243 }
244
245 const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index)
246 {
247         try {
248                 return (*config)->getView(display, index);
249         }
250         catch (Exception &exception) {
251                 OCIO_reportException(exception);
252         }
253
254         return NULL;
255 }
256
257 const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view)
258 {
259         try {
260                 return (*config)->getDisplayColorSpaceName(display, view);
261         }
262         catch (Exception &exception) {
263                 OCIO_reportException(exception);
264         }
265
266         return NULL;
267 }
268
269 int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs)
270 {
271         const char *family = (*cs)->getFamily();
272
273         if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
274                 /* assume display and rrt transformations are not invertible
275                  * in fact some of them could be, but it doesn't make much sense to allow use them as invertible
276                  */
277                 return false;
278         }
279
280         if ((*cs)->isData()) {
281                 /* data color spaces don't have transformation at all */
282                 return true;
283         }
284
285         if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
286                 /* if there's defined transform to reference space, color space could be converted to scene linear */
287                 return true;
288         }
289
290         return true;
291 }
292
293 void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs)
294 {
295         MEM_DELETE(cs, ConstColorSpaceRcPtr);
296 }
297
298 ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName)
299 {
300         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
301
302         try {
303                 *p = (*config)->getProcessor(srcName, dstName);
304
305                 if (*p)
306                         return p;
307         }
308         catch (Exception &exception) {
309                 OCIO_reportException(exception);
310         }
311
312         return 0;
313 }
314
315 ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform)
316 {
317         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
318
319         try {
320                 *p = (*config)->getProcessor(*transform);
321
322                 if (*p)
323                         return p;
324         }
325         catch (Exception &exception) {
326                 OCIO_reportException(exception);
327         }
328
329         return NULL;
330 }
331
332 void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img)
333 {
334         try {
335                 (*processor)->apply(*img);
336         }
337         catch (Exception &exception) {
338                 OCIO_reportException(exception);
339         }
340 }
341
342 void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img)
343 {
344         try {
345                 int channels = img->getNumChannels();
346
347                 if (channels == 4) {
348                         float *pixels = img->getData();
349
350                         int width = img->getWidth();
351                         int height = img->getHeight();
352
353                         for (int y = 0; y < height; y++) {
354                                 for (int x = 0; x < width; x++) {
355                                         float *pixel = pixels + 4 * (y * width + x);
356
357                                         OCIO_processorApplyRGBA_predivide(processor, pixel);
358                                 }
359                         }
360                 }
361                 else {
362                         (*processor)->apply(*img);
363                 }
364         }
365         catch (Exception &exception) {
366                 OCIO_reportException(exception);
367         }
368 }
369
370 void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel)
371 {
372         (*processor)->applyRGB(pixel);
373 }
374
375 void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel)
376 {
377         (*processor)->applyRGBA(pixel);
378 }
379
380 void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel)
381 {
382         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
383                 (*processor)->applyRGBA(pixel);
384         }
385         else {
386                 float alpha, inv_alpha;
387
388                 alpha = pixel[3];
389                 inv_alpha = 1.0f / alpha;
390
391                 pixel[0] *= inv_alpha;
392                 pixel[1] *= inv_alpha;
393                 pixel[2] *= inv_alpha;
394
395                 (*processor)->applyRGBA(pixel);
396
397                 pixel[0] *= alpha;
398                 pixel[1] *= alpha;
399                 pixel[2] *= alpha;
400         }
401 }
402
403 void OCIO_processorRelease(ConstProcessorRcPtr *p)
404 {
405         p->~ConstProcessorRcPtr();
406         MEM_freeN(p);
407 }
408
409 const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs)
410 {
411         return (*cs)->getName();
412 }
413
414 const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs)
415 {
416         return (*cs)->getDescription();
417 }
418
419 const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs)
420 {
421         return (*cs)->getFamily();
422 }
423
424 DisplayTransformRcPtr *OCIO_createDisplayTransform(void)
425 {
426         DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
427
428         *dt = DisplayTransform::Create();
429
430         return dt;
431 }
432
433 void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name)
434 {
435         (*dt)->setInputColorSpaceName(name);
436 }
437
438 void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name)
439 {
440         (*dt)->setDisplay(name);
441 }
442
443 void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name)
444 {
445         (*dt)->setView(name);
446 }
447
448 void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
449 {
450         (*dt)->setDisplayCC(*t);
451 }
452
453 void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
454 {
455         (*dt)->setLinearCC(*t);
456 }
457
458 void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt)
459 {
460         MEM_DELETE(dt, DisplayTransformRcPtr);
461 }
462
463 PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels,
464                                             long chanStrideBytes, long xStrideBytes, long yStrideBytes)
465 {
466         try {
467                 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
468                 PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
469
470                 return id;
471         }
472         catch (Exception &exception) {
473                 OCIO_reportException(exception);
474         }
475
476         return NULL;
477 }
478
479 void OCIO_packedImageDescRelease(PackedImageDesc* id)
480 {
481         MEM_DELETE(id, PackedImageDesc);
482 }
483
484 ExponentTransformRcPtr *OCIO_createExponentTransform(void)
485 {
486         ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
487
488         *et = ExponentTransform::Create();
489
490         return et;
491 }
492
493 void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent)
494 {
495         (*et)->setValue(exponent);
496 }
497
498 void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et)
499 {
500         MEM_DELETE(et, ExponentTransformRcPtr);
501 }
502
503 MatrixTransformRcPtr *OCIO_createMatrixTransform(void)
504 {
505         MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
506
507         *mt = MatrixTransform::Create();
508
509         return mt;
510 }
511
512 void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
513 {
514         (*mt)->setValue(m44, offset4);
515 }
516
517 void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt)
518 {
519         MEM_DELETE(mt, MatrixTransformRcPtr);
520 }
521
522 void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f)
523 {
524         MatrixTransform::Scale(m44, offset4, scale4f);
525 }