Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 471366 | Differences between
and this patch

Collapse All | Expand All

(-)a/CMakeLists.txt (-2 / +4 lines)
Lines 225-237 else(USE_EXTERNAL_YAML) Link Here
225
    endif()
225
    endif()
226
endif(USE_EXTERNAL_YAML)
226
endif(USE_EXTERNAL_YAML)
227
227
228
228
if(YAML_CPP_VERSION VERSION_LESS "0.5.0")
229
    set(YAML_CPP_COMPILE_FLAGS "-DOLDYAML")
230
endif()
229
231
230
###############################################################################
232
###############################################################################
231
### Externals ###
233
### Externals ###
232
234
233
set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/ext/dist/include)
235
set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/ext/dist/include)
234
set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL")
236
set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL ${YAML_CPP_COMPILE_FLAGS}")
235
237
236
if(CMAKE_COMPILER_IS_GNUCXX)
238
if(CMAKE_COMPILER_IS_GNUCXX)
237
    
239
    
(-)a/export/OpenColorIO/OpenColorIO.h (+6 lines)
Lines 279-284 OCIO_NAMESPACE_ENTER Link Here
279
        const char * getEnvironmentVarDefault(const char * name) const;
279
        const char * getEnvironmentVarDefault(const char * name) const;
280
        //!cpp:function::
280
        //!cpp:function::
281
        void clearEnvironmentVars();
281
        void clearEnvironmentVars();
282
        //!cpp:function::
283
        void setEnvironmentMode(EnvironmentMode mode);
284
        //!cpp:function::
285
        EnvironmentMode getEnvironmentMode() const;
286
        //!cpp:function::
287
        void loadEnvironment();
282
        
288
        
283
        //!cpp:function::
289
        //!cpp:function::
284
        const char * getSearchPath() const;
290
        const char * getSearchPath() const;
(-)a/src/core/Config.cpp (-485 / +33 lines)
Lines 40-45 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Link Here
40
#include "HashUtils.h"
40
#include "HashUtils.h"
41
#include "Logging.h"
41
#include "Logging.h"
42
#include "LookParse.h"
42
#include "LookParse.h"
43
#include "Display.h"
43
#include "MathUtils.h"
44
#include "MathUtils.h"
44
#include "Mutex.h"
45
#include "Mutex.h"
45
#include "OpBuilders.h"
46
#include "OpBuilders.h"
Lines 208-214 OCIO_NAMESPACE_ENTER Link Here
208
        if(csname.empty()) return false;
209
        if(csname.empty()) return false;
209
        
210
        
210
        std::string csnamelower = pystring::lower(csname);
211
        std::string csnamelower = pystring::lower(csname);
211
        
212
        for(unsigned int i = 0; i < colorspaces.size(); ++i)
212
        for(unsigned int i = 0; i < colorspaces.size(); ++i)
213
        {
213
        {
214
            if(csnamelower == pystring::lower(colorspaces[i]->getName()))
214
            if(csnamelower == pystring::lower(colorspaces[i]->getName()))
Lines 220-403 OCIO_NAMESPACE_ENTER Link Here
220
        
220
        
221
        return false;
221
        return false;
222
    }
222
    }
223
    
224
    
225
    // Displays
226
    struct View
227
    {
228
        std::string name;
229
        std::string colorspace;
230
        std::string looks;
231
        
232
        View() { }
233
        
234
        View(const std::string & name_,
235
             const std::string & colorspace_,
236
             const std::string & looksList_) :
237
                name(name_),
238
                colorspace(colorspace_),
239
                looks(looksList_)
240
        { }
241
    };
242
    
243
    typedef std::vector<View> ViewVec;
244
    typedef std::map<std::string, ViewVec> DisplayMap;  // (display name : ViewVec)
245
    
246
    void operator >> (const YAML::Node& node, View& v)
247
    {
248
        if(node.Tag() != "View")
249
            return;
250
        
251
        std::string key, stringval;
252
        
253
        for (YAML::Iterator iter = node.begin();
254
             iter != node.end();
255
             ++iter)
256
        {
257
            iter.first() >> key;
258
            
259
            if(key == "name")
260
            {
261
                if (iter.second().Type() != YAML::NodeType::Null && 
262
                    iter.second().Read<std::string>(stringval))
263
                    v.name = stringval;
264
            }
265
            else if(key == "colorspace")
266
            {
267
                if (iter.second().Type() != YAML::NodeType::Null && 
268
                    iter.second().Read<std::string>(stringval))
269
                    v.colorspace = stringval;
270
            }
271
            else if(key == "looks" || key == "look")
272
            {
273
                if (iter.second().Type() != YAML::NodeType::Null && 
274
                    iter.second().Read<std::string>(stringval))
275
                    v.looks = stringval;
276
            }
277
            else
278
            {
279
                LogUnknownKeyWarning(node.Tag(), iter.first());
280
            }
281
        }
282
        
283
        if(v.name.empty())
284
        {
285
            throw Exception("View does not specify 'name'.");
286
        }
287
        if(v.colorspace.empty())
288
        {
289
            std::ostringstream os;
290
            os << "View '" << v.name << "' ";
291
            os << "does not specify colorspace.";
292
            throw Exception(os.str().c_str());
293
        }
294
    }
295
    
296
    YAML::Emitter& operator << (YAML::Emitter& out, View view)
297
    {
298
        out << YAML::VerbatimTag("View");
299
        out << YAML::Flow;
300
        out << YAML::BeginMap;
301
        out << YAML::Key << "name" << YAML::Value << view.name;
302
        out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
303
        if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
304
        out << YAML::EndMap;
305
        return out;
306
    }
307
    
308
    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
309
    {
310
        for(DisplayMap::iterator iter = displays.begin();
311
            iter != displays.end();
312
            ++iter)
313
        {
314
            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
315
        }
316
        return displays.end();
317
    }
318
    
319
    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
320
    {
321
        for(DisplayMap::const_iterator iter = displays.begin();
322
            iter != displays.end();
323
            ++iter)
324
        {
325
            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
326
        }
327
        return displays.end();
328
    }
329
    
330
    int find_view(const ViewVec & vec, const std::string & name)
331
    {
332
        for(unsigned int i=0; i<vec.size(); ++i)
333
        {
334
            if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
335
        }
336
        return -1;
337
    }
338
    
339
    void AddDisplay(DisplayMap & displays,
340
                    const std::string & display,
341
                    const std::string & view,
342
                    const std::string & colorspace,
343
                    const std::string & looks)
344
    {
345
        DisplayMap::iterator iter = find_display(displays, display);
346
        if(iter == displays.end())
347
        {
348
            ViewVec views;
349
            views.push_back( View(view, colorspace, looks) );
350
            displays[display] = views;
351
        }
352
        else
353
        {
354
            ViewVec & views = iter->second;
355
            int index = find_view(views, view);
356
            if(index<0)
357
            {
358
                views.push_back( View(view, colorspace, looks) );
359
            }
360
            else
361
            {
362
                views[index].colorspace = colorspace;
363
                views[index].looks = looks;
364
            }
365
        }
366
    }
367
    
368
    void ComputeDisplays(StringVec & displayCache,
369
                         const DisplayMap & displays,
370
                         const StringVec & activeDisplays,
371
                         const StringVec & activeDisplaysEnvOverride)
372
    {
373
        displayCache.clear();
374
        
223
        
375
        StringVec displayMasterList;
376
        for(DisplayMap::const_iterator iter = displays.begin();
377
            iter != displays.end();
378
            ++iter)
379
        {
380
            displayMasterList.push_back(iter->first);
381
        }
382
        
383
        // Apply the env override if it's not empty.
384
        if(!activeDisplaysEnvOverride.empty())
385
        {
386
            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
387
            if(!displayCache.empty()) return;
388
        }
389
        // Otherwise, aApply the active displays if it's not empty.
390
        else if(!activeDisplays.empty())
391
        {
392
            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
393
            if(!displayCache.empty()) return;
394
        }
395
        
396
        displayCache = displayMasterList;
397
    }
398
    
399
    
400
    
401
    } // namespace
224
    } // namespace
402
    
225
    
403
    class Config::Impl
226
    class Config::Impl
Lines 431-436 OCIO_NAMESPACE_ENTER Link Here
431
        mutable StringMap cacheids_;
254
        mutable StringMap cacheids_;
432
        mutable std::string cacheidnocontext_;
255
        mutable std::string cacheidnocontext_;
433
        
256
        
257
        OCIOYaml io_;
258
        
434
        Impl() : 
259
        Impl() : 
435
            context_(Context::Create()),
260
            context_(Context::Create()),
436
            strictParsing_(true),
261
            strictParsing_(true),
Lines 497-504 OCIO_NAMESPACE_ENTER Link Here
497
            return *this;
322
            return *this;
498
        }
323
        }
499
        
324
        
500
        void load(std::istream & istream, const char * name);
501
        
502
        // Any time you modify the state of the config, you must call this
325
        // Any time you modify the state of the config, you must call this
503
        // to reset internal cache states.  You also should do this in a
326
        // to reset internal cache states.  You also should do this in a
504
        // thread safe manner by acquiring the cacheidMutex_;
327
        // thread safe manner by acquiring the cacheidMutex_;
Lines 536-542 OCIO_NAMESPACE_ENTER Link Here
536
        istream.str(INTERNAL_RAW_PROFILE);
359
        istream.str(INTERNAL_RAW_PROFILE);
537
        
360
        
538
        ConfigRcPtr config = Config::Create();
361
        ConfigRcPtr config = Config::Create();
539
        config->getImpl()->load(istream, "");
362
        config->getImpl()->io_.open(istream, config);
540
        return config;
363
        return config;
541
    }
364
    }
542
    
365
    
Lines 551-564 OCIO_NAMESPACE_ENTER Link Here
551
        }
374
        }
552
        
375
        
553
        ConfigRcPtr config = Config::Create();
376
        ConfigRcPtr config = Config::Create();
554
        config->getImpl()->load(istream, filename);
377
        config->getImpl()->io_.open(istream, config, filename);
555
        return config;
378
        return config;
556
    }
379
    }
557
    
380
    
558
    ConstConfigRcPtr Config::CreateFromStream(std::istream & istream)
381
    ConstConfigRcPtr Config::CreateFromStream(std::istream & istream)
559
    {
382
    {
560
        ConfigRcPtr config = Config::Create();
383
        ConfigRcPtr config = Config::Create();
561
        config->getImpl()->load(istream, "");
384
        config->getImpl()->io_.open(istream, config);
562
        return config;
385
        return config;
563
    }
386
    }
564
    
387
    
Lines 893-898 OCIO_NAMESPACE_ENTER Link Here
893
        getImpl()->resetCacheIDs();
716
        getImpl()->resetCacheIDs();
894
    }
717
    }
895
    
718
    
719
    void Config::setEnvironmentMode(EnvironmentMode mode)
720
    {
721
        getImpl()->context_->setEnvironmentMode(mode);
722
        
723
        AutoMutex lock(getImpl()->cacheidMutex_);
724
        getImpl()->resetCacheIDs();
725
    }
726
    
727
    EnvironmentMode Config::getEnvironmentMode() const
728
    {
729
        return getImpl()->context_->getEnvironmentMode();
730
    }
731
    
732
    void Config::loadEnvironment()
733
    {
734
        getImpl()->context_->loadEnvironment();
735
        
736
        AutoMutex lock(getImpl()->cacheidMutex_);
737
        getImpl()->resetCacheIDs();
738
    }
739
    
896
    const char * Config::getSearchPath() const
740
    const char * Config::getSearchPath() const
897
    {
741
    {
898
        return getImpl()->context_->getSearchPath();
742
        return getImpl()->context_->getSearchPath();
Lines 1647-1706 OCIO_NAMESPACE_ENTER Link Here
1647
    {
1491
    {
1648
        try
1492
        try
1649
        {
1493
        {
1650
            YAML::Emitter out;
1494
            getImpl()->io_.write(os, this);
1651
            out << YAML::Block;
1652
            out << YAML::BeginMap;
1653
            out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
1654
            out << YAML::Newline;
1655
            if(getImpl()->env_.size() > 0) {
1656
                out << YAML::Key << "environment";
1657
                out << YAML::Value << getImpl()->env_;
1658
                out << YAML::Newline;
1659
            }
1660
            out << YAML::Key << "search_path" << YAML::Value << getImpl()->context_->getSearchPath();
1661
            out << YAML::Key << "strictparsing" << YAML::Value << getImpl()->strictParsing_;
1662
            out << YAML::Key << "luma" << YAML::Value << YAML::Flow << getImpl()->defaultLumaCoefs_;
1663
            
1664
            if(getImpl()->description_ != "")
1665
            {
1666
                out << YAML::Newline;
1667
                out << YAML::Key << "description";
1668
                out << YAML::Value << getImpl()->description_;
1669
            }
1670
            
1671
            // Roles
1672
            out << YAML::Newline;
1673
            out << YAML::Key << "roles";
1674
            out << YAML::Value << getImpl()->roles_;
1675
            
1676
            // Displays
1677
            out << YAML::Newline;
1678
            out << YAML::Key << "displays";
1679
            out << YAML::Value << getImpl()->displays_;
1680
            out << YAML::Newline;
1681
            out << YAML::Key << "active_displays";
1682
            out << YAML::Value << YAML::Flow << getImpl()->activeDisplays_;
1683
            out << YAML::Key << "active_views";
1684
            out << YAML::Value << YAML::Flow << getImpl()->activeViews_;
1685
            
1686
            // Looks
1687
            if(!getImpl()->looksList_.empty())
1688
            {
1689
                out << YAML::Newline;
1690
                out << YAML::Key << "looks";
1691
                out << YAML::Value << getImpl()->looksList_;
1692
            }
1693
            
1694
            // ColorSpaces
1695
            {
1696
                out << YAML::Newline;
1697
                out << YAML::Key << "colorspaces";
1698
                out << YAML::Value << getImpl()->colorspaces_;
1699
            }
1700
            
1701
            out << YAML::EndMap;
1702
            
1703
            os << out.c_str();
1704
        }
1495
        }
1705
        catch( const std::exception & e)
1496
        catch( const std::exception & e)
1706
        {
1497
        {
Lines 1710-1955 OCIO_NAMESPACE_ENTER Link Here
1710
        }
1501
        }
1711
    }
1502
    }
1712
    
1503
    
1713
    void Config::Impl::load(std::istream & istream, const char * filename)
1714
    {
1715
        try
1716
        {
1717
            YAML::Parser parser(istream);
1718
            YAML::Node node;
1719
            parser.GetNextDocument(node);
1720
            
1721
            // check profile version
1722
            int profile_version = 0;
1723
            if(node.FindValue("ocio_profile_version") == NULL)
1724
            {
1725
                std::ostringstream os;
1726
                os << "The specified file ";
1727
                os << "does not appear to be an OCIO configuration.";
1728
                throw Exception (os.str().c_str());
1729
            }
1730
            
1731
            node["ocio_profile_version"] >> profile_version;
1732
            if(profile_version > 1)
1733
            {
1734
                std::ostringstream os;
1735
                os << "This .ocio config ";
1736
                if(filename && *filename)
1737
                {
1738
                    os << " '" << filename << "' ";
1739
                }
1740
                os << "is version " << profile_version << ". ";
1741
                os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
1742
                os << "is not known to be able to load this profile. ";
1743
                os << "An attempt will be made, but there are no guarantees that the ";
1744
                os << "results will be accurate. Continue at your own risk.";
1745
                LogWarning(os.str());
1746
            }
1747
            
1748
            
1749
            std::string key, stringval;
1750
            bool boolval = false;
1751
            EnvironmentMode mode = ENV_ENVIRONMENT_LOAD_ALL;
1752
            
1753
            for (YAML::Iterator iter = node.begin();
1754
                 iter != node.end();
1755
                 ++iter)
1756
            {
1757
                iter.first() >> key;
1758
                
1759
                if(key == "ocio_profile_version") { } // Already handled above.
1760
                else if(key == "environment")
1761
                {
1762
                    mode = ENV_ENVIRONMENT_LOAD_PREDEFINED;
1763
                    const YAML::Node& environment = iter.second();
1764
                    if(environment.Type() != YAML::NodeType::Map)
1765
                    {
1766
                        std::ostringstream os;
1767
                        os << "'environment' field needs to be a (name: key) map.";
1768
                        throw Exception(os.str().c_str());
1769
                    }
1770
                    for (YAML::Iterator it  = environment.begin();
1771
                                        it != environment.end(); ++it)
1772
                    {
1773
                        std::string k, v;
1774
                        it.first() >> k;
1775
                        it.second() >> v;
1776
                        env_[k] = v;
1777
                        context_->setStringVar(k.c_str(), v.c_str());
1778
                    }
1779
                }
1780
                else if(key == "search_path" || key == "resource_path")
1781
                {
1782
                    if (iter.second().Type() != YAML::NodeType::Null && 
1783
                        iter.second().Read<std::string>(stringval))
1784
                        context_->setSearchPath(stringval.c_str());
1785
                }
1786
                else if(key == "strictparsing")
1787
                {
1788
                    if (iter.second().Type() != YAML::NodeType::Null && 
1789
                        iter.second().Read<bool>(boolval))
1790
                        strictParsing_ = boolval;
1791
                }
1792
                else if(key == "description")
1793
                {
1794
                    if (iter.second().Type() != YAML::NodeType::Null && 
1795
                        iter.second().Read<std::string>(stringval))
1796
                        description_ = stringval;
1797
                }
1798
                else if(key == "luma")
1799
                {
1800
                    std::vector<float> val;
1801
                    if (iter.second().Type() != YAML::NodeType::Null)
1802
                    {
1803
                        iter.second() >> val;
1804
                        if(val.size() != 3)
1805
                        {
1806
                            std::ostringstream os;
1807
                            os << "'luma' field must be 3 ";
1808
                            os << "floats. Found '" << val.size() << "'.";
1809
                            throw Exception(os.str().c_str());
1810
                        }
1811
                        defaultLumaCoefs_ = val;
1812
                    }
1813
                }
1814
                else if(key == "roles")
1815
                {
1816
                    const YAML::Node& roles = iter.second();
1817
                    if(roles.Type() != YAML::NodeType::Map)
1818
                    {
1819
                        std::ostringstream os;
1820
                        os << "'roles' field needs to be a (name: key) map.";
1821
                        throw Exception(os.str().c_str());
1822
                    }
1823
                    for (YAML::Iterator it  = roles.begin();
1824
                                        it != roles.end(); ++it)
1825
                    {
1826
                        std::string k, v;
1827
                        it.first() >> k;
1828
                        it.second() >> v;
1829
                        roles_[pystring::lower(k)] = v;
1830
                    }
1831
                }
1832
                else if(key == "displays")
1833
                {
1834
                    if (iter.second().Type() != YAML::NodeType::Null)
1835
                    {
1836
                        iter.second() >> displays_;
1837
                    }
1838
                }
1839
                else if(key == "active_displays")
1840
                {
1841
                    if (iter.second().Type() != YAML::NodeType::Null)
1842
                    {
1843
                        iter.second() >> activeDisplays_;
1844
                    }
1845
                }
1846
                else if(key == "active_views")
1847
                {
1848
                    if (iter.second().Type() != YAML::NodeType::Null)
1849
                    {
1850
                        iter.second() >> activeViews_;
1851
                    }
1852
                }
1853
                else if(key == "colorspaces")
1854
                {
1855
                    const YAML::Node& colorspaces = iter.second();
1856
                    
1857
                    if(colorspaces.Type() != YAML::NodeType::Sequence)
1858
                    {
1859
                        std::ostringstream os;
1860
                        os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
1861
                        throw Exception(os.str().c_str());
1862
                    }
1863
                    
1864
                    for(unsigned i = 0; i < colorspaces.size(); ++i)
1865
                    {
1866
                        if(colorspaces[i].Tag() == "ColorSpace")
1867
                        {
1868
                            ColorSpaceRcPtr cs = ColorSpace::Create();
1869
                            colorspaces[i] >> cs;
1870
                            colorspaces_.push_back( cs );
1871
                        }
1872
                        else
1873
                        {
1874
                            std::ostringstream os;
1875
                            os << "Unknown element found in colorspaces:";
1876
                            os << colorspaces[i].Tag() << ". Only ColorSpace(s)";
1877
                            os << " currently handled.";
1878
                            LogWarning(os.str());
1879
                        }
1880
                    }
1881
                }
1882
                else if(key == "looks")
1883
                {
1884
                    const YAML::Node& looks = iter.second();
1885
                    
1886
                    if(looks.Type() != YAML::NodeType::Sequence)
1887
                    {
1888
                        std::ostringstream os;
1889
                        os << "'looks' field needs to be a (- !<Look>) list.";
1890
                        throw Exception(os.str().c_str());
1891
                    }
1892
                    
1893
                    for(unsigned i = 0; i < looks.size(); ++i)
1894
                    {
1895
                        if(looks[i].Tag() == "Look")
1896
                        {
1897
                            LookRcPtr look = Look::Create();
1898
                            looks[i] >> look;
1899
                            looksList_.push_back( look );
1900
                        }
1901
                        else
1902
                        {
1903
                            std::ostringstream os;
1904
                            os << "Unknown element found in looks:";
1905
                            os << looks[i].Tag() << ". Only Look(s)";
1906
                            os << " currently handled.";
1907
                            LogWarning(os.str());
1908
                        }
1909
                    }
1910
                }
1911
                else
1912
                {
1913
                    LogUnknownKeyWarning("profile", iter.first());
1914
                }
1915
            }
1916
            
1917
            if(filename)
1918
            {
1919
                std::string realfilename = pystring::os::path::abspath(filename);
1920
                std::string configrootdir = pystring::os::path::dirname(realfilename);
1921
                context_->setWorkingDir(configrootdir.c_str());
1922
            }
1923
            
1924
            context_->setEnvironmentMode(mode);
1925
            context_->loadEnvironment();
1926
            
1927
            if(mode == ENV_ENVIRONMENT_LOAD_ALL)
1928
            {
1929
                std::ostringstream os;
1930
                os << "This .ocio config ";
1931
                if(filename && *filename)
1932
                {
1933
                    os << " '" << filename << "' ";
1934
                }
1935
                os << "has no environment section defined. The default behaviour is to ";
1936
                os << "load all environment variables (" << context_->getNumStringVars() << ")";
1937
                os << ", which reduces the efficiency of OCIO's caching. Considering ";
1938
                os << "predefining the environment variables used.";
1939
                LogDebug(os.str());
1940
            }
1941
            
1942
        }
1943
        catch( const std::exception & e)
1944
        {
1945
            std::ostringstream os;
1946
            os << "Error: Loading the OCIO profile ";
1947
            if(filename) os << "'" << filename << "' ";
1948
            os << "failed. " << e.what();
1949
            throw Exception(os.str().c_str());
1950
        }
1951
    }
1952
    
1953
    void Config::Impl::resetCacheIDs()
1504
    void Config::Impl::resetCacheIDs()
1954
    {
1505
    {
1955
        cacheids_.clear();
1506
        cacheids_.clear();
Lines 2287-2295 OIIO_ADD_TEST(Config, SanityCheck) Link Here
2287
    std::istringstream is;
1838
    std::istringstream is;
2288
    is.str(SIMPLE_PROFILE);
1839
    is.str(SIMPLE_PROFILE);
2289
    OCIO::ConstConfigRcPtr config;
1840
    OCIO::ConstConfigRcPtr config;
2290
    OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
1841
    OIIO_CHECK_THOW(config = OCIO::Config::CreateFromStream(is), OCIO::Exception);
2291
    
2292
    OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
2293
    }
1842
    }
2294
    
1843
    
2295
    {
1844
    {
Lines 2330-2337 OIIO_ADD_TEST(Config, EnvCheck) Link Here
2330
    "colorspaces:\n"
1879
    "colorspaces:\n"
2331
    "  - !<ColorSpace>\n"
1880
    "  - !<ColorSpace>\n"
2332
    "      name: raw\n"
1881
    "      name: raw\n"
2333
    "  - !<ColorSpace>\n"
2334
    "      name: raw\n"
2335
    "strictparsing: false\n"
1882
    "strictparsing: false\n"
2336
    "roles:\n"
1883
    "roles:\n"
2337
    "  default: raw\n"
1884
    "  default: raw\n"
Lines 2345-2352 OIIO_ADD_TEST(Config, EnvCheck) Link Here
2345
    "colorspaces:\n"
1892
    "colorspaces:\n"
2346
    "  - !<ColorSpace>\n"
1893
    "  - !<ColorSpace>\n"
2347
    "      name: raw\n"
1894
    "      name: raw\n"
2348
    "  - !<ColorSpace>\n"
2349
    "      name: raw\n"
2350
    "strictparsing: false\n"
1895
    "strictparsing: false\n"
2351
    "roles:\n"
1896
    "roles:\n"
2352
    "  default: raw\n"
1897
    "  default: raw\n"
Lines 2370-2376 OIIO_ADD_TEST(Config, EnvCheck) Link Here
2370
        "testbarchedder") == 0);
1915
        "testbarchedder") == 0);
2371
    OIIO_CHECK_ASSERT(strcmp(config->getCurrentContext()->resolveStringVar("${SHOW}"),
1916
    OIIO_CHECK_ASSERT(strcmp(config->getCurrentContext()->resolveStringVar("${SHOW}"),
2372
        "bar") == 0);
1917
        "bar") == 0);
2373
    OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
2374
    OIIO_CHECK_ASSERT(strcmp(config->getEnvironmentVarDefault("SHOW"), "super") == 0);
1918
    OIIO_CHECK_ASSERT(strcmp(config->getEnvironmentVarDefault("SHOW"), "super") == 0);
2375
    
1919
    
2376
    OCIO::ConfigRcPtr edit = config->createEditableCopy();
1920
    OCIO::ConfigRcPtr edit = config->createEditableCopy();
Lines 2403-2408 OIIO_ADD_TEST(Config, EnvCheck) Link Here
2403
        "lighting") == 0);
1947
        "lighting") == 0);
2404
    OCIO::SetLoggingLevel(loglevel);
1948
    OCIO::SetLoggingLevel(loglevel);
2405
    
1949
    
1950
    OIIO_CHECK_EQUAL(edit->getEnvironmentMode(), OCIO::ENV_ENVIRONMENT_LOAD_PREDEFINED);
1951
    edit->setEnvironmentMode(OCIO::ENV_ENVIRONMENT_LOAD_ALL);
1952
    OIIO_CHECK_EQUAL(edit->getEnvironmentMode(), OCIO::ENV_ENVIRONMENT_LOAD_ALL);
1953
    
2406
    }
1954
    }
2407
}
1955
}
2408
1956
(-)a/src/core/Display.cpp (+145 lines)
Line 0 Link Here
1
/*
2
Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
3
All Rights Reserved.
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are
7
met:
8
* Redistributions of source code must retain the above copyright
9
  notice, this list of conditions and the following disclaimer.
10
* Redistributions in binary form must reproduce the above copyright
11
  notice, this list of conditions and the following disclaimer in the
12
  documentation and/or other materials provided with the distribution.
13
* Neither the name of Sony Pictures Imageworks nor the names of its
14
  contributors may be used to endorse or promote products derived from
15
  this software without specific prior written permission.
16
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
#include <string>
30
31
#include <OpenColorIO/OpenColorIO.h>
32
33
#include "Display.h"
34
#include "ParseUtils.h"
35
36
OCIO_NAMESPACE_ENTER
37
{
38
    
39
    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
40
    {
41
        for(DisplayMap::iterator iter = displays.begin();
42
            iter != displays.end();
43
            ++iter)
44
        {
45
            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
46
        }
47
        return displays.end();
48
    }
49
    
50
    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
51
    {
52
        for(DisplayMap::const_iterator iter = displays.begin();
53
            iter != displays.end();
54
            ++iter)
55
        {
56
            if(StrEqualsCaseIgnore(display, iter->first)) return iter;
57
        }
58
        return displays.end();
59
    }
60
    
61
    int find_view(const ViewVec & vec, const std::string & name)
62
    {
63
        for(unsigned int i=0; i<vec.size(); ++i)
64
        {
65
            if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
66
        }
67
        return -1;
68
    }
69
    
70
    void AddDisplay(DisplayMap & displays,
71
                    const std::string & display,
72
                    const std::string & view,
73
                    const std::string & colorspace,
74
                    const std::string & looks)
75
    {
76
        DisplayMap::iterator iter = find_display(displays, display);
77
        if(iter == displays.end())
78
        {
79
            ViewVec views;
80
            views.push_back( View(view, colorspace, looks) );
81
            displays[display] = views;
82
        }
83
        else
84
        {
85
            ViewVec & views = iter->second;
86
            int index = find_view(views, view);
87
            if(index<0)
88
            {
89
                views.push_back( View(view, colorspace, looks) );
90
            }
91
            else
92
            {
93
                views[index].colorspace = colorspace;
94
                views[index].looks = looks;
95
            }
96
        }
97
    }
98
    
99
    void ComputeDisplays(StringVec & displayCache,
100
                         const DisplayMap & displays,
101
                         const StringVec & activeDisplays,
102
                         const StringVec & activeDisplaysEnvOverride)
103
    {
104
        displayCache.clear();
105
        
106
        StringVec displayMasterList;
107
        for(DisplayMap::const_iterator iter = displays.begin();
108
            iter != displays.end();
109
            ++iter)
110
        {
111
            displayMasterList.push_back(iter->first);
112
        }
113
        
114
        // Apply the env override if it's not empty.
115
        if(!activeDisplaysEnvOverride.empty())
116
        {
117
            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
118
            if(!displayCache.empty()) return;
119
        }
120
        // Otherwise, aApply the active displays if it's not empty.
121
        else if(!activeDisplays.empty())
122
        {
123
            displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
124
            if(!displayCache.empty()) return;
125
        }
126
        
127
        displayCache = displayMasterList;
128
    }
129
130
}
131
OCIO_NAMESPACE_EXIT
132
133
///////////////////////////////////////////////////////////////////////////////
134
135
#ifdef OCIO_UNIT_TEST
136
137
namespace OCIO = OCIO_NAMESPACE;
138
#include "UnitTest.h"
139
140
OIIO_ADD_TEST(Display, Basic)
141
{
142
    
143
}
144
145
#endif // OCIO_UNIT_TEST
(-)a/src/core/Display.h (+85 lines)
Line 0 Link Here
1
/*
2
Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
3
All Rights Reserved.
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are
7
met:
8
* Redistributions of source code must retain the above copyright
9
  notice, this list of conditions and the following disclaimer.
10
* Redistributions in binary form must reproduce the above copyright
11
  notice, this list of conditions and the following disclaimer in the
12
  documentation and/or other materials provided with the distribution.
13
* Neither the name of Sony Pictures Imageworks nor the names of its
14
  contributors may be used to endorse or promote products derived from
15
  this software without specific prior written permission.
16
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
30
#ifndef INCLUDED_OCIO_DISPLAY_H
31
#define INCLUDED_OCIO_DISPLAY_H
32
33
#include <OpenColorIO/OpenColorIO.h>
34
35
#include <string>
36
#include <vector>
37
#include <map>
38
39
#include "PrivateTypes.h"
40
41
OCIO_NAMESPACE_ENTER
42
{
43
    
44
    // Displays
45
    struct View
46
    {
47
        std::string name;
48
        std::string colorspace;
49
        std::string looks;
50
        
51
        View() { }
52
        
53
        View(const std::string & name_,
54
             const std::string & colorspace_,
55
             const std::string & looksList_) :
56
                name(name_),
57
                colorspace(colorspace_),
58
                looks(looksList_)
59
        { }
60
    };
61
    
62
    typedef std::vector<View> ViewVec;
63
    typedef std::map<std::string, ViewVec> DisplayMap;  // (display name : ViewVec)
64
    
65
    DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display);
66
    
67
    DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display);
68
    
69
    int find_view(const ViewVec & vec, const std::string & name);
70
    
71
    void AddDisplay(DisplayMap & displays,
72
                    const std::string & display,
73
                    const std::string & view,
74
                    const std::string & colorspace,
75
                    const std::string & looks);
76
    
77
    void ComputeDisplays(StringVec & displayCache,
78
                         const DisplayMap & displays,
79
                         const StringVec & activeDisplays,
80
                         const StringVec & activeDisplaysEnvOverride);
81
    
82
}
83
OCIO_NAMESPACE_EXIT
84
85
#endif
(-)a/src/core/OCIOYaml.cpp (-964 / +1563 lines)
Lines 30-1217 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Link Here
30
30
31
#include <OpenColorIO/OpenColorIO.h>
31
#include <OpenColorIO/OpenColorIO.h>
32
32
33
#ifndef WINDOWS
34
35
// fwd declare yaml-cpp visibility
36
#pragma GCC visibility push(hidden)
37
namespace YAML {
38
    class Exception;
39
    class BadDereference;
40
    class RepresentationException;
41
    class EmitterException;
42
    class ParserException;
43
    class InvalidScalar;
44
    class KeyNotFound;
45
    template <typename T> class TypedKeyNotFound;
46
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
47
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
48
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
49
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
50
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
51
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
52
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
53
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
54
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
55
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
56
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
57
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
58
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
59
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
60
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
61
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
62
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
63
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
64
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
65
}
66
#pragma GCC visibility pop
67
68
#endif
69
70
#include <yaml-cpp/yaml.h>
71
33
#include "Logging.h"
72
#include "Logging.h"
34
#include "MathUtils.h"
73
#include "MathUtils.h"
74
#include "pystring/pystring.h"
75
#include "PathUtils.h"
76
#include "ParseUtils.h"
77
#include "Display.h"
35
#include "OCIOYaml.h"
78
#include "OCIOYaml.h"
36
79
37
OCIO_NAMESPACE_ENTER
80
OCIO_NAMESPACE_ENTER
38
{
81
{
39
    ///////////////////////////////////////////////////////////////////////////
40
    //  Core
41
    
82
    
42
    void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag)
83
    namespace
43
    {
84
    {
44
        std::string key;
45
        tag >> key;
46
        
47
        std::ostringstream os;
48
        os << "Unknown key in " << name << ": ";
49
        os << "'" << key << "'. (line ";
50
        os << (tag.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
51
        os << tag.GetMark().column << ")";
52
        LogWarning(os.str());
53
    }
54
    
85
    
55
    void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs)
86
#ifdef OLDYAML
56
    {
87
        typedef YAML::Iterator Iterator;
57
        if(node.Tag() != "ColorSpace")
88
#else
58
            return; // not a !<ColorSpace> tag
89
        typedef YAML::const_iterator Iterator;
90
#endif
59
        
91
        
60
        std::string key, stringval;
92
        // Iterator access
61
        bool boolval;
62
        
93
        
63
        for (YAML::Iterator iter = node.begin();
94
        inline const YAML::Node& get_first(const Iterator it)
64
             iter != node.end();
65
             ++iter)
66
        {
67
            iter.first() >> key;
68
            
69
            if(key == "name")
70
            {
71
                if (iter.second().Type() != YAML::NodeType::Null && 
72
                    iter.second().Read<std::string>(stringval))
73
                    cs->setName(stringval.c_str());
74
            }
75
            else if(key == "description")
76
            {
77
                if (iter.second().Type() != YAML::NodeType::Null && 
78
                    iter.second().Read<std::string>(stringval))
79
                    cs->setDescription(stringval.c_str());
80
            }
81
            else if(key == "family")
82
            {
83
                if (iter.second().Type() != YAML::NodeType::Null && 
84
                    iter.second().Read<std::string>(stringval))
85
                    cs->setFamily(stringval.c_str());
86
            }
87
            else if(key == "equalitygroup")
88
            {
89
                if (iter.second().Type() != YAML::NodeType::Null && 
90
                    iter.second().Read<std::string>(stringval))
91
                    cs->setEqualityGroup(stringval.c_str());
92
            }
93
            else if(key == "bitdepth")
94
            {
95
                BitDepth ret;
96
                if (iter.second().Type() != YAML::NodeType::Null && 
97
                    iter.second().Read<BitDepth>(ret))
98
                    cs->setBitDepth(ret);
99
            }
100
            else if(key == "isdata")
101
            {
102
                if (iter.second().Type() != YAML::NodeType::Null && 
103
                    iter.second().Read<bool>(boolval))
104
                    cs->setIsData(boolval);
105
            }
106
            else if(key == "allocation")
107
            {
108
                Allocation val;
109
                if (iter.second().Type() != YAML::NodeType::Null && 
110
                    iter.second().Read<Allocation>(val))
111
                    cs->setAllocation(val);
112
            }
113
            else if(key == "allocationvars")
114
            {
115
                std::vector<float> val;
116
                if (iter.second().Type() != YAML::NodeType::Null)
117
                {
118
                    iter.second() >> val;
119
                    if(!val.empty())
120
                    {
121
                        cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
122
                    }
123
                }
124
            }
125
            else if(key == "to_reference")
126
            {
127
                TransformRcPtr val;
128
                if (iter.second().Type() != YAML::NodeType::Null && 
129
                    iter.second().Read<TransformRcPtr>(val))
130
                  cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
131
            }
132
            else if(key == "from_reference")
133
            {
134
                TransformRcPtr val;
135
                if (iter.second().Type() != YAML::NodeType::Null && 
136
                    iter.second().Read<TransformRcPtr>(val))
137
                  cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
138
            }
139
            else
140
            {
141
                LogUnknownKeyWarning(node.Tag(), iter.first());
142
            }
143
        }
144
    }
145
    
146
    YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs)
147
    {
148
        out << YAML::VerbatimTag("ColorSpace");
149
        out << YAML::BeginMap;
150
        
151
        out << YAML::Key << "name" << YAML::Value << cs->getName();
152
        out << YAML::Key << "family" << YAML::Value << cs->getFamily();
153
        out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
154
        out << YAML::Key << "bitdepth" << YAML::Value << cs->getBitDepth();
155
        if(strlen(cs->getDescription()) > 0)
156
        {
95
        {
157
            out << YAML::Key << "description";
96
#ifdef OLDYAML
158
            out << YAML::Value << YAML::Literal << cs->getDescription();
97
            return it.first();
98
#else
99
            return it->first;
100
#endif
159
        }
101
        }
160
        out << YAML::Key << "isdata" << YAML::Value << cs->isData();
161
        
102
        
162
        out << YAML::Key << "allocation" << YAML::Value << cs->getAllocation();
103
        inline const YAML::Node& get_second(const Iterator it)
163
        if(cs->getAllocationNumVars() > 0)
164
        {
104
        {
165
            std::vector<float> allocationvars(cs->getAllocationNumVars());
105
#ifdef OLDYAML
166
            cs->getAllocationVars(&allocationvars[0]);
106
            return it.second();
167
            out << YAML::Key << "allocationvars";
107
#else
168
            out << YAML::Flow << YAML::Value << allocationvars;
108
            return it->second;
109
#endif
169
        }
110
        }
170
        
111
        
171
        ConstTransformRcPtr toref = \
112
        // Basic types
172
            cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
173
        if(toref)
174
            out << YAML::Key << "to_reference" << YAML::Value << toref;
175
        
176
        ConstTransformRcPtr fromref = \
177
            cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
178
        if(fromref)
179
            out << YAML::Key << "from_reference" << YAML::Value << fromref;
180
        
181
        out << YAML::EndMap;
182
        out << YAML::Newline;
183
        
184
        return out;
185
    }
186
    
187
    
188
    ///////////////////////////////////////////////////////////////////////////
189
    
190
    // Look. (not the transform, the top-level class)
191
    
192
    void operator >> (const YAML::Node& node, LookRcPtr& look)
193
    {
194
        if(node.Tag() != "Look")
195
            return;
196
        
197
        std::string key, stringval;
198
        
113
        
199
        for (YAML::Iterator iter = node.begin();
114
        inline void load(const YAML::Node& node, bool& x)
200
             iter != node.end();
201
             ++iter)
202
        {
115
        {
203
            iter.first() >> key;
116
#ifdef OLDYAML
204
            
117
            node.Read<bool>(x);
205
            if(key == "name")
118
#else
206
            {
119
            x = node.as<bool>();
207
                if (iter.second().Type() != YAML::NodeType::Null && 
120
#endif
208
                    iter.second().Read<std::string>(stringval))
209
                    look->setName(stringval.c_str());
210
            }
211
            else if(key == "process_space")
212
            {
213
                if (iter.second().Type() != YAML::NodeType::Null && 
214
                    iter.second().Read<std::string>(stringval))
215
                    look->setProcessSpace(stringval.c_str());
216
            }
217
            else if(key == "transform")
218
            {
219
                TransformRcPtr val;
220
                if (iter.second().Type() != YAML::NodeType::Null && 
221
                    iter.second().Read<TransformRcPtr>(val))
222
                    look->setTransform(val);
223
            }
224
            else if(key == "inverse_transform")
225
            {
226
                TransformRcPtr val;
227
                if (iter.second().Type() != YAML::NodeType::Null && 
228
                    iter.second().Read<TransformRcPtr>(val))
229
                    look->setInverseTransform(val);
230
            }
231
            else
232
            {
233
                LogUnknownKeyWarning(node.Tag(), iter.first());
234
            }
235
        }
121
        }
236
    }
237
    
238
    YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr look)
239
    {
240
        out << YAML::VerbatimTag("Look");
241
        out << YAML::BeginMap;
242
        out << YAML::Key << "name" << YAML::Value << look->getName();
243
        out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
244
        
122
        
245
        if(look->getTransform())
123
        inline void load(const YAML::Node& node, int& x)
246
        {
124
        {
247
            out << YAML::Key << "transform";
125
#ifdef OLDYAML
248
            out << YAML::Value << look->getTransform();
126
            node.Read<int>(x);
127
#else
128
            x = node.as<int>();
129
#endif
249
        }
130
        }
250
        
131
        
251
        if(look->getInverseTransform())
132
        inline void load(const YAML::Node& node, float& x)
252
        {
133
        {
253
            out << YAML::Key << "inverse_transform";
134
#ifdef OLDYAML
254
            out << YAML::Value << look->getInverseTransform();
135
            node.Read<float>(x);
136
#else
137
            x = node.as<float>();
138
#endif
255
        }
139
        }
256
        
140
        
257
        out << YAML::EndMap;
141
        inline void load(const YAML::Node& node, std::string& x)
258
        out << YAML::Newline;
142
        {
143
#ifdef OLDYAML
144
            node.Read<std::string>(x);
145
#else
146
            x = node.as<std::string>();
147
#endif
148
        }
259
        
149
        
260
        return out;
150
        inline void load(const YAML::Node& node, std::vector<std::string>& x)
261
    }
262
    
263
    
264
    
265
    ///////////////////////////////////////////////////////////////////////////
266
    
267
    
268
    namespace
269
    {
270
        void EmitBaseTransformKeyValues(YAML::Emitter & out,
271
                                        const ConstTransformRcPtr & t)
272
        {
151
        {
273
            if(t->getDirection() != TRANSFORM_DIR_FORWARD)
152
#ifdef OLDYAML
274
            {
153
            node >> x;
275
                out << YAML::Key << "direction";
154
#else
276
                out << YAML::Value << YAML::Flow << t->getDirection();
155
            x = node.as<std::vector<std::string> >();
277
            }
156
#endif
278
        }
157
        }
279
    }
158
        
280
    
159
        inline void load(const YAML::Node& node, std::vector<float>& x)
281
    void operator >> (const YAML::Node& node, TransformRcPtr& t)
282
    {
283
        if(node.Type() != YAML::NodeType::Map)
284
        {
160
        {
285
            std::ostringstream os;
161
#ifdef OLDYAML
286
            os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
162
            node >> x;
287
            os << "Only Mapping types supported. (line ";
163
#else
288
            os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
164
            x = node.as<std::vector<float> >();
289
            os << node.GetMark().column << ")";
165
#endif
290
            throw Exception(os.str().c_str());
291
        }
166
        }
292
        
167
        
293
        std::string type = node.Tag();
168
        // Enums
294
        
169
        
295
        if(type == "AllocationTransform") {
170
        inline void load(const YAML::Node& node, BitDepth& depth)
296
            AllocationTransformRcPtr temp;
171
        {
297
            node.Read<AllocationTransformRcPtr>(temp);
172
            std::string str;
298
            t = temp;
173
            load(node, str);
174
            depth = BitDepthFromString(str.c_str());
299
        }
175
        }
300
        else if(type == "CDLTransform") {
176
        
301
            CDLTransformRcPtr temp;
177
        inline void save(YAML::Emitter& out, BitDepth depth)
302
            node.Read<CDLTransformRcPtr>(temp);
178
        {
303
            t = temp;
179
            out << BitDepthToString(depth);
304
        }
180
        }
305
        else if(type == "ColorSpaceTransform")  {
181
        
306
            ColorSpaceTransformRcPtr temp;
182
        inline void load(const YAML::Node& node, Allocation& alloc)
307
            node.Read<ColorSpaceTransformRcPtr>(temp);
183
        {
308
            t = temp;
184
            std::string str;
185
            load(node, str);
186
            alloc = AllocationFromString(str.c_str());
309
        }
187
        }
310
        // TODO: DisplayTransform
188
        
311
        else if(type == "ExponentTransform")  {
189
        inline void save(YAML::Emitter& out, Allocation alloc)
312
            ExponentTransformRcPtr temp;
190
        {
313
            node.Read<ExponentTransformRcPtr>(temp);
191
            out << AllocationToString(alloc);
314
            t = temp;
315
        }
192
        }
316
        else if(type == "FileTransform")  {
193
        
317
            FileTransformRcPtr temp;
194
        inline void load(const YAML::Node& node, ColorSpaceDirection& dir)
318
            node.Read<FileTransformRcPtr>(temp);
195
        {
319
            t = temp;
196
            std::string str;
197
            load(node, str);
198
            dir = ColorSpaceDirectionFromString(str.c_str());
320
        }
199
        }
321
        else if(type == "GroupTransform") {
200
        
322
            GroupTransformRcPtr temp;
201
        inline void save(YAML::Emitter& out, ColorSpaceDirection dir)
323
            node.Read<GroupTransformRcPtr>(temp);
202
        {
324
            t = temp;
203
            out << ColorSpaceDirectionToString(dir);
325
        }
204
        }
326
        else if(type == "LogTransform") {
205
        
327
            LogTransformRcPtr temp;
206
        inline void load(const YAML::Node& node, TransformDirection& dir)
328
            node.Read<LogTransformRcPtr>(temp);
207
        {
329
            t = temp;
208
            std::string str;
209
            load(node, str);
210
            dir = TransformDirectionFromString(str.c_str());
330
        }
211
        }
331
        else if(type == "LookTransform") {
212
        
332
            LookTransformRcPtr temp;
213
        inline void save(YAML::Emitter& out, TransformDirection dir)
333
            node.Read<LookTransformRcPtr>(temp);
214
        {
334
            t = temp;
215
            out << TransformDirectionToString(dir);
335
        }
216
        }
336
        else if(type == "MatrixTransform")  {
217
        
337
            MatrixTransformRcPtr temp;
218
        inline void load(const YAML::Node& node, Interpolation& interp)
338
            node.Read<MatrixTransformRcPtr>(temp);
219
        {
339
            t = temp;
220
            std::string str;
221
            load(node, str);
222
            interp = InterpolationFromString(str.c_str());
340
        }
223
        }
341
        else if(type == "TruelightTransform")  {
224
        
342
            TruelightTransformRcPtr temp;
225
        inline void save(YAML::Emitter& out, Interpolation interp)
343
            node.Read<TruelightTransformRcPtr>(temp);
226
        {
344
            t = temp;
227
            out << InterpolationToString(interp);
345
        }
228
        }
346
        else
229
        
230
        //
231
        
232
        inline void LogUnknownKeyWarning(const std::string & name,
233
                                         const YAML::Node& tag)
347
        {
234
        {
348
            // TODO: add a new empty (better name?) aka passthru Transform()
235
            std::string key;
349
            // which does nothing. This is so upsupported !<tag> types don't
236
            load(tag, key);
350
            // throw an exception. Alternativly this could be caught in the
237
        
351
            // GroupTransformRcPtr >> operator with some type of
352
            // supported_tag() method
353
            
354
            // TODO: consider the forwards-compatibility implication of
355
            // throwing an exception.  Should this be a warning, instead?
356
            
357
            //  t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
358
            std::ostringstream os;
238
            std::ostringstream os;
359
            os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
239
            os << "Unknown key in " << name << ": '" << key << "'.";
360
            os << " (line ";
240
            LogWarning(os.str());
361
            os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
362
            os << node.GetMark().column << ")";
363
            throw Exception(os.str().c_str());
364
        }
241
        }
365
    }
366
    
367
    YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t)
368
    {
369
        if(ConstAllocationTransformRcPtr Allocation_tran = \
370
            DynamicPtrCast<const AllocationTransform>(t))
371
            out << Allocation_tran;
372
        else if(ConstCDLTransformRcPtr CDL_tran = \
373
            DynamicPtrCast<const CDLTransform>(t))
374
            out << CDL_tran;
375
        else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
376
            DynamicPtrCast<const ColorSpaceTransform>(t))
377
            out << ColorSpace_tran;
378
        else if(ConstExponentTransformRcPtr Exponent_tran = \
379
            DynamicPtrCast<const ExponentTransform>(t))
380
            out << Exponent_tran;
381
        else if(ConstFileTransformRcPtr File_tran = \
382
            DynamicPtrCast<const FileTransform>(t))
383
            out << File_tran;
384
        else if(ConstGroupTransformRcPtr Group_tran = \
385
            DynamicPtrCast<const GroupTransform>(t))
386
            out << Group_tran;
387
        else if(ConstLogTransformRcPtr Log_tran = \
388
            DynamicPtrCast<const LogTransform>(t))
389
            out << Log_tran;
390
        else if(ConstLookTransformRcPtr Look_tran = \
391
            DynamicPtrCast<const LookTransform>(t))
392
            out << Look_tran;
393
        else if(ConstMatrixTransformRcPtr Matrix_tran = \
394
            DynamicPtrCast<const MatrixTransform>(t))
395
            out << Matrix_tran;
396
        else if(ConstTruelightTransformRcPtr Truelight_tran = \
397
            DynamicPtrCast<const TruelightTransform>(t))
398
            out << Truelight_tran;
399
        else
400
            throw Exception("Unsupported Transform() type for serialization.");
401
        
402
        return out;
403
    }
404
    
405
    
406
    ///////////////////////////////////////////////////////////////////////////
407
    //  Transforms
408
    
409
    void operator >> (const YAML::Node& node, GroupTransformRcPtr& t)
410
    {
411
        t = GroupTransform::Create();
412
        
242
        
413
        std::string key;
243
        // View
414
        
244
        
415
        for (YAML::Iterator iter = node.begin();
245
        inline void load(const YAML::Node& node, View& v)
416
             iter != node.end();
417
             ++iter)
418
        {
246
        {
419
            iter.first() >> key;
247
            if(node.Tag() != "View")
248
                return;
420
            
249
            
421
            if(key == "children")
250
            std::string key, stringval;
422
            {
251
            
423
                const YAML::Node & children = iter.second();
252
            for (Iterator iter = node.begin();
424
                for(unsigned i = 0; i <children.size(); ++i)
253
                 iter != node.end();
254
                 ++iter)
255
            {
256
                const YAML::Node& first = get_first(iter);
257
                const YAML::Node& second = get_second(iter);
258
                
259
                load(first, key);
260
                
261
                if (second.Type() == YAML::NodeType::Null) continue;
262
                
263
                if(key == "name")
425
                {
264
                {
426
                    TransformRcPtr childTransform;
265
                    load(second, stringval);
427
                    children[i].Read<TransformRcPtr>(childTransform);
266
                    v.name = stringval;
428
                    
267
                }
429
                    // TODO: consider the forwards-compatibility implication of
268
                else if(key == "colorspace")
430
                    // throwing an exception.  Should this be a warning, instead?
269
                {
431
                    if(!childTransform)
270
                    load(second, stringval);
432
                    {
271
                    v.colorspace = stringval;
433
                        throw Exception("Child transform could not be parsed.");
272
                }
434
                    }
273
                else if(key == "looks" || key == "look")
435
                    
274
                {
436
                    t->push_back(childTransform);
275
                    load(second, stringval);
276
                    v.looks = stringval;
277
                }
278
                else
279
                {
280
                    LogUnknownKeyWarning(node.Tag(), first);
437
                }
281
                }
438
            }
282
            }
439
            else if(key == "direction")
283
            
284
            if(v.name.empty())
440
            {
285
            {
441
                TransformDirection val;
286
                throw Exception("View does not specify 'name'.");
442
                if (iter.second().Type() != YAML::NodeType::Null && 
443
                    iter.second().Read<TransformDirection>(val))
444
                  t->setDirection(val);
445
            }
287
            }
446
            else
288
            if(v.colorspace.empty())
447
            {
289
            {
448
                LogUnknownKeyWarning(node.Tag(), iter.first());
290
                std::ostringstream os;
291
                os << "View '" << v.name << "' ";
292
                os << "does not specify colorspace.";
293
                throw Exception(os.str().c_str());
449
            }
294
            }
450
        }
295
        }
451
    }
452
    
453
    YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t)
454
    {
455
        out << YAML::VerbatimTag("GroupTransform");
456
        out << YAML::BeginMap;
457
        EmitBaseTransformKeyValues(out, t);
458
        
459
        out << YAML::Key << "children";
460
        out << YAML::Value;
461
        
296
        
462
        out << YAML::BeginSeq;
297
        inline void save(YAML::Emitter& out, View view)
463
        for(int i = 0; i < t->size(); ++i)
464
        {
298
        {
465
            out << t->getTransform(i);
299
            out << YAML::VerbatimTag("View");
300
            out << YAML::Flow;
301
            out << YAML::BeginMap;
302
            out << YAML::Key << "name" << YAML::Value << view.name;
303
            out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
304
            if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
305
            out << YAML::EndMap;
466
        }
306
        }
467
        out << YAML::EndSeq;
468
        
469
        out << YAML::EndMap;
470
        
471
        return out;
472
    }
473
    
474
    
475
    
476
    void operator >> (const YAML::Node& node, FileTransformRcPtr& t)
477
    {
478
        t = FileTransform::Create();
479
        
307
        
480
        std::string key, stringval;
308
        // Common Transform
481
        
309
        
482
        for (YAML::Iterator iter = node.begin();
310
        inline void EmitBaseTransformKeyValues(YAML::Emitter & out,
483
             iter != node.end();
311
                                               const ConstTransformRcPtr & t)
484
             ++iter)
485
        {
312
        {
486
            iter.first() >> key;
313
            if(t->getDirection() != TRANSFORM_DIR_FORWARD)
487
            
488
            if(key == "src")
489
            {
490
                if (iter.second().Type() != YAML::NodeType::Null && 
491
                    iter.second().Read<std::string>(stringval))
492
                  t->setSrc(stringval.c_str());
493
            }
494
            else if(key == "cccid")
495
            {
496
                if (iter.second().Type() != YAML::NodeType::Null && 
497
                    iter.second().Read<std::string>(stringval))
498
                  t->setCCCId(stringval.c_str());
499
            }
500
            else if(key == "interpolation")
501
            {
502
                Interpolation val;
503
                if (iter.second().Type() != YAML::NodeType::Null && 
504
                    iter.second().Read<Interpolation>(val))
505
                  t->setInterpolation(val);
506
            }
507
            else if(key == "direction")
508
            {
509
                TransformDirection val;
510
                if (iter.second().Type() != YAML::NodeType::Null && 
511
                    iter.second().Read<TransformDirection>(val))
512
                  t->setDirection(val);
513
            }
514
            else
515
            {
314
            {
516
                LogUnknownKeyWarning(node.Tag(), iter.first());
315
                out << YAML::Key << "direction";
316
                out << YAML::Value << YAML::Flow;
317
                save(out, t->getDirection());
517
            }
318
            }
518
        }
319
        }
519
    }
520
    
521
    YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t)
522
    {
523
        out << YAML::VerbatimTag("FileTransform");
524
        out << YAML::Flow << YAML::BeginMap;
525
        out << YAML::Key << "src" << YAML::Value << t->getSrc();
526
        const char * cccid = t->getCCCId();
527
        if(cccid && *cccid)
528
        {
529
            out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
530
        }
531
        out << YAML::Key << "interpolation";
532
        out << YAML::Value << t->getInterpolation();
533
        
534
        EmitBaseTransformKeyValues(out, t);
535
        out << YAML::EndMap;
536
        return out;
537
    }
538
    
539
    void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t)
540
    {
541
        t = ColorSpaceTransform::Create();
542
        
320
        
543
        std::string key, stringval;
321
        // AllocationTransform
544
        
322
        
545
        for (YAML::Iterator iter = node.begin();
323
        inline void load(const YAML::Node& node, AllocationTransformRcPtr& t)
546
             iter != node.end();
547
             ++iter)
548
        {
324
        {
549
            iter.first() >> key;
325
            t = AllocationTransform::Create();
550
            
326
            
551
            if(key == "src")
327
            std::string key;
552
            {
328
            
553
                if (iter.second().Type() != YAML::NodeType::Null && 
329
            for (Iterator iter = node.begin();
554
                    iter.second().Read<std::string>(stringval))
330
                 iter != node.end();
555
                  t->setSrc(stringval.c_str());
331
                 ++iter)
556
            }
332
            {
557
            else if(key == "dst")
333
                const YAML::Node& first = get_first(iter);
558
            {
334
                const YAML::Node& second = get_second(iter);
559
                if (iter.second().Type() != YAML::NodeType::Null && 
335
                
560
                    iter.second().Read<std::string>(stringval))
336
                load(first, key);
561
                  t->setDst(stringval.c_str());
337
                
562
            }
338
                if (second.Type() == YAML::NodeType::Null) continue;
563
            else if(key == "direction")
339
                
564
            {
340
                if(key == "allocation")
565
                TransformDirection val;
341
                {
566
                if (iter.second().Type() != YAML::NodeType::Null && 
342
                    Allocation val;
567
                    iter.second().Read<TransformDirection>(val))
343
                    load(second, val);
568
                  t->setDirection(val);
344
                    t->setAllocation(val);
569
            }
345
                }
570
            else
346
                else if(key == "vars")
571
            {
347
                {
572
                LogUnknownKeyWarning(node.Tag(), iter.first());
348
                    std::vector<float> val;
349
                    load(second, val);
350
                    if(!val.empty())
351
                    {
352
                        t->setVars(static_cast<int>(val.size()), &val[0]);
353
                    }
354
                }
355
                else if(key == "direction")
356
                {
357
                    TransformDirection val;
358
                    load(second, val);
359
                    t->setDirection(val);
360
                }
361
                else
362
                {
363
                    LogUnknownKeyWarning(node.Tag(), first);
364
                }
573
            }
365
            }
574
        }
366
        }
575
    }
576
    
577
    YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
578
    {
579
        out << YAML::VerbatimTag("ColorSpaceTransform");
580
        out << YAML::Flow << YAML::BeginMap;
581
        out << YAML::Key << "src" << YAML::Value << t->getSrc();
582
        out << YAML::Key << "dst" << YAML::Value << t->getDst();
583
        EmitBaseTransformKeyValues(out, t);
584
        out << YAML::EndMap;
585
        return out;
586
    }
587
    
588
    void operator >> (const YAML::Node& node, LookTransformRcPtr& t)
589
    {
590
        t = LookTransform::Create();
591
        
592
        std::string key, stringval;
593
        
367
        
594
        for (YAML::Iterator iter = node.begin();
368
        inline void save(YAML::Emitter& out, ConstAllocationTransformRcPtr t)
595
             iter != node.end();
596
             ++iter)
597
        {
369
        {
598
            iter.first() >> key;
370
            out << YAML::VerbatimTag("AllocationTransform");
371
            out << YAML::Flow << YAML::BeginMap;
599
            
372
            
600
            if(key == "src")
373
            out << YAML::Key << "allocation";
601
            {
374
            out << YAML::Value << YAML::Flow;
602
                if (iter.second().Type() != YAML::NodeType::Null && 
375
            save(out, t->getAllocation());
603
                    iter.second().Read<std::string>(stringval))
376
            
604
                  t->setSrc(stringval.c_str());
377
            if(t->getNumVars() > 0)
605
            }
606
            else if(key == "dst")
607
            {
608
                if (iter.second().Type() != YAML::NodeType::Null && 
609
                    iter.second().Read<std::string>(stringval))
610
                  t->setDst(stringval.c_str());
611
            }
612
            else if(key == "looks")
613
            {
614
                if (iter.second().Type() != YAML::NodeType::Null && 
615
                    iter.second().Read<std::string>(stringval))
616
                  t->setLooks(stringval.c_str());
617
            }
618
            else if(key == "direction")
619
            {
620
                TransformDirection val;
621
                if (iter.second().Type() != YAML::NodeType::Null && 
622
                    iter.second().Read<TransformDirection>(val))
623
                  t->setDirection(val);
624
            }
625
            else
626
            {
378
            {
627
                LogUnknownKeyWarning(node.Tag(), iter.first());
379
                std::vector<float> vars(t->getNumVars());
380
                t->getVars(&vars[0]);
381
                out << YAML::Key << "vars";
382
                out << YAML::Flow << YAML::Value << vars;
628
            }
383
            }
384
            
385
            EmitBaseTransformKeyValues(out, t);
386
            out << YAML::EndMap;
629
        }
387
        }
630
    }
631
    
632
    YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t)
633
    {
634
        out << YAML::VerbatimTag("LookTransform");
635
        out << YAML::Flow << YAML::BeginMap;
636
        out << YAML::Key << "src" << YAML::Value << t->getSrc();
637
        out << YAML::Key << "dst" << YAML::Value << t->getDst();
638
        out << YAML::Key << "looks" << YAML::Value << t->getLooks();
639
        EmitBaseTransformKeyValues(out, t);
640
        out << YAML::EndMap;
641
        return out;
642
    }
643
    
644
    void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t)
645
    {
646
        t = ExponentTransform::Create();
647
        
388
        
648
        std::string key;
389
        // CDLTransform
649
        
390
        
650
        for (YAML::Iterator iter = node.begin();
391
        inline void load(const YAML::Node& node, CDLTransformRcPtr& t)
651
             iter != node.end();
652
             ++iter)
653
        {
392
        {
654
            iter.first() >> key;
393
            t = CDLTransform::Create();
655
            
394
            
656
            if(key == "value")
395
            std::string key;
657
            {
396
            std::vector<float> floatvecval;
658
                std::vector<float> val;
397
            
659
                if (iter.second().Type() != YAML::NodeType::Null)
398
            for (Iterator iter = node.begin();
399
                 iter != node.end();
400
                 ++iter)
401
            {
402
                const YAML::Node& first = get_first(iter);
403
                const YAML::Node& second = get_second(iter);
404
                
405
                load(first, key);
406
                
407
                if (second.Type() == YAML::NodeType::Null) continue;
408
                
409
                if(key == "slope")
660
                {
410
                {
661
                    iter.second() >> val;
411
                    load(second, floatvecval);
662
                    if(val.size() != 4)
412
                    if(floatvecval.size() != 3)
663
                    {
413
                    {
664
                        std::ostringstream os;
414
                        std::ostringstream os;
665
                        os << "ExponentTransform parse error, value field must be 4 ";
415
                        os << "CDLTransform parse error, 'slope' field must be 3 ";
666
                        os << "floats. Found '" << val.size() << "'.";
416
                        os << "floats. Found '" << floatvecval.size() << "'.";
667
                        throw Exception(os.str().c_str());
417
                        throw Exception(os.str().c_str());
668
                    }
418
                    }
669
                    t->setValue(&val[0]);
419
                    t->setSlope(&floatvecval[0]);
670
                }
420
                }
671
            }
421
                else if(key == "offset")
672
            else if(key == "direction")
673
            {
674
                TransformDirection val;
675
                if (iter.second().Type() != YAML::NodeType::Null && 
676
                    iter.second().Read<TransformDirection>(val))
677
                  t->setDirection(val);
678
            }
679
            else
680
            {
681
                LogUnknownKeyWarning(node.Tag(), iter.first());
682
            }
683
        }
684
    }
685
    
686
    YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t)
687
    {
688
        out << YAML::VerbatimTag("ExponentTransform");
689
        out << YAML::Flow << YAML::BeginMap;
690
        
691
        std::vector<float> value(4, 0.0);
692
        t->getValue(&value[0]);
693
        out << YAML::Key << "value";
694
        out << YAML::Value << YAML::Flow << value;
695
        EmitBaseTransformKeyValues(out, t);
696
        out << YAML::EndMap;
697
        return out;
698
    }
699
    
700
    void operator >> (const YAML::Node& node, LogTransformRcPtr& t)
701
    {
702
        t = LogTransform::Create();
703
        
704
        std::string key;
705
        
706
        for (YAML::Iterator iter = node.begin();
707
             iter != node.end();
708
             ++iter)
709
        {
710
            iter.first() >> key;
711
            
712
            if(key == "base")
713
            {
714
                float val = 0.0f;
715
                if (iter.second().Type() != YAML::NodeType::Null && 
716
                    iter.second().Read<float>(val))
717
                  t->setBase(val);
718
            }
719
            else if(key == "direction")
720
            {
721
                TransformDirection val;
722
                if (iter.second().Type() != YAML::NodeType::Null && 
723
                    iter.second().Read<TransformDirection>(val))
724
                  t->setDirection(val);
725
            }
726
            else
727
            {
728
                LogUnknownKeyWarning(node.Tag(), iter.first());
729
            }
730
        }
731
    }
732
    
733
    YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t)
734
    {
735
        out << YAML::VerbatimTag("LogTransform");
736
        out << YAML::Flow << YAML::BeginMap;
737
        out << YAML::Key << "base" << YAML::Value << t->getBase();
738
        EmitBaseTransformKeyValues(out, t);
739
        out << YAML::EndMap;
740
        return out;
741
    }
742
    
743
    void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t)
744
    {
745
        t = MatrixTransform::Create();
746
        
747
        std::string key;
748
        
749
        for (YAML::Iterator iter = node.begin();
750
             iter != node.end();
751
             ++iter)
752
        {
753
            iter.first() >> key;
754
            
755
            if(key == "matrix")
756
            {
757
                std::vector<float> val;
758
                if (iter.second().Type() != YAML::NodeType::Null)
759
                {
422
                {
760
                    iter.second() >> val;
423
                    load(second, floatvecval);
761
                    if(val.size() != 16)
424
                    if(floatvecval.size() != 3)
762
                    {
425
                    {
763
                        std::ostringstream os;
426
                        std::ostringstream os;
764
                        os << "MatrixTransform parse error, matrix field must be 16 ";
427
                        os << "CDLTransform parse error, 'offset' field must be 3 ";
765
                        os << "floats. Found '" << val.size() << "'.";
428
                        os << "floats. Found '" << floatvecval.size() << "'.";
766
                        throw Exception(os.str().c_str());
429
                        throw Exception(os.str().c_str());
767
                    }
430
                    }
768
                    t->setMatrix(&val[0]);
431
                    t->setOffset(&floatvecval[0]);
769
                }
432
                }
770
            }
433
                else if(key == "power")
771
            else if(key == "offset")
772
            {
773
                std::vector<float> val;
774
                if (iter.second().Type() != YAML::NodeType::Null)
775
                {
434
                {
776
                    iter.second() >> val;
435
                    load(second, floatvecval);
777
                    if(val.size() != 4)
436
                    if(floatvecval.size() != 3)
778
                    {
437
                    {
779
                        std::ostringstream os;
438
                        std::ostringstream os;
780
                        os << "MatrixTransform parse error, offset field must be 4 ";
439
                        os << "CDLTransform parse error, 'power' field must be 3 ";
781
                        os << "floats. Found '" << val.size() << "'.";
440
                        os << "floats. Found '" << floatvecval.size() << "'.";
782
                        throw Exception(os.str().c_str());
441
                        throw Exception(os.str().c_str());
783
                    }
442
                    }
784
                    t->setOffset(&val[0]);
443
                    t->setPower(&floatvecval[0]);
444
                }
445
                else if(key == "saturation" || key == "sat")
446
                {
447
                    float val = 0.0f;
448
                    load(second, val);
449
                    t->setSat(val);
785
                }
450
                }
451
                else if(key == "direction")
452
                {
453
                    TransformDirection val;
454
                    load(second, val);
455
                    t->setDirection(val);
456
                }
457
                else
458
                {
459
                    LogUnknownKeyWarning(node.Tag(), first);
460
                }
461
            }
462
        }
463
        
464
        inline void save(YAML::Emitter& out, ConstCDLTransformRcPtr t)
465
        {
466
            out << YAML::VerbatimTag("CDLTransform");
467
            out << YAML::Flow << YAML::BeginMap;
468
            
469
            std::vector<float> slope(3);
470
            t->getSlope(&slope[0]);
471
            if(!IsVecEqualToOne(&slope[0], 3))
472
            {
473
                out << YAML::Key << "slope";
474
                out << YAML::Value << YAML::Flow << slope;
786
            }
475
            }
787
            else if(key == "direction")
476
            
477
            std::vector<float> offset(3);
478
            t->getOffset(&offset[0]);
479
            if(!IsVecEqualToZero(&offset[0], 3))
788
            {
480
            {
789
                TransformDirection val;
481
                out << YAML::Key << "offset";
790
                if (iter.second().Type() != YAML::NodeType::Null && 
482
                out << YAML::Value << YAML::Flow << offset;
791
                    iter.second().Read<TransformDirection>(val))
792
                  t->setDirection(val);
793
            }
483
            }
794
            else
484
            
485
            std::vector<float> power(3);
486
            t->getPower(&power[0]);
487
            if(!IsVecEqualToOne(&power[0], 3))
488
            {
489
                out << YAML::Key << "power";
490
                out << YAML::Value << YAML::Flow << power;
491
            }
492
            
493
            if(!IsScalarEqualToOne(t->getSat()))
795
            {
494
            {
796
                LogUnknownKeyWarning(node.Tag(), iter.first());
495
                out << YAML::Key << "sat" << YAML::Value << t->getSat();
797
            }
496
            }
497
            
498
            EmitBaseTransformKeyValues(out, t);
499
            out << YAML::EndMap;
798
        }
500
        }
799
    }
800
    
801
    YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t)
802
    {
803
        out << YAML::VerbatimTag("MatrixTransform");
804
        out << YAML::Flow << YAML::BeginMap;
805
        
501
        
806
        std::vector<float> matrix(16, 0.0);
502
        // ColorSpaceTransform
807
        t->getMatrix(&matrix[0]);
503
        
808
        if(!IsM44Identity(&matrix[0]))
504
        inline void load(const YAML::Node& node, ColorSpaceTransformRcPtr& t)
809
        {
505
        {
810
            out << YAML::Key << "matrix";
506
            t = ColorSpaceTransform::Create();
811
            out << YAML::Value << YAML::Flow << matrix;
507
            
508
            std::string key, stringval;
509
            
510
            for (Iterator iter = node.begin();
511
                 iter != node.end();
512
                 ++iter)
513
            {
514
                const YAML::Node& first = get_first(iter);
515
                const YAML::Node& second = get_second(iter);
516
                
517
                load(first, key);
518
                
519
                if (second.Type() == YAML::NodeType::Null) continue;
520
                
521
                if(key == "src")
522
                {
523
                    load(second, stringval);
524
                    t->setSrc(stringval.c_str());
525
                }
526
                else if(key == "dst")
527
                {
528
                    load(second, stringval);
529
                    t->setDst(stringval.c_str());
530
                }
531
                else if(key == "direction")
532
                {
533
                    TransformDirection val;
534
                    load(second, val);
535
                    t->setDirection(val);
536
                }
537
                else
538
                {
539
                    LogUnknownKeyWarning(node.Tag(), first);
540
                }
541
            }
812
        }
542
        }
813
        
543
        
814
        std::vector<float> offset(4, 0.0);
544
        inline void save(YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
815
        t->getOffset(&offset[0]);
816
        if(!IsVecEqualToZero(&offset[0],4))
817
        {
545
        {
818
            out << YAML::Key << "offset";
546
            out << YAML::VerbatimTag("ColorSpaceTransform");
819
            out << YAML::Value << YAML::Flow << offset;
547
            out << YAML::Flow << YAML::BeginMap;
548
            out << YAML::Key << "src" << YAML::Value << t->getSrc();
549
            out << YAML::Key << "dst" << YAML::Value << t->getDst();
550
            EmitBaseTransformKeyValues(out, t);
551
            out << YAML::EndMap;
820
        }
552
        }
821
        
553
        
822
        EmitBaseTransformKeyValues(out, t);
554
        // ExponentTransform
823
        out << YAML::EndMap;
824
        return out;
825
    }
826
    
827
    void operator >> (const YAML::Node& node, CDLTransformRcPtr& t)
828
    {
829
        t = CDLTransform::Create();
830
        
555
        
831
        std::string key;
556
        inline void load(const YAML::Node& node, ExponentTransformRcPtr& t)
832
        std::vector<float> floatvecval;
833
        
834
        for (YAML::Iterator iter = node.begin();
835
             iter != node.end();
836
             ++iter)
837
        {
557
        {
838
            iter.first() >> key;
558
            t = ExponentTransform::Create();
839
            
559
            
840
            if(key == "slope")
560
            std::string key;
841
            {
561
            
842
                if (iter.second().Type() != YAML::NodeType::Null)
562
            for (Iterator iter = node.begin();
563
                 iter != node.end();
564
                 ++iter)
565
            {
566
                const YAML::Node& first = get_first(iter);
567
                const YAML::Node& second = get_second(iter);
568
                
569
                load(first, key);
570
                
571
                if (second.Type() == YAML::NodeType::Null) continue;
572
                
573
                if(key == "value")
843
                {
574
                {
844
                    iter.second() >> floatvecval;
575
                    std::vector<float> val;
845
                    if(floatvecval.size() != 3)
576
                    load(second, val);
577
                    if(val.size() != 4)
846
                    {
578
                    {
847
                        std::ostringstream os;
579
                        std::ostringstream os;
848
                        os << "CDLTransform parse error, 'slope' field must be 3 ";
580
                        os << "ExponentTransform parse error, value field must be 4 ";
849
                        os << "floats. Found '" << floatvecval.size() << "'.";
581
                        os << "floats. Found '" << val.size() << "'.";
850
                        throw Exception(os.str().c_str());
582
                        throw Exception(os.str().c_str());
851
                    }
583
                    }
852
                    t->setSlope(&floatvecval[0]);
584
                    t->setValue(&val[0]);
585
                }
586
                else if(key == "direction")
587
                {
588
                    TransformDirection val;
589
                    load(second, val);
590
                    t->setDirection(val);
591
                }
592
                else
593
                {
594
                    LogUnknownKeyWarning(node.Tag(), first);
853
                }
595
                }
854
            }
596
            }
855
            else if(key == "offset")
597
        }
856
            {
598
        
857
                if (iter.second().Type() != YAML::NodeType::Null)
599
        inline void save(YAML::Emitter& out, ConstExponentTransformRcPtr t)
600
        {
601
            out << YAML::VerbatimTag("ExponentTransform");
602
            out << YAML::Flow << YAML::BeginMap;
603
            
604
            std::vector<float> value(4, 0.0);
605
            t->getValue(&value[0]);
606
            out << YAML::Key << "value";
607
            out << YAML::Value << YAML::Flow << value;
608
            EmitBaseTransformKeyValues(out, t);
609
            out << YAML::EndMap;
610
        }
611
        
612
        // FileTransform
613
        
614
        inline void load(const YAML::Node& node, FileTransformRcPtr& t)
615
        {
616
            t = FileTransform::Create();
617
            
618
            std::string key, stringval;
619
            
620
            for (Iterator iter = node.begin();
621
                 iter != node.end();
622
                 ++iter)
623
            {
624
                const YAML::Node& first = get_first(iter);
625
                const YAML::Node& second = get_second(iter);
626
                
627
                load(first, key);
628
                
629
                if (second.Type() == YAML::NodeType::Null) continue;
630
                
631
                if(key == "src")
858
                {
632
                {
859
                    iter.second() >> floatvecval;
633
                    load(second, stringval);
860
                    if(floatvecval.size() != 3)
634
                    t->setSrc(stringval.c_str());
861
                    {
635
                }
862
                        std::ostringstream os;
636
                else if(key == "cccid")
863
                        os << "CDLTransform parse error, 'offset' field must be 3 ";
637
                {
864
                        os << "floats. Found '" << floatvecval.size() << "'.";
638
                    load(second, stringval);
865
                        throw Exception(os.str().c_str());
639
                    t->setCCCId(stringval.c_str());
866
                    }
640
                }
867
                    t->setOffset(&floatvecval[0]);
641
                else if(key == "interpolation")
642
                {
643
                    Interpolation val;
644
                    load(second, val);
645
                    t->setInterpolation(val);
646
                }
647
                else if(key == "direction")
648
                {
649
                    TransformDirection val;
650
                    load(second, val);
651
                    t->setDirection(val);
652
                }
653
                else
654
                {
655
                    LogUnknownKeyWarning(node.Tag(), first);
868
                }
656
                }
869
            }
657
            }
870
            else if(key == "power")
658
        }
659
        
660
        inline void save(YAML::Emitter& out, ConstFileTransformRcPtr t)
661
        {
662
            out << YAML::VerbatimTag("FileTransform");
663
            out << YAML::Flow << YAML::BeginMap;
664
            out << YAML::Key << "src" << YAML::Value << t->getSrc();
665
            const char * cccid = t->getCCCId();
666
            if(cccid && *cccid)
871
            {
667
            {
872
                if (iter.second().Type() != YAML::NodeType::Null)
668
                out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
669
            }
670
            out << YAML::Key << "interpolation";
671
            out << YAML::Value;
672
            save(out, t->getInterpolation());
673
            
674
            EmitBaseTransformKeyValues(out, t);
675
            out << YAML::EndMap;
676
        }
677
        
678
        // GroupTransform
679
        
680
        void load(const YAML::Node& node, TransformRcPtr& t);
681
        void save(YAML::Emitter& out, ConstTransformRcPtr t);
682
        
683
        inline void load(const YAML::Node& node, GroupTransformRcPtr& t)
684
        {
685
            t = GroupTransform::Create();
686
            
687
            std::string key;
688
            
689
            for (Iterator iter = node.begin();
690
                 iter != node.end();
691
                 ++iter)
692
            {
693
                const YAML::Node& first = get_first(iter);
694
                const YAML::Node& second = get_second(iter);
695
                
696
                load(first, key);
697
                
698
                if (second.Type() == YAML::NodeType::Null) continue;
699
                
700
                if(key == "children")
873
                {
701
                {
874
                    iter.second() >> floatvecval;
702
                    for(unsigned i = 0; i < second.size(); ++i)
875
                    if(floatvecval.size() != 3)
876
                    {
703
                    {
877
                        std::ostringstream os;
704
                        TransformRcPtr childTransform;
878
                        os << "CDLTransform parse error, 'power' field must be 3 ";
705
                        load(second[i], childTransform);
879
                        os << "floats. Found '" << floatvecval.size() << "'.";
706
                        
880
                        throw Exception(os.str().c_str());
707
                        // TODO: consider the forwards-compatibility implication of
708
                        // throwing an exception.  Should this be a warning, instead?
709
                        if(!childTransform)
710
                        {
711
                            throw Exception("Child transform could not be parsed.");
712
                        }
713
                        
714
                        t->push_back(childTransform);
881
                    }
715
                    }
882
                    t->setPower(&floatvecval[0]);
716
                }
717
                else if(key == "direction")
718
                {
719
                    TransformDirection val;
720
                    load(second, val);
721
                    t->setDirection(val);
722
                }
723
                else
724
                {
725
                    LogUnknownKeyWarning(node.Tag(), first);
883
                }
726
                }
884
            }
727
            }
885
            else if(key == "saturation" || key == "sat")
728
        }
886
            {
729
        
887
                float val = 0.0f;
730
        inline void save(YAML::Emitter& out, ConstGroupTransformRcPtr t)
888
                if (iter.second().Type() != YAML::NodeType::Null && 
731
        {
889
                    iter.second().Read<float>(val))
732
            out << YAML::VerbatimTag("GroupTransform");
890
                  t->setSat(val);
733
            out << YAML::BeginMap;
891
            }
734
            EmitBaseTransformKeyValues(out, t);
892
            else if(key == "direction")
735
            
893
            {
736
            out << YAML::Key << "children";
894
                TransformDirection val;
737
            out << YAML::Value;
895
                if (iter.second().Type() != YAML::NodeType::Null && 
738
            
896
                    iter.second().Read<TransformDirection>(val))
739
            out << YAML::BeginSeq;
897
                  t->setDirection(val);
740
            for(int i = 0; i < t->size(); ++i)
898
            }
899
            else
900
            {
741
            {
901
                LogUnknownKeyWarning(node.Tag(), iter.first());
742
                save(out, t->getTransform(i));
902
            }
743
            }
744
            out << YAML::EndSeq;
745
            
746
            out << YAML::EndMap;
903
        }
747
        }
904
    }
905
    
906
    YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t)
907
    {
908
        out << YAML::VerbatimTag("CDLTransform");
909
        out << YAML::Flow << YAML::BeginMap;
910
        
748
        
911
        std::vector<float> slope(3);
749
        // LogTransform
912
        t->getSlope(&slope[0]);
750
        
913
        if(!IsVecEqualToOne(&slope[0], 3))
751
        inline void load(const YAML::Node& node, LogTransformRcPtr& t)
914
        {
752
        {
915
            out << YAML::Key << "slope";
753
            t = LogTransform::Create();
916
            out << YAML::Value << YAML::Flow << slope;
754
            
755
            std::string key;
756
            
757
            for (Iterator iter = node.begin();
758
                 iter != node.end();
759
                 ++iter)
760
            {
761
                const YAML::Node& first = get_first(iter);
762
                const YAML::Node& second = get_second(iter);
763
                
764
                load(first, key);
765
                
766
                if (second.Type() == YAML::NodeType::Null) continue;
767
                
768
                if(key == "base")
769
                {
770
                    float val = 0.0f;
771
                    load(second, val);
772
                    t->setBase(val);
773
                }
774
                else if(key == "direction")
775
                {
776
                    TransformDirection val;
777
                    load(second, val);
778
                    t->setDirection(val);
779
                }
780
                else
781
                {
782
                    LogUnknownKeyWarning(node.Tag(), first);
783
                }
784
            }
917
        }
785
        }
918
        
786
        
919
        std::vector<float> offset(3);
787
        inline void save(YAML::Emitter& out, ConstLogTransformRcPtr t)
920
        t->getOffset(&offset[0]);
921
        if(!IsVecEqualToZero(&offset[0], 3))
922
        {
788
        {
923
            out << YAML::Key << "offset";
789
            out << YAML::VerbatimTag("LogTransform");
924
            out << YAML::Value << YAML::Flow << offset;
790
            out << YAML::Flow << YAML::BeginMap;
791
            out << YAML::Key << "base" << YAML::Value << t->getBase();
792
            EmitBaseTransformKeyValues(out, t);
793
            out << YAML::EndMap;
925
        }
794
        }
926
        
795
        
927
        std::vector<float> power(3);
796
        // LookTransform
928
        t->getPower(&power[0]);
797
        
929
        if(!IsVecEqualToOne(&power[0], 3))
798
        inline void load(const YAML::Node& node, LookTransformRcPtr& t)
930
        {
799
        {
931
            out << YAML::Key << "power";
800
            t = LookTransform::Create();
932
            out << YAML::Value << YAML::Flow << power;
801
            
802
            std::string key, stringval;
803
            
804
            for (Iterator iter = node.begin();
805
                 iter != node.end();
806
                 ++iter)
807
            {
808
                const YAML::Node& first = get_first(iter);
809
                const YAML::Node& second = get_second(iter);
810
                
811
                load(first, key);
812
                
813
                if (second.Type() == YAML::NodeType::Null) continue;
814
                
815
                if(key == "src")
816
                {
817
                    load(second, stringval);
818
                    t->setSrc(stringval.c_str());
819
                }
820
                else if(key == "dst")
821
                {
822
                    load(second, stringval);
823
                    t->setDst(stringval.c_str());
824
                }
825
                else if(key == "looks")
826
                {
827
                    load(second, stringval);
828
                    t->setLooks(stringval.c_str());
829
                }
830
                else if(key == "direction")
831
                {
832
                    TransformDirection val;
833
                    load(second, val);
834
                    t->setDirection(val);
835
                }
836
                else
837
                {
838
                    LogUnknownKeyWarning(node.Tag(), first);
839
                }
840
            }
933
        }
841
        }
934
        
842
        
935
        if(!IsScalarEqualToOne(t->getSat()))
843
        inline void save(YAML::Emitter& out, ConstLookTransformRcPtr t)
936
        {
844
        {
937
            out << YAML::Key << "sat" << YAML::Value << t->getSat();
845
            out << YAML::VerbatimTag("LookTransform");
846
            out << YAML::Flow << YAML::BeginMap;
847
            out << YAML::Key << "src" << YAML::Value << t->getSrc();
848
            out << YAML::Key << "dst" << YAML::Value << t->getDst();
849
            out << YAML::Key << "looks" << YAML::Value << t->getLooks();
850
            EmitBaseTransformKeyValues(out, t);
851
            out << YAML::EndMap;
938
        }
852
        }
939
        
853
        
940
        EmitBaseTransformKeyValues(out, t);
854
        // MatrixTransform
941
        out << YAML::EndMap;
942
        return out;
943
    }
944
    
945
    void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t)
946
    {
947
        t = AllocationTransform::Create();
948
        
949
        std::string key;
950
        
855
        
951
        for (YAML::Iterator iter = node.begin();
856
        inline void load(const YAML::Node& node, MatrixTransformRcPtr& t)
952
             iter != node.end();
953
             ++iter)
954
        {
857
        {
955
            iter.first() >> key;
858
            t = MatrixTransform::Create();
956
            
859
            
957
            if(key == "allocation")
860
            std::string key;
958
            {
861
            
959
                Allocation val;
862
            for (Iterator iter = node.begin();
960
                if (iter.second().Type() != YAML::NodeType::Null && 
863
                 iter != node.end();
961
                    iter.second().Read<Allocation>(val))
864
                 ++iter)
962
                  t->setAllocation(val);
865
            {
963
            }
866
                const YAML::Node& first = get_first(iter);
964
            else if(key == "vars")
867
                const YAML::Node& second = get_second(iter);
965
            {
868
                
966
                std::vector<float> val;
869
                load(first, key);
967
                if (iter.second().Type() != YAML::NodeType::Null)
870
                
871
                if (second.Type() == YAML::NodeType::Null) continue;
872
                
873
                if(key == "matrix")
968
                {
874
                {
969
                    iter.second() >> val;
875
                    std::vector<float> val;
970
                    if(!val.empty())
876
                    load(second, val);
877
                    if(val.size() != 16)
971
                    {
878
                    {
972
                        t->setVars(static_cast<int>(val.size()), &val[0]);
879
                        std::ostringstream os;
880
                        os << "MatrixTransform parse error, matrix field must be 16 ";
881
                        os << "floats. Found '" << val.size() << "'.";
882
                        throw Exception(os.str().c_str());
883
                    }
884
                    t->setMatrix(&val[0]);
885
                }
886
                else if(key == "offset")
887
                {
888
                    std::vector<float> val;
889
                    load(second, val);
890
                    if(val.size() != 4)
891
                    {
892
                        std::ostringstream os;
893
                        os << "MatrixTransform parse error, offset field must be 4 ";
894
                        os << "floats. Found '" << val.size() << "'.";
895
                        throw Exception(os.str().c_str());
973
                    }
896
                    }
897
                    t->setOffset(&val[0]);
898
                }
899
                else if(key == "direction")
900
                {
901
                    TransformDirection val;
902
                    load(second, val);
903
                    t->setDirection(val);
904
                }
905
                else
906
                {
907
                    LogUnknownKeyWarning(node.Tag(), first);
974
                }
908
                }
975
            }
909
            }
976
            else if(key == "direction")
910
        }
911
        
912
        inline void save(YAML::Emitter& out, ConstMatrixTransformRcPtr t)
913
        {
914
            out << YAML::VerbatimTag("MatrixTransform");
915
            out << YAML::Flow << YAML::BeginMap;
916
            
917
            std::vector<float> matrix(16, 0.0);
918
            t->getMatrix(&matrix[0]);
919
            if(!IsM44Identity(&matrix[0]))
977
            {
920
            {
978
                TransformDirection val;
921
                out << YAML::Key << "matrix";
979
                if (iter.second().Type() != YAML::NodeType::Null && 
922
                out << YAML::Value << YAML::Flow << matrix;
980
                    iter.second().Read<TransformDirection>(val))
981
                  t->setDirection(val);
982
            }
923
            }
983
            else
924
            
925
            std::vector<float> offset(4, 0.0);
926
            t->getOffset(&offset[0]);
927
            if(!IsVecEqualToZero(&offset[0],4))
984
            {
928
            {
985
                LogUnknownKeyWarning(node.Tag(), iter.first());
929
                out << YAML::Key << "offset";
930
                out << YAML::Value << YAML::Flow << offset;
986
            }
931
            }
932
            
933
            EmitBaseTransformKeyValues(out, t);
934
            out << YAML::EndMap;
987
        }
935
        }
988
    }
989
    
990
    YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t)
991
    {
992
        out << YAML::VerbatimTag("AllocationTransform");
993
        out << YAML::Flow << YAML::BeginMap;
994
        
936
        
995
        out << YAML::Key << "allocation";
937
        // TruelightTransform
996
        out << YAML::Value << YAML::Flow << t->getAllocation();
997
        
938
        
998
        if(t->getNumVars() > 0)
939
        inline void load(const YAML::Node& node, TruelightTransformRcPtr& t)
999
        {
940
        {
1000
            std::vector<float> vars(t->getNumVars());
941
            t = TruelightTransform::Create();
1001
            t->getVars(&vars[0]);
942
            
1002
            out << YAML::Key << "vars";
943
            std::string key, stringval;
1003
            out << YAML::Flow << YAML::Value << vars;
944
            
945
            for (Iterator iter = node.begin();
946
                 iter != node.end();
947
                 ++iter)
948
            {
949
                const YAML::Node& first = get_first(iter);
950
                const YAML::Node& second = get_second(iter);
951
                
952
                load(first, key);
953
                
954
                if (second.Type() == YAML::NodeType::Null) continue;
955
                
956
                if(key == "config_root")
957
                {
958
                    load(second, stringval);
959
                    t->setConfigRoot(stringval.c_str());
960
                }
961
                else if(key == "profile")
962
                {
963
                    load(second, stringval);
964
                    t->setProfile(stringval.c_str());
965
                }
966
                else if(key == "camera")
967
                {
968
                    load(second, stringval);
969
                    t->setCamera(stringval.c_str());
970
                }
971
                else if(key == "input_display")
972
                {
973
                    load(second, stringval);
974
                    t->setInputDisplay(stringval.c_str());
975
                }
976
                else if(key == "recorder")
977
                {
978
                    load(second, stringval);
979
                    t->setRecorder(stringval.c_str());
980
                }
981
                else if(key == "print")
982
                {
983
                    load(second, stringval);
984
                    t->setPrint(stringval.c_str());
985
                }
986
                else if(key == "lamp")
987
                {
988
                    load(second, stringval);
989
                    t->setLamp(stringval.c_str());
990
                }
991
                else if(key == "output_camera")
992
                {
993
                    load(second, stringval);
994
                    t->setOutputCamera(stringval.c_str());
995
                }
996
                else if(key == "display")
997
                {
998
                    load(second, stringval);
999
                    t->setDisplay(stringval.c_str());
1000
                }
1001
                else if(key == "cube_input")
1002
                {
1003
                    load(second, stringval);
1004
                     t->setCubeInput(stringval.c_str());
1005
                }
1006
                else if(key == "direction")
1007
                {
1008
                    TransformDirection val;
1009
                    load(second, val);
1010
                    t->setDirection(val);
1011
                }
1012
                else
1013
                {
1014
                    LogUnknownKeyWarning(node.Tag(), first);
1015
                }
1016
            }
1004
        }
1017
        }
1005
        
1018
        
1006
        EmitBaseTransformKeyValues(out, t);
1019
        inline void save(YAML::Emitter& out, ConstTruelightTransformRcPtr t)
1007
        out << YAML::EndMap;
1008
        return out;
1009
    }
1010
    
1011
    void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t)
1012
    {
1013
        t = TruelightTransform::Create();
1014
        
1015
        std::string key, stringval;
1016
        
1017
        for (YAML::Iterator iter = node.begin();
1018
             iter != node.end();
1019
             ++iter)
1020
        {
1020
        {
1021
            iter.first() >> key;
1022
            
1021
            
1023
            if(key == "config_root")
1022
            out << YAML::VerbatimTag("TruelightTransform");
1023
            out << YAML::Flow << YAML::BeginMap;
1024
            if(strcmp(t->getConfigRoot(), "") != 0)
1024
            {
1025
            {
1025
                if (iter.second().Type() != YAML::NodeType::Null && 
1026
                out << YAML::Key << "config_root";
1026
                    iter.second().Read<std::string>(stringval))
1027
                out << YAML::Value << YAML::Flow << t->getConfigRoot();
1027
                  t->setConfigRoot(stringval.c_str());
1028
            }
1028
            }
1029
            else if(key == "profile")
1029
            if(strcmp(t->getProfile(), "") != 0)
1030
            {
1030
            {
1031
                if (iter.second().Type() != YAML::NodeType::Null && 
1031
                out << YAML::Key << "profile";
1032
                    iter.second().Read<std::string>(stringval))
1032
                out << YAML::Value << YAML::Flow << t->getProfile();
1033
                  t->setProfile(stringval.c_str());
1034
            }
1033
            }
1035
            else if(key == "camera")
1034
            if(strcmp(t->getCamera(), "") != 0)
1036
            {
1035
            {
1037
                if (iter.second().Type() != YAML::NodeType::Null && 
1036
                out << YAML::Key << "camera";
1038
                    iter.second().Read<std::string>(stringval))
1037
                out << YAML::Value << YAML::Flow << t->getCamera();
1039
                  t->setCamera(stringval.c_str());
1040
            }
1038
            }
1041
            else if(key == "input_display")
1039
            if(strcmp(t->getInputDisplay(), "") != 0)
1042
            {
1040
            {
1043
                if (iter.second().Type() != YAML::NodeType::Null && 
1041
                out << YAML::Key << "input_display";
1044
                    iter.second().Read<std::string>(stringval))
1042
                out << YAML::Value << YAML::Flow << t->getInputDisplay();
1045
                  t->setInputDisplay(stringval.c_str());
1046
            }
1043
            }
1047
            else if(key == "recorder")
1044
            if(strcmp(t->getRecorder(), "") != 0)
1048
            {
1045
            {
1049
                if (iter.second().Type() != YAML::NodeType::Null && 
1046
                out << YAML::Key << "recorder";
1050
                    iter.second().Read<std::string>(stringval))
1047
                out << YAML::Value << YAML::Flow << t->getRecorder();
1051
                  t->setRecorder(stringval.c_str());
1052
            }
1048
            }
1053
            else if(key == "print")
1049
            if(strcmp(t->getPrint(), "") != 0)
1054
            {
1050
            {
1055
                if (iter.second().Type() != YAML::NodeType::Null && 
1051
                out << YAML::Key << "print";
1056
                    iter.second().Read<std::string>(stringval))
1052
                out << YAML::Value << YAML::Flow << t->getPrint();
1057
                  t->setPrint(stringval.c_str());
1058
            }
1053
            }
1059
            else if(key == "lamp")
1054
            if(strcmp(t->getLamp(), "") != 0)
1060
            {
1055
            {
1061
                if (iter.second().Type() != YAML::NodeType::Null && 
1056
                out << YAML::Key << "lamp";
1062
                    iter.second().Read<std::string>(stringval))
1057
                out << YAML::Value << YAML::Flow << t->getLamp();
1063
                  t->setLamp(stringval.c_str());
1064
            }
1058
            }
1065
            else if(key == "output_camera")
1059
            if(strcmp(t->getOutputCamera(), "") != 0)
1066
            {
1060
            {
1067
                if (iter.second().Type() != YAML::NodeType::Null && 
1061
                out << YAML::Key << "output_camera";
1068
                    iter.second().Read<std::string>(stringval))
1062
                out << YAML::Value << YAML::Flow << t->getOutputCamera();
1069
                  t->setOutputCamera(stringval.c_str());
1070
            }
1063
            }
1071
            else if(key == "display")
1064
            if(strcmp(t->getDisplay(), "") != 0)
1072
            {
1065
            {
1073
                if (iter.second().Type() != YAML::NodeType::Null && 
1066
                out << YAML::Key << "display";
1074
                    iter.second().Read<std::string>(stringval))
1067
                out << YAML::Value << YAML::Flow << t->getDisplay();
1075
                  t->setDisplay(stringval.c_str());
1076
            }
1068
            }
1077
            else if(key == "cube_input")
1069
            if(strcmp(t->getCubeInput(), "") != 0)
1078
            {
1070
            {
1079
                if (iter.second().Type() != YAML::NodeType::Null && 
1071
                out << YAML::Key << "cube_input";
1080
                    iter.second().Read<std::string>(stringval))
1072
                out << YAML::Value << YAML::Flow << t->getCubeInput();
1081
                  t->setCubeInput(stringval.c_str());
1082
            }
1073
            }
1083
            else if(key == "direction")
1074
            
1075
            EmitBaseTransformKeyValues(out, t);
1076
            
1077
            out << YAML::EndMap;
1078
        }
1079
        
1080
        // Transform
1081
        
1082
        void load(const YAML::Node& node, TransformRcPtr& t)
1083
        {
1084
            if(node.Type() != YAML::NodeType::Map)
1084
            {
1085
            {
1085
                TransformDirection val;
1086
                std::ostringstream os;
1086
                if (iter.second().Type() != YAML::NodeType::Null && 
1087
                os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
1087
                    iter.second().Read<TransformDirection>(val))
1088
                os << "Only Mapping types supported.";
1088
                  t->setDirection(val);
1089
                throw Exception(os.str().c_str());
1090
            }
1091
            
1092
            std::string type = node.Tag();
1093
            
1094
            if(type == "AllocationTransform") {
1095
                AllocationTransformRcPtr temp;
1096
                load(node, temp);
1097
                t = temp;
1098
            }
1099
            else if(type == "CDLTransform") {
1100
                CDLTransformRcPtr temp;
1101
                load(node, temp);
1102
                t = temp;
1103
            }
1104
            else if(type == "ColorSpaceTransform")  {
1105
                ColorSpaceTransformRcPtr temp;
1106
                load(node, temp);
1107
                t = temp;
1108
            }
1109
            // TODO: DisplayTransform
1110
            else if(type == "ExponentTransform")  {
1111
                ExponentTransformRcPtr temp;
1112
                load(node, temp);
1113
                t = temp;
1114
            }
1115
            else if(type == "FileTransform")  {
1116
                FileTransformRcPtr temp;
1117
                load(node, temp);
1118
                t = temp;
1119
            }
1120
            else if(type == "GroupTransform") {
1121
                GroupTransformRcPtr temp;
1122
                load(node, temp);
1123
                t = temp;
1124
            }
1125
            else if(type == "LogTransform") {
1126
                LogTransformRcPtr temp;
1127
                load(node, temp);
1128
                t = temp;
1129
            }
1130
            else if(type == "LookTransform") {
1131
                LookTransformRcPtr temp;
1132
                load(node, temp);
1133
                t = temp;
1134
            }
1135
            else if(type == "MatrixTransform")  {
1136
                MatrixTransformRcPtr temp;
1137
                load(node, temp);
1138
                t = temp;
1139
            }
1140
            else if(type == "TruelightTransform")  {
1141
                TruelightTransformRcPtr temp;
1142
                load(node, temp);
1143
                t = temp;
1089
            }
1144
            }
1090
            else
1145
            else
1091
            {
1146
            {
1092
                LogUnknownKeyWarning(node.Tag(), iter.first());
1147
                // TODO: add a new empty (better name?) aka passthru Transform()
1148
                // which does nothing. This is so upsupported !<tag> types don't
1149
                // throw an exception. Alternativly this could be caught in the
1150
                // GroupTransformRcPtr >> operator with some type of
1151
                // supported_tag() method
1152
                
1153
                // TODO: consider the forwards-compatibility implication of
1154
                // throwing an exception.  Should this be a warning, instead?
1155
                
1156
                //  t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
1157
                std::ostringstream os;
1158
                os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
1159
                throw Exception(os.str().c_str());
1093
            }
1160
            }
1094
        }
1161
        }
1095
    }
1096
    
1097
    YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t)
1098
    {
1099
        
1162
        
1100
        out << YAML::VerbatimTag("TruelightTransform");
1163
        void save(YAML::Emitter& out, ConstTransformRcPtr t)
1101
        out << YAML::Flow << YAML::BeginMap;
1102
        if(strcmp(t->getConfigRoot(), "") != 0)
1103
        {
1104
            out << YAML::Key << "config_root";
1105
            out << YAML::Value << YAML::Flow << t->getConfigRoot();
1106
        }
1107
        if(strcmp(t->getProfile(), "") != 0)
1108
        {
1164
        {
1109
            out << YAML::Key << "profile";
1165
            if(ConstAllocationTransformRcPtr Allocation_tran = \
1110
            out << YAML::Value << YAML::Flow << t->getProfile();
1166
                DynamicPtrCast<const AllocationTransform>(t))
1111
        }
1167
                save(out, Allocation_tran);
1112
        if(strcmp(t->getCamera(), "") != 0)
1168
            else if(ConstCDLTransformRcPtr CDL_tran = \
1113
        {
1169
                DynamicPtrCast<const CDLTransform>(t))
1114
            out << YAML::Key << "camera";
1170
                save(out, CDL_tran);
1115
            out << YAML::Value << YAML::Flow << t->getCamera();
1171
            else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
1116
        }
1172
                DynamicPtrCast<const ColorSpaceTransform>(t))
1117
        if(strcmp(t->getInputDisplay(), "") != 0)
1173
                save(out, ColorSpace_tran);
1118
        {
1174
            else if(ConstExponentTransformRcPtr Exponent_tran = \
1119
            out << YAML::Key << "input_display";
1175
                DynamicPtrCast<const ExponentTransform>(t))
1120
            out << YAML::Value << YAML::Flow << t->getInputDisplay();
1176
                save(out, Exponent_tran);
1177
            else if(ConstFileTransformRcPtr File_tran = \
1178
                DynamicPtrCast<const FileTransform>(t))
1179
                save(out, File_tran);
1180
            else if(ConstGroupTransformRcPtr Group_tran = \
1181
                DynamicPtrCast<const GroupTransform>(t))
1182
                save(out, Group_tran);
1183
            else if(ConstLogTransformRcPtr Log_tran = \
1184
                DynamicPtrCast<const LogTransform>(t))
1185
                save(out, Log_tran);
1186
            else if(ConstLookTransformRcPtr Look_tran = \
1187
                DynamicPtrCast<const LookTransform>(t))
1188
                save(out, Look_tran);
1189
            else if(ConstMatrixTransformRcPtr Matrix_tran = \
1190
                DynamicPtrCast<const MatrixTransform>(t))
1191
                save(out, Matrix_tran);
1192
            else if(ConstTruelightTransformRcPtr Truelight_tran = \
1193
                DynamicPtrCast<const TruelightTransform>(t))
1194
                save(out, Truelight_tran);
1195
            else
1196
                throw Exception("Unsupported Transform() type for serialization.");
1121
        }
1197
        }
1122
        if(strcmp(t->getRecorder(), "") != 0)
1198
        
1199
        // ColorSpace
1200
        
1201
        inline void load(const YAML::Node& node, ColorSpaceRcPtr& cs)
1123
        {
1202
        {
1124
            out << YAML::Key << "recorder";
1203
            if(node.Tag() != "ColorSpace")
1125
            out << YAML::Value << YAML::Flow << t->getRecorder();
1204
                return; // not a !<ColorSpace> tag
1205
            
1206
            std::string key, stringval;
1207
            bool boolval;
1208
            
1209
            for (Iterator iter = node.begin();
1210
                 iter != node.end();
1211
                 ++iter)
1212
            {
1213
                const YAML::Node& first = get_first(iter);
1214
                const YAML::Node& second = get_second(iter);
1215
                
1216
                load(first, key);
1217
                
1218
                if (second.Type() == YAML::NodeType::Null) continue;
1219
                
1220
                if(key == "name")
1221
                {
1222
                    load(second, stringval);
1223
                    cs->setName(stringval.c_str());
1224
                }
1225
                else if(key == "description")
1226
                {
1227
                    load(second, stringval);
1228
                    cs->setDescription(stringval.c_str());
1229
                }
1230
                else if(key == "family")
1231
                {
1232
                    load(second, stringval);
1233
                    cs->setFamily(stringval.c_str());
1234
                }
1235
                else if(key == "equalitygroup")
1236
                {
1237
                    load(second, stringval);
1238
                    cs->setEqualityGroup(stringval.c_str());
1239
                }
1240
                else if(key == "bitdepth")
1241
                {
1242
                    BitDepth ret;
1243
                    load(second, ret);
1244
                    cs->setBitDepth(ret);
1245
                }
1246
                else if(key == "isdata")
1247
                {
1248
                    load(second, boolval);
1249
                    cs->setIsData(boolval);
1250
                }
1251
                else if(key == "allocation")
1252
                {
1253
                    Allocation val;
1254
                    load(second, val);
1255
                    cs->setAllocation(val);
1256
                }
1257
                else if(key == "allocationvars")
1258
                {
1259
                    std::vector<float> val;
1260
                    load(second, val);
1261
                    if(!val.empty())
1262
                        cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
1263
                }
1264
                else if(key == "to_reference")
1265
                {
1266
                    TransformRcPtr val;
1267
                    load(second, val);
1268
                    cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
1269
                }
1270
                else if(key == "from_reference")
1271
                {
1272
                    TransformRcPtr val;
1273
                    load(second, val);
1274
                    cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
1275
                }
1276
                else
1277
                {
1278
                    LogUnknownKeyWarning(node.Tag(), first);
1279
                }
1280
            }
1126
        }
1281
        }
1127
        if(strcmp(t->getPrint(), "") != 0)
1282
        
1283
        inline void save(YAML::Emitter& out, ConstColorSpaceRcPtr cs)
1128
        {
1284
        {
1129
            out << YAML::Key << "print";
1285
            out << YAML::VerbatimTag("ColorSpace");
1130
            out << YAML::Value << YAML::Flow << t->getPrint();
1286
            out << YAML::BeginMap;
1287
            
1288
            out << YAML::Key << "name" << YAML::Value << cs->getName();
1289
            out << YAML::Key << "family" << YAML::Value << cs->getFamily();
1290
            out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
1291
            out << YAML::Key << "bitdepth" << YAML::Value;
1292
            save(out, cs->getBitDepth());
1293
            if(cs->getDescription() != NULL && strlen(cs->getDescription()) > 0)
1294
            {
1295
                out << YAML::Key << "description";
1296
                out << YAML::Value << YAML::Literal << cs->getDescription();
1297
            }
1298
            out << YAML::Key << "isdata" << YAML::Value << cs->isData();
1299
            
1300
            out << YAML::Key << "allocation" << YAML::Value;
1301
            save(out, cs->getAllocation());
1302
            if(cs->getAllocationNumVars() > 0)
1303
            {
1304
                std::vector<float> allocationvars(cs->getAllocationNumVars());
1305
                cs->getAllocationVars(&allocationvars[0]);
1306
                out << YAML::Key << "allocationvars";
1307
                out << YAML::Flow << YAML::Value << allocationvars;
1308
            }
1309
            
1310
            ConstTransformRcPtr toref = \
1311
                cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
1312
            if(toref)
1313
            {
1314
                out << YAML::Key << "to_reference" << YAML::Value;
1315
                save(out, toref);
1316
            }
1317
            
1318
            ConstTransformRcPtr fromref = \
1319
                cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
1320
            if(fromref)
1321
            {
1322
                out << YAML::Key << "from_reference" << YAML::Value;
1323
                save(out, fromref);
1324
            }
1325
            
1326
            out << YAML::EndMap;
1327
            out << YAML::Newline;
1131
        }
1328
        }
1132
        if(strcmp(t->getLamp(), "") != 0)
1329
        
1330
        // Look
1331
        
1332
        inline void load(const YAML::Node& node, LookRcPtr& look)
1133
        {
1333
        {
1134
            out << YAML::Key << "lamp";
1334
            if(node.Tag() != "Look")
1135
            out << YAML::Value << YAML::Flow << t->getLamp();
1335
                return;
1336
            
1337
            std::string key, stringval;
1338
            
1339
            for (Iterator iter = node.begin();
1340
                 iter != node.end();
1341
                 ++iter)
1342
            {
1343
                const YAML::Node& first = get_first(iter);
1344
                const YAML::Node& second = get_second(iter);
1345
                
1346
                load(first, key);
1347
                
1348
                if (second.Type() == YAML::NodeType::Null) continue;
1349
                
1350
                if(key == "name")
1351
                {
1352
                    load(second, stringval);
1353
                    look->setName(stringval.c_str());
1354
                }
1355
                else if(key == "process_space")
1356
                {
1357
                    load(second, stringval);
1358
                    look->setProcessSpace(stringval.c_str());
1359
                }
1360
                else if(key == "transform")
1361
                {
1362
                    TransformRcPtr val;
1363
                    load(second, val);
1364
                    look->setTransform(val);
1365
                }
1366
                else if(key == "inverse_transform")
1367
                {
1368
                    TransformRcPtr val;
1369
                    load(second, val);
1370
                    look->setInverseTransform(val);
1371
                }
1372
                else
1373
                {
1374
                    LogUnknownKeyWarning(node.Tag(), first);
1375
                }
1376
            }
1136
        }
1377
        }
1137
        if(strcmp(t->getOutputCamera(), "") != 0)
1378
        
1379
        inline void save(YAML::Emitter& out, ConstLookRcPtr look)
1138
        {
1380
        {
1139
            out << YAML::Key << "output_camera";
1381
            out << YAML::VerbatimTag("Look");
1140
            out << YAML::Value << YAML::Flow << t->getOutputCamera();
1382
            out << YAML::BeginMap;
1383
            out << YAML::Key << "name" << YAML::Value << look->getName();
1384
            out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
1385
            
1386
            if(look->getTransform())
1387
            {
1388
                out << YAML::Key << "transform";
1389
                out << YAML::Value;
1390
                save(out, look->getTransform());
1391
            }
1392
            
1393
            if(look->getInverseTransform())
1394
            {
1395
                out << YAML::Key << "inverse_transform";
1396
                out << YAML::Value;
1397
                save(out, look->getInverseTransform());
1398
            }
1399
            
1400
            out << YAML::EndMap;
1401
            out << YAML::Newline;
1141
        }
1402
        }
1142
        if(strcmp(t->getDisplay(), "") != 0)
1403
        
1404
        // Config
1405
        
1406
        inline void load(const YAML::Node& node, ConfigRcPtr& c, const char* filename)
1143
        {
1407
        {
1144
            out << YAML::Key << "display";
1408
            
1145
            out << YAML::Value << YAML::Flow << t->getDisplay();
1409
            // check profile version
1410
            int profile_version = 0;
1411
#ifdef OLDYAML
1412
            if(node.FindValue("ocio_profile_version") == NULL)
1413
#else
1414
            if(node["ocio_profile_version"] == NULL)
1415
#endif
1416
            {
1417
                std::ostringstream os;
1418
                os << "The specified file ";
1419
                os << "does not appear to be an OCIO configuration.";
1420
                throw Exception (os.str().c_str());
1421
            }
1422
            
1423
            load(node["ocio_profile_version"], profile_version);
1424
            if(profile_version > 1)
1425
            {
1426
                std::ostringstream os;
1427
                os << "This .ocio config ";
1428
                if(filename && *filename)
1429
                {
1430
                    os << " '" << filename << "' ";
1431
                }
1432
                os << "is version " << profile_version << ". ";
1433
                os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
1434
                os << "is not known to be able to load this profile. ";
1435
                os << "An attempt will be made, but there are no guarantees that the ";
1436
                os << "results will be accurate. Continue at your own risk.";
1437
                LogWarning(os.str());
1438
            }
1439
            
1440
            std::string key, stringval;
1441
            bool boolval = false;
1442
            EnvironmentMode mode = ENV_ENVIRONMENT_LOAD_ALL;
1443
            
1444
            for (Iterator iter = node.begin();
1445
                 iter != node.end();
1446
                 ++iter)
1447
            {
1448
                const YAML::Node& first = get_first(iter);
1449
                const YAML::Node& second = get_second(iter);
1450
                
1451
                load(first, key);
1452
                
1453
                if (second.Type() == YAML::NodeType::Null) continue;
1454
                
1455
                if(key == "ocio_profile_version") { } // Already handled above.
1456
                else if(key == "environment")
1457
                {
1458
                    mode = ENV_ENVIRONMENT_LOAD_PREDEFINED;
1459
                    if(second.Type() != YAML::NodeType::Map)
1460
                    {
1461
                        std::ostringstream os;
1462
                        os << "'environment' field needs to be a (name: key) map.";
1463
                        throw Exception(os.str().c_str());
1464
                    }
1465
                    for (Iterator it = second.begin();
1466
                         it != second.end();
1467
                         ++it)
1468
                    {
1469
                        std::string k, v;
1470
                        load(get_first(it), k);
1471
                        load(get_second(it), v);
1472
                        c->addEnvironmentVar(k.c_str(), v.c_str());
1473
                    }
1474
                }
1475
                else if(key == "search_path" || key == "resource_path")
1476
                {
1477
                    load(second, stringval);
1478
                    c->setSearchPath(stringval.c_str());
1479
                }
1480
                else if(key == "strictparsing")
1481
                {
1482
                    load(second, boolval);
1483
                    c->setStrictParsingEnabled(boolval);
1484
                }
1485
                else if(key == "description")
1486
                {
1487
                    load(second, stringval);
1488
                    c->setDescription(stringval.c_str());
1489
                }
1490
                else if(key == "luma")
1491
                {
1492
                    std::vector<float> val;
1493
                    load(second, val);
1494
                    if(val.size() != 3)
1495
                    {
1496
                        std::ostringstream os;
1497
                        os << "'luma' field must be 3 ";
1498
                        os << "floats. Found '" << val.size() << "'.";
1499
                        throw Exception(os.str().c_str());
1500
                    }
1501
                    c->setDefaultLumaCoefs(&val[0]);
1502
                }
1503
                else if(key == "roles")
1504
                {
1505
                    if(second.Type() != YAML::NodeType::Map)
1506
                    {
1507
                        std::ostringstream os;
1508
                        os << "'roles' field needs to be a (name: key) map.";
1509
                        throw Exception(os.str().c_str());
1510
                    }
1511
                    for (Iterator it = second.begin();
1512
                         it != second.end();
1513
                         ++it)
1514
                    {
1515
                        std::string k, v;
1516
                        load(get_first(it), k);
1517
                        load(get_second(it), v);
1518
                        c->setRole(k.c_str(), v.c_str());
1519
                    }
1520
                }
1521
                else if(key == "displays")
1522
                {
1523
                    if(second.Type() != YAML::NodeType::Map)
1524
                    {
1525
                        std::ostringstream os;
1526
                        os << "'displays' field needs to be a (name: key) map.";
1527
                        throw Exception(os.str().c_str());
1528
                    }
1529
                    for (Iterator it = second.begin();
1530
                         it != second.end();
1531
                         ++it)
1532
                    {
1533
                        std::string display;
1534
                        load(get_first(it), display);
1535
                        const YAML::Node& dsecond = get_second(it);
1536
                        for(unsigned i = 0; i < dsecond.size(); ++i)
1537
                        {
1538
                            View view;
1539
                            load(dsecond[i], view);
1540
                            c->addDisplay(display.c_str(), view.name.c_str(),
1541
                                          view.colorspace.c_str(), view.looks.c_str());
1542
                        }
1543
                    }
1544
                }
1545
                else if(key == "active_displays")
1546
                {
1547
                    std::vector<std::string> display;
1548
                    load(second, display);
1549
                    const char* displays = JoinStringEnvStyle(display).c_str();
1550
                    c->setActiveDisplays(displays);
1551
                }
1552
                else if(key == "active_views")
1553
                {
1554
                    std::vector<std::string> view;
1555
                    load(second, view);
1556
                    const char* views = JoinStringEnvStyle(view).c_str();
1557
                    c->setActiveViews(views);
1558
                }
1559
                else if(key == "colorspaces")
1560
                {
1561
                    if(second.Type() != YAML::NodeType::Sequence)
1562
                    {
1563
                        std::ostringstream os;
1564
                        os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
1565
                        throw Exception(os.str().c_str());
1566
                    }
1567
                    for(unsigned i = 0; i < second.size(); ++i)
1568
                    {
1569
                        if(second[i].Tag() == "ColorSpace")
1570
                        {
1571
                            ColorSpaceRcPtr cs = ColorSpace::Create();
1572
                            load(second[i], cs);
1573
                            for(int ii = 0; ii < c->getNumColorSpaces(); ++ii)
1574
                            {
1575
                                if(strcmp(c->getColorSpaceNameByIndex(ii), cs->getName()) == 0)
1576
                                {
1577
                                    std::ostringstream os;
1578
                                    os << "Colorspace with name '" << cs->getName() << "' already defined.";
1579
                                    throw Exception(os.str().c_str());
1580
                                }
1581
                            }
1582
                            c->addColorSpace(cs);
1583
                        }
1584
                        else
1585
                        {
1586
                            std::ostringstream os;
1587
                            os << "Unknown element found in colorspaces:";
1588
                            os << second[i].Tag() << ". Only ColorSpace(s)";
1589
                            os << " currently handled.";
1590
                            LogWarning(os.str());
1591
                        }
1592
                    }
1593
                }
1594
                else if(key == "looks")
1595
                {
1596
                    if(second.Type() != YAML::NodeType::Sequence)
1597
                    {
1598
                        std::ostringstream os;
1599
                        os << "'looks' field needs to be a (- !<Look>) list.";
1600
                        throw Exception(os.str().c_str());
1601
                    }
1602
                    
1603
                    for(unsigned i = 0; i < second.size(); ++i)
1604
                    {
1605
                        if(second[i].Tag() == "Look")
1606
                        {
1607
                            LookRcPtr look = Look::Create();
1608
                            load(second[i], look);
1609
                            c->addLook(look);
1610
                        }
1611
                        else
1612
                        {
1613
                            std::ostringstream os;
1614
                            os << "Unknown element found in looks:";
1615
                            os << second[i].Tag() << ". Only Look(s)";
1616
                            os << " currently handled.";
1617
                            LogWarning(os.str());
1618
                        }
1619
                    }
1620
                }
1621
                else
1622
                {
1623
                    LogUnknownKeyWarning("profile", first);
1624
                }
1625
            }
1626
            
1627
            if(filename)
1628
            {
1629
                std::string realfilename = pystring::os::path::abspath(filename);
1630
                std::string configrootdir = pystring::os::path::dirname(realfilename);
1631
                c->setWorkingDir(configrootdir.c_str());
1632
            }
1633
            
1634
            c->setEnvironmentMode(mode);
1635
            c->loadEnvironment();
1636
            
1637
            if(mode == ENV_ENVIRONMENT_LOAD_ALL)
1638
            {
1639
                std::ostringstream os;
1640
                os << "This .ocio config ";
1641
                if(filename && *filename)
1642
                {
1643
                    os << " '" << filename << "' ";
1644
                }
1645
                os << "has no environment section defined. The default behaviour is to ";
1646
                os << "load all environment variables (" << c->getNumEnvironmentVars() << ")";
1647
                os << ", which reduces the efficiency of OCIO's caching. Considering ";
1648
                os << "predefining the environment variables used.";
1649
                LogDebug(os.str());
1650
            }
1651
            
1146
        }
1652
        }
1147
        if(strcmp(t->getCubeInput(), "") != 0)
1653
        
1654
        inline void save(YAML::Emitter& out, const Config* c)
1148
        {
1655
        {
1149
            out << YAML::Key << "cube_input";
1656
            out << YAML::Block;
1150
            out << YAML::Value << YAML::Flow << t->getCubeInput();
1657
            out << YAML::BeginMap;
1658
            out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
1659
            out << YAML::Newline;
1660
#ifndef OLDYAML
1661
            out << YAML::Newline;
1662
#endif
1663
            
1664
            if(c->getNumEnvironmentVars() > 0)
1665
            {
1666
                out << YAML::Key << "environment";
1667
                out << YAML::Value << YAML::BeginMap;
1668
                for(unsigned i = 0; i < c->getNumEnvironmentVars(); ++i)
1669
                {   
1670
                    const char* name = c->getEnvironmentVarNameByIndex(i);
1671
                    out << YAML::Key << name;
1672
                    out << YAML::Value << c->getEnvironmentVarDefault(name);
1673
                }
1674
                out << YAML::EndMap;
1675
                out << YAML::Newline;
1676
            }
1677
            out << YAML::Key << "search_path" << YAML::Value << c->getSearchPath();
1678
            out << YAML::Key << "strictparsing" << YAML::Value << c->isStrictParsingEnabled();
1679
            
1680
            std::vector<float> luma(3, 0.f);
1681
            c->getDefaultLumaCoefs(&luma[0]);
1682
            out << YAML::Key << "luma" << YAML::Value << YAML::Flow << luma;
1683
            
1684
            if(c->getDescription() != NULL && strlen(c->getDescription()) > 0)
1685
            {
1686
                out << YAML::Newline;
1687
                out << YAML::Key << "description";
1688
                out << YAML::Value << c->getDescription();
1689
                out << YAML::Newline;
1690
            }
1691
            
1692
            // Roles
1693
            out << YAML::Newline;
1694
#ifndef OLDYAML
1695
            out << YAML::Newline;
1696
#endif
1697
            out << YAML::Key << "roles";
1698
            out << YAML::Value << YAML::BeginMap;
1699
            for(unsigned i = 0; i < c->getNumRoles(); ++i)
1700
            {
1701
                const char* role = c->getRoleName(i);
1702
                out << YAML::Key << role;
1703
                out << YAML::Value << c->getColorSpace(role)->getName();
1704
            }
1705
            out << YAML::EndMap;
1706
#ifndef OLDYAML
1707
            out << YAML::Newline;
1708
#endif
1709
            
1710
            // Displays
1711
            out << YAML::Newline;
1712
            out << YAML::Key << "displays";
1713
            out << YAML::Value << YAML::BeginMap;
1714
            for(unsigned i = 0; i < c->getNumDisplays(); ++i)
1715
            {
1716
                const char* display = c->getDisplay(i);
1717
                out << YAML::Key << display;
1718
                out << YAML::Value << YAML::BeginSeq;
1719
                for(unsigned v = 0; v < c->getNumViews(display); ++v)
1720
                {
1721
                    View dview;
1722
                    dview.name = c->getView(display, v);
1723
                    dview.colorspace = c->getDisplayColorSpaceName(display, dview.name.c_str());
1724
                    if(c->getDisplayLooks(display, dview.name.c_str()) != NULL)
1725
                        dview.looks = c->getDisplayLooks(display, dview.name.c_str());
1726
                    save(out, dview);
1727
                
1728
                }
1729
                out << YAML::EndSeq;
1730
            }
1731
            out << YAML::EndMap;
1732
            
1733
#ifndef OLDYAML
1734
            out << YAML::Newline;
1735
#endif
1736
            out << YAML::Newline;
1737
            out << YAML::Key << "active_displays";
1738
            std::vector<std::string> active_displays;
1739
            if(c->getActiveDisplays() != NULL && strlen(c->getActiveDisplays()) > 0)
1740
                SplitStringEnvStyle(active_displays, c->getActiveDisplays());
1741
            out << YAML::Value << YAML::Flow << active_displays;
1742
            out << YAML::Key << "active_views";
1743
            std::vector<std::string> active_views;
1744
            if(c->getActiveViews() != NULL && strlen(c->getActiveViews()) > 0)
1745
                SplitStringEnvStyle(active_views, c->getActiveViews());
1746
            out << YAML::Value << YAML::Flow << active_views;
1747
#ifndef OLDYAML
1748
            out << YAML::Newline;
1749
#endif
1750
            
1751
            // Looks
1752
            if(c->getNumLooks() > 0)
1753
            {
1754
                out << YAML::Newline;
1755
                out << YAML::Key << "looks";
1756
                out << YAML::Value << YAML::BeginSeq;
1757
                for(unsigned i = 0; i < c->getNumLooks(); ++i)
1758
                {
1759
                    const char* name = c->getLookNameByIndex(i);
1760
                    save(out, c->getLook(name));
1761
                }
1762
                out << YAML::EndSeq;
1763
                out << YAML::Newline;
1764
            }
1765
            
1766
            // ColorSpaces
1767
            {
1768
                out << YAML::Newline;
1769
                out << YAML::Key << "colorspaces";
1770
                out << YAML::Value << YAML::BeginSeq;
1771
                for(unsigned i = 0; i < c->getNumColorSpaces(); ++i)
1772
                {
1773
                    const char* name = c->getColorSpaceNameByIndex(i);
1774
                    save(out, c->getColorSpace(name));
1775
                }
1776
                out << YAML::EndSeq;
1777
            }
1778
            
1779
            out << YAML::EndMap;
1151
        }
1780
        }
1152
        
1781
        
1153
        EmitBaseTransformKeyValues(out, t);
1154
        
1155
        out << YAML::EndMap;
1156
        return out;
1157
    }
1782
    }
1158
    
1783
    
1159
    ///////////////////////////////////////////////////////////////////////////
1784
    ///////////////////////////////////////////////////////////////////////////
1160
    //  Enums
1161
    
1162
    YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth) {
1163
        out << BitDepthToString(depth);
1164
        return out;
1165
    }
1166
    
1167
    void operator >> (const YAML::Node& node, BitDepth& depth) {
1168
        std::string str;
1169
        node.Read<std::string>(str);
1170
        depth = BitDepthFromString(str.c_str());
1171
    }
1172
    
1173
    YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc) {
1174
        out << AllocationToString(alloc);
1175
        return out;
1176
    }
1177
    
1178
    void operator >> (const YAML::Node& node, Allocation& alloc) {
1179
        std::string str;
1180
        node.Read<std::string>(str);
1181
        alloc = AllocationFromString(str.c_str());
1182
    }
1183
    
1184
    YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir) {
1185
        out << ColorSpaceDirectionToString(dir);
1186
        return out;
1187
    }
1188
    
1785
    
1189
    void operator >> (const YAML::Node& node, ColorSpaceDirection& dir) {
1786
    void OCIOYaml::open(std::istream& istream, ConfigRcPtr& c, const char* filename) const
1190
        std::string str;
1787
    {
1191
        node.Read<std::string>(str);
1788
        try
1192
        dir = ColorSpaceDirectionFromString(str.c_str());
1789
        {
1193
    }
1790
#ifdef OLDYAML
1194
    
1791
            YAML::Parser parser(istream);
1195
    YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir) {
1792
            YAML::Node node;
1196
        out << TransformDirectionToString(dir);
1793
            parser.GetNextDocument(node);
1197
        return out;
1794
#else
1198
    }
1795
            YAML::Node node = YAML::Load(istream);
1199
    
1796
#endif
1200
    void operator >> (const YAML::Node& node, TransformDirection& dir) {
1797
            load(node, c, filename);
1201
        std::string str;
1798
        }
1202
        node.Read<std::string>(str);
1799
        catch(const std::exception & e)
1203
        dir = TransformDirectionFromString(str.c_str());
1800
        {
1204
    }
1801
            std::ostringstream os;
1205
    
1802
            os << "Error: Loading the OCIO profile ";
1206
    YAML::Emitter& operator << (YAML::Emitter& out, Interpolation interp) {
1803
            if(filename) os << "'" << filename << "' ";
1207
        out << InterpolationToString(interp);
1804
            os << "failed. " << e.what();
1208
        return out;
1805
            throw Exception(os.str().c_str());
1806
        }
1209
    }
1807
    }
1210
    
1808
    
1211
    void operator >> (const YAML::Node& node, Interpolation& interp) {
1809
    void OCIOYaml::write(std::ostream& ostream, const Config* c) const
1212
        std::string str;
1810
    {
1213
        node.Read<std::string>(str);
1811
        YAML::Emitter out;
1214
        interp = InterpolationFromString(str.c_str());
1812
        save(out, c);
1813
        ostream << out.c_str();
1215
    }
1814
    }
1216
    
1815
    
1217
}
1816
}
(-)a/src/core/OCIOYaml.h (-85 / +6 lines)
Lines 28-124 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Link Here
28
28
29
#include <OpenColorIO/OpenColorIO.h>
29
#include <OpenColorIO/OpenColorIO.h>
30
30
31
#include "Platform.h"
32
33
#ifndef WINDOWS
34
35
// fwd declare yaml-cpp visibility
36
#pragma GCC visibility push(hidden)
37
namespace YAML {
38
    class Exception;
39
    class BadDereference;
40
    class RepresentationException;
41
    class EmitterException;
42
    class ParserException;
43
    class InvalidScalar;
44
    class KeyNotFound;
45
    template <typename T> class TypedKeyNotFound;
46
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
47
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
48
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
49
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
50
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
51
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
52
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
53
    
54
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
55
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
56
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
57
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
58
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
59
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
60
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
61
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
62
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
63
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
64
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
65
    template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
66
}
67
#pragma GCC visibility pop
68
69
#endif 
70
71
#include <yaml-cpp/yaml.h>
72
73
#ifndef INCLUDED_OCIO_YAML_H
31
#ifndef INCLUDED_OCIO_YAML_H
74
#define INCLUDED_OCIO_YAML_H
32
#define INCLUDED_OCIO_YAML_H
75
33
76
OCIO_NAMESPACE_ENTER
34
OCIO_NAMESPACE_ENTER
77
{
35
{
78
    
36
    
79
    // Core
37
    class OCIOYaml
80
    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs);
38
    {
81
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs);
39
    public:
82
    OCIOHIDDEN void operator >> (const YAML::Node& node, GroupTransformRcPtr& t);
40
        void open(std::istream& istream, ConfigRcPtr& c, const char* filename = NULL) const;
83
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t);
41
        void write(std::ostream& ostream, const Config* c) const;
84
    OCIOHIDDEN void operator >> (const YAML::Node& node, TransformRcPtr& t);
42
    };
85
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t);
86
    OCIOHIDDEN void operator >> (const YAML::Node& node, LookRcPtr& cs);
87
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr cs);
88
    
89
    // Transforms
90
    OCIOHIDDEN void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t);
91
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t);
92
    OCIOHIDDEN void operator >> (const YAML::Node& node, CDLTransformRcPtr& t);
93
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t);
94
    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t);
95
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t);
96
    OCIOHIDDEN void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t);
97
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t);
98
    OCIOHIDDEN void operator >> (const YAML::Node& node, FileTransformRcPtr& t);
99
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t);
100
    OCIOHIDDEN void operator >> (const YAML::Node& node, LogTransformRcPtr& t);
101
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t);
102
    OCIOHIDDEN void operator >> (const YAML::Node& node, LookTransformRcPtr& t);
103
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t);
104
    OCIOHIDDEN void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t);
105
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t);
106
    OCIOHIDDEN void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t);
107
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t);
108
    
109
    // Enums
110
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth);
111
    OCIOHIDDEN void operator >> (const YAML::Node& node, BitDepth& depth);
112
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc);
113
    OCIOHIDDEN void operator >> (const YAML::Node& node, Allocation& alloc);
114
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir);
115
    OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceDirection& dir);
116
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir);
117
    OCIOHIDDEN void operator >> (const YAML::Node& node, TransformDirection& dir);
118
    OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, Interpolation iterp);
119
    OCIOHIDDEN void operator >> (const YAML::Node& node, Interpolation& iterp);
120
    
43
    
121
    void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag);
122
}
44
}
123
OCIO_NAMESPACE_EXIT
45
OCIO_NAMESPACE_EXIT
124
46
125
- 

Return to bug 471366