summaryrefslogtreecommitdiff
path: root/src/core/DisplayTransform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/DisplayTransform.cpp')
-rw-r--r--src/core/DisplayTransform.cpp410
1 files changed, 410 insertions, 0 deletions
diff --git a/src/core/DisplayTransform.cpp b/src/core/DisplayTransform.cpp
new file mode 100644
index 0000000..35216db
--- /dev/null
+++ b/src/core/DisplayTransform.cpp
@@ -0,0 +1,410 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "OpBuilders.h"
+
+#include <cmath>
+#include <cstring>
+#include <iterator>
+
+OCIO_NAMESPACE_ENTER
+{
+ DisplayTransformRcPtr DisplayTransform::Create()
+ {
+ return DisplayTransformRcPtr(new DisplayTransform(), &deleter);
+ }
+
+ void DisplayTransform::deleter(DisplayTransform* t)
+ {
+ delete t;
+ }
+
+ class DisplayTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ std::string inputColorSpaceName_;
+ TransformRcPtr linearCC_;
+ TransformRcPtr colorTimingCC_;
+ TransformRcPtr channelView_;
+ std::string display_;
+ std::string view_;
+ TransformRcPtr displayCC_;
+
+ std::string looksOverride_;
+ bool looksOverrideEnabled_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD),
+ looksOverrideEnabled_(false)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ inputColorSpaceName_ = rhs.inputColorSpaceName_;
+
+ linearCC_ = rhs.linearCC_;
+ if(linearCC_) linearCC_ = linearCC_->createEditableCopy();
+
+ colorTimingCC_ = rhs.colorTimingCC_;
+ if(colorTimingCC_) colorTimingCC_ = colorTimingCC_->createEditableCopy();
+
+ channelView_ = rhs.channelView_;
+ if(channelView_) channelView_ = channelView_->createEditableCopy();
+
+ display_ = rhs.display_;
+ view_ = rhs.view_;
+
+ displayCC_ = rhs.displayCC_;
+ if(displayCC_) displayCC_ = displayCC_->createEditableCopy();
+
+ looksOverride_ = rhs.looksOverride_;
+ looksOverrideEnabled_ = rhs.looksOverrideEnabled_;
+
+ return *this;
+ }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ DisplayTransform::DisplayTransform()
+ : m_impl(new DisplayTransform::Impl)
+ {
+ }
+
+ TransformRcPtr DisplayTransform::createEditableCopy() const
+ {
+ DisplayTransformRcPtr transform = DisplayTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ DisplayTransform::~DisplayTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ DisplayTransform& DisplayTransform::operator= (const DisplayTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection DisplayTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void DisplayTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ void DisplayTransform::setInputColorSpaceName(const char * name)
+ {
+ getImpl()->inputColorSpaceName_ = name;
+ }
+
+ const char * DisplayTransform::getInputColorSpaceName() const
+ {
+ return getImpl()->inputColorSpaceName_.c_str();
+ }
+
+ void DisplayTransform::setLinearCC(const ConstTransformRcPtr & cc)
+ {
+ getImpl()->linearCC_ = cc->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getLinearCC() const
+ {
+ return getImpl()->linearCC_;
+ }
+
+ void DisplayTransform::setColorTimingCC(const ConstTransformRcPtr & cc)
+ {
+ getImpl()->colorTimingCC_ = cc->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getColorTimingCC() const
+ {
+ return getImpl()->colorTimingCC_;
+ }
+
+ void DisplayTransform::setChannelView(const ConstTransformRcPtr & transform)
+ {
+ getImpl()->channelView_ = transform->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getChannelView() const
+ {
+ return getImpl()->channelView_;
+ }
+
+ void DisplayTransform::setDisplay(const char * display)
+ {
+ getImpl()->display_ = display;
+ }
+
+ const char * DisplayTransform::getDisplay() const
+ {
+ return getImpl()->display_.c_str();
+ }
+
+ void DisplayTransform::setView(const char * view)
+ {
+ getImpl()->view_ = view;
+ }
+
+ const char * DisplayTransform::getView() const
+ {
+ return getImpl()->view_.c_str();
+ }
+
+ void DisplayTransform::setDisplayCC(const ConstTransformRcPtr & cc)
+ {
+ getImpl()->displayCC_ = cc->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getDisplayCC() const
+ {
+ return getImpl()->displayCC_;
+ }
+
+ void DisplayTransform::setLooksOverride(const char * looks)
+ {
+ getImpl()->looksOverride_ = looks;
+ }
+
+ const char * DisplayTransform::getLooksOverride() const
+ {
+ return getImpl()->looksOverride_.c_str();
+ }
+
+ void DisplayTransform::setLooksOverrideEnabled(bool enabled)
+ {
+ getImpl()->looksOverrideEnabled_ = enabled;
+ }
+
+ bool DisplayTransform::getLooksOverrideEnabled() const
+ {
+ return getImpl()->looksOverrideEnabled_;
+ }
+
+ std::ostream& operator<< (std::ostream& os, const DisplayTransform& t)
+ {
+ os << "<DisplayTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << "inputColorSpace=" << t.getInputColorSpaceName() << ", ";
+ os << "display=" << t.getDisplay() << ", ";
+ os << "view=" << t.getView() << ", ";
+ os << ">\n";
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ void BuildDisplayOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const DisplayTransform & displayTransform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ displayTransform.getDirection());
+ if(combinedDir != TRANSFORM_DIR_FORWARD)
+ {
+ std::ostringstream os;
+ os << "DisplayTransform can only be applied in the forward direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string inputColorSpaceName = displayTransform.getInputColorSpaceName();
+ ConstColorSpaceRcPtr inputColorSpace = config.getColorSpace(inputColorSpaceName.c_str());
+ if(!inputColorSpace)
+ {
+ std::ostringstream os;
+ os << "DisplayTransform error.";
+ if(inputColorSpaceName.empty()) os << " InputColorSpaceName is unspecified.";
+ else os << " Cannot find inputColorSpace, named '" << inputColorSpaceName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string display = displayTransform.getDisplay();
+ std::string view = displayTransform.getView();
+
+ std::string displayColorSpaceName = config.getDisplayColorSpaceName(display.c_str(), view.c_str());
+ ConstColorSpaceRcPtr displayColorspace = config.getColorSpace(displayColorSpaceName.c_str());
+ if(!displayColorspace)
+ {
+ std::ostringstream os;
+ os << "DisplayTransform error.";
+ os << " Cannot find display colorspace, '" << displayColorSpaceName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ bool skipColorSpaceConversions = (inputColorSpace->isData() || displayColorspace->isData());
+
+ // If we're viewing alpha, also skip all color space conversions.
+ // If the user does uses a different transform for the channel view,
+ // in place of a simple matrix, they run the risk that when viewing alpha
+ // the colorspace transforms will not be skipped. (I.e., filmlook will be applied
+ // to alpha.) If this ever becomes an issue, additional engineering will be
+ // added at that time.
+
+ ConstMatrixTransformRcPtr typedChannelView = DynamicPtrCast<const MatrixTransform>(
+ displayTransform.getChannelView());
+ if(typedChannelView)
+ {
+ float matrix44[16];
+ typedChannelView->getValue(matrix44, 0x0);
+
+ if((matrix44[3]>0.0f) || (matrix44[7]>0.0f) || (matrix44[11]>0.0f))
+ {
+ skipColorSpaceConversions = true;
+ }
+ }
+
+
+
+ ConstColorSpaceRcPtr currentColorSpace = inputColorSpace;
+
+
+
+ // Apply a transform in ROLE_SCENE_LINEAR
+ ConstTransformRcPtr linearCC = displayTransform.getLinearCC();
+ if(linearCC)
+ {
+ // Put the new ops into a temp array, to see if it's a no-op
+ // If it is a no-op, dont bother doing the colorspace conversion.
+ OpRcPtrVec tmpOps;
+ BuildOps(tmpOps, config, context, linearCC, TRANSFORM_DIR_FORWARD);
+
+ if(!IsOpVecNoOp(tmpOps))
+ {
+ ConstColorSpaceRcPtr targetColorSpace = config.getColorSpace(ROLE_SCENE_LINEAR);
+
+ if(!skipColorSpaceConversions)
+ {
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ targetColorSpace);
+ currentColorSpace = targetColorSpace;
+ }
+
+ std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops));
+ }
+ }
+
+
+ // Apply a color correction, in ROLE_COLOR_TIMING
+ ConstTransformRcPtr colorTimingCC = displayTransform.getColorTimingCC();
+ if(colorTimingCC)
+ {
+ // Put the new ops into a temp array, to see if it's a no-op
+ // If it is a no-op, dont bother doing the colorspace conversion.
+ OpRcPtrVec tmpOps;
+ BuildOps(tmpOps, config, context, colorTimingCC, TRANSFORM_DIR_FORWARD);
+
+ if(!IsOpVecNoOp(tmpOps))
+ {
+ ConstColorSpaceRcPtr targetColorSpace = config.getColorSpace(ROLE_COLOR_TIMING);
+
+ if(!skipColorSpaceConversions)
+ {
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ targetColorSpace);
+ currentColorSpace = targetColorSpace;
+ }
+
+ std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops));
+ }
+ }
+
+ // Apply a look, if specified
+ LookParseResult looks;
+ if(displayTransform.getLooksOverrideEnabled())
+ {
+ looks.parse(displayTransform.getLooksOverride());
+ }
+ else if(!skipColorSpaceConversions)
+ {
+ looks.parse(config.getDisplayLooks(display.c_str(), view.c_str()));
+ }
+
+ if(!looks.empty())
+ {
+ BuildLookOps(ops,
+ currentColorSpace,
+ skipColorSpaceConversions,
+ config,
+ context,
+ looks);
+ }
+
+ // Apply a channel view
+ ConstTransformRcPtr channelView = displayTransform.getChannelView();
+ if(channelView)
+ {
+ BuildOps(ops, config, context, channelView, TRANSFORM_DIR_FORWARD);
+ }
+
+
+ // Apply the conversion to the display color space
+ if(!skipColorSpaceConversions)
+ {
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ displayColorspace);
+ currentColorSpace = displayColorspace;
+ }
+
+
+ // Apply a display cc
+ ConstTransformRcPtr displayCC = displayTransform.getDisplayCC();
+ if(displayCC)
+ {
+ BuildOps(ops, config, context, displayCC, TRANSFORM_DIR_FORWARD);
+ }
+
+ }
+}
+OCIO_NAMESPACE_EXIT