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