[packages/OpenColorIO] - added patch to fix build with yaml-cpp >= 5.0 - temp rel 2.1

baggins baggins at pld-linux.org
Sat Feb 1 20:42:40 CET 2014


commit 15f9dc5e915d9b48be609f99bc06a79b33724da4
Author: Jan Rękorajski <baggins at pld-linux.org>
Date:   Sat Feb 1 20:42:10 2014 +0100

    - added patch to fix build with yaml-cpp >= 5.0
    - temp rel 2.1

 OpenColorIO-yaml-cpp.patch | 3915 ++++++++++++++++++++++++++++++++++++++++++--
 OpenColorIO.spec           |    5 +-
 2 files changed, 3767 insertions(+), 153 deletions(-)
---
diff --git a/OpenColorIO.spec b/OpenColorIO.spec
index a6af031..a82d51c 100644
--- a/OpenColorIO.spec
+++ b/OpenColorIO.spec
@@ -16,7 +16,7 @@ Summary:	Complete color management solution
 Summary(pl.UTF-8):	Kompletny pakiet do zarządzania kolorami
 Name:		OpenColorIO
 Version:	1.0.9
-Release:	2
+Release:	2.1
 License:	BSD
 Group:		Libraries
 Source0:	https://github.com/imageworks/OpenColorIO/tarball/v%{version}/%{name}-%{version}.tar.gz
@@ -25,7 +25,6 @@ Patch0:		%{name}-system-libs.patch
 Patch1:		%{name}-java.patch
 Patch2:		%{name}-libsuffix.patch
 Patch3:		%{name}-missing.patch
-# for yaml-cpp 0.5.0 (unfinished)
 Patch4:		%{name}-yaml-cpp.patch
 URL:		http://opencolorio.org/
 # g++ with tr1 support or...
@@ -41,7 +40,6 @@ BuildRequires:	texlive-latex-ams
 %endif
 BuildRequires:	tinyxml-devel >= 2.6.1
 BuildRequires:	yaml-cpp-devel >= 0.2.6
-BuildRequires:	yaml-cpp-devel < 0.4.0
 %if %{with opengl}
 BuildRequires:	OpenGL-devel
 BuildRequires:	OpenGL-glut-devel
@@ -167,6 +165,7 @@ Plik nagłówkowy API PyOpenColorIO.
 %patch1 -p1
 %patch2 -p1
 %patch3 -p1
+%patch4 -p1
 
 %build
 # required for cmake to find JNI headers/libs when lib64 is in use
diff --git a/OpenColorIO-yaml-cpp.patch b/OpenColorIO-yaml-cpp.patch
index fbb45b1..58543ef 100644
--- a/OpenColorIO-yaml-cpp.patch
+++ b/OpenColorIO-yaml-cpp.patch
@@ -1,215 +1,3830 @@
---- imageworks-OpenColorIO-8883824/src/core/Config.cpp.orig	2012-12-12 00:21:23.000000000 +0100
-+++ imageworks-OpenColorIO-8883824/src/core/Config.cpp	2013-05-25 18:28:05.264387301 +0200
-@@ -240,35 +240,27 @@ OCIO_NAMESPACE_ENTER
-         if(node.Tag() != "View")
-             return;
+From 63c6bde2acac363c8c5e7fd3d744e17ea99e20ab Mon Sep 17 00:00:00 2001
+From: Malcolm Humphreys <malcolmhumphreys at gmail.com>
+Date: Thu, 30 Jan 2014 12:42:21 +0000
+Subject: [PATCH]
+ * added support form yaml-cpp > 5.0.1
+ * when yaml-cpp < 5.0.0 define OLDYAML
+ * added yaml-cpp 5.0.1 tarball in preparation for moving to  the new api
+ * added OCIOYaml class and moved all yaml-cpp code into  OCIOYaml.cpp
+ * moved Config serialize code into OCIOYaml.cpp
+ * added  Config::setEnvironmentMode(), Config::getEnvironmentMode(),  Config::loadEnvironment()
+ * moved Display code from Config.cpp into it's own files
+
+---
+ CMakeLists.txt                   |    6 +-
+ export/OpenColorIO/OpenColorIO.h |    6 +
+ ext/yaml-cpp-0.5.1.patch         |   12 +
+ ext/yaml-cpp-0.5.1.tar.gz        |  Bin 0 -> 118244 bytes
+ src/core/Config.cpp              |  518 +-------
+ src/core/Display.cpp             |  145 +++
+ src/core/Display.h               |   85 ++
+ src/core/OCIOYaml.cpp            | 2527 +++++++++++++++++++++++---------------
+ src/core/OCIOYaml.h              |   90 +-
+ 9 files changed, 1854 insertions(+), 1535 deletions(-)
+ create mode 100644 ext/yaml-cpp-0.5.1.patch
+ create mode 100644 ext/yaml-cpp-0.5.1.tar.gz
+ create mode 100644 src/core/Display.cpp
+ create mode 100644 src/core/Display.h
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 13e2d64..ea3fb8b 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -225,13 +225,15 @@ else(USE_EXTERNAL_YAML)
+     endif()
+ endif(USE_EXTERNAL_YAML)
+ 
+-
++if(YAML_CPP_VERSION VERSION_LESS "0.5.0")
++    set(YAML_CPP_COMPILE_FLAGS "-DOLDYAML")
++endif()
+ 
+ ###############################################################################
+ ### Externals ###
+ 
+ set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/ext/dist/include)
+-set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL")
++set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL ${YAML_CPP_COMPILE_FLAGS}")
+ 
+ if(CMAKE_COMPILER_IS_GNUCXX)
+     
+diff --git a/export/OpenColorIO/OpenColorIO.h b/export/OpenColorIO/OpenColorIO.h
+index 561ce50..00716fa 100644
+--- a/export/OpenColorIO/OpenColorIO.h
++++ b/export/OpenColorIO/OpenColorIO.h
+@@ -279,6 +279,12 @@
+         const char * getEnvironmentVarDefault(const char * name) const;
+         //!cpp:function::
+         void clearEnvironmentVars();
++        //!cpp:function::
++        void setEnvironmentMode(EnvironmentMode mode);
++        //!cpp:function::
++        EnvironmentMode getEnvironmentMode() const;
++        //!cpp:function::
++        void loadEnvironment();
+         
+         //!cpp:function::
+         const char * getSearchPath() const;
+diff --git a/ext/yaml-cpp-0.5.1.patch b/ext/yaml-cpp-0.5.1.patch
+new file mode 100644
+index 0000000..23433cb
+--- /dev/null
++++ b/ext/yaml-cpp-0.5.1.patch
+@@ -0,0 +1,12 @@
++diff -Naur yaml-cpp-0.5.1.orig/CMakeLists.txt yaml-cpp-0.5.1/CMakeLists.txt
++--- yaml-cpp-0.5.1.orig/CMakeLists.txt	2014-01-30 09:45:54.000000000 +0000
+++++ yaml-cpp-0.5.1/CMakeLists.txt	2014-01-30 09:51:04.000000000 +0000
++@@ -140,7 +140,7 @@
++ 		set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
++ 	endif()
++ 	#
++-	set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
+++	set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long -fPIC -fvisibility-inlines-hidden -fvisibility=hidden ${CMAKE_CXX_FLAGS}")
++ 	#
++ 	add_custom_target(debuggable $(MAKE) clean
++ 		COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
+diff --git a/src/core/Config.cpp b/src/core/Config.cpp
+index 00e1e70..82b5073 100644
+--- a/src/core/Config.cpp
++++ b/src/core/Config.cpp
+@@ -40,6 +40,7 @@
+ #include "HashUtils.h"
+ #include "Logging.h"
+ #include "LookParse.h"
++#include "Display.h"
+ #include "MathUtils.h"
+ #include "Mutex.h"
+ #include "OpBuilders.h"
+@@ -208,7 +209,6 @@
+         if(csname.empty()) return false;
+         
+         std::string csnamelower = pystring::lower(csname);
+-        
+         for(unsigned int i = 0; i < colorspaces.size(); ++i)
+         {
+             if(csnamelower == pystring::lower(colorspaces[i]->getName()))
+@@ -220,184 +220,7 @@
          
+         return false;
+     }
+-    
+-    
+-    // Displays
+-    struct View
+-    {
+-        std::string name;
+-        std::string colorspace;
+-        std::string looks;
+-        
+-        View() { }
+-        
+-        View(const std::string & name_,
+-             const std::string & colorspace_,
+-             const std::string & looksList_) :
+-                name(name_),
+-                colorspace(colorspace_),
+-                looks(looksList_)
+-        { }
+-    };
+-    
+-    typedef std::vector<View> ViewVec;
+-    typedef std::map<std::string, ViewVec> DisplayMap;  // (display name : ViewVec)
+-    
+-    void operator >> (const YAML::Node& node, View& v)
+-    {
+-        if(node.Tag() != "View")
+-            return;
+-        
 -        std::string key, stringval;
 -        
 -        for (YAML::Iterator iter = node.begin();
-+        for (YAML::const_iterator iter = node.begin();
-              iter != node.end();
-              ++iter)
-         {
+-             iter != node.end();
+-             ++iter)
+-        {
 -            iter.first() >> key;
-+	    std::string key = iter->first.as<std::string>();
-             
-             if(key == "name")
-             {
+-            
+-            if(key == "name")
+-            {
 -                if (iter.second().Type() != YAML::NodeType::Null && 
 -                    iter.second().Read<std::string>(stringval))
 -                    v.name = stringval;
-+                    v.name = iter->second.as<std::string>();
-             }
-             else if(key == "colorspace")
-             {
+-            }
+-            else if(key == "colorspace")
+-            {
 -                if (iter.second().Type() != YAML::NodeType::Null && 
 -                    iter.second().Read<std::string>(stringval))
 -                    v.colorspace = stringval;
-+                    v.colorspace = iter->second.as<std::string>();
-             }
-             else if(key == "looks" || key == "look")
-             {
+-            }
+-            else if(key == "looks" || key == "look")
+-            {
 -                if (iter.second().Type() != YAML::NodeType::Null && 
 -                    iter.second().Read<std::string>(stringval))
 -                    v.looks = stringval;
-+                    v.looks = iter->second.as<std::string>();
-             }
-             else
-             {
+-            }
+-            else
+-            {
 -                LogUnknownKeyWarning(node.Tag(), iter.first());
-+                LogUnknownKeyWarning(node.Tag(), iter->first);
-             }
+-            }
+-        }
+-        
+-        if(v.name.empty())
+-        {
+-            throw Exception("View does not specify 'name'.");
+-        }
+-        if(v.colorspace.empty())
+-        {
+-            std::ostringstream os;
+-            os << "View '" << v.name << "' ";
+-            os << "does not specify colorspace.";
+-            throw Exception(os.str().c_str());
+-        }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, View view)
+-    {
+-        out << YAML::VerbatimTag("View");
+-        out << YAML::Flow;
+-        out << YAML::BeginMap;
+-        out << YAML::Key << "name" << YAML::Value << view.name;
+-        out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
+-        if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
+-    {
+-        for(DisplayMap::iterator iter = displays.begin();
+-            iter != displays.end();
+-            ++iter)
+-        {
+-            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
+-        }
+-        return displays.end();
+-    }
+-    
+-    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
+-    {
+-        for(DisplayMap::const_iterator iter = displays.begin();
+-            iter != displays.end();
+-            ++iter)
+-        {
+-            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
+-        }
+-        return displays.end();
+-    }
+-    
+-    int find_view(const ViewVec & vec, const std::string & name)
+-    {
+-        for(unsigned int i=0; i<vec.size(); ++i)
+-        {
+-            if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
+-        }
+-        return -1;
+-    }
+-    
+-    void AddDisplay(DisplayMap & displays,
+-                    const std::string & display,
+-                    const std::string & view,
+-                    const std::string & colorspace,
+-                    const std::string & looks)
+-    {
+-        DisplayMap::iterator iter = find_display(displays, display);
+-        if(iter == displays.end())
+-        {
+-            ViewVec views;
+-            views.push_back( View(view, colorspace, looks) );
+-            displays[display] = views;
+-        }
+-        else
+-        {
+-            ViewVec & views = iter->second;
+-            int index = find_view(views, view);
+-            if(index<0)
+-            {
+-                views.push_back( View(view, colorspace, looks) );
+-            }
+-            else
+-            {
+-                views[index].colorspace = colorspace;
+-                views[index].looks = looks;
+-            }
+-        }
+-    }
+-    
+-    void ComputeDisplays(StringVec & displayCache,
+-                         const DisplayMap & displays,
+-                         const StringVec & activeDisplays,
+-                         const StringVec & activeDisplaysEnvOverride)
+-    {
+-        displayCache.clear();
+         
+-        StringVec displayMasterList;
+-        for(DisplayMap::const_iterator iter = displays.begin();
+-            iter != displays.end();
+-            ++iter)
+-        {
+-            displayMasterList.push_back(iter->first);
+-        }
+-        
+-        // Apply the env override if it's not empty.
+-        if(!activeDisplaysEnvOverride.empty())
+-        {
+-            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
+-            if(!displayCache.empty()) return;
+-        }
+-        // Otherwise, aApply the active displays if it's not empty.
+-        else if(!activeDisplays.empty())
+-        {
+-            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
+-            if(!displayCache.empty()) return;
+-        }
+-        
+-        displayCache = displayMasterList;
+-    }
+-    
+-    
+-    
+     } // namespace
+     
+     class Config::Impl
+@@ -431,6 +254,8 @@
+         mutable StringMap cacheids_;
+         mutable std::string cacheidnocontext_;
+         
++        OCIOYaml io_;
++        
+         Impl() : 
+             context_(Context::Create()),
+             strictParsing_(true),
+@@ -497,8 +322,6 @@
+             return *this;
          }
          
-@@ -391,7 +383,24 @@ OCIO_NAMESPACE_ENTER
+-        void load(std::istream & istream, const char * name);
+-        
+         // Any time you modify the state of the config, you must call this
+         // to reset internal cache states.  You also should do this in a
+         // thread safe manner by acquiring the cacheidMutex_;
+@@ -536,7 +359,7 @@
+         istream.str(INTERNAL_RAW_PROFILE);
+         
+         ConfigRcPtr config = Config::Create();
+-        config->getImpl()->load(istream, "");
++        config->getImpl()->io_.open(istream, config);
+         return config;
+     }
      
+@@ -551,14 +374,14 @@
+         }
+         
+         ConfigRcPtr config = Config::Create();
+-        config->getImpl()->load(istream, filename);
++        config->getImpl()->io_.open(istream, config, filename);
+         return config;
+     }
      
-     } // namespace
--    
-+
-+}
-+
-+namespace YAML {
-+    template<>
-+    struct convert<OCIO_NAMESPACE::View> {
-+	static bool decode(const Node &n, View &v)
-+	{
-+            if(node.Tag() != "View")
-+                return false;
-+	    n >> v;
-+	    return true;
-+	}
-+    };
-+}
-+
-+OCIO_NAMESPACE_ENTER
-+{
-     class Config::Impl
+     ConstConfigRcPtr Config::CreateFromStream(std::istream & istream)
+     {
+         ConfigRcPtr config = Config::Create();
+-        config->getImpl()->load(istream, "");
++        config->getImpl()->io_.open(istream, config);
+         return config;
+     }
+     
+@@ -893,6 +716,27 @@
+         getImpl()->resetCacheIDs();
+     }
+     
++    void Config::setEnvironmentMode(EnvironmentMode mode)
++    {
++        getImpl()->context_->setEnvironmentMode(mode);
++        
++        AutoMutex lock(getImpl()->cacheidMutex_);
++        getImpl()->resetCacheIDs();
++    }
++    
++    EnvironmentMode Config::getEnvironmentMode() const
++    {
++        return getImpl()->context_->getEnvironmentMode();
++    }
++    
++    void Config::loadEnvironment()
++    {
++        getImpl()->context_->loadEnvironment();
++        
++        AutoMutex lock(getImpl()->cacheidMutex_);
++        getImpl()->resetCacheIDs();
++    }
++    
+     const char * Config::getSearchPath() const
      {
-     public:
-@@ -1658,13 +1667,11 @@ OCIO_NAMESPACE_ENTER
+         return getImpl()->context_->getSearchPath();
+@@ -1647,60 +1491,7 @@
      {
          try
          {
+-            YAML::Emitter out;
+-            out << YAML::Block;
+-            out << YAML::BeginMap;
+-            out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
+-            out << YAML::Newline;
+-            if(getImpl()->env_.size() > 0) {
+-                out << YAML::Key << "environment";
+-                out << YAML::Value << getImpl()->env_;
+-                out << YAML::Newline;
+-            }
+-            out << YAML::Key << "search_path" << YAML::Value << getImpl()->context_->getSearchPath();
+-            out << YAML::Key << "strictparsing" << YAML::Value << getImpl()->strictParsing_;
+-            out << YAML::Key << "luma" << YAML::Value << YAML::Flow << getImpl()->defaultLumaCoefs_;
+-            
+-            if(getImpl()->description_ != "")
+-            {
+-                out << YAML::Newline;
+-                out << YAML::Key << "description";
+-                out << YAML::Value << getImpl()->description_;
+-            }
+-            
+-            // Roles
+-            out << YAML::Newline;
+-            out << YAML::Key << "roles";
+-            out << YAML::Value << getImpl()->roles_;
+-            
+-            // Displays
+-            out << YAML::Newline;
+-            out << YAML::Key << "displays";
+-            out << YAML::Value << getImpl()->displays_;
+-            out << YAML::Newline;
+-            out << YAML::Key << "active_displays";
+-            out << YAML::Value << YAML::Flow << getImpl()->activeDisplays_;
+-            out << YAML::Key << "active_views";
+-            out << YAML::Value << YAML::Flow << getImpl()->activeViews_;
+-            
+-            // Looks
+-            if(!getImpl()->looksList_.empty())
+-            {
+-                out << YAML::Newline;
+-                out << YAML::Key << "looks";
+-                out << YAML::Value << getImpl()->looksList_;
+-            }
+-            
+-            // ColorSpaces
+-            {
+-                out << YAML::Newline;
+-                out << YAML::Key << "colorspaces";
+-                out << YAML::Value << getImpl()->colorspaces_;
+-            }
+-            
+-            out << YAML::EndMap;
+-            
+-            os << out.c_str();
++            getImpl()->io_.write(os, this);
+         }
+         catch( const std::exception & e)
+         {
+@@ -1710,246 +1501,6 @@
+         }
+     }
+     
+-    void Config::Impl::load(std::istream & istream, const char * filename)
+-    {
+-        try
+-        {
 -            YAML::Parser parser(istream);
 -            YAML::Node node;
 -            parser.GetNextDocument(node);
-+            YAML::Node node = YAML::Load(istream);
-             
-             // check profile version
-             int profile_version = 0;
+-            
+-            // check profile version
+-            int profile_version = 0;
 -            if(node.FindValue("ocio_profile_version") == NULL)
-+            if(!node["ocio_profile_version"])
-             {
-                 std::ostringstream os;
-                 os << "The specified file ";
-@@ -1672,7 +1679,7 @@ OCIO_NAMESPACE_ENTER
-                 throw Exception (os.str().c_str());
-             }
-             
+-            {
+-                std::ostringstream os;
+-                os << "The specified file ";
+-                os << "does not appear to be an OCIO configuration.";
+-                throw Exception (os.str().c_str());
+-            }
+-            
 -            node["ocio_profile_version"] >> profile_version;
-+            profile_version = node["ocio_profile_version"].as<int>();
-             if(profile_version > 1)
-             {
-                 std::ostringstream os;
-@@ -1690,40 +1697,30 @@ OCIO_NAMESPACE_ENTER
-             }
-             
-             
+-            if(profile_version > 1)
+-            {
+-                std::ostringstream os;
+-                os << "This .ocio config ";
+-                if(filename && *filename)
+-                {
+-                    os << " '" << filename << "' ";
+-                }
+-                os << "is version " << profile_version << ". ";
+-                os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
+-                os << "is not known to be able to load this profile. ";
+-                os << "An attempt will be made, but there are no guarantees that the ";
+-                os << "results will be accurate. Continue at your own risk.";
+-                LogWarning(os.str());
+-            }
+-            
+-            
 -            std::string key, stringval;
 -            bool boolval = false;
+-            EnvironmentMode mode = ENV_ENVIRONMENT_LOAD_ALL;
 -            
 -            for (YAML::Iterator iter = node.begin();
-+            for (YAML::iterator iter = node.begin();
-                  iter != node.end();
-                  ++iter)
-             {
+-                 iter != node.end();
+-                 ++iter)
+-            {
 -                iter.first() >> key;
-+		std::string key = iter->first.as<std::string>();
-                 
-                 if(key == "ocio_profile_version") { } // Already handled above.
-                 else if(key == "search_path" || key == "resource_path")
-                 {
+-                
+-                if(key == "ocio_profile_version") { } // Already handled above.
+-                else if(key == "environment")
+-                {
+-                    mode = ENV_ENVIRONMENT_LOAD_PREDEFINED;
+-                    const YAML::Node& environment = iter.second();
+-                    if(environment.Type() != YAML::NodeType::Map)
+-                    {
+-                        std::ostringstream os;
+-                        os << "'environment' field needs to be a (name: key) map.";
+-                        throw Exception(os.str().c_str());
+-                    }
+-                    for (YAML::Iterator it  = environment.begin();
+-                                        it != environment.end(); ++it)
+-                    {
+-                        std::string k, v;
+-                        it.first() >> k;
+-                        it.second() >> v;
+-                        env_[k] = v;
+-                        context_->setStringVar(k.c_str(), v.c_str());
+-                    }
+-                }
+-                else if(key == "search_path" || key == "resource_path")
+-                {
 -                    if (iter.second().Type() != YAML::NodeType::Null && 
 -                        iter.second().Read<std::string>(stringval))
 -                        context_->setSearchPath(stringval.c_str());
-+                        context_->setSearchPath(iter->second.as<std::string>().c_str());
-                 }
-                 else if(key == "strictparsing")
-                 {
+-                }
+-                else if(key == "strictparsing")
+-                {
 -                    if (iter.second().Type() != YAML::NodeType::Null && 
 -                        iter.second().Read<bool>(boolval))
 -                        strictParsing_ = boolval;
-+                        strictParsing_ = iter->second.as<bool>();
-                 }
-                 else if(key == "description")
-                 {
+-                }
+-                else if(key == "description")
+-                {
 -                    if (iter.second().Type() != YAML::NodeType::Null && 
 -                        iter.second().Read<std::string>(stringval))
 -                        description_ = stringval;
-+                        description_ = iter->second.as<std::string>();
-                 }
-                 else if(key == "luma")
-                 {
-                     std::vector<float> val;
+-                }
+-                else if(key == "luma")
+-                {
+-                    std::vector<float> val;
 -                    if (iter.second().Type() != YAML::NodeType::Null)
-                     {
+-                    {
 -                        iter.second() >> val;
-+                        val = iter->second.as< std::vector<float> >();
-                         if(val.size() != 3)
-                         {
-                             std::ostringstream os;
-@@ -1736,46 +1733,35 @@ OCIO_NAMESPACE_ENTER
-                 }
-                 else if(key == "roles")
-                 {
+-                        if(val.size() != 3)
+-                        {
+-                            std::ostringstream os;
+-                            os << "'luma' field must be 3 ";
+-                            os << "floats. Found '" << val.size() << "'.";
+-                            throw Exception(os.str().c_str());
+-                        }
+-                        defaultLumaCoefs_ = val;
+-                    }
+-                }
+-                else if(key == "roles")
+-                {
 -                    const YAML::Node& roles = iter.second();
-+                    const YAML::Node& roles = iter->second;
-                     if(roles.Type() != YAML::NodeType::Map)
-                     {
-                         std::ostringstream os;
-                         os << "'roles' field needs to be a (name: key) map.";
-                         throw Exception(os.str().c_str());
-                     }
+-                    if(roles.Type() != YAML::NodeType::Map)
+-                    {
+-                        std::ostringstream os;
+-                        os << "'roles' field needs to be a (name: key) map.";
+-                        throw Exception(os.str().c_str());
+-                    }
 -                    for (YAML::Iterator it  = roles.begin();
-+                    for (YAML::const_iterator it  = roles.begin();
-                                         it != roles.end(); ++it)
-                     {
+-                                        it != roles.end(); ++it)
+-                    {
 -                        std::string k, v;
 -                        it.first() >> k;
 -                        it.second() >> v;
 -                        roles_[pystring::lower(k)] = v;
-+                        roles_[pystring::lower(it->first.as<std::string>())] = it->second.as<std::string>();
-                     }
-                 }
-                 else if(key == "displays")
-                 {
+-                    }
+-                }
+-                else if(key == "displays")
+-                {
 -                    if (iter.second().Type() != YAML::NodeType::Null)
 -                    {
 -                        iter.second() >> displays_;
 -                    }
-+                        //displays_ = iter->second.as<DisplayMap>();
-+                        iter->second >> displays_;
-                 }
-                 else if(key == "active_displays")
-                 {
+-                }
+-                else if(key == "active_displays")
+-                {
 -                    if (iter.second().Type() != YAML::NodeType::Null)
 -                    {
 -                        iter.second() >> activeDisplays_;
 -                    }
-+                        activeDisplays_ = iter->second.as<StringVec>();
-                 }
-                 else if(key == "active_views")
-                 {
+-                }
+-                else if(key == "active_views")
+-                {
 -                    if (iter.second().Type() != YAML::NodeType::Null)
 -                    {
 -                        iter.second() >> activeViews_;
 -                    }
-+                        activeViews_ = iter->second.as<StringVec>();
-                 }
-                 else if(key == "colorspaces")
-                 {
+-                }
+-                else if(key == "colorspaces")
+-                {
 -                    const YAML::Node& colorspaces = iter.second();
-+                    const YAML::Node& colorspaces = iter->second;
-                     
-                     if(colorspaces.Type() != YAML::NodeType::Sequence)
-                     {
-@@ -1804,7 +1790,7 @@ OCIO_NAMESPACE_ENTER
-                 }
-                 else if(key == "looks")
-                 {
+-                    
+-                    if(colorspaces.Type() != YAML::NodeType::Sequence)
+-                    {
+-                        std::ostringstream os;
+-                        os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
+-                        throw Exception(os.str().c_str());
+-                    }
+-                    
+-                    for(unsigned i = 0; i < colorspaces.size(); ++i)
+-                    {
+-                        if(colorspaces[i].Tag() == "ColorSpace")
+-                        {
+-                            ColorSpaceRcPtr cs = ColorSpace::Create();
+-                            colorspaces[i] >> cs;
+-                            colorspaces_.push_back( cs );
+-                        }
+-                        else
+-                        {
+-                            std::ostringstream os;
+-                            os << "Unknown element found in colorspaces:";
+-                            os << colorspaces[i].Tag() << ". Only ColorSpace(s)";
+-                            os << " currently handled.";
+-                            LogWarning(os.str());
+-                        }
+-                    }
+-                }
+-                else if(key == "looks")
+-                {
 -                    const YAML::Node& looks = iter.second();
-+                    const YAML::Node& looks = iter->second;
-                     
-                     if(looks.Type() != YAML::NodeType::Sequence)
-                     {
-@@ -1833,7 +1819,7 @@ OCIO_NAMESPACE_ENTER
-                 }
-                 else
-                 {
+-                    
+-                    if(looks.Type() != YAML::NodeType::Sequence)
+-                    {
+-                        std::ostringstream os;
+-                        os << "'looks' field needs to be a (- !<Look>) list.";
+-                        throw Exception(os.str().c_str());
+-                    }
+-                    
+-                    for(unsigned i = 0; i < looks.size(); ++i)
+-                    {
+-                        if(looks[i].Tag() == "Look")
+-                        {
+-                            LookRcPtr look = Look::Create();
+-                            looks[i] >> look;
+-                            looksList_.push_back( look );
+-                        }
+-                        else
+-                        {
+-                            std::ostringstream os;
+-                            os << "Unknown element found in looks:";
+-                            os << looks[i].Tag() << ". Only Look(s)";
+-                            os << " currently handled.";
+-                            LogWarning(os.str());
+-                        }
+-                    }
+-                }
+-                else
+-                {
 -                    LogUnknownKeyWarning("profile", iter.first());
-+                    LogUnknownKeyWarning("profile", iter->first);
-                 }
-             }
-             
+-                }
+-            }
+-            
+-            if(filename)
+-            {
+-                std::string realfilename = pystring::os::path::abspath(filename);
+-                std::string configrootdir = pystring::os::path::dirname(realfilename);
+-                context_->setWorkingDir(configrootdir.c_str());
+-            }
+-            
+-            context_->setEnvironmentMode(mode);
+-            context_->loadEnvironment();
+-            
+-            if(mode == ENV_ENVIRONMENT_LOAD_ALL)
+-            {
+-                std::ostringstream os;
+-                os << "This .ocio config ";
+-                if(filename && *filename)
+-                {
+-                    os << " '" << filename << "' ";
+-                }
+-                os << "has no environment section defined. The default behaviour is to ";
+-                os << "load all environment variables (" << context_->getNumStringVars() << ")";
+-                os << ", which reduces the efficiency of OCIO's caching. Considering ";
+-                os << "predefining the environment variables used.";
+-                LogDebug(os.str());
+-            }
+-            
+-        }
+-        catch( const std::exception & e)
+-        {
+-            std::ostringstream os;
+-            os << "Error: Loading the OCIO profile ";
+-            if(filename) os << "'" << filename << "' ";
+-            os << "failed. " << e.what();
+-            throw Exception(os.str().c_str());
+-        }
+-    }
+-    
+     void Config::Impl::resetCacheIDs()
+     {
+         cacheids_.clear();
+@@ -2287,9 +1838,7 @@
+     std::istringstream is;
+     is.str(SIMPLE_PROFILE);
+     OCIO::ConstConfigRcPtr config;
+-    OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
+-    
+-    OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
++    OIIO_CHECK_THOW(config = OCIO::Config::CreateFromStream(is), OCIO::Exception);
+     }
+     
+     {
+@@ -2330,8 +1879,6 @@
+     "colorspaces:\n"
+     "  - !<ColorSpace>\n"
+     "      name: raw\n"
+-    "  - !<ColorSpace>\n"
+-    "      name: raw\n"
+     "strictparsing: false\n"
+     "roles:\n"
+     "  default: raw\n"
+@@ -2345,8 +1892,6 @@
+     "colorspaces:\n"
+     "  - !<ColorSpace>\n"
+     "      name: raw\n"
+-    "  - !<ColorSpace>\n"
+-    "      name: raw\n"
+     "strictparsing: false\n"
+     "roles:\n"
+     "  default: raw\n"
+@@ -2370,7 +1915,6 @@
+         "testbarchedder") == 0);
+     OIIO_CHECK_ASSERT(strcmp(config->getCurrentContext()->resolveStringVar("${SHOW}"),
+         "bar") == 0);
+-    OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
+     OIIO_CHECK_ASSERT(strcmp(config->getEnvironmentVarDefault("SHOW"), "super") == 0);
+     
+     OCIO::ConfigRcPtr edit = config->createEditableCopy();
+@@ -2403,6 +1947,10 @@
+         "lighting") == 0);
+     OCIO::SetLoggingLevel(loglevel);
+     
++    OIIO_CHECK_EQUAL(edit->getEnvironmentMode(), OCIO::ENV_ENVIRONMENT_LOAD_PREDEFINED);
++    edit->setEnvironmentMode(OCIO::ENV_ENVIRONMENT_LOAD_ALL);
++    OIIO_CHECK_EQUAL(edit->getEnvironmentMode(), OCIO::ENV_ENVIRONMENT_LOAD_ALL);
++    
+     }
+ }
+ 
+diff --git a/src/core/Display.cpp b/src/core/Display.cpp
+new file mode 100644
+index 0000000..7c0a1ef
+--- /dev/null
++++ b/src/core/Display.cpp
+@@ -0,0 +1,145 @@
++/*
++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 <string>
++
++#include <OpenColorIO/OpenColorIO.h>
++
++#include "Display.h"
++#include "ParseUtils.h"
++
++OCIO_NAMESPACE_ENTER
++{
++    
++    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
++    {
++        for(DisplayMap::iterator iter = displays.begin();
++            iter != displays.end();
++            ++iter)
++        {
++            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
++        }
++        return displays.end();
++    }
++    
++    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
++    {
++        for(DisplayMap::const_iterator iter = displays.begin();
++            iter != displays.end();
++            ++iter)
++        {
++            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
++        }
++        return displays.end();
++    }
++    
++    int find_view(const ViewVec & vec, const std::string & name)
++    {
++        for(unsigned int i=0; i<vec.size(); ++i)
++        {
++            if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
++        }
++        return -1;
++    }
++    
++    void AddDisplay(DisplayMap & displays,
++                    const std::string & display,
++                    const std::string & view,
++                    const std::string & colorspace,
++                    const std::string & looks)
++    {
++        DisplayMap::iterator iter = find_display(displays, display);
++        if(iter == displays.end())
++        {
++            ViewVec views;
++            views.push_back( View(view, colorspace, looks) );
++            displays[display] = views;
++        }
++        else
++        {
++            ViewVec & views = iter->second;
++            int index = find_view(views, view);
++            if(index<0)
++            {
++                views.push_back( View(view, colorspace, looks) );
++            }
++            else
++            {
++                views[index].colorspace = colorspace;
++                views[index].looks = looks;
++            }
++        }
++    }
++    
++    void ComputeDisplays(StringVec & displayCache,
++                         const DisplayMap & displays,
++                         const StringVec & activeDisplays,
++                         const StringVec & activeDisplaysEnvOverride)
++    {
++        displayCache.clear();
++        
++        StringVec displayMasterList;
++        for(DisplayMap::const_iterator iter = displays.begin();
++            iter != displays.end();
++            ++iter)
++        {
++            displayMasterList.push_back(iter->first);
++        }
++        
++        // Apply the env override if it's not empty.
++        if(!activeDisplaysEnvOverride.empty())
++        {
++            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
++            if(!displayCache.empty()) return;
++        }
++        // Otherwise, aApply the active displays if it's not empty.
++        else if(!activeDisplays.empty())
++        {
++            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
++            if(!displayCache.empty()) return;
++        }
++        
++        displayCache = displayMasterList;
++    }
++
++}
++OCIO_NAMESPACE_EXIT
++
++///////////////////////////////////////////////////////////////////////////////
++
++#ifdef OCIO_UNIT_TEST
++
++namespace OCIO = OCIO_NAMESPACE;
++#include "UnitTest.h"
++
++OIIO_ADD_TEST(Display, Basic)
++{
++    
++}
++
++#endif // OCIO_UNIT_TEST
+\ No newline at end of file
+diff --git a/src/core/Display.h b/src/core/Display.h
+new file mode 100644
+index 0000000..6d63a43
+--- /dev/null
++++ b/src/core/Display.h
+@@ -0,0 +1,85 @@
++/*
++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.
++*/
++
++
++#ifndef INCLUDED_OCIO_DISPLAY_H
++#define INCLUDED_OCIO_DISPLAY_H
++
++#include <OpenColorIO/OpenColorIO.h>
++
++#include <string>
++#include <vector>
++#include <map>
++
++#include "PrivateTypes.h"
++
++OCIO_NAMESPACE_ENTER
++{
++    
++    // Displays
++    struct View
++    {
++        std::string name;
++        std::string colorspace;
++        std::string looks;
++        
++        View() { }
++        
++        View(const std::string & name_,
++             const std::string & colorspace_,
++             const std::string & looksList_) :
++                name(name_),
++                colorspace(colorspace_),
++                looks(looksList_)
++        { }
++    };
++    
++    typedef std::vector<View> ViewVec;
++    typedef std::map<std::string, ViewVec> DisplayMap;  // (display name : ViewVec)
++    
++    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display);
++    
++    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display);
++    
++    int find_view(const ViewVec & vec, const std::string & name);
++    
++    void AddDisplay(DisplayMap & displays,
++                    const std::string & display,
++                    const std::string & view,
++                    const std::string & colorspace,
++                    const std::string & looks);
++    
++    void ComputeDisplays(StringVec & displayCache,
++                         const DisplayMap & displays,
++                         const StringVec & activeDisplays,
++                         const StringVec & activeDisplaysEnvOverride);
++    
++}
++OCIO_NAMESPACE_EXIT
++
++#endif
+\ No newline at end of file
+diff --git a/src/core/OCIOYaml.cpp b/src/core/OCIOYaml.cpp
+index 7089318..fc2f5f8 100644
+--- a/src/core/OCIOYaml.cpp
++++ b/src/core/OCIOYaml.cpp
+@@ -30,1188 +30,1787 @@
+ 
+ #include <OpenColorIO/OpenColorIO.h>
+ 
++#ifndef WINDOWS
++
++// fwd declare yaml-cpp visibility
++#pragma GCC visibility push(hidden)
++namespace YAML {
++    class Exception;
++    class BadDereference;
++    class RepresentationException;
++    class EmitterException;
++    class ParserException;
++    class InvalidScalar;
++    class KeyNotFound;
++    template <typename T> class TypedKeyNotFound;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
++    template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
++}
++#pragma GCC visibility pop
++
++#endif
++
++#include <yaml-cpp/yaml.h>
++
+ #include "Logging.h"
+ #include "MathUtils.h"
++#include "pystring/pystring.h"
++#include "PathUtils.h"
++#include "ParseUtils.h"
++#include "Display.h"
+ #include "OCIOYaml.h"
+ 
+ OCIO_NAMESPACE_ENTER
+ {
+-    ///////////////////////////////////////////////////////////////////////////
+-    //  Core
+     
+-    void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag)
++    namespace
+     {
+-        std::string key;
+-        tag >> key;
+-        
+-        std::ostringstream os;
+-        os << "Unknown key in " << name << ": ";
+-        os << "'" << key << "'. (line ";
+-        os << (tag.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
+-        os << tag.GetMark().column << ")";
+-        LogWarning(os.str());
+-    }
+     
+-    void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs)
+-    {
+-        if(node.Tag() != "ColorSpace")
+-            return; // not a !<ColorSpace> tag
++#ifdef OLDYAML
++        typedef YAML::Iterator Iterator;
++#else
++        typedef YAML::const_iterator Iterator;
++#endif
+         
+-        std::string key, stringval;
+-        bool boolval;
++        // Iterator access
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
+-        {
+-            iter.first() >> key;
+-            
+-            if(key == "name")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                    cs->setName(stringval.c_str());
+-            }
+-            else if(key == "description")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                    cs->setDescription(stringval.c_str());
+-            }
+-            else if(key == "family")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                    cs->setFamily(stringval.c_str());
+-            }
+-            else if(key == "equalitygroup")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                    cs->setEqualityGroup(stringval.c_str());
+-            }
+-            else if(key == "bitdepth")
+-            {
+-                BitDepth ret;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<BitDepth>(ret))
+-                    cs->setBitDepth(ret);
+-            }
+-            else if(key == "isdata")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<bool>(boolval))
+-                    cs->setIsData(boolval);
+-            }
+-            else if(key == "allocation")
+-            {
+-                Allocation val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<Allocation>(val))
+-                    cs->setAllocation(val);
+-            }
+-            else if(key == "allocationvars")
+-            {
+-                std::vector<float> val;
+-                if (iter.second().Type() != YAML::NodeType::Null)
+-                {
+-                    iter.second() >> val;
+-                    if(!val.empty())
+-                    {
+-                        cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
+-                    }
+-                }
+-            }
+-            else if(key == "to_reference")
+-            {
+-                TransformRcPtr val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformRcPtr>(val))
+-                  cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
+-            }
+-            else if(key == "from_reference")
+-            {
+-                TransformRcPtr val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformRcPtr>(val))
+-                  cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
+-            }
+-            else
+-            {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
+-            }
+-        }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs)
+-    {
+-        out << YAML::VerbatimTag("ColorSpace");
+-        out << YAML::BeginMap;
+-        
+-        out << YAML::Key << "name" << YAML::Value << cs->getName();
+-        out << YAML::Key << "family" << YAML::Value << cs->getFamily();
+-        out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
+-        out << YAML::Key << "bitdepth" << YAML::Value << cs->getBitDepth();
+-        if(strlen(cs->getDescription()) > 0)
++        inline const YAML::Node& get_first(const Iterator it)
+         {
+-            out << YAML::Key << "description";
+-            out << YAML::Value << YAML::Literal << cs->getDescription();
++#ifdef OLDYAML
++            return it.first();
++#else
++            return it->first;
++#endif
+         }
+-        out << YAML::Key << "isdata" << YAML::Value << cs->isData();
+         
+-        out << YAML::Key << "allocation" << YAML::Value << cs->getAllocation();
+-        if(cs->getAllocationNumVars() > 0)
++        inline const YAML::Node& get_second(const Iterator it)
+         {
+-            std::vector<float> allocationvars(cs->getAllocationNumVars());
+-            cs->getAllocationVars(&allocationvars[0]);
+-            out << YAML::Key << "allocationvars";
+-            out << YAML::Flow << YAML::Value << allocationvars;
++#ifdef OLDYAML
++            return it.second();
++#else
++            return it->second;
++#endif
+         }
+         
+-        ConstTransformRcPtr toref = \
+-            cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
+-        if(toref)
+-            out << YAML::Key << "to_reference" << YAML::Value << toref;
+-        
+-        ConstTransformRcPtr fromref = \
+-            cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
+-        if(fromref)
+-            out << YAML::Key << "from_reference" << YAML::Value << fromref;
+-        
+-        out << YAML::EndMap;
+-        out << YAML::Newline;
+-        
+-        return out;
+-    }
+-    
+-    
+-    ///////////////////////////////////////////////////////////////////////////
+-    
+-    // Look. (not the transform, the top-level class)
+-    
+-    void operator >> (const YAML::Node& node, LookRcPtr& look)
+-    {
+-        if(node.Tag() != "Look")
+-            return;
+-        
+-        std::string key, stringval;
++        // Basic types
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void load(const YAML::Node& node, bool& x)
+         {
+-            iter.first() >> key;
+-            
+-            if(key == "name")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                    look->setName(stringval.c_str());
+-            }
+-            else if(key == "process_space")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                    look->setProcessSpace(stringval.c_str());
+-            }
+-            else if(key == "transform")
+-            {
+-                TransformRcPtr val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformRcPtr>(val))
+-                    look->setTransform(val);
+-            }
+-            else if(key == "inverse_transform")
+-            {
+-                TransformRcPtr val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformRcPtr>(val))
+-                    look->setInverseTransform(val);
+-            }
+-            else
+-            {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
+-            }
++#ifdef OLDYAML
++            node.Read<bool>(x);
++#else
++            x = node.as<bool>();
++#endif
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr look)
+-    {
+-        out << YAML::VerbatimTag("Look");
+-        out << YAML::BeginMap;
+-        out << YAML::Key << "name" << YAML::Value << look->getName();
+-        out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
+         
+-        if(look->getTransform())
++        inline void load(const YAML::Node& node, int& x)
+         {
+-            out << YAML::Key << "transform";
+-            out << YAML::Value << look->getTransform();
++#ifdef OLDYAML
++            node.Read<int>(x);
++#else
++            x = node.as<int>();
++#endif
+         }
+         
+-        if(look->getInverseTransform())
++        inline void load(const YAML::Node& node, float& x)
+         {
+-            out << YAML::Key << "inverse_transform";
+-            out << YAML::Value << look->getInverseTransform();
++#ifdef OLDYAML
++            node.Read<float>(x);
++#else
++            x = node.as<float>();
++#endif
+         }
+         
+-        out << YAML::EndMap;
+-        out << YAML::Newline;
++        inline void load(const YAML::Node& node, std::string& x)
++        {
++#ifdef OLDYAML
++            node.Read<std::string>(x);
++#else
++            x = node.as<std::string>();
++#endif
++        }
+         
+-        return out;
+-    }
+-    
+-    
+-    
+-    ///////////////////////////////////////////////////////////////////////////
+-    
+-    
+-    namespace
+-    {
+-        void EmitBaseTransformKeyValues(YAML::Emitter & out,
+-                                        const ConstTransformRcPtr & t)
++        inline void load(const YAML::Node& node, std::vector<std::string>& x)
+         {
+-            if(t->getDirection() != TRANSFORM_DIR_FORWARD)
+-            {
+-                out << YAML::Key << "direction";
+-                out << YAML::Value << YAML::Flow << t->getDirection();
+-            }
++#ifdef OLDYAML
++            node >> x;
++#else
++            x = node.as<std::vector<std::string> >();
++#endif
+         }
+-    }
+-    
+-    void operator >> (const YAML::Node& node, TransformRcPtr& t)
+-    {
+-        if(node.Type() != YAML::NodeType::Map)
++        
++        inline void load(const YAML::Node& node, std::vector<float>& x)
+         {
+-            std::ostringstream os;
+-            os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
+-            os << "Only Mapping types supported. (line ";
+-            os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
+-            os << node.GetMark().column << ")";
+-            throw Exception(os.str().c_str());
++#ifdef OLDYAML
++            node >> x;
++#else
++            x = node.as<std::vector<float> >();
++#endif
+         }
+         
+-        std::string type = node.Tag();
++        // Enums
+         
+-        if(type == "AllocationTransform") {
+-            AllocationTransformRcPtr temp;
+-            node.Read<AllocationTransformRcPtr>(temp);
+-            t = temp;
++        inline void load(const YAML::Node& node, BitDepth& depth)
++        {
++            std::string str;
++            load(node, str);
++            depth = BitDepthFromString(str.c_str());
+         }
+-        else if(type == "CDLTransform") {
+-            CDLTransformRcPtr temp;
+-            node.Read<CDLTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void save(YAML::Emitter& out, BitDepth depth)
++        {
++            out << BitDepthToString(depth);
+         }
+-        else if(type == "ColorSpaceTransform")  {
+-            ColorSpaceTransformRcPtr temp;
+-            node.Read<ColorSpaceTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void load(const YAML::Node& node, Allocation& alloc)
++        {
++            std::string str;
++            load(node, str);
++            alloc = AllocationFromString(str.c_str());
+         }
+-        // TODO: DisplayTransform
+-        else if(type == "ExponentTransform")  {
+-            ExponentTransformRcPtr temp;
+-            node.Read<ExponentTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void save(YAML::Emitter& out, Allocation alloc)
++        {
++            out << AllocationToString(alloc);
+         }
+-        else if(type == "FileTransform")  {
+-            FileTransformRcPtr temp;
+-            node.Read<FileTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void load(const YAML::Node& node, ColorSpaceDirection& dir)
++        {
++            std::string str;
++            load(node, str);
++            dir = ColorSpaceDirectionFromString(str.c_str());
+         }
+-        else if(type == "GroupTransform") {
+-            GroupTransformRcPtr temp;
+-            node.Read<GroupTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void save(YAML::Emitter& out, ColorSpaceDirection dir)
++        {
++            out << ColorSpaceDirectionToString(dir);
+         }
+-        else if(type == "LogTransform") {
+-            LogTransformRcPtr temp;
+-            node.Read<LogTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void load(const YAML::Node& node, TransformDirection& dir)
++        {
++            std::string str;
++            load(node, str);
++            dir = TransformDirectionFromString(str.c_str());
+         }
+-        else if(type == "LookTransform") {
+-            LookTransformRcPtr temp;
+-            node.Read<LookTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void save(YAML::Emitter& out, TransformDirection dir)
++        {
++            out << TransformDirectionToString(dir);
+         }
+-        else if(type == "MatrixTransform")  {
+-            MatrixTransformRcPtr temp;
+-            node.Read<MatrixTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void load(const YAML::Node& node, Interpolation& interp)
++        {
++            std::string str;
++            load(node, str);
++            interp = InterpolationFromString(str.c_str());
+         }
+-        else if(type == "TruelightTransform")  {
+-            TruelightTransformRcPtr temp;
+-            node.Read<TruelightTransformRcPtr>(temp);
+-            t = temp;
++        
++        inline void save(YAML::Emitter& out, Interpolation interp)
++        {
++            out << InterpolationToString(interp);
+         }
+-        else
++        
++        //
++        
++        inline void LogUnknownKeyWarning(const std::string & name,
++                                         const YAML::Node& tag)
+         {
+-            // TODO: add a new empty (better name?) aka passthru Transform()
+-            // which does nothing. This is so upsupported !<tag> types don't
+-            // throw an exception. Alternativly this could be caught in the
+-            // GroupTransformRcPtr >> operator with some type of
+-            // supported_tag() method
+-            
+-            // TODO: consider the forwards-compatibility implication of
+-            // throwing an exception.  Should this be a warning, instead?
+-            
+-            //  t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
++            std::string key;
++            load(tag, key);
++        
+             std::ostringstream os;
+-            os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
+-            os << " (line ";
+-            os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
+-            os << node.GetMark().column << ")";
+-            throw Exception(os.str().c_str());
++            os << "Unknown key in " << name << ": '" << key << "'.";
++            LogWarning(os.str());
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t)
+-    {
+-        if(ConstAllocationTransformRcPtr Allocation_tran = \
+-            DynamicPtrCast<const AllocationTransform>(t))
+-            out << Allocation_tran;
+-        else if(ConstCDLTransformRcPtr CDL_tran = \
+-            DynamicPtrCast<const CDLTransform>(t))
+-            out << CDL_tran;
+-        else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
+-            DynamicPtrCast<const ColorSpaceTransform>(t))
+-            out << ColorSpace_tran;
+-        else if(ConstExponentTransformRcPtr Exponent_tran = \
+-            DynamicPtrCast<const ExponentTransform>(t))
+-            out << Exponent_tran;
+-        else if(ConstFileTransformRcPtr File_tran = \
+-            DynamicPtrCast<const FileTransform>(t))
+-            out << File_tran;
+-        else if(ConstGroupTransformRcPtr Group_tran = \
+-            DynamicPtrCast<const GroupTransform>(t))
+-            out << Group_tran;
+-        else if(ConstLogTransformRcPtr Log_tran = \
+-            DynamicPtrCast<const LogTransform>(t))
+-            out << Log_tran;
+-        else if(ConstLookTransformRcPtr Look_tran = \
+-            DynamicPtrCast<const LookTransform>(t))
+-            out << Look_tran;
+-        else if(ConstMatrixTransformRcPtr Matrix_tran = \
+-            DynamicPtrCast<const MatrixTransform>(t))
+-            out << Matrix_tran;
+-        else if(ConstTruelightTransformRcPtr Truelight_tran = \
+-            DynamicPtrCast<const TruelightTransform>(t))
+-            out << Truelight_tran;
+-        else
+-            throw Exception("Unsupported Transform() type for serialization.");
+-        
+-        return out;
+-    }
+-    
+-    
+-    ///////////////////////////////////////////////////////////////////////////
+-    //  Transforms
+-    
+-    void operator >> (const YAML::Node& node, GroupTransformRcPtr& t)
+-    {
+-        t = GroupTransform::Create();
+         
+-        std::string key;
++        // View
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void load(const YAML::Node& node, View& v)
+         {
+-            iter.first() >> key;
++            if(node.Tag() != "View")
++                return;
+             
+-            if(key == "children")
+-            {
+-                const YAML::Node & children = iter.second();
+-                for(unsigned i = 0; i <children.size(); ++i)
++            std::string key, stringval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "name")
+                 {
+-                    TransformRcPtr childTransform;
+-                    children[i].Read<TransformRcPtr>(childTransform);
+-                    
+-                    // TODO: consider the forwards-compatibility implication of
+-                    // throwing an exception.  Should this be a warning, instead?
+-                    if(!childTransform)
+-                    {
+-                        throw Exception("Child transform could not be parsed.");
+-                    }
+-                    
+-                    t->push_back(childTransform);
++                    load(second, stringval);
++                    v.name = stringval;
++                }
++                else if(key == "colorspace")
++                {
++                    load(second, stringval);
++                    v.colorspace = stringval;
++                }
++                else if(key == "looks" || key == "look")
++                {
++                    load(second, stringval);
++                    v.looks = stringval;
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
+                 }
+             }
+-            else if(key == "direction")
++            
++            if(v.name.empty())
+             {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
++                throw Exception("View does not specify 'name'.");
+             }
+-            else
++            if(v.colorspace.empty())
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                std::ostringstream os;
++                os << "View '" << v.name << "' ";
++                os << "does not specify colorspace.";
++                throw Exception(os.str().c_str());
+             }
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("GroupTransform");
+-        out << YAML::BeginMap;
+-        EmitBaseTransformKeyValues(out, t);
+-        
+-        out << YAML::Key << "children";
+-        out << YAML::Value;
+         
+-        out << YAML::BeginSeq;
+-        for(int i = 0; i < t->size(); ++i)
++        inline void save(YAML::Emitter& out, View view)
+         {
+-            out << t->getTransform(i);
++            out << YAML::VerbatimTag("View");
++            out << YAML::Flow;
++            out << YAML::BeginMap;
++            out << YAML::Key << "name" << YAML::Value << view.name;
++            out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
++            if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
++            out << YAML::EndMap;
+         }
+-        out << YAML::EndSeq;
+-        
+-        out << YAML::EndMap;
+-        
+-        return out;
+-    }
+-    
+-    
+-    
+-    void operator >> (const YAML::Node& node, FileTransformRcPtr& t)
+-    {
+-        t = FileTransform::Create();
+         
+-        std::string key, stringval;
++        // Common Transform
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void EmitBaseTransformKeyValues(YAML::Emitter & out,
++                                               const ConstTransformRcPtr & t)
+         {
+-            iter.first() >> key;
+-            
+-            if(key == "src")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setSrc(stringval.c_str());
+-            }
+-            else if(key == "cccid")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setCCCId(stringval.c_str());
+-            }
+-            else if(key == "interpolation")
+-            {
+-                Interpolation val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<Interpolation>(val))
+-                  t->setInterpolation(val);
+-            }
+-            else if(key == "direction")
+-            {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
+-            }
+-            else
++            if(t->getDirection() != TRANSFORM_DIR_FORWARD)
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                out << YAML::Key << "direction";
++                out << YAML::Value << YAML::Flow;
++                save(out, t->getDirection());
+             }
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("FileTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+-        out << YAML::Key << "src" << YAML::Value << t->getSrc();
+-        const char * cccid = t->getCCCId();
+-        if(cccid && *cccid)
+-        {
+-            out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
+-        }
+-        out << YAML::Key << "interpolation";
+-        out << YAML::Value << t->getInterpolation();
+-        
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t)
+-    {
+-        t = ColorSpaceTransform::Create();
+         
+-        std::string key, stringval;
++        // AllocationTransform
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void load(const YAML::Node& node, AllocationTransformRcPtr& t)
+         {
+-            iter.first() >> key;
++            t = AllocationTransform::Create();
+             
+-            if(key == "src")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setSrc(stringval.c_str());
+-            }
+-            else if(key == "dst")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setDst(stringval.c_str());
+-            }
+-            else if(key == "direction")
+-            {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
+-            }
+-            else
+-            {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++            std::string key;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "allocation")
++                {
++                    Allocation val;
++                    load(second, val);
++                    t->setAllocation(val);
++                }
++                else if(key == "vars")
++                {
++                    std::vector<float> val;
++                    load(second, val);
++                    if(!val.empty())
++                    {
++                        t->setVars(static_cast<int>(val.size()), &val[0]);
++                    }
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
+             }
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("ColorSpaceTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+-        out << YAML::Key << "src" << YAML::Value << t->getSrc();
+-        out << YAML::Key << "dst" << YAML::Value << t->getDst();
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, LookTransformRcPtr& t)
+-    {
+-        t = LookTransform::Create();
+-        
+-        std::string key, stringval;
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void save(YAML::Emitter& out, ConstAllocationTransformRcPtr t)
+         {
+-            iter.first() >> key;
++            out << YAML::VerbatimTag("AllocationTransform");
++            out << YAML::Flow << YAML::BeginMap;
+             
+-            if(key == "src")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setSrc(stringval.c_str());
+-            }
+-            else if(key == "dst")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setDst(stringval.c_str());
+-            }
+-            else if(key == "looks")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setLooks(stringval.c_str());
+-            }
+-            else if(key == "direction")
+-            {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
+-            }
+-            else
++            out << YAML::Key << "allocation";
++            out << YAML::Value << YAML::Flow;
++            save(out, t->getAllocation());
++            
++            if(t->getNumVars() > 0)
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                std::vector<float> vars(t->getNumVars());
++                t->getVars(&vars[0]);
++                out << YAML::Key << "vars";
++                out << YAML::Flow << YAML::Value << vars;
+             }
++            
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("LookTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+-        out << YAML::Key << "src" << YAML::Value << t->getSrc();
+-        out << YAML::Key << "dst" << YAML::Value << t->getDst();
+-        out << YAML::Key << "looks" << YAML::Value << t->getLooks();
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t)
+-    {
+-        t = ExponentTransform::Create();
+         
+-        std::string key;
++        // CDLTransform
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void load(const YAML::Node& node, CDLTransformRcPtr& t)
+         {
+-            iter.first() >> key;
++            t = CDLTransform::Create();
+             
+-            if(key == "value")
+-            {
+-                std::vector<float> val;
+-                if (iter.second().Type() != YAML::NodeType::Null)
++            std::string key;
++            std::vector<float> floatvecval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "slope")
+                 {
+-                    iter.second() >> val;
+-                    if(val.size() != 4)
++                    load(second, floatvecval);
++                    if(floatvecval.size() != 3)
+                     {
+                         std::ostringstream os;
+-                        os << "ExponentTransform parse error, value field must be 4 ";
+-                        os << "floats. Found '" << val.size() << "'.";
++                        os << "CDLTransform parse error, 'slope' field must be 3 ";
++                        os << "floats. Found '" << floatvecval.size() << "'.";
+                         throw Exception(os.str().c_str());
+                     }
+-                    t->setValue(&val[0]);
++                    t->setSlope(&floatvecval[0]);
+                 }
+-            }
+-            else if(key == "direction")
+-            {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
+-            }
+-            else
+-            {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
+-            }
+-        }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("ExponentTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+-        
+-        std::vector<float> value(4, 0.0);
+-        t->getValue(&value[0]);
+-        out << YAML::Key << "value";
+-        out << YAML::Value << YAML::Flow << value;
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, LogTransformRcPtr& t)
+-    {
+-        t = LogTransform::Create();
+-        
+-        std::string key;
+-        
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
+-        {
+-            iter.first() >> key;
+-            
+-            if(key == "base")
+-            {
+-                float val = 0.0f;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<float>(val))
+-                  t->setBase(val);
+-            }
+-            else if(key == "direction")
+-            {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
+-            }
+-            else
+-            {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
+-            }
+-        }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("LogTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+-        out << YAML::Key << "base" << YAML::Value << t->getBase();
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t)
+-    {
+-        t = MatrixTransform::Create();
+-        
+-        std::string key;
+-        
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
+-        {
+-            iter.first() >> key;
+-            
+-            if(key == "matrix")
+-            {
+-                std::vector<float> val;
+-                if (iter.second().Type() != YAML::NodeType::Null)
++                else if(key == "offset")
+                 {
+-                    iter.second() >> val;
+-                    if(val.size() != 16)
++                    load(second, floatvecval);
++                    if(floatvecval.size() != 3)
+                     {
+                         std::ostringstream os;
+-                        os << "MatrixTransform parse error, matrix field must be 16 ";
+-                        os << "floats. Found '" << val.size() << "'.";
++                        os << "CDLTransform parse error, 'offset' field must be 3 ";
++                        os << "floats. Found '" << floatvecval.size() << "'.";
+                         throw Exception(os.str().c_str());
+                     }
+-                    t->setMatrix(&val[0]);
++                    t->setOffset(&floatvecval[0]);
+                 }
+-            }
+-            else if(key == "offset")
+-            {
+-                std::vector<float> val;
+-                if (iter.second().Type() != YAML::NodeType::Null)
++                else if(key == "power")
+                 {
+-                    iter.second() >> val;
+-                    if(val.size() != 4)
++                    load(second, floatvecval);
++                    if(floatvecval.size() != 3)
+                     {
+                         std::ostringstream os;
+-                        os << "MatrixTransform parse error, offset field must be 4 ";
+-                        os << "floats. Found '" << val.size() << "'.";
++                        os << "CDLTransform parse error, 'power' field must be 3 ";
++                        os << "floats. Found '" << floatvecval.size() << "'.";
+                         throw Exception(os.str().c_str());
+                     }
+-                    t->setOffset(&val[0]);
++                    t->setPower(&floatvecval[0]);
++                }
++                else if(key == "saturation" || key == "sat")
++                {
++                    float val = 0.0f;
++                    load(second, val);
++                    t->setSat(val);
+                 }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
++        }
++        
++        inline void save(YAML::Emitter& out, ConstCDLTransformRcPtr t)
++        {
++            out << YAML::VerbatimTag("CDLTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            
++            std::vector<float> slope(3);
++            t->getSlope(&slope[0]);
++            if(!IsVecEqualToOne(&slope[0], 3))
++            {
++                out << YAML::Key << "slope";
++                out << YAML::Value << YAML::Flow << slope;
+             }
+-            else if(key == "direction")
++            
++            std::vector<float> offset(3);
++            t->getOffset(&offset[0]);
++            if(!IsVecEqualToZero(&offset[0], 3))
+             {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
++                out << YAML::Key << "offset";
++                out << YAML::Value << YAML::Flow << offset;
+             }
+-            else
++            
++            std::vector<float> power(3);
++            t->getPower(&power[0]);
++            if(!IsVecEqualToOne(&power[0], 3))
++            {
++                out << YAML::Key << "power";
++                out << YAML::Value << YAML::Flow << power;
++            }
++            
++            if(!IsScalarEqualToOne(t->getSat()))
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                out << YAML::Key << "sat" << YAML::Value << t->getSat();
+             }
++            
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("MatrixTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+         
+-        std::vector<float> matrix(16, 0.0);
+-        t->getMatrix(&matrix[0]);
+-        if(!IsM44Identity(&matrix[0]))
++        // ColorSpaceTransform
++        
++        inline void load(const YAML::Node& node, ColorSpaceTransformRcPtr& t)
+         {
+-            out << YAML::Key << "matrix";
+-            out << YAML::Value << YAML::Flow << matrix;
++            t = ColorSpaceTransform::Create();
++            
++            std::string key, stringval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "src")
++                {
++                    load(second, stringval);
++                    t->setSrc(stringval.c_str());
++                }
++                else if(key == "dst")
++                {
++                    load(second, stringval);
++                    t->setDst(stringval.c_str());
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
+         }
+         
+-        std::vector<float> offset(4, 0.0);
+-        t->getOffset(&offset[0]);
+-        if(!IsVecEqualToZero(&offset[0],4))
++        inline void save(YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
+         {
+-            out << YAML::Key << "offset";
+-            out << YAML::Value << YAML::Flow << offset;
++            out << YAML::VerbatimTag("ColorSpaceTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            out << YAML::Key << "src" << YAML::Value << t->getSrc();
++            out << YAML::Key << "dst" << YAML::Value << t->getDst();
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
+         }
+         
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, CDLTransformRcPtr& t)
+-    {
+-        t = CDLTransform::Create();
++        // ExponentTransform
+         
+-        std::string key;
+-        std::vector<float> floatvecval;
+-        
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void load(const YAML::Node& node, ExponentTransformRcPtr& t)
+         {
+-            iter.first() >> key;
++            t = ExponentTransform::Create();
+             
+-            if(key == "slope")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null)
++            std::string key;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "value")
+                 {
+-                    iter.second() >> floatvecval;
+-                    if(floatvecval.size() != 3)
++                    std::vector<float> val;
++                    load(second, val);
++                    if(val.size() != 4)
+                     {
+                         std::ostringstream os;
+-                        os << "CDLTransform parse error, 'slope' field must be 3 ";
+-                        os << "floats. Found '" << floatvecval.size() << "'.";
++                        os << "ExponentTransform parse error, value field must be 4 ";
++                        os << "floats. Found '" << val.size() << "'.";
+                         throw Exception(os.str().c_str());
+                     }
+-                    t->setSlope(&floatvecval[0]);
++                    t->setValue(&val[0]);
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
+                 }
+             }
+-            else if(key == "offset")
+-            {
+-                if (iter.second().Type() != YAML::NodeType::Null)
++        }
++        
++        inline void save(YAML::Emitter& out, ConstExponentTransformRcPtr t)
++        {
++            out << YAML::VerbatimTag("ExponentTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            
++            std::vector<float> value(4, 0.0);
++            t->getValue(&value[0]);
++            out << YAML::Key << "value";
++            out << YAML::Value << YAML::Flow << value;
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
++        }
++        
++        // FileTransform
++        
++        inline void load(const YAML::Node& node, FileTransformRcPtr& t)
++        {
++            t = FileTransform::Create();
++            
++            std::string key, stringval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "src")
+                 {
+-                    iter.second() >> floatvecval;
+-                    if(floatvecval.size() != 3)
+-                    {
+-                        std::ostringstream os;
+-                        os << "CDLTransform parse error, 'offset' field must be 3 ";
+-                        os << "floats. Found '" << floatvecval.size() << "'.";
+-                        throw Exception(os.str().c_str());
+-                    }
+-                    t->setOffset(&floatvecval[0]);
++                    load(second, stringval);
++                    t->setSrc(stringval.c_str());
++                }
++                else if(key == "cccid")
++                {
++                    load(second, stringval);
++                    t->setCCCId(stringval.c_str());
++                }
++                else if(key == "interpolation")
++                {
++                    Interpolation val;
++                    load(second, val);
++                    t->setInterpolation(val);
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
+                 }
+             }
+-            else if(key == "power")
++        }
++        
++        inline void save(YAML::Emitter& out, ConstFileTransformRcPtr t)
++        {
++            out << YAML::VerbatimTag("FileTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            out << YAML::Key << "src" << YAML::Value << t->getSrc();
++            const char * cccid = t->getCCCId();
++            if(cccid && *cccid)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null)
++                out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
++            }
++            out << YAML::Key << "interpolation";
++            out << YAML::Value;
++            save(out, t->getInterpolation());
++            
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
++        }
++        
++        // GroupTransform
++        
++        void load(const YAML::Node& node, TransformRcPtr& t);
++        void save(YAML::Emitter& out, ConstTransformRcPtr t);
++        
++        inline void load(const YAML::Node& node, GroupTransformRcPtr& t)
++        {
++            t = GroupTransform::Create();
++            
++            std::string key;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "children")
+                 {
+-                    iter.second() >> floatvecval;
+-                    if(floatvecval.size() != 3)
++                    for(unsigned i = 0; i < second.size(); ++i)
+                     {
+-                        std::ostringstream os;
+-                        os << "CDLTransform parse error, 'power' field must be 3 ";
+-                        os << "floats. Found '" << floatvecval.size() << "'.";
+-                        throw Exception(os.str().c_str());
++                        TransformRcPtr childTransform;
++                        load(second[i], childTransform);
++                        
++                        // TODO: consider the forwards-compatibility implication of
++                        // throwing an exception.  Should this be a warning, instead?
++                        if(!childTransform)
++                        {
++                            throw Exception("Child transform could not be parsed.");
++                        }
++                        
++                        t->push_back(childTransform);
+                     }
+-                    t->setPower(&floatvecval[0]);
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
+                 }
+             }
+-            else if(key == "saturation" || key == "sat")
+-            {
+-                float val = 0.0f;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<float>(val))
+-                  t->setSat(val);
+-            }
+-            else if(key == "direction")
+-            {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
+-            }
+-            else
++        }
++        
++        inline void save(YAML::Emitter& out, ConstGroupTransformRcPtr t)
++        {
++            out << YAML::VerbatimTag("GroupTransform");
++            out << YAML::BeginMap;
++            EmitBaseTransformKeyValues(out, t);
++            
++            out << YAML::Key << "children";
++            out << YAML::Value;
++            
++            out << YAML::BeginSeq;
++            for(int i = 0; i < t->size(); ++i)
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                save(out, t->getTransform(i));
+             }
++            out << YAML::EndSeq;
++            
++            out << YAML::EndMap;
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("CDLTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+         
+-        std::vector<float> slope(3);
+-        t->getSlope(&slope[0]);
+-        if(!IsVecEqualToOne(&slope[0], 3))
++        // LogTransform
++        
++        inline void load(const YAML::Node& node, LogTransformRcPtr& t)
+         {
+-            out << YAML::Key << "slope";
+-            out << YAML::Value << YAML::Flow << slope;
++            t = LogTransform::Create();
++            
++            std::string key;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "base")
++                {
++                    float val = 0.0f;
++                    load(second, val);
++                    t->setBase(val);
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
+         }
+         
+-        std::vector<float> offset(3);
+-        t->getOffset(&offset[0]);
+-        if(!IsVecEqualToZero(&offset[0], 3))
++        inline void save(YAML::Emitter& out, ConstLogTransformRcPtr t)
+         {
+-            out << YAML::Key << "offset";
+-            out << YAML::Value << YAML::Flow << offset;
++            out << YAML::VerbatimTag("LogTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            out << YAML::Key << "base" << YAML::Value << t->getBase();
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
+         }
+         
+-        std::vector<float> power(3);
+-        t->getPower(&power[0]);
+-        if(!IsVecEqualToOne(&power[0], 3))
++        // LookTransform
++        
++        inline void load(const YAML::Node& node, LookTransformRcPtr& t)
+         {
+-            out << YAML::Key << "power";
+-            out << YAML::Value << YAML::Flow << power;
++            t = LookTransform::Create();
++            
++            std::string key, stringval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "src")
++                {
++                    load(second, stringval);
++                    t->setSrc(stringval.c_str());
++                }
++                else if(key == "dst")
++                {
++                    load(second, stringval);
++                    t->setDst(stringval.c_str());
++                }
++                else if(key == "looks")
++                {
++                    load(second, stringval);
++                    t->setLooks(stringval.c_str());
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
+         }
+         
+-        if(!IsScalarEqualToOne(t->getSat()))
++        inline void save(YAML::Emitter& out, ConstLookTransformRcPtr t)
+         {
+-            out << YAML::Key << "sat" << YAML::Value << t->getSat();
++            out << YAML::VerbatimTag("LookTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            out << YAML::Key << "src" << YAML::Value << t->getSrc();
++            out << YAML::Key << "dst" << YAML::Value << t->getDst();
++            out << YAML::Key << "looks" << YAML::Value << t->getLooks();
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
+         }
+         
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t)
+-    {
+-        t = AllocationTransform::Create();
+-        
+-        std::string key;
++        // MatrixTransform
+         
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void load(const YAML::Node& node, MatrixTransformRcPtr& t)
+         {
+-            iter.first() >> key;
++            t = MatrixTransform::Create();
+             
+-            if(key == "allocation")
+-            {
+-                Allocation val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<Allocation>(val))
+-                  t->setAllocation(val);
+-            }
+-            else if(key == "vars")
+-            {
+-                std::vector<float> val;
+-                if (iter.second().Type() != YAML::NodeType::Null)
++            std::string key;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "matrix")
+                 {
+-                    iter.second() >> val;
+-                    if(!val.empty())
++                    std::vector<float> val;
++                    load(second, val);
++                    if(val.size() != 16)
+                     {
+-                        t->setVars(static_cast<int>(val.size()), &val[0]);
++                        std::ostringstream os;
++                        os << "MatrixTransform parse error, matrix field must be 16 ";
++                        os << "floats. Found '" << val.size() << "'.";
++                        throw Exception(os.str().c_str());
++                    }
++                    t->setMatrix(&val[0]);
++                }
++                else if(key == "offset")
++                {
++                    std::vector<float> val;
++                    load(second, val);
++                    if(val.size() != 4)
++                    {
++                        std::ostringstream os;
++                        os << "MatrixTransform parse error, offset field must be 4 ";
++                        os << "floats. Found '" << val.size() << "'.";
++                        throw Exception(os.str().c_str());
+                     }
++                    t->setOffset(&val[0]);
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
+                 }
+             }
+-            else if(key == "direction")
++        }
++        
++        inline void save(YAML::Emitter& out, ConstMatrixTransformRcPtr t)
++        {
++            out << YAML::VerbatimTag("MatrixTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            
++            std::vector<float> matrix(16, 0.0);
++            t->getMatrix(&matrix[0]);
++            if(!IsM44Identity(&matrix[0]))
+             {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
++                out << YAML::Key << "matrix";
++                out << YAML::Value << YAML::Flow << matrix;
+             }
+-            else
++            
++            std::vector<float> offset(4, 0.0);
++            t->getOffset(&offset[0]);
++            if(!IsVecEqualToZero(&offset[0],4))
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                out << YAML::Key << "offset";
++                out << YAML::Value << YAML::Flow << offset;
+             }
++            
++            EmitBaseTransformKeyValues(out, t);
++            out << YAML::EndMap;
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t)
+-    {
+-        out << YAML::VerbatimTag("AllocationTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+         
+-        out << YAML::Key << "allocation";
+-        out << YAML::Value << YAML::Flow << t->getAllocation();
++        // TruelightTransform
+         
+-        if(t->getNumVars() > 0)
++        inline void load(const YAML::Node& node, TruelightTransformRcPtr& t)
+         {
+-            std::vector<float> vars(t->getNumVars());
+-            t->getVars(&vars[0]);
+-            out << YAML::Key << "vars";
+-            out << YAML::Flow << YAML::Value << vars;
++            t = TruelightTransform::Create();
++            
++            std::string key, stringval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "config_root")
++                {
++                    load(second, stringval);
++                    t->setConfigRoot(stringval.c_str());
++                }
++                else if(key == "profile")
++                {
++                    load(second, stringval);
++                    t->setProfile(stringval.c_str());
++                }
++                else if(key == "camera")
++                {
++                    load(second, stringval);
++                    t->setCamera(stringval.c_str());
++                }
++                else if(key == "input_display")
++                {
++                    load(second, stringval);
++                    t->setInputDisplay(stringval.c_str());
++                }
++                else if(key == "recorder")
++                {
++                    load(second, stringval);
++                    t->setRecorder(stringval.c_str());
++                }
++                else if(key == "print")
++                {
++                    load(second, stringval);
++                    t->setPrint(stringval.c_str());
++                }
++                else if(key == "lamp")
++                {
++                    load(second, stringval);
++                    t->setLamp(stringval.c_str());
++                }
++                else if(key == "output_camera")
++                {
++                    load(second, stringval);
++                    t->setOutputCamera(stringval.c_str());
++                }
++                else if(key == "display")
++                {
++                    load(second, stringval);
++                    t->setDisplay(stringval.c_str());
++                }
++                else if(key == "cube_input")
++                {
++                    load(second, stringval);
++                     t->setCubeInput(stringval.c_str());
++                }
++                else if(key == "direction")
++                {
++                    TransformDirection val;
++                    load(second, val);
++                    t->setDirection(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
+         }
+         
+-        EmitBaseTransformKeyValues(out, t);
+-        out << YAML::EndMap;
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t)
+-    {
+-        t = TruelightTransform::Create();
+-        
+-        std::string key, stringval;
+-        
+-        for (YAML::Iterator iter = node.begin();
+-             iter != node.end();
+-             ++iter)
++        inline void save(YAML::Emitter& out, ConstTruelightTransformRcPtr t)
+         {
+-            iter.first() >> key;
+             
+-            if(key == "config_root")
++            out << YAML::VerbatimTag("TruelightTransform");
++            out << YAML::Flow << YAML::BeginMap;
++            if(strcmp(t->getConfigRoot(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setConfigRoot(stringval.c_str());
++                out << YAML::Key << "config_root";
++                out << YAML::Value << YAML::Flow << t->getConfigRoot();
+             }
+-            else if(key == "profile")
++            if(strcmp(t->getProfile(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setProfile(stringval.c_str());
++                out << YAML::Key << "profile";
++                out << YAML::Value << YAML::Flow << t->getProfile();
+             }
+-            else if(key == "camera")
++            if(strcmp(t->getCamera(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setCamera(stringval.c_str());
++                out << YAML::Key << "camera";
++                out << YAML::Value << YAML::Flow << t->getCamera();
+             }
+-            else if(key == "input_display")
++            if(strcmp(t->getInputDisplay(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setInputDisplay(stringval.c_str());
++                out << YAML::Key << "input_display";
++                out << YAML::Value << YAML::Flow << t->getInputDisplay();
+             }
+-            else if(key == "recorder")
++            if(strcmp(t->getRecorder(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setRecorder(stringval.c_str());
++                out << YAML::Key << "recorder";
++                out << YAML::Value << YAML::Flow << t->getRecorder();
+             }
+-            else if(key == "print")
++            if(strcmp(t->getPrint(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setPrint(stringval.c_str());
++                out << YAML::Key << "print";
++                out << YAML::Value << YAML::Flow << t->getPrint();
+             }
+-            else if(key == "lamp")
++            if(strcmp(t->getLamp(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setLamp(stringval.c_str());
++                out << YAML::Key << "lamp";
++                out << YAML::Value << YAML::Flow << t->getLamp();
+             }
+-            else if(key == "output_camera")
++            if(strcmp(t->getOutputCamera(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setOutputCamera(stringval.c_str());
++                out << YAML::Key << "output_camera";
++                out << YAML::Value << YAML::Flow << t->getOutputCamera();
+             }
+-            else if(key == "display")
++            if(strcmp(t->getDisplay(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setDisplay(stringval.c_str());
++                out << YAML::Key << "display";
++                out << YAML::Value << YAML::Flow << t->getDisplay();
+             }
+-            else if(key == "cube_input")
++            if(strcmp(t->getCubeInput(), "") != 0)
+             {
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<std::string>(stringval))
+-                  t->setCubeInput(stringval.c_str());
++                out << YAML::Key << "cube_input";
++                out << YAML::Value << YAML::Flow << t->getCubeInput();
+             }
+-            else if(key == "direction")
++            
++            EmitBaseTransformKeyValues(out, t);
++            
++            out << YAML::EndMap;
++        }
++        
++        // Transform
++        
++        void load(const YAML::Node& node, TransformRcPtr& t)
++        {
++            if(node.Type() != YAML::NodeType::Map)
+             {
+-                TransformDirection val;
+-                if (iter.second().Type() != YAML::NodeType::Null && 
+-                    iter.second().Read<TransformDirection>(val))
+-                  t->setDirection(val);
++                std::ostringstream os;
++                os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
++                os << "Only Mapping types supported.";
++                throw Exception(os.str().c_str());
++            }
++            
++            std::string type = node.Tag();
++            
++            if(type == "AllocationTransform") {
++                AllocationTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "CDLTransform") {
++                CDLTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "ColorSpaceTransform")  {
++                ColorSpaceTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            // TODO: DisplayTransform
++            else if(type == "ExponentTransform")  {
++                ExponentTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "FileTransform")  {
++                FileTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "GroupTransform") {
++                GroupTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "LogTransform") {
++                LogTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "LookTransform") {
++                LookTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "MatrixTransform")  {
++                MatrixTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
++            }
++            else if(type == "TruelightTransform")  {
++                TruelightTransformRcPtr temp;
++                load(node, temp);
++                t = temp;
+             }
+             else
+             {
+-                LogUnknownKeyWarning(node.Tag(), iter.first());
++                // TODO: add a new empty (better name?) aka passthru Transform()
++                // which does nothing. This is so upsupported !<tag> types don't
++                // throw an exception. Alternativly this could be caught in the
++                // GroupTransformRcPtr >> operator with some type of
++                // supported_tag() method
++                
++                // TODO: consider the forwards-compatibility implication of
++                // throwing an exception.  Should this be a warning, instead?
++                
++                //  t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
++                std::ostringstream os;
++                os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
++                throw Exception(os.str().c_str());
+             }
+         }
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t)
+-    {
+         
+-        out << YAML::VerbatimTag("TruelightTransform");
+-        out << YAML::Flow << YAML::BeginMap;
+-        if(strcmp(t->getConfigRoot(), "") != 0)
+-        {
+-            out << YAML::Key << "config_root";
+-            out << YAML::Value << YAML::Flow << t->getConfigRoot();
+-        }
+-        if(strcmp(t->getProfile(), "") != 0)
++        void save(YAML::Emitter& out, ConstTransformRcPtr t)
+         {
+-            out << YAML::Key << "profile";
+-            out << YAML::Value << YAML::Flow << t->getProfile();
+-        }
+-        if(strcmp(t->getCamera(), "") != 0)
+-        {
+-            out << YAML::Key << "camera";
+-            out << YAML::Value << YAML::Flow << t->getCamera();
+-        }
+-        if(strcmp(t->getInputDisplay(), "") != 0)
+-        {
+-            out << YAML::Key << "input_display";
+-            out << YAML::Value << YAML::Flow << t->getInputDisplay();
++            if(ConstAllocationTransformRcPtr Allocation_tran = \
++                DynamicPtrCast<const AllocationTransform>(t))
++                save(out, Allocation_tran);
++            else if(ConstCDLTransformRcPtr CDL_tran = \
++                DynamicPtrCast<const CDLTransform>(t))
++                save(out, CDL_tran);
++            else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
++                DynamicPtrCast<const ColorSpaceTransform>(t))
++                save(out, ColorSpace_tran);
++            else if(ConstExponentTransformRcPtr Exponent_tran = \
++                DynamicPtrCast<const ExponentTransform>(t))
++                save(out, Exponent_tran);
++            else if(ConstFileTransformRcPtr File_tran = \
++                DynamicPtrCast<const FileTransform>(t))
++                save(out, File_tran);
++            else if(ConstGroupTransformRcPtr Group_tran = \
++                DynamicPtrCast<const GroupTransform>(t))
++                save(out, Group_tran);
++            else if(ConstLogTransformRcPtr Log_tran = \
++                DynamicPtrCast<const LogTransform>(t))
++                save(out, Log_tran);
++            else if(ConstLookTransformRcPtr Look_tran = \
++                DynamicPtrCast<const LookTransform>(t))
++                save(out, Look_tran);
++            else if(ConstMatrixTransformRcPtr Matrix_tran = \
++                DynamicPtrCast<const MatrixTransform>(t))
++                save(out, Matrix_tran);
++            else if(ConstTruelightTransformRcPtr Truelight_tran = \
++                DynamicPtrCast<const TruelightTransform>(t))
++                save(out, Truelight_tran);
++            else
++                throw Exception("Unsupported Transform() type for serialization.");
+         }
+-        if(strcmp(t->getRecorder(), "") != 0)
++        
++        // ColorSpace
++        
++        inline void load(const YAML::Node& node, ColorSpaceRcPtr& cs)
+         {
+-            out << YAML::Key << "recorder";
+-            out << YAML::Value << YAML::Flow << t->getRecorder();
++            if(node.Tag() != "ColorSpace")
++                return; // not a !<ColorSpace> tag
++            
++            std::string key, stringval;
++            bool boolval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "name")
++                {
++                    load(second, stringval);
++                    cs->setName(stringval.c_str());
++                }
++                else if(key == "description")
++                {
++                    load(second, stringval);
++                    cs->setDescription(stringval.c_str());
++                }
++                else if(key == "family")
++                {
++                    load(second, stringval);
++                    cs->setFamily(stringval.c_str());
++                }
++                else if(key == "equalitygroup")
++                {
++                    load(second, stringval);
++                    cs->setEqualityGroup(stringval.c_str());
++                }
++                else if(key == "bitdepth")
++                {
++                    BitDepth ret;
++                    load(second, ret);
++                    cs->setBitDepth(ret);
++                }
++                else if(key == "isdata")
++                {
++                    load(second, boolval);
++                    cs->setIsData(boolval);
++                }
++                else if(key == "allocation")
++                {
++                    Allocation val;
++                    load(second, val);
++                    cs->setAllocation(val);
++                }
++                else if(key == "allocationvars")
++                {
++                    std::vector<float> val;
++                    load(second, val);
++                    if(!val.empty())
++                        cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
++                }
++                else if(key == "to_reference")
++                {
++                    TransformRcPtr val;
++                    load(second, val);
++                    cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
++                }
++                else if(key == "from_reference")
++                {
++                    TransformRcPtr val;
++                    load(second, val);
++                    cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
+         }
+-        if(strcmp(t->getPrint(), "") != 0)
++        
++        inline void save(YAML::Emitter& out, ConstColorSpaceRcPtr cs)
+         {
+-            out << YAML::Key << "print";
+-            out << YAML::Value << YAML::Flow << t->getPrint();
++            out << YAML::VerbatimTag("ColorSpace");
++            out << YAML::BeginMap;
++            
++            out << YAML::Key << "name" << YAML::Value << cs->getName();
++            out << YAML::Key << "family" << YAML::Value << cs->getFamily();
++            out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
++            out << YAML::Key << "bitdepth" << YAML::Value;
++            save(out, cs->getBitDepth());
++            if(cs->getDescription() != NULL && strlen(cs->getDescription()) > 0)
++            {
++                out << YAML::Key << "description";
++                out << YAML::Value << YAML::Literal << cs->getDescription();
++            }
++            out << YAML::Key << "isdata" << YAML::Value << cs->isData();
++            
++            out << YAML::Key << "allocation" << YAML::Value;
++            save(out, cs->getAllocation());
++            if(cs->getAllocationNumVars() > 0)
++            {
++                std::vector<float> allocationvars(cs->getAllocationNumVars());
++                cs->getAllocationVars(&allocationvars[0]);
++                out << YAML::Key << "allocationvars";
++                out << YAML::Flow << YAML::Value << allocationvars;
++            }
++            
++            ConstTransformRcPtr toref = \
++                cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
++            if(toref)
++            {
++                out << YAML::Key << "to_reference" << YAML::Value;
++                save(out, toref);
++            }
++            
++            ConstTransformRcPtr fromref = \
++                cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
++            if(fromref)
++            {
++                out << YAML::Key << "from_reference" << YAML::Value;
++                save(out, fromref);
++            }
++            
++            out << YAML::EndMap;
++            out << YAML::Newline;
+         }
+-        if(strcmp(t->getLamp(), "") != 0)
++        
++        // Look
++        
++        inline void load(const YAML::Node& node, LookRcPtr& look)
+         {
+-            out << YAML::Key << "lamp";
+-            out << YAML::Value << YAML::Flow << t->getLamp();
++            if(node.Tag() != "Look")
++                return;
++            
++            std::string key, stringval;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "name")
++                {
++                    load(second, stringval);
++                    look->setName(stringval.c_str());
++                }
++                else if(key == "process_space")
++                {
++                    load(second, stringval);
++                    look->setProcessSpace(stringval.c_str());
++                }
++                else if(key == "transform")
++                {
++                    TransformRcPtr val;
++                    load(second, val);
++                    look->setTransform(val);
++                }
++                else if(key == "inverse_transform")
++                {
++                    TransformRcPtr val;
++                    load(second, val);
++                    look->setInverseTransform(val);
++                }
++                else
++                {
++                    LogUnknownKeyWarning(node.Tag(), first);
++                }
++            }
+         }
+-        if(strcmp(t->getOutputCamera(), "") != 0)
++        
++        inline void save(YAML::Emitter& out, ConstLookRcPtr look)
+         {
+-            out << YAML::Key << "output_camera";
+-            out << YAML::Value << YAML::Flow << t->getOutputCamera();
++            out << YAML::VerbatimTag("Look");
++            out << YAML::BeginMap;
++            out << YAML::Key << "name" << YAML::Value << look->getName();
++            out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
++            
++            if(look->getTransform())
++            {
++                out << YAML::Key << "transform";
++                out << YAML::Value;
++                save(out, look->getTransform());
++            }
++            
++            if(look->getInverseTransform())
++            {
++                out << YAML::Key << "inverse_transform";
++                out << YAML::Value;
++                save(out, look->getInverseTransform());
++            }
++            
++            out << YAML::EndMap;
++            out << YAML::Newline;
+         }
+-        if(strcmp(t->getDisplay(), "") != 0)
++        
++        // Config
++        
++        inline void load(const YAML::Node& node, ConfigRcPtr& c, const char* filename)
+         {
+-            out << YAML::Key << "display";
+-            out << YAML::Value << YAML::Flow << t->getDisplay();
++            
++            // check profile version
++            int profile_version = 0;
++#ifdef OLDYAML
++            if(node.FindValue("ocio_profile_version") == NULL)
++#else
++            if(node["ocio_profile_version"] == NULL)
++#endif
++            {
++                std::ostringstream os;
++                os << "The specified file ";
++                os << "does not appear to be an OCIO configuration.";
++                throw Exception (os.str().c_str());
++            }
++            
++            load(node["ocio_profile_version"], profile_version);
++            if(profile_version > 1)
++            {
++                std::ostringstream os;
++                os << "This .ocio config ";
++                if(filename && *filename)
++                {
++                    os << " '" << filename << "' ";
++                }
++                os << "is version " << profile_version << ". ";
++                os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
++                os << "is not known to be able to load this profile. ";
++                os << "An attempt will be made, but there are no guarantees that the ";
++                os << "results will be accurate. Continue at your own risk.";
++                LogWarning(os.str());
++            }
++            
++            std::string key, stringval;
++            bool boolval = false;
++            EnvironmentMode mode = ENV_ENVIRONMENT_LOAD_ALL;
++            
++            for (Iterator iter = node.begin();
++                 iter != node.end();
++                 ++iter)
++            {
++                const YAML::Node& first = get_first(iter);
++                const YAML::Node& second = get_second(iter);
++                
++                load(first, key);
++                
++                if (second.Type() == YAML::NodeType::Null) continue;
++                
++                if(key == "ocio_profile_version") { } // Already handled above.
++                else if(key == "environment")
++                {
++                    mode = ENV_ENVIRONMENT_LOAD_PREDEFINED;
++                    if(second.Type() != YAML::NodeType::Map)
++                    {
++                        std::ostringstream os;
++                        os << "'environment' field needs to be a (name: key) map.";
++                        throw Exception(os.str().c_str());
++                    }
++                    for (Iterator it = second.begin();
++                         it != second.end();
++                         ++it)
++                    {
++                        std::string k, v;
++                        load(get_first(it), k);
++                        load(get_second(it), v);
++                        c->addEnvironmentVar(k.c_str(), v.c_str());
++                    }
++                }
++                else if(key == "search_path" || key == "resource_path")
++                {
++                    load(second, stringval);
++                    c->setSearchPath(stringval.c_str());
++                }
++                else if(key == "strictparsing")
++                {
++                    load(second, boolval);
++                    c->setStrictParsingEnabled(boolval);
++                }
++                else if(key == "description")
++                {
++                    load(second, stringval);
++                    c->setDescription(stringval.c_str());
++                }
++                else if(key == "luma")
++                {
++                    std::vector<float> val;
++                    load(second, val);
++                    if(val.size() != 3)
++                    {
++                        std::ostringstream os;
++                        os << "'luma' field must be 3 ";
++                        os << "floats. Found '" << val.size() << "'.";
++                        throw Exception(os.str().c_str());
++                    }
++                    c->setDefaultLumaCoefs(&val[0]);
++                }
++                else if(key == "roles")
++                {
++                    if(second.Type() != YAML::NodeType::Map)
++                    {
++                        std::ostringstream os;
++                        os << "'roles' field needs to be a (name: key) map.";
++                        throw Exception(os.str().c_str());
++                    }
++                    for (Iterator it = second.begin();
++                         it != second.end();
++                         ++it)
++                    {
++                        std::string k, v;
++                        load(get_first(it), k);
++                        load(get_second(it), v);
++                        c->setRole(k.c_str(), v.c_str());
++                    }
++                }
++                else if(key == "displays")
++                {
++                    if(second.Type() != YAML::NodeType::Map)
++                    {
++                        std::ostringstream os;
++                        os << "'displays' field needs to be a (name: key) map.";
++                        throw Exception(os.str().c_str());
++                    }
++                    for (Iterator it = second.begin();
++                         it != second.end();
++                         ++it)
++                    {
++                        std::string display;
++                        load(get_first(it), display);
++                        const YAML::Node& dsecond = get_second(it);
++                        for(unsigned i = 0; i < dsecond.size(); ++i)
++                        {
++                            View view;
++                            load(dsecond[i], view);
++                            c->addDisplay(display.c_str(), view.name.c_str(),
++                                          view.colorspace.c_str(), view.looks.c_str());
++                        }
++                    }
++                }
++                else if(key == "active_displays")
++                {
++                    std::vector<std::string> display;
++                    load(second, display);
++                    const char* displays = JoinStringEnvStyle(display).c_str();
++                    c->setActiveDisplays(displays);
++                }
++                else if(key == "active_views")
++                {
++                    std::vector<std::string> view;
++                    load(second, view);
++                    const char* views = JoinStringEnvStyle(view).c_str();
++                    c->setActiveViews(views);
++                }
++                else if(key == "colorspaces")
++                {
++                    if(second.Type() != YAML::NodeType::Sequence)
++                    {
++                        std::ostringstream os;
++                        os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
++                        throw Exception(os.str().c_str());
++                    }
++                    for(unsigned i = 0; i < second.size(); ++i)
++                    {
++                        if(second[i].Tag() == "ColorSpace")
++                        {
++                            ColorSpaceRcPtr cs = ColorSpace::Create();
++                            load(second[i], cs);
++                            for(int ii = 0; ii < c->getNumColorSpaces(); ++ii)
++                            {
++                                if(strcmp(c->getColorSpaceNameByIndex(ii), cs->getName()) == 0)
++                                {
++                                    std::ostringstream os;
++                                    os << "Colorspace with name '" << cs->getName() << "' already defined.";
++                                    throw Exception(os.str().c_str());
++                                }
++                            }
++                            c->addColorSpace(cs);
++                        }
++                        else
++                        {
++                            std::ostringstream os;
++                            os << "Unknown element found in colorspaces:";
++                            os << second[i].Tag() << ". Only ColorSpace(s)";
++                            os << " currently handled.";
++                            LogWarning(os.str());
++                        }
++                    }
++                }
++                else if(key == "looks")
++                {
++                    if(second.Type() != YAML::NodeType::Sequence)
++                    {
++                        std::ostringstream os;
++                        os << "'looks' field needs to be a (- !<Look>) list.";
++                        throw Exception(os.str().c_str());
++                    }
++                    
++                    for(unsigned i = 0; i < second.size(); ++i)
++                    {
++                        if(second[i].Tag() == "Look")
++                        {
++                            LookRcPtr look = Look::Create();
++                            load(second[i], look);
++                            c->addLook(look);
++                        }
++                        else
++                        {
++                            std::ostringstream os;
++                            os << "Unknown element found in looks:";
++                            os << second[i].Tag() << ". Only Look(s)";
++                            os << " currently handled.";
++                            LogWarning(os.str());
++                        }
++                    }
++                }
++                else
++                {
++                    LogUnknownKeyWarning("profile", first);
++                }
++            }
++            
++            if(filename)
++            {
++                std::string realfilename = pystring::os::path::abspath(filename);
++                std::string configrootdir = pystring::os::path::dirname(realfilename);
++                c->setWorkingDir(configrootdir.c_str());
++            }
++            
++            c->setEnvironmentMode(mode);
++            c->loadEnvironment();
++            
++            if(mode == ENV_ENVIRONMENT_LOAD_ALL)
++            {
++                std::ostringstream os;
++                os << "This .ocio config ";
++                if(filename && *filename)
++                {
++                    os << " '" << filename << "' ";
++                }
++                os << "has no environment section defined. The default behaviour is to ";
++                os << "load all environment variables (" << c->getNumEnvironmentVars() << ")";
++                os << ", which reduces the efficiency of OCIO's caching. Considering ";
++                os << "predefining the environment variables used.";
++                LogDebug(os.str());
++            }
++            
+         }
+-        if(strcmp(t->getCubeInput(), "") != 0)
++        
++        inline void save(YAML::Emitter& out, const Config* c)
+         {
+-            out << YAML::Key << "cube_input";
+-            out << YAML::Value << YAML::Flow << t->getCubeInput();
++            out << YAML::Block;
++            out << YAML::BeginMap;
++            out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
++            out << YAML::Newline;
++#ifndef OLDYAML
++            out << YAML::Newline;
++#endif
++            
++            if(c->getNumEnvironmentVars() > 0)
++            {
++                out << YAML::Key << "environment";
++                out << YAML::Value << YAML::BeginMap;
++                for(unsigned i = 0; i < c->getNumEnvironmentVars(); ++i)
++                {   
++                    const char* name = c->getEnvironmentVarNameByIndex(i);
++                    out << YAML::Key << name;
++                    out << YAML::Value << c->getEnvironmentVarDefault(name);
++                }
++                out << YAML::EndMap;
++                out << YAML::Newline;
++            }
++            out << YAML::Key << "search_path" << YAML::Value << c->getSearchPath();
++            out << YAML::Key << "strictparsing" << YAML::Value << c->isStrictParsingEnabled();
++            
++            std::vector<float> luma(3, 0.f);
++            c->getDefaultLumaCoefs(&luma[0]);
++            out << YAML::Key << "luma" << YAML::Value << YAML::Flow << luma;
++            
++            if(c->getDescription() != NULL && strlen(c->getDescription()) > 0)
++            {
++                out << YAML::Newline;
++                out << YAML::Key << "description";
++                out << YAML::Value << c->getDescription();
++                out << YAML::Newline;
++            }
++            
++            // Roles
++            out << YAML::Newline;
++#ifndef OLDYAML
++            out << YAML::Newline;
++#endif
++            out << YAML::Key << "roles";
++            out << YAML::Value << YAML::BeginMap;
++            for(unsigned i = 0; i < c->getNumRoles(); ++i)
++            {
++                const char* role = c->getRoleName(i);
++                out << YAML::Key << role;
++                out << YAML::Value << c->getColorSpace(role)->getName();
++            }
++            out << YAML::EndMap;
++#ifndef OLDYAML
++            out << YAML::Newline;
++#endif
++            
++            // Displays
++            out << YAML::Newline;
++            out << YAML::Key << "displays";
++            out << YAML::Value << YAML::BeginMap;
++            for(unsigned i = 0; i < c->getNumDisplays(); ++i)
++            {
++                const char* display = c->getDisplay(i);
++                out << YAML::Key << display;
++                out << YAML::Value << YAML::BeginSeq;
++                for(unsigned v = 0; v < c->getNumViews(display); ++v)
++                {
++                    View dview;
++                    dview.name = c->getView(display, v);
++                    dview.colorspace = c->getDisplayColorSpaceName(display, dview.name.c_str());
++                    if(c->getDisplayLooks(display, dview.name.c_str()) != NULL)
++                        dview.looks = c->getDisplayLooks(display, dview.name.c_str());
++                    save(out, dview);
++                
++                }
++                out << YAML::EndSeq;
++            }
++            out << YAML::EndMap;
++            
++#ifndef OLDYAML
++            out << YAML::Newline;
++#endif
++            out << YAML::Newline;
++            out << YAML::Key << "active_displays";
++            std::vector<std::string> active_displays;
++            if(c->getActiveDisplays() != NULL && strlen(c->getActiveDisplays()) > 0)
++                SplitStringEnvStyle(active_displays, c->getActiveDisplays());
++            out << YAML::Value << YAML::Flow << active_displays;
++            out << YAML::Key << "active_views";
++            std::vector<std::string> active_views;
++            if(c->getActiveViews() != NULL && strlen(c->getActiveViews()) > 0)
++                SplitStringEnvStyle(active_views, c->getActiveViews());
++            out << YAML::Value << YAML::Flow << active_views;
++#ifndef OLDYAML
++            out << YAML::Newline;
++#endif
++            
++            // Looks
++            if(c->getNumLooks() > 0)
++            {
++                out << YAML::Newline;
++                out << YAML::Key << "looks";
++                out << YAML::Value << YAML::BeginSeq;
++                for(unsigned i = 0; i < c->getNumLooks(); ++i)
++                {
++                    const char* name = c->getLookNameByIndex(i);
++                    save(out, c->getLook(name));
++                }
++                out << YAML::EndSeq;
++                out << YAML::Newline;
++            }
++            
++            // ColorSpaces
++            {
++                out << YAML::Newline;
++                out << YAML::Key << "colorspaces";
++                out << YAML::Value << YAML::BeginSeq;
++                for(unsigned i = 0; i < c->getNumColorSpaces(); ++i)
++                {
++                    const char* name = c->getColorSpaceNameByIndex(i);
++                    save(out, c->getColorSpace(name));
++                }
++                out << YAML::EndSeq;
++            }
++            
++            out << YAML::EndMap;
+         }
+         
+-        EmitBaseTransformKeyValues(out, t);
+-        
+-        out << YAML::EndMap;
+-        return out;
+     }
+     
+     ///////////////////////////////////////////////////////////////////////////
+-    //  Enums
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth) {
+-        out << BitDepthToString(depth);
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, BitDepth& depth) {
+-        std::string str;
+-        node.Read<std::string>(str);
+-        depth = BitDepthFromString(str.c_str());
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc) {
+-        out << AllocationToString(alloc);
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, Allocation& alloc) {
+-        std::string str;
+-        node.Read<std::string>(str);
+-        alloc = AllocationFromString(str.c_str());
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir) {
+-        out << ColorSpaceDirectionToString(dir);
+-        return out;
+-    }
+     
+-    void operator >> (const YAML::Node& node, ColorSpaceDirection& dir) {
+-        std::string str;
+-        node.Read<std::string>(str);
+-        dir = ColorSpaceDirectionFromString(str.c_str());
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir) {
+-        out << TransformDirectionToString(dir);
+-        return out;
+-    }
+-    
+-    void operator >> (const YAML::Node& node, TransformDirection& dir) {
+-        std::string str;
+-        node.Read<std::string>(str);
+-        dir = TransformDirectionFromString(str.c_str());
+-    }
+-    
+-    YAML::Emitter& operator << (YAML::Emitter& out, Interpolation interp) {
+-        out << InterpolationToString(interp);
+-        return out;
++    void OCIOYaml::open(std::istream& istream, ConfigRcPtr& c, const char* filename) const
++    {
++        try
++        {
++#ifdef OLDYAML
++            YAML::Parser parser(istream);
++            YAML::Node node;
++            parser.GetNextDocument(node);
++#else
++            YAML::Node node = YAML::Load(istream);
++#endif
++            load(node, c, filename);
++        }
++        catch(const std::exception & e)
++        {
++            std::ostringstream os;
++            os << "Error: Loading the OCIO profile ";
++            if(filename) os << "'" << filename << "' ";
++            os << "failed. " << e.what();
++            throw Exception(os.str().c_str());
++        }
+     }
+     
+-    void operator >> (const YAML::Node& node, Interpolation& interp) {
+-        std::string str;
+-        node.Read<std::string>(str);
+-        interp = InterpolationFromString(str.c_str());
++    void OCIOYaml::write(std::ostream& ostream, const Config* c) const
++    {
++        YAML::Emitter out;
++        save(out, c);
++        ostream << out.c_str();
+     }
+     
+ }
+diff --git a/src/core/OCIOYaml.h b/src/core/OCIOYaml.h
+index 7104123..364a262 100644
+--- a/src/core/OCIOYaml.h
++++ b/src/core/OCIOYaml.h
+@@ -28,97 +28,19 @@
+ 
+ #include <OpenColorIO/OpenColorIO.h>
+ 
+-#include "Platform.h"
+-
+-#ifndef WINDOWS
+-
+-// fwd declare yaml-cpp visibility
+-#pragma GCC visibility push(hidden)
+-namespace YAML {
+-    class Exception;
+-    class BadDereference;
+-    class RepresentationException;
+-    class EmitterException;
+-    class ParserException;
+-    class InvalidScalar;
+-    class KeyNotFound;
+-    template <typename T> class TypedKeyNotFound;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
+-    
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
+-    template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
+-}
+-#pragma GCC visibility pop
+-
+-#endif 
+-
+-#include <yaml-cpp/yaml.h>
+-
+ #ifndef INCLUDED_OCIO_YAML_H
+ #define INCLUDED_OCIO_YAML_H
+ 
+ OCIO_NAMESPACE_ENTER
+ {
+     
+-    // Core
+-    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs);
+-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs);
+-    OCIOHIDDEN void operator >> (const YAML::Node& node, GroupTransformRcPtr& t);
+-    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t);
+-    OCIOHIDDEN void operator >> (const YAML::Node& node, TransformRcPtr& t);
<Skipped 48 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/OpenColorIO.git/commitdiff/15f9dc5e915d9b48be609f99bc06a79b33724da4



More information about the pld-cvs-commit mailing list