2012-09-15 10:03:17 +00:00
|
|
|
/*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2012 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Xavier Thomas
|
|
|
|
* Lukas Toene,
|
|
|
|
* Sergey Sharybin
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <OpenColorIO/OpenColorIO.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#define OCIO_CAPI_IMPLEMENTATION
|
|
|
|
#include "ocio_capi.h"
|
|
|
|
|
|
|
|
#ifdef NDEBUG
|
|
|
|
# define OCIO_abort()
|
|
|
|
#else
|
|
|
|
# include <stdlib.h>
|
|
|
|
# define OCIO_abort() abort()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
# define __func__ __FUNCTION__
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type()
|
2012-09-18 19:20:26 +00:00
|
|
|
#define MEM_DELETE(what, type) if(what) { what->~type(); MEM_freeN(what); } (void)0
|
2012-09-15 10:03:17 +00:00
|
|
|
|
|
|
|
static void OCIO_reportError(const char *err)
|
|
|
|
{
|
|
|
|
std::cerr << "OpenColorIO Error: " << err << std::endl;
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
// OCIO_abort();
|
2012-09-15 10:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void OCIO_reportException(Exception &exception)
|
|
|
|
{
|
|
|
|
OCIO_reportError(exception.what());
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstConfigRcPtr *OCIO_getCurrentConfig(void)
|
|
|
|
{
|
|
|
|
ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
|
|
|
|
|
|
|
|
try {
|
|
|
|
*config = GetCurrentConfig();
|
|
|
|
|
|
|
|
if(*config)
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
MEM_DELETE(config, ConstConfigRcPtr);
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-16 15:17:22 +00:00
|
|
|
ConstConfigRcPtr *OCIO_getDefaultConfig(void)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
void OCIO_setCurrentConfig(const ConstConfigRcPtr *config)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
SetCurrentConfig(*config);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstConfigRcPtr *OCIO_configCreateFromEnv(void)
|
|
|
|
{
|
|
|
|
ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
|
|
|
|
|
|
|
|
try {
|
|
|
|
*config = Config::CreateFromEnv();
|
|
|
|
|
|
|
|
if (*config)
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
MEM_DELETE(config, ConstConfigRcPtr);
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename)
|
|
|
|
{
|
|
|
|
ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr);
|
|
|
|
|
|
|
|
try {
|
|
|
|
*config = Config::CreateFromFile(filename);
|
|
|
|
|
|
|
|
if (*config)
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
MEM_DELETE(config, ConstConfigRcPtr);
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_configRelease(ConstConfigRcPtr *config)
|
|
|
|
{
|
|
|
|
MEM_DELETE(config, ConstConfigRcPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getNumColorSpaces();
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getColorSpaceNameByIndex(index);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name)
|
|
|
|
{
|
|
|
|
ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr);
|
|
|
|
|
|
|
|
try {
|
|
|
|
*cs = (*config)->getColorSpace(name);
|
|
|
|
|
|
|
|
if (*cs)
|
|
|
|
return cs;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
MEM_DELETE(cs, ConstColorSpaceRcPtr);
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getIndexForColorSpace(name);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getDefaultDisplay();
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OCIO_configGetNumDisplays(ConstConfigRcPtr* config)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getNumDisplays();
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getDisplay(index);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getDefaultView(display);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getNumViews(display);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getView(display, index);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return (*config)->getDisplayColorSpaceName(display, view);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs)
|
|
|
|
{
|
|
|
|
const char *family = (*cs)->getFamily();
|
|
|
|
|
|
|
|
if (!strcmp(family, "rrt") || !strcmp(family, "display")) {
|
|
|
|
/* assume display and rrt transformations are not invertible
|
|
|
|
* in fact some of them could be, but it doesn't make much sense to allow use them as invertible
|
|
|
|
*/
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*cs)->isData()) {
|
|
|
|
/* data color spaces don't have transformation at all */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) {
|
|
|
|
/* if there's defined transform to reference space, color space could be converted to scene linear */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-19 15:01:36 +00:00
|
|
|
int OCIO_colorSpaceIsData(ConstColorSpaceRcPtr *cs)
|
|
|
|
{
|
|
|
|
return ((*cs)->isData());
|
|
|
|
}
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs)
|
|
|
|
{
|
|
|
|
MEM_DELETE(cs, ConstColorSpaceRcPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName)
|
|
|
|
{
|
|
|
|
ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
|
|
|
|
|
|
|
|
try {
|
|
|
|
*p = (*config)->getProcessor(srcName, dstName);
|
|
|
|
|
|
|
|
if (*p)
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
MEM_DELETE(p, ConstProcessorRcPtr);
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform)
|
|
|
|
{
|
|
|
|
ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr);
|
|
|
|
|
|
|
|
try {
|
|
|
|
*p = (*config)->getProcessor(*transform);
|
|
|
|
|
|
|
|
if (*p)
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
2012-09-18 19:20:26 +00:00
|
|
|
MEM_DELETE(p, ConstProcessorRcPtr);
|
|
|
|
|
2012-09-15 10:03:17 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
(*processor)->apply(*img);
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
int channels = img->getNumChannels();
|
|
|
|
|
|
|
|
if (channels == 4) {
|
|
|
|
float *pixels = img->getData();
|
|
|
|
|
|
|
|
int width = img->getWidth();
|
|
|
|
int height = img->getHeight();
|
|
|
|
|
|
|
|
for (int y = 0; y < height; y++) {
|
|
|
|
for (int x = 0; x < width; x++) {
|
|
|
|
float *pixel = pixels + 4 * (y * width + x);
|
|
|
|
|
|
|
|
OCIO_processorApplyRGBA_predivide(processor, pixel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
(*processor)->apply(*img);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel)
|
|
|
|
{
|
|
|
|
(*processor)->applyRGB(pixel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel)
|
|
|
|
{
|
|
|
|
(*processor)->applyRGBA(pixel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel)
|
|
|
|
{
|
|
|
|
if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
|
|
|
|
(*processor)->applyRGBA(pixel);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
float alpha, inv_alpha;
|
|
|
|
|
|
|
|
alpha = pixel[3];
|
|
|
|
inv_alpha = 1.0f / alpha;
|
|
|
|
|
|
|
|
pixel[0] *= inv_alpha;
|
|
|
|
pixel[1] *= inv_alpha;
|
|
|
|
pixel[2] *= inv_alpha;
|
|
|
|
|
|
|
|
(*processor)->applyRGBA(pixel);
|
|
|
|
|
|
|
|
pixel[0] *= alpha;
|
|
|
|
pixel[1] *= alpha;
|
|
|
|
pixel[2] *= alpha;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_processorRelease(ConstProcessorRcPtr *p)
|
|
|
|
{
|
|
|
|
p->~ConstProcessorRcPtr();
|
|
|
|
MEM_freeN(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs)
|
|
|
|
{
|
|
|
|
return (*cs)->getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs)
|
|
|
|
{
|
|
|
|
return (*cs)->getDescription();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs)
|
|
|
|
{
|
|
|
|
return (*cs)->getFamily();
|
|
|
|
}
|
|
|
|
|
|
|
|
DisplayTransformRcPtr *OCIO_createDisplayTransform(void)
|
|
|
|
{
|
|
|
|
DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr);
|
|
|
|
|
|
|
|
*dt = DisplayTransform::Create();
|
|
|
|
|
|
|
|
return dt;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name)
|
|
|
|
{
|
|
|
|
(*dt)->setInputColorSpaceName(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name)
|
|
|
|
{
|
|
|
|
(*dt)->setDisplay(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name)
|
|
|
|
{
|
|
|
|
(*dt)->setView(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
|
|
|
|
{
|
|
|
|
(*dt)->setDisplayCC(*t);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
|
|
|
|
{
|
|
|
|
(*dt)->setLinearCC(*t);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt)
|
|
|
|
{
|
|
|
|
MEM_DELETE(dt, DisplayTransformRcPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels,
|
|
|
|
long chanStrideBytes, long xStrideBytes, long yStrideBytes)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
|
|
|
|
PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
|
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
catch (Exception &exception) {
|
|
|
|
OCIO_reportException(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_packedImageDescRelease(PackedImageDesc* id)
|
|
|
|
{
|
|
|
|
MEM_DELETE(id, PackedImageDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExponentTransformRcPtr *OCIO_createExponentTransform(void)
|
|
|
|
{
|
|
|
|
ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr);
|
|
|
|
|
|
|
|
*et = ExponentTransform::Create();
|
|
|
|
|
|
|
|
return et;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent)
|
|
|
|
{
|
|
|
|
(*et)->setValue(exponent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et)
|
|
|
|
{
|
|
|
|
MEM_DELETE(et, ExponentTransformRcPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
MatrixTransformRcPtr *OCIO_createMatrixTransform(void)
|
|
|
|
{
|
|
|
|
MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr);
|
|
|
|
|
|
|
|
*mt = MatrixTransform::Create();
|
|
|
|
|
|
|
|
return mt;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
|
|
|
|
{
|
|
|
|
(*mt)->setValue(m44, offset4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt)
|
|
|
|
{
|
|
|
|
MEM_DELETE(mt, MatrixTransformRcPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f)
|
|
|
|
{
|
|
|
|
MatrixTransform::Scale(m44, offset4, scale4f);
|
|
|
|
}
|