dff25f238a7b32c095c3d8ee269b61c04959d3d0
[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::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
286 {
287         try {
288                 return (*(ConstConfigRcPtr *) config)->getNumLooks();
289         }
290         catch (Exception &exception) {
291                 OCIO_reportException(exception);
292         }
293
294         return 0;
295 }
296
297 const char *OCIOImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index)
298 {
299         try {
300                 return (*(ConstConfigRcPtr *) config)->getLookNameByIndex(index);
301         }
302         catch (Exception &exception) {
303                 OCIO_reportException(exception);
304         }
305
306         return NULL;
307 }
308
309 OCIO_ConstLookRcPtr *OCIOImpl::configGetLook(OCIO_ConstConfigRcPtr *config, const char *name)
310 {
311         ConstLookRcPtr *look = MEM_NEW(ConstLookRcPtr);
312
313         try {
314                 *look = (*(ConstConfigRcPtr *) config)->getLook(name);
315
316                 if (*look)
317                         return (OCIO_ConstLookRcPtr *) look;
318         }
319         catch (Exception &exception) {
320                 OCIO_reportException(exception);
321         }
322
323         MEM_DELETE(look, ConstLookRcPtr);
324
325         return NULL;
326 }
327
328 const char *OCIOImpl::lookGetProcessSpace(OCIO_ConstLookRcPtr *look)
329 {
330         return (*(ConstLookRcPtr *) look)->getProcessSpace();
331 }
332
333 void OCIOImpl::lookRelease(OCIO_ConstLookRcPtr *look)
334 {
335         MEM_DELETE((ConstLookRcPtr *) look, ConstLookRcPtr);
336 }
337
338 int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_)
339 {
340         ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *) cs_;
341         const char *family = (*cs)->getFamily();
342
343         if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
344                 /* assume display and rrt transformations are not invertible
345                  * in fact some of them could be, but it doesn't make much sense to allow use them as invertible
346                  */
347                 return false;
348         }
349
350         if ((*cs)->isData()) {
351                 /* data color spaces don't have transformation at all */
352                 return true;
353         }
354
355         if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
356                 /* if there's defined transform to reference space, color space could be converted to scene linear */
357                 return true;
358         }
359
360         return true;
361 }
362
363 int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
364 {
365         return (*(ConstColorSpaceRcPtr *) cs)->isData();
366 }
367
368 void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
369 {
370         MEM_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr);
371 }
372
373 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
374 {
375         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
376
377         try {
378                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(srcName, dstName);
379
380                 if (*p)
381                         return (OCIO_ConstProcessorRcPtr *) p;
382         }
383         catch (Exception &exception) {
384                 OCIO_reportException(exception);
385         }
386
387         MEM_DELETE(p, ConstProcessorRcPtr);
388
389         return 0;
390 }
391
392 OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform)
393 {
394         ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
395
396         try {
397                 *p = (*(ConstConfigRcPtr *) config)->getProcessor(*(ConstTransformRcPtr *) transform);
398
399                 if (*p)
400                         return (OCIO_ConstProcessorRcPtr *) p;
401         }
402         catch (Exception &exception) {
403                 OCIO_reportException(exception);
404         }
405
406         MEM_DELETE(p, ConstProcessorRcPtr);
407
408         return NULL;
409 }
410
411 void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
412 {
413         try {
414                 (*(ConstProcessorRcPtr *) processor)->apply(*(PackedImageDesc *) img);
415         }
416         catch (Exception &exception) {
417                 OCIO_reportException(exception);
418         }
419 }
420
421 void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img_)
422 {
423         try {
424                 PackedImageDesc *img = (PackedImageDesc *) img_;
425                 int channels = img->getNumChannels();
426
427                 if (channels == 4) {
428                         float *pixels = img->getData();
429
430                         int width = img->getWidth();
431                         int height = img->getHeight();
432
433                         for (int y = 0; y < height; y++) {
434                                 for (int x = 0; x < width; x++) {
435                                         float *pixel = pixels + 4 * (y * width + x);
436
437                                         processorApplyRGBA_predivide(processor, pixel);
438                                 }
439                         }
440                 }
441                 else {
442                         (*(ConstProcessorRcPtr *) processor)->apply(*img);
443                 }
444         }
445         catch (Exception &exception) {
446                 OCIO_reportException(exception);
447         }
448 }
449
450 void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
451 {
452         (*(ConstProcessorRcPtr *) processor)->applyRGB(pixel);
453 }
454
455 void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
456 {
457         (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
458 }
459
460 void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
461 {
462         if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
463                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
464         }
465         else {
466                 float alpha, inv_alpha;
467
468                 alpha = pixel[3];
469                 inv_alpha = 1.0f / alpha;
470
471                 pixel[0] *= inv_alpha;
472                 pixel[1] *= inv_alpha;
473                 pixel[2] *= inv_alpha;
474
475                 (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel);
476
477                 pixel[0] *= alpha;
478                 pixel[1] *= alpha;
479                 pixel[2] *= alpha;
480         }
481 }
482
483 void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p)
484 {
485         MEM_DELETE(p, ConstProcessorRcPtr);
486 }
487
488 const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
489 {
490         return (*(ConstColorSpaceRcPtr *) cs)->getName();
491 }
492
493 const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs)
494 {
495         return (*(ConstColorSpaceRcPtr *) cs)->getDescription();
496 }
497
498 const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
499 {
500         return (*(ConstColorSpaceRcPtr *)cs)->getFamily();
501 }
502
503 OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void)
504 {
505         DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
506
507         *dt = DisplayTransform::Create();
508
509         return (OCIO_DisplayTransformRcPtr *) dt;
510 }
511
512 void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name)
513 {
514         (*(DisplayTransformRcPtr *) dt)->setInputColorSpaceName(name);
515 }
516
517 void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name)
518 {
519         (*(DisplayTransformRcPtr *) dt)->setDisplay(name);
520 }
521
522 void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name)
523 {
524         (*(DisplayTransformRcPtr *) dt)->setView(name);
525 }
526
527 void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
528 {
529         (*(DisplayTransformRcPtr *) dt)->setDisplayCC(* (ConstTransformRcPtr *) t);
530 }
531
532 void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t)
533 {
534         (*(DisplayTransformRcPtr *) dt)->setLinearCC(*(ConstTransformRcPtr *) t);
535 }
536
537 void OCIOImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks)
538 {
539         (*(DisplayTransformRcPtr *) dt)->setLooksOverride(looks);
540 }
541
542 void OCIOImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled)
543 {
544         (*(DisplayTransformRcPtr *) dt)->setLooksOverrideEnabled(enabled);
545 }
546
547 void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
548 {
549         MEM_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr);
550 }
551
552 OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
553                                                            long chanStrideBytes, long xStrideBytes, long yStrideBytes)
554 {
555         try {
556                 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
557                 PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
558
559                 return (OCIO_PackedImageDesc *) id;
560         }
561         catch (Exception &exception) {
562                 OCIO_reportException(exception);
563         }
564
565         return NULL;
566 }
567
568 void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
569 {
570         MEM_DELETE((PackedImageDesc *) id, PackedImageDesc);
571 }
572
573 OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void)
574 {
575         ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
576
577         *et = ExponentTransform::Create();
578
579         return (OCIO_ExponentTransformRcPtr *) et;
580 }
581
582 void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent)
583 {
584         (*(ExponentTransformRcPtr *) et)->setValue(exponent);
585 }
586
587 void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et)
588 {
589         MEM_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr);
590 }
591
592 OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void)
593 {
594         MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
595
596         *mt = MatrixTransform::Create();
597
598         return (OCIO_MatrixTransformRcPtr *) mt;
599 }
600
601 void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
602 {
603         (*(MatrixTransformRcPtr *) mt)->setValue(m44, offset4);
604 }
605
606 void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt)
607 {
608         MEM_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr);
609 }
610
611 void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4f)
612 {
613         MatrixTransform::Scale(m44, offset4, scale4f);
614 }