2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2012 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Xavier Thomas
25 * ***** END GPL LICENSE BLOCK *****
31 #include <OpenColorIO/OpenColorIO.h>
33 #include "MEM_guardedalloc.h"
35 #define OCIO_CAPI_IMPLEMENTATION
36 #include "ocio_capi.h"
42 # define OCIO_abort() abort()
46 # define __func__ __FUNCTION__
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
52 static void OCIO_reportError(const char *err)
54 std::cerr << "OpenColorIO Error: " << err << std::endl;
59 static void OCIO_reportException(Exception &exception)
61 OCIO_reportError(exception.what());
64 ConstConfigRcPtr *OCIO_getCurrentConfig(void)
66 ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
69 *config = GetCurrentConfig();
74 catch (Exception &exception) {
75 OCIO_reportException(exception);
81 void OCIO_setCurrentConfig(const ConstConfigRcPtr *config)
84 SetCurrentConfig(*config);
86 catch (Exception &exception) {
87 OCIO_reportException(exception);
91 ConstConfigRcPtr *OCIO_configCreateFromEnv(void)
93 ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
96 *config = Config::CreateFromEnv();
101 catch (Exception &exception) {
102 OCIO_reportException(exception);
109 ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename)
111 ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
114 *config = Config::CreateFromFile(filename);
119 catch (Exception &exception) {
120 OCIO_reportException(exception);
126 void OCIO_configRelease(ConstConfigRcPtr *config)
128 MEM_DELETE(config, ConstConfigRcPtr);
131 int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config)
134 return (*config)->getNumColorSpaces();
136 catch (Exception &exception) {
137 OCIO_reportException(exception);
143 const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index)
146 return (*config)->getColorSpaceNameByIndex(index);
148 catch (Exception &exception) {
149 OCIO_reportException(exception);
155 ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name)
157 ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr);
160 *cs = (*config)->getColorSpace(name);
165 catch (Exception &exception) {
166 OCIO_reportException(exception);
167 MEM_DELETE(cs, ConstColorSpaceRcPtr);
173 int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name)
176 return (*config)->getIndexForColorSpace(name);
178 catch (Exception &exception) {
179 OCIO_reportException(exception);
185 const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config)
188 return (*config)->getDefaultDisplay();
190 catch (Exception &exception) {
191 OCIO_reportException(exception);
197 int OCIO_configGetNumDisplays(ConstConfigRcPtr* config)
200 return (*config)->getNumDisplays();
202 catch (Exception &exception) {
203 OCIO_reportException(exception);
209 const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index)
212 return (*config)->getDisplay(index);
214 catch (Exception &exception) {
215 OCIO_reportException(exception);
221 const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display)
224 return (*config)->getDefaultView(display);
226 catch (Exception &exception) {
227 OCIO_reportException(exception);
233 int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display)
236 return (*config)->getNumViews(display);
238 catch (Exception &exception) {
239 OCIO_reportException(exception);
245 const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index)
248 return (*config)->getView(display, index);
250 catch (Exception &exception) {
251 OCIO_reportException(exception);
257 const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view)
260 return (*config)->getDisplayColorSpaceName(display, view);
262 catch (Exception &exception) {
263 OCIO_reportException(exception);
269 int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs)
271 const char *family = (*cs)->getFamily();
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
280 if ((*cs)->isData()) {
281 /* data color spaces don't have transformation at all */
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 */
293 void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs)
295 MEM_DELETE(cs, ConstColorSpaceRcPtr);
298 ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName)
300 ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
303 *p = (*config)->getProcessor(srcName, dstName);
308 catch (Exception &exception) {
309 OCIO_reportException(exception);
315 ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform)
317 ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
320 *p = (*config)->getProcessor(*transform);
325 catch (Exception &exception) {
326 OCIO_reportException(exception);
332 void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img)
335 (*processor)->apply(*img);
337 catch (Exception &exception) {
338 OCIO_reportException(exception);
342 void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img)
345 int channels = img->getNumChannels();
348 float *pixels = img->getData();
350 int width = img->getWidth();
351 int height = img->getHeight();
353 for (int y = 0; y < height; y++) {
354 for (int x = 0; x < width; x++) {
355 float *pixel = pixels + 4 * (y * width + x);
357 OCIO_processorApplyRGBA_predivide(processor, pixel);
362 (*processor)->apply(*img);
365 catch (Exception &exception) {
366 OCIO_reportException(exception);
370 void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel)
372 (*processor)->applyRGB(pixel);
375 void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel)
377 (*processor)->applyRGBA(pixel);
380 void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel)
382 if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
383 (*processor)->applyRGBA(pixel);
386 float alpha, inv_alpha;
389 inv_alpha = 1.0f / alpha;
391 pixel[0] *= inv_alpha;
392 pixel[1] *= inv_alpha;
393 pixel[2] *= inv_alpha;
395 (*processor)->applyRGBA(pixel);
403 void OCIO_processorRelease(ConstProcessorRcPtr *p)
405 p->~ConstProcessorRcPtr();
409 const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs)
411 return (*cs)->getName();
414 const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs)
416 return (*cs)->getDescription();
419 const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs)
421 return (*cs)->getFamily();
424 DisplayTransformRcPtr *OCIO_createDisplayTransform(void)
426 DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
428 *dt = DisplayTransform::Create();
433 void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name)
435 (*dt)->setInputColorSpaceName(name);
438 void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name)
440 (*dt)->setDisplay(name);
443 void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name)
445 (*dt)->setView(name);
448 void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
450 (*dt)->setDisplayCC(*t);
453 void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
455 (*dt)->setLinearCC(*t);
458 void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt)
460 MEM_DELETE(dt, DisplayTransformRcPtr);
463 PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels,
464 long chanStrideBytes, long xStrideBytes, long yStrideBytes)
467 void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
468 PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
472 catch (Exception &exception) {
473 OCIO_reportException(exception);
479 void OCIO_packedImageDescRelease(PackedImageDesc* id)
481 MEM_DELETE(id, PackedImageDesc);
484 ExponentTransformRcPtr *OCIO_createExponentTransform(void)
486 ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
488 *et = ExponentTransform::Create();
493 void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent)
495 (*et)->setValue(exponent);
498 void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et)
500 MEM_DELETE(et, ExponentTransformRcPtr);
503 MatrixTransformRcPtr *OCIO_createMatrixTransform(void)
505 MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
507 *mt = MatrixTransform::Create();
512 void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
514 (*mt)->setValue(m44, offset4);
517 void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt)
519 MEM_DELETE(mt, MatrixTransformRcPtr);
522 void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f)
524 MatrixTransform::Scale(m44, offset4, scale4f);