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