summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo F. Vescovi <mfv.debian@gmail.com>2013-08-20 09:53:19 +0100
committerMatteo F. Vescovi <mfv.debian@gmail.com>2013-08-20 09:53:19 +0100
commit66e5d9e2915733247bca47d077414ec2594aedad (patch)
treef4070a31bf015e159dadd34378cda703d8f6edea
opencolorio (1.0.8~dfsg0-2) unstable; urgency=low
* debian/rules: get-orig-source stuff added * debian/rules: useless dh addon removed * debian/rules: License.txt duplicate removed * debian/rules: SSE optimization disabled (Closes: #719174) * debian/libopencolorio1.symbols: file removed (Closes: #719175) # imported from the archive
-rw-r--r--.gitignore6
-rw-r--r--.pc/.quilt_patches1
-rw-r--r--.pc/.quilt_series1
-rw-r--r--.pc/.version1
-rw-r--r--.pc/0001-Fix_built-in_documentation_dependencies.patch/CMakeLists.txt406
-rw-r--r--.pc/0001-Fix_built-in_documentation_dependencies.patch/docs/CMakeLists.txt131
-rw-r--r--.pc/applied-patches1
-rw-r--r--.travis.yml23
-rw-r--r--CMakeLists.txt403
-rw-r--r--ChangeLog301
-rw-r--r--INSTALL1
-rw-r--r--LICENSE251
-rw-r--r--README20
-rw-r--r--debian/changelog15
-rw-r--r--debian/compat1
-rw-r--r--debian/control171
-rw-r--r--debian/copyright77
-rw-r--r--debian/docs1
-rw-r--r--debian/examples1
-rw-r--r--debian/libopencolorio-dev.install3
-rw-r--r--debian/libopencolorio1.install1
-rw-r--r--debian/manpages/ociobakelut.199
-rw-r--r--debian/manpages/ociocheck.135
-rw-r--r--debian/manpages/ocioconvert.128
-rw-r--r--debian/manpages/ociolutimage.143
-rw-r--r--debian/opencolorio-doc.doc-base11
-rw-r--r--debian/opencolorio-doc.install1
-rw-r--r--debian/opencolorio-doc.links2
-rw-r--r--debian/opencolorio-tools.install1
-rw-r--r--debian/opencolorio-tools.manpages1
-rw-r--r--debian/patches/0001-Fix_built-in_documentation_dependencies.patch116
-rw-r--r--debian/patches/series1
-rw-r--r--debian/python-pyopencolorio.install2
-rw-r--r--debian/repack.local2
-rwxr-xr-xdebian/repack.sh161
-rw-r--r--debian/repack.stub82
-rwxr-xr-xdebian/rules40
-rw-r--r--debian/source/format1
-rw-r--r--debian/watch3
-rw-r--r--docs/CMakeLists.txt73
-rwxr-xr-xdocs/ChangeLog.rst6
-rw-r--r--docs/CompatibleSoftware.rst268
-rw-r--r--docs/FAQ.rst141
-rwxr-xr-xdocs/License.rst5
-rw-r--r--docs/conf.py.in110
-rw-r--r--docs/configurations/allocation_vars.rst119
-rw-r--r--docs/configurations/images/spi-vfx/gn10_to_linear_light.jpegbin0 -> 34921 bytes
-rw-r--r--docs/configurations/images/spi-vfx/gnf_to_linear_light.jpegbin0 -> 34769 bytes
-rw-r--r--docs/configurations/images/spi-vfx/lg10_to_linear_light.jpegbin0 -> 37622 bytes
-rw-r--r--docs/configurations/images/spi-vfx/lg8_to_vd8.jpegbin0 -> 36153 bytes
-rw-r--r--docs/configurations/images/spi-vfx/lgf_to_linear_light.jpegbin0 -> 37440 bytes
-rw-r--r--docs/configurations/index.rst22
-rw-r--r--docs/configurations/nuke_default.rst19
-rw-r--r--docs/configurations/spi_anim.rst4
-rw-r--r--docs/configurations/spi_pipeline.rst74
-rw-r--r--docs/configurations/spi_vfx.rst186
-rw-r--r--docs/developers/api/index.rst6
-rw-r--r--docs/developers/bindings/PythonAPI.rst147
-rw-r--r--docs/developers/bindings/PythonTransforms.rst132
-rw-r--r--docs/developers/bindings/PythonTypes.rst9
-rw-r--r--docs/developers/coding_guidelines.rst109
-rw-r--r--docs/developers/getting_started.rst47
-rw-r--r--docs/developers/index.rst45
-rw-r--r--docs/developers/internal_architecture.rst287
-rw-r--r--docs/developers/issues.rst4
-rw-r--r--docs/developers/submitting_changes.rst14
-rw-r--r--docs/developers/usage_examples.rst357
-rw-r--r--docs/downloads.rst41
-rw-r--r--docs/index.rst77
-rw-r--r--docs/installation.rst234
-rw-r--r--docs/ociotheme/layout.html74
-rw-r--r--docs/ociotheme/page.html29
-rw-r--r--docs/ociotheme/searchbox.html12
-rw-r--r--docs/ociotheme/static/alert_info_32.pngbin0 -> 1168 bytes
-rw-r--r--docs/ociotheme/static/alert_warning_32.pngbin0 -> 1060 bytes
-rw-r--r--docs/ociotheme/static/bg-page.pngbin0 -> 164 bytes
-rw-r--r--docs/ociotheme/static/bullet_orange.pngbin0 -> 182 bytes
-rw-r--r--docs/ociotheme/static/clo_res19_lm10.0101.jpgbin0 -> 12478 bytes
-rw-r--r--docs/ociotheme/static/clo_res19_lnf.0101.jpgbin0 -> 13461 bytes
-rw-r--r--docs/ociotheme/static/clo_res19_vd16.0101.jpgbin0 -> 15721 bytes
-rw-r--r--docs/ociotheme/static/ocio.css_t469
-rw-r--r--docs/ociotheme/theme.conf13
-rw-r--r--docs/userguide/baking_luts.rst359
-rw-r--r--docs/userguide/contexts.rst361
-rw-r--r--docs/userguide/images/ps_icc/psicc_itworks.pngbin0 -> 272150 bytes
-rw-r--r--docs/userguide/images/ps_icc/psicc_open_current_profile.pngbin0 -> 45999 bytes
-rw-r--r--docs/userguide/images/ps_icc/psicc_proof_setup.pngbin0 -> 11632 bytes
-rw-r--r--docs/userguide/images/ps_icc/psicc_reveal_profile.pngbin0 -> 30846 bytes
-rw-r--r--docs/userguide/images/ps_icc/psicc_select_profile.pngbin0 -> 28233 bytes
-rw-r--r--docs/userguide/index.rst15
-rw-r--r--docs/userguide/looks.rst139
-rw-r--r--docs/userguide/tool_overview.rst168
-rw-r--r--export/OpenColorIO/OpenColorABI.h.in89
-rw-r--r--export/OpenColorIO/OpenColorIO.h1238
-rw-r--r--export/OpenColorIO/OpenColorTransforms.h812
-rw-r--r--export/OpenColorIO/OpenColorTypes.h397
-rw-r--r--export/PyOpenColorIO/PyOpenColorIO.h98
-rw-r--r--export/pkgconfig/OpenColorIO.pc.in10
-rw-r--r--share/cmake/FindNuke.cmake96
-rw-r--r--share/cmake/FindTinyXML.cmake59
-rw-r--r--share/cmake/FindTruelight.cmake87
-rw-r--r--share/cmake/OCIOMacros.cmake339
-rw-r--r--share/cmake/ParseArguments.cmake57
-rw-r--r--share/cmake/TestForDDImageVersion.cxx14
-rw-r--r--share/cmake/andriod-toolchain.cmake61
-rw-r--r--share/cmake/iPhone-armv6-toolchain.cmake42
-rw-r--r--share/cmake/iPhone-toolchain.cmake42
-rw-r--r--share/cmake/iPhoneSimulator-toolchain.cmake43
-rw-r--r--share/nuke/examples/colorlookup_to_spi1d.py24
-rw-r--r--share/nuke/examples/ocio_to_colorlookup_all.py36
-rw-r--r--share/nuke/examples/ocio_to_colorlookup_rgb.py29
-rw-r--r--share/nuke/init.py26
-rw-r--r--share/nuke/menu.py26
-rw-r--r--share/nuke/ocio_icon.pngbin0 -> 2507 bytes
-rw-r--r--share/nuke/ocionuke/__init__.py0
-rw-r--r--share/nuke/ocionuke/cdl.py269
-rw-r--r--share/nuke/ocionuke/viewer.py50
-rw-r--r--share/ocio/setup_ocio.sh.in14
-rwxr-xr-xshare/sphinx/ExtractRstFromSourceCPP.py324
-rwxr-xr-xshare/sphinx/ExtractRstFromSourceSimple.py110
-rw-r--r--src/aftereffects/DrawbotBot.cpp239
-rw-r--r--src/aftereffects/DrawbotBot.h89
-rwxr-xr-xsrc/aftereffects/OpenColorIO_AE.cpp1133
-rwxr-xr-xsrc/aftereffects/OpenColorIO_AE.h227
-rw-r--r--src/aftereffects/OpenColorIO_AE_ArbData.cpp408
-rw-r--r--src/aftereffects/OpenColorIO_AE_Context.cpp1051
-rw-r--r--src/aftereffects/OpenColorIO_AE_Context.h153
-rw-r--r--src/aftereffects/OpenColorIO_AE_Dialogs.h60
-rw-r--r--src/aftereffects/OpenColorIO_AE_GL.h61
-rw-r--r--src/aftereffects/OpenColorIO_AE_PiPL.r102
-rw-r--r--src/aftereffects/OpenColorIO_AE_UI.cpp1229
-rwxr-xr-xsrc/aftereffects/mac/OpenColorIO_AE.plugin-Info.plist24
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_Dialogs_Cocoa.mm237
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_GL_Cocoa.mm178
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_Menu.h45
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_Menu.m114
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser.xib494
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.h46
-rw-r--r--src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.m195
-rw-r--r--src/aftereffects/vc/vc9/OpenColorABI.h100
-rw-r--r--src/aftereffects/vc/vc9/OpenColorIO.vcproj667
-rw-r--r--src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.sln57
-rw-r--r--src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.vcproj448
-rw-r--r--src/aftereffects/vc/vc9/ext/glew.vcproj319
-rw-r--r--src/aftereffects/vc/vc9/ext/lcms.vcproj407
-rw-r--r--src/aftereffects/vc/vc9/ext/tinyxml.vcproj323
-rw-r--r--src/aftereffects/vc/vc9/ext/yaml.vcproj603
-rw-r--r--src/aftereffects/win/OpenColorIO.rc99
-rw-r--r--src/aftereffects/win/OpenColorIO_AE_Dialogs_Win.cpp564
-rw-r--r--src/aftereffects/win/OpenColorIO_AE_GL_Win.cpp212
-rw-r--r--src/aftereffects/win/resource.h17
-rw-r--r--src/aftereffects/xcode/OpenColorABI.h100
-rw-r--r--src/aftereffects/xcode/OpenColorIO.xcodeproj/project.pbxproj589
-rwxr-xr-xsrc/aftereffects/xcode/aftereffects/OpenColorIO_AE.xcodeproj/project.pbxproj509
-rw-r--r--src/aftereffects/xcode/ext/lcms.xcodeproj/project.pbxproj343
-rw-r--r--src/aftereffects/xcode/ext/tinyxml.xcodeproj/project.pbxproj248
-rw-r--r--src/aftereffects/xcode/ext/yaml.xcodeproj/project.pbxproj571
-rw-r--r--src/apps/ociobakelut/CMakeLists.txt46
-rw-r--r--src/apps/ociobakelut/main.cpp537
-rw-r--r--src/apps/ociobakelut/ocioicc.cpp251
-rw-r--r--src/apps/ociobakelut/ocioicc.h71
-rw-r--r--src/apps/ociocheck/CMakeLists.txt17
-rw-r--r--src/apps/ociocheck/main.cpp301
-rw-r--r--src/apps/ocioconvert/CMakeLists.txt16
-rw-r--r--src/apps/ocioconvert/main.cpp309
-rw-r--r--src/apps/ociodisplay/CMakeLists.txt11
-rw-r--r--src/apps/ociodisplay/main.cpp734
-rw-r--r--src/apps/ociolutimage/CMakeLists.txt16
-rw-r--r--src/apps/ociolutimage/main.cpp398
-rw-r--r--src/apps/share/argparse.cpp528
-rw-r--r--src/apps/share/argparse.h181
-rw-r--r--src/apps/share/pystring.cpp1658
-rw-r--r--src/apps/share/pystring.h438
-rw-r--r--src/apps/share/strutil.cpp86
-rw-r--r--src/apps/share/strutil.h83
-rw-r--r--src/core/AllocationOp.cpp128
-rw-r--r--src/core/AllocationOp.h45
-rw-r--r--src/core/AllocationTransform.cpp182
-rw-r--r--src/core/Baker.cpp297
-rw-r--r--src/core/CDLTransform.cpp776
-rw-r--r--src/core/CDLTransform.h53
-rw-r--r--src/core/CMakeLists.txt93
-rw-r--r--src/core/Caching.cpp47
-rw-r--r--src/core/ColorSpace.cpp270
-rw-r--r--src/core/ColorSpaceTransform.cpp246
-rw-r--r--src/core/Config.cpp2223
-rw-r--r--src/core/Context.cpp364
-rw-r--r--src/core/DisplayTransform.cpp410
-rw-r--r--src/core/Exception.cpp74
-rw-r--r--src/core/ExponentOps.cpp372
-rw-r--r--src/core/ExponentOps.h50
-rw-r--r--src/core/ExponentTransform.cpp151
-rw-r--r--src/core/FileFormat3DL.cpp638
-rw-r--r--src/core/FileFormatCC.cpp151
-rw-r--r--src/core/FileFormatCCC.cpp195
-rw-r--r--src/core/FileFormatCSP.cpp1112
-rw-r--r--src/core/FileFormatHDL.cpp1481
-rw-r--r--src/core/FileFormatIridasCube.cpp398
-rw-r--r--src/core/FileFormatIridasItx.cpp336
-rw-r--r--src/core/FileFormatIridasLook.cpp1356
-rw-r--r--src/core/FileFormatPandora.cpp286
-rw-r--r--src/core/FileFormatSpi1D.cpp261
-rw-r--r--src/core/FileFormatSpi3D.cpp209
-rw-r--r--src/core/FileFormatSpiMtx.cpp195
-rw-r--r--src/core/FileFormatTruelight.cpp620
-rw-r--r--src/core/FileFormatVF.cpp297
-rw-r--r--src/core/FileTransform.cpp579
-rw-r--r--src/core/FileTransform.h156
-rw-r--r--src/core/GpuShaderDesc.cpp131
-rw-r--r--src/core/GpuShaderUtils.cpp193
-rw-r--r--src/core/GpuShaderUtils.h58
-rw-r--r--src/core/GroupTransform.cpp196
-rw-r--r--src/core/HashUtils.cpp71
-rw-r--r--src/core/HashUtils.h48
-rw-r--r--src/core/ImageDesc.cpp392
-rw-r--r--src/core/ImagePacking.cpp407
-rw-r--r--src/core/ImagePacking.h71
-rw-r--r--src/core/LogOps.cpp499
-rw-r--r--src/core/LogOps.h57
-rw-r--r--src/core/LogTransform.cpp157
-rw-r--r--src/core/Logging.cpp156
-rw-r--r--src/core/Logging.h47
-rw-r--r--src/core/Look.cpp163
-rw-r--r--src/core/LookParse.cpp309
-rw-r--r--src/core/LookParse.h79
-rw-r--r--src/core/LookTransform.cpp405
-rw-r--r--src/core/Lut1DOp.cpp1038
-rw-r--r--src/core/Lut1DOp.h107
-rw-r--r--src/core/Lut3DOp.cpp982
-rw-r--r--src/core/Lut3DOp.h114
-rw-r--r--src/core/MathUtils.cpp603
-rw-r--r--src/core/MathUtils.h186
-rw-r--r--src/core/MatrixOps.cpp788
-rw-r--r--src/core/MatrixOps.h75
-rw-r--r--src/core/MatrixTransform.cpp386
-rw-r--r--src/core/Mutex.h115
-rw-r--r--src/core/NoOps.cpp641
-rw-r--r--src/core/NoOps.h67
-rw-r--r--src/core/OCIOYaml.cpp1218
-rw-r--r--src/core/OCIOYaml.h125
-rw-r--r--src/core/Op.cpp126
-rw-r--r--src/core/Op.h136
-rw-r--r--src/core/OpBuilders.h125
-rw-r--r--src/core/OpOptimizers.cpp364
-rw-r--r--src/core/ParseUtils.cpp438
-rw-r--r--src/core/ParseUtils.h89
-rw-r--r--src/core/PathUtils.cpp229
-rw-r--r--src/core/PathUtils.h95
-rw-r--r--src/core/Platform.h202
-rw-r--r--src/core/PrivateTypes.h54
-rw-r--r--src/core/Processor.cpp640
-rw-r--r--src/core/Processor.h132
-rw-r--r--src/core/SSE.h37
-rw-r--r--src/core/ScanlineHelper.cpp123
-rw-r--r--src/core/ScanlineHelper.h78
-rw-r--r--src/core/Transform.cpp175
-rw-r--r--src/core/TruelightOp.cpp395
-rw-r--r--src/core/TruelightOp.h44
-rw-r--r--src/core/TruelightTransform.cpp365
-rw-r--r--src/core/UnitTest.cpp39
-rw-r--r--src/core/UnitTest.h38
-rw-r--r--src/core/md5/md5.cpp391
-rw-r--r--src/core/md5/md5.h97
-rw-r--r--src/core/pystring/pystring.cpp1658
-rw-r--r--src/core/pystring/pystring.h438
-rw-r--r--src/core_tests/CMakeLists.txt51
-rw-r--r--src/core_tests/ocio_core_tests.sh.in8
-rw-r--r--src/jniglue/CMakeLists.txt92
-rw-r--r--src/jniglue/JNIBaker.cpp264
-rw-r--r--src/jniglue/JNIColorSpace.cpp239
-rw-r--r--src/jniglue/JNIConfig.cpp607
-rw-r--r--src/jniglue/JNIContext.cpp170
-rw-r--r--src/jniglue/JNIGlobals.cpp417
-rw-r--r--src/jniglue/JNIGpuShaderDesc.cpp125
-rw-r--r--src/jniglue/JNIImageDesc.cpp309
-rw-r--r--src/jniglue/JNILook.cpp131
-rw-r--r--src/jniglue/JNIProcessor.cpp133
-rw-r--r--src/jniglue/JNITransforms.cpp1151
-rw-r--r--src/jniglue/JNIUtil.cpp122
-rw-r--r--src/jniglue/JNIUtil.h282
-rw-r--r--src/jniglue/LoadLibrary.java.in40
-rw-r--r--src/jniglue/Manifest.txt.in7
-rw-r--r--src/jniglue/org/OpenColorIO/Allocation.java44
-rw-r--r--src/jniglue/org/OpenColorIO/AllocationTransform.java42
-rw-r--r--src/jniglue/org/OpenColorIO/Baker.java62
-rw-r--r--src/jniglue/org/OpenColorIO/BitDepth.java56
-rw-r--r--src/jniglue/org/OpenColorIO/CDLTransform.java56
-rw-r--r--src/jniglue/org/OpenColorIO/ColorSpace.java59
-rw-r--r--src/jniglue/org/OpenColorIO/ColorSpaceDirection.java44
-rw-r--r--src/jniglue/org/OpenColorIO/ColorSpaceTransform.java41
-rw-r--r--src/jniglue/org/OpenColorIO/Config.java96
-rw-r--r--src/jniglue/org/OpenColorIO/Context.java52
-rw-r--r--src/jniglue/org/OpenColorIO/DisplayTransform.java55
-rw-r--r--src/jniglue/org/OpenColorIO/ExceptionBase.java37
-rw-r--r--src/jniglue/org/OpenColorIO/ExceptionMissingFile.java37
-rw-r--r--src/jniglue/org/OpenColorIO/ExponentTransform.java39
-rw-r--r--src/jniglue/org/OpenColorIO/FileTransform.java46
-rw-r--r--src/jniglue/org/OpenColorIO/Globals.java78
-rw-r--r--src/jniglue/org/OpenColorIO/GpuLanguage.java46
-rw-r--r--src/jniglue/org/OpenColorIO/GpuShaderDesc.java46
-rw-r--r--src/jniglue/org/OpenColorIO/GroupTransform.java42
-rw-r--r--src/jniglue/org/OpenColorIO/ImageDesc.java36
-rw-r--r--src/jniglue/org/OpenColorIO/Interpolation.java48
-rw-r--r--src/jniglue/org/OpenColorIO/LogTransform.java39
-rw-r--r--src/jniglue/org/OpenColorIO/LoggingLevel.java48
-rw-r--r--src/jniglue/org/OpenColorIO/Look.java48
-rw-r--r--src/jniglue/org/OpenColorIO/LookTransform.java43
-rw-r--r--src/jniglue/org/OpenColorIO/MatrixTransform.java54
-rw-r--r--src/jniglue/org/OpenColorIO/PackedImageDesc.java59
-rw-r--r--src/jniglue/org/OpenColorIO/PlanarImageDesc.java63
-rw-r--r--src/jniglue/org/OpenColorIO/Processor.java51
-rw-r--r--src/jniglue/org/OpenColorIO/Transform.java41
-rw-r--r--src/jniglue/org/OpenColorIO/TransformDirection.java44
-rw-r--r--src/jniglue/org/OpenColorIO/TruelightTransform.java58
-rw-r--r--src/jniglue/tests/CMakeLists.txt17
-rw-r--r--src/jniglue/tests/org/OpenColorIO/BakerTest.java84
-rw-r--r--src/jniglue/tests/org/OpenColorIO/ColorSpaceTest.java41
-rw-r--r--src/jniglue/tests/org/OpenColorIO/ConfigTest.java220
-rw-r--r--src/jniglue/tests/org/OpenColorIO/ContextTest.java38
-rw-r--r--src/jniglue/tests/org/OpenColorIO/GlobalsTest.java150
-rw-r--r--src/jniglue/tests/org/OpenColorIO/GpuShaderDescTest.java24
-rw-r--r--src/jniglue/tests/org/OpenColorIO/LookTest.java35
-rw-r--r--src/jniglue/tests/org/OpenColorIO/OpenColorIOTestSuite.java30
-rw-r--r--src/jniglue/tests/org/OpenColorIO/PackedImageDescTest.java39
-rw-r--r--src/jniglue/tests/org/OpenColorIO/PlanarImageDescTest.java51
-rw-r--r--src/jniglue/tests/org/OpenColorIO/TransformsTest.java237
-rw-r--r--src/jniglue/tests/org/OpenColorIO/test.cc11
-rw-r--r--src/mari/1.4v1/README10
-rwxr-xr-xsrc/mari/1.4v1/_ocio_filter.py127
-rwxr-xr-xsrc/mari/1.4v1/_ocio_toolbar.py1279
-rwxr-xr-xsrc/mari/1.4v1/ocio.py789
-rw-r--r--src/mari/prototype/README3
-rw-r--r--src/mari/prototype/ociodisplay.py242
-rw-r--r--src/mari/prototype/ociofiletransform.py93
-rw-r--r--src/nuke/CMakeLists.txt138
-rw-r--r--src/nuke/OCIOCDLTransform/OCIOCDLTransform.cpp387
-rw-r--r--src/nuke/OCIOCDLTransform/OCIOCDLTransform.h137
-rw-r--r--src/nuke/OCIOColorSpace/OCIOColorSpace.cpp376
-rw-r--r--src/nuke/OCIOColorSpace/OCIOColorSpace.h120
-rw-r--r--src/nuke/OCIODisplay/OCIODisplay.cpp561
-rw-r--r--src/nuke/OCIODisplay/OCIODisplay.h133
-rw-r--r--src/nuke/OCIOFileTransform/OCIOFileTransform.cpp287
-rw-r--r--src/nuke/OCIOFileTransform/OCIOFileTransform.h128
-rw-r--r--src/nuke/OCIOLogConvert/OCIOLogConvert.cpp179
-rw-r--r--src/nuke/OCIOLogConvert/OCIOLogConvert.h101
-rw-r--r--src/nuke/OCIOLookTransform/OCIOLookTransform.cpp533
-rw-r--r--src/nuke/OCIOLookTransform/OCIOLookTransform.h140
-rw-r--r--src/pyglue/CMakeLists.txt106
-rw-r--r--src/pyglue/DocStrings/AllocationTransform.py54
-rw-r--r--src/pyglue/DocStrings/CDLTransform.py141
-rw-r--r--src/pyglue/DocStrings/ColorSpace.py103
-rw-r--r--src/pyglue/DocStrings/ColorSpaceTransform.py51
-rw-r--r--src/pyglue/DocStrings/Config.py527
-rw-r--r--src/pyglue/DocStrings/Constants.py43
-rw-r--r--src/pyglue/DocStrings/Context.py32
-rw-r--r--src/pyglue/DocStrings/DisplayTransform.py222
-rw-r--r--src/pyglue/DocStrings/Exception.py11
-rw-r--r--src/pyglue/DocStrings/ExceptionMissingFile.py11
-rw-r--r--src/pyglue/DocStrings/ExponentTransform.py31
-rw-r--r--src/pyglue/DocStrings/FileTransform.py19
-rw-r--r--src/pyglue/DocStrings/GroupTransform.py21
-rw-r--r--src/pyglue/DocStrings/LogTransform.py26
-rw-r--r--src/pyglue/DocStrings/Look.py35
-rw-r--r--src/pyglue/DocStrings/LookTransform.py19
-rw-r--r--src/pyglue/DocStrings/MatrixTransform.py29
-rw-r--r--src/pyglue/DocStrings/OpenColorIO.py17
-rw-r--r--src/pyglue/DocStrings/Processor.py141
-rw-r--r--src/pyglue/DocStrings/ProcessorMetadata.py34
-rw-r--r--src/pyglue/DocStrings/Transform.py19
-rw-r--r--src/pyglue/DocStrings/__init__.py23
-rw-r--r--src/pyglue/PyAllocationTransform.cpp300
-rw-r--r--src/pyglue/PyCDLTransform.cpp611
-rw-r--r--src/pyglue/PyColorSpace.cpp756
-rw-r--r--src/pyglue/PyColorSpace.h52
-rw-r--r--src/pyglue/PyColorSpaceTransform.cpp294
-rw-r--r--src/pyglue/PyConfig.cpp1220
-rw-r--r--src/pyglue/PyConfig.h52
-rw-r--r--src/pyglue/PyConstants.cpp239
-rw-r--r--src/pyglue/PyConstants.h41
-rw-r--r--src/pyglue/PyContext.cpp494
-rw-r--r--src/pyglue/PyContext.h52
-rw-r--r--src/pyglue/PyDisplayTransform.cpp577
-rw-r--r--src/pyglue/PyExponentTransform.cpp269
-rw-r--r--src/pyglue/PyFileTransform.cpp344
-rw-r--r--src/pyglue/PyGroupTransform.cpp397
-rw-r--r--src/pyglue/PyLogTransform.cpp251
-rw-r--r--src/pyglue/PyLook.cpp450
-rw-r--r--src/pyglue/PyLook.h50
-rw-r--r--src/pyglue/PyLookTransform.cpp343
-rw-r--r--src/pyglue/PyMain.cpp236
-rw-r--r--src/pyglue/PyMatrixTransform.cpp630
-rw-r--r--src/pyglue/PyProcessor.cpp500
-rw-r--r--src/pyglue/PyProcessor.h50
-rw-r--r--src/pyglue/PyProcessorMetadata.cpp245
-rw-r--r--src/pyglue/PyProcessorMetadata.h50
-rw-r--r--src/pyglue/PyTransform.cpp411
-rw-r--r--src/pyglue/PyTransform.h81
-rw-r--r--src/pyglue/PyUtil.cpp742
-rw-r--r--src/pyglue/PyUtil.h103
-rw-r--r--src/pyglue/createPyDocH.py86
-rw-r--r--src/rv/Makefile6
-rw-r--r--src/rv/Mu/rvload1
-rw-r--r--src/rv/Mu/rvload22
-rw-r--r--src/rv/Packages/.gitignore1
-rw-r--r--src/rv/Packages/rvinstall1
-rw-r--r--src/rv/Python/PACKAGE12
-rw-r--r--src/rv/Python/ociorv.py288
-rw-r--r--testdata/3dl.zipbin0 -> 47309 bytes
-rw-r--r--testdata/csp.zipbin0 -> 371798 bytes
-rw-r--r--testdata/cub.zipbin0 -> 68743 bytes
-rw-r--r--testdata/cube.zipbin0 -> 38160 bytes
-rw-r--r--testdata/iridas.zipbin0 -> 619494 bytes
-rw-r--r--testdata/itx.zipbin0 -> 45252 bytes
-rw-r--r--testdata/mga.zipbin0 -> 228540 bytes
-rw-r--r--testdata/spi.zipbin0 -> 199598 bytes
415 files changed, 83847 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7235cb8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.DS_Store
+attic
+build*
+dist*
+mastercopy
+*.pyc
diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/.pc/0001-Fix_built-in_documentation_dependencies.patch/CMakeLists.txt b/.pc/0001-Fix_built-in_documentation_dependencies.patch/CMakeLists.txt
new file mode 100644
index 0000000..3e36ca5
--- /dev/null
+++ b/.pc/0001-Fix_built-in_documentation_dependencies.patch/CMakeLists.txt
@@ -0,0 +1,406 @@
+project(OpenColorIO)
+set(OCIO_VERSION_MAJOR 1)
+set(OCIO_VERSION_MINOR 0)
+set(OCIO_VERSION_PATCH 8)
+
+cmake_minimum_required(VERSION 2.8)
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake)
+if(NOT DEFINED CMAKE_FIRST_RUN)
+ SET(CMAKE_FIRST_RUN 1 CACHE INTERNAL "")
+endif()
+
+###############################################################################
+### GLOBAL ###
+
+option(OCIO_BUILD_SHARED "Set to OFF to disable building the shared core library" ON)
+option(OCIO_BUILD_STATIC "Set to OFF to disable building the static core library" ON)
+option(OCIO_BUILD_TRUELIGHT "Set to OFF to disable truelight" ON)
+option(OCIO_BUILD_APPS "Set to OFF to disable command-line apps" ON)
+option(OCIO_BUILD_NUKE "Set to OFF to disable building nuke plugins" ON)
+option(OCIO_BUILD_DOCS "Specify whether to build documentation" OFF)
+option(OCIO_BUILD_TESTS "Specify whether to build unittests" OFF)
+option(OCIO_BUILD_PYGLUE "Specify whether to build python bindings" ON)
+option(OCIO_BUILD_JNIGLUE "Specify whether to build java bindings" OFF)
+option(OCIO_STATIC_JNIGLUE "Specify whether to statically link ocio to the java bindings" ON)
+
+option(OCIO_USE_SSE "Specify whether to enable SSE CPU performance optimizations" ON)
+
+# Use boost's shared_ptr by default on Windows (as <VS2010 doesn't have it),
+# Use std::tr1::shared_ptr by default on other platforms
+option(OCIO_USE_BOOST_PTR "Set to ON to enable boost shared_ptr (necessary when tr1 is not available)" WIN32)
+
+option(OCIO_PYGLUE_LINK "If ON, link the Python module to the core shared library" OFF)
+option(OCIO_PYGLUE_RESPECT_ABI "If ON, the Python module install path includes Python UCS version" OFF)
+option(OCIO_PYGLUE_SONAME "If ON, soname/soversion will be set for Python module library" OFF)
+option(OCIO_PYGLUE_LIB_PREFIX "If ON, prefix the Python module with 'lib'" OFF)
+
+if(UNIX AND NOT APPLE)
+ option(USE_EXTERNAL_YAML "Use system installed yaml-cpp library." OFF)
+ option(USE_EXTERNAL_TINYXML "Use system installed tinyxml library." OFF)
+ option(USE_EXTERNAL_LCMS "Use system install lcms2 library." OFF)
+endif()
+
+# This does not include the SOVERSION override, on purpose, so that the
+# OCIO_VERSION value will be an accurate reflection of the underlying library version.
+set(OCIO_VERSION "${OCIO_VERSION_MAJOR}.${OCIO_VERSION_MINOR}.${OCIO_VERSION_PATCH}")
+
+if(NOT SOVERSION)
+ set(SOVERSION ${OCIO_VERSION_MAJOR} CACHE STRING "Set the SO version in the SO name of the output library")
+endif()
+
+###############################################################################
+
+
+include(ParseArguments)
+include(OCIOMacros)
+include(ExternalProject)
+
+enable_language(CXX)
+
+ENABLE_TESTING()
+
+if(APPLE OR IPHONE)
+ if(NOT CMAKE_OSX_ARCHITECTURES)
+ set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING
+ "Setting OSX Architectures, options are: ppc;i386;ppc64;x86_64"
+ FORCE)
+ endif()
+ if(CMAKE_FIRST_RUN)
+ message(STATUS "Setting OSX Architectures to: ${CMAKE_OSX_ARCHITECTURES}")
+ endif()
+endif()
+
+# Set the default built type
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
+ "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+ FORCE)
+endif(NOT CMAKE_BUILD_TYPE)
+if(CMAKE_FIRST_RUN)
+ message(STATUS "Setting Build Type to: ${CMAKE_BUILD_TYPE}")
+endif()
+
+# Set the default namespace
+if(NOT OCIO_NAMESPACE)
+ set(OCIO_NAMESPACE OpenColorIO CACHE STRING
+ "Specify the master OCIO C++ namespace: Options include OpenColorIO OpenColorIO_<YOURFACILITY> etc."
+ FORCE)
+endif(NOT OCIO_NAMESPACE)
+messageonce("Setting Namespace to: ${OCIO_NAMESPACE}")
+
+# If CMAKE_INSTALL_EXEC_PREFIX is not specified, install binaries
+# directly into the regular install prefix
+if(NOT CMAKE_INSTALL_EXEC_PREFIX)
+ messageonce("Exec prefix not specified, defaulting to ${CMAKE_INSTALL_PREFIX}")
+ set(CMAKE_INSTALL_EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
+endif()
+
+messageonce("Use Boost Ptr: ${OCIO_USE_BOOST_PTR}")
+if(OCIO_USE_BOOST_PTR)
+ set(Boost_ADDITIONAL_VERSIONS "1.49" "1.45" "1.44" "1.43" "1.43.0" "1.42"
+ "1.42.0" "1.41" "1.41.0" "1.40"
+ "1.40.0" "1.39" "1.39.0" "1.38"
+ "1.38.0" "1.37" "1.37.0" "1.34.1"
+ "1_34_1")
+ set(Boost_USE_MULTITHREADED ON)
+ find_package(Boost 1.34)
+ if(NOT Boost_FOUND)
+ message(FATAL_ERROR "OCIO_USE_BOOST_PTR is specified, but a boost installation could not be found.")
+ else()
+ set(OCIO_USE_BOOST_PTR 1)
+ endif()
+
+ set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIR})
+ # set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
+else()
+ set(OCIO_USE_BOOST_PTR 0)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+ # Enable a bunch of compiler warnings...
+ # http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2")
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
+endif(CMAKE_COMPILER_IS_GNUCXX)
+
+if(WIN32)
+ if(PYTHON_VERSION AND PYTHON_INCLUDE AND PYTHON_LIB)
+ set(EXTDIST_PYTHONPATH ${PYTHON_LIB}/python${PYTHON_VARIANT_PATH}/site-packages)
+ set(PYTHONPATH ${EXTDIST_PYTHONPATH};$ENV{PYTHONPATH})
+ set(PYTHON_OK YES)
+ message(STATUS "Setting Python path to: ${PYTHONPATH}")
+ endif()
+else()
+ # Find Python, used for (possibly) building pyglue, and now to
+ # construct the external project path
+ OCIOFindPython()
+
+ set(EXTDIST_ROOT ${CMAKE_BINARY_DIR}/ext/dist)
+ set(EXTDIST_BINPATH ${EXTDIST_ROOT}/bin)
+ if(PYTHON_OK)
+ set(EXTDIST_PYTHONPATH ${EXTDIST_ROOT}/lib/python${PYTHON_VERSION}/site-packages)
+ set(PYTHONPATH ${EXTDIST_PYTHONPATH}:$ENV{PYTHONPATH})
+ endif()
+endif()
+
+messageonce("Setting EXTDIST_BINPATH: ${EXTDIST_BINPATH}")
+messageonce("Setting EXTDIST_PYTHONPATH: ${EXTDIST_PYTHONPATH}")
+
+###############################################################################
+### tinyxml ###
+
+if(USE_EXTERNAL_TINYXML)
+ set(TINYXML_VERSION_MIN "2.6.1")
+ find_package(TinyXML)
+ if(TINYXML_FOUND)
+ if(TINYXML_VERSION VERSION_EQUAL ${TINYXML_VERSION_MIN} OR
+ TINYXML_VERSION VERSION_GREATER ${TINYXML_VERSION_MIN})
+ message(STATUS "External TinyXML will be used.")
+ else()
+ message(FATAL_ERROR "ERROR: ${TINYXML_VERSION} found, but ${TINYXML_VERSION_MIN} or newer is required.")
+ endif()
+ else(TINYXML_FOUND)
+ message(STATUS "TinyXML was not found. Perhaps you forgot to install the development package?")
+ endif(TINYXML_FOUND)
+
+else(USE_EXTERNAL_TINYXML)
+ set(TINYXML_VERSION 2_6_1)
+ set(TINYXML_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/ext/dist)
+ if(CMAKE_TOOLCHAIN_FILE)
+ set(TINYXML_CMAKE_ARGS ${TINYXML_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
+ endif()
+ ExternalProject_Add(tinyxml
+ URL ${CMAKE_SOURCE_DIR}/ext/tinyxml_${TINYXML_VERSION}.tar.gz
+ PATCH_COMMAND patch -f -p1 < ${CMAKE_SOURCE_DIR}/ext/tinyxml_${TINYXML_VERSION}.patch
+ BINARY_DIR ext/build/tinyxml
+ INSTALL_DIR ext/dist
+ CMAKE_ARGS ${TINYXML_CMAKE_ARGS}
+ )
+ if(WIN32)
+ set(TINYXML_STATIC_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/tinyxml.lib)
+ else()
+ set(TINYXML_STATIC_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libtinyxml.a)
+ endif()
+endif(USE_EXTERNAL_TINYXML)
+
+###############################################################################
+### YAML ###
+
+if(USE_EXTERNAL_YAML)
+ # Set minimum yaml version for non-patched sources.
+ set(YAML_VERSION_MIN "0.3.0")
+ include(FindPkgConfig)
+ pkg_check_modules(YAML_CPP yaml-cpp)
+ if(YAML_CPP_FOUND)
+ if(YAML_CPP_VERSION VERSION_EQUAL ${YAML_VERSION_MIN} OR
+ YAML_CPP_VERSION VERSION_GREATER ${YAML_VERSION_MIN})
+ message(STATUS "System yaml-cpp library will be used.")
+ include_directories(BEFORE ${YAML_CPP_INCLUDE_DIRS})
+ else()
+ message(FATAL_ERROR "ERROR: yaml-cpp ${YAML_VERSION_MIN} or greater is required.")
+ endif()
+ else(YAML_CPP_FOUND)
+ message(FATAL_ERROR "ERROR: System yaml-cpp library was not found. Make sure the library is installed and the pkg-config file exists.")
+ endif(YAML_CPP_FOUND)
+else(USE_EXTERNAL_YAML)
+ set(YAML_CPP_VERSION 0.3.0)
+ set(YAML_CPP_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/ext/dist -DYAML_CPP_BUILD_TOOLS:BOOL=FALSE)
+ if(CMAKE_TOOLCHAIN_FILE)
+ set(YAML_CPP_CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
+ endif()
+ ExternalProject_Add(YAML_CPP_LOCAL
+ URL ${CMAKE_SOURCE_DIR}/ext/yaml-cpp-${YAML_CPP_VERSION}.tar.gz
+ BINARY_DIR ext/build/yaml-cpp
+ PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/ext/yaml-cpp-${YAML_CPP_VERSION}.patch
+ INSTALL_DIR ext/dist
+ CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS}
+ )
+ set(YAML_CPP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ext/dist/include)
+ set(YAML_CPP_LIBRARY_DIRS ${PROJECT_BINARY_DIR}/ext/dist/lib)
+ if(WIN32)
+ set(YAML_CPP_STATIC_DEBUG_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libyaml-cppmdd.lib)
+ set(YAML_CPP_STATIC_OPTIMIZED_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libyaml-cppmd.lib)
+ else()
+ set(YAML_CPP_STATIC_GENERAL_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libyaml-cpp.a)
+ endif()
+endif(USE_EXTERNAL_YAML)
+
+
+
+###############################################################################
+### Externals ###
+
+set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/ext/dist/include)
+set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL")
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+
+ if (GCC_VERSION VERSION_LESS 4.2)
+ message(STATUS "GCC Version < 4.2 - symbol visibility hiding disabled")
+ set(EXTERNAL_COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS} -fPIC")
+ else()
+ set(EXTERNAL_COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS} -fPIC -fvisibility-inlines-hidden -fvisibility=hidden")
+ endif()
+endif()
+
+set(EXTERNAL_LINK_FLAGS "")
+set(EXTERNAL_LIBRARY_DIRS ${PROJECT_BINARY_DIR}/ext/dist/lib)
+set(EXTERNAL_DEBUG_LIBRARIES ${YAML_CPP_STATIC_DEBUG_LIBRARIES})
+set(EXTERNAL_OPTIMIZED_LIBRARIES ${YAML_CPP_STATIC_OPTIMIZED_LIBRARIES})
+set(EXTERNAL_GENERAL_LIBRARIES ${TINYXML_STATIC_LIBRARIES} ${YAML_CPP_STATIC_GENERAL_LIBRARIES})
+
+###############################################################################
+### Documentation ###
+
+messageonce("Generate Documentation: ${OCIO_BUILD_DOCS}")
+
+if(OCIO_BUILD_DOCS)
+ if(PYTHON_OK)
+ add_subdirectory(docs)
+ else()
+ message(STATUS "Building the documentation requires Python, but locating Python failed: ${PYTHON_ERR}")
+ endif()
+endif()
+
+###############################################################################
+### SSE ###
+
+messageonce("SSE Optimizations: ${OCIO_USE_SSE}")
+
+if(OCIO_USE_SSE)
+ if(WIN32)
+ # SSE instructions are automatically compiled into 64-bit applications so enabling the option is redundant and
+ # actually produces an unknown option warning in Visual Studio.
+ if(NOT CMAKE_CL_64)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2")
+ endif()
+ else()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
+ endif()
+ add_definitions("-DUSE_SSE")
+endif()
+
+###############################################################################
+### TRUELIGHT ###
+
+if(OCIO_BUILD_TRUELIGHT)
+ find_package(Truelight)
+ if(TRUELIGHT_FOUND)
+ messageonce("Will build the truelight transform support against ${Truelight_LIBRARY_DIR}")
+ add_definitions(-DOCIO_TRUELIGHT_SUPPORT)
+ set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${Truelight_INCLUDE_DIR})
+ set(EXTERNAL_COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS} ${Truelight_COMPILE_FLAGS}")
+ set(EXTERNAL_LINK_FLAGS "${EXTERNAL_LINK_FLAGS} ${Truelight_LINK_FLAGS}")
+ set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${Truelight_LIBRARIES})
+ else()
+ messageonce("Not building truelight transform support. Add the flag -D TRUELIGHT_INSTALL_PATH=... or set the TRUELIGHT_ROOT environment variable")
+ endif()
+endif()
+
+###############################################################################
+### CORE ###
+
+add_subdirectory(src/core)
+
+messageonce("Build Unit Tests: ${OCIO_BUILD_TESTS}")
+if(OCIO_BUILD_TESTS)
+ add_subdirectory(src/core_tests)
+endif()
+
+###############################################################################
+### APPS ###
+
+if(OCIO_BUILD_APPS)
+ # Try to find OpenImageIO (OIIO) and OpenGL stuff
+ OCIOFindOpenImageIO()
+
+ if(OIIO_FOUND)
+ add_subdirectory(src/apps/ocioconvert)
+ add_subdirectory(src/apps/ociolutimage)
+ else()
+ messageonce("Not building ocioconvert/ociolutimage. Requirement(s) found: OIIO:${OIIO_FOUND}")
+ endif()
+
+ # ociodisplay, displays color-transformed images (uses OpenImageIO,
+ # and OpenGL)
+ OCIOFindOpenGL()
+ if(OPENGL_FOUND AND GLUT_FOUND AND GLEW_FOUND AND OIIO_FOUND)
+ add_subdirectory(src/apps/ociodisplay)
+ else()
+ messageonce("Not building ociodisplay. Requirement(s) found, OpenGL:${OPENGL_FOUND}, GLUT:${GLUT_FOUND}, GLEW:${GLEW_FOUND}, OIIO:${OIIO_FOUND}")
+ endif()
+
+ # ociocheck: verifies an OCIO config
+ add_subdirectory(src/apps/ociocheck)
+
+ # ociobakelut writes out luts
+ add_subdirectory(src/apps/ociobakelut)
+endif()
+
+###############################################################################
+### NUKE ###
+
+if(OCIO_BUILD_NUKE)
+ find_package(Nuke)
+ if(NUKE_FOUND)
+ messageonce("Will build the Nuke plugins against ${Nuke_LIBRARY_DIR}")
+ add_subdirectory(src/nuke)
+ else()
+ messageonce("Not building Nuke plugins. Add the flag -D NUKE_INSTALL_PATH=... or set the NDK_PATH environment variable")
+ endif()
+endif()
+
+###############################################################################
+### PYGLUE ###
+
+if(OCIO_BUILD_PYGLUE)
+ if(PYTHON_OK)
+ add_subdirectory(src/pyglue)
+ else()
+ messageonce("Python bindings will not be built: ${PYTHON_ERR}")
+ endif()
+endif()
+
+###############################################################################
+### JNIGLUE ###
+
+if(OCIO_BUILD_JNIGLUE)
+ OCIOFindJava()
+ if(Java_FOUND)
+ add_subdirectory(src/jniglue)
+ else()
+ messageonce("Java bindings will not be built as we can't find Java")
+ endif()
+endif()
+
+###############################################################################
+### Configure env script ###
+configure_file(${CMAKE_SOURCE_DIR}/share/ocio/setup_ocio.sh.in
+ ${CMAKE_CURRENT_BINARY_DIR}/share/ocio/setup_ocio.sh @ONLY)
+
+INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/share/ocio/setup_ocio.sh DESTINATION share/ocio/)
+
+###############################################################################
+### CPACK ###
+
+set(CPACK_PACKAGE_VERSION_MAJOR ${SOVERSION})
+set(CPACK_PACKAGE_VERSION_MINOR ${OCIO_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${OCIO_VERSION_PATCH})
+set(CPACK_GENERATOR None)
+set(CPACK_SOURCE_GENERATOR TGZ)
+set(CPACK_SOURCE_PACKAGE_FILE_NAME "ocio.${OCIO_VERSION}")
+include(CPack)
+
+###############################################################################
+### CTEST ###
+
+add_custom_target(test_verbose
+ COMMAND ctest -VV
+ DEPENDS ocio_core_tests
+ COMMENT "Running ctest with verbose output")
+
+# Log CMake first run done
+SET(CMAKE_FIRST_RUN 0 CACHE INTERNAL "")
diff --git a/.pc/0001-Fix_built-in_documentation_dependencies.patch/docs/CMakeLists.txt b/.pc/0001-Fix_built-in_documentation_dependencies.patch/docs/CMakeLists.txt
new file mode 100644
index 0000000..0cbfd67
--- /dev/null
+++ b/.pc/0001-Fix_built-in_documentation_dependencies.patch/docs/CMakeLists.txt
@@ -0,0 +1,131 @@
+
+###############################################################################
+### External Doc Apps ###
+
+# setuptools
+set(SETUPTOOLS_VERSION 0.6c11)
+ExternalProject_Add(setuptools
+ URL ${CMAKE_SOURCE_DIR}/ext/setuptools-${SETUPTOOLS_VERSION}.tar.gz
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+ BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+ INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+)
+
+# docutils
+set(DOCUTILS_VERSION 0.7)
+ExternalProject_Add(docutils
+ DEPENDS setuptools
+ URL ${CMAKE_SOURCE_DIR}/ext/docutils-${DOCUTILS_VERSION}.tar.gz
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+ BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+ INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+)
+
+# jinja2
+set(JINJA2_VERSION 2.5.5)
+ExternalProject_Add(Jinja2
+ DEPENDS setuptools
+ URL ${CMAKE_SOURCE_DIR}/ext/Jinja2-${JINJA2_VERSION}.tar.gz
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+ BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+ INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+)
+
+# Pygments
+set(PYGMENTS_VERSION 1.3.1)
+ExternalProject_Add(Pygments
+ DEPENDS setuptools
+ URL ${CMAKE_SOURCE_DIR}/ext/Pygments-${PYGMENTS_VERSION}.tar.gz
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+ BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+ INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+)
+
+# sphinx
+set(SPHINX_VERSION f52b631f501a) # 1.1pre
+ExternalProject_Add(Sphinx
+ DEPENDS setuptools docutils Jinja2 Pygments
+ URL ${CMAKE_SOURCE_DIR}/ext/sphinx-${SPHINX_VERSION}.tar.gz
+ PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/ext/sphinx-${SPHINX_VERSION}.patch
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+ BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+ INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT} --install-scripts=${EXTDIST_ROOT}/bin
+)
+
+###############################################################################
+### Create Doc Targets ###
+
+message(STATUS "Create sphinx conf.py from conf.py.in")
+configure_file(${CMAKE_SOURCE_DIR}/docs/conf.py.in
+ ${CMAKE_BINARY_DIR}/docs/conf.py @ONLY)
+
+message(STATUS "Copying doc to staging area")
+file(COPY ${CMAKE_SOURCE_DIR}/docs/ DESTINATION ${CMAKE_BINARY_DIR}/docs)
+
+message(STATUS "Copy extra doc files to staging area")
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/README)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/INSTALL)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/ChangeLog)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/LICENSE)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/share/nuke/ocionuke/viewer.py)
+CopyFiles(RSTDOC ${DOCFILES})
+
+message(STATUS "Extracting .rst files from C++ headers")
+ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorIO.h developers/api/OpenColorIO.rst)
+ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorTransforms.h developers/api/OpenColorTransforms.rst)
+ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorTypes.h developers/api/OpenColorTypes.rst)
+
+add_custom_target(doc ALL
+ COMMAND PYTHONPATH=${PYTHONPATH} ${EXTDIST_BINPATH}/sphinx-build -b html . ${CMAKE_CURRENT_BINARY_DIR}/build-html
+ DEPENDS
+ OpenColorIO
+ PyOpenColorIO
+ ${CMAKE_BINARY_DIR}/docs/conf.py
+ developers/api/OpenColorIO.rst
+ developers/api/OpenColorTransforms.rst
+ developers/api/OpenColorTypes.rst
+ ${RSTDOC_OUTPUT}
+ COMMENT "Building html docs"
+ SOURCES ${DOCFILES})
+
+# note: ExternalProject will not build when added to a add_custom_target this
+# works around this problem. This seems to be fixed in the cmake ^HEAD
+add_dependencies(doc Sphinx)
+
+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-html/
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/OpenColorIO/html
+ PATTERN .* EXCLUDE
+)
+
+find_package(LATEX)
+if(PDFLATEX_COMPILER)
+
+ add_custom_target(latex
+ COMMAND PYTHONPATH=${PYTHONPATH} ${EXTDIST_BINPATH}/sphinx-build -b latex . ${CMAKE_CURRENT_BINARY_DIR}/build-latex
+ DEPENDS
+ OpenColorIO
+ ${CMAKE_BINARY_DIR}/docs/conf.py
+ developers/api/OpenColorIO.rst
+ developers/api/OpenColorTransforms.rst
+ developers/api/OpenColorTypes.rst
+ ${RSTDOC_OUTPUT}
+ COMMENT "Building latex doc"
+ SOURCES ${DOCFILES})
+ add_dependencies(latex Sphinx)
+
+ add_custom_target(pdf ALL
+ COMMAND ${PDFLATEX_COMPILER} OpenColorIO.tex
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-latex
+ COMMENT "Building pdf doc"
+ SOURCES ${DOCFILES})
+ add_dependencies(pdf latex)
+
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/build-latex/OpenColorIO.pdf
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/OpenColorIO/)
+
+endif()
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644
index 0000000..9db761e
--- /dev/null
+++ b/.pc/applied-patches
@@ -0,0 +1 @@
+0001-Fix_built-in_documentation_dependencies.patch
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..2b59b18
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,23 @@
+# travis-ci.org build file
+
+# As CMake is not officially supported we use erlang VMs
+language: erlang
+
+# Settings to try
+env:
+ - OPTIONS="-DCMAKE_BUILD_TYPE=Release -DOCIO_BUILD_TESTS=yes"
+
+# Make sure CMake is installed
+install:
+ - sudo apt-get install cmake
+
+# Run the Build script
+script:
+ - mkdir _build
+ - cd _build
+ - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS
+ - cmake --build . --target install
+
+# Run Tests
+after_script:
+ - ctest --output-on-failure .
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..a0e6adb
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,403 @@
+project(OpenColorIO)
+set(OCIO_VERSION_MAJOR 1)
+set(OCIO_VERSION_MINOR 0)
+set(OCIO_VERSION_PATCH 8)
+
+cmake_minimum_required(VERSION 2.8)
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake)
+if(NOT DEFINED CMAKE_FIRST_RUN)
+ SET(CMAKE_FIRST_RUN 1 CACHE INTERNAL "")
+endif()
+
+###############################################################################
+### GLOBAL ###
+
+option(OCIO_BUILD_SHARED "Set to OFF to disable building the shared core library" ON)
+option(OCIO_BUILD_STATIC "Set to OFF to disable building the static core library" ON)
+option(OCIO_BUILD_TRUELIGHT "Set to OFF to disable truelight" ON)
+option(OCIO_BUILD_APPS "Set to OFF to disable command-line apps" ON)
+option(OCIO_BUILD_NUKE "Set to OFF to disable building nuke plugins" ON)
+option(OCIO_BUILD_DOCS "Specify whether to build documentation" OFF)
+option(OCIO_BUILD_TESTS "Specify whether to build unittests" OFF)
+option(OCIO_BUILD_PYGLUE "Specify whether to build python bindings" ON)
+option(OCIO_BUILD_JNIGLUE "Specify whether to build java bindings" OFF)
+option(OCIO_STATIC_JNIGLUE "Specify whether to statically link ocio to the java bindings" ON)
+
+option(OCIO_USE_SSE "Specify whether to enable SSE CPU performance optimizations" ON)
+
+# Use boost's shared_ptr by default on Windows (as <VS2010 doesn't have it),
+# Use std::tr1::shared_ptr by default on other platforms
+option(OCIO_USE_BOOST_PTR "Set to ON to enable boost shared_ptr (necessary when tr1 is not available)" WIN32)
+
+option(OCIO_PYGLUE_LINK "If ON, link the Python module to the core shared library" OFF)
+option(OCIO_PYGLUE_RESPECT_ABI "If ON, the Python module install path includes Python UCS version" OFF)
+option(OCIO_PYGLUE_SONAME "If ON, soname/soversion will be set for Python module library" OFF)
+option(OCIO_PYGLUE_LIB_PREFIX "If ON, prefix the Python module with 'lib'" OFF)
+
+if(UNIX AND NOT APPLE)
+ option(USE_EXTERNAL_YAML "Use system installed yaml-cpp library." OFF)
+ option(USE_EXTERNAL_TINYXML "Use system installed tinyxml library." OFF)
+ option(USE_EXTERNAL_LCMS "Use system install lcms2 library." OFF)
+endif()
+
+# This does not include the SOVERSION override, on purpose, so that the
+# OCIO_VERSION value will be an accurate reflection of the underlying library version.
+set(OCIO_VERSION "${OCIO_VERSION_MAJOR}.${OCIO_VERSION_MINOR}.${OCIO_VERSION_PATCH}")
+
+if(NOT SOVERSION)
+ set(SOVERSION ${OCIO_VERSION_MAJOR} CACHE STRING "Set the SO version in the SO name of the output library")
+endif()
+
+###############################################################################
+
+
+include(ParseArguments)
+include(OCIOMacros)
+include(ExternalProject)
+
+enable_language(CXX)
+
+ENABLE_TESTING()
+
+if(APPLE OR IPHONE)
+ if(NOT CMAKE_OSX_ARCHITECTURES)
+ set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING
+ "Setting OSX Architectures, options are: ppc;i386;ppc64;x86_64"
+ FORCE)
+ endif()
+ if(CMAKE_FIRST_RUN)
+ message(STATUS "Setting OSX Architectures to: ${CMAKE_OSX_ARCHITECTURES}")
+ endif()
+endif()
+
+# Set the default built type
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
+ "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+ FORCE)
+endif(NOT CMAKE_BUILD_TYPE)
+if(CMAKE_FIRST_RUN)
+ message(STATUS "Setting Build Type to: ${CMAKE_BUILD_TYPE}")
+endif()
+
+# Set the default namespace
+if(NOT OCIO_NAMESPACE)
+ set(OCIO_NAMESPACE OpenColorIO CACHE STRING
+ "Specify the master OCIO C++ namespace: Options include OpenColorIO OpenColorIO_<YOURFACILITY> etc."
+ FORCE)
+endif(NOT OCIO_NAMESPACE)
+messageonce("Setting Namespace to: ${OCIO_NAMESPACE}")
+
+# If CMAKE_INSTALL_EXEC_PREFIX is not specified, install binaries
+# directly into the regular install prefix
+if(NOT CMAKE_INSTALL_EXEC_PREFIX)
+ messageonce("Exec prefix not specified, defaulting to ${CMAKE_INSTALL_PREFIX}")
+ set(CMAKE_INSTALL_EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
+endif()
+
+messageonce("Use Boost Ptr: ${OCIO_USE_BOOST_PTR}")
+if(OCIO_USE_BOOST_PTR)
+ set(Boost_ADDITIONAL_VERSIONS "1.49" "1.45" "1.44" "1.43" "1.43.0" "1.42"
+ "1.42.0" "1.41" "1.41.0" "1.40"
+ "1.40.0" "1.39" "1.39.0" "1.38"
+ "1.38.0" "1.37" "1.37.0" "1.34.1"
+ "1_34_1")
+ set(Boost_USE_MULTITHREADED ON)
+ find_package(Boost 1.34)
+ if(NOT Boost_FOUND)
+ message(FATAL_ERROR "OCIO_USE_BOOST_PTR is specified, but a boost installation could not be found.")
+ else()
+ set(OCIO_USE_BOOST_PTR 1)
+ endif()
+
+ set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIR})
+ # set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
+else()
+ set(OCIO_USE_BOOST_PTR 0)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+ # Enable a bunch of compiler warnings...
+ # http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2")
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
+endif(CMAKE_COMPILER_IS_GNUCXX)
+
+if(WIN32)
+ if(PYTHON_VERSION AND PYTHON_INCLUDE AND PYTHON_LIB)
+ set(EXTDIST_PYTHONPATH ${PYTHON_LIB}/python${PYTHON_VARIANT_PATH}/site-packages)
+ set(PYTHONPATH ${EXTDIST_PYTHONPATH};$ENV{PYTHONPATH})
+ set(PYTHON_OK YES)
+ message(STATUS "Setting Python path to: ${PYTHONPATH}")
+ endif()
+else()
+ # Find Python, used for (possibly) building pyglue, and now to
+ # construct the external project path
+ OCIOFindPython()
+
+ if(PYTHON_OK)
+ set(EXTDIST_PYTHONPATH /usr/lib/python${PYTHON_VERSION}/dist-packages)
+ set(PYTHONPATH ${EXTDIST_PYTHONPATH}:$ENV{PYTHONPATH})
+ endif()
+endif()
+
+messageonce("Setting EXTDIST_PYTHONPATH: ${EXTDIST_PYTHONPATH}")
+
+###############################################################################
+### tinyxml ###
+
+if(USE_EXTERNAL_TINYXML)
+ set(TINYXML_VERSION_MIN "2.6.1")
+ find_package(TinyXML)
+ if(TINYXML_FOUND)
+ if(TINYXML_VERSION VERSION_EQUAL ${TINYXML_VERSION_MIN} OR
+ TINYXML_VERSION VERSION_GREATER ${TINYXML_VERSION_MIN})
+ message(STATUS "External TinyXML will be used.")
+ else()
+ message(FATAL_ERROR "ERROR: ${TINYXML_VERSION} found, but ${TINYXML_VERSION_MIN} or newer is required.")
+ endif()
+ else(TINYXML_FOUND)
+ message(STATUS "TinyXML was not found. Perhaps you forgot to install the development package?")
+ endif(TINYXML_FOUND)
+
+else(USE_EXTERNAL_TINYXML)
+ set(TINYXML_VERSION 2_6_1)
+ set(TINYXML_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/ext/dist)
+ if(CMAKE_TOOLCHAIN_FILE)
+ set(TINYXML_CMAKE_ARGS ${TINYXML_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
+ endif()
+ ExternalProject_Add(tinyxml
+ URL ${CMAKE_SOURCE_DIR}/ext/tinyxml_${TINYXML_VERSION}.tar.gz
+ PATCH_COMMAND patch -f -p1 < ${CMAKE_SOURCE_DIR}/ext/tinyxml_${TINYXML_VERSION}.patch
+ BINARY_DIR ext/build/tinyxml
+ INSTALL_DIR ext/dist
+ CMAKE_ARGS ${TINYXML_CMAKE_ARGS}
+ )
+ if(WIN32)
+ set(TINYXML_STATIC_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/tinyxml.lib)
+ else()
+ set(TINYXML_STATIC_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libtinyxml.a)
+ endif()
+endif(USE_EXTERNAL_TINYXML)
+
+###############################################################################
+### YAML ###
+
+if(USE_EXTERNAL_YAML)
+ # Set minimum yaml version for non-patched sources.
+ set(YAML_VERSION_MIN "0.3.0")
+ include(FindPkgConfig)
+ pkg_check_modules(YAML_CPP yaml-cpp)
+ if(YAML_CPP_FOUND)
+ if(YAML_CPP_VERSION VERSION_EQUAL ${YAML_VERSION_MIN} OR
+ YAML_CPP_VERSION VERSION_GREATER ${YAML_VERSION_MIN})
+ message(STATUS "System yaml-cpp library will be used.")
+ include_directories(BEFORE ${YAML_CPP_INCLUDE_DIRS})
+ else()
+ message(FATAL_ERROR "ERROR: yaml-cpp ${YAML_VERSION_MIN} or greater is required.")
+ endif()
+ else(YAML_CPP_FOUND)
+ message(FATAL_ERROR "ERROR: System yaml-cpp library was not found. Make sure the library is installed and the pkg-config file exists.")
+ endif(YAML_CPP_FOUND)
+else(USE_EXTERNAL_YAML)
+ set(YAML_CPP_VERSION 0.3.0)
+ set(YAML_CPP_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/ext/dist -DYAML_CPP_BUILD_TOOLS:BOOL=FALSE)
+ if(CMAKE_TOOLCHAIN_FILE)
+ set(YAML_CPP_CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
+ endif()
+ ExternalProject_Add(YAML_CPP_LOCAL
+ URL ${CMAKE_SOURCE_DIR}/ext/yaml-cpp-${YAML_CPP_VERSION}.tar.gz
+ BINARY_DIR ext/build/yaml-cpp
+ PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/ext/yaml-cpp-${YAML_CPP_VERSION}.patch
+ INSTALL_DIR ext/dist
+ CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS}
+ )
+ set(YAML_CPP_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ext/dist/include)
+ set(YAML_CPP_LIBRARY_DIRS ${PROJECT_BINARY_DIR}/ext/dist/lib)
+ if(WIN32)
+ set(YAML_CPP_STATIC_DEBUG_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libyaml-cppmdd.lib)
+ set(YAML_CPP_STATIC_OPTIMIZED_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libyaml-cppmd.lib)
+ else()
+ set(YAML_CPP_STATIC_GENERAL_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/libyaml-cpp.a)
+ endif()
+endif(USE_EXTERNAL_YAML)
+
+
+
+###############################################################################
+### Externals ###
+
+set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/ext/dist/include)
+set(EXTERNAL_COMPILE_FLAGS "-DTIXML_USE_STL")
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+
+ if (GCC_VERSION VERSION_LESS 4.2)
+ message(STATUS "GCC Version < 4.2 - symbol visibility hiding disabled")
+ set(EXTERNAL_COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS} -fPIC")
+ else()
+ set(EXTERNAL_COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS} -fPIC -fvisibility-inlines-hidden -fvisibility=hidden")
+ endif()
+endif()
+
+set(EXTERNAL_LINK_FLAGS "")
+set(EXTERNAL_LIBRARY_DIRS ${PROJECT_BINARY_DIR}/ext/dist/lib)
+set(EXTERNAL_DEBUG_LIBRARIES ${YAML_CPP_STATIC_DEBUG_LIBRARIES})
+set(EXTERNAL_OPTIMIZED_LIBRARIES ${YAML_CPP_STATIC_OPTIMIZED_LIBRARIES})
+set(EXTERNAL_GENERAL_LIBRARIES ${TINYXML_STATIC_LIBRARIES} ${YAML_CPP_STATIC_GENERAL_LIBRARIES})
+
+###############################################################################
+### Documentation ###
+
+messageonce("Generate Documentation: ${OCIO_BUILD_DOCS}")
+
+if(OCIO_BUILD_DOCS)
+ if(PYTHON_OK)
+ add_subdirectory(docs)
+ else()
+ message(STATUS "Building the documentation requires Python, but locating Python failed: ${PYTHON_ERR}")
+ endif()
+endif()
+
+###############################################################################
+### SSE ###
+
+messageonce("SSE Optimizations: ${OCIO_USE_SSE}")
+
+if(OCIO_USE_SSE)
+ if(WIN32)
+ # SSE instructions are automatically compiled into 64-bit applications so enabling the option is redundant and
+ # actually produces an unknown option warning in Visual Studio.
+ if(NOT CMAKE_CL_64)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2")
+ endif()
+ else()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
+ endif()
+ add_definitions("-DUSE_SSE")
+endif()
+
+###############################################################################
+### TRUELIGHT ###
+
+if(OCIO_BUILD_TRUELIGHT)
+ find_package(Truelight)
+ if(TRUELIGHT_FOUND)
+ messageonce("Will build the truelight transform support against ${Truelight_LIBRARY_DIR}")
+ add_definitions(-DOCIO_TRUELIGHT_SUPPORT)
+ set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${Truelight_INCLUDE_DIR})
+ set(EXTERNAL_COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS} ${Truelight_COMPILE_FLAGS}")
+ set(EXTERNAL_LINK_FLAGS "${EXTERNAL_LINK_FLAGS} ${Truelight_LINK_FLAGS}")
+ set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${Truelight_LIBRARIES})
+ else()
+ messageonce("Not building truelight transform support. Add the flag -D TRUELIGHT_INSTALL_PATH=... or set the TRUELIGHT_ROOT environment variable")
+ endif()
+endif()
+
+###############################################################################
+### CORE ###
+
+add_subdirectory(src/core)
+
+messageonce("Build Unit Tests: ${OCIO_BUILD_TESTS}")
+if(OCIO_BUILD_TESTS)
+ add_subdirectory(src/core_tests)
+endif()
+
+###############################################################################
+### APPS ###
+
+if(OCIO_BUILD_APPS)
+ # Try to find OpenImageIO (OIIO) and OpenGL stuff
+ OCIOFindOpenImageIO()
+
+ if(OIIO_FOUND)
+ add_subdirectory(src/apps/ocioconvert)
+ add_subdirectory(src/apps/ociolutimage)
+ else()
+ messageonce("Not building ocioconvert/ociolutimage. Requirement(s) found: OIIO:${OIIO_FOUND}")
+ endif()
+
+ # ociodisplay, displays color-transformed images (uses OpenImageIO,
+ # and OpenGL)
+ OCIOFindOpenGL()
+ if(OPENGL_FOUND AND GLUT_FOUND AND GLEW_FOUND AND OIIO_FOUND)
+ add_subdirectory(src/apps/ociodisplay)
+ else()
+ messageonce("Not building ociodisplay. Requirement(s) found, OpenGL:${OPENGL_FOUND}, GLUT:${GLUT_FOUND}, GLEW:${GLEW_FOUND}, OIIO:${OIIO_FOUND}")
+ endif()
+
+ # ociocheck: verifies an OCIO config
+ add_subdirectory(src/apps/ociocheck)
+
+ # ociobakelut writes out luts
+ add_subdirectory(src/apps/ociobakelut)
+endif()
+
+###############################################################################
+### NUKE ###
+
+if(OCIO_BUILD_NUKE)
+ find_package(Nuke)
+ if(NUKE_FOUND)
+ messageonce("Will build the Nuke plugins against ${Nuke_LIBRARY_DIR}")
+ add_subdirectory(src/nuke)
+ else()
+ messageonce("Not building Nuke plugins. Add the flag -D NUKE_INSTALL_PATH=... or set the NDK_PATH environment variable")
+ endif()
+endif()
+
+###############################################################################
+### PYGLUE ###
+
+if(OCIO_BUILD_PYGLUE)
+ if(PYTHON_OK)
+ add_subdirectory(src/pyglue)
+ else()
+ messageonce("Python bindings will not be built: ${PYTHON_ERR}")
+ endif()
+endif()
+
+###############################################################################
+### JNIGLUE ###
+
+if(OCIO_BUILD_JNIGLUE)
+ OCIOFindJava()
+ if(Java_FOUND)
+ add_subdirectory(src/jniglue)
+ else()
+ messageonce("Java bindings will not be built as we can't find Java")
+ endif()
+endif()
+
+###############################################################################
+### Configure env script ###
+configure_file(${CMAKE_SOURCE_DIR}/share/ocio/setup_ocio.sh.in
+ ${CMAKE_CURRENT_BINARY_DIR}/share/ocio/setup_ocio.sh @ONLY)
+
+INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/share/ocio/setup_ocio.sh DESTINATION share/ocio/)
+
+###############################################################################
+### CPACK ###
+
+set(CPACK_PACKAGE_VERSION_MAJOR ${SOVERSION})
+set(CPACK_PACKAGE_VERSION_MINOR ${OCIO_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${OCIO_VERSION_PATCH})
+set(CPACK_GENERATOR None)
+set(CPACK_SOURCE_GENERATOR TGZ)
+set(CPACK_SOURCE_PACKAGE_FILE_NAME "ocio.${OCIO_VERSION}")
+include(CPack)
+
+###############################################################################
+### CTEST ###
+
+add_custom_target(test_verbose
+ COMMAND ctest -VV
+ DEPENDS ocio_core_tests
+ COMMENT "Running ctest with verbose output")
+
+# Log CMake first run done
+SET(CMAKE_FIRST_RUN 0 CACHE INTERNAL "")
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..0893c24
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,301 @@
+**Version 1.0.8 (Dec 11 2012):**
+ * After Effects plugin
+ * Core increased precision for matrix inversion
+ * Core md5 symbols no longer leaked
+ * CMake compatibility with OIIO 1.0 namespacing
+ * Cmake option to control python soname
+ * Nuke register_viewers defaults OCIODisplay to "all"
+ * Nuke ColorLookup <-> spi1d lut examples
+ * Windows uses boost shared_ptr by default
+ * Windows fixed csp writing
+ * Windows build fixes
+ * ociobakelut supports looks
+
+**Version 1.0.7 (April 17 2012):**
+ * IRIDAS .look support
+ * ociolutimage utility added (handles image <-> 3dlut)
+ * CMake build allows optional reliance on system libraries
+ * CMake layout changes for python and nuke installs
+ * Bumped internals to yaml 0.3.0, pystring 1.1.2
+ * Optimized internal handling of Matrix / Exponent Ops
+ * Added INTERP_BEST interpolation option
+ * Python config.clearLooks() added
+ * Python docs revamp
+ * Nuke config-dependent knob values now baked into .nk scripts
+ * Nuke OCIOLookTransform gets reload button
+ * Nuke nodes get updated help text
+
+**Version 1.0.6 (March 12 2012):**
+ * JNI (Java) updates
+ * ocioconvert arbitrary attr support
+
+**Version 1.0.5 (Feb 22 2012):**
+ * Internal optimization framework added
+ * SetLoggingLevel(..) bugfix
+ * Python API Documentation / website updates
+ * Clang compilation fix
+
+**Version 1.0.4 (Jan 25 2012):**
+ * ocio2icc deprecated (functionality merged into ociobakelut)
+ * rv integration (beta)
+ * nuke: updated channel handling
+ * Documentation / website updates
+
+**Version 1.0.3 (Dec 21 2011):**
+ * Tetrahedral 3dlut interpolation (CPU only)
+ * ociocheck and Config.sanityCheck() have improved validation
+ * Mari: updated examples
+ * Makefile: misc updates to match distro library conventions
+
+**Version 1.0.2 (Nov 30 2011):**
+ * 3D lut processing (cpu) is resiliant to nans
+ * Nuke OCIOFileTransform gains Reload buttons
+ * Installation on multi-lib *nix systems improved
+ * Installation handling of soversion for C++/python improved
+ * ociobakelut improvements
+ * Initial version of Java bindings (alpha)
+
+**Version 1.0.1 (Oct 31 2011):**
+ * Luts with incorrect extension are properly loaded
+ * ocio2icc / ociobakelut get --lut option (no longer requires ocio config)
+ * DisplayTransform looks do not apply to 'data' passes.
+
+**Version 1.0.0 (Oct 3 2011):**
+ * ABI Lockoff for 1.0 branch
+ * General API Cleanup (removed deprecated / unnecessary functions)
+ * New features can be added, but the ABI will only be extended in a binary compatible manner.
+ Profiles written from 1.0 will always be readable in future versions.
+ * Fixed Truelight Reading Bug
+ * ocio2icc no longer requires ocio config (can provide raw lut(s)
+
+
+-------------------------------------------------------------------------------
+
+
+**Version 0.8.7 (Oct 3 2011):**
+ * Fixed Truelight Reading Bug
+
+**Version 0.8.6 (Sept 7 2011):**
+ * Updated .ocio config reading / writing to be forwards compatibile with 1.0
+ (Profiles written in 0.8.6+ will be 1.0 compatible. Compatibility from prior versions is likely, though not guaranteed.)
+ * Better logging
+ * Added ColorSpace.equalitygroup (makes ColorSpace equality explicit)
+ * Substantial Nuke node updates
+ * Added support for Iridas .itx read/write
+ * Windows Build Support
+
+**Version 0.8.5 (Aug 2 2011):**
+ * Nuke OCIODisplay fixed (bug from 0.8.4)
+ * Updated Houdini HDL Reader / Writer
+
+**Version 0.8.4 (July 25 2011):**
+ * Native Look Support
+ * Core / Nuke OCIODisplay supports alpha viewing
+ * Added Houdini (.lut) writing
+ * Added Pandora (.mga,.m3d) reading
+ * Additional internal bug fixes
+
+**Version 0.8.3 (June 27 2011):**
+ * OCIO::Config symlink resolution fixed (bugfix)
+ * Nuke OCIODisplay knobs use string storage (bugfix)
+ * Makefile cleanup
+ * Documentation cleanup
+
+**Version 0.8.2 (June 7 2011):**
+ * Numerous Windows compatibility fixes
+ * Python binding improvements
+ * OCIO::Baker / ociobakelut improvements
+ * Lut1D/3D do not crash on nans (bugfix)
+ * Nuke UI doesnt crash in known corner case (bugfix)
+
+**Version 0.8.1 (May 9 2011):**
+ * New roles: TEXTURE_PAINT + MATTE_PAINT
+ * Mari API Example (src/mari)
+ * FileFormat registry updated to allow Windows + Debug support
+ * boost_ptr build compatibility option
+
+**Version 0.8.0 (Apr 19 2011):**
+ * ABI Lockoff for stable 0.8 branch
+ New features can be added, but the ABI will only be extended in a binary compatible manner
+ * Otherwise identical to 0.7.9
+
+-------------------------------------------------------------------------------
+
+**Version 0.7.9 (Apr 18 2011):**
+ * Added support for .vf luts
+ * Misc. Nuke enhancements
+ * Adds optional boost ptr support (backwards compatibility)
+ * Makefile enhancements (Nuke / CMAKE_INSTALL_EXEC_PREFIX)
+ * cdlTransform.setXML crash fix
+
+**Version 0.7.8 (March 31 2011):**
+ * Iridas lut (.cube) bugfix, DOMAIN_MIN / DOMAIN_MAX now obeyed
+ * Exposed GPU functions in python (needed for Mari)
+ * Nuke OCIODisplay cleanup: Fixed knob names and added envvar support
+ * ociobaker cleanup
+ * tinyxml ABI visibility cleaned up
+ * Removed Boost dependency, tr1::shared_ptr now used instead
+
+**Version 0.7.7 (March 1 2011):**
+ * Lut baking API + standalone app
+ * Truelight runtime support (optional)
+ * Cinespace (3d) lut writing
+ * CSP prelut support
+ * Boost argparse dependency removed
+ * SanityCheck is more exhaustive
+ * FileTransform supports relative path dirs
+ * Python enhancements (transform kwarg support)
+ * Makefile enhancements (OIIO Path)
+ * Processor API update (code compatible, binary incompatible)
+
+**Version 0.7.6 (Feb 1 2011):**
+ * Updated Config Display API (.ocio config format updated)
+ * Added ocio2icc app (ICC Profile Generation)
+ * Revamp of ASC CDL, added .cc and .ccc support
+ * Documentation Improvements
+ * Makefile enhancements (Boost_INCLUDE_DIR, etc)
+
+**Version 0.7.5 (Jan 13 2011):**
+ * ociodisplay enhancements
+ * gpu display bugfix (glsl profile 1.0 only)
+ * Makefile enhancements
+ * Nuke installation cleanup
+ * Doc generation using sphinx (html + pdf)
+
+**Version 0.7.4 (Jan 4 2011):**
+ * Added 'Context', allowing for 'per-shot' Transforms
+ * Misc API Cleanup: removed old functions + fixed const-ness
+ * Added config.sanityCheck() for validation
+ * Additional Makefile configuration options, SONAME, etc.
+
+**Version 0.7.3 (Dec 16 2010):**
+ * Added example applications: ociodisplay, ocioconvert
+ * Makefile: Add boost header dependency
+ * Makefile: Nuke plugins are now version specific
+ * Fixed bug in GLSL MatrixOp
+
+**Version 0.7.2 (Dec 9 2010):**
+ * GPUAllocation refactor (API tweak)
+ * Added AllocationTransform
+ * Added LogTransform
+ * Removed CineonLogToLinTransform
+ * A few bug fixes
+
+**Version 0.7.1 (Nov 15 2010):**
+ * Additional 3d lut formats: Truelight .cub + Iridas .cube
+ * FileTransform supports envvars and search paths
+ * Added Nuke plugins: LogConvert + FileTransform
+ * Improved OCIO profile formatting
+ * GCC visibility used (when available) to hide private symbols
+ * A few bug fixes
+
+**Version 0.7.0 (Oct 21 2010):**
+ * Switched file format from XML to Yaml
+
+-------------------------------------------------------------------------------
+
+**Version 0.6.1 (Oct 5 2010):**
+ * Exposed ExponentTransform
+ * Added CineonLogToLinTransform - a simple 'straight-line' negative
+ linearization. Not strictly needed (could be done previously
+ with LUTs) but often convenient to have.
+ * Added DisplayTransform.displayCC for post display lut CC.
+ * Many python improvements
+ * A few bug fixes
+ * A few Makefile enhancements
+
+**Version 0.6.0 (Sept 21 2010):**
+ * Start of 0.6, "stable" branch
+
+ All 0.6.x builds will be ABI compatible (forward only).
+ New features (even experimental ones) will be added to the 0.6 branch,
+ as long as binary and source compatibility is maintained.
+ Once this no longer is possible, a 0.7 "dev" branch will be forked.
+
+ * Split public header into 3 parts for improved readability
+ (you still only import <OpenColorIO/OpenColorIO.h> though)
+ * Added MatrixTransform
+ * Refactored internal unit testing
+ * Fixed many compile warnings
+
+-------------------------------------------------------------------------------
+
+**Version 0.5.16 (Sept 16 2010):**
+ * PyTransforms now use native python class inheritance
+ * OCIO namespace can now be configured at build time (for distribution in commercial apps)
+ * Updated make install behavior
+ * DisplayTransform accepts generic cc operators (instead of CDL only)
+ * A few bug fixes / compile warning fixes
+
+**Version 0.5.15 (Sept 8 2010):**
+ * OCIO is well behaved when $OCIO is unset, allowing un-color-managed use.
+ * Color Transforms can be applied in python config->getProcessor
+ * Simplification of API (getColorSpace allows cs name, role names, and cs objects)
+ * Makefile enhancements (courtesy Malcolm Humphreys)
+ * A bunch of bug fixes
+
+**Version 0.5.14 (Sept 1 2010):**
+ * Python binding enhancements
+ * Simplified class implmentations (reduced internal header count)
+
+**Version 0.5.13 (Aug 24 2010):**
+ * GPU Processing now supports High Dynamic Range color spaces
+ * Added log processing operator
+ * Numerous bug fixes
+ * Numerous enhancements to python glue
+ * Exposed PyOpenColorIO header, for use in apps that require custom python glue
+ * Matrix op is optimized for diagonal-only subcases
+ * Numerous changes to Nuke Plugin (now with an addition node, OCIODisplay)
+
+**Version 0.5.12 (Aug 18 2010):**
+ * Additional DisplayTransform improvements
+ * Additional GPU Improvements
+ * Added op hashing (processor->getGPULut3DCacheID)
+
+**Version 0.5.11 (Aug 11 2010):**
+ * Initial DisplayTransform implementation
+ * ASC CDL Support
+ * Config Luma coefficients
+
+**Version 0.5.10 (July 22 2010):**
+ * Updated Nuke Plugin, now works in OSX
+ * Fixed misc. build warnings.
+ * Continued GPU progress (still under development)
+
+**Version 0.5.9 (June 28 2010):**
+ * Renamed project, classes, namespaces to OpenColorIO (OCIO)
+ * Added single-pixel processor path
+ * Improved python path makefile detection
+ * Continued GPU progress (still under development)
+
+**Version 0.5.8 (June 22 2010):**
+ * Support for .3dl
+ * Support for matrix ops
+ * Code refactor (added Processors) to support gpu/cpu model
+ * Much better error checking
+ * Compilation support for python 2.5
+ * Compilation support for OSX
+
+**Version 0.5.7 (June 14 2010):**
+ * Python API is much more fleshed out
+ * Improved public C++ header
+
+**Version 0.5.6 (June 8 2010):**
+ * PyConfig stub implementation
+ * Dropped ImageDesc.init; added PlanarImageDesc / PackedImageDesc
+ * Dropped tr1::shared_ptr; added boost::shared_ptr
+
+**Version 0.5.5 (June 4 2010):**
+ * .ocio supports path references
+ * Switch config envvar to $OCIO
+ * Added 3D lut processing ops
+
+**Version 0.5.4 (June 1 2010):**
+ * Initial Release
+ * CMake linux support
+ * XML OCIO format parsing / saving
+ * Example colorspace configuration with a few 'trivial' colorspaces
+ * Mutable colorspace configuration API
+ * Support for 1D lut processing
+ * Support for SPI 1D fileformats.
+ * Nuke plugin
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..b6d7aa5
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1 @@
+For install instructions, see docs/setup.rst
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6585e68
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,251 @@
+All code by Sony Pictures Imageworks except:
+
+Pystring
+http://code.google.com/p/pystring/
+
+TinyXML
+http://sourceforge.net/projects/tinyxml/
+
+yaml-cpp
+http://code.google.com/p/yaml-cpp/
+
+PTex (Mutex), courtesy of Brent Burley and Disney
+http://ptex.us/
+
+Little CMS
+http://www.littlecms.com/
+
+MD5, courtesy L. Peter Deutsch, Aladdin Enterprises.
+http://sourceforge.net/projects/libmd5-rfc/files/
+
+argparse, courtesy OpenImageIO and Larry Gritz
+http://openimageio.org
+
+---------------------------------------------------------------------
+
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------------------
+
+Pystring
+
+Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+Neither the name of the organization Sony Pictures Imageworks nor the
+names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------------------
+
+TinyXML is released under the zlib license:
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+---------------------------------------------------------------------
+
+yaml-cpp
+
+Copyright (c) 2008 Jesse Beder.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+---------------------------------------------------------------------
+
+PTEX SOFTWARE
+Copyright 2009 Disney Enterprises, Inc. All rights reserved
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
+ Studios" or the names of its contributors may NOT be used to
+ endorse or promote products derived from this software without
+ specific prior written permission from Walt Disney Pictures.
+
+Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
+IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+---------------------------------------------------------------------
+
+Little CMS
+Copyright (c) 1998-2010 Marti Maria Saguer
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+---------------------------------------------------------------------
+
+MD5
+
+Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+L. Peter Deutsch
+ghost@aladdin.com
+
+---------------------------------------------------------------------
+
+argparse
+
+Copyright 2008 Larry Gritz and the other authors and contributors.
+All Rights Reserved.
+Based on BSD-licensed software Copyright 2004 NVIDIA Corp.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+* Neither the name of the software's owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(This is the Modified BSD License) \ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..587d6e1
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+OpenColorIO (OCIO) is a complete color management solution geared towards motion
+picture production with an emphasis on visual effects and computer animation.
+OCIO provides a straightforward and consistent user experience across all
+supporting applications while allowing for sophisticated back-end configuration
+options suitable for high-end production usage. OCIO is compatible with the
+Academy Color Encoding Specification (ACES) and is LUT-format agnostic,
+supporting many popular formats.
+
+OpenColorIO is released as version 1.0 and has been in development since 2003.
+OCIO represents the culmination of years of production experience earned on such
+films as SpiderMan 2 (2004), Surf's Up (2007), Cloudy with a Chance of Meatballs
+(2009), Alice in Wonderland (2010), and many more. OpenColorIO is natively
+supported in commercial applications like Katana, Mari, Silhouette FX, and others
+coming soon.
+
+OpenColorIO is `free <http://opencolorio.org/License.html>`__ and is one of
+several open source projects actively sponsored by `Sony Imageworks
+<http://opensource.imageworks.com>`__.
+
+http://opencolorio.org
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..1b4841d
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,15 @@
+opencolorio (1.0.8~dfsg0-2) unstable; urgency=low
+
+ * debian/rules: get-orig-source stuff added
+ * debian/rules: useless dh addon removed
+ * debian/rules: License.txt duplicate removed
+ * debian/rules: SSE optimization disabled (Closes: #719174)
+ * debian/libopencolorio1.symbols: file removed (Closes: #719175)
+
+ -- Matteo F. Vescovi <mfv.debian@gmail.com> Tue, 20 Aug 2013 10:53:19 +0200
+
+opencolorio (1.0.8~dfsg0-1) unstable; urgency=low
+
+ * Initial release (Closes: #700676)
+
+ -- Matteo F. Vescovi <mfv.debian@gmail.com> Wed, 12 Jun 2013 14:54:06 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..002bece
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,171 @@
+Source: opencolorio
+Section: libs
+Priority: extra
+Maintainer: Debian PhotoTools Maintainers <pkg-phototools-devel@lists.alioth.debian.org>
+Uploaders: Matteo F. Vescovi <mfv.debian@gmail.com>
+Build-Depends:
+ cmake,
+ debhelper (>= 9),
+ junit4,
+ libglew-dev,
+ liblcms2-dev,
+ libopenimageio-dev,
+ libqt4-opengl-dev,
+ libtinyxml-dev,
+ libyaml-cpp-dev,
+ pkg-config,
+ python-dev,
+ python-docutils,
+ python-jinja2,
+ python-pygments,
+ python-setuptools,
+ python-sphinx,
+ texlive-fonts-recommended,
+ texlive-latex-base,
+ texlive-latex-extra,
+ texlive-latex-recommended
+X-Python-Version: >= 2.7
+Standards-Version: 3.9.4
+Homepage: http://opencolorio.org
+Vcs-Git: git://anonscm.debian.org/pkg-phototools/opencolorio.git
+Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-phototools/opencolorio.git
+
+Package: libopencolorio-dev
+Section: libdevel
+Architecture: any
+Depends: libopencolorio1 (= ${binary:Version}),
+ ${misc:Depends}
+Description: complete color management solution - development
+ OpenColorIO (OCIO) is a complete color management solution geared
+ towards motion picture production with an emphasis on visual effects
+ and computer animation. OCIO provides a straightforward and consistent
+ user experience across all supporting applications while allowing for
+ sophisticated back-end configuration options suitable for high-end
+ production usage. OCIO is compatible with the Academy Color Encoding
+ Specification (ACES) and is LUT-format agnostic, supporting many
+ popular formats.
+ .
+ OpenColorIO is released as version 1.0 and has been in development
+ since 2003. OCIO represents the culmination of years of production
+ experience earned on such films as SpiderMan 2 (2004), Surf's Up
+ (2007), Cloudy with a Chance of Meatballs (2009), Alice in Wonderland
+ (2010), and many more. OpenColorIO is natively supported in commercial
+ applications like Katana, Mari, Silhouette FX, and others coming soon.
+ .
+ OpenColorIO is free and is one of several open source projects
+ actively sponsored by Sony Imageworks.
+ .
+ This package provides the development files used to build applications
+ using libopencolorio.
+
+Package: libopencolorio1
+Section: libdevel
+Architecture: any
+Depends: ${misc:Depends},
+ ${shlibs:Depends}
+Description: complete color management solution - runtime
+ OpenColorIO (OCIO) is a complete color management solution geared
+ towards motion picture production with an emphasis on visual effects
+ and computer animation. OCIO provides a straightforward and consistent
+ user experience across all supporting applications while allowing for
+ sophisticated back-end configuration options suitable for high-end
+ production usage. OCIO is compatible with the Academy Color Encoding
+ Specification (ACES) and is LUT-format agnostic, supporting many
+ popular formats.
+ .
+ OpenColorIO is released as version 1.0 and has been in development
+ since 2003. OCIO represents the culmination of years of production
+ experience earned on such films as SpiderMan 2 (2004), Surf's Up
+ (2007), Cloudy with a Chance of Meatballs (2009), Alice in Wonderland
+ (2010), and many more. OpenColorIO is natively supported in commercial
+ applications like Katana, Mari, Silhouette FX, and others coming soon.
+ .
+ OpenColorIO is free and is one of several open source projects
+ actively sponsored by Sony Imageworks.
+ .
+ This package provides the runtime files used to run applications
+ built against libopencolorio.
+
+Package: opencolorio-tools
+Section: utils
+Architecture: any
+Depends: ${misc:Depends},
+ ${shlibs:Depends}
+Description: complete color management solution - utilities
+ OpenColorIO (OCIO) is a complete color management solution geared
+ towards motion picture production with an emphasis on visual effects
+ and computer animation. OCIO provides a straightforward and consistent
+ user experience across all supporting applications while allowing for
+ sophisticated back-end configuration options suitable for high-end
+ production usage. OCIO is compatible with the Academy Color Encoding
+ Specification (ACES) and is LUT-format agnostic, supporting many
+ popular formats.
+ .
+ OpenColorIO is released as version 1.0 and has been in development
+ since 2003. OCIO represents the culmination of years of production
+ experience earned on such films as SpiderMan 2 (2004), Surf's Up
+ (2007), Cloudy with a Chance of Meatballs (2009), Alice in Wonderland
+ (2010), and many more. OpenColorIO is natively supported in commercial
+ applications like Katana, Mari, Silhouette FX, and others coming soon.
+ .
+ OpenColorIO is free and is one of several open source projects
+ actively sponsored by Sony Imageworks.
+ .
+ This package provides some utilities.
+
+Package: opencolorio-doc
+Section: doc
+Architecture: all
+Depends: libjs-jquery,
+ libjs-underscore,
+ ${misc:Depends}
+Description: complete color management solution - documentation
+ OpenColorIO (OCIO) is a complete color management solution geared
+ towards motion picture production with an emphasis on visual effects
+ and computer animation. OCIO provides a straightforward and consistent
+ user experience across all supporting applications while allowing for
+ sophisticated back-end configuration options suitable for high-end
+ production usage. OCIO is compatible with the Academy Color Encoding
+ Specification (ACES) and is LUT-format agnostic, supporting many
+ popular formats.
+ .
+ OpenColorIO is released as version 1.0 and has been in development
+ since 2003. OCIO represents the culmination of years of production
+ experience earned on such films as SpiderMan 2 (2004), Surf's Up
+ (2007), Cloudy with a Chance of Meatballs (2009), Alice in Wonderland
+ (2010), and many more. OpenColorIO is natively supported in commercial
+ applications like Katana, Mari, Silhouette FX, and others coming soon.
+ .
+ OpenColorIO is free and is one of several open source projects
+ actively sponsored by Sony Imageworks.
+ .
+ This package provides the documentation.
+
+Package: python-pyopencolorio
+Section: python
+Architecture: any
+Depends: libopencolorio1 (= ${binary:Version}),
+ ${misc:Depends},
+ ${python:Depends},
+ ${shlibs:Depends}
+Description: complete color management solution - python bindings
+ OpenColorIO (OCIO) is a complete color management solution geared
+ towards motion picture production with an emphasis on visual effects
+ and computer animation. OCIO provides a straightforward and consistent
+ user experience across all supporting applications while allowing for
+ sophisticated back-end configuration options suitable for high-end
+ production usage. OCIO is compatible with the Academy Color Encoding
+ Specification (ACES) and is LUT-format agnostic, supporting many
+ popular formats.
+ .
+ OpenColorIO is released as version 1.0 and has been in development
+ since 2003. OCIO represents the culmination of years of production
+ experience earned on such films as SpiderMan 2 (2004), Surf's Up
+ (2007), Cloudy with a Chance of Meatballs (2009), Alice in Wonderland
+ (2010), and many more. OpenColorIO is natively supported in commercial
+ applications like Katana, Mari, Silhouette FX, and others coming soon.
+ .
+ OpenColorIO is free and is one of several open source projects
+ actively sponsored by Sony Imageworks.
+ .
+ This package provides Python bindings to the OpenColorIO library.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..ef075a4
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,77 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: opencolorio
+Source: https://github.com/imageworks/OpenColorIO
+
+Files: *
+Copyright: 2003-2010 Sony Pictures Imageworks Inc., et al.
+License: BSD-3-Clause
+
+Files: debian/*
+Copyright: 2013 Matteo F. Vescovi <mfv.debian@gmail.com>
+License: BSD-3-Clause
+
+Files: docs/ociotheme/static/*
+Copyright: 2008-2009, Haiku.
+License: MIT
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+ .
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Files: src/core/md5/*
+Copyright: 1999, 2002 Aladdin Enterprises
+License: zlib
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+ .
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+ .
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+License: BSD-3-Clause
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..e845566
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1 @@
+README
diff --git a/debian/examples b/debian/examples
new file mode 100644
index 0000000..dd22b73
--- /dev/null
+++ b/debian/examples
@@ -0,0 +1 @@
+debian/cmake/share/ocio/setup_ocio.sh
diff --git a/debian/libopencolorio-dev.install b/debian/libopencolorio-dev.install
new file mode 100644
index 0000000..8c14d24
--- /dev/null
+++ b/debian/libopencolorio-dev.install
@@ -0,0 +1,3 @@
+usr/include/OpenColorIO
+usr/lib/lib*.so
+usr/lib/pkgconfig
diff --git a/debian/libopencolorio1.install b/debian/libopencolorio1.install
new file mode 100644
index 0000000..d0dbfd1
--- /dev/null
+++ b/debian/libopencolorio1.install
@@ -0,0 +1 @@
+usr/lib/lib*.so.*
diff --git a/debian/manpages/ociobakelut.1 b/debian/manpages/ociobakelut.1
new file mode 100644
index 0000000..8804c54
--- /dev/null
+++ b/debian/manpages/ociobakelut.1
@@ -0,0 +1,99 @@
+.TH OCIOBAKELUT 1
+.SH NAME
+ociobakelut \- create a new LUT or icc profile from an OCIO config or lut file(s)
+.SH SYNOPSIS
+.B ociobakelut
+.RI [ options ] " output-file" ...
+.SH DESCRIPTION
+This manual page documents briefly the
+.B ociobakelut
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBociobakelut\fP is a program which bakes a color transform into various color
+lookup file formats ("a LUT")
+.PP
+This is intended for applications that have not directly integrated
+OCIO, but can load LUT files
+.PP
+.SH OPTIONS
+A summary of options is included below.
+.TP
+.BI "\-\-inputspace " space
+Input OCIO ColorSpace (or Role)
+.TP
+.BI "\-\-outputspace " space
+Output OCIO ColorSpace (or Role)
+.TP
+.BI "\-\-shaperspace " space
+the OCIO ColorSpace or Role, for the shaper
+.TP
+.BI "\-\-looks " looks
+the OCIO looks to apply
+.TP
+.BI "\-\-iconfig " configfile
+.PP
+Input .ocio configuration file (default: $OCIO)
+Config-Free LUT Baking
+.TP
+.BI "\-\-lut " lut
+Specify a LUT (forward direction)
+.TP
+.BI "\-\-invlut " lut
+Specify a LUT (inverse direction)
+.TP
+.BI "\-\-slope " "x y z"
+slope
+.TP
+.BI "\-\-offset " "x y z"
+offset (float)
+.TP
+.BI "\-\-offset10 " "x y z"
+offset (10-bit)
+.TP
+.BI "\-\-power " "x y z"
+power
+.TP
+.BI "\-\-sat " x
+saturation (ASC-CDL luma coefficients)
+.PP
+Baking options
+.TP
+.BI "\-\-format " format
+.TP
+.BI "\-\-shapersize ' n
+size of the shaper (default: format specific)
+.TP
+.BI "\-\-cubesize " n
+size of the cube (default: format specific)
+.TP
+.B "\-\-stdout"
+Write to stdout (rather than file)
+.PP
+ICC Options
+.TP
+.BI "\-\-whitepoint " n
+whitepoint for the profile (default: 6505)
+.BI "\-\-displayicc " s
+an icc profile which matches the OCIO profiles target display
+.BI "\-\-description " s
+a meaningful description, this will show up in UI like photoshop
+.BI "\-\-copyright " s
+a copyright field
+.PP
+other options
+.TP
+.B "\-\-v"
+Verbose
+.TP
+.B \-\-help
+Show summary of options.
+.TP
+.SH SEE ALSO
+.BR ociocheck (1),
+.BR ocioconvert (1),
+.BR ociolutimage (1).
+.br
+.B /usr/share/doc/opencolorio/OpenColorIO.pdf
diff --git a/debian/manpages/ociocheck.1 b/debian/manpages/ociocheck.1
new file mode 100644
index 0000000..2a17fff
--- /dev/null
+++ b/debian/manpages/ociocheck.1
@@ -0,0 +1,35 @@
+.TH OCIOCHECK 1
+.SH NAME
+ociocheck \- validate an OpenColorIO configuration
+.SH SYNOPSIS
+.B ociocheck
+.RI [ options ] " output-file" ...
+.SH DESCRIPTION
+This manual page documents briefly the
+.B ociocheck
+command.
+.PP
+\fBociocheck\fP validates the specified .ocio configuration,
+and checks that all the color transforms are defined.
+For example, it is possible that the configuration may reference
+lookup tables that do not exist. ociocheck will find these cases.
+
+ociocheck can also be used to clean up formatting on an existing profile
+that has been manually edited, using the '\-o' option.
+.SH OPTIONS
+A summary of options is included below.
+.TP
+.BI "\-\-help " space
+print help message
+.TP
+.BI "\-\-iconfig " configfile
+Input .ocio configuration file (default: $OCIO)
+.TP
+.BI "\-\-oconfig " configfile
+Output .ocio file
+.SH SEE ALSO
+.BR ociobakelut (1),
+.BR ocioconvert (1),
+.BR ociolutimage (1).
+.br
+.B /usr/share/doc/opencolorio/OpenColorIO.pdf
diff --git a/debian/manpages/ocioconvert.1 b/debian/manpages/ocioconvert.1
new file mode 100644
index 0000000..e209caf
--- /dev/null
+++ b/debian/manpages/ocioconvert.1
@@ -0,0 +1,28 @@
+.TH OCIOCONVERT 1
+.SH NAME
+ocioconvert \- apply colorspace transform to an image
+.SH SYNOPSIS
+.B ocioconvert
+.RI [ options ] " output-file" ...
+.SH DESCRIPTION
+This manual page documents briefly the
+.B ocioconvert
+command.
+.SH OPTIONS
+A summary of options is included below.
+.TP
+.TP
+.BI "\-\-float\-attribute " N=F
+name=float pair defining OCIO float atribute
+.TP
+.BI "\-\-int\-attribute " N=I
+name=int pair defining OCIO int atribute
+.TP
+.BI "\-\-string\-attribute " N=S
+name=string pair defining OCIO string atribute
+.SH SEE ALSO
+.BR ociobakelut (1),
+.BR ociocheck (1),
+.BR ociolutimage (1).
+.br
+.B /usr/share/doc/opencolorio/OpenColorIO.pdf
diff --git a/debian/manpages/ociolutimage.1 b/debian/manpages/ociolutimage.1
new file mode 100644
index 0000000..54100c6
--- /dev/null
+++ b/debian/manpages/ociolutimage.1
@@ -0,0 +1,43 @@
+.TH OCIOLUTIMAGE 1
+.SH NAME
+ociolutimage \- Convert a 3dlut to or from an image
+.SH SYNOPSIS
+.B ociolutimage
+.RI [ options ] " output-file" ...
+.SH DESCRIPTION
+This manual page documents briefly the
+.B ociolutimage
+command.
+.PP
+.SH OPTIONS
+A summary of options is included below.
+.TP
+.BI \-\-generate
+Generate a lattice image
+.TP
+.BI \-\-extract
+Extract a 3dlut from an input image
+.TP
+.BI "\-\-input " file
+Specify the input filename
+.TP
+.BI "\-\-output " file
+Specify the output filename
+.TP
+.BI "\-\-cubesize " n
+Size of the cube (default: 32)
+.TP
+.BI "\-\-maxwidth " n
+Specify maximum width of the image (default: 2048)
+.TP
+.BI "\-\-config " file
+\&.ocio configuration file (default: $OCIO)
+.TP
+.BI "\-\-colorconvert " "in out"
+Apply a color space conversion to the image.
+.SH SEE ALSO
+.BR ociobakelut (1),
+.BR ocioconvert (1),
+.BR ocioconvert (1).
+.br
+.B /usr/share/doc/opencolorio/OpenColorIO.pdf
diff --git a/debian/opencolorio-doc.doc-base b/debian/opencolorio-doc.doc-base
new file mode 100644
index 0000000..fc19136
--- /dev/null
+++ b/debian/opencolorio-doc.doc-base
@@ -0,0 +1,11 @@
+Document: opencolorio
+Title: Debian OpenColorIO Manual
+Section: Programming/C++
+
+Format: HTML
+Index: /usr/share/doc/opencolorio/html/genindex.html
+Files: /usr/share/doc/opencolorio/html/*.html
+
+Format: Text
+Index: /usr/share/doc/opencolorio/html/_sources/index.txt
+Files: /usr/share/doc/opencolorio/html/_sources/*.txt
diff --git a/debian/opencolorio-doc.install b/debian/opencolorio-doc.install
new file mode 100644
index 0000000..e858050
--- /dev/null
+++ b/debian/opencolorio-doc.install
@@ -0,0 +1 @@
+usr/share/doc/opencolorio
diff --git a/debian/opencolorio-doc.links b/debian/opencolorio-doc.links
new file mode 100644
index 0000000..8c647fa
--- /dev/null
+++ b/debian/opencolorio-doc.links
@@ -0,0 +1,2 @@
+usr/share/javascript/jquery/jquery.js usr/share/doc/opencolorio/html/_static/jquery.js
+usr/share/javascript/underscore/underscore.js usr/share/doc/opencolorio/html/_static/underscore.js
diff --git a/debian/opencolorio-tools.install b/debian/opencolorio-tools.install
new file mode 100644
index 0000000..e772481
--- /dev/null
+++ b/debian/opencolorio-tools.install
@@ -0,0 +1 @@
+usr/bin
diff --git a/debian/opencolorio-tools.manpages b/debian/opencolorio-tools.manpages
new file mode 100644
index 0000000..4cd44fd
--- /dev/null
+++ b/debian/opencolorio-tools.manpages
@@ -0,0 +1 @@
+debian/manpages/*.1
diff --git a/debian/patches/0001-Fix_built-in_documentation_dependencies.patch b/debian/patches/0001-Fix_built-in_documentation_dependencies.patch
new file mode 100644
index 0000000..a2d4216
--- /dev/null
+++ b/debian/patches/0001-Fix_built-in_documentation_dependencies.patch
@@ -0,0 +1,116 @@
+From: "Matteo F. Vescovi" <mfv.debian@gmail.com>
+Date: Wed, 12 Jun 2013 12:21:44 +0200
+Subject: Fix_built-in_documentation_dependencies
+
+---
+ CMakeLists.txt | 5 +----
+ docs/CMakeLists.txt | 62 ++---------------------------------------------------
+ 2 files changed, 3 insertions(+), 64 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 3e36ca5..a0e6adb 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -135,15 +135,12 @@ else()
+ # construct the external project path
+ OCIOFindPython()
+
+- set(EXTDIST_ROOT ${CMAKE_BINARY_DIR}/ext/dist)
+- set(EXTDIST_BINPATH ${EXTDIST_ROOT}/bin)
+ if(PYTHON_OK)
+- set(EXTDIST_PYTHONPATH ${EXTDIST_ROOT}/lib/python${PYTHON_VERSION}/site-packages)
++ set(EXTDIST_PYTHONPATH /usr/lib/python${PYTHON_VERSION}/dist-packages)
+ set(PYTHONPATH ${EXTDIST_PYTHONPATH}:$ENV{PYTHONPATH})
+ endif()
+ endif()
+
+-messageonce("Setting EXTDIST_BINPATH: ${EXTDIST_BINPATH}")
+ messageonce("Setting EXTDIST_PYTHONPATH: ${EXTDIST_PYTHONPATH}")
+
+ ###############################################################################
+diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
+index 0cbfd67..e15db13 100644
+--- a/docs/CMakeLists.txt
++++ b/docs/CMakeLists.txt
+@@ -1,63 +1,5 @@
+
+ ###############################################################################
+-### External Doc Apps ###
+-
+-# setuptools
+-set(SETUPTOOLS_VERSION 0.6c11)
+-ExternalProject_Add(setuptools
+- URL ${CMAKE_SOURCE_DIR}/ext/setuptools-${SETUPTOOLS_VERSION}.tar.gz
+- BUILD_IN_SOURCE 1
+- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+- BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+- INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+-)
+-
+-# docutils
+-set(DOCUTILS_VERSION 0.7)
+-ExternalProject_Add(docutils
+- DEPENDS setuptools
+- URL ${CMAKE_SOURCE_DIR}/ext/docutils-${DOCUTILS_VERSION}.tar.gz
+- BUILD_IN_SOURCE 1
+- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+- BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+- INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+-)
+-
+-# jinja2
+-set(JINJA2_VERSION 2.5.5)
+-ExternalProject_Add(Jinja2
+- DEPENDS setuptools
+- URL ${CMAKE_SOURCE_DIR}/ext/Jinja2-${JINJA2_VERSION}.tar.gz
+- BUILD_IN_SOURCE 1
+- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+- BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+- INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+-)
+-
+-# Pygments
+-set(PYGMENTS_VERSION 1.3.1)
+-ExternalProject_Add(Pygments
+- DEPENDS setuptools
+- URL ${CMAKE_SOURCE_DIR}/ext/Pygments-${PYGMENTS_VERSION}.tar.gz
+- BUILD_IN_SOURCE 1
+- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+- BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+- INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT}
+-)
+-
+-# sphinx
+-set(SPHINX_VERSION f52b631f501a) # 1.1pre
+-ExternalProject_Add(Sphinx
+- DEPENDS setuptools docutils Jinja2 Pygments
+- URL ${CMAKE_SOURCE_DIR}/ext/sphinx-${SPHINX_VERSION}.tar.gz
+- PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/ext/sphinx-${SPHINX_VERSION}.patch
+- BUILD_IN_SOURCE 1
+- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${EXTDIST_PYTHONPATH}
+- BUILD_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py build
+- INSTALL_COMMAND PYTHONPATH=${PYTHONPATH} python setup.py install --prefix=${EXTDIST_ROOT} --install-scripts=${EXTDIST_ROOT}/bin
+-)
+-
+-###############################################################################
+ ### Create Doc Targets ###
+
+ message(STATUS "Create sphinx conf.py from conf.py.in")
+@@ -81,7 +23,7 @@ ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorTransforms.h devel
+ ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorTypes.h developers/api/OpenColorTypes.rst)
+
+ add_custom_target(doc ALL
+- COMMAND PYTHONPATH=${PYTHONPATH} ${EXTDIST_BINPATH}/sphinx-build -b html . ${CMAKE_CURRENT_BINARY_DIR}/build-html
++ COMMAND PYTHONPATH=${PYTHONPATH} sphinx-build -b html . ${CMAKE_CURRENT_BINARY_DIR}/build-html
+ DEPENDS
+ OpenColorIO
+ PyOpenColorIO
+@@ -106,7 +48,7 @@ find_package(LATEX)
+ if(PDFLATEX_COMPILER)
+
+ add_custom_target(latex
+- COMMAND PYTHONPATH=${PYTHONPATH} ${EXTDIST_BINPATH}/sphinx-build -b latex . ${CMAKE_CURRENT_BINARY_DIR}/build-latex
++ COMMAND PYTHONPATH=${PYTHONPATH} sphinx-build -b latex . ${CMAKE_CURRENT_BINARY_DIR}/build-latex
+ DEPENDS
+ OpenColorIO
+ ${CMAKE_BINARY_DIR}/docs/conf.py
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..9db761e
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+0001-Fix_built-in_documentation_dependencies.patch
diff --git a/debian/python-pyopencolorio.install b/debian/python-pyopencolorio.install
new file mode 100644
index 0000000..a99b715
--- /dev/null
+++ b/debian/python-pyopencolorio.install
@@ -0,0 +1,2 @@
+usr/include/PyOpenColorIO
+usr/lib/python2.7/site-packages/*.so usr/lib/python2.7/dist-packages/
diff --git a/debian/repack.local b/debian/repack.local
new file mode 100644
index 0000000..ea04873
--- /dev/null
+++ b/debian/repack.local
@@ -0,0 +1,2 @@
+SUFFIX=~dfsg0
+rm ext/
diff --git a/debian/repack.sh b/debian/repack.sh
new file mode 100755
index 0000000..a3bb5f9
--- /dev/null
+++ b/debian/repack.sh
@@ -0,0 +1,161 @@
+#!/bin/sh
+
+# see the repack.stub for how to use
+
+# TODO: provide example watch files and repack.locals
+# TODO: test suite. problems fixed that need to be tested:
+# * globbing
+# * whitespace and then comments in the MANIFEST
+# TODO: does / in weird places work? test suite too.
+# TODO: I actually broke stuff with the MANIFEST change not thinking..
+# TODO: allow for a sepearate (and multiple) MANIFEST files, then
+# de-uglify libsyntax-highlight-engine-kate-perl.
+# TODO: have each mv and rm check that something actually changed, and
+# if not, die
+
+set -e
+set -u
+
+usage() {
+ echo "Usage: repack.sh --upstream-version <ver> <downloaded file>"
+ exit 1
+}
+
+if [ "$#" != "3" ]; then
+ usage
+fi
+if [ "$1" != "--upstream-version" ]; then
+ usage
+fi
+if [ ! -f "$3" ]; then
+ if [ -n "$3" ]; then
+ echo "$3 doesn't exist"
+ fi
+ usage
+fi
+VER="$2"
+FILE="$3"
+PKG=`dpkg-parsechangelog|grep ^Source:|sed 's/^Source: //'`
+
+SUFFIX="~dfsg"
+
+echo
+echo "Repackaging $FILE"
+echo
+
+DIR=`mktemp -d ./tmpRepackXXXXXX`
+DIR=$(readlink -f "$DIR")
+trap "/bin/rm -rf \"$DIR\"" QUIT INT EXIT
+
+# Create an extra directory to cope with rootless tarballs
+UP_BASE="$DIR/unpack"
+mkdir "$UP_BASE"
+tar xf "$FILE" -C "$UP_BASE" || unzip "$FILE" -d "$UP_BASE"
+
+if [ `ls -1 "$UP_BASE" | wc -l` -eq 1 ]; then
+ # Tarball does contain a root directory
+ UP_BASE="$UP_BASE/`ls -1 "$UP_BASE"`"
+fi
+
+RM_OPTS="-vrf"
+
+real_rm(){
+ /bin/rm "$@"
+}
+
+real_mv(){
+ /bin/mv "$@"
+}
+
+rm(){
+ set +f
+ MYOLDPWD=$(pwd)
+ cd "$UP_BASE"
+ if [ "$MANIFEST" = "1" ]; then
+ PERM=$(stat --format=%a "MANIFEST")
+ chmod u+w "MANIFEST"
+ fi
+ for i in $@; do
+ if [ "$MANIFEST" = "1" ]; then
+ PATTERN="^$i"
+ if [ -d "$i" ]; then
+ if ! { echo "$PATTERN" | grep -q "/$" ; }; then
+ PATTERN="${PATTERN}/"
+ fi
+ else
+ PATTERN="${PATTERN}\s?"
+ fi
+ grep -Ev "$PATTERN" "MANIFEST" > "$DIR/MANIFEST"
+ real_mv "$DIR/MANIFEST" "MANIFEST"
+ fi
+ real_rm "$RM_OPTS" "$i"
+ done
+ if [ "$MANIFEST" = "1" ]; then
+ chmod $PERM "MANIFEST"
+ fi
+ cd $MYOLDPWD
+ set -f
+}
+
+mv(){
+ set +f
+ OLD=$(pwd)
+ cd $UP_BASE
+ real_mv "$@"
+ cd $OLD
+ if [ "$MANIFEST" = "1" ]; then
+ echo "MANIFEST cannot be manipulated with mv yet, patches welcome"
+ exit 1
+ fi
+ set -f
+}
+
+# bump with incompatible changes
+REPACK_VERSION=3
+
+requires_version(){
+ if [ $REPACK_VERSION -lt $1 ]; then
+ echo "repack.sh is not up to date enough for this package. you need at least version $1, while this script is only version $REPACK_VERSION"
+ exit 1
+ fi
+}
+
+MANIFEST=0
+## Remove stuff
+set -f
+MYORIGPWD=$(pwd)
+cd "$UP_BASE"
+. "$MYORIGPWD/debian/repack.local"
+cd $MYORIGPWD
+set +f
+## End
+
+REPACK_DIR="$PKG-${VER}${SUFFIX}.orig" # DevRef § 6.7.8.2
+DFSG_TAR="$(dirname $FILE)/${PKG}_${VER}${SUFFIX}.orig.tar"
+
+real_mv "$UP_BASE" "$DIR/$REPACK_DIR"
+
+# .gz or .bz2?
+FILETYPE=$(file --brief --mime-type --dereference "$FILE")
+case "$FILETYPE" in
+ application/x-gzip|application/gzip|application/zip)
+ C_PROGRAM="gzip"
+ C_SUFFIX="gz"
+ ;;
+ application/x-bzip2)
+ C_PROGRAM="bzip2"
+ C_SUFFIX="bz2"
+ ;;
+ *)
+ echo "E: Unknown filetye $FILETYPE"
+ exit 1
+ ;;
+esac
+
+# Using a pipe hides tar errors!
+tar cfC "$DIR/repacked.tar" "$DIR" "$REPACK_DIR"
+$C_PROGRAM -9 < "$DIR/repacked.tar" > "$DIR/repacked.tar.$C_SUFFIX"
+
+real_mv "$DIR/repacked.tar.$C_SUFFIX" "$DFSG_TAR.$C_SUFFIX"
+
+echo "*** $DFSG_TAR.$C_SUFFIX ready"
diff --git a/debian/repack.stub b/debian/repack.stub
new file mode 100644
index 0000000..a07c135
--- /dev/null
+++ b/debian/repack.stub
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+: <<=cut
+=pod
+
+=head1 NAME
+
+repack.stub - script to repack upstream tarballs from uscan
+
+=head1 INSTRUCTIONS
+
+put this in debian/repack.stub and add "debian sh debian/repack.stub" to
+the end of the line in debian/watch. you will also need to add a version
+mangle to debian/watch.
+
+then create a debian/repack.local. this is a shell script that is
+sources under "set -e", so be careful to check returns codes.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item rm
+
+rm is replaced by a function that does some magic ("rm -rv" by default), but also changes MANIFEST if $MANIFEST is 1
+
+=item mv
+
+mv is replaced by a function that just does mv (by default), but also changes MANIFEST if $MANIFEST is 1
+
+=item requires_version
+
+requires_version is there for future usage for requiring certain versions of the script
+
+=back
+
+=head1 VARIABLES
+
+=over 4
+
+=item SUFFIX
+
+defaults to ~dfsg
+
+what to append to the upstream version
+
+=item RM_OPTS
+
+defaults to -vrf
+
+options to pass to rm
+
+=item MANIFEST
+
+defaults to 0, set to 1 to turn on.
+
+this will manipulate MANIFEST files in CPAN tarballs.
+
+=item UP_BASE
+
+this is the directory where the upstream source is.
+
+=back
+
+=cut
+
+if [ -z "$REPACK_SH" ]; then
+ if [ -f ../../scripts/repack.sh ]; then
+ REPACK_SH=../../scripts/repack.sh
+ fi
+ if [ -z "$REPACK_SH" ] && which repack.sh > /dev/null; then
+ REPACK_SH=$(which repack.sh)
+ fi
+fi
+
+if [ ! -f "$REPACK_SH" ]; then
+ echo "Couldn't find a repack.sh. please put it in your PATH, put it at ../../scripts/repack.sh, or put it somewhere else and set the REPACK_SH variable"
+ echo "You can get it from http://svn.debian.org/viewsvn/pkg-perl/scripts/repack.sh"
+ exit 1
+fi
+
+exec "$REPACK_SH" "$@"
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..a4432d3
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,40 @@
+#!/usr/bin/make -f
+
+CXXFLAGS = $(shell dpkg-buildflags --get CXXFLAGS)
+CPPFLAGS = $(shell dpkg-buildflags --get CPPFLAGS)
+export LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS)
+export REPACK_SH=$(CURDIR)/debian/repack.sh
+BLDDIR = debian/cmake
+INSTDIR = debian/tmp
+
+%:
+ dh $@ -Scmake -B$(BLDDIR) --parallel --with python2
+
+override_dh_auto_configure:
+ dh_auto_configure -- \
+ -DCMAKE_CXX_FLAGS="$(CXXFLAGS) $(CPPFLAGS)" \
+ -DOCIO_BUILD_DOCS=ON \
+ -DOCIO_BUILD_NUKE=OFF \
+ -DOCIO_BUILD_STATIC=OFF \
+ -DOCIO_BUILD_TESTS=OFF \
+ -DOCIO_BUILD_TRUELIGHT=OFF \
+ -DOCIO_USE_SSE=OFF \
+ -DUSE_EXTERNAL_TINYXML=ON \
+ -DUSE_EXTERNAL_YAML=ON
+
+override_dh_auto_install:
+ dh_auto_install
+ rm -f $(INSTDIR)/usr/share/doc/OpenColorIO/html/_sources/License.txt
+ rm -f $(INSTDIR)/usr/share/doc/OpenColorIO/html/_static/jquery.js
+ rm -f $(INSTDIR)/usr/share/doc/OpenColorIO/html/_static/underscore.js
+
+override_dh_install:
+ mv $(INSTDIR)/usr/share/doc/OpenColorIO $(INSTDIR)/usr/share/doc/opencolorio
+ dh_install
+
+override_dh_auto_clean:
+ pyclean .
+ dh_auto_clean
+
+get-orig-source:
+ uscan --force-download
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..df02b54
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,3 @@
+version=3
+opts="dversionmangle=s/\~dfsg.*//" \
+https://github.com/imageworks/OpenColorIO/tags .*/v(\d.*)\.(?:tgz|tar\.(?:gz|bz2|xz))
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
new file mode 100644
index 0000000..e15db13
--- /dev/null
+++ b/docs/CMakeLists.txt
@@ -0,0 +1,73 @@
+
+###############################################################################
+### Create Doc Targets ###
+
+message(STATUS "Create sphinx conf.py from conf.py.in")
+configure_file(${CMAKE_SOURCE_DIR}/docs/conf.py.in
+ ${CMAKE_BINARY_DIR}/docs/conf.py @ONLY)
+
+message(STATUS "Copying doc to staging area")
+file(COPY ${CMAKE_SOURCE_DIR}/docs/ DESTINATION ${CMAKE_BINARY_DIR}/docs)
+
+message(STATUS "Copy extra doc files to staging area")
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/README)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/INSTALL)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/ChangeLog)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/LICENSE)
+list(APPEND DOCFILES ${CMAKE_SOURCE_DIR}/share/nuke/ocionuke/viewer.py)
+CopyFiles(RSTDOC ${DOCFILES})
+
+message(STATUS "Extracting .rst files from C++ headers")
+ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorIO.h developers/api/OpenColorIO.rst)
+ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorTransforms.h developers/api/OpenColorTransforms.rst)
+ExtractRstCPP(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorTypes.h developers/api/OpenColorTypes.rst)
+
+add_custom_target(doc ALL
+ COMMAND PYTHONPATH=${PYTHONPATH} sphinx-build -b html . ${CMAKE_CURRENT_BINARY_DIR}/build-html
+ DEPENDS
+ OpenColorIO
+ PyOpenColorIO
+ ${CMAKE_BINARY_DIR}/docs/conf.py
+ developers/api/OpenColorIO.rst
+ developers/api/OpenColorTransforms.rst
+ developers/api/OpenColorTypes.rst
+ ${RSTDOC_OUTPUT}
+ COMMENT "Building html docs"
+ SOURCES ${DOCFILES})
+
+# note: ExternalProject will not build when added to a add_custom_target this
+# works around this problem. This seems to be fixed in the cmake ^HEAD
+add_dependencies(doc Sphinx)
+
+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-html/
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/OpenColorIO/html
+ PATTERN .* EXCLUDE
+)
+
+find_package(LATEX)
+if(PDFLATEX_COMPILER)
+
+ add_custom_target(latex
+ COMMAND PYTHONPATH=${PYTHONPATH} sphinx-build -b latex . ${CMAKE_CURRENT_BINARY_DIR}/build-latex
+ DEPENDS
+ OpenColorIO
+ ${CMAKE_BINARY_DIR}/docs/conf.py
+ developers/api/OpenColorIO.rst
+ developers/api/OpenColorTransforms.rst
+ developers/api/OpenColorTypes.rst
+ ${RSTDOC_OUTPUT}
+ COMMENT "Building latex doc"
+ SOURCES ${DOCFILES})
+ add_dependencies(latex Sphinx)
+
+ add_custom_target(pdf ALL
+ COMMAND ${PDFLATEX_COMPILER} OpenColorIO.tex
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-latex
+ COMMENT "Building pdf doc"
+ SOURCES ${DOCFILES})
+ add_dependencies(pdf latex)
+
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/build-latex/OpenColorIO.pdf
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/OpenColorIO/)
+
+endif()
diff --git a/docs/ChangeLog.rst b/docs/ChangeLog.rst
new file mode 100755
index 0000000..3ebc244
--- /dev/null
+++ b/docs/ChangeLog.rst
@@ -0,0 +1,6 @@
+.. _changelog-main:
+
+ChangeLog
+=========
+
+.. include:: ChangeLog
diff --git a/docs/CompatibleSoftware.rst b/docs/CompatibleSoftware.rst
new file mode 100644
index 0000000..05845e6
--- /dev/null
+++ b/docs/CompatibleSoftware.rst
@@ -0,0 +1,268 @@
+.. _compatiblesoftware:
+
+Compatible Software
+===================
+
+The following sofware all supports OpenColorIO (to varying degrees).
+
+If you are interested in getting OCIO support for an application not listed
+here, please contact the ocio-dev mailing list.
+
+If you are a developer and would like assistance integration OCIO into your
+application, please contant ocio-dev as well.
+
+
+After Effects
+*************
+
+`Compositor - Adobe <http://www.adobe.com/products/aftereffects.html>`__
+
+OpenColorIO nodes are available for use in After Effects.
+
+See `src/aftereffects
+<http://github.com/imageworks/OpenColorIO/tree/master/src/aftereffects>`__
+if you are interested in building your own OCIO plugins.
+
+Pre-built binaries are also available for `download
+<http://www.fnordware.com/OpenColorIO>`__, courtesy of
+`fnordware <http://www.fnordware.com>`__.
+
+
+Krita
+*****
+
+`2D Paint - Open Source <http://www.krita.org/>`__
+
+Krita now support OpenColorIO for image viewing, allowing for the accurate
+painting of float32/OpenEXR imagery.
+
+See `krita.org
+<http://www.krita.org/item/113-krita-starts-supporting-opencolorio>`__
+for details.
+
+
+Silhouette
+**********
+
+`Roto, Paint, Keying - SilhouetteFX <http://www.silhouettefx.com/silhouette>`__
+
+OCIO is natively integrated in
+`4.5+ <http://www.silhouettefx.com/silhouette/silhouette-4.5-WhatsNew.pdf>`__
+Full support is provide for both image import/export, as well as image display.
+
+
+
+Nuke
+****
+
+`Compositor - The Foundry <http://www.thefoundry.co.uk/products/nuke>`__
+
+Nuke 6.3v7+ ships with native support for OpenColorIO. The OCIO configuration
+is selectable in the user preferences.
+
+OCIO Nodes: OCIOCDLTransform, OCIOColorSpace, OCIODisplay, OCIOFileTransform,
+OCIOLookConvert, OCIOLogConvert
+
+The OCIODisplay node is suitable for use in the Viewer as an input process (IP),
+and a register function is provides to add viewer options for each display upon
+launch.
+
+The OCIO config "nuke-default" is provided, which matches the built-in Nuke
+color processing. This profile is useful for those who want to mirror the native
+nuke color processing in other applications. (The underlying equations are
+also provided as python code in the config as well).
+
+A `video demonstration <http://vimeo.com/38773736>`__ of the Nuke OCIO workflow.
+
+Mari
+****
+
+`3D Paint - The Foundry <http://www.thefoundry.co.uk/products/mari>`__
+
+Mari 1.4v1+ ships with native support for OpenColorIO in their display toolbar.
+
+A `video demonstration <http://vimeo.com/32909648>`__ of the Mari OCIO workflow.
+
+Katana
+******
+
+`CG Pipeline / Lighting Tool - The Foundry <http://www.thefoundry.co.uk/products/katana>`__
+
+Color management in Katana (all versions) natively relies on OCIO.
+
+2D Nodes: OCIODisplay, OCIOColorSpace, OCIOCDLTransform
+Monitor Panel: Full OCIO Support
+
+Hiero
+*****
+
+`Conform & Review - The Foundry <http://www.thefoundry.co.uk/products/hiero>`__
+
+Hiero 1.0 will ship with native support for OCIO in the display and the
+equivalent of Nuke's OCIOColorSpace in the Read nodes.
+
+It comes with “nuke-default” OCIO config by default, so the Hiero viewer
+matches when sending files to Nuke for rendering.
+
+
+Photoshop
+*********
+OpenColorIO display luts can be exported as ICC profiles for use in photoshop.
+See the ociobakelut details below for additional info. The core idea is to
+create an .icc profile, with a valid description, and then to save it to the
+proper OS icc directory. (On OSX, ~/Library/ColorSync/Profiles/) Upon a
+Photoshop relaunch, Edit->Assign Profile, and then select your new OCIO lut.
+
+
+OpenImageIO
+***********
+
+`Open Source Image Library / Renderer Texture Engine <http://openimageio.org>`__
+
+Available in the current code trunk. Integration is with makecolortx (allowing
+for color space conversion during mipmap generation), and also through the
+public header `src/include/color.h <http://github.com/OpenImageIO/oiio/blob/master/src/include/color.h>`__ .
+
+Remaining integration tasks include
+`color conversion at runtime <http://github.com/OpenImageIO/oiio/issues/193>`__ .
+
+C++
+***
+The core OpenColorIO API is avaiable for use in C++. See the `export directory
+<http://github.com/imageworks/OpenColorIO/tree/master/export/OpenColorIO>`__
+for the C++ API headers. Minimal code examples are also available in the source
+code distribution. Of particular note are apps/ocioconvert and apps/ociodisplay.
+
+Python
+******
+The OpenColorIO API is available for use in python. See the "pyglue" directory
+in the codebase.
+
+
+Apps w/icc or luts
+******************
+flame (.3dl), lustre (.3dl), cinespace (.csp), houdini (.lut), iridas_itx (.itx)
+photoshop (.icc)
+
+Export capabilities through ociobakelut::
+
+ $ ociobakelut -- create a new LUT or icc profile from an OCIO config or lut file(s)
+ $
+ $ usage: ociobakelut [options] <OUTPUTFILE.LUT>
+ $
+ $ example: ociobakelut --inputspace lg10 --outputspace srgb8 --format flame lg_to_srgb.3dl
+ $ example: ociobakelut --lut filmlut.3dl --lut calibration.3dl --format flame display.3dl
+ $ example: ociobakelut --lut look.3dl --offset 0.01 -0.02 0.03 --lut display.3dl --format flame display_with_look.3dl
+ $ example: ociobakelut --inputspace lg10 --outputspace srgb8 --format icc ~/Library/ColorSync/Profiles/test.icc
+ $ example: ociobakelut --lut filmlut.3dl --lut calibration.3dl --format icc ~/Library/ColorSync/Profiles/test.icc
+ $
+ $
+ $ Using Existing OCIO Configurations
+ $ --inputspace %s Input OCIO ColorSpace (or Role)
+ $ --outputspace %s Output OCIO ColorSpace (or Role)
+ $ --shaperspace %s the OCIO ColorSpace or Role, for the shaper
+ $ --iconfig %s Input .ocio configuration file (default: $OCIO)
+ $
+ $ Config-Free LUT Baking
+ $ (all options can be specified multiple times, each is applied in order)
+ $ --lut %s Specify a LUT (forward direction)
+ $ --invlut %s Specify a LUT (inverse direction)
+ $ --slope %f %f %f slope
+ $ --offset %f %f %f offset (float)
+ $ --offset10 %f %f %f offset (10-bit)
+ $ --power %f %f %f power
+ $ --sat %f saturation (ASC-CDL luma coefficients)
+ $
+ $ Baking Options
+ $ --format %s the lut format to bake: flame (.3dl), lustre (.3dl),
+ $ cinespace (.csp), houdini (.lut), iridas_itx (.itx), icc (.icc)
+ $ --shapersize %d size of the shaper (default: format specific)
+ $ --cubesize %d size of the cube (default: format specific)
+ $ --stdout Write to stdout (rather than file)
+ $ --v Verbose
+ $ --help Print help message
+ $
+ $ ICC Options
+ $ --whitepoint %d whitepoint for the profile (default: 6505)
+ $ --displayicc %s an icc profile which matches the OCIO profiles target display
+ $ --description %s a meaningful description, this will show up in UI like photoshop
+ $ --copyright %s a copyright field
+
+
+
+See this `ocio-dev thread
+<http://groups.google.com/group/ocio-dev/browse_thread/thread/56fd58e60d98e0f6#>`__
+for additional usage discussions.
+
+When exporting an ICC Profile, you will be asked to specify your monitor’s
+profile (it will be selected for you by default). This is because ICC Profile
+are not LUTs per se. An ICC Profile describes a color space and then needs a
+destination profile to calculate the transformation. So if you have an operation
+working and looking good on the monitor you’re using (and maybe its
+profile has been properly measured using a spectrophotometer), then choose your
+display. If the transform was approved on a different monitor, then maybe you
+should choose its profile instead.
+
+
+RV (Beta)
+*********
+
+`Playback Tool - Tweak Software <http://www.tweaksoftware.com>`__
+
+`OCIO support in RV <https://github.com/imageworks/OpenColorIO/tree/master/src/rv>`__
+is currently being developed by Ben Dickson (dbr).
+
+See this `email thread <http://groups.google.com/group/ocio-dev/browse_thread/thread/955fc6271f89a28e>`__
+for additional details.
+
+This integration is currently considered a work in progress, and should not be
+relied upon for critical production work.
+
+
+Java (Beta)
+***********
+The OpenColorIO API is available for use in Java. See the `jniglue directory
+<http://github.com/imageworks/OpenColorIO/tree/master/src/jniglue>`__
+in the codebase.
+
+This integration is currently considered a work in progress, and should not be
+relied upon for critical production work.
+
+java.com
+
+
+Blender (Beta)
+**************
+`Open Source 3D Application <http://www.blender.org/>`__
+
+Blender currently has `limited support
+<http://wiki.blender.org/index.php/Dev:Source/Image/OpenColorIO#OpenColorIO_Integration>`__
+for OCIO.
+
+Xaview Thomas has begun the `Blender OCIO integration <http://github.com/thmxv/blender-ocio>`__ .
+Currently undergoing development.
+
+`Blender Developers Meeting Notes July 31, 2011
+<http://www.blendernation.com/2011/08/01/blender-developers-meeting-notes-july-31-2011>`__
+
+`YouTube Blender Example
+<http://www.youtube.com/watch?v=O43ItUVvcks>`__
+
+
+Ramen (Beta)
+************
+`Open Source Compositor <http://ramencomp.blogspot.com>`__
+
+Under development, with native OCIO color managment.
+
+
+CryEngine3 (Beta)
+*****************
+
+`Game Engine - Crytek (Cinema Sandbox) <http://mycryengine.com/index.php?conid=59>`__
+
+CryENGINE is a real-time game engine, targeting applications in the
+motion-picture market. While we don't know many details about the CryEngine
+OpenColorIO integration, we're looking forward to learning more as information
+becomes available.
+
diff --git a/docs/FAQ.rst b/docs/FAQ.rst
new file mode 100644
index 0000000..9530cec
--- /dev/null
+++ b/docs/FAQ.rst
@@ -0,0 +1,141 @@
+.. _faq:
+
+FAQ
+===
+
+License?
+********
+
+New BSD.
+
+You are welcome to include the OpenColorIO in commercial, or open source
+applications. See the :ref:`license` for further details.
+
+
+Terminology
+***********
+
+- Transform - a function that alters RGB(A) data (e.g transform an image from scene linear to sRGB)
+- Reference space - a space that connects colorspaces
+- Colorspace - a meaningful space that can be transferred to and from the reference space
+- Display - a virtual or physical display device (e.g an sRGB display device)
+- View - a meaningful view of the reference space on a Display (e.g a film emulation view on an sRGB display device)
+- Role - abstract colorspace naming (e.g specify the "lnh" colorspace as the scene_linear role)
+
+
+.. _faq-supportedlut:
+
+What LUT Formats are supported?
+*******************************
+
+========= =================================== ===============================
+Ext Details Notes
+========= =================================== ===============================
+3dl Autodesk Apps: Lustre, Flame, etc. Read + Write Support.
+ Supports shaper LUT + 3D
+ccc ASC CDL ColorCorrectionCollection Full read support.
+cc ASC CDL ColorCorrection Full read support.
+csp Cinespace (Rising Sun Research) Read + Write Support. Shaper is
+ LUT. Spline-based shaper LUT, with resampled into simple 1D LUT
+ either 1D or 3D LUT. with 2^16 samples.
+cub Truelight format. Shaper Lut + 3D Full read support.
+cube Iridas format. Either 1D or 3D Lut. Full read support
+hdl Houdini. 1D Lut, 3D lut, 1D shaper Only 'C' type is supported.
+ Lut Need to add R G B A RGB RGBA ALL.
+ No support for Sampling tag.
+ Header fields must be in strict order.
+look IRIDAS .look Read baked 3D LUT embedded in file.
+ No mask support.
+mga/m3d Pandora 3D lut Full read support.
+spi1d 1D format. Imageworks native 1D Full read support.
+ lut format. HDR friendly, supports
+ arbitrary input and output domains
+spi3d 3D format. Imageworks native 3D Full read support.
+ lut format.
+spimtx 3x3 matrix + color offset. Full read support.
+ Imageworks native color matrix
+ format
+vf Inventor 3d lut. Read support for 3d lut data
+ and global_transform element
+========= =================================== ===============================
+
+.. note::
+ Shaper LUT application in OCIO currently only supports linear interpolation.
+ For very small shaper LUT sizes this may not be sufficient. (CSP shaper luts
+ excluded; they do use spline interpolation at load-time).
+
+
+Can you query a color space by name (like "Rec709") and get back XYZ coordinates of its primaries and whitepoint?
+*****************************************************************************************************************
+
+Not currently.
+
+OCIO is a color configuration 'playback' tool that tries to be as flexible as possible;
+color information such as this is often only needed / relevant at configuration authoring time.
+Making primaries / whitepoint required would limit the pipeline OCIO could service. In the
+strictest sense, we would consider OCIO to be a 'baked' representation of color processes,
+similar to how Alembic files do not store animation rig data, but rather only the baked geometry.
+
+Also, remember that not all colorspaces using in visual effects even have strongly
+defined color space definitions. For example, scanned film negatives, when linearized with
+1d transfer curves (the historical norm in vfx), do not have defined primaries/white point.
+Each rgb value could of course individually be tied to a specific color, but if you were to
+do a sweep of the pure 'red channel', for example, you'd find that it creates a curves in
+chromaticity space, not a single point. (This is due to the 1d linearization not attempting
+to undo the subtractive processes that created the pixels in the first place.
+
+But many color spaces in OCIO *do* have very strongly defined white points/chromaticities.
+On the display side, for example, we have very precise information on this.
+
+Perhaps OCIO should include optional metadata to tag outputs? We are looking at this as
+as a OCIO 1.2 feature.
+
+Can you convert XYZ <-> named color space RGB values?
+*****************************************************
+
+OCIO includes a MatrixTransform, so the processing capability is there. But there is no convenience
+function to compute this matrix for you. (We do include other Matrix convenience functions though,
+so it already has a place to be added. See MatrixTransform in export/OpenColorTransforms.h)
+
+There's talk of extended OCIO 1.2 to have a plugin api where colorspaces could be dynamically
+added at runtime (such as after reading exr chromaticity header metadata). This would
+necessitate adding such a feature.
+
+
+What are the differences between Nuke's Vectorfield and OCIOFileTransform?
+**************************************************************************
+
+(All tests done with Nuke 6.3)
+
+========= ============================================= ===============================
+Ext Details Notes
+========= ============================================= ===============================
+3dl Matched Results
+ccc n/a
+cc n/a
+csp *Difference* Gain error. Believe OCIO is correct, but need to verify.
+cub Matched Results Note: Nuke's .cub exporter is broken (gain error)
+cube Matched Results
+hdl n/a
+mga/m3d n/a
+spi1d n/a
+spi3d n/a
+spimtx n/a
+vf *Difference* Gain error. Believe OCIO is correct, but need to verify.
+========= ============================================= ===============================
+
+All gain differences are due to a common 'gotcha' when interpolating 3d luts, related to
+internal index computation. If you have a 32x32x32 3dlut, when sampling values from (0,1)
+do you internally scale by 31.0 or 32.0? This is typically well-defined for each format,
+(in this case the answer is usually 31.0) but when incorrectly handled in an application,
+you occationally see gain errors that differ by this amount. (In the case of a 32-sized
+3dlut, 32/31 = ~3% error)
+
+
+What do ColorSpace::setAllocation() and ColorSpace::setAllocationVars() do?
+***************************************************************************
+
+These hints only come into play during GPU processing, and are used to determine proper
+colorspace allocation handling for 3D LUTs. See this page :ref:`allocationvars` for
+further information.
+
diff --git a/docs/License.rst b/docs/License.rst
new file mode 100755
index 0000000..9d35840
--- /dev/null
+++ b/docs/License.rst
@@ -0,0 +1,5 @@
+.. _license:
+
+License
+=======
+.. include:: LICENSE
diff --git a/docs/conf.py.in b/docs/conf.py.in
new file mode 100644
index 0000000..b08493b
--- /dev/null
+++ b/docs/conf.py.in
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+
+# See:
+# http://sphinx.pocoo.org/config.html
+
+import sys, os
+
+# -- Add PyOpenColorIO to sys.path
+sys.path.insert(0, "@CMAKE_BINARY_DIR@/src/pyglue")
+
+# -- General configuration -----------------------------------------------------
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.ifconfig']
+templates_path = ['templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = u'OpenColorIO'
+copyright = u'2010, Sony Pictures Imageworks'
+# The short X.Y version.
+version = '@OCIO_VERSION_MAJOR@.@OCIO_VERSION_MINOR@'
+# The full version, including alpha/beta/rc tags.
+release = '@OCIO_VERSION@'
+exclude_patterns = ['build', '*-prefix']
+#add_function_parentheses = True
+#add_module_names = True
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+#modindex_common_prefix = []
+
+rst_prolog = """
+.. |OCIO| replace:: *OCIO*
+.. |OpenColorIO| replace:: **OpenColorIO**
+.. _Sony Imageworks: http://www.imageworks.com/
+.. |Sony Imageworks| replace:: `Sony Imageworks`_
+.. _Jeremy Selan: mailto:jeremy.selan@gmail.com
+.. |Jeremy Selan| replace:: `Jeremy Selan`_
+.. _ocio-users: http://groups.google.com/group/ocio-users
+.. _ocio-dev: http://groups.google.com/group/ocio-dev
+"""
+
+# -- Options for HTML output ---------------------------------------------------
+html_theme_path = ['.']
+html_theme = 'ociotheme'
+#html_theme_options = {}
+#html_title = None
+#html_short_title = None
+#html_logo = None
+#html_favicon = None
+html_static_path = []
+#html_last_updated_fmt = '%b %d, %Y'
+#html_use_smartypants = True
+#html_sidebars = {}
+#html_additional_pages = {}
+html_domain_indices = ['cpp-modindex', 'py-modindex']
+#html_use_index = True
+#html_split_index = False
+#html_show_sourcelink = True
+#html_show_sphinx = True
+#html_show_copyright = True
+#html_use_opensearch = ''
+#html_file_suffix = None
+htmlhelp_basename = 'OpenColorIOdoc'
+
+# -- Options for LaTeX output --------------------------------------------------
+#latex_paper_size = 'letter'
+#latex_font_size = '10pt'
+latex_documents = [
+ ('index', 'OpenColorIO.tex', u'OpenColorIO Documentation',
+ u'Sony Pictures Imageworks', 'manual', False),
+]
+latex_elements = {
+ 'preamble': '\setcounter{tocdepth}{2}',
+ 'footer': 'test...123'
+}
+
+#latex_logo = None
+#latex_use_parts = False
+#latex_show_pagerefs = False
+#latex_show_urls = False
+#latex_preamble = '\setcounter{tocdepth}{2}'
+#latex_appendices = []
+latex_domain_indices = ['cpp-modindex', 'py-modindex']
+
+# -- Options for manual page output --------------------------------------------
+man_pages = [
+ ('index', 'opencolorio', u'OpenColorIO Documentation',
+ [u'Sony Pictures Imageworks'], 1)
+]
+
+# -- Options for Texinfo output ------------------------------------------------
+texinfo_documents = [
+ ('index', 'OpenColorIO', u'OpenColorIO Documentation', u'Sony Pictures Imageworks',
+ 'OpenColorIO', 'One line description of project.', 'Miscellaneous'),
+]
+texinfo_appendices = []
+
+# -- Options for Epub output ---------------------------------------------------
+epub_title = u'OpenColorIO'
+epub_author = u'Sony Pictures Imageworks'
+epub_publisher = u'Sony Pictures Imageworks'
+epub_copyright = u'2010, Sony Pictures Imageworks'
+#epub_language = ''
+#epub_scheme = ''
+#epub_identifier = ''
+#epub_uid = ''
+#epub_cover = ()
+#epub_pre_files = []
+#epub_post_files = []
+#epub_exclude_files = []
+#epub_tocdepth = 3
+#epub_tocdup = True
diff --git a/docs/configurations/allocation_vars.rst b/docs/configurations/allocation_vars.rst
new file mode 100644
index 0000000..9cb2a05
--- /dev/null
+++ b/docs/configurations/allocation_vars.rst
@@ -0,0 +1,119 @@
+.. _allocationvars:
+
+How to Configure ColorSpace Allocation
+======================================
+
+The allocation / allocation vars are utilized using during GPU 3dlut / shader
+text generation. (Processor::getGpuShaderText, Processor::getGpuLut3D).
+
+If, in the course of GPU processing, a 3D lut is required, the "allocation /
+allocation vars" direct how OCIO should sample the colorspace, with the intent
+being to maintain maximum fidelity and minimize clamping.
+
+Currently support allocations / variables:
+
+ALLOCATION_UNIFORM::
+ 2 vars: [min, max]
+
+ALLOCATION_LG2::
+ 2 vars: [lg2min, lg2max]
+ 3 vars: [lg2min, lg2max, linear_offset]
+
+So say you have an srgb image (such as an 8-bit tif), where you know the data
+ranges between 0.0 - 1.0 (after converting to float). If you wanted to apply
+a 3d lut to this data, there is no danger in samplingthat space uniformly and
+clamping data outside (0,1). So for this colorspace we would tag it:
+
+.. code-block:: yaml
+
+ allocation: uniform
+ allocationvars: [0.0, 1.0]
+
+These are the defaults, so the tagging could also be skipped.
+
+But what if you were actually first processing the data, where occasionally
+small undershoot and overshoot values were encountered? If you wanted OCIO to
+preserve this overshoot / undershoot pixel information, you would do so by
+modifying the allocation vars.
+
+.. code-block:: yaml
+
+ allocation: uniform
+ allocationvars: [-0.125, 1.125]
+
+This would mean that any image data originally within [-0.125, 1.125] will be
+preserved during GPU processing. (Protip: Data outside this range *may*
+actually be preserved in some circumstances - such as if a 3d lut is not needed
+- but it's not required to be preserved).
+
+So why not leave this at huge values (such as [-1000.0, 1000.0]) all the time?
+Well, there's a cost to supporting this larger dynamic range, and that cost is
+reduced precision within the 3D luts sample space. So in general you're best
+served by using sensible allocations (the smallest you can get away with, but
+no smaller).
+
+Now in the case of high-dynamic range color spaces (such as float linear), a
+uniform sampling is not sufficient because the max value we need to preserve is
+so high.
+
+Say you were using a 32x32x32 3d lookup table (a common size). Middle gray is
+at 0.18, and specular values are very much above that. Say the max value we
+wanted to preserve in our coding space is 256.0, each 3d lut lattice coordinates
+would represent 8.0 units of linear light! That means the vast majority of the
+perceptually significant portions of the space wouldnt be sampled at all!
+
+unform allocation from 0-256\:
+0
+8.0
+16.0
+...
+240.0
+256.0
+
+So another allocation is defined, lg2
+
+.. code-block:: yaml
+
+ - !<ColorSpace>
+ name: linear
+ description: |
+ Scene-linear, high dynamic range. Used for rendering and compositing.
+ allocation: lg2
+ allocationvars: [-8, 8]
+
+In this case, we're saying that the appropriate ways to sample the 3d lut are
+logarithmically, from 2^-8 stops to 2^8 stops.
+
+Sample locations:
+2^-8\: 0.0039
+2^-7\: 0.0078
+2^-6\: 0.0156
+...
+2^0\: 1.0
+...
+2^6\: 64.0
+2^7\: 128.0
+2^8\: 256.0
+
+Which gives us a much better perceptual sampling of the space.
+
+The one downside of this approach is that it can't represent 0.0,
+which is why we optionally allow a 3d allocation var, a black point
+offset. If you need to preserve 0.0 values, and you have a high
+dynamic range space, you can specify a small offset.
+
+Example:
+
+.. code-block:: yaml
+
+ allocation: lg2
+ allocationvars: [-8, 8, 0.00390625]
+
+The [-15.0, 6.0] values in spi-vfx come from the fact that all of the
+linearizations provided in that profile span the region from 2^-15
+stops, to 2^6 stops. One could probably change that black point to a
+higher number (such as -8), but if you raised it too much you would
+start seeing black values be clipped. Conversely, on the high end
+one could raise it a bit but if you raised it too far the precision
+would suffer around gray, and if you lowered it further you'd start to
+see highlight clipping.
diff --git a/docs/configurations/images/spi-vfx/gn10_to_linear_light.jpeg b/docs/configurations/images/spi-vfx/gn10_to_linear_light.jpeg
new file mode 100644
index 0000000..ffc228e
--- /dev/null
+++ b/docs/configurations/images/spi-vfx/gn10_to_linear_light.jpeg
Binary files differ
diff --git a/docs/configurations/images/spi-vfx/gnf_to_linear_light.jpeg b/docs/configurations/images/spi-vfx/gnf_to_linear_light.jpeg
new file mode 100644
index 0000000..25deaf4
--- /dev/null
+++ b/docs/configurations/images/spi-vfx/gnf_to_linear_light.jpeg
Binary files differ
diff --git a/docs/configurations/images/spi-vfx/lg10_to_linear_light.jpeg b/docs/configurations/images/spi-vfx/lg10_to_linear_light.jpeg
new file mode 100644
index 0000000..cbef9b4
--- /dev/null
+++ b/docs/configurations/images/spi-vfx/lg10_to_linear_light.jpeg
Binary files differ
diff --git a/docs/configurations/images/spi-vfx/lg8_to_vd8.jpeg b/docs/configurations/images/spi-vfx/lg8_to_vd8.jpeg
new file mode 100644
index 0000000..ba49ad4
--- /dev/null
+++ b/docs/configurations/images/spi-vfx/lg8_to_vd8.jpeg
Binary files differ
diff --git a/docs/configurations/images/spi-vfx/lgf_to_linear_light.jpeg b/docs/configurations/images/spi-vfx/lgf_to_linear_light.jpeg
new file mode 100644
index 0000000..8b897ed
--- /dev/null
+++ b/docs/configurations/images/spi-vfx/lgf_to_linear_light.jpeg
Binary files differ
diff --git a/docs/configurations/index.rst b/docs/configurations/index.rst
new file mode 100644
index 0000000..0284d34
--- /dev/null
+++ b/docs/configurations/index.rst
@@ -0,0 +1,22 @@
+.. _configurations:
+
+Configurations
+==============
+
+This section gives an overview of what existing (public) OCIO configuration exist,
+and how to create new ones.
+
+OCIO Configurations can be downloaded here: `.zip <http://github.com/imageworks/OpenColorIO-Configs/zipball/master>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO-Configs/tarball/master>`__ (OCIO v1.0+)
+
+If you are interested in crafting custom color configurations, and need assistance, please contact: ocio-dev_\ ``@googlegroups.com``
+
+.. toctree::
+ :maxdepth: 1
+
+ spi_pipeline
+
+ spi_vfx
+ spi_anim
+ nuke_default
+
+ allocation_vars
diff --git a/docs/configurations/nuke_default.rst b/docs/configurations/nuke_default.rst
new file mode 100644
index 0000000..7e3a7ee
--- /dev/null
+++ b/docs/configurations/nuke_default.rst
@@ -0,0 +1,19 @@
+Nuke default
+============
+
+This profile corresponds to the default Nuke color configuration (currently generated from Nuke 6.1).
+
+If you have made modifications to a nuke color configuration, and wish to re-export your own custom OCIO profile, please refer to the nuke_to_ocio utility script distributed with OpenColorIO.
+
+The following color transforms are defined:
+
+- linear
+- sRGB
+- rec709
+- Cineon
+- Gamma 1.8
+- Gamma 2.2
+- Panalog
+- REDLog
+- ViperLog
+- REDSpace
diff --git a/docs/configurations/spi_anim.rst b/docs/configurations/spi_anim.rst
new file mode 100644
index 0000000..49a7779
--- /dev/null
+++ b/docs/configurations/spi_anim.rst
@@ -0,0 +1,4 @@
+spi-anim
+========
+
+This is a real OCIO color profile in use at Sony Pictures Imageworks, and is suitable for use on animated features. The concepts utilized in this profile have been successfully validated on a variety of Sony Pictures Animation features including Cloudy With A Chance Of Meatballs, Surf's Up, and Arthur Christmas.
diff --git a/docs/configurations/spi_pipeline.rst b/docs/configurations/spi_pipeline.rst
new file mode 100644
index 0000000..c508899
--- /dev/null
+++ b/docs/configurations/spi_pipeline.rst
@@ -0,0 +1,74 @@
+Sony Pictures Imageworks Color Pipeline
+=======================================
+
+This document describes a high-level overview on how to emulate the current color management practice at Sony Imageworks. It applies equally to all profiles used at Imageworks, including both the VFX and Animation profiles. It's by no means a requirement to follow this workflow at your own facility, this is merely a guideline on how we choose to work.
+
+General Pipeline Observations
+*****************************
+
+* All images, on disk, contain colorspace information as a substring withing the filename. This is obeyed by all applications that load image, write images, or view images. File extensions and metadata are ignored with regards to color processing.
+
+ Example::
+
+ colorimage_lnf.exr : lnf
+ dataimage_ncf.exr : ncf
+ plate_lg10.dpx : lg10
+ texture_dt8.tif: dt8
+
+ Note: fileformat extension does NOT imply a color space. Not all dpx files are lg10. Note all tif images are dt8.
+
+* The common file formats we use are exr, tif, dpx.
+
+ * render outputs: exr
+ * render inputs (mipmapped-textures): exr, tif (txtif)
+ * photographic plates (scans): dpx
+ * composite outputs: dpx, exr
+ * on-set reference: (camera raw) NEF, CR2, etc.
+ * painted textures: psd, tif
+ * output proxies: jpg
+
+* All pipelines that need to be colorspace aware rely on ``Config.parseColorSpaceFromString``.
+
+* Color configurations are show specific. The $OCIO environment variable is set as part of a 'setshot' process, before other applications are launched. Artists are not allowed to work across different shows without using a fresh shell + setshot.
+
+* While the list of colorspaces can be show specific, care is taken to maintain similar naming to the greatest extent feasible. This reduces artist confusion. Even if two color spaces are not identical across shows, if they serve a similar purpose they are named the same. Example: We label 10-bit scanned film negatives as lg10. Even if two different shows use different acquisition film stocks, and rely on different linearization curves, they are both labelled lg10.
+
+* There is no explicit guarantee that image assets copied across shows will be transferable in a color-correct manner. For example, in the above film scan example, one would not expect that the linearized versions of scans processed on different shows to match. In practice, this is not a problematic issue as the colorspaces which are convenient to copy (such as texture assets) happen to be similarly defined across show profiles.
+
+
+Rendering
+*********
+
+* Rendering and shading occurs in a scene-linear floating point space, typically named "ln". Half-float (16-bit) images are labelled lnh, full float images (32-bit) are labelled lnf.
+
+
+* All image inputs should be converted to ln prior to render-time. Typically, this is done when textures are published. (See below)
+
+* Renderer outputs are always floating-point. Color outputs are typically stored as lnh (16-bit half float). Data outputs (normals, depth data, etc) are stored as ncf ("not color" data, 32-bit full float). Lossy compression is never utilized.
+
+* Render outputs are always viewed with an OCIO compatible image viewer. Thus, for typical color imagery the lnf display transform will be applied. In Nuke, this can be emulated using the OCIODisplay node. A standalone image viewer, ociodisplay, is also included with OpenColorIO src/example.
+
+
+Texture Painting / Matte Painting
+*********************************
+
+* Textures are painted in non-OCIO color-managed environment. (Photoshop, etc).
+
+* At texture publish time, before mipmaps are generated, all color processing is applied. Internally at SPI we use a modified version of OpenImageIO's maketx that also links to OpenColorIO. We intend to make this code available as soon as possible. In the meantime, the OpenColorIO 'ocioconvert' script included in examples can be relied upon. Color processing (linearization) is applied before mipmap generation in order to assure energy preservation in the render. If the opposite processing order were used, (mipmap in the original space, color convert in the shader), the apparent intensity of texture values would change as the object approached to receeded to the camera.
+
+* The original texture filenames contain the colorspace information as a substring, to signify processing intent.
+
+ * Textures that contain data (bump maps, opacity maps, blend maps, etc) are labelled with the nc colorspaces according to their bitdepth. Ex: an 8-bit opacity map -> skin_opacity_nc8.tif
+
+ * Painted textures that are intended to modulate diffuse color components are labelled dt (standing for "diffuse texture"). The dt8 colorspace is designed such that, when linearized, values will not extend above 1.0. At texture publishing time these are converted to lnh mipmapped tiffs/exr. Note that as linear textures have greater allocation requirements, a bit depth promotion is required in this case. I.e., even if the original texture as painted was only 8-bits, the mipmapped texture will be stored as a 16-bit float image.
+
+ * Painted environment maps, which may be emissive as labelled vd (standing for 'video'). These values, when linearized, have the potential to generate specular information well above 1.0. Note that in the current vd linearization curves, the top code values may be very "sensitive". I.e., very small changes in the initial code value (such as 254->255) may actually result in very large differences in the estimated scene-linear intensity. All environment maps are store as lnh mipmapped tiffs/exr. The same bit-depth promotion as in the dt8 case is required here.
+
+
+Compositing
+***********
+
+* The majority of compositing operations happen in scene-linear, lnf, colorspace.
+* All image inputs are linearized to lnf as they are loaded. Customized input nodes make this processing convenient. Rendered elements, which are stored in linear already, do not require processing. Photographic plates will typically be linearized according to their source type, (lg10 for film scans, gn10 for genesis sources, etc).
+* All output images are de-linearized from lnf when they are written. A customized output node makes this convenient.
+* On occasion log data is required for certain processing operations. (Plate resizing, pulling keys, degrain, etc). For each show, a colorspace is specified as appropriate for this operation. The artist does not have to keep track of which colorspace is appropriate to use; the OCIOLogConvert node is always intended for this purpose. (Within the OCIO profile, this is specified using the 'compositing_log' role).
diff --git a/docs/configurations/spi_vfx.rst b/docs/configurations/spi_vfx.rst
new file mode 100644
index 0000000..9e6cc96
--- /dev/null
+++ b/docs/configurations/spi_vfx.rst
@@ -0,0 +1,186 @@
+.. _config-spivfx:
+
+spi-vfx
+=======
+
+This is a real OCIO color profile in use at Sony Pictures Imageworks, and is suitable for use on visual effects (VFX) work. The concepts utilized in this profile have been successfully validated on a variety of Imageworks visual effects films, including Spider-Man, Alice In Wonderland, G-Force, and Green Lantern.
+
+**Conversion from film to/from scene-linear is a simple, trivially invertible 1D transform. The display transforms are complex, 3D film-print emulations.**
+
+In production, this profile is typically used before final color details are worked out. Although it sounds temporary, most of a film can be made off this configuration. Final color decisions for a film are often made long after significant work has been done. In some cases shots from a film can be finaled before the color details, such as which Digital Intermediate (DI) house will be used, are decided. Entire projects have been completed using this profile without modification.
+
+This profile embodies two philosophies of color management familiar to those in production: *"Keep It Simple"*, and, *"Don't Be Evil"*.
+
+The following steps outline a simplified visual effects color workflow:
+
+* Load a plate (log film scan, digital motion picture camera, etc)
+* Convert device color space to scene-linear
+* Render and composite in scene-linear
+* Convert from scene-linear to device color space
+* Output final plate
+
+It is absolutely critical to guarantee that process - end to end - is colorimetrically a no-op. Under no circumstances are any unintended modifications to the original image allowed.
+
+Thus, this profile uses very simple (1D) conversions for all input and output color space conversions. All of the complexity (the 3D LUT film emulation lifting) is handled at display time, and is never baked (or unbaked) into the imagery. For visualization, this profile includes a generic Kodak Vision print emulation suitable for display on a reference sRGB monitor or a P3 Digital Cinema projector.
+
+Caveot 1: Of course, we realize that there are many other color workflows that may be equally good (or better) than the one presented here. Please, if you have a successful alternative workflows share the details!
+
+Caveot 2: We are not distributing the code that generates the luts from their underlying curve representations. While we hope to publish this eventually, at the current time this process relies on internal tools and we don't have the spare development cycles to port this code to something suitable for distribution.
+
+
+Invertibility
++++++++++++++
+
+Elements often need to be transferred back and forth many times between different colorspaces. Since it’s impossible to know in advance how many times an image may be transferred between colorspaces it is essential for the majority of transformations to be lossless invertible transformations. By the end of the color pipeline even a 1 value difference in a 10bit transformation can become a significant issue. Invertible transformations can be taken from the source space, to linear and back with no change to the data. A higher value is placed on transformations being predictable and invertible than absolutely correct. All 1-d luts allow for forward and inverse transformations with no loss. Unless specified all channels are equally affected. The luts are 1 bit wider than stated, so lg8 actually defines 9 bits worth of entries. This allows the rounding in the inverse direction to be applied unambiguously (lossless).
+
+Non-invertible transforms contain 3d lookups. 3D transformations can not be inverted due to gamut mapping issues. Non-invertible transformations are only used for final output media (such as QuickTimes) and for display purposes.
+
+Film Emulation Inversion
+++++++++++++++++++++++++
+
+Inverse film emulation luts aren’t supported in a default configuration. Imageworks does not use a film emulation inversion lut for texture or matte paintings. In its place a film emulation preview lut, commonly as an ICC profile, is used. Although most film emulation luts are similar they do differ significantly. The DI facility creating final color is often chosen long after significant vfx work has been begun. The film luts the film will be finished on are not made until weeks, or days, before DI begins. So the ‘true’ lut that will be used for the finishing is not available until very late in the production, from a VFX perspective. There are many color gamut mapping issues that arise when inverting film to video lut. Using a film inversion lut at this stage would bake in a look that isn't quite right and is very difficult to fully un-bake. It is safer to work with images in a non-constrained way and apply a visualization that can be toggled on and off.
+
+Scene Linear
+************
+
+**lnf, lnh, ln16**
+
+**Middle Gray: 0.18**
+
+The linear space is a photometrically linear space, representing high-dynamic range (HDR) pixel values in our virtual world. Middle gray is defined to be at 0.18. While the dynamic range of lnf is technically unbounded, pixel values for natural, well exposed imagery will often fall between +/- 8 stops from gray.
+
+The scene linear colorspace is used for compositing, rendering, and is also the profile connection space. All colorspace conversions are made in relation how they transform into or out of scene linear.
+
+The colors defined in linear are implicitly bounded by film negative sensitivities. The space is based off an OCN film scan where values refer to linear light at the focal plane. 0.18 in linear will correspond to a %18 percent grey card captured on filmplane under the same lighting conditions where diffuse white is 1.0. Values above 1.0 in any channel would indicate a 'specular', or light emitting objects.
+
+lnf is a full precision (32-bit) floating point colorspace. It is used for rendering and compositing.
+
+lnh is a half precision (16-bit) floating point colorspace. It is used for rendering and compositing.
+
+ln16 is a 16 bit integer representation of the [0,1] range of lnf. This is no longer used but is kept if a legacy image needs to be loaded, or if linear images need to be loaded into an application that does not support float. Note that storing a float lnf image using an integer ln16 representation is destructive, and throws away data.
+
+
+Film Log
+********
+
+**lg8, lg10, lg16, lgf**
+
+**Middle Gray: 445 (of 1023)**
+
+The log to linear curve is based on an analysis of several commonly used Kodak acquisition stocks. It was found that Kodak 5218 is right about in the middle in terms of tone response given the input imagery we receive. The curve incorporates some toe compensation. The curve gamma closely matches 5218. The transformation does not represent any single stock. The Imageworks log conversions are not channel specific, all color channels are transformed uniformly. Compositing productivity gains have been found using the toe compensations when compared to using a straight line log to linear curve. Shoulder compensation - while technically correct - detracted from compositing quality, often creating situations where grain film noise would result in larger than desired changes in linear light.
+
+lg8, lg10, and lg16 are similar. They are all the same log to linear transformation but are explicitly defined to be lossless at the specified bit depths. The luts use nearest neighbor interpolation to search for an exact match. Significant performance gains were found when using the proper bitdepth lut. While using the lg16 conversion on an 8 bit image will yield the same result, it is measurably slower than using the 8-bit conversion (assuming 8-bits is all that is needed). This performance gap remains even on current graphics hardware.
+
+.. figure:: images/spi-vfx/lg10_to_linear_light.jpeg
+ :align: center
+
+ lg10 to linear light. The green curve represents the lg to ln conversion. The red curve show the green channel of a Kodak 5218 exposure test. The x-axis is in 10bit input lg the output is in lg base2 linear light units. 0.0 Represents diffuse white.
+
+lg spaces specify 21 of stops of dynamic range. 0 in lg10 space is 15 stops below diffuse white. 445 correspond to 18% grey and is ~2.47 below diffuse white. 1023 in lg10 space is 6 stops above diffuse white.
+
+lgf is identical on the range from 0-1 to the standard lg luts. It specifies an additional range below 0.0 and above 1.0. In 10 bit the spaces is defined from -512 to 2048. Lg color timing number from either on set color correction devices or from a DI house to be applied in a way that can be fully inverted out without loss. Lgf specifies 18 stops above the lg10 max and 36 stops below the log10 min with a total dynamic range of 85 stops. The space is designed to be bigger than needed.
+
+
+.. figure:: images/spi-vfx/lgf_to_linear_light.jpeg
+ :align: center
+
+ lgf to linear light. The green curve represents the lg to ln conversion. The red curve show the green channel of a Kodak 5218 exposure test. The x axis is in 10bit input lg the output is in log(base2) linear light units. 0 Represents diffuse white
+
+
+Panalog (Genesis)
+*****************
+
+**gn8, gn10, gn16, gnf**
+
+GN is the Imageworks Panalog space. It follows the Panalog specification and additionally extrapolates so all of the values from 0 to 1023 are defined. This was necessary due to compression artifacts that could create values below the Panalog specifications. gn8,10,16 are defined with diffuse white at 681, Max white is approximately 2.6 stops above diffuse white and black is approximately 12.6 stops below diffuse white. The dynamic range is less than that of lg.
+
+.. figure:: images/spi-vfx/gn10_to_linear_light.jpeg
+ :align: center
+
+ gn10 to linear light. the x axis is in 10bit Panalog values. The Y axis is in linear light. The green curve is the gn curve. the red curve is the Panalog data.
+
+gnf is similar in purpose and function to lgf. It is identical on the range from 0-1 to the regular gn and specifies an additional range below 0.0 and above 1.0. In 10 bit numbers gnf is defined from -255 to 3125. This allows for color timing number from either on set color correction devices or from a DI house to be applied in a way that can be fully inverted. Additionally it allows for lg10 based image data to be fully represented without clipping.
+
+gnf specifies 14.5 stops above the gn10 max and 18 of stops below the gn10 min. The entire range of gnf is 47 stops.
+
+.. figure:: images/spi-vfx/gnf_to_linear_light.jpeg
+ :align: center
+
+ gnf to linear light. the x axis is in 10bit Panalog values. The Y axis is in linear light. The green curve is the gn curve. the red curve is the Panalog data. Only a subset of the function is used to define the gnf solorspace
+
+
+Reference Art
+*************
+
+**vd8, vd16, vdf, hd10**
+
+The vd spaces are mappings of linear image data into display space. The main part of the transformation is defined as a single curve that is conceptually two parts. The first is a ln to lg conversion. The second is lg to sRGB conversion. This is based off the neutral channel response of the sRGB film emulation lut used in the profile. The dynamic range of the vd colorspace is limited. It is undesirable to map the vd max to the linear max. Such a conversion results in linear values are almost never what an artist intended. The rule of thumb is that, at the high end, single value deltas in an 8 bit image should never create over a half stop of additional linear light. The vd conversion curve is limited to prevent this case.
+
+.. figure :: images/spi-vfx/lg8_to_vd8.jpeg
+ :align: center
+
+ The curve used to map from Lg8 to vd 8. The x-axis is in lg8 units, the y-axis is in vd8 units.
+
+The dynamic range of the vd is limited to around 2.5 stops above diffuse white. This has two positive attributes. It allows vd to be used to directly on matte paintings. It also allows all of vd to be represented in a gn10 image. The last part of the transformation is a matrix transformation that moves the whitepoint of film to look correct when displayed with a d65 whitepoint.
+
+The main use of this colorspace is to import RGB images with an unknown colorspace. This colorspace no longer gets much use alone; However it is an integral part of many conversions. It is also part of the matte painting and diffuse texture pipelines.
+
+vdf works differently than the other floating spaces. It still only defines the color transformation from 0-1. This colorspace is used when we receive video space encoded exr's.
+
+HD10 is a vd based space that is used for importing and exporting REC709 range broadcast material. This works very well for broadcast camera native material and poorly for material with a film emulation lut baked in. This transformation works well exporting film based material to tape, even though it lacks a film emulation lut. It does not give an accurate color rendering but created a pleasing image that makes clients happy.
+
+Structurally the conversion is a matrix operation that scales the data then adds an offset to limit the range from 64-940. From there the standard vd transformation is applied.
+
+Texture Painting
+****************
+
+**dt8, dt16**
+
+DT 8,16 - Diffuse texture colorspaces. These colorspaces are used for the conversion of textures painted in video space into a range limited linear space for use in rendering. The Color space is based on the vd transformation but limits the conversion into linear space so that no values above diffuse white can be created. This ensures that textures do not add light to a render. This is achieved by using a matrix transformation to limit the mapping of vd to the linear value of diffuse white.
+
+Data
+****
+
+**nc8, nc10, nc16, ncf**
+
+Non-Color (NC) spaces are used to hold any data that needs to be processed though the color pipeline unaltered. These are data spaces and can hold anything such as point clouds, normals, untagged reference art, etc. These data spaces do not get transformations applied at any point.
+
+
+Display Transforms
+******************
+
+**srgb8, p3dci8, xyz16**
+
+**srgb8** bakes in the film3d emulation lut. This table can be used for either QuickTime generation or output to the sRGB display. The transformation is a 3d film emulation table with gray balance compensation, so a value of 445,445,445 in lg10 space os modified to become equal RGB values in sRGB. Additionally the lut is scaled so that at least one of the color channels on maximum white uses the display max.
+
+The transformation takes place in three parts. First the linear data is converted to the show log space. Then a film emulation table is applied. Then the grey balance and white scaling compensation are applied. This table is designed to be evaluated in a dimly lit office environment on a sRGB display.
+
+**p3dci8** is an implementation of film emulation table that has an output of DCI P3. This is only ever used for driving DLPs for display. The transformation has two parts. First the linear image data is converted to lg10 based image data then the DCI P3 film emulation lut is applied. No additional compensations are made.
+
+**xyz16** is designed for the creation of a Digital Cinema Distribution Master (DCDM). The color matches that of the P3 output (dlpqt8), but has an additional output transformation to convert to X'Y'Z'. The transformation takes the linear image data and converts it to lg, then applies the filmlook. The data is then in DCI P3 colorspace. That data is converted to display linear P3, using an inverse gamma curve. A matrix conversion is then used to transform from DCI P3’ into XYZ’. The final step is to reapply the gamma 2.6 to result in XYZ16 values.
+
+In this profile each display has three identical looks defined. The names are kept consistent between devices to minimize confusion. OCIO uses a specific tag to associate colorspaces with displays. The tags are nothing more than links to already defined colorspaces.
+
+**Film** is the image displayed though a film emulation lut. This visualization is display compensated and should visually match between a sRGB display and a P3 projector. The goal is to match how the film will look in a DI. The luts in use for this profile roughly match the Sony ColorWorks environment.
+
+**Raw** visualization shows the image data on the screen with no display compensation. This is used for image debugging purposes, for instance to see if potential image discontinuities are in the source data or the visualization.
+
+**Log** visualization displays the image as if it were converted to the show specific log. This is transformation also has no display compensation. The common use for this us to see how well elements fit into the comp without the film emulation lut disguising any flaws. Old school compositors love it for grain matching.
+
+sRGB Film : srgb8
+sRGB Raw : nc10
+sRGB Log : lg10
+
+DCIP3 Raw : nc10
+DCIP3 Log : lg10
+DCIP3 Film : dlpqt8
+
+
+Display Calibration
+*******************
+
+**sRGB** is the supported desktop display specification, calibrated to the sRGB standard and viewed in a dim office environment. As Imageworks switched from crt based display devices to LCD based devices a number of possible colorspaces were explored. It was a long decision but sRGB was chosen for a few reasons. An important one was that almost every display manufacturer can implement sRGB, reasonable well. This becomes a boon when we work needs to be done outside of our main facilities. Even a consumer display with calibration can come close to matching the sRGB standard. Since so many monitor manufacturers can hit sRGB calibration we are not tied to purchasing from a specific vendor. It becomes unnecessary to specify a specific display to with productions or external vendors. It also reduces the amount of studio specific color requirements that need to be communicated when working with other facilities. 80 cd/m^2, D65 white point, srgb gamma function (approx 2.4)
+
+**P3** was deemed especially unusable on the desktop. The full specification requires a white point of 48 cd/m^2. To adapt P3 for desktop use (in dim ambient environments), the whitepoint luminance needed to be raised. The specified 2.6 gamma is very challenging to the current display technology on very dark colors. This meant that we would have a special Imageworks video P3. A custom colorspace wouldn't make compositing better and would require a conversation, or conversion, every time video was sent out of house.
+
+**DCIP3** is a projector calibrated to DCI P3 mastering specification in a theatrical mastering environment. We use a mix of display technologies, SXRD and DLP, depending on application. Gamma 2.6. Traditional DCI calibration.
diff --git a/docs/developers/api/index.rst b/docs/developers/api/index.rst
new file mode 100644
index 0000000..eccef5c
--- /dev/null
+++ b/docs/developers/api/index.rst
@@ -0,0 +1,6 @@
+.. toctree::
+ :maxdepth: 1
+
+ OpenColorIO
+ OpenColorTransforms
+ OpenColorTypes
diff --git a/docs/developers/bindings/PythonAPI.rst b/docs/developers/bindings/PythonAPI.rst
new file mode 100644
index 0000000..839e9d2
--- /dev/null
+++ b/docs/developers/bindings/PythonAPI.rst
@@ -0,0 +1,147 @@
+##########
+Python API
+##########
+
+Description
+===========
+
+A color configuration (:py:class:`Config`) defines all the color spaces to be
+available at runtime.
+
+(:py:class:`Config`) is the main object for interacting with this library.
+It encapsulates all the information necessary to use customized
+:py:class:`PyOpenColorIO.ColorSpaceTransform` and
+:py:class:`PyOpenColorIO.DisplayTransform` operations.
+
+See the :ref:`user-guide` for more information on selecting, creating,
+and working with custom color configurations.
+
+For applications interested in using only one color configuration at
+a time (this is the vast majority of apps), their API would
+traditionally get the global configuration and use that, as
+opposed to creating a new one. This simplifies the use case
+for plugins and bindings, as it alleviates the need to pass
+around configuration handles.
+
+An example of an application where this would not be
+sufficient would be a multi-threaded image proxy server
+(daemon) that wants to handle multiple show configurations
+concurrently in a single process. This app would need to keep
+multiple configurations alive, and manage them appropriately.
+
+Roughly speaking, a novice user should select a default
+configuration that most closely approximates the use case
+(animation, visual effects, etc.), and set the :envvar:`OCIO`
+environment variable to point at the root of that configuration.
+
+.. note::
+ Initialization using environment variables is typically preferable
+ in a multi-app ecosystem, as it allows all applications to be consistently configured.
+
+.. note::
+ Paths to LUTs can be relative. The search paths are defined in :py:class:`Config`.
+
+See :ref:`developers-usageexamples`
+
+Examples of Use
+---------------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+
+ # Load an existing configuration from the environment.
+ # The resulting configuration is read-only. If $OCIO is set, it will use that.
+ # Otherwise it will use an internal default.
+ config = OCIO.GetCurrentConfig()
+
+ # What color spaces exist?
+ colorSpaceNames = [ cs.getName() for cs in config.getColorSpaces() ]
+
+ # Given a string, can we parse a color space name from it?
+ inputString = 'myname_linear.exr'
+ colorSpaceName = config.parseColorSpaceFromString(inputString)
+ if colorSpaceName:
+ print 'Found color space', colorSpaceName
+ else:
+ print 'Could not get color space from string', inputString
+
+ # What is the name of scene-linear in the configuration?
+ colorSpace = config.getColorSpace(OCIO.Constants.ROLE_SCENE_LINEAR)
+ if colorSpace:
+ print colorSpace.getName()
+ else:
+ print 'The role of scene-linear is not defined in the configuration'
+
+ # For examples of how to actually perform the color transform math,
+ # see 'Python: Processor' docs.
+
+ # Create a new, empty, editable configuration
+ config = OCIO.Config()
+
+ # Create a new color space, and add it
+ cs = OCIO.ColorSpace(...)
+ # (See ColorSpace for details)
+ config.addColorSpace(cs)
+
+ # For additional examples of config manipulation, see
+ # https://github.com/imageworks/OpenColorIO-Configs/blob/master/nuke-default/make.py
+
+Exceptions
+==========
+
+.. autoclass:: PyOpenColorIO.Exception
+ :members:
+ :undoc-members:
+
+.. autoclass:: PyOpenColorIO.ExceptionMissingFile
+ :members:
+ :undoc-members:
+
+Global
+======
+
+.. autofunction:: PyOpenColorIO.ClearAllCaches
+
+.. autofunction:: PyOpenColorIO.GetCurrentConfig
+
+.. autofunction:: PyOpenColorIO.GetLoggingLevel
+
+.. autofunction:: PyOpenColorIO.SetCurrentConfig
+
+.. autofunction:: PyOpenColorIO.SetLoggingLevel
+
+Config
+======
+
+.. autoclass:: PyOpenColorIO.Config
+ :members:
+ :undoc-members:
+
+ColorSpace
+==========
+
+.. autoclass:: PyOpenColorIO.ColorSpace
+ :members:
+ :undoc-members:
+
+Look
+====
+
+.. autoclass:: PyOpenColorIO.Look
+ :members:
+ :undoc-members:
+
+Processor
+=========
+
+.. autoclass:: PyOpenColorIO.Processor
+ :members:
+ :undoc-members:
+
+Context
+=======
+
+.. autoclass:: PyOpenColorIO.Context
+ :members:
+ :undoc-members:
diff --git a/docs/developers/bindings/PythonTransforms.rst b/docs/developers/bindings/PythonTransforms.rst
new file mode 100644
index 0000000..d59a877
--- /dev/null
+++ b/docs/developers/bindings/PythonTransforms.rst
@@ -0,0 +1,132 @@
+Python Transforms
+=================
+
+Transform
+---------
+
+.. autoclass:: PyOpenColorIO.Transform
+ :members:
+ :undoc-members:
+
+AllocationTransform
+-------------------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+ transform = OCIO.AllocationTransform()
+ transform.setAllocation(OCIO.Constants.ALLOCATION)
+
+.. autoclass:: PyOpenColorIO.AllocationTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+CDLTransform
+------------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+
+ cdl = OCIO.CDLTransform()
+ # Set the slope, offset, power, and saturation for each channel.
+ cdl.setSOP([, , , , , , , , ])
+ cdl.setSat([, , ])
+ cdl.getSatLumaCoefs()
+
+.. autoclass:: PyOpenColorIO.CDLTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+ColorSpaceTransform
+-------------------
+
+This class is meant so that ColorSpace conversions can be reused, referencing ColorSpaces that already exist.
+
+.. note::
+ Careless use of this may create infinite loops, so avoid referencing the colorspace you're in.
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+ transform = OCIO.ColorSpaceTransform()
+
+.. autoclass:: PyOpenColorIO.ColorSpaceTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+DisplayTransform
+----------------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+ transform = OCIO.DisplayTransform()
+
+.. autoclass:: PyOpenColorIO.DisplayTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+ExponentTransform
+-----------------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+ transform = OCIO.ExponentTransform()
+
+.. autoclass:: PyOpenColorIO.ExponentTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+FileTransform
+-------------
+
+.. autoclass:: PyOpenColorIO.FileTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+GroupTransform
+--------------
+
+.. autoclass:: PyOpenColorIO.GroupTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+LogTransform
+------------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+
+:py:class:`LogTransform` is used to define a log transform. The direction of
+the transform and its numerical base can be specified.
+
+.. autoclass:: PyOpenColorIO.LogTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+LookTransform
+-------------
+
+.. autoclass:: PyOpenColorIO.LookTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
+
+MatrixTransform
+---------------
+
+.. autoclass:: PyOpenColorIO.MatrixTransform
+ :members:
+ :undoc-members:
+ :inherited-members:
diff --git a/docs/developers/bindings/PythonTypes.rst b/docs/developers/bindings/PythonTypes.rst
new file mode 100644
index 0000000..074e65e
--- /dev/null
+++ b/docs/developers/bindings/PythonTypes.rst
@@ -0,0 +1,9 @@
+Python Types
+============
+
+Constants
+---------
+
+.. automodule:: PyOpenColorIO.Constants
+ :members:
+ :undoc-members:
diff --git a/docs/developers/coding_guidelines.rst b/docs/developers/coding_guidelines.rst
new file mode 100644
index 0000000..742b0f8
--- /dev/null
+++ b/docs/developers/coding_guidelines.rst
@@ -0,0 +1,109 @@
+Coding guidelines
+=================
+
+There are only two important rules:
+
+1. When making changes, conform to the style and conventions of the surrounding code.
+
+2. Strive for clarity, even if that means occasionally breaking the guidelines. Use your head and ask for advice if your common sense seems to disagree with the conventions.
+
+File Conventions
+****************
+
+C++ implementation should be named ``*.cpp``. Headers should be named ``*.h``.
+All source files should begin with the copyright and license, which can be cut and pasted from other source files). For NEW source files, please do change the copyright year to the present. However DO NOT edit existing files just to update the copyright year, it just creates pointless deltas and offers no increased protection
+
+Line Length
+***********
+
+Each line of text in your code should be at most 80 characters long.
+
+Generally the only exceptions are for comments with example commands or URLs - to make cut and paste easier.
+
+The other exception is for those rare cases where letting a line be longer (and wrapping on an 80-character window) is actually a better and clearer alternative than trying to split it into two lines. Sometimes this happens, but it's rare.
+
+DO NOT alter somebody else's code to re-wrap lines (or change whitespace) just because you found something that violates the rules. Let the group/author/leader know, and resist the temptation to change it yourself.
+
+Formatting
+**********
+
+* Indent 4 spaces at a time, and use actual spaces, not tabs. This is particularly critical on python code. The only exception currently allowed in within Makefiles, where tab characters are sometimes required.
+
+* Opening brace on the line following the condition or loop.
+
+* The contents of namespaces are not indented.
+
+* Function names should be on the same line as their return values.
+
+* Function calls should NOT have a space between the function name and the opening parenthesis. A single space should be added after each required comma.
+
+Here is a short code fragement that shows these concepts in action:
+
+.. code-block:: c++
+
+ namespace
+ {
+
+
+ int MungeMyNumbers(int a, int b)
+ {
+ int x = a + b;
+
+ if (a == 0 || b==0)
+ {
+ x += 1;
+ x += 2;
+ }
+ else
+ {
+ for (int i=0; i<16; ++i)
+ {
+ x += a * i;
+ }
+ }
+
+ return x;
+ }
+
+
+ } // namespace
+
+Misc. Rules
+***********
+
+* Avoid macros when possible.
+
+* Anonymous namespaces are preferred when sensible.
+
+* Variable names should be camelCase, as well as longAndExplicit.
+
+* Avoid long function implementations. Break up work into small, manageable chunks.
+
+* Use "TODO:" comments for code that is temporary, a short-term solution, or good-enough but not perfect. This is vastly preferred to leaving subtle corner cases undocumented.
+
+* Always initialize variables on construction.
+
+* Do not leave dead code paths around. (This is what revision history is for)
+
+* Includes should always be ordered as follows: C library, C++ library, other libraries' .h, OCIO public headers, OCIO private headers. Includes within a category should be alphabetized.
+
+* The C++ "using" directive is not allowed.
+
+* Static / global variables should be avoided at all costs.
+
+* Use const whenever it makes sense to do so.
+
+* The use of Boost is not allowed, except for unit_test_framework and shared_ptr.
+
+* Default function arguments are not allowed.
+
+Bottom Line
+***********
+
+When in doubt, look elsewhere in the code base for examples of similar structures and try to format your code in the same manner.
+
+
+Portions of this document have been blatantly lifted from OpenImageIO, and Google.
+
+http://openimageio.org/wiki/index.php?title=Coding_Style_Guide
+http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml \ No newline at end of file
diff --git a/docs/developers/getting_started.rst b/docs/developers/getting_started.rst
new file mode 100644
index 0000000..88f61ae
--- /dev/null
+++ b/docs/developers/getting_started.rst
@@ -0,0 +1,47 @@
+Getting started
+===============
+
+Checking Out The Codebase
+*************************
+
+The master code repository is available on Github: http://github.com/imageworks/OpenColorIO
+
+For those unfamiliar with git, the wonderful part about it is that even though only a limited number people have write access to the master repository, anyone is free to create, and even check in, changes to their own local git repository. Your local changes will not automatically be pushed back to the master repository, so everyone feel free to informally play around with the codebase. Also - unlike svn - when you download the git repository you have a full copy of the project's history (including revision history, logs, etc), so the majority of code changes you will make, including commits, do not require network server access.
+
+The first step is to install git on your system. For those new to the world of git, github has an excellent tutorial stepping you through the process, available at: http://help.github.com/
+
+To check out a read-only version of the repository (no github signup required)::
+
+ git clone git://github.com/imageworks/OpenColorIO.git ocio
+
+For write-access, you must first register for a Github account (free). Then, you must create a local fork of the OpenColorIO repository by visiting http://github.com/imageworks/OpenColorIO and clicking the "Fork" icon. If you get hung up on this, further instructions on this process are available at http://help.github.com/forking/
+
+To check out a read-write version of the repository (github acct required)::
+
+ git clone git@github.com:yourgitusername/OpenColorIO.git ocio
+
+ Initialized empty Git repository in /mcp/ocio/.git/
+ remote: Counting objects: 2220, done.
+ remote: Compressing objects: 100% (952/952), done.
+ remote: Total 2220 (delta 1434), reused 1851 (delta 1168)
+ Receiving objects: 100% (2220/2220), 2.89 MiB | 2.29 MiB/s, done.
+ Resolving deltas: 100% (1434/1434), done.
+
+Both read + read/write users should then add the Imageworks (SPI) master branch as a remote. This will allow you to more easily fetch updates as they become available::
+
+ cd ocio
+ git remote add spi git://github.com/imageworks/OpenColorIO.git
+
+Optionally, you may then add any additional users who have individual working forks (just as you've done). This will allow you to track, view, and potentially merge intermediate changes before they're been pushed into the main trunk. (For really bleeding edge folks). For example, to add Jeremy Selan's working fork::
+
+ git remote add js git://github.com/jeremyselan/OpenColorIO.git
+
+You should then do a git fetch, and git merge (detailed below) to download the remote branches you've just added.
+
+
+Merging changes
+***************
+
+More detailed guide coming soon, for now, see http://help.github.com/remotes/
+
+.. TODO: Write this \ No newline at end of file
diff --git a/docs/developers/index.rst b/docs/developers/index.rst
new file mode 100644
index 0000000..67a2da2
--- /dev/null
+++ b/docs/developers/index.rst
@@ -0,0 +1,45 @@
+.. _developer-guide:
+
+Developer guide
+===============
+
+Some information on contributing to OCIO:
+
+.. toctree::
+ :maxdepth: 1
+
+ getting_started
+ coding_guidelines
+ submitting_changes
+ issues
+
+Instructions on using OCIO:
+
+.. toctree::
+ :maxdepth: 1
+
+ usage_examples
+
+C++ API documentation:
+
+.. toctree::
+ :maxdepth: 1
+
+ api/index
+
+Python API documentation:
+
+.. toctree::
+ :maxdepth: 1
+
+ bindings/PythonAPI
+ bindings/PythonTransforms
+ bindings/PythonTypes
+
+Internal Architecture:
+
+.. toctree::
+ :maxdepth: 1
+
+ internal_architecture
+
diff --git a/docs/developers/internal_architecture.rst b/docs/developers/internal_architecture.rst
new file mode 100644
index 0000000..d74bd0d
--- /dev/null
+++ b/docs/developers/internal_architecture.rst
@@ -0,0 +1,287 @@
+Internal Architecture Overview
+==============================
+
+External API
+************
+
+
+Configs
+~~~~~~~
+
+At the highest level, we have OCIO::Configs. This represents the entirety of the
+current color "universe". Configs are serialized as .ocio files, read at runtime,
+and are often used in a 'read-only' context.
+
+Config are loaded at runtime to allow for customized color handling in a show-
+dependent manner.
+
+Example Configs:
+
+* ACES (Acacdemy's standard color workflow)
+* spi-vfx (Used on some Imageworks VFX shows such as spiderman, etc).
+* and others
+
+
+ColorSpaces
+~~~~~~~~~~~
+
+The meat of an OCIO::Config is a list of named ColorSpaces. ColorSpace often
+correspond to input image states, output image states, or image states used for
+internal processing.
+
+Example ColorSpaces (from ACES configuration):
+
+* aces (HDR, scene-linear)
+* adx10 (log-like density encoding space)
+* slogf35 (sony F35 slog camera encoding)
+* rrt_srgb (baked in display transform, suitable for srgb display)
+* rrt_p3dci (baked in display transform, suitable for dcip3 display)
+
+
+
+Transforms
+~~~~~~~~~~
+
+ColorSpaces contain an ordered list of transforms, which define the conversion
+to and from the Config's "reference" space.
+
+Transforms are the atomic units available to the designer in order to specify a
+color conversion.
+
+Examples of OCIO::Transforms are:
+
+* File-based transforms (1d lut, 3d lut, mtx... anything, really.)
+* Math functions (gamma, log, mtx)
+* The 'meta' GroupTransform, which contains itself an ordered lists of transforms
+* The 'meta' LookTransform, which contains an ordered lists of transforms
+
+For example, the adx10 ColorSpace (in one particular ACES configuration)
+-Transform FROM adx, to our reference ColorSpace:
+
+#. Apply FileTransform adx_adx10_to_cdd.spimtx
+#. Apply FileTransform adx_cdd_to_cid.spimtx
+#. Apply FileTransform adx_cid_to_rle.spi1d
+#. Apply LogTransform base 10 (inverse)
+#. Apply FileTransform adx_exp_to_aces.spimtx
+
+If we have an image in the reference ColorSpace (unnamed), we can convert TO
+adx by applying each in the inverse direction:
+
+#. Apply FileTransform adx_exp_to_aces.spimtx (inverse)
+#. Apply LogTransform base 10 (forward)
+#. Apply FileTransform adx_cid_to_rle.spi1d (inverse)
+#. Apply FileTransform adx_cdd_to_cid.spimtx (inverse)
+#. Apply FileTransform adx_adx10_to_cdd.spimtx (inverse)
+
+Note that this isn't possible in all cases (what if a lut or matrix is not
+invertible?), but conceptually it's a simple way to think about the design.
+
+
+
+Summary
+~~~~~~~
+
+Configs and ColorSpaces are just a bookkeeping device used to get and ordered
+lists of Transforms corresponding to image color transformation.
+
+Transforms are visible to the person AUTHORING the OCIO config, but are
+NOT visible to the client applications. Client apps need only concern themselves
+with Configs and Processors.
+
+
+
+
+OCIO::Processors
+~~~~~~~~~~~~~~~~
+
+A processor corresponds to a 'baked' color transformation. You specify two arguments
+when querying a processor: the :ref:`colorspace_section` you are coming from,
+and the :ref:`colorspace_section` you are going to.
+
+Once you have the processor, you can apply the color transformation using the
+"apply" function. For the CPU veseion, first wrap your image in an
+ImageDesc class, and then call apply to process in place.
+
+Example:
+
+.. code-block:: cpp
+
+ #include <OpenColorIO/OpenColorIO.h>
+ namespace OCIO = OCIO_NAMESPACE;
+
+ try
+ {
+ // Get the global OpenColorIO config
+ // This will auto-initialize (using $OCIO) on first use
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ // Get the processor corresponding to this transform.
+ // These strings, in this example, are specific to the above
+ // example. ColorSpace names should NEVER be hard-coded into client
+ // software, but should be dynamically queried at runtime from the library
+ OCIO::ConstProcessorRcPtr processor = config->getProcessor("adx10", "aces");
+
+ // Wrap the image in a light-weight ImageDescription
+ OCIO::PackedImageDesc img(imageData, w, h, 4);
+
+ // Apply the color transformation (in place)
+ processor->apply(img);
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cerr << "OpenColorIO Error: " << exception.what() << std::endl;
+ }
+
+
+The GPU code path is similar. You get the processor from the config, and then
+query the shaderText and the lut3d. The client loads these to the GPU themselves,
+and then makes the appropriate calls to the newly defined function.
+
+See `src/apps/ociodisplay` for an example.
+
+
+
+Internal API
+************
+
+
+The Op Abstraction
+~~~~~~~~~~~~~~~~~~
+
+It is a useful abstraction, both for code-reuse and optimization, to not relying
+on the transforms to do pixel processing themselves.
+
+Consider that the FileTransform represents a wide-range of image processing
+operations (basically all of em), many of which are really complex. For example,
+the houdini lut format in a single file may contain a log convert, a 1d lut, and
+then a 3d lut; all of which need to be applied in a row! If we dont want the
+FileTransform to know how to process all possible pixel operations, it's much
+simpler to make light-weight processing operations, which the transforms can
+create to do the dirty work as needed.
+
+All image processing operations (ops) are a class that present the same
+interface, and it's rather simple:
+(src/core/Op.h)
+
+.. code-block:: cpp
+
+ virtual void apply(float* rgbaBuffer, long numPixels)
+
+Basically, given a packed float array with the specified number of pixels, process em.
+
+Examples of ops include Lut1DOp, Lut3DOp, MtxOffsetOp, LogOp, etc.
+
+Thus, the job of a transform becomes much simpler and they're only responsible
+for converting themselves to a list of ops. A simple FileTransform that only has
+a single 1D lut internally may just generate a single Lut1DOp, but a
+FileTransform that references a more complex format (such as the houdini lut case
+referenced above) may generate a few ops:
+
+.. code-block:: cpp
+
+ void FileFormatHDL::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const {
+
+ // Code omitted which loads the lut file into the file cache...
+
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), dir);
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), dir);
+
+See (src/core/*Ops.h) for the available ops.
+
+Note that while compositors often have complex, branching trees of image processing
+operations, we just have a linear list of ops, lending itself very well to
+optimization.
+
+Before the ops are run, they are optimized. (Collapsed with appropriate neighbors, etc).
+
+
+An Example
+~~~~~~~~~~
+
+Let us consider the internal steps when getProcessor() is called to convert
+from ColorSpace 'adx10' to ColorSpace 'aces'.
+
+* The first step is to turn this ColorSpace conversion into an ordered list of
+transforms. We do this by creating a single of the conversions from 'adx10'
+to reference, and then adding the transforms required to go from reference to
+'aces'.
+
+* The Transform list is then converted into a list of ops. It is during this
+stage luts, are loaded, etc.
+
+
+
+CPU CODE PATH
+~~~~~~~~~~~~~
+
+The master list of ops is then optimized, and stored internally in the processor.
+
+.. code-block:: cpp
+
+ FinalizeOpVec(m_cpuOps);
+
+During Processor::apply(...), a subunit of pixels in the image are formatted into a sequential rgba block. (Block size is optimized for computational (SSE) simplicity and performance, and is typically similar in size to an image scanline)
+
+.. code-block:: cpp
+
+ float * rgbaBuffer = 0;
+ long numPixels = 0;
+ while(true) {
+ scanlineHelper.prepRGBAScanline(&rgbaBuffer, &numPixels);
+ ...
+
+Then for each op, op->apply is called in-place.
+
+.. code-block:: cpp
+
+ for(OpRcPtrVec::size_type i=0, size = m_cpuOps.size(); i<size; ++i)
+ {
+ m_cpuOps[i]->apply(rgbaBuffer, numPixels);
+ }
+
+After all ops have been applied, the results are copied back to the source
+
+.. code-block:: cpp
+
+ scanlineHelper.finishRGBAScanline();
+
+
+
+GPU CODE PATH
+~~~~~~~~~~~~~
+
+#. The master list of ops is partitioned into 3 ordered lists:
+
+- As many ops as possible from the BEGINNING of the op-list that can be done
+ analytically in shader text. (called gpu-preops)
+- As many ops as possible from the END of the op-list that can be done
+ analytically in shader text. (called gpu-postops)
+- The left-over ops in the middle that cannot support shader text, and thus
+ will be baked into a 3dlut. (called gpu-lattice)
+
+#. Between the first an the second lists (gpu-preops, and gpu-latticeops), we
+anaylze the op-stream metadata and determine the appropriate allocation to use.
+(to minimize clamping, quantization, etc). This is accounted for here by
+interserting a forward allocation to the end of the pre-ops, and the inverse
+allocation to the start of the lattice ops.
+
+See https://github.com/imageworks/OpenColorIO/blob/master/src/core/NoOps.cpp#L183
+
+#. The 3 lists of ops are then optimized individually, and stored on the processor.
+The Lut3d is computed by applying the gpu-lattice ops, on the CPU, to a lut3d
+image.
+
+The shader text is computed by calculating the shader for the gpu-preops, adding
+a sampling function of the 3d lut, and then calculating the shader for the gpu
+post ops.
+
+
+
+
diff --git a/docs/developers/issues.rst b/docs/developers/issues.rst
new file mode 100644
index 0000000..e26bd3b
--- /dev/null
+++ b/docs/developers/issues.rst
@@ -0,0 +1,4 @@
+Issues
+======
+
+Please visit http://github.com/imageworks/OpenColorIO/issues for an up to date listing of bugs, feature requests etc \ No newline at end of file
diff --git a/docs/developers/submitting_changes.rst b/docs/developers/submitting_changes.rst
new file mode 100644
index 0000000..ca1169d
--- /dev/null
+++ b/docs/developers/submitting_changes.rst
@@ -0,0 +1,14 @@
+Submitting Changes
+==================
+
+Code Review
+***********
+
+Ask early, and ask often!
+
+All new contributors are highly encouraged to post development ideas, questions,
+or any other thoughts to the :ref:`mailing_lists` before starting to code. This
+greatly improves the process and quality of the resulting library. Code
+reviews (particularly for non-trivial changes) are typically far simpler if the
+reviewers are aware of a development task beforehand. (And, who knows? Maybe they
+will have implementation suggestions as well!)
diff --git a/docs/developers/usage_examples.rst b/docs/developers/usage_examples.rst
new file mode 100644
index 0000000..8dace70
--- /dev/null
+++ b/docs/developers/usage_examples.rst
@@ -0,0 +1,357 @@
+.. _developers-usageexamples:
+
+Usage Examples
+==============
+
+Some examples of using the OCIO API, via both C++ and the Python bindings.
+
+For further examples, see the ``src/apps/`` directory in the git repository
+
+.. _usage_applybasic:
+
+Applying a basic ColorSpace transform, using the CPU
+****************************************************
+This describes what code is used to convert from a specified source
+:cpp:class:`ColorSpace` to a specified destination :cpp:class:`ColorSpace`.
+If you are using the OCIO Nuke plugins, the OCIOColorSpace node performs these
+steps internally.
+
+#. **Get the Config.**
+ This represents the entirety of the current color "universe". It can either
+ be initialized by your app at startup or created explicitly. In common
+ usage, you can just query :cpp:func:`GetCurrentConfig`, which will auto
+ initialize on first use using the :envvar:`OCIO` environment variable.
+
+#. **Get Processor from the Config.**
+ A processor corresponds to a 'baked' color transformation. You specify two
+ arguments when querying a processor: the :ref:`colorspace_section` you are
+ coming from, and the :ref:`colorspace_section` you are going to.
+ :ref:`cfgcolorspaces_section` ColorSpaces can be either explicitly named
+ strings (defined by the current configuration) or can be
+ :ref:`cfgroles_section` (essentially :ref:`colorspace_section` aliases)
+ which are consistent across configurations. Constructing a
+ :cpp:class:`Processor` object is likely a blocking operation (thread-wise)
+ so care should be taken to do this as infrequently as is sensible. Once per
+ render 'setup' would be appropriate, once per scanline would be
+ inappropriate.
+
+#. **Convert your image, using the Processor.**
+ Once you have the processor, you can apply the color transformation using
+ the "apply" function. In :ref:`usage_applybasic_cpp`, you apply the
+ processing in-place, by first wrapping your image in an
+ :cpp:class:`ImageDesc` class. This approach is intended to be used in high
+ performance applications, and can be used on multiple threads (per scanline,
+ per tile, etc). In :ref:`usage_applybasic_python` you call
+ "applyRGB" / "applyRGBA" on your sequence of pixels. Note that in both
+ languages, it is far more efficient to call "apply" on batches of pixels at
+ a time.
+
+.. _usage_applybasic_cpp:
+
+C++
+---
+
+.. code-block:: cpp
+
+ #include <OpenColorIO/OpenColorIO.h>
+ namespace OCIO = OCIO_NAMESPACE;
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ ConstProcessorRcPtr processor = config->getProcessor(OCIO::ROLE_COMPOSITING_LOG,
+ OCIO::ROLE_SCENE_LINEAR);
+
+ OCIO::PackedImageDesc img(imageData, w, h, 4);
+ processor->apply(img);
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cerr << "OpenColorIO Error: " << exception.what() << std::endl;
+ }
+
+.. _usage_applybasic_python:
+
+Python
+------
+
+.. code-block:: py
+
+ import PyOpenColorIO as OCIO
+
+ try:
+ config = OCIO.GetCurrentConfig()
+ processor = config.getProcessor(OCIO.Constants.ROLE_COMPOSITING_LOG,
+ OCIO.Constants.ROLE_SCENE_LINEAR)
+
+ # Apply the color transform to the existing RGBA pixel data
+ img = processor.applyRGBA(img)
+ except Exception, e:
+ print "OpenColorIO Error",e
+
+.. _usage_displayimage:
+
+Displaying an image, using the CPU (simple ColorSpace conversion)
+*****************************************************************
+Converting an image for display is similar to a normal color space conversion.
+The only difference is that one has to first determine the name of the display
+(destination) ColorSpace by querying the config with the device name and
+transform name.
+
+#. **Get the Config.**
+ See :ref:`usage_applybasic` for details.
+
+#. **Lookup the display ColorSpace.**
+ The display :cpp:class:`ColorSpace` is queried from the configuration using
+ :cpp:func:`Config::getDisplayColorSpaceName`. If the user has specified
+ value for the ``device`` or the ``displayTransformName``, use them. If these
+ values are unknown default values can be queried (as shown below).
+
+#. **Get the processor from the Config.**
+ See :ref:`usage_applybasic` for details.
+
+#. **Convert your image, using the processor.**
+ See :ref:`usage_applybasic` for details.
+
+C++
+---
+
+.. code-block:: cpp
+
+ #include <OpenColorIO/OpenColorIO.h>
+ namespace OCIO = OCIO_NAMESPACE;
+
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ // If the user hasn't picked a display, use the defaults...
+ const char * device = config->getDefaultDisplayDeviceName();
+ const char * transformName = config->getDefaultDisplayTransformName(device);
+ const char * displayColorSpace = config->getDisplayColorSpaceName(device, transformName);
+
+ ConstProcessorRcPtr processor = config->getProcessor(OCIO::ROLE_SCENE_LINEAR,
+ displayColorSpace);
+
+ OCIO::PackedImageDesc img(imageData, w, h, 4);
+ processor->apply(img);
+
+Python
+------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+
+ config = OCIO.GetCurrentConfig()
+
+ device = config.getDefaultDisplayDeviceName()
+ transformName = config.getDefaultDisplayTransformName(device)
+ displayColorSpace = config.getDisplayColorSpaceName(device, transformName)
+
+ processor = config.getProcessor(OCIO.Constants.ROLE_SCENE_LINEAR, displayColorSpace)
+
+ processor.applyRGB(imageData)
+
+
+Displaying an image, using the CPU (Full Display Pipeline)
+**********************************************************
+
+This alternative version allows for a more complex displayTransform, allowing
+for all of the controls typically added to real-world viewer interfaces. For
+example, options are allowed to control which channels (red, green, blue,
+alpha, luma) are visible, as well as allowing for optional color corrections
+(such as an exposure offset in scene linear). If you are using the OCIO Nuke
+plugins, the OCIODisplay node performs these steps internally.
+
+#. **Get the Config.**
+ See :ref:`usage_applybasic` for details.
+#. **Lookup the display ColorSpace.**
+ See :ref:`usage_displayimage` for details
+#. **Create a new DisplayTransform.**
+ This transform will embody the full 'display' pipeline you wish to control.
+ The user is required to call
+ :cpp:func:`DisplayTransform::setInputColorSpaceName` to set the input
+ ColorSpace, as well as
+ :cpp:func:`DisplayTransform::setDisplayColorSpaceName` (with the results of
+ :cpp:func:`Config::getDisplayColorSpaceName`).
+#. **Set any additional DisplayTransform options.**
+ If the user wants to specify a channel swizzle, a scene-linear exposure
+ offset, an artistic look, this is the place to add it. See below for an
+ example. Note that although we provide recommendations for display, any
+ transforms are allowed to be added into any of the slots. So if for your app
+ you want to add 3 transforms into a particular slot (chained together), you
+ are free to wrap them in a :cpp:class:`GroupTransform` and set it
+ accordingly!
+#. **Get the processor from the Config.**
+ The processor is then queried from the config passing the new
+ :cpp:class:`DisplayTransform` as the argument. Once the processor has been
+ returned, the original :cpp:class:`DisplayTransform` is no longer necessary
+ to hold onto. (Though if you'd like to for re-use, there is no problem doing
+ so).
+#. **Convert your image, using the processor.**
+ See :ref:`usage_applybasic` for details.
+
+C++
+---
+
+.. code-block:: cpp
+
+ // Step 1: Get the config
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ // Step 2: Lookup the display ColorSpace
+ const char * device = config->getDefaultDisplayDeviceName();
+ const char * transformName = config->getDefaultDisplayTransformName(device);
+ const char * displayColorSpace = config->getDisplayColorSpaceName(device, transformName);
+
+ // Step 3: Create a DisplayTransform, and set the input and display ColorSpaces
+ // (This example assumes the input is scene linear. Adapt as needed.)
+
+ OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
+ transform->setInputColorSpaceName( OCIO::ROLE_SCENE_LINEAR );
+ transform->setDisplayColorSpaceName( displayColorSpace );
+
+ // Step 4: Add custom transforms for a 'canonical' Display Pipeline
+
+ // Add an fstop exposure control (in SCENE_LINEAR)
+ float gain = powf(2.0f, exposure_in_stops);
+ const float slope3f[] = { gain, gain, gain };
+ OCIO::CDLTransformRcPtr cc = OCIO::CDLTransform::Create();
+ cc->setSlope(slope3f);
+ transform->setLinearCC(cc);
+
+ // Add a Channel view 'swizzle'
+
+ // 'channelHot' controls which channels are viewed.
+ int channelHot[4] = { 1, 1, 1, 1 }; // show rgb
+ //int channelHot[4] = { 1, 0, 0, 0 }; // show red
+ //int channelHot[4] = { 0, 0, 0, 1 }; // show alpha
+ //int channelHot[4] = { 1, 1, 1, 0 }; // show luma
+
+ float lumacoef[3];
+ config.getDefaultLumaCoefs(lumacoef);
+
+ float m44[16];
+ float offset[4];
+ OCIO::MatrixTransform::View(m44, offset, channelHot, lumacoef);
+ OCIO::MatrixTransformRcPtr swizzle = OCIO::MatrixTransform::Create();
+ swizzle->setValue(m44, offset);
+ transform->setChannelView(swizzle);
+
+ // And then process the image normally.
+ OCIO::ConstProcessorRcPtr processor = config->getProcessor(transform);
+
+ OCIO::PackedImageDesc img(imageData, w, h, 4);
+ processor->apply(img);
+
+Python
+------
+
+.. code-block:: python
+
+ import PyOpenColorIO as OCIO
+
+ # Step 1: Get the config
+ config = OCIO.GetCurrentConfig()
+
+ # Step 2: Lookup the display ColorSpace
+ device = config.getDefaultDisplayDeviceName()
+ transformName = config.getDefaultDisplayTransformName(device)
+ displayColorSpace = config.getDisplayColorSpaceName(device, transformName)
+
+ # Step 3: Create a DisplayTransform, and set the input and display ColorSpaces
+ # (This example assumes the input is scene linear. Adapt as needed.)
+
+ transform = OCIO.DisplayTransform()
+ transform.setInputColorSpaceName(OCIO.Constants.ROLE_SCENE_LINEAR)
+ transform.setDisplayColorSpaceName(displayColorSpace)
+
+ # Step 4: Add custom transforms for a 'canonical' Display Pipeline
+
+ # Add an fstop exposure control (in SCENE_LINEAR)
+ gain = 2**exposure
+ slope3f = (gain, gain, gain)
+
+ cc = OCIO.CDLTransform()
+ cc.setSlope(slope3f)
+
+ transform.setLinearCC(cc)
+
+ # Add a Channel view 'swizzle'
+
+ channelHot = (1, 1, 1, 1) # show rgb
+ # channelHot = (1, 0, 0, 0) # show red
+ # channelHot = (0, 0, 0, 1) # show alpha
+ # channelHot = (1, 1, 1, 0) # show luma
+
+ lumacoef = config.getDefaultLumaCoefs()
+
+ m44, offset = OCIO.MatrixTransform.View(channelHot, lumacoef)
+
+ swizzle = OCIO.MatrixTransform()
+ swizzle.setValue(m44, offset)
+ transform.setChannelView(swizzle)
+
+ # And then process the image normally.
+ processor = config.getProcessor(transform)
+
+ print processor.applyRGB(imageData)
+
+
+Displaying an image, using the GPU
+**********************************
+
+Applying OpenColorIO's color processing using GPU processing is
+straightforward, provided you have the capability to upload custom shader code
+and a custom 3D Lookup Table (3DLUT).
+
+#. **Get the Processor.**
+ This portion of the pipeline is identical to the CPU approach. Just get the
+ processor as you normally would have, see above for details.
+#. **Create a GpuShaderDesc.**
+#. **Query the GPU Shader Text + 3D LUT.**
+#. **Configure the GPU State.**
+#. **Draw your image.**
+
+C++
+---
+
+This example is available as a working app in the OCIO source: src/apps/ociodisplay.
+
+.. code-block:: cpp
+
+ // Step 0: Get the processor using any of the pipelines mentioned above.
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ const char * device = config->getDefaultDisplayDeviceName();
+ const char * transformName = config->getDefaultDisplayTransformName(device);
+ const char * displayColorSpace = config->getDisplayColorSpaceName(device, transformName);
+ ConstProcessorRcPtr processor = config->getProcessor(OCIO::ROLE_SCENE_LINEAR,
+ displayColorSpace);
+
+ // Step 1: Create a GPU Shader Description
+ GpuShaderDesc shaderDesc;
+ shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
+ shaderDesc.setFunctionName("OCIODisplay");
+ const int LUT3D_EDGE_SIZE = 32;
+ shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+
+ // Step 2: Compute and the 3D LUT
+ // Optional Optimization:
+ // Only do this the 3D LUT's contents
+ // are different from the last drawn frame.
+ // Use getGpuLut3DCacheID to compute the cacheID.
+ // cheaply.
+ //
+ // std::string lut3dCacheID = processor->getGpuLut3DCacheID(shaderDesc);
+ int num3Dentries = 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE;
+ std::vector<float> g_lut3d;
+ g_lut3d.resize(num3Dentries);
+ processor->getGpuLut3D(&g_lut3d[0], shaderDesc);
+
+ // Load the data into an OpenGL 3D Texture
+ glGenTextures(1, &g_lut3d_textureID);
+ glBindTexture(GL_TEXTURE_3D, g_lut3d_textureID);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB,
+ LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+ 0, GL_RGB,GL_FLOAT, &g_lut3d[0]);
+
+ // Step 3: Query
diff --git a/docs/downloads.rst b/docs/downloads.rst
new file mode 100644
index 0000000..d5e6615
--- /dev/null
+++ b/docs/downloads.rst
@@ -0,0 +1,41 @@
+.. _downloads:
+
+Downloads
+=========
+
+* Sample OCIO Configurations -- `.zip <http://github.com/imageworks/OpenColorIO-Configs/zipball/master>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO-Configs/tarball/master>`__
+* Reference Images v1.0v4 -- `.tgz <http://code.google.com/p/opencolorio/downloads/detail?name=ocio-images.1.0v4.tgz>`__
+* Core Library v1.0.8 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.8>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.8>`__
+* Core Library latest -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/master>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/master>`__
+
+Per-version updates: :ref:`changelog-main`.
+
+Build instructions: :ref:`building-from-source`.
+
+.. _contributor-license-agreements:
+
+Contributor License Agreements
+******************************
+Please see the `Imageworks Open Source website <http://opensource.imageworks.com/cla/>`__
+
+Deprecated Downloads
+********************
+* Reference Images v1.0v2 `tgz <http://code.google.com/p/opencolorio/downloads/detail?name=ocio-images.1.0v2.tgz>`__
+* Reference Images v1.0v1 `tgz <http://code.google.com/p/opencolorio/downloads/detail?name=ocio-images.1.0v1.tgz>`__
+
+* Core Library v1.0.7 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.7>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.7>`__
+* Core Library v1.0.6 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.6>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.6>`__
+* Core Library v1.0.5 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.5>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.5>`__
+* Core Library v1.0.4 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.4>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.4>`__
+* Core Library v1.0.3 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.3>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.3>`__
+* Core Library v1.0.2 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.2>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.2>`__
+* Core Library v1.0.1 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.1>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.1>`__
+* Core Library v1.0.0 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v1.0.0>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v1.0.0>`__
+
+* Color Config v0.7v4 `tgz <http://code.google.com/p/opencolorio/downloads/detail?name=ocio-configs.0.7v4.tgz>`__ (OCIO v0.7.6+)
+* Core Library v0.8.7 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v0.8.7>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v0.8.7>`__
+* Core Library v0.7.9 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v0.7.9>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v0.7.9>`__
+* Core Library v0.6.1 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v0.6.1>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v0.6.1>`__
+* Core Library v0.5.16 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v0.5.16>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v0.5.16>`__
+* Core Library v0.5.8 -- `.zip <http://github.com/imageworks/OpenColorIO/zipball/v0.5.8>`__ `.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/v0.5.8>`__
+
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..3757b66
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,77 @@
+Home
+====
+
+.. include:: README
+
+.. _mailing_lists:
+
+Mailing lists
+"""""""""""""
+
+There are two mailing lists associated with OpenColorIO:
+
+`ocio-users <http://groups.google.com/group/ocio-users>`__\ ``@googlegroups.com``
+ For end users (artists, often) interested in OCIO profile design,
+ facility color management, and workflow.
+
+`ocio-dev <http://groups.google.com/group/ocio-dev>`__\ ``@googlegroups.com``
+ For developers interested OCIO APIs, code integration, compilation, etc.
+
+Using OpenColorIO
+"""""""""""""""""
+
+Most users will likely want to use the OpenColorIO that comes precompiled with
+their applications. See the :ref:`compatiblesoftware` for further details on
+each application.
+
+Note that OCIO configurations aren't required to do any 'real' work, and are
+available separately on the :ref:`downloads` section of this site. Example
+images are also available. For assistance customizing .ocio configurations,
+contact the ocio-users email alias.
+
+- Step 1: set the OCIO environment-variable to /path/to/your/profile.ocio
+- Step 2: Launch supported application.
+
+If you are on a platform that is not envvar friendly, most applications also
+provide a menu option to select a different OCIO configuration after launch.
+
+Please be sure to select a profile that matches your color workflow (VFX work
+typically requires a different profile than animated features). If you need
+assistance picking a profile, email ocio-users.
+
+Downloading and building the code
+"""""""""""""""""""""""""""""""""
+
+Source code is available on Github at
+http://github.com/imageworks/OpenColorIO
+
+Download a `.zip <http://github.com/imageworks/OpenColorIO/zipball/master>`_ or
+`.tar.gz <http://github.com/imageworks/OpenColorIO/tarball/master>`_ of the
+current state of the repository.
+
+Please see the :ref:`developer-guide` for more info, and contact ocio-dev with any
+questions.
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ self
+ CompatibleSoftware
+
+ configurations/index
+ installation
+
+ userguide/index
+
+ developers/index
+
+ FAQ
+ downloads
+
+ ChangeLog
+ License
+
+:ref:`search`
+
+:ref:`genindex`
diff --git a/docs/installation.rst b/docs/installation.rst
new file mode 100644
index 0000000..e6e26e2
--- /dev/null
+++ b/docs/installation.rst
@@ -0,0 +1,234 @@
+Installation
+============
+
+.. _building-from-source:
+
+Building from source
+********************
+
+While there is a huge range of possible setups, the following steps
+should work on OS X and most Linux distros.
+
+The basic requirements are:
+
+- cmake >= 2.8
+- (optional) Python 2.x (for the Python bindings)
+- (optional) Nuke 6.x (for the Nuke nodes)
+- (optional) OpenImageIO (for apps including ocioconvert)
+- (optional) Truelight SDK (for TruelightTransform)
+
+To keep things simple, this guide will use the following example
+paths - these will almost definitely be different for you:
+
+- source code: ``/source/ocio``
+- the temporary build location: ``/tmp/ociobuild``
+- the final install directory: ``/software/ocio``
+
+First make the build directory and cd to it::
+
+ $ mkdir /tmp/ociobuild
+ $ cd /tmp/ociobuild
+
+Next step is to run cmake, which looks for things such as the
+compiler's required arguments, optional requirements like Python,
+Nuke, OpenImageIO etc
+
+As we want to install OCIO to a custom location (instead of the
+default ``/usr/local``), we will run cmake with
+``CMAKE_INSTALL_PREFIX``
+
+Still in ``/tmp/ociobuild``, run::
+
+ $ cmake -D CMAKE_INSTALL_PREFIX=/software/ocio /source/ocio
+
+The last argument is the location of the OCIO source code (containing
+the main CMakeLists.txt file). You should see something along the
+lines of::
+
+ -- Configuring done
+ -- Generating done
+ -- Build files have been written to: /tmp/ociobuild
+
+Next, build everything (with the ``-j`` flag to build using 8
+threads)::
+
+ $ make -j8
+
+This should complete in a few minutes. Finally, install the files into
+the specified location::
+
+ $ make install
+
+If nothing went wrong, ``/software/ocio`` should look something like
+this::
+
+ $ cd /software/ocio
+ $ ls
+ bin/ include/ lib/
+ $ ls bin/
+ ocio2icc ociobakelut ociocheck
+ $ ls include/
+ OpenColorIO/ PyOpenColorIO/ pkgconfig/
+ $ ls lib/
+ libOpenColorIO.a libOpenColorIO.dylib
+
+
+.. _enabling-optional-components:
+
+Enabling optional components
+----------------------------
+
+The OpenColorIO library is probably not all you want - the Python
+libraries bindings, the Nuke nodes and several applications are only
+built if their dependencies are found.
+
+In the case of the Python bindings, the dependencies are the Python
+headers for the version you wish to use. These may be picked up by
+default - if so, when you run cmake you would see::
+
+ -- Python 2.6 okay, will build the Python bindings against .../include/python2.6
+
+If not, you can point cmake to correct Python executable using the
+``-D PYTHON=...`` cmake flag::
+
+ $ cmake -D PYTHON=/my/custom/python2.6 /source/ocio
+
+Same process with Nuke (although it less likely to be picked up
+automatically). Point cmake to your Nuke install directory by adding
+``-D NUKE_INSTALL_PATH``::
+
+ $ cmake -D PYTHON=/my/custom/python2.6 -D NUKE_INSTALL_PATH=/Applications/Nuke6.2v1/Nuke6.2v1.app/Contents/MacOS/ /source/ocio
+
+The ``NUKE_INSTALL_PATH`` directory should contain the Nuke executable
+(e.g Nuke6.2v1), and a ``include/`` directory containing ``DDImage/``
+and others.
+
+If set correctly, you will see something similar to::
+
+ -- Found Nuke: /Applications/Nuke6.2v1/Nuke6.2v1.app/Contents/MacOS/include
+ -- Nuke_API_VERSION: --6.2--
+
+The Nuke plugins are installed into ``lib/nuke$MAJOR.$MINOR/``, e.g
+``lib/nuke6.2/OCIODisdplay.so``
+
+
+.. note::
+
+ If you are using the Nuke plugins, you should compile the Python
+ bindings for the same version of Python that Nuke uses
+ internally. For Nuke 6.0 and 6.1 this is Python 2.5, and for 6.2
+ it is Python 2.6
+
+The applications included with OCIO have various dependencies - to
+determine these, look at the CMake output when first run::
+
+ -- Not building ocioconvert. Requirement(s) found: OIIO:FALSE
+
+
+.. _quick-env-config:
+
+Quick environment configuration
+*******************************
+
+The quickest way to set the required :ref:`environment-setup` is to
+source the ``share/ocio/setup_ocio.sh`` script installed with OCIO.
+
+For a simple single-user setup, add the following to ``~/.bashrc``
+(assuming you are using bash, and the example install directory of
+``/software/ocio``)::
+
+ source /software/ocio/share/ocio/setup_ocio.sh
+
+The only environment variable you must configure manually is
+:envvar:`OCIO`, which points to the configuration file you wish to
+use. For prebuilt config files, see the
+:ref:`downloads` section
+
+To do this, you would add a line to ``~/.bashrc`` (or a per-project
+configuration script etc), for example::
+
+ export OCIO="/path/to/my/config.ocio"
+
+
+.. _nuke-configuration:
+
+Nuke Configuration
+******************
+
+If you specified the ``NUKE_INSTALL_PATH`` option when running cmake,
+you should have a ``/software/ocio/lib/nuke6.2`` directory containing
+various files.
+
+If you have followed :ref:`quick-env-config`, the plugins should be
+functional. However, one common additional configuration step is to
+register an OCIODisplay node for each display device/view specified in
+the config.
+
+To do this, in a menu.py on :envvar:`NUKE_PATH` (e.g
+``~/.nuke/menu.py`` for a single user setup), add the following:
+
+.. code-block:: python
+
+ import ocionuke.viewer
+ ocionuke.viewer.populate_viewer(also_remove = "default")
+
+The ``also_remove`` argument can be set to either "default" to remove
+the default sRGB/rec709 options, "all" to remove everything, or "none"
+to leave existing viewer processes untouched.
+
+Alternatively, if your workflow has different requirements, you can
+copy the function and modify it as required, or use it as reference to
+write your own, better viewer setup function!
+
+.. literalinclude:: viewer.py
+ :language: python
+
+
+.. _environment-setup:
+
+Environment variables
+*********************
+
+.. envvar:: OCIO
+
+ This variable needs to point to the global OCIO config file, e.g
+ ``config.ocio``
+
+.. envvar:: DYLD_LIBRARY_PATH
+
+ The ``lib/`` folder (containing ``libOpenColorIO.dylib``) must be
+ on the ``DYLD_LIBRARY_PATH`` search path, or you will get an error
+ similar to::
+
+ dlopen(.../OCIOColorSpace.so, 2): Library not loaded: libOpenColorIO.dylib
+ Referenced from: .../OCIOColorSpace.so
+ Reason: image not found
+
+ This applies to anything that links against OCIO, including the
+ Nuke nodes, and the ``PyOpenColorIO`` Python bindings.
+
+.. envvar:: LD_LIBRARY_PATH
+
+ Equivalent to the ``DYLD_LIBRARY_PATH`` on Linux
+
+.. envvar:: PYTHONPATH
+
+ Python's module search path. If you are using the PyOpenColorIO
+ module, you must add ``lib/python2.x`` to this search path (e.g
+ ``python/2.5``), or importing the module will fail::
+
+ >>> import PyOpenColorIO
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ ImportError: No module named PyOpenColorIO
+
+ Note that :envvar:`DYLD_LIBRARY_PATH` or :envvar:`LD_LIBRARY_PATH`
+ must be set correctly for the module to work.
+
+.. envvar:: NUKE_PATH
+
+ Nuke's customisation search path, where it will look for plugins,
+ gizmos, init.py and menu.py scripts and other customisations.
+
+ This should point to both ``lib/nuke6.2/`` (or whatever version
+ the plugins are built against), and ``share/nuke/``
diff --git a/docs/ociotheme/layout.html b/docs/ociotheme/layout.html
new file mode 100644
index 0000000..43a5858
--- /dev/null
+++ b/docs/ociotheme/layout.html
@@ -0,0 +1,74 @@
+{#
+ haiku/layout.html
+ ~~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the haiku theme.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{% extends "basic/layout.html" %}
+{% set script_files = script_files + ['_static/theme_extras.js'] %}
+{% set css_files = css_files + ['_static/print.css'] %}
+
+{% block relbar1 %}{% endblock %}
+{% block relbar2 %}{% endblock %}
+
+{% block htmltitle %}
+ <title>OpenColorIO</title>
+{% endblock %}
+
+{% macro nav() %}
+ <p>
+ {%- block haikurel1 %}
+ {%- endblock %}
+ {%- block haikurel2 %}
+ {%- endblock %}
+ </p>
+{% endmacro %}
+
+{% block content %}
+ <div class="header">
+ {%- block haikuheader %}
+ {%- if theme_full_logo != "false" %}
+ <a href="{{ pathto('index') }}">
+ <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ </a>
+ {%- else %}
+ {%- if logo -%}
+ <img class="rightlogo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
+ {%- endif -%}
+ <h1 class="heading"><a href="{{ pathto('index') }}">
+ <span>OpenColorIO</span></a></h1>
+ <h2 class="heading"><span>Open Source Color Management</span></h2>
+ {%- endif %}
+ {%- endblock %}
+ </div>
+ <div class="topnav">
+ {{ shorttitle|e }}
+ </div>
+ <div class="content">
+ {#{%- if display_toc %}
+ <div id="toc">
+ <h3>Table Of Contents</h3>
+ {{ toc }}
+ </div>
+ {%- endif %}#}
+ <table width="100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td width="200">
+ <div class="sidebar2">
+ {{toctree()}}
+ {%- include "searchbox.html" %}
+ </div>
+ </td>
+ <td width="100%" id="bodycontent">
+ {% block body %}{% endblock %}
+ </td>
+ </tr></table>
+ <br>
+ </div>
+ <div class="bottomnav">
+ {{ nav() }}
+ </div>
+{% endblock %}
diff --git a/docs/ociotheme/page.html b/docs/ociotheme/page.html
new file mode 100644
index 0000000..6442a17
--- /dev/null
+++ b/docs/ociotheme/page.html
@@ -0,0 +1,29 @@
+{#
+ basic/page.html
+ ~~~~~~~~~~~~~~~
+
+ Master template for simple pages.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{% extends "layout.html" %}
+{% block body %}
+{{ body }}
+ {% if pagename == "index" %}
+ <td width="275">
+ <div class="imageBar">
+ <p style="text-align: center; font-size: small;"><b>Color Transform Example</b></p>
+ <img src="{{ pathto('_static/clo_res19_vd16.0101.jpg', 1) }}">
+ <div class="caption">Final Image: sRGB</div>
+ <img src="{{ pathto('_static/clo_res19_lm10.0101.jpg', 1) }}">
+ <div class="caption">Digital Intermediate (DI): log dpx</div>
+ <img src="{{ pathto('_static/clo_res19_lnf.0101.jpg', 1) }}">
+ <div class="caption">Render: scene-linear exr</div>
+ <p style="text-align: right">Images from "Cloudy With A Chance of Meatballs"</p>
+ <p style="text-align: right">Copyright 2011 Sony Pictures Inc. All Rights Reserved.</p>
+ <p style="text-align: right">spi-animation profile, available here.</p>
+ </div>
+ </td>
+ {% endif %}
+{% endblock %}
diff --git a/docs/ociotheme/searchbox.html b/docs/ociotheme/searchbox.html
new file mode 100644
index 0000000..e631a35
--- /dev/null
+++ b/docs/ociotheme/searchbox.html
@@ -0,0 +1,12 @@
+
+<div id="searchbox" style="display: none">
+ <h3>{{ _('Quick search') }}</h3>
+ <form class="search" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="{{ _('Go') }}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+
diff --git a/docs/ociotheme/static/alert_info_32.png b/docs/ociotheme/static/alert_info_32.png
new file mode 100644
index 0000000..05b4fe8
--- /dev/null
+++ b/docs/ociotheme/static/alert_info_32.png
Binary files differ
diff --git a/docs/ociotheme/static/alert_warning_32.png b/docs/ociotheme/static/alert_warning_32.png
new file mode 100644
index 0000000..f13611c
--- /dev/null
+++ b/docs/ociotheme/static/alert_warning_32.png
Binary files differ
diff --git a/docs/ociotheme/static/bg-page.png b/docs/ociotheme/static/bg-page.png
new file mode 100644
index 0000000..c6f3bc4
--- /dev/null
+++ b/docs/ociotheme/static/bg-page.png
Binary files differ
diff --git a/docs/ociotheme/static/bullet_orange.png b/docs/ociotheme/static/bullet_orange.png
new file mode 100644
index 0000000..7171fd5
--- /dev/null
+++ b/docs/ociotheme/static/bullet_orange.png
Binary files differ
diff --git a/docs/ociotheme/static/clo_res19_lm10.0101.jpg b/docs/ociotheme/static/clo_res19_lm10.0101.jpg
new file mode 100644
index 0000000..121f814
--- /dev/null
+++ b/docs/ociotheme/static/clo_res19_lm10.0101.jpg
Binary files differ
diff --git a/docs/ociotheme/static/clo_res19_lnf.0101.jpg b/docs/ociotheme/static/clo_res19_lnf.0101.jpg
new file mode 100644
index 0000000..0d5f4c5
--- /dev/null
+++ b/docs/ociotheme/static/clo_res19_lnf.0101.jpg
Binary files differ
diff --git a/docs/ociotheme/static/clo_res19_vd16.0101.jpg b/docs/ociotheme/static/clo_res19_vd16.0101.jpg
new file mode 100644
index 0000000..1e8ec02
--- /dev/null
+++ b/docs/ociotheme/static/clo_res19_vd16.0101.jpg
Binary files differ
diff --git a/docs/ociotheme/static/ocio.css_t b/docs/ociotheme/static/ocio.css_t
new file mode 100644
index 0000000..f991bba
--- /dev/null
+++ b/docs/ociotheme/static/ocio.css_t
@@ -0,0 +1,469 @@
+/*
+ * haiku.css_t
+ * ~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- haiku theme.
+ *
+ * Adapted from http://haiku-os.org/docs/Haiku-doc.css.
+ * Original copyright message:
+ *
+ * Copyright 2008-2009, Haiku. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * Francois Revol <revol@free.fr>
+ * Stephan Assmus <superstippi@gmx.de>
+ * Braden Ewing <brewin@gmail.com>
+ * Humdinger <humdingerb@gmail.com>
+ *
+ * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@import url("basic.css");
+
+html {
+ margin: 0px;
+ padding: 0px;
+ background: #FFF url(bg-page.png) top left repeat-x;
+}
+
+body {
+ line-height: 1.5;
+ margin: auto;
+ padding: 0px;
+ font-family: "DejaVu Sans", Arial, Helvetica, sans-serif;
+ min-width: 59em;
+ color: {{ theme_textcolor }};
+}
+
+div.footer {
+ /* padding: 8px; */
+ font-size: 11px;
+ text-align: center;
+ letter-spacing: 0.5px;
+}
+
+/* Sidebar */
+
+/* link colors and text decoration */
+
+a:link {
+ font-weight: bold;
+ text-decoration: none;
+ color: {{ theme_linkcolor }};
+}
+
+a:visited {
+ font-weight: bold;
+ text-decoration: none;
+ color: {{ theme_visitedlinkcolor }};
+}
+
+a:hover, a:active {
+ text-decoration: underline;
+ color: {{ theme_hoverlinkcolor }};
+}
+
+/* Some headers act as anchors, don't give them a hover effect */
+
+h1 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+h2 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+h3 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+h4 a:hover, a:active {
+ text-decoration: none;
+ color: {{ theme_headingcolor }};
+}
+
+a.headerlink {
+ color: #a7ce38;
+ padding-left: 5px;
+}
+
+a.headerlink:hover {
+ color: #a7ce38;
+}
+
+/* basic text elements */
+
+div.content {
+ margin-top: 20px;
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-bottom: 50px;
+ font-size: 0.9em;
+}
+
+/* heading and navigation */
+
+div.header {
+ position: relative;
+ left: 0px;
+ top: 0px;
+ height: 85px;
+ /* background: #eeeeee; */
+ padding: 0 40px;
+}
+div.header h1 {
+ font-size: 1.6em;
+ font-weight: normal;
+ letter-spacing: 1px;
+ color: {{ theme_headingcolor }};
+ border: 0;
+ margin: 0;
+ padding-top: 15px;
+}
+div.header h1 a {
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+}
+div.header h2 {
+ font-size: 1.3em;
+ font-weight: normal;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+ color: #aaa;
+ border: 0;
+ margin-top: -3px;
+ padding: 0;
+}
+
+div.header img.rightlogo {
+ float: right;
+}
+
+
+div.title {
+ font-size: 1.3em;
+ font-weight: bold;
+ color: {{ theme_headingcolor }};
+ border-bottom: dotted thin #e0e0e0;
+ margin-bottom: 25px;
+}
+div.topnav {
+ background: #e0e0e0;
+ font-size: 0.8em;
+ text-align: right;
+}
+div.topnav p {
+ margin-top: 0;
+ margin-left: 40px;
+ margin-right: 40px;
+ margin-bottom: 0px;
+ text-align: right;
+ font-size: 0.8em;
+}
+div.bottomnav {
+ background: #eeeeee;
+}
+div.bottomnav p {
+ margin-right: 40px;
+ text-align: right;
+ font-size: 0.8em;
+}
+
+a.uplink {
+ font-weight: normal;
+}
+
+
+/* contents box */
+
+table.index {
+ /*margin: 0px 0px 30px 30px;*/
+ padding: 1px;
+ border-width: 1px;
+ border-style: dotted;
+ border-color: #e0e0e0;
+}
+table.index tr.heading {
+ background-color: #e0e0e0;
+ text-align: center;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+table.index tr.index {
+ background-color: #eeeeee;
+}
+table.index td {
+ padding: 5px 20px;
+}
+
+table.index a:link, table.index a:visited {
+ font-weight: normal;
+ text-decoration: none;
+ color: {{ theme_linkcolor }};
+}
+table.index a:hover, table.index a:active {
+ text-decoration: underline;
+ color: {{ theme_hoverlinkcolor }};
+}
+
+
+/* Haiku User Guide styles and layout */
+
+/* Rounded corner boxes */
+/* Common declarations */
+div.admonition {
+ -webkit-border-radius: 10px;
+ -khtml-border-radius: 10px;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+ border-style: dotted;
+ border-width: thin;
+ border-color: #dcdcdc;
+ padding: 10px 15px 10px 15px;
+ margin-bottom: 15px;
+ margin-top: 15px;
+}
+div.note {
+ padding: 10px 15px 10px 80px;
+ background: #e4ffde url(alert_info_32.png) 15px 15px no-repeat;
+ min-height: 42px;
+}
+div.warning {
+ padding: 10px 15px 10px 80px;
+ background: #fffbc6 url(alert_warning_32.png) 15px 15px no-repeat;
+ min-height: 42px;
+}
+div.seealso {
+ background: #e4ffde;
+}
+
+/* More layout and styles */
+h1 {
+ font-size: 1.3em;
+ font-weight: bold;
+ color: {{ theme_headingcolor }};
+ border-bottom: dotted thin #e0e0e0;
+ margin-top: 30px;
+}
+
+h2 {
+ font-size: 1.2em;
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+ border-bottom: dotted thin #e0e0e0;
+ margin-top: 30px;
+}
+
+h3 {
+ font-size: 1.1em;
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+ margin-top: 30px;
+}
+
+h4 {
+ font-size: 1.0em;
+ font-weight: normal;
+ color: {{ theme_headingcolor }};
+ margin-top: 30px;
+}
+
+p {
+ text-align: justify;
+}
+
+p.last {
+ margin-bottom: 0;
+}
+
+ol {
+ padding-left: 20px;
+}
+
+ul {
+ padding-left: 5px;
+ margin-top: 3px;
+}
+
+li {
+ line-height: 1.3;
+}
+
+div.content ul > li {
+ -moz-background-clip:border;
+ -moz-background-inline-policy:continuous;
+ -moz-background-origin:padding;
+ background: transparent url(bullet_orange.png) no-repeat scroll left 0.45em;
+ list-style-image: none;
+ list-style-type: none;
+ padding: 0 0 0 1.666em;
+ margin-bottom: 3px;
+ font-weight: normal;
+}
+
+td {
+ vertical-align: top;
+}
+
+tt {
+ background-color: #e2e2e2;
+ font-size: 1.0em;
+ font-family: monospace;
+}
+
+pre {
+ border-color: #0c3762;
+ border-style: dotted;
+ border-width: thin;
+ margin: 0 0 12px 0;
+ padding: 0.8em;
+ background-color: #f0f0f0;
+}
+
+hr {
+ border-top: 1px solid #ccc;
+ border-bottom: 0;
+ border-right: 0;
+ border-left: 0;
+ margin-bottom: 10px;
+ margin-top: 20px;
+}
+
+/* printer only pretty stuff */
+@media print {
+ .noprint {
+ display: none;
+ }
+ /* for acronyms we want their definitions inlined at print time */
+ acronym[title]:after {
+ font-size: small;
+ content: " (" attr(title) ")";
+ font-style: italic;
+ }
+ /* and not have mozilla dotted underline */
+ acronym {
+ border: none;
+ }
+ div.topnav, div.bottomnav, div.header, table.index {
+ display: none;
+ }
+ div.content {
+ margin: 0px;
+ padding: 0px;
+ }
+ html {
+ background: #FFF;
+ }
+}
+
+.viewcode-back {
+ font-family: "DejaVu Sans", Arial, Helvetica, sans-serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+ margin: -1px -12px;
+ padding: 0 12px;
+}
+
+div.imageBar {
+ font-size:x-small;
+ text-align: right;
+ padding: 10px;
+ margin-left: 15px;
+ margin-right: 10px;
+ margin-top: 10px;
+ border: 1px solid #000000;
+ background-color: #DDDDDD;
+}
+
+div.tocBar {
+
+ text-align: left;
+ padding: 10px;
+ margin-left: 15px;
+ margin-right: 10px;
+ margin-top: 10px;
+ border: 1px solid #000000;
+ background-color: #DDDDDD;
+}
+
+div.content div.tocBar ul > li.toctree-l1 {
+ width: 400;
+ font-family: Arial, sans-serif;
+ color: #0C3762;
+ font-size: 1.2em;
+ font-weight: normal;
+ margin: 0; /** reset the margins back to 0**/
+ padding: 2px 5px;
+ /**text-shadow: 1px 1px 0 white;**/
+ background: #ddd;
+ font-size: 1.1em;
+}
+
+p.caption {
+ font-size:x-small;
+ text-align: right;
+ background-color: #cdcdcd;
+}
+
+div.sidebar2 {
+ width: 200px;
+ font-size: 0.75em;
+ line-height: 1.5em;
+ margin: 10px;
+ /*
+ padding-left: 10px;
+ padding-right: 10px;
+ */
+}
+
+div.content div.sidebar2 ul > li.toctree-l1 {
+ font-family: Arial, sans-serif;
+ color: #0C3762;
+ font-size: 1.2em;
+ font-weight: normal;
+ margin: 0; /** reset the margins back to 0**/
+ padding: 2px 5px;
+ /**text-shadow: 1px 1px 0 white;**/
+ background: #ddd;
+ font-size: 1.1em;
+}
+
+div.content ul > li.toctree-l1 > ul {
+ margin: 0;
+}
+
+div.sidebar2 h3 a {
+ color: #444;
+}
+
+div.sidebar2 ul {
+ /** This is the selected sidebar text **/
+ margin: 5px 10px;
+ /**
+ padding: 5px;
+ **/
+ padding-left: 0px;
+ /**background-color: #cdcdcd;**/
+}
+
+div.sidebar2 li {
+ padding:3px;
+}
+
+div.sidebar2 a {
+ color: #444;
+}
+
+#bodycontent {
+ padding: 4px;
+}
diff --git a/docs/ociotheme/theme.conf b/docs/ociotheme/theme.conf
new file mode 100644
index 0000000..d8118b4
--- /dev/null
+++ b/docs/ociotheme/theme.conf
@@ -0,0 +1,13 @@
+[theme]
+inherit = basic
+stylesheet = ocio.css
+pygments_style = autumn
+
+[options]
+full_logo = false
+textcolor = #333333
+headingcolor = #0c3762
+linkcolor = #dc3c01
+visitedlinkcolor = #892601
+hoverlinkcolor = #ff4500
+rightsidebar = true
diff --git a/docs/userguide/baking_luts.rst b/docs/userguide/baking_luts.rst
new file mode 100644
index 0000000..7085bf5
--- /dev/null
+++ b/docs/userguide/baking_luts.rst
@@ -0,0 +1,359 @@
+.. _userguide-bakelut:
+
+Baking LUT's
+============
+
+Sometimes it is necessary to write a color transform as a
+lookup-table file
+
+This is usually because an application does not natively support OCIO
+(unlike, say, Nuke which various OCIO nodes), but can load a LUT of
+some kind. This would currently include applications like Autodesk
+Flame, Adobe Photoshop, SideFX's MPlay (Houdini's "Image Viewer")
+
+Remember that baking a LUT is not a perfect solution. Different LUT
+formats have various limitations. Certain applications might apply
+LUT's differently (often incorrectly), and some formats simply cannot
+accurately represent certain transforms. Others might require
+carefully selecting shaper spaces and so on.
+
+Be sure to carefully test the generated LUT in the target
+application. Burning the LUT into a test image (such as Marcie!), and
+carefully comparing to a reference is often the only way to be sure a
+LUT is correct.
+
+Config-based baking
+*******************
+
+This section assumes you have a working OCIO config.
+
+The config can either be specified by setting the OCIO environment variable::
+
+ bash$ export OCIO=~/path/to/spi-vfx/config.ocio
+
+Alternatively the config can be specified as a command-line argument
+to the ociobakelut command, ``--iconfig ~/path/to/spi-vfx/config.ocio``
+
+These examples will use the :ref:`config-spivfx` config, specifically the
+following colorspaces
+
+* ``lnf`` - scene-referred linear light colorspace (reference colorspace)
+* ``lg10`` - film log colorspace (0-1 colorspace)
+* ``srgb8`` - sRGB display colorspace
+
+Remember these are just for the examples - you can of course use any
+config and any colorspaces
+
+Log-input display LUT
++++++++++++++++++++++
+
+Say we have a ``lg10`` image in MPlay (maybe a ".cin" film scan), and
+wish to view it in our main display colorspace, ``srgb8``
+
+The available formats are listed in the ``ociobakelut --help`` - for
+MPlay, we use the "houdini" format (see :ref:`the FAQ<faq-supportedlut>`
+for a more detailed list)
+
+So, to create a LUT that transforms from ``lg10`` to ``srgb8``::
+
+ bash$ ociobakelut --format houdini --inputspace lg10 --outputspace srgb8 log_to_display.lut
+
+We could then load this LUT into MPlay and view a lg10 image
+correctly! (note that by MPlay tries to linearise ".cin" files by
+default, which can be disabled in the preferences, "Convert form 10bit
+Log")
+
+For most other applications, we could simply change the ``--format``
+
+Shaper spaces
++++++++++++++
+
+Before we create a LUT to view linear-light images, it's important to
+understand shaper-spaces and preluts.
+
+The two main types of LUT's are 1D and 3D. Such LUT formats typically
+require input values in the 0.0-1.0 range. Such a LUT would be
+unsuitable for linear-light values input images (where values are
+often over 1)
+
+To address this, various LUT formats contain a smaller "prelut" (or
+"shaper LUT") which is applied before the main LUT. This is used to
+transform the input values into a 0-1 range (typically a linear-to-log
+type transform)
+
+In terms of color-transforms, the prelut transforms from
+"input-space" to "shaper-space", then the main LUT transforms from
+"shaper-space" to "output-space"
+
+Some formats do not support such a shaper LUT - these are typically
+used in applications which do not work with floating-point images (e.g
+Lustre often works with 10-bit integer DPX's, so it's natively
+supported "--format lustre" (3DL) format has no need for a prelut)
+
+
+Linear-light input display LUT
+++++++++++++++++++++++++++++++
+
+With shaper-spaces explained, lets say we have a ``lnf`` linear light
+image in MPlay, and wish to view it in the ``srgb8`` colorspace.
+
+To create this LUT accurately, without clipping, we will use the LUT's
+prelut to transform from ``lnf`` to ``lg10``, then the 3D LUT will
+transform from ``lg10`` to ``srgb8``
+
+Sounds complicated, but the command is almost the same as before, just
+with the ``--shaperspace`` argument (and ``--inputspace`` changed, of
+course)::
+
+ bash$ ociobakelut --format houdini --inputspace lnf --shaperspace lg10 --outputspace srgb8 lin_to_display.lut
+
+Allocation-based prelut
++++++++++++++++++++++++
+
+If your :ref:`allocation variables<allocationvars>` are setup
+correctly, you can omit the ``--shaperspace`` argument, and a prelut
+will be automatically created based on the allocation vars (see the
+linked page for more information)
+
+Since the colorspaces in the config we are using (:ref:`config-spivfx`) have
+their allocation variables set correctly, we could simplify the
+``lnf`` to ``srgb8`` bake command::
+
+ bash$ ociobakelut --format houdini --inputspace lnf --outputspace srgb8 lin_to_display_allocbased.lut
+
+This command creates a very different prelut to the explicitly
+specified ``--shaperspace lg10`` in the previous example. Explicitly
+specifying a shaper can produce better results, however the
+allocation-based prelut usually works nicely, and is convinient
+
+Note that allocation-var based preluts is baker-format dependant, and
+not all formats currently implement them
+
+
+Config-free baking
+******************
+
+You can perform baking without using a OCIO config. This means you
+don't have to create a temporary config just to, say, convert from one
+LUT format to another.
+
+Converting between formats
+++++++++++++++++++++++++++
+
+Say we have a houdini LUT named ``log_to_display.lut``. To convert
+this to a Flame compatible 3dl file, simply run::
+
+ ociobakelut --format flame --lut log_to_display.lut for_flame.3dl
+
+
+Reversing a 1D LUT
+++++++++++++++++++
+
+You can apply a LUT in reverse, and write this to a new LUT (this does
+not work for 3D LUT's, but will for 1D LUT's)::
+
+ bash$ ociobakelut --format flame --invlut logtosrgb.3dl srgbtolog.3dl
+
+Creating a grade LUT
+++++++++++++++++++++
+
+You can create a LUT which applies CDL-compliant grades::
+
+ ociobakelut --format cinespace --slope 1.2 1.0 0.9 mygrade.csp
+
+Combining options
++++++++++++++++++
+
+These options can be used together, or used multiple times.
+
+For example, to perform a slope offset, then apply "mylut.csp", saving
+it out for Lustre::
+
+ bash$ ociobakelut --format lustre --slope 2.0 1.5 0.4 --lut mylut.csp output.3dl
+
+
+ICC profiles (Photoshop)
+************************
+
+Photoshop is very focused around print and graphic-design, industries
+with very different color management concerns to modern feature-film
+VFX. As such, it can be a pain to integrate.
+
+The main issue is current versions of Photoshop (CS5) are only
+practical for working with 16-bit integer images (not floating
+point/linear-light images as is common in compositing software)
+
+The second issue is there is no simple way to load a simple 1D or 3D
+LUT into Photoshop (and it's API does not make this easy either!)
+
+A working space
++++++++++++++++
+
+First, we need to decide on a colorspace to use for the images in
+Photoshop. This is the colorspace in which matte-paintings will be
+performed (likely a different colorspace that used for
+texture-painting, as these have different requirements)
+
+The working space should be a "0-1 colorspace", reversable, and for
+matte-paintings ideally allow painting values over "diffuse white" (in
+other words, to paint values over 1.0 when converted to linear-light
+in comp)
+
+This is a facility-dependant workflow choice.
+
+For this example we will use the ``vd16`` colorspace, as described by
+the :ref:`config-spivfx`
+
+Creating display LUT
+++++++++++++++++++++
+
+"Proofing profiles" in Photoshop can be used in a very similar way to
+a display LUT in applications like Nuke. This proof-profile can be
+used to apply a 3D color transform from the working-space to a
+display space (e.g transform from ``vd16`` to ``srgb8`` in the spi-vfx
+config)
+
+These proofing-profiles are ICC profiles - a rather print-specific
+technology and relatively complex format
+
+Luckily, ``ociobakelut`` can be used to create these... but, first,
+there are some important considerations:
+
+It is important to match the ``--displayicc`` option to the profile
+used for the display.
+
+Secondly, Photoshop has a lot of print-focused color-management
+options, some of which can cause problems.
+
+Determine display ICC
++++++++++++++++++++++
+
+On OS X, launch "System Preferences", open "Displays" and click
+"Color" tab. The currently active ICC profile is selected.
+
+If you just want something simple that "probably matches" a Linux
+machine, say, it is easiest to uncheck "Show profiles for this display
+only" and select the "sRGB IEC61966-2.1" profile. You can skip the
+rest of this section in this case.
+
+.. figure:: images/ps_icc/psicc_open_current_profile.png
+ :align: center
+
+However, if you have a specific display-profile selected (maybe
+created by monitor-calibration software), you should do the following:
+
+Click "Open Profile", and right-click the icon in the top of the window, and click the folder:
+
+.. figure:: images/ps_icc/psicc_reveal_profile.png
+ :align: center
+
+This reveals the current profile in Finder. You can drag the file onto
+a Terminal.app window to get the full path (or, type it manually)
+
+.. TODO: Is there a standard way to find this on Windows?
+
+Create the ICC profile
+++++++++++++++++++++++
+
+Almost done now. We can write the ICC profile!
+
+The full command is, using our example colorspaces of ``vd16`` and ``srgb8``::
+
+ bash$ ociobakelut --format icc --inputspace vd16 --outputspace srgb8 --displayicc /path/to/my/monitorprofile.icc --description "vd16 to srgb8"
+
+
+The first three options are the same as any other LUT::
+
+ bash$ ociobakelut --format icc --inputspace vd16 --outputspace srgb8 [...]
+
+Then we specify the display ICC profile::
+
+ [...] --displayicc /path/to/my/monitorprofile.icc [...]
+
+We can set the description (shown in Photoshop), and as the last argument, specify::
+
+ [...] --description "vd16 to srgb8" [...]
+
+Finally an argument for the output file:
+
+ [...] vd16_to_srgb.icc
+
+
+If you selected the "sRGB IEC61966-2.1" display profile, you can omit
+the ``--displayicc`` argument (it defaults to an standard sRGB
+profile)::
+
+ bash$ ociobakelut --format icc --inputspace vd16 --outputspace srgb8 --description "vd16 to srgb8"
+
+Loading the "display LUT"
++++++++++++++++++++++++++
+
+Last step is to load the ICC profile into Photoshop, and enable it.
+
+On OS X, these can be put into::
+
+ /Library/ColorSync/Profiles/
+
+(or the equivelant directory in your home-directory)
+
+On Windows, right-click the profile and select "Install profile"
+
+
+Then on either platform, click "View > Proof Setup > Custom..."
+
+.. figure:: images/ps_icc/psicc_proof_setup.png
+ :align: center
+
+Select your profile from the "Device to simulate" dropdown (the name
+is what you supplied with ``--description``):
+
+.. figure:: images/ps_icc/psicc_select_profile.png
+ :align: center
+
+As pictured, selecting "Preserve RGB numbers", and deselecting
+"Simulate Black Ink" is a good starting point (see the next section on
+"Other color settings")
+
+Finally, you can load an image in your working space, and click "View
+> Proof Colors", or hit cmd+y (or ctrl+y)
+
+When active, the profile name is shown in the window title (e.g
+".... (RGB/16#/vd16 to srgb8", where the part after the "#/" is the
+profile name, "RGB/16" indicates the current image mode)
+
+Other color settings
++++++++++++++++++++++
+
+(note this guide is based on Photoshop CS5, and written while checking
+the OS X version, although most of these apply similarly on Windows 7)
+
+It is usually possible to get a matte-painting to look identical in
+Photoshop as it does in a more VFX-friendly application such as Nuke.
+
+However, as mentioned Photoshop has a lot of color-management related
+options, many of which can impair the match between it and other
+applications. The operating system also has some controls (as seen
+before with the ColorSync display profile)
+
+The settings that require tweaking have a tendency to change with OS
+versions, Photoshop versions and the phase of the moon. The only way
+to be sure is to compare Photoshop side-by-side with a
+LUT-reference-image (ideally toggling between Photoshop and Nuke):
+
+.. figure:: images/ps_icc/psicc_itworks.png
+ :align: center
+
+
+The most improtant settings are in the "View > Proof Setup > Custom
+..." menu.
+
+The recommended "Preserve RGB" setting works sometimes. Other times
+disabling "Preserve RGB Numbers" and selecting "Rendering Intent:
+Relative Colorimetric" can be closer.
+
+It is safest to not assign a profile to the images you are working
+on - this is done by clicking "Edit > Assign Profile", and selecting
+"Don't Color Manage This Document".
+
+In closing, of course none of this matters if you don't have a
+calibrated monitor!
diff --git a/docs/userguide/contexts.rst b/docs/userguide/contexts.rst
new file mode 100644
index 0000000..262f158
--- /dev/null
+++ b/docs/userguide/contexts.rst
@@ -0,0 +1,361 @@
+Contexts
+========
+
+OCIO's allows different LUT's or grades to be applied based on the
+current context.
+
+These contexts are usually based on environment variables, but also
+allows on-the-fly context switching in applications that operate on
+multiple shots (such as playback tools)
+
+Typically these would be used as part of the display transform, to
+apply shot-specific looks (such as a CDL color correction, or a 1D
+grade LUT)
+
+
+.. _context_per_shot_luts:
+
+A contrived example
+*******************
+
+The simplest way to explain this feature is with examples. Say we have
+two shots, ``ab-123`` and ``sf-432``, and each shot requires a
+different LUT to view. The current shot name is stored in the
+environment variable SHOT.
+
+In the OCIO config, you can use this SHOT environment variable to
+construct the LUT's path/filename. This path can be absolute (e.g
+``/example/path/${SHOT}.spi1d``), or relative to any directory on the
+OCIO search path, which includes the resource path (e.g
+``${SHOT}.spi1d``)
+
+This is a simplified example, to demonstrate the context
+feature. Typically this "contextual LUT" would be used in conjuction
+with other LUT's (e.g before a scene-linear to log transform, followed
+by a 3D film emulation LUT), this will be covered in
+:ref:`context_per_shot_grade`
+
+So, we have our empty OCIO config in ``~/showcfg``, and our two LUTs
+in ``~/showcfg/luts`` which are named ``af-123.spi1d`` and
+``sf-432.spi1d``::
+
+ ~/showcfg/
+ config.ocio
+ luts/
+ af-123.spi1d
+ sf-432.spi1d
+
+In the config, we first specify the config version, and the resource
+path (usually this is relative to the directory containing
+``config.ocio``, although can be an absolute path)::
+
+ ocio_profile_version: 1
+ resource_path: luts
+
+Next, we define a colorspace that transforms from the show reference
+space to the display colorspace:
+
+.. code-block:: yaml
+
+ colorspaces:
+ - !<ColorSpace>
+ name: srgb8
+ family: srgb
+ bitdepth: 8ui
+ from_reference: !<FileTransform> {src: ${SHOT}.spi1d}
+
+Then add a display alias for this transform:
+
+.. code-block:: yaml
+
+ displays:
+ - !<Display> {device: sRGB, name: "Shot LUT", colorspace: srgb8}
+
+
+Finally, we point the OCIO env-variable to the config, set the SHOT
+env-variable to the shot being worked on, and launch Nuke (or any
+other OCIO-enabled application)::
+
+ export OCIO=~/showcfg/config.ocio
+ export SHOT=af-123
+ nuke
+
+In Nuke, we create an OCIODisplay node, select our "sRGB" device with
+the "Shot LUT" transform, and this will apply the ``af-123.spi1d``
+LUT.
+
+.. _context_per_shot_grade:
+
+Per-shot grades
+***************
+
+Similarly to LUTs, we use a ``.cc`` file (an XML file containing a
+single ASC CDL ``<ColorCorrection>``), or a ``.ccc`` file (an XML file
+containing multiple ASC CDL color corrections, each with a unique ID)
+
+The ``.cc`` file is applied identically to a regular LUT files, using
+a ``FileTransform``. For example, if we have ``af-123.cc`` in the
+``luts/`` directory:
+
+.. code-block:: xml
+
+ <ColorCorrection id="mygrade">
+ <SOPNode>
+ <Slope>2 1 1</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1 1 1</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>1</Saturation>
+ </SATNode>
+ </ColorCorrection>
+
+
+We wish to apply this grade on the scene-linear image, then transform
+into log and apply a 3D print emulation LUT. Since this requires
+multiple transforms, instead of using a single ``FileTransform``, we
+use a ``GroupTransform`` (which is is just a collection of other
+transforms):
+
+.. code-block:: yaml
+
+ colorspaces:
+ - !<ColorSpace>
+ name: lnh
+ family: ln
+ bitdepth: 16f:
+ isdata: false
+
+ - !<ColorSpace>
+ name: lg10
+ family: lg
+ bitdepth: 10ui
+ isdata: false
+ to_reference: !<FileTransform> {src: lg10.spi1d, interpolation: nearest}
+
+ - !<ColorSpace>
+ name: srgb8
+ family: srgb
+ bitdepth: 8ui
+ isdata: false
+ from_reference: !<GroupTransform>
+ children:
+ - !<FileTransform> {src: ${SHOT}.cc}
+ - !<ColorSpaceTransform> {src: lnh, dst: lg10}
+ - !<FileTransform> {src: film_emulation.spi3d, interpolation: linear}
+
+A .ccc file is a collection of ``<ColorCorrection>``'s. The only
+difference is when defining the ``FileTransform``, you must specify
+the ``cccdid`` key, which you can also construct using the context's
+environment variables. This means we could create a ``grades.ccc``
+file containing the grade for all our shots:
+
+.. code-block:: xml
+
+ <ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
+ <ColorCorrection id="af-123">
+ <SOPNode>
+ <Slope>2 1 1</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1 1 1</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>1</Saturation>
+ </SATNode>
+ </ColorCorrection>
+ <ColorCorrection id="mygrade">
+ <SOPNode>
+ <Slope>0.9 0.7 0.9</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1 1 1</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>1</Saturation>
+ </SATNode>
+ </ColorCorrection>
+ </ColorCorrectionCollection>
+
+And the colorspace definition to utilise this:
+
+.. code-block:: yaml
+
+ - !<ColorSpace>
+ name: srgb8
+ family: srgb
+ bitdepth: 8ui
+ isdata: false
+ from_reference: !<GroupTransform>
+ children:
+ - !<FileTransform> {src: grades.ccc, cccid: ${SHOT}}
+ - !<ColorSpaceTransform> {src: lnh, dst: lg10}
+ - !<FileTransform> {src: film_emulation.spi3d, interpolation: linear}
+
+
+.. _context_complete_example:
+
+A complete example
+******************
+
+.. warning::
+ This is incomplete, the lnh_graded space is likely wrong
+
+The context feature can be used to accommodate complex grading
+pipelines. In this example, we have a "neutral grade" for each shot,
+to neutralise color casts and exposure variations, keeping plates
+consistent throughout a sequence.
+
+To view a shot, we reverse this neutral grade, apply a "beauty grade",
+then apply the display transform (the usual lin-to-log and a film
+emulation LUT)
+
+We will use the same two example shots from before, af-123 (which is
+in the af sequence) and sg-432 (in the sg sequence). Imagine we have
+many shots in each sequence, so we wish to put the grades for each
+sequence in a separate file.
+
+Using the same directory structure as above, in ``~/showcfg/luts`` we
+first create two grade files, ``grades_af.ccc``:
+
+.. code-block:: xml
+
+ <ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
+ <ColorCorrection id="af/af-123/neutral">
+ <SOPNode>
+ <Slope>2 1 1</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1 1 1</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>1</Saturation>
+ </SATNode>
+ </ColorCorrection>
+
+ <ColorCorrection id="af/af-123/beauty">
+ <SOPNode>
+ <Slope>1.5 1.2 0.9</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1 1 1</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>0.8</Saturation>
+ </SATNode>
+ </ColorCorrection>
+
+ <!-- More ColorCorrection's... -->
+ </ColorCorrectionCollection>
+
+
+And ``grades_sg.ccc``:
+
+.. code-block:: xml
+
+ <ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
+ <ColorCorrection id="sg/sg-432/neutral">
+ <SOPNode>
+ <Slope>0.9 0.7 0.9</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1 1 1</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>1</Saturation>
+ </SATNode>
+ </ColorCorrection>
+
+ <ColorCorrection id="sg/sg-432/beauty">
+ <SOPNode>
+ <Slope>1.1 0.9 0.8</Slope>
+ <Offset>0 0 0</Offset>
+ <Power>1.2 0.9 1.5</Power>
+ </SOPNode>
+ <SATNode>
+ <Saturation>1</Saturation>
+ </SATNode>
+ </ColorCorrection>
+
+ <!-- More ColorCorrection's.. -->
+ </ColorCorrectionCollection>
+
+
+Next, we create the ``config.ocio`` file, containing a colorspace to
+define several colorspaces:
+
+* ``lnh``, the scene-linear, 16-bit half-float space in which
+ compositing will happen
+
+* ``lg10``, the 10-bit log space in which material will be received
+ (e.g in .dpx format)
+
+* ``srgb8``, the display colorspace, for viewing the neutrally graded
+ footage on an sRGB display
+
+* ``srgb8graded``, another display colorspace, for viewing the final
+ "beauty grade"
+
+
+.. code-block:: yaml
+
+ ocio_profile_version: 1
+
+ # The directory relative to the location of this config
+ resource_path: "luts"
+
+ roles:
+ scene_linear: lnh
+ compositing_log: lgf
+
+ displays:
+ # Reference to display transform, without reversing the working grade
+ - !<Display> {device: sRGB, name: Film1D, colorspace: srgb8}
+
+ # Reference to display, reversing the working grade, and applying
+ # the beauty grade
+ - !<Display> {device: sRGB, name: Film1DGraded, colorspace: srgb8graded}
+
+ colorspaces:
+
+ # The source space, containing a log to scene-linear LUT
+ - !<ColorSpace>
+ name: lg10
+ family: lg
+ bitdepth: 10ui
+ isdata: false
+ to_reference: !<FileTransform> {src: lg10.spi1d, interpolation: nearest}
+
+ # Our scene-linear space (reference space)
+ - !<ColorSpace>
+ name: lnh
+ family: ln
+ bitdepth: 16f
+ isdata: false
+
+ # Neutrally graded scene-linear
+ - !<ColorSpace>
+ name: lnh_graded
+ family: ln
+ bitdepth: 16f
+ isdata: false
+ to_reference: !<FileTransform> {src: "grades_${SEQ}.ccc", cccid: "${SEQ}/${SHOT}/neutral"}
+
+
+ # The display colorspace - how to get from scene-linear to sRGB
+ - !<ColorSpace>
+ name: srgb8
+ family: srgb
+ bitdepth: 8ui
+ isdata: false
+ from_reference: !<GroupTransform>
+ children:
+ - !<ColorSpaceTransform> {src: lnh, dst: lg10}
+ - !<FileTransform> {src: lg_to_srgb.spi3d, interpolation: linear}
+
+ # Display color, with neutral grade reversed, and beauty grade applied
+ - !<ColorSpace>
+ name: srgb8graded
+ family: srgb
+ bitdepth: 8ui
+ isdata: false
+ from_reference: !<GroupTransform>
+ children:
+ - !<FileTransform> {src: "grades_${SEQ}.ccc", cccid: "${SEQ}/${SHOT}/neutral", direction: inverse}
+ - !<FileTransform> {src: "grades_${SEQ}.ccc", cccid: "${SEQ}/${SHOT}/beauty", direction: forward}
+ - !<ColorSpaceTransform> {src: lnh, dst: srgb8}
diff --git a/docs/userguide/images/ps_icc/psicc_itworks.png b/docs/userguide/images/ps_icc/psicc_itworks.png
new file mode 100644
index 0000000..242db00
--- /dev/null
+++ b/docs/userguide/images/ps_icc/psicc_itworks.png
Binary files differ
diff --git a/docs/userguide/images/ps_icc/psicc_open_current_profile.png b/docs/userguide/images/ps_icc/psicc_open_current_profile.png
new file mode 100644
index 0000000..1654ae6
--- /dev/null
+++ b/docs/userguide/images/ps_icc/psicc_open_current_profile.png
Binary files differ
diff --git a/docs/userguide/images/ps_icc/psicc_proof_setup.png b/docs/userguide/images/ps_icc/psicc_proof_setup.png
new file mode 100644
index 0000000..179eb8e
--- /dev/null
+++ b/docs/userguide/images/ps_icc/psicc_proof_setup.png
Binary files differ
diff --git a/docs/userguide/images/ps_icc/psicc_reveal_profile.png b/docs/userguide/images/ps_icc/psicc_reveal_profile.png
new file mode 100644
index 0000000..07ad56c
--- /dev/null
+++ b/docs/userguide/images/ps_icc/psicc_reveal_profile.png
Binary files differ
diff --git a/docs/userguide/images/ps_icc/psicc_select_profile.png b/docs/userguide/images/ps_icc/psicc_select_profile.png
new file mode 100644
index 0000000..06fecef
--- /dev/null
+++ b/docs/userguide/images/ps_icc/psicc_select_profile.png
Binary files differ
diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst
new file mode 100644
index 0000000..256d89d
--- /dev/null
+++ b/docs/userguide/index.rst
@@ -0,0 +1,15 @@
+.. _user-guide:
+
+User Guide
+==========
+
+These guides will focus on a specific task (for example, writing a basic config, or setting up per-shot LUT's).
+For a "broader picture" expiation of how to use OCIO, see the :ref:`configurations` section
+
+.. toctree::
+ :maxdepth: 2
+
+ tool_overview
+ baking_luts
+ contexts
+ looks
diff --git a/docs/userguide/looks.rst b/docs/userguide/looks.rst
new file mode 100644
index 0000000..591d835
--- /dev/null
+++ b/docs/userguide/looks.rst
@@ -0,0 +1,139 @@
+Looks
+=====
+
+A "look" is a named color transform, intended to modify the look of an
+image in a "creative" manner (as opposed to a colorspace definion
+which tends to be technically/mathematically defined)
+
+Examples of looks may be a neutral grade, to be applied to film scans
+prior to VFX work, or a per-shot DI grade decided on by the director,
+to be applied just before the viewing transform
+
+Looks are defined similarly to colorspaces, you specify a name and a
+transform (possibly a GroupTransform containing several other
+transforms), and optionally an inverse transform.
+
+Where looks differ from colorspace definions are in how they are
+applied. With a look, you also specify the "process space" - the
+colorspace in which the transform is applied.
+
+Example configuration
+*********************
+
+Step 1: Setup a Look
+
+A look is a top-level OCIO configuration object. Conceptually, it's a
+named transform which gets applied in a specific color space. All of the
+changes below to the .ocio configs can be done manually by editing the
+text, or using the Python API.
+
+Example look definition in a OCIO config:
+
+.. code-block:: yaml
+
+ looks:
+ - !<Look>
+ name: di
+ process_space: rclg16
+ transform: !<FileTransform> {src: look_di.cc, interpolation: linear}
+
+
+The src file can be any LUT type that OCIO supports (in this case, it's a
+file that contains the ``<ColorCorrection>`` element from a CDL file.) You
+could also specify a .3dl, etc.
+
+Once you define a look in your configuration, you'll see that the
+``OCIOLookTransform`` node in Nuke will provide the named option. In
+this example, the 'DI' look conceptually represents a look that will
+be applied in DI. Other look names we often used are 'onset',
+'editorial', etc. The ``process_space`` specifies that the transform
+should be applied in that space. In this example, if you provide
+linear input to the ``OCIOLookTransform`` node, the pixels will be
+converted to ``rclg16`` before applying the ``look_di.cc``
+file-transform.
+
+Step 2: Update the Display to use a look.
+
+You can specify an optional 'looks' tag in the View tag, which will
+apply the specified look(s). This lets application in the viewer
+provide options which use the looks.
+
+Example:
+
+.. code-block:: yaml
+
+ displays:
+ DLP:
+ - !<View> {name: Raw, colorspace: nc10}
+ - !<View> {name: Log, colorspace: rclg10}
+ - !<View> {name: Film, colorspace: p3dci16}
+ - !<View> {name: Film DI, colorspace: p3dci16, looks: di}
+ sRGB:
+ - !<View> {name: Raw, colorspace: nc10}
+ - !<View> {name: Log, colorspace: rclg10}
+ - !<View> {name: Film, colorspace: srgb10}
+ - !<View> {name: Film DI, colorspace: srgb10, looks: di}
+
+
+Option for advanced users: The looks tag is actually a comma-delimited
+list supporting +/- modifiers. So if you you wanted to specify a View
+that undoes DI, and then adds Onset, you could do "-di,+onset".
+
+Step 3: Get per-shot looks supported.
+
+In the top example, look_di.cc, being a relative path location, will check
+each location in the config's search_path. The first file that's found
+will be used.
+
+So if your config contains::
+
+ search_path: luts
+
+... then only the 'luts' subdir relative to the OCIO config will be
+checked.
+
+However if you specify::
+
+ search_path: /shots/show/$SHOT/cc/data:luts
+
+...the directory '/shots/show/$SHOT/cc/data/' will be evaluated first,
+and only if not found will the 'luts' directory be checked.
+
+env-vars, absolute, and relative paths can be used both in the config's
+``search_path``, as well as the View's src specification.
+
+Example:
+
+.. code-block:: yaml
+
+ - !<Look>
+ name: di
+ process_space: rclg16
+ transform: !<FileTransform> {src: looks/$SHOT_di/current/look_$SHOT_di.cc, interpolation: linear}
+
+
+Note that if the per-shot lut is not found, you can control whether a
+fallback LUT succeeds based on if it's in the master location. You can
+also use this for multiple levels (show, shot, etc).
+
+Advanced option: If some shots use .cc files, and some use 3d-luts
+currently there's no simple way to handle this. What we'd recommend as a
+work around is to label all of your files with the same extension (such as
+.cc), and then rely on OCIO's resiliance to misnamed lut files to just load
+them anyways. Caveat: this only works in 1.0.1+ (commit sha-1: 6da3411ced)
+
+Advanced option: In the Nuke OCIO nodes, you often want to preview
+looks 'across shots' (often for reference, same-as, etc). You can
+override the env-vars in each node, using the 'Context' menu. For
+example, if you know that $SHOT is being used, in the context key1 you
+should specify 'SHOT', and the in value1 specify the shot to use (such
+as dev.lookdev). You can also use expressions, to say parse a shot
+name out of ``[metadata "input/filename"]``
+
+Advanced option: If you are writing your own OCIO integration code,
+``getProcessor`` will fail if the per-shot lut is not found, and you
+may want to distinguish this error from other OCIO errors. For this
+reason, we provide OCIO::ExceptionMissingFile, which can be explicitly
+caught (this can then handled using
+``OCIO::DisplayTransform::setLooksOverride()``). I'd expect image
+flipbook applications to use this approach.
diff --git a/docs/userguide/tool_overview.rst b/docs/userguide/tool_overview.rst
new file mode 100644
index 0000000..f9ac0e4
--- /dev/null
+++ b/docs/userguide/tool_overview.rst
@@ -0,0 +1,168 @@
+.. _userguide-tooloverview:
+
+Tool overview
+=============
+
+OCIO is comprised of many parts. At the lowest level there is the C++ API.
+This API can be used in applications and plugins
+
+Note that all these plugins use the same config file to define color spaces,
+roles and so on. For information on setting up configurations, see
+:ref:`configurations`
+
+The API
+*******
+
+Most users will never directly interact with the C++ API. However the API is used by all the supplied applications (e.g :ref:`overview-ocio2icc`) and plugins (e.g
+the :ref:`overview-nukeplugins`)
+
+To get started with the API, see the :ref:`developer-guide`
+
+.. _overview-ociocheck:
+
+ociocheck
+*********
+
+This is a command line tool which shows an overview of an OCIO config
+file, and check for obvious errors
+
+For example, the following shows the output of a config with a typo -
+the colorspace used for ``compositing_log`` is not incorrect::
+
+ $ ociocheck --iconfig example.ocio
+
+ OpenColorIO Library Version: 0.8.3
+ OpenColorIO Library VersionHex: 525056
+ Loading example.ocio
+
+ ** General **
+ Search Path: luts
+ Working Dir: /tmp
+
+ Default Display: sRGB
+ Default View: Film
+
+ ** Roles **
+ ncf (default)
+ lnf (scene_linear)
+ NOT DEFINED (compositing_log)
+
+ ** ColorSpaces **
+ lnf
+ lgf
+ ncf
+ srgb8 -- output only
+
+ ERROR: Config failed sanitycheck. The role 'compositing_log' refers to a colorspace, 'lgff', which is not defined.
+
+ Tests complete.
+
+It cannot verify the defined color transforms are "correct", only that the
+config file can be loaded by OCIO without error.
+
+As with all the OCIO command line tools, you can use the `--help` argument to
+read a description and see the other arguments accepted::
+
+ $ ociocheck --help
+ ociocheck -- validate an OpenColorIO configuration
+
+ usage: ociocheck [options]
+
+ --help Print help message
+ --iconfig %s Input .ocio configuration file (default: $OCIO)
+ --oconfig %s Output .ocio file
+
+
+.. _overview-ociobakelut:
+
+ociobakelut
+************
+
+A command line tool which bakes a color transform into various color
+lookup file formats ("a LUT")
+
+This is intended for applications that have not directly integrated
+OCIO, but can load LUT files
+
+If we want to create a ``lnf`` to ``srgb8`` viewer LUT for Houdini's
+MPlay::
+
+ $ ociobakelut --inputspace scene_linear --shaperspace lg10 --outputspace srgb8 --format houdini houdini__lnf_to_lg10_to_srgb8.lut
+
+The ``--inputspace`` and ``-outputspace`` options specify the
+colorspace of the input image, and the displayed image.
+
+Since a 3D LUT can only practically operate on 0-1 (e.g a Log image),
+the ``--shaperspace`` option is specified. This uses the Houdini LUT's
+1D "pretransform" LUT to do "lnf" to "lg10", then the 3D LUT part to
+go from "lg10" to "srgb8" (basically creating a single file containing
+a 1D linear-to-log LUT, and a 3D log-to-sRGB LUT)
+
+To make a log to sRGB LUT for Flame, the usage is similar, except the
+shaperspace option is omitted, as the input colorspace does not have
+values outside 0.0-1.0 (being a Log space)::
+
+ $ ociobakelut --inputspace lg10 --outputspace srgb8 --format flame flame__lg10_to_srgb.3dl
+
+See the :ref:`faq-supportedlut` section for a list of formats that
+support baking
+
+.. TODO: For more information on baking LUT's, see :ref:`userguide-bakelut`
+
+
+.. _overview-ocio2icc:
+
+ocio2icc
+********
+
+A command line tool to generate an ICC "proofing" profile from a color space
+transform, which can be used in applications such as Photoshop.
+
+A common workflow is for matte-painters to work on sRGB files in Photoshop. An
+ICC profile is used to view the work with the same film emulation transform as
+used in other departments.
+
+.. TODO: Link to more elaborate description
+
+
+.. _overview-ocioconvert:
+
+ocioconvert
+***********
+
+Loads an image, applies a color transform, and saves it to a new file.
+
+OpenImageIO is used to open and save the file, so a wide range of formats are supported.
+
+.. TODO: Link to more elaborate description
+
+
+.. _overview-ociodisplay:
+
+ociodisplay
+***********
+
+A basic image viewer. Uses OpenImageIO to load images, and displays them using OCIO and typical viewer controls (scene-linear exposure control and a post-display gamma control)
+
+May be useful to users to quickly check colorspace configuration, but
+primarily a demonstration of the OCIO API
+
+.. TODO: Link to more elaborate description
+
+
+.. _overview-nukeplugins:
+
+Nuke plugins
+************
+
+A set of OCIO nodes for The Foundry's Nuke, including:
+
+* OCIOColorSpace, transforms between two color spaces (similar to the built-in "ColorSpace" node, but the colorspaces are described in the OCIO config file)
+
+* OCIODisplay to be used as viewer processes
+
+* OCIOFileTransform loads a transform from a file (e.g a 1D or 3D LUT), and applies it
+
+* OCIOCDLTransform applies CDL-compliant grades, and includes utilities to create/load ASC CDL files
+
+.. TODO - Link to more elaborate description
diff --git a/export/OpenColorIO/OpenColorABI.h.in b/export/OpenColorIO/OpenColorABI.h.in
new file mode 100644
index 0000000..d39d586
--- /dev/null
+++ b/export/OpenColorIO/OpenColorABI.h.in
@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_OPENCOLORABI_H
+#define INCLUDED_OCIO_OPENCOLORABI_H
+
+// Makefile configuration options
+#define OCIO_NAMESPACE @OCIO_NAMESPACE@
+#define OCIO_USE_BOOST_PTR @OCIO_USE_BOOST_PTR@
+#define OCIO_VERSION "@OCIO_VERSION@"
+#define OCIO_VERSION_NS v@SOVERSION@
+
+/* Version as a single 4-byte hex number, e.g. 0x01050200 == 1.5.2
+ Use this for numeric comparisons, e.g. #if OCIO_VERSION_HEX >= ...
+ Note: in the case where SOVERSION is overridden at compile-time,
+ this will reflect the original API version number.
+ */
+#define OCIO_VERSION_HEX ((@OCIO_VERSION_MAJOR@ << 24) | \
+ (@OCIO_VERSION_MINOR@ << 16) | \
+ (@OCIO_VERSION_PATCH@ << 8))
+
+
+// Namespace / version mojo
+#define OCIO_NAMESPACE_ENTER namespace OCIO_NAMESPACE { namespace OCIO_VERSION_NS
+#define OCIO_NAMESPACE_EXIT using namespace OCIO_VERSION_NS; }
+#define OCIO_NAMESPACE_USING using namespace OCIO_NAMESPACE;
+
+// shared_ptr / dynamic_pointer_cast
+#if OCIO_USE_BOOST_PTR
+#include <boost/shared_ptr.hpp>
+#define OCIO_SHARED_PTR boost::shared_ptr
+#define OCIO_DYNAMIC_POINTER_CAST boost::dynamic_pointer_cast
+#elif __GNUC__ >= 4
+#include <tr1/memory>
+#define OCIO_SHARED_PTR std::tr1::shared_ptr
+#define OCIO_DYNAMIC_POINTER_CAST std::tr1::dynamic_pointer_cast
+#else
+#error OCIO needs gcc 4 or later to get access to <tr1/memory> (or specify USE_BOOST_PTR instead)
+#endif
+
+// If supported, define OCIOEXPORT, OCIOHIDDEN
+// (used to choose which symbols to export from OpenColorIO)
+#if defined __linux__ || __APPLE__
+ #if __GNUC__ >= 4
+ #define OCIOEXPORT __attribute__ ((visibility("default")))
+ #define OCIOHIDDEN __attribute__ ((visibility("hidden")))
+ #else
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+ #endif
+#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+ // Windows requires you to export from the main library and then import in any others
+ #if defined OpenColorIO_EXPORTS
+ #define OCIOEXPORT __declspec(dllexport)
+ #else
+ #define OCIOEXPORT __declspec(dllimport)
+ #endif
+ #define OCIOHIDDEN
+#else // Others platforms not supported atm
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+#endif
+
+#endif // INCLUDED_OCIO_OPENCOLORABI_H
diff --git a/export/OpenColorIO/OpenColorIO.h b/export/OpenColorIO/OpenColorIO.h
new file mode 100644
index 0000000..b83538f
--- /dev/null
+++ b/export/OpenColorIO/OpenColorIO.h
@@ -0,0 +1,1238 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_OPENCOLORIO_H
+#define INCLUDED_OCIO_OPENCOLORIO_H
+
+#include <exception>
+#include <iosfwd>
+#include <string>
+#include <cstddef>
+
+#include "OpenColorABI.h"
+#include "OpenColorTypes.h"
+#include "OpenColorTransforms.h"
+
+/*!rst::
+C++ API
+=======
+
+**Usage Example:** *Compositing plugin that converts from "log" to "lin"*
+
+.. code-block:: cpp
+
+ #include <OpenColorIO/OpenColorIO.h>
+ namespace OCIO = OCIO_NAMESPACE;
+
+ try
+ {
+ // Get the global OpenColorIO config
+ // This will auto-initialize (using $OCIO) on first use
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ // Get the processor corresponding to this transform.
+ OCIO::ConstProcessorRcPtr processor = config->getProcessor(OCIO::ROLE_COMPOSITING_LOG,
+ OCIO::ROLE_SCENE_LINEAR);
+
+ // Wrap the image in a light-weight ImageDescription
+ OCIO::PackedImageDesc img(imageData, w, h, 4);
+
+ // Apply the color transformation (in place)
+ processor->apply(img);
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cerr << "OpenColorIO Error: " << exception.what() << std::endl;
+ }
+
+*/
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Exceptions
+ // **********
+
+ //!cpp:class:: An exception class to throw for errors detected at
+ // runtime.
+ //
+ // .. warning::
+ // All functions in the Config class can potentially throw this exception.
+ class OCIOEXPORT Exception : public std::exception
+ {
+ public:
+ //!cpp:function:: Constructor that takes a string as the exception message.
+ Exception(const char *) throw();
+ //!cpp:function:: Constructor that takes an exception pointer.
+ Exception(const Exception&) throw();
+ //!cpp:function:: Constructor that takes an exception pointer and returns an exception pointer (???).
+ Exception& operator=(const Exception&) throw();
+ //!cpp:function::
+ virtual ~Exception() throw();
+ //!cpp:function::
+ virtual const char* what() const throw();
+
+ private:
+ std::string msg_;
+ };
+
+ //!cpp:class:: An exception class for errors detected at
+ // runtime, thrown when OCIO cannot find a file that is expected to
+ // exist. This is provided as a custom type to
+ // distinguish cases where one wants to continue looking for
+ // missing files, but wants to properly fail
+ // for other error conditions.
+
+ class OCIOEXPORT ExceptionMissingFile : public Exception
+ {
+ public:
+ //!cpp:function::
+ ExceptionMissingFile(const char *) throw();
+ //!cpp:function::
+ ExceptionMissingFile(const ExceptionMissingFile&) throw();
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Global
+ // ******
+
+ //!cpp:function::
+ // OpenColorIO, during normal usage, tends to cache certain information
+ // (such as the contents of LUTs on disk, intermediate results, etc.).
+ // Calling this function will flush all such information.
+ // Under normal usage, this is not necessary, but it can be helpful in particular instances,
+ // such as designing OCIO profiles, and wanting to re-read luts without
+ // restarting.
+
+ extern OCIOEXPORT void ClearAllCaches();
+
+ //!cpp:function:: Get the version number for the library, as a
+ // dot-delimited string (e.g., "1.0.0"). This is also available
+ // at compile time as OCIO_VERSION.
+
+ extern OCIOEXPORT const char * GetVersion();
+
+ //!cpp:function:: Get the version number for the library, as a
+ // single 4-byte hex number (e.g., 0x01050200 for "1.5.2"), to be used
+ // for numeric comparisons. This is also available
+ // at compile time as OCIO_VERSION_HEX.
+
+ extern OCIOEXPORT int GetVersionHex();
+
+ //!cpp:function:: Get the global logging level.
+ // You can override this at runtime using the :envvar:`OCIO_LOGGING_LEVEL`
+ // environment variable. The client application that sets this should use
+ // :cpp:func:`SetLoggingLevel`, and not the environment variable. The default value is INFO.
+
+ extern OCIOEXPORT LoggingLevel GetLoggingLevel();
+
+ //!cpp:function:: Set the global logging level.
+ extern OCIOEXPORT void SetLoggingLevel(LoggingLevel level);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Config
+ // ******
+ //
+ // A config defines all the color spaces to be available at runtime.
+ //
+ // The color configuration (:cpp:class:`Config`) is the main object for
+ // interacting with this library. It encapsulates all of the information
+ // necessary to use customized :cpp:class:`ColorSpaceTransform` and
+ // :cpp:class:`DisplayTransform` operations.
+ //
+ // See the :ref:`user-guide` for more information on
+ // selecting, creating, and working with custom color configurations.
+ //
+ // For applications interested in using only one color config at
+ // a time (this is the vast majority of apps), their API would
+ // traditionally get the global configuration and use that, as opposed to
+ // creating a new one. This simplifies the use case for
+ // plugins and bindings, as it alleviates the need to pass around configuration
+ // handles.
+ //
+ // An example of an application where this would not be sufficient would be
+ // a multi-threaded image proxy server (daemon), which wished to handle
+ // multiple show configurations in a single process concurrently. This
+ // app would need to keep multiple configurations alive, and to manage them
+ // appropriately.
+ //
+ // Roughly speaking, a novice user should select a
+ // default configuration that most closely approximates the use case
+ // (animation, visual effects, etc.), and set the :envvar:`OCIO` environment
+ // variable to point at the root of that configuration.
+ //
+ // .. note::
+ // Initialization using environment variables is typically preferable in
+ // a multi-app ecosystem, as it allows all applications to be
+ // consistently configured.
+ //
+ // See :ref:`developers-usageexamples`
+
+ //!cpp:function:: Get the current configuration.
+
+ extern OCIOEXPORT ConstConfigRcPtr GetCurrentConfig();
+
+ //!cpp:function:: Set the current configuration. This will then store a copy of the specified config.
+ extern OCIOEXPORT void SetCurrentConfig(const ConstConfigRcPtr & config);
+
+
+ //!cpp:class::
+ class OCIOEXPORT Config
+ {
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfginit_section:
+ //
+ // Initialization
+ // ^^^^^^^^^^^^^^
+
+ //!cpp:function:: Constructor...ELABORATE
+ static ConfigRcPtr Create();
+ //!cpp:function::
+ static ConstConfigRcPtr CreateFromEnv();
+ //!cpp:function::
+ static ConstConfigRcPtr CreateFromFile(const char * filename);
+ //!cpp:function::
+ static ConstConfigRcPtr CreateFromStream(std::istream & istream);
+
+ //!cpp:function::
+ ConfigRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ // This will throw an exception if the config is malformed. The most
+ // common error occurs when references are made to colorspaces that do not
+ // exist.
+ void sanityCheck() const;
+
+ //!cpp:function::
+ const char * getDescription() const;
+ //!cpp:function::
+ void setDescription(const char * description);
+
+ //!cpp:function::
+ // Returns the string representation of the Config in YAML text form.
+ // This is typically stored on disk in a file with the extension .ocio.
+ void serialize(std::ostream & os) const;
+
+ //!cpp:function::
+ // This will produce a hash of the all colorspace definitions, etc.
+ // All external references, such as files used in FileTransforms, etc.,
+ // will be incorporated into the cacheID. While the contents of
+ // the files are not read, the file system is queried for relavent
+ // information (mtime, inode) so that the config's cacheID will
+ // change when the underlying luts are updated.
+ // If a context is not provided, the current Context will be used.
+ // If a null context is provided, file references will not be taken into
+ // account (this is essentially a hash of Config::serialize).
+ const char * getCacheID() const;
+ //!cpp:function::
+ const char * getCacheID(const ConstContextRcPtr & context) const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfgresource_section:
+ //
+ // Resources
+ // ^^^^^^^^^
+ // Given a lut src name, where should we find it?
+
+ //!cpp:function::
+ ConstContextRcPtr getCurrentContext() const;
+
+ //!cpp:function::
+ const char * getSearchPath() const;
+ void setSearchPath(const char * path);
+
+ //!cpp:function::
+ const char * getWorkingDir() const;
+ void setWorkingDir(const char * dirname);
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfgcolorspaces_section:
+ //
+ // ColorSpaces
+ // ^^^^^^^^^^^
+
+ //!cpp:function::
+ int getNumColorSpaces() const;
+ //!cpp:function:: This will null if an invalid index is specified
+ const char * getColorSpaceNameByIndex(int index) const;
+
+ //!rst::
+ // .. note::
+ // These fcns all accept either a color space OR role name.
+ // (Colorspace names take precedence over roles.)
+
+ //!cpp:function:: This will return null if the specified name is not
+ // found.
+ ConstColorSpaceRcPtr getColorSpace(const char * name) const;
+ //!cpp:function::
+ int getIndexForColorSpace(const char * name) const;
+
+ //!cpp:function::
+ // .. note::
+ // If another color space is already registered with the same name,
+ // this will overwrite it. This stores a copy of the specified
+ // color space.
+ void addColorSpace(const ConstColorSpaceRcPtr & cs);
+ //!cpp:function::
+ void clearColorSpaces();
+
+ //!cpp:function:: Given the specified string, get the longest,
+ // right-most, colorspace substring that appears.
+ //
+ // * If strict parsing is enabled, and no color space is found, return
+ // an empty string.
+ // * If strict parsing is disabled, return ROLE_DEFAULT (if defined).
+ // * If the default role is not defined, return an empty string.
+ const char * parseColorSpaceFromString(const char * str) const;
+
+ //!cpp:function::
+ bool isStrictParsingEnabled() const;
+ //!cpp:function::
+ void setStrictParsingEnabled(bool enabled);
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfgroles_section:
+ //
+ // Roles
+ // ^^^^^
+ // A role is like an alias for a colorspace. You can query the colorspace
+ // corresponding to a role using the normal getColorSpace fcn.
+
+ //!cpp:function::
+ // .. note::
+ // Setting the ``colorSpaceName`` name to a null string unsets it.
+ void setRole(const char * role, const char * colorSpaceName);
+ //!cpp:function::
+ int getNumRoles() const;
+ //!cpp:function:: Return true if the role has been defined.
+ bool hasRole(const char * role) const;
+ //!cpp:function:: Get the role name at index, this will return values
+ // like 'scene_linear', 'compositing_log'.
+ // Return empty string if index is out of range.
+ const char * getRoleName(int index) const;
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfgdisplayview_section:
+ //
+ // Display/View Registration
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^
+ //
+ // Looks is a potentially comma (or colon) delimited list of lookNames,
+ // Where +/- prefixes are optionally allowed to denote forward/inverse
+ // look specification. (And forward is assumed in the absense of either)
+
+ //!cpp:function::
+ const char * getDefaultDisplay() const;
+ //!cpp:function::
+ int getNumDisplays() const;
+ //!cpp:function::
+ const char * getDisplay(int index) const;
+
+ //!cpp:function::
+ const char * getDefaultView(const char * display) const;
+ //!cpp:function::
+ int getNumViews(const char * display) const;
+ //!cpp:function::
+ const char * getView(const char * display, int index) const;
+
+ //!cpp:function::
+ const char * getDisplayColorSpaceName(const char * display, const char * view) const;
+ //!cpp:function::
+ const char * getDisplayLooks(const char * display, const char * view) const;
+
+ //!cpp:function:: For the (display,view) combination,
+ // specify which colorSpace and look to use.
+ // If a look is not desired, then just pass an empty string
+
+ void addDisplay(const char * display, const char * view,
+ const char * colorSpaceName, const char * looks);
+
+ //!cpp:function::
+ void clearDisplays();
+
+ // $OCIO_ACTIVE_DISPLAYS envvar can, at runtime, optionally override the allowed displays.
+ // It is a comma or colon delimited list.
+ // Active displays that are not in the specified profile will be ignored, and the
+ // left-most defined display will be the default.
+
+ //!cpp:function:: Comma-delimited list of display names.
+ void setActiveDisplays(const char * displays);
+ //!cpp:function::
+ const char * getActiveDisplays() const;
+
+ // $OCIO_ACTIVE_VIEWS envvar can, at runtime, optionally override the allowed views.
+ // It is a comma or colon delimited list.
+ // Active views that are not in the specified profile will be ignored, and the
+ // left-most defined view will be the default.
+
+ //!cpp:function:: Comma-delimited list of view names.
+ void setActiveViews(const char * views);
+ //!cpp:function::
+ const char * getActiveViews() const;
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfgluma_section:
+ //
+ // Luma
+ // ^^^^
+ //
+ // Get the default coefficients for computing luma.
+ //
+ // .. note::
+ // There is no "1 size fits all" set of luma coefficients. (The
+ // values are typically different for each colorspace, and the
+ // application of them may be nonsensical depending on the
+ // intensity coding anyways). Thus, the 'right' answer is to make
+ // these functions on the :cpp:class:`Config` class. However, it's
+ // often useful to have a config-wide default so here it is. We will
+ // add the colorspace specific luma call if/when another client is
+ // interesting in using it.
+
+ //!cpp:function::
+ void getDefaultLumaCoefs(float * rgb) const;
+ //!cpp:function:: These should be normalized (sum to 1.0 exactly).
+ void setDefaultLumaCoefs(const float * rgb);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cflooka_section:
+ //
+ // Look
+ // ^^^^
+ //
+ // Manager per-shot look settings.
+ //
+
+ //!cpp:function::
+ ConstLookRcPtr getLook(const char * name) const;
+
+ //!cpp:function::
+ int getNumLooks() const;
+
+ //!cpp:function::
+ const char * getLookNameByIndex(int index) const;
+
+ //!cpp:function::
+ void addLook(const ConstLookRcPtr & look);
+
+ //!cpp:function::
+ void clearLooks();
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _cfgprocessors_section:
+ //
+ // Processors
+ // ^^^^^^^^^^
+ //
+ // Convert from inputColorSpace to outputColorSpace
+ //
+ // .. note::
+ // This may provide higher fidelity than anticipated due to internal
+ // optimizations. For example, if the inputcolorspace and the
+ // outputColorSpace are members of the same family, no conversion
+ // will be applied, even though strictly speaking quantization
+ // should be added.
+ //
+ // If you wish to test these calls for quantization characteristics,
+ // apply in two steps; the image must contain RGB triples (though
+ // arbitrary numbers of additional channels can be supported (ignored)
+ // using the pixelStrideBytes arg).
+
+ //!cpp:function::
+ ConstProcessorRcPtr getProcessor(const ConstContextRcPtr & context,
+ const ConstColorSpaceRcPtr & srcColorSpace,
+ const ConstColorSpaceRcPtr & dstColorSpace) const;
+ //!cpp:function::
+ ConstProcessorRcPtr getProcessor(const ConstColorSpaceRcPtr & srcColorSpace,
+ const ConstColorSpaceRcPtr & dstColorSpace) const;
+
+ //!cpp:function::
+ // .. note::
+ // Names can be colorspace name, role name, or a combination of both.
+ ConstProcessorRcPtr getProcessor(const char * srcName,
+ const char * dstName) const;
+ //!cpp:function::
+ ConstProcessorRcPtr getProcessor(const ConstContextRcPtr & context,
+ const char * srcName,
+ const char * dstName) const;
+
+ //!rst:: Get the processor for the specified transform.
+ //
+ // Not often needed, but will allow for the re-use of atomic OCIO
+ // functionality (such as to apply an individual LUT file).
+
+ //!cpp:function::
+ ConstProcessorRcPtr getProcessor(const ConstTransformRcPtr& transform) const;
+ //!cpp:function::
+ ConstProcessorRcPtr getProcessor(const ConstTransformRcPtr& transform,
+ TransformDirection direction) const;
+ //!cpp:function::
+ ConstProcessorRcPtr getProcessor(const ConstContextRcPtr & context,
+ const ConstTransformRcPtr& transform,
+ TransformDirection direction) const;
+
+ private:
+ Config();
+ ~Config();
+
+ Config(const Config &);
+ Config& operator= (const Config &);
+
+ static void deleter(Config* c);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const Config&);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _colorspace_section:
+ //
+ // ColorSpace
+ // **********
+ // The *ColorSpace* is the state of an image with respect to colorimetry
+ // and color encoding. Transforming images between different
+ // *ColorSpaces* is the primary motivation for this library.
+ //
+ // While a complete discussion of colorspaces is beyond the scope of
+ // header documentation, traditional uses would be to have *ColorSpaces*
+ // corresponding to: physical capture devices (known cameras, scanners),
+ // and internal 'convenience' spaces (such as scene linear, logarithmic).
+ //
+ // *ColorSpaces* are specific to a particular image precision (float32,
+ // uint8, etc.), and the set of ColorSpaces that provide equivalent mappings
+ // (at different precisions) are referred to as a 'family'.
+
+ //!cpp:class::
+ class OCIOEXPORT ColorSpace
+ {
+ public:
+ //!cpp:function::
+ static ColorSpaceRcPtr Create();
+
+ //!cpp:function::
+ ColorSpaceRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ const char * getName() const;
+ //!cpp:function::
+ void setName(const char * name);
+
+ //!cpp:function::Get the family, for use in user interfaces (optional)
+ const char * getFamily() const;
+ //!cpp:function::Set the family, for use in user interfaces (optional)
+ void setFamily(const char * family);
+
+ //!cpp:function::Get the ColorSpace group name (used for equality comparisons)
+ // This allows no-op transforms between different colorspaces.
+ // If an equalityGroup is not defined (an empty string), it will be considered
+ // unique (i.e., it will not compare as equal to other ColorSpaces with an
+ // empty equality group). This is often, though not always, set to the
+ // same value as 'family'.
+ const char * getEqualityGroup() const;
+ //!cpp:function::
+ void setEqualityGroup(const char * equalityGroup);
+
+ //!cpp:function::
+ const char * getDescription() const;
+ //!cpp:function::
+ void setDescription(const char * description);
+
+ //!cpp:function::
+ BitDepth getBitDepth() const;
+ //!cpp:function::
+ void setBitDepth(BitDepth bitDepth);
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Data
+ // ^^^^
+ // ColorSpaces that are data are treated a bit special. Basically, any
+ // colorspace transforms you try to apply to them are ignored. (Think
+ // of applying a gamut mapping transform to an ID pass). Also, the
+ // :cpp:class:`DisplayTransform` process obeys special 'data min' and
+ // 'data max' args.
+ //
+ // This is traditionally used for pixel data that represents non-color
+ // pixel data, such as normals, point positions, ID information, etc.
+
+ //!cpp:function::
+ bool isData() const;
+ //!cpp:function::
+ void setIsData(bool isData);
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Allocation
+ // ^^^^^^^^^^
+ // If this colorspace needs to be transferred to a limited dynamic
+ // range coding space (such as during display with a GPU path), use this
+ // allocation to maximize bit efficiency.
+
+ //!cpp:function::
+ Allocation getAllocation() const;
+ //!cpp:function::
+ void setAllocation(Allocation allocation);
+
+ //!rst::
+ // Specify the optional variable values to configure the allocation.
+ // If no variables are specified, the defaults are used.
+ //
+ // ALLOCATION_UNIFORM::
+ //
+ // 2 vars: [min, max]
+ //
+ // ALLOCATION_LG2::
+ //
+ // 2 vars: [lg2min, lg2max]
+ // 3 vars: [lg2min, lg2max, linear_offset]
+
+ //!cpp:function::
+ int getAllocationNumVars() const;
+ //!cpp:function::
+ void getAllocationVars(float * vars) const;
+ //!cpp:function::
+ void setAllocationVars(int numvars, const float * vars);
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Transform
+ // ^^^^^^^^^
+
+ //!cpp:function::
+ // If a transform in the specified direction has been specified,
+ // return it. Otherwise return a null ConstTransformRcPtr
+ ConstTransformRcPtr getTransform(ColorSpaceDirection dir) const;
+ //!cpp:function::
+ // Specify the transform for the appropriate direction.
+ // Setting the transform to null will clear it.
+ void setTransform(const ConstTransformRcPtr & transform,
+ ColorSpaceDirection dir);
+
+ private:
+ ColorSpace();
+ ~ColorSpace();
+
+ ColorSpace(const ColorSpace &);
+ ColorSpace& operator= (const ColorSpace &);
+
+ static void deleter(ColorSpace* c);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const ColorSpace&);
+
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst:: .. _look_section:
+ //
+ // Look
+ // ****
+ // The *Look* is an 'artistic' image modification, in a specified image
+ // state.
+ // The processSpace defines the ColorSpace the image is required to be
+ // in, for the math to apply correctly.
+
+ //!cpp:class::
+ class OCIOEXPORT Look
+ {
+ public:
+ //!cpp:function::
+ static LookRcPtr Create();
+
+ //!cpp:function::
+ LookRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ const char * getName() const;
+ //!cpp:function::
+ void setName(const char * name);
+
+ //!cpp:function::
+ const char * getProcessSpace() const;
+ //!cpp:function::
+ void setProcessSpace(const char * processSpace);
+
+ //!cpp:function::
+ ConstTransformRcPtr getTransform() const;
+ //!cpp:function:: Setting a transform to a non-null call makes it allowed.
+ void setTransform(const ConstTransformRcPtr & transform);
+
+ //!cpp:function::
+ ConstTransformRcPtr getInverseTransform() const;
+ //!cpp:function:: Setting a transform to a non-null call makes it allowed.
+ void setInverseTransform(const ConstTransformRcPtr & transform);
+ private:
+ Look();
+ ~Look();
+
+ Look(const Look &);
+ Look& operator= (const Look &);
+
+ static void deleter(Look* c);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const Look&);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Processor
+ // *********
+
+ //!cpp:class::
+ class OCIOEXPORT Processor
+ {
+ public:
+ //!cpp:function::
+ static ProcessorRcPtr Create();
+
+ //!cpp:function::
+ bool isNoOp() const;
+
+ //!cpp:function:: does the processor represent an image transformation that
+ // introduces crosstalk between the image channels
+ bool hasChannelCrosstalk() const;
+
+ //!cpp:function::
+ ConstProcessorMetadataRcPtr getMetadata() const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // CPU Path
+ // ^^^^^^^^
+
+ //!cpp:function:: Apply to an image.
+ void apply(ImageDesc& img) const;
+
+ //!rst::
+ // Apply to a single pixel.
+ //
+ // .. note::
+ // This is not as efficient as applying to an entire image at once.
+ // If you are processing multiple pixels, and have the flexibility,
+ // use the above function instead.
+
+ //!cpp:function::
+ void applyRGB(float * pixel) const;
+ //!cpp:function::
+ void applyRGBA(float * pixel) const;
+
+ //!cpp:function::
+ const char * getCpuCacheID() const;
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // GPU Path
+ // ^^^^^^^^
+ // Get the 3d lut + cg shader for the specified
+ // :cpp:class:`DisplayTransform`.
+ //
+ // cg signature will be::
+ //
+ // shaderFcnName(in half4 inPixel, const uniform sampler3D lut3d)
+ //
+ // lut3d should be size: 3 * edgeLen * edgeLen * edgeLen
+ // return 0 if unknown
+
+ //!cpp:function::
+ const char * getGpuShaderText(const GpuShaderDesc & shaderDesc) const;
+ //!cpp:function::
+ const char * getGpuShaderTextCacheID(const GpuShaderDesc & shaderDesc) const;
+
+ //!cpp:function::
+ void getGpuLut3D(float* lut3d, const GpuShaderDesc & shaderDesc) const;
+ //!cpp:function::
+ const char * getGpuLut3DCacheID(const GpuShaderDesc & shaderDesc) const;
+
+ private:
+ Processor();
+ ~Processor();
+
+ Processor(const Processor &);
+ Processor& operator= (const Processor &);
+
+ static void deleter(Processor* c);
+
+ friend class Config;
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+
+ //!cpp:class::
+ // This class contains meta information about the process that generated
+ // this processor. The results of these functions do not
+ // impact the pixel processing.
+
+ class OCIOEXPORT ProcessorMetadata
+ {
+ public:
+ //!cpp:function::
+ static ProcessorMetadataRcPtr Create();
+
+ //!cpp:function::
+ int getNumFiles() const;
+ //!cpp:function::
+ const char * getFile(int index) const;
+
+ //!cpp:function::
+ int getNumLooks() const;
+ //!cpp:function::
+ const char * getLook(int index) const;
+
+ //!cpp:function::
+ void addFile(const char * fname);
+ //!cpp:function::
+ void addLook(const char * look);
+ private:
+ ProcessorMetadata();
+ ~ProcessorMetadata();
+ ProcessorMetadata(const ProcessorMetadata &);
+ ProcessorMetadata& operator= (const ProcessorMetadata &);
+
+ static void deleter(ProcessorMetadata* c);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Baker
+ // *****
+ //
+ // In certain situations it is nessary to serilize transforms into a variety
+ // of application specific lut formats. The Baker can be used to create lut
+ // formats that ocio supports for writing.
+ //
+ // **Usage Example:** *Bake a houdini sRGB viewer lut*
+ //
+ // .. code-block:: cpp
+ //
+ // OCIO::ConstConfigRcPtr config = OCIO::Config::CreateFromEnv();
+ // OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+ // baker->setConfig(config);
+ // baker->setFormat("houdini"); // set the houdini type
+ // baker->setType("3D"); // we want a 3D lut
+ // baker->setInputSpace("lnf");
+ // baker->setShaperSpace("log");
+ // baker->setTargetSpace("sRGB");
+ // std::ostringstream out;
+ // baker->bake(out); // fresh bread anyone!
+ // std::cout << out.str();
+
+ class OCIOEXPORT Baker
+ {
+ public:
+ //!cpp:function:: create a new Baker
+ static BakerRcPtr Create();
+
+ //!cpp:function:: create a copy of this Baker
+ BakerRcPtr createEditableCopy() const;
+
+ //!cpp:function:: set the config to use
+ void setConfig(const ConstConfigRcPtr & config);
+ //!cpp:function:: get the config to use
+ ConstConfigRcPtr getConfig() const;
+
+ //!cpp:function:: set the lut output format
+ void setFormat(const char * formatName);
+ //!cpp:function:: get the lut output format
+ const char * getFormat() const;
+
+ // TODO: Change this to an enum
+ //!cpp:function:: set the lut output type (1D or 3D)
+ void setType(const char * type);
+ //!cpp:function:: get the lut output type
+ const char * getType() const;
+
+ //!cpp:function:: set *optional* meta data for luts that support it
+ void setMetadata(const char * metadata);
+ //!cpp:function:: get the meta data that has been set
+ const char * getMetadata() const;
+
+ //!cpp:function:: set the input ColorSpace that the lut will be
+ // applied to
+ void setInputSpace(const char * inputSpace);
+ //!cpp:function:: get the input ColorSpace that has been set
+ const char * getInputSpace() const;
+
+ //!cpp:function:: set an *optional* ColorSpace to be used to shape /
+ // transfer the input colorspace. This is mostly used to allocate
+ // an HDR luminance range into an LDR one. If a shaper space
+ // is not explicitly specified, and the file format supports one,
+ // the ColorSpace Allocation will be used
+
+ void setShaperSpace(const char * shaperSpace);
+ //!cpp:function:: get the shaper colorspace that has been set
+ const char * getShaperSpace() const;
+
+ //!cpp:function:: set the looks to be applied during baking
+ // Looks is a potentially comma (or colon) delimited list of lookNames,
+ // Where +/- prefixes are optionally allowed to denote forward/inverse
+ // look specification. (And forward is assumed in the absense of either)
+ void setLooks(const char * looks);
+ //!cpp:function:: get the looks to be applied during baking
+ const char * getLooks() const;
+
+ //!cpp:function:: set the target device colorspace for the lut
+ void setTargetSpace(const char * targetSpace);
+ //!cpp:function:: get the target colorspace that has been set
+ const char * getTargetSpace() const;
+
+ //!cpp:function:: override the default the shaper sample size,
+ // default: <format specific>
+ void setShaperSize(int shapersize);
+ //!cpp:function:: get the shaper sample size
+ int getShaperSize() const;
+
+ //!cpp:function:: override the default cube sample size
+ // default: <format specific>
+ void setCubeSize(int cubesize);
+ //!cpp:function:: get the cube sample size
+ int getCubeSize() const;
+
+ //!cpp:function:: bake the lut into the output stream
+ void bake(std::ostream & os) const;
+
+ //!cpp:function:: get the number of lut writers
+ static int getNumFormats();
+
+ //!cpp:function:: get the lut writer at index, return empty string if
+ // an invalid index is specified
+ static const char * getFormatNameByIndex(int index);
+ static const char * getFormatExtensionByIndex(int index);
+
+ private:
+ Baker();
+ ~Baker();
+
+ Baker(const Baker &);
+ Baker& operator= (const Baker &);
+
+ static void deleter(Baker* o);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // ImageDesc
+ // *********
+
+ //!rst::
+ // .. c:var:: const ptrdiff_t AutoStride
+ //
+ // AutoStride
+ const ptrdiff_t AutoStride = std::numeric_limits<ptrdiff_t>::min();
+
+ //!cpp:class::
+ // This is a light-weight wrapper around an image, that provides a context
+ // for pixel access. This does NOT claim ownership of the pixels or copy
+ // image data
+
+ class OCIOEXPORT ImageDesc
+ {
+ public:
+ //!cpp:function::
+ virtual ~ImageDesc();
+ private:
+ ImageDesc& operator= (const ImageDesc &);
+ };
+
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const ImageDesc&);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // PackedImageDesc
+ // ^^^^^^^^^^^^^^^
+
+ //!cpp:class::
+ class OCIOEXPORT PackedImageDesc : public ImageDesc
+ {
+ public:
+ //!cpp:function::
+ // Pass the pointer to packed image data: rgbrgbrgb, etc.
+ // The number of channels must be greater than or equal to 3
+ // If a 4th channel is specified, it is assumed to be alpha
+ // information. Channels > 4 will be ignored.
+
+ PackedImageDesc(float * data,
+ long width, long height,
+ long numChannels,
+ ptrdiff_t chanStrideBytes = AutoStride,
+ ptrdiff_t xStrideBytes = AutoStride,
+ ptrdiff_t yStrideBytes = AutoStride);
+ //!cpp:function::
+ virtual ~PackedImageDesc();
+
+ //!cpp:function::
+ float * getData() const;
+
+ //!cpp:function::
+ long getWidth() const;
+ //!cpp:function::
+ long getHeight() const;
+ //!cpp:function::
+ long getNumChannels() const;
+
+ //!cpp:function::
+ ptrdiff_t getChanStrideBytes() const;
+ //!cpp:function::
+ ptrdiff_t getXStrideBytes() const;
+ //!cpp:function::
+ ptrdiff_t getYStrideBytes() const;
+
+ private:
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+
+ PackedImageDesc(const PackedImageDesc &);
+ PackedImageDesc& operator= (const PackedImageDesc &);
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // PlanarImageDesc
+ // ^^^^^^^^^^^^^^^
+
+ //!cpp:class::
+ class OCIOEXPORT PlanarImageDesc : public ImageDesc
+ {
+ public:
+ //!cpp:function::
+ // Pass the pointer to the specified image planes: rrrr gggg bbbb, etc.
+ // aData is optional, pass NULL if no alpha exists.
+ // {r,g,b} Data must be specified
+
+ PlanarImageDesc(float * rData, float * gData, float * bData, float * aData,
+ long width, long height,
+ ptrdiff_t yStrideBytes = AutoStride);
+ //!cpp:function::
+ virtual ~PlanarImageDesc();
+
+ //!cpp:function::
+ float* getRData() const;
+ //!cpp:function::
+ float* getGData() const;
+ //!cpp:function::
+ float* getBData() const;
+ //!cpp:function::
+ float* getAData() const;
+
+ //!cpp:function::
+ long getWidth() const;
+ //!cpp:function::
+ long getHeight() const;
+
+ //!cpp:function::
+ ptrdiff_t getYStrideBytes() const;
+
+ private:
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+
+ PlanarImageDesc(const PlanarImageDesc &);
+ PlanarImageDesc& operator= (const PlanarImageDesc &);
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // GpuShaderDesc
+ // *************
+
+ //!cpp:class::
+ class OCIOEXPORT GpuShaderDesc
+ {
+ public:
+ //!cpp:function::
+ GpuShaderDesc();
+ //!cpp:function::
+ ~GpuShaderDesc();
+
+ //!cpp:function::
+ void setLanguage(GpuLanguage lang);
+ //!cpp:function::
+ GpuLanguage getLanguage() const;
+
+ //!cpp:function::
+ void setFunctionName(const char * name);
+ //!cpp:function::
+ const char * getFunctionName() const;
+
+ //!cpp:function::
+ void setLut3DEdgeLen(int len);
+ //!cpp:function::
+ int getLut3DEdgeLen() const;
+
+ //!cpp:function::
+ const char * getCacheID() const;
+
+ private:
+
+ GpuShaderDesc(const GpuShaderDesc &);
+ GpuShaderDesc& operator= (const GpuShaderDesc &);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!rst::
+ // Context
+ // *******
+
+ //!cpp:class::
+ class OCIOEXPORT Context
+ {
+ public:
+ //!cpp:function::
+ static ContextRcPtr Create();
+
+ //!cpp:function::
+ ContextRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ const char * getCacheID() const;
+
+ //!cpp:function::
+ void setSearchPath(const char * path);
+ //!cpp:function::
+ const char * getSearchPath() const;
+
+ //!cpp:function::
+ void setWorkingDir(const char * dirname);
+ //!cpp:function::
+ const char * getWorkingDir() const;
+
+ //!cpp:function::
+ void setStringVar(const char * name, const char * value);
+ //!cpp:function::
+ const char * getStringVar(const char * name) const;
+
+ int getNumStringVars() const;
+ const char * getStringVarNameByIndex(int index) const;
+
+ //!cpp:function:: Seed all string vars with the current environment.
+ void loadEnvironment();
+
+ //! Do a string lookup.
+ //!cpp:function:: Do a file lookup.
+ //
+ // Evaluate the specified variable (as needed). Will not throw exceptions.
+ const char * resolveStringVar(const char * val) const;
+
+ //! Do a file lookup.
+ //!cpp:function:: Do a file lookup.
+ //
+ // Evaluate all variables (as needed).
+ // Also, walk the full search path until the file is found.
+ // If the filename cannot be found, an exception will be thrown.
+ const char * resolveFileLocation(const char * filename) const;
+
+ private:
+ Context();
+ ~Context();
+
+ Context(const Context &);
+ Context& operator= (const Context &);
+
+ static void deleter(Context* c);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const Context&);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif // INCLUDED_OCIO_OPENCOLORIO_H
diff --git a/export/OpenColorIO/OpenColorTransforms.h b/export/OpenColorIO/OpenColorTransforms.h
new file mode 100644
index 0000000..c987179
--- /dev/null
+++ b/export/OpenColorIO/OpenColorTransforms.h
@@ -0,0 +1,812 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_OPENCOLORTRANSFORMS_H
+#define INCLUDED_OCIO_OPENCOLORTRANSFORMS_H
+
+#include "OpenColorTypes.h"
+
+#ifndef OCIO_NAMESPACE_ENTER
+#error This header cannot be used directly. Use <OpenColorIO/OpenColorIO.h> instead.
+#endif
+
+/*!rst::
+C++ Transforms
+==============
+
+Typically only needed when creating and/or manipulating configurations
+*/
+
+OCIO_NAMESPACE_ENTER
+{
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class::
+ class OCIOEXPORT Transform
+ {
+ public:
+ virtual ~Transform();
+ virtual TransformRcPtr createEditableCopy() const = 0;
+
+ virtual TransformDirection getDirection() const = 0;
+ virtual void setDirection(TransformDirection dir) = 0;
+
+ private:
+ Transform& operator= (const Transform &);
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const Transform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class:: Forward direction wraps the 'expanded' range into the
+ // specified, often compressed, range.
+ class OCIOEXPORT AllocationTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static AllocationTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ Allocation getAllocation() const;
+ //!cpp:function::
+ void setAllocation(Allocation allocation);
+
+ //!cpp:function::
+ int getNumVars() const;
+ //!cpp:function::
+ void getVars(float * vars) const;
+ //!cpp:function::
+ void setVars(int numvars, const float * vars);
+
+ private:
+ AllocationTransform();
+ AllocationTransform(const AllocationTransform &);
+ virtual ~AllocationTransform();
+
+ AllocationTransform& operator= (const AllocationTransform &);
+
+ static void deleter(AllocationTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const AllocationTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class:: An implementation of the ASC CDL Transfer Functions and
+ // Interchange - Syntax (Based on the version 1.2 document)
+ //
+ // .. note::
+ // the clamping portion of the CDL is only applied if a non-identity
+ // power is specified.
+ class OCIOEXPORT CDLTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static CDLTransformRcPtr Create();
+
+ //!cpp:function::
+ // Load the CDL from the src .cc or .ccc file.
+ // If a .ccc is used, the cccid must also be specified
+ // src must be an absolute path reference, no relative directory
+ // or envvar resolution is performed.
+ static CDLTransformRcPtr CreateFromFile(const char * src, const char * cccid);
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ bool equals(const ConstCDLTransformRcPtr & other) const;
+
+ //!cpp:function::
+ const char * getXML() const;
+ //!cpp:function::
+ void setXML(const char * xml);
+
+ //!rst:: **ASC_SOP**
+ //
+ // Slope, offset, power::
+ //
+ // out = clamp( (in * slope) + offset ) ^ power
+
+ //!cpp:function::
+ void setSlope(const float * rgb);
+ //!cpp:function::
+ void getSlope(float * rgb) const;
+
+ //!cpp:function::
+ void setOffset(const float * rgb);
+ //!cpp:function::
+ void getOffset(float * rgb) const;
+
+ //!cpp:function::
+ void setPower(const float * rgb);
+ //!cpp:function::
+ void getPower(float * rgb) const;
+
+ //!cpp:function::
+ void setSOP(const float * vec9);
+ //!cpp:function::
+ void getSOP(float * vec9) const;
+
+ //!rst:: **ASC_SAT**
+
+ //!cpp:function::
+ void setSat(float sat);
+ //!cpp:function::
+ float getSat() const;
+
+ //!cpp:function:: These are hard-coded, by spec, to r709
+ void getSatLumaCoefs(float * rgb) const;
+
+ //!rst:: **Metadata**
+ //
+ // These do not affect the image processing, but
+ // are often useful for pipeline purposes and are
+ // included in the serialization.
+
+ //!cpp:function:: Unique Identifier for this correction
+ void setID(const char * id);
+ //!cpp:function::
+ const char * getID() const;
+
+ //!cpp:function:: Textual description of color correction
+ // (stored on the SOP)
+ void setDescription(const char * desc);
+ //!cpp:function::
+ const char * getDescription() const;
+
+ private:
+ CDLTransform();
+ CDLTransform(const CDLTransform &);
+ virtual ~CDLTransform();
+
+ CDLTransform& operator= (const CDLTransform &);
+
+ static void deleter(CDLTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const CDLTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class::
+ class OCIOEXPORT ColorSpaceTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static ColorSpaceTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ const char * getSrc() const;
+ //!cpp:function::
+ void setSrc(const char * src);
+
+ //!cpp:function::
+ const char * getDst() const;
+ //!cpp:function::
+ void setDst(const char * dst);
+
+ private:
+ ColorSpaceTransform();
+ ColorSpaceTransform(const ColorSpaceTransform &);
+ virtual ~ColorSpaceTransform();
+
+ ColorSpaceTransform& operator= (const ColorSpaceTransform &);
+
+ static void deleter(ColorSpaceTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const ColorSpaceTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class::
+ class OCIOEXPORT DisplayTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static DisplayTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+
+
+
+ //!cpp:function:: Step 0. Specify the incoming color space
+ void setInputColorSpaceName(const char * name);
+ //!cpp:function::
+ const char * getInputColorSpaceName() const;
+
+ //!cpp:function:: Step 1: Apply a Color Correction, in ROLE_SCENE_LINEAR
+ void setLinearCC(const ConstTransformRcPtr & cc);
+ //!cpp:function::
+ ConstTransformRcPtr getLinearCC() const;
+
+ //!cpp:function:: Step 2: Apply a color correction, in ROLE_COLOR_TIMING
+ void setColorTimingCC(const ConstTransformRcPtr & cc);
+ //!cpp:function::
+ ConstTransformRcPtr getColorTimingCC() const;
+
+ //!cpp:function:: Step 3: Apply the Channel Viewing Swizzle (mtx)
+ void setChannelView(const ConstTransformRcPtr & transform);
+ //!cpp:function::
+ ConstTransformRcPtr getChannelView() const;
+
+ //!cpp:function:: Step 4: Apply the output display transform
+ // This is controlled by the specification of (display, view)
+ void setDisplay(const char * display);
+ //!cpp:function::
+ const char * getDisplay() const;
+
+ //!cpp:function::Specify which view transform to use
+ void setView(const char * view);
+ //!cpp:function::
+ const char * getView() const;
+
+ //!cpp:function:: Step 5: Apply a post display transform color correction
+ void setDisplayCC(const ConstTransformRcPtr & cc);
+ //!cpp:function::
+ ConstTransformRcPtr getDisplayCC() const;
+
+
+
+ //!cpp:function:: A user can optionally override the looks that are,
+ // by default, used with the expected display / view combination.
+ // A common use case for this functionality is in an image viewing
+ // app, where per-shot looks are supported. If for some reason
+ // a per-shot look is not defined for the current Context, the
+ // Config::getProcessor fcn will not succeed by default. Thus,
+ // with this mechanism the viewing app could override to looks = "",
+ // and this will allow image display to continue (though hopefully)
+ // the interface would reflect this fallback option.)
+ //
+ // Looks is a potentially comma (or colon) delimited list of lookNames,
+ // Where +/- prefixes are optionally allowed to denote forward/inverse
+ // look specification. (And forward is assumed in the absense of either)
+
+ void setLooksOverride(const char * looks);
+ //!cpp:function::
+ const char * getLooksOverride() const;
+
+ //!cpp:function:: Specifiy whether the lookOverride should be used,
+ // or not. This is a speparate flag, as it's often useful to override
+ // "looks" to an empty string
+ void setLooksOverrideEnabled(bool enabled);
+ //!cpp:function::
+ bool getLooksOverrideEnabled() const;
+
+ private:
+ DisplayTransform();
+ DisplayTransform(const DisplayTransform &);
+ virtual ~DisplayTransform();
+
+ DisplayTransform& operator= (const DisplayTransform &);
+
+ static void deleter(DisplayTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const DisplayTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class:: Represents exponent transform: pow( clamp(color), value)
+ //
+ // If the exponent is 1.0, this will not clamp. Otherwise, the input color
+ // will be clamped between [0.0, inf]
+ class OCIOEXPORT ExponentTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static ExponentTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ void setValue(const float * vec4);
+ //!cpp:function::
+ void getValue(float * vec4) const;
+
+ private:
+ ExponentTransform();
+ ExponentTransform(const ExponentTransform &);
+ virtual ~ExponentTransform();
+
+ ExponentTransform& operator= (const ExponentTransform &);
+
+ static void deleter(ExponentTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const ExponentTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class::
+ class OCIOEXPORT FileTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static FileTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ const char * getSrc() const;
+ //!cpp:function::
+ void setSrc(const char * src);
+
+ //!cpp:function::
+ const char * getCCCId() const;
+ //!cpp:function::
+ void setCCCId(const char * id);
+
+ //!cpp:function::
+ Interpolation getInterpolation() const;
+ //!cpp:function::
+ void setInterpolation(Interpolation interp);
+
+ //!cpp:function:: get the number of lut readers
+ static int getNumFormats();
+ //!cpp:function:: get the lut readers at index, return empty string if
+ // an invalid index is specified
+ static const char * getFormatNameByIndex(int index);
+
+ //!cpp:function:: get the lut reader extension at index, return empty string if
+ // an invalid index is specified
+ static const char * getFormatExtensionByIndex(int index);
+
+ private:
+ FileTransform();
+ FileTransform(const FileTransform &);
+ virtual ~FileTransform();
+
+ FileTransform& operator= (const FileTransform &);
+
+ static void deleter(FileTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const FileTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class::
+ class OCIOEXPORT GroupTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static GroupTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ ConstTransformRcPtr getTransform(int index) const;
+
+ //!cpp:function::
+ int size() const;
+ //!cpp:function::
+ void push_back(const ConstTransformRcPtr& transform);
+ //!cpp:function::
+ void clear();
+ //!cpp:function::
+ bool empty() const;
+
+ private:
+ GroupTransform();
+ GroupTransform(const GroupTransform &);
+ virtual ~GroupTransform();
+
+ GroupTransform& operator= (const GroupTransform &);
+
+ static void deleter(GroupTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const GroupTransform&);
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class:: Represents log transform: log(color, base)
+ //
+ // * The input will be clamped for negative numbers.
+ // * Default base is 2.0
+ // * Only the rgb channels are affected
+ class OCIOEXPORT LogTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static LogTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ void setBase(float val);
+ //!cpp:function::
+ float getBase() const;
+
+ private:
+ LogTransform();
+ LogTransform(const LogTransform &);
+ virtual ~LogTransform();
+
+ LogTransform& operator= (const LogTransform &);
+
+ static void deleter(LogTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const LogTransform&);
+
+
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class::
+ class OCIOEXPORT LookTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static LookTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ const char * getSrc() const;
+ //!cpp:function::
+ void setSrc(const char * src);
+
+ //!cpp:function::
+ const char * getDst() const;
+ //!cpp:function::
+ void setDst(const char * dst);
+
+ //!cpp:function:: Specify looks to apply.
+ // Looks is a potentially comma (or colon) delimited list of look names,
+ // Where +/- prefixes are optionally allowed to denote forward/inverse
+ // look specification. (And forward is assumed in the absense of either)
+ void setLooks(const char * looks);
+ //!cpp:function::
+ const char * getLooks() const;
+
+ private:
+ LookTransform();
+ LookTransform(const LookTransform &);
+ virtual ~LookTransform();
+
+ LookTransform& operator= (const LookTransform &);
+
+ static void deleter(LookTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const LookTransform&);
+
+
+
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class:: Represents an MX+B Matrix transform
+ class OCIOEXPORT MatrixTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static MatrixTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ bool equals(const MatrixTransform & other) const;
+
+ //!cpp:function::
+ void setValue(const float * m44, const float * offset4);
+ //!cpp:function::
+ void getValue(float * m44, float * offset4) const;
+
+ //!cpp:function::
+ void setMatrix(const float * m44);
+ //!cpp:function::
+ void getMatrix(float * m44) const;
+
+ //!cpp:function::
+ void setOffset(const float * offset4);
+ //!cpp:function::
+ void getOffset(float * offset4) const;
+
+ //!rst:: **Convenience functions**
+ //
+ // to get the mtx and offset corresponding to higher-level concepts
+ //
+ // .. note::
+ // These can throw an exception if for any component
+ // ``oldmin == oldmax. (divide by 0)``
+
+ //!cpp:function::
+ static void Fit(float * m44, float * offset4,
+ const float * oldmin4, const float * oldmax4,
+ const float * newmin4, const float * newmax4);
+
+ //!cpp:function::
+ static void Identity(float * m44, float * offset4);
+
+ //!cpp:function::
+ static void Sat(float * m44, float * offset4,
+ float sat, const float * lumaCoef3);
+
+ //!cpp:function::
+ static void Scale(float * m44, float * offset4,
+ const float * scale4);
+
+ //!cpp:function::
+ static void View(float * m44, float * offset4,
+ int * channelHot4,
+ const float * lumaCoef3);
+
+ private:
+ MatrixTransform();
+ MatrixTransform(const MatrixTransform &);
+ virtual ~MatrixTransform();
+
+ MatrixTransform& operator= (const MatrixTransform &);
+
+ static void deleter(MatrixTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const MatrixTransform&);
+
+ //!rst:: //////////////////////////////////////////////////////////////////
+
+ //!cpp:class:: Truelight transform using its API
+ class OCIOEXPORT TruelightTransform : public Transform
+ {
+ public:
+ //!cpp:function::
+ static TruelightTransformRcPtr Create();
+
+ //!cpp:function::
+ virtual TransformRcPtr createEditableCopy() const;
+
+ //!cpp:function::
+ virtual TransformDirection getDirection() const;
+ //!cpp:function::
+ virtual void setDirection(TransformDirection dir);
+
+ //!cpp:function::
+ void setConfigRoot(const char * configroot);
+ //!cpp:function::
+ const char * getConfigRoot() const;
+
+ //!cpp:function::
+ void setProfile(const char * profile);
+ //!cpp:function::
+ const char * getProfile() const;
+
+ //!cpp:function::
+ void setCamera(const char * camera);
+ //!cpp:function::
+ const char * getCamera() const;
+
+ //!cpp:function::
+ void setInputDisplay(const char * display);
+ //!cpp:function::
+ const char * getInputDisplay() const;
+
+ //!cpp:function::
+ void setRecorder(const char * recorder);
+ //!cpp:function::
+ const char * getRecorder() const;
+
+ //!cpp:function::
+ void setPrint(const char * print);
+ //!cpp:function::
+ const char * getPrint() const;
+
+ //!cpp:function::
+ void setLamp(const char * lamp);
+ //!cpp:function::
+ const char * getLamp() const;
+
+ //!cpp:function::
+ void setOutputCamera(const char * camera);
+ //!cpp:function::
+ const char * getOutputCamera() const;
+
+ //!cpp:function::
+ void setDisplay(const char * display);
+ //!cpp:function::
+ const char * getDisplay() const;
+
+ //!cpp:function::
+ void setCubeInput(const char * type);
+ //!cpp:function::
+ const char * getCubeInput() const;
+
+ private:
+ TruelightTransform();
+ TruelightTransform(const TruelightTransform &);
+ virtual ~TruelightTransform();
+
+ TruelightTransform& operator= (const TruelightTransform &);
+
+ static void deleter(TruelightTransform* t);
+
+ class Impl;
+ friend class Impl;
+ Impl * m_impl;
+ Impl * getImpl() { return m_impl; }
+ const Impl * getImpl() const { return m_impl; }
+ };
+
+ //!cpp:function::
+ extern OCIOEXPORT std::ostream& operator<< (std::ostream&, const TruelightTransform &);
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/export/OpenColorIO/OpenColorTypes.h b/export/OpenColorIO/OpenColorTypes.h
new file mode 100644
index 0000000..1d2bddb
--- /dev/null
+++ b/export/OpenColorIO/OpenColorTypes.h
@@ -0,0 +1,397 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_OPENCOLORTYPES_H
+#define INCLUDED_OCIO_OPENCOLORTYPES_H
+
+#include "OpenColorABI.h"
+
+#ifndef OCIO_NAMESPACE_ENTER
+#error This header cannot be used directly. Use <OpenColorIO/OpenColorIO.h> instead.
+#endif
+
+#include <limits>
+#include <string>
+
+/*!rst::
+C++ Types
+=========
+*/
+
+OCIO_NAMESPACE_ENTER
+{
+ // Predeclare all class ptr definitions
+
+ //!rst::
+ // Core
+ // ****
+
+ class OCIOEXPORT Config;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const Config> ConstConfigRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<Config> ConfigRcPtr;
+
+ class OCIOEXPORT ColorSpace;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const ColorSpace> ConstColorSpaceRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<ColorSpace> ColorSpaceRcPtr;
+
+ class OCIOEXPORT Look;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const Look> ConstLookRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<Look> LookRcPtr;
+
+ class OCIOEXPORT Context;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const Context> ConstContextRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<Context> ContextRcPtr;
+
+ class OCIOEXPORT Processor;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const Processor> ConstProcessorRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<Processor> ProcessorRcPtr;
+
+ class OCIOEXPORT ProcessorMetadata;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const ProcessorMetadata> ConstProcessorMetadataRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<ProcessorMetadata> ProcessorMetadataRcPtr;
+
+ class OCIOEXPORT Baker;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const Baker> ConstBakerRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<Baker> BakerRcPtr;
+
+ class OCIOEXPORT ImageDesc;
+ class OCIOEXPORT GpuShaderDesc;
+ class OCIOEXPORT Exception;
+
+
+ //!rst::
+ // Transforms
+ // **********
+
+ class OCIOEXPORT Transform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const Transform> ConstTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<Transform> TransformRcPtr;
+
+ class OCIOEXPORT AllocationTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const AllocationTransform> ConstAllocationTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<AllocationTransform> AllocationTransformRcPtr;
+
+ class OCIOEXPORT CDLTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const CDLTransform> ConstCDLTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<CDLTransform> CDLTransformRcPtr;
+
+ class OCIOEXPORT ColorSpaceTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const ColorSpaceTransform> ConstColorSpaceTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<ColorSpaceTransform> ColorSpaceTransformRcPtr;
+
+ class OCIOEXPORT DisplayTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const DisplayTransform> ConstDisplayTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<DisplayTransform> DisplayTransformRcPtr;
+
+ class OCIOEXPORT ExponentTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const ExponentTransform> ConstExponentTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<ExponentTransform> ExponentTransformRcPtr;
+
+ class OCIOEXPORT FileTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const FileTransform> ConstFileTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<FileTransform> FileTransformRcPtr;
+
+ class OCIOEXPORT GroupTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const GroupTransform> ConstGroupTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<GroupTransform> GroupTransformRcPtr;
+
+ class OCIOEXPORT LogTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const LogTransform> ConstLogTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<LogTransform> LogTransformRcPtr;
+
+ class OCIOEXPORT LookTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const LookTransform> ConstLookTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<LookTransform> LookTransformRcPtr;
+
+ class OCIOEXPORT MatrixTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const MatrixTransform> ConstMatrixTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<MatrixTransform> MatrixTransformRcPtr;
+
+ class OCIOEXPORT TruelightTransform;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<const TruelightTransform> ConstTruelightTransformRcPtr;
+ //!cpp:type::
+ typedef OCIO_SHARED_PTR<TruelightTransform> TruelightTransformRcPtr;
+
+ template <class T, class U>
+ inline OCIO_SHARED_PTR<T> DynamicPtrCast(OCIO_SHARED_PTR<U> const & ptr)
+ {
+ return OCIO_DYNAMIC_POINTER_CAST<T,U>(ptr);
+ }
+
+
+ //!rst::
+ // Enums
+ // *****
+
+ enum LoggingLevel
+ {
+ LOGGING_LEVEL_NONE = 0,
+ LOGGING_LEVEL_WARNING = 1,
+ LOGGING_LEVEL_INFO = 2,
+ LOGGING_LEVEL_DEBUG = 3,
+ LOGGING_LEVEL_UNKNOWN = 255
+ };
+
+ //!cpp:type::
+ enum ColorSpaceDirection
+ {
+ COLORSPACE_DIR_UNKNOWN = 0,
+ COLORSPACE_DIR_TO_REFERENCE,
+ COLORSPACE_DIR_FROM_REFERENCE
+ };
+
+ //!cpp:type::
+ enum TransformDirection
+ {
+ TRANSFORM_DIR_UNKNOWN = 0,
+ TRANSFORM_DIR_FORWARD,
+ TRANSFORM_DIR_INVERSE
+ };
+
+ //!cpp:type::
+ //
+ // Specify the interpolation type to use
+ // If the specified interpolation type is not supported in the requested
+ // context (for example, using tetrahedral interpolationon 1D luts)
+ // an exception will be throw.
+ //
+ // INTERP_BEST will choose the best interpolation type for the requested
+ // context:
+ //
+ // Lut1D INTERP_BEST: LINEAR
+ // Lut3D INTERP_BEST: LINEAR
+ //
+ // Note: INTERP_BEST is subject to change in minor releases, so if you
+ // care about locking off on a specific interpolation type, we'd recommend
+ // directly specifying it.
+
+ enum Interpolation
+ {
+ INTERP_UNKNOWN = 0,
+ INTERP_NEAREST = 1, //! nearest neighbor in all dimensions
+ INTERP_LINEAR = 2, //! linear interpolation in all dimensions
+ INTERP_TETRAHEDRAL = 3, //! tetrahedral interpolation in all directions
+ INTERP_BEST = 255 //! the 'best' suitable interpolation type
+ };
+
+ //!cpp:type::
+ enum BitDepth {
+ BIT_DEPTH_UNKNOWN = 0,
+ BIT_DEPTH_UINT8,
+ BIT_DEPTH_UINT10,
+ BIT_DEPTH_UINT12,
+ BIT_DEPTH_UINT14,
+ BIT_DEPTH_UINT16,
+ BIT_DEPTH_UINT32,
+ BIT_DEPTH_F16,
+ BIT_DEPTH_F32
+ };
+
+ //!cpp:type::
+ enum Allocation {
+ ALLOCATION_UNKNOWN = 0,
+ ALLOCATION_UNIFORM,
+ ALLOCATION_LG2
+ };
+
+ //!cpp:type:: Used when there is a choice of hardware shader language.
+ enum GpuLanguage
+ {
+ GPU_LANGUAGE_UNKNOWN = 0,
+ GPU_LANGUAGE_CG, ///< Nvidia Cg shader
+ GPU_LANGUAGE_GLSL_1_0, ///< OpenGL Shading Language
+ GPU_LANGUAGE_GLSL_1_3 ///< OpenGL Shading Language
+ };
+
+
+ //!rst::
+ // Conversion
+ // **********
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * BoolToString(bool val);
+ //!cpp:function::
+ extern OCIOEXPORT bool BoolFromString(const char * s);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * LoggingLevelToString(LoggingLevel level);
+ //!cpp:function::
+ extern OCIOEXPORT LoggingLevel LoggingLevelFromString(const char * s);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * TransformDirectionToString(TransformDirection dir);
+ //!cpp:function::
+ extern OCIOEXPORT TransformDirection TransformDirectionFromString(const char * s);
+
+ //!cpp:function::
+ extern OCIOEXPORT TransformDirection GetInverseTransformDirection(TransformDirection dir);
+ //!cpp:function::
+ extern OCIOEXPORT TransformDirection CombineTransformDirections(TransformDirection d1,
+ TransformDirection d2);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * ColorSpaceDirectionToString(ColorSpaceDirection dir);
+ //!cpp:function::
+ extern OCIOEXPORT ColorSpaceDirection ColorSpaceDirectionFromString(const char * s);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * BitDepthToString(BitDepth bitDepth);
+ //!cpp:function::
+ extern OCIOEXPORT BitDepth BitDepthFromString(const char * s);
+ //!cpp:function::
+ extern OCIOEXPORT bool BitDepthIsFloat(BitDepth bitDepth);
+ //!cpp:function::
+ extern OCIOEXPORT int BitDepthToInt(BitDepth bitDepth);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * AllocationToString(Allocation allocation);
+ //!cpp:function::
+ extern OCIOEXPORT Allocation AllocationFromString(const char * s);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * InterpolationToString(Interpolation interp);
+ //!cpp:function::
+ extern OCIOEXPORT Interpolation InterpolationFromString(const char * s);
+
+ //!cpp:function::
+ extern OCIOEXPORT const char * GpuLanguageToString(GpuLanguage language);
+ //!cpp:function::
+ extern OCIOEXPORT GpuLanguage GpuLanguageFromString(const char * s);
+
+
+ /*!rst::
+ Roles
+ *****
+
+ ColorSpace Roles are used so that plugins, in addition to this API can have
+ abstract ways of asking for common colorspaces, without referring to them
+ by hardcoded names.
+
+ Internal::
+
+ GetGPUDisplayTransform - (ROLE_SCENE_LINEAR (fstop exposure))
+ (ROLE_COLOR_TIMING (ASCColorCorrection))
+
+ External Plugins (currently known)::
+
+ Colorpicker UIs - (ROLE_COLOR_PICKING)
+ Compositor LogConvert - (ROLE_SCENE_LINEAR, ROLE_COMPOSITING_LOG)
+
+ */
+
+ //!rst::
+ // .. c:var:: const char* ROLE_DEFAULT
+ //
+ // "default"
+ extern OCIOEXPORT const char * ROLE_DEFAULT;
+ //!rst::
+ // .. c:var:: const char* ROLE_REFERENCE
+ //
+ // "reference"
+ extern OCIOEXPORT const char * ROLE_REFERENCE;
+ //!rst::
+ // .. c:var:: const char* ROLE_DATA
+ //
+ // "data"
+ extern OCIOEXPORT const char * ROLE_DATA;
+ //!rst::
+ // .. c:var:: const char* ROLE_COLOR_PICKING
+ //
+ // "color_picking"
+ extern OCIOEXPORT const char * ROLE_COLOR_PICKING;
+ //!rst::
+ // .. c:var:: const char* ROLE_SCENE_LINEAR
+ //
+ // "scene_linear"
+ extern OCIOEXPORT const char * ROLE_SCENE_LINEAR;
+ //!rst::
+ // .. c:var:: const char* ROLE_COMPOSITING_LOG
+ //
+ // "compositing_log"
+ extern OCIOEXPORT const char * ROLE_COMPOSITING_LOG;
+ //!rst::
+ // .. c:var:: const char* ROLE_COLOR_TIMING
+ //
+ // "color_timing"
+ extern OCIOEXPORT const char * ROLE_COLOR_TIMING;
+ //!rst::
+ // .. c:var:: const char* ROLE_TEXTURE_PAINT
+ //
+ // This role defines the transform for painting textures. In some
+ // workflows this is just a inverse display gamma with some limits
+ extern OCIOEXPORT const char * ROLE_TEXTURE_PAINT;
+ //!rst::
+ // .. c:var:: const char* ROLE_MATTE_PAINT
+ //
+ // This role defines the transform for matte painting. In some workflows
+ // this is a 1D HDR to LDR allocation. It is normally combined with
+ // another display transform in the host app for preview.
+ extern OCIOEXPORT const char * ROLE_MATTE_PAINT;
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/export/PyOpenColorIO/PyOpenColorIO.h b/export/PyOpenColorIO/PyOpenColorIO.h
new file mode 100644
index 0000000..2cb50cc
--- /dev/null
+++ b/export/PyOpenColorIO/PyOpenColorIO.h
@@ -0,0 +1,98 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYOCIO_H
+#define INCLUDED_PYOCIO_PYOCIO_H
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // ColorSpace
+ PyObject * BuildConstPyColorSpace(ConstColorSpaceRcPtr colorSpace);
+ PyObject * BuildEditablePyColorSpace(ColorSpaceRcPtr colorSpace);
+ bool IsPyColorSpace(PyObject * pyobject);
+ bool IsPyColorSpaceEditable(PyObject * pyobject);
+ ConstColorSpaceRcPtr GetConstColorSpace(PyObject * pyobject, bool allowCast);
+ ColorSpaceRcPtr GetEditableColorSpace(PyObject * pyobject);
+
+ // Config
+ PyObject * BuildConstPyConfig(ConstConfigRcPtr config);
+ PyObject * BuildEditablePyConfig(ConfigRcPtr config);
+ bool IsPyConfig(PyObject * config);
+ bool IsPyConfigEditable(PyObject * config);
+ ConstConfigRcPtr GetConstConfig(PyObject * config, bool allowCast);
+ ConfigRcPtr GetEditableConfig(PyObject * config);
+
+ // Context
+ PyObject * BuildConstPyContext(ConstContextRcPtr context);
+ PyObject * BuildEditablePyContext(ContextRcPtr context);
+ bool IsPyContext(PyObject * config);
+ bool IsPyContextEditable(PyObject * config);
+ ConstContextRcPtr GetConstContext(PyObject * context, bool allowCast);
+ ContextRcPtr GetEditableContext(PyObject * context);
+
+ // Exception
+ // Warning: these cannot return valid PyObject pointers before
+ // the python module has been initialized. Beware of calling these
+ // at static construction time.
+ PyObject * GetExceptionPyType();
+ PyObject * GetExceptionMissingFilePyType();
+
+ // Processor
+ PyObject * BuildConstPyProcessor(ConstProcessorRcPtr processor);
+ bool IsPyProcessor(PyObject * pyobject);
+ ConstProcessorRcPtr GetConstProcessor(PyObject * pyobject);
+
+ // ProcessorMetadata
+ PyObject * BuildConstPyProcessorMetadata(ConstProcessorMetadataRcPtr metadata);
+ bool IsPyProcessorMetadata(PyObject * pyobject);
+ ConstProcessorMetadataRcPtr GetConstProcessorMetadata(PyObject * pyobject);
+
+ // Transform
+ PyObject * BuildConstPyTransform(ConstTransformRcPtr transform);
+ PyObject * BuildEditablePyTransform(TransformRcPtr transform);
+ bool IsPyTransform(PyObject * pyobject);
+ bool IsPyTransformEditable(PyObject * pyobject);
+ ConstTransformRcPtr GetConstTransform(PyObject * pyobject, bool allowCast);
+ TransformRcPtr GetEditableTransform(PyObject * pyobject);
+
+ // Look
+ PyObject * BuildConstPyLook(ConstLookRcPtr look);
+ PyObject * BuildEditablePyLook(LookRcPtr look);
+ bool IsPyLook(PyObject * pyobject);
+ bool IsPyLookEditable(PyObject * pyobject);
+ ConstLookRcPtr GetConstLook(PyObject * pyobject, bool allowCast);
+ LookRcPtr GetEditableLook(PyObject * pyobject);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/export/pkgconfig/OpenColorIO.pc.in b/export/pkgconfig/OpenColorIO.pc.in
new file mode 100644
index 0000000..81ab4ce
--- /dev/null
+++ b/export/pkgconfig/OpenColorIO.pc.in
@@ -0,0 +1,10 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_EXEC_PREFIX@
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib@LIB_SUFFIX@
+
+Name: OpenColorIO
+Description: A color management framework for visual effects and animation
+Version: @OCIO_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lOpenColorIO
diff --git a/share/cmake/FindNuke.cmake b/share/cmake/FindNuke.cmake
new file mode 100644
index 0000000..79320b1
--- /dev/null
+++ b/share/cmake/FindNuke.cmake
@@ -0,0 +1,96 @@
+#==========
+#
+# Copyright (c) 2010, Dan Bethell.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Dan Bethell nor the names of any
+# other contributors to this software may be used to endorse or
+# promote products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#==========
+#
+# Variables defined by this module:
+# Nuke_FOUND
+# Nuke_INCLUDE_DIR
+# Nuke_COMPILE_FLAGS
+# Nuke_LINK_FLAGS
+# Nuke_LIBRARIES
+# Nuke_LIBRARY_DIR
+#
+# Usage:
+# FIND_PACKAGE( Nuke )
+# FIND_PACKAGE( Nuke REQUIRED )
+#
+# Note:
+# You can tell the module where Nuke is installed by setting
+# the NUKE_INSTALL_PATH (or setting the NDK_PATH environment
+# variable before calling FIND_PACKAGE.
+#
+# E.g.
+# SET( NUKE_INSTALL_PATH "/usr/local/Nuke5.2v3" )
+# FIND_PACKAGE( Nuke REQUIRED )
+#
+#==========
+
+# our includes
+FIND_PATH( Nuke_INCLUDE_DIR DDImage/Op.h
+ $ENV{NDK_PATH}/include
+ ${NUKE_INSTALL_PATH}/include
+ )
+
+# our library
+FIND_LIBRARY( Nuke_LIBRARIES DDImage
+ $ENV{NDK_PATH}
+ ${NUKE_INSTALL_PATH}
+ )
+
+SET( Nuke_COMPILE_FLAGS "" )
+SET( Nuke_LINK_FLAGS "" )
+IF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" )
+ SET( Nuke_COMPILE_FLAGS "-arch i386" )
+ SET( Nuke_LINK_FLAGS "-arch i386" )
+ENDIF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" )
+
+# our library path
+GET_FILENAME_COMPONENT( Nuke_LIBRARY_DIR ${Nuke_LIBRARIES} PATH )
+
+# did we find everything?
+INCLUDE( FindPackageHandleStandardArgs )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( "Nuke" DEFAULT_MSG
+ Nuke_INCLUDE_DIR
+ Nuke_LIBRARIES
+ Nuke_LIBRARY_DIR
+ )
+
+SET( Nuke_API_VERSION "" )
+IF( NUKE_FOUND )
+ TRY_RUN(NUKE_VERSION_EXITCODE NUKE_VERSION_COMPILED
+ ${CMAKE_BINARY_DIR} ${CMAKE_MODULE_PATH}/TestForDDImageVersion.cxx
+ COMPILE_DEFINITIONS "-I${Nuke_INCLUDE_DIR}"
+ RUN_OUTPUT_VARIABLE Nuke_API_VERSION)
+ message(STATUS "Nuke_API_VERSION: --${Nuke_API_VERSION}--")
+ENDIF()
diff --git a/share/cmake/FindTinyXML.cmake b/share/cmake/FindTinyXML.cmake
new file mode 100644
index 0000000..7e54cc0
--- /dev/null
+++ b/share/cmake/FindTinyXML.cmake
@@ -0,0 +1,59 @@
+# Find the tinyxml XML parsing library.
+#
+# Sets the usual variables expected for find_package scripts:
+#
+# TINYXML_INCLUDE_DIRS - header location
+# TINYXML_LIBRARIES - library to link against
+# TINYXML_FOUND - true if tinyxml was found.
+# TINYXML_MAJOR_VERSION
+# TINYXML_MINOR_VERSION
+# TINYXML_PATCH_VERSION
+# TINYXML_VERSION
+
+find_path(TINYXML_INCLUDE_DIR tinyxml.h)
+find_library(TINYXML_LIBRARY NAMES tinyxml)
+
+# Try to get the tinyxml version from the header file.
+if(TINYXML_INCLUDE_DIR)
+ set(_tixml_header ${TINYXML_INCLUDE_DIR}/tinyxml.h)
+ file(READ ${_tixml_header} _contents)
+ if(_contents)
+ string(REGEX MATCH "const int TIXML_MAJOR_VERSION = ([0-9]+);" _TMP_major "${_contents}")
+ string(REGEX REPLACE ".*([0-9]+).*" "\\1" _OUT_major "${_TMP_major}")
+ string(REGEX MATCH "const int TIXML_MINOR_VERSION = ([0-9]+);" _TMP_minor "${_contents}")
+ string(REGEX REPLACE ".*([0-9]+).*" "\\1" _OUT_minor "${_TMP_minor}")
+ string(REGEX MATCH "const int TIXML_PATCH_VERSION = ([0-9]+);" _TMP_patch "${_contents}")
+ string(REGEX REPLACE ".*([0-9]+).*" "\\1" _OUT_patch "${_TMP_patch}")
+
+ if(NOT ${_OUT_major} MATCHES "[0-9]+")
+ message(FATAL_ERROR "Version parsing failed for TIXML_MAJOR_VERSION!")
+ endif()
+ if(NOT ${_OUT_minor} MATCHES "[0-9]+")
+ message(FATAL_ERROR "Version parsing failed for TIXML_MINOR_VERSION!")
+ endif()
+ if(NOT ${_OUT_patch} MATCHES "[0-9]+")
+ message(FATAL_ERROR "Version parsing failed for TIXML_MICRO_VERSION!")
+ endif()
+
+ set(TINYXML_MAJOR_VERSION ${_OUT_major})
+ set(TINYXML_MINOR_VERSION ${_OUT_minor})
+ set(TINYXML_PATCH_VERSION ${_OUT_patch})
+ set(TINYXML_VERSION ${TINYXML_MAJOR_VERSION}.${TINYXML_MINOR_VERSION}.${TINYXML_PATCH_VERSION})
+ else()
+ message(FATAL_ERROR "Include file ${_tixml_header} does not exist")
+ endif()
+endif()
+
+# Support the REQUIRED and QUIET arguments, and set TINYXML_FOUND if found.
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS (TinyXML DEFAULT_MSG TINYXML_LIBRARY
+ TINYXML_INCLUDE_DIR)
+
+message(STATUS "TinyXML version: ${TINYXML_VERSION}")
+
+if(TINYXML_FOUND)
+ set(TINYXML_LIBRARIES ${TINYXML_LIBRARY})
+ set(TINYXML_INCLUDE_DIRS ${TINYXML_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(TINYXML_LIBRARY TINYXML_INCLUDE_DIR)
diff --git a/share/cmake/FindTruelight.cmake b/share/cmake/FindTruelight.cmake
new file mode 100644
index 0000000..5d437b2
--- /dev/null
+++ b/share/cmake/FindTruelight.cmake
@@ -0,0 +1,87 @@
+#==========
+#
+# Copyright (c) 2011, Malcolm Humphreys.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Dan Bethell nor the names of any
+# other contributors to this software may be used to endorse or
+# promote products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#==========
+#
+# Variables defined by this module:
+# Truelight_FOUND
+# Truelight_INCLUDE_DIR
+# Truelight_COMPILE_FLAGS
+# Truelight_LINK_FLAGS
+# Truelight_LIBRARIES
+# Truelight_LIBRARY_DIR
+#
+# Usage:
+# FIND_PACKAGE( Truelight )
+# FIND_PACKAGE( Truelight REQUIRED )
+#
+# Note:
+# You can tell the module where Truelight is installed by setting
+# the TRUELIGHT_INSTALL_PATH (or setting the TRUELIGHT_ROOT environment
+# variable before calling FIND_PACKAGE.
+#
+# E.g.
+# SET( TRUELIGHT_INSTALL_PATH "/usr/fl/truelight" )
+# FIND_PACKAGE( Truelight REQUIRED )
+#
+#==========
+
+# our includes
+FIND_PATH( Truelight_INCLUDE_DIR truelight.h
+ $ENV{TRUELIGHT_ROOT}/include
+ ${TRUELIGHT_INSTALL_PATH}/include
+ )
+
+# our library
+FIND_LIBRARY( Truelight_LIBRARIES libtruelight.a
+ $ENV{TRUELIGHT_ROOT}/lib
+ ${TRUELIGHT_INSTALL_PATH}/lib
+ )
+
+SET( Truelight_COMPILE_FLAGS "" )
+SET( Truelight_LINK_FLAGS "" )
+IF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" )
+ SET( Truelight_COMPILE_FLAGS "" )
+ SET( Truelight_LINK_FLAGS "-framework CoreServices -framework IOKit" )
+ENDIF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" )
+
+# our library path
+GET_FILENAME_COMPONENT( Truelight_LIBRARY_DIR ${Truelight_LIBRARIES} PATH )
+
+# did we find everything?
+INCLUDE( FindPackageHandleStandardArgs )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( "Truelight" DEFAULT_MSG
+ Truelight_INCLUDE_DIR
+ Truelight_LIBRARIES
+ Truelight_LIBRARY_DIR
+ )
diff --git a/share/cmake/OCIOMacros.cmake b/share/cmake/OCIOMacros.cmake
new file mode 100644
index 0000000..daf2c67
--- /dev/null
+++ b/share/cmake/OCIOMacros.cmake
@@ -0,0 +1,339 @@
+MACRO(messageonce MSG)
+ if(CMAKE_FIRST_RUN)
+ message(STATUS ${MSG})
+ endif()
+ENDMACRO()
+
+MACRO(OCIOFindOpenGL)
+ if(APPLE)
+ INCLUDE_DIRECTORIES(/System/Library/Frameworks)
+ endif()
+
+ # Find OpenGL
+ find_package(OpenGL)
+ if(OPENGL_FOUND)
+ message(STATUS "Found OpenGL library ${OPENGL_LIBRARY}")
+ message(STATUS "Found OpenGL includes ${OPENGL_INCLUDE_DIR}")
+ else()
+ message(STATUS "OpenGL not found")
+ endif()
+
+ # Find GLUT
+ find_package(GLUT)
+ if(GLUT_FOUND)
+ message(STATUS "Found GLUT library ${GLUT_LIBRARY}")
+ else()
+ message(STATUS "GLUT not found")
+ endif()
+
+ # Find GLEW
+ set(GLEW_VERSION 1.5.1)
+ FIND_PATH(GLEW_INCLUDES GL/glew.h
+ /usr/include
+ /usr/local/include
+ /sw/include
+ /opt/local/include
+ DOC "The directory where GL/glew.h resides")
+ FIND_LIBRARY(GLEW_LIBRARIES
+ NAMES GLEW glew
+ /usr/lib64
+ /usr/lib
+ /usr/local/lib64
+ /usr/local/lib
+ /sw/lib
+ /opt/local/lib
+ PATHS
+ DOC "The GLEW library")
+ if(GLEW_INCLUDES AND GLEW_LIBRARIES)
+ set(GLEW_FOUND TRUE)
+ message(STATUS "Found GLEW library ${GLEW_LIBRARIES}")
+ message(STATUS "Found GLEW includes ${GLEW_INCLUDES}")
+ else()
+ message(STATUS "GLEW not found")
+ set(GLEW_FOUND FALSE)
+ endif()
+ENDMACRO()
+
+MACRO(OCIOFindOpenImageIO)
+ if(OIIO_PATH)
+ message(STATUS "OIIO path explicitly specified: ${OIIO_PATH}")
+ endif()
+ if(OIIO_INCLUDE_PATH)
+ message(STATUS "OIIO INCLUDE_PATH explicitly specified: ${OIIO_INCLUDE_PATH}")
+ endif()
+ if(OIIO_LIBRARY_PATH)
+ message(STATUS "OIIO LIBRARY_PATH explicitly specified: ${OIIO_LIBRARY_PATH}")
+ endif()
+ FIND_PATH( OIIO_INCLUDES OpenImageIO/version.h
+ ${OIIO_INCLUDE_PATH}
+ ${OIIO_PATH}/include/
+ /usr/include
+ /usr/local/include
+ /sw/include
+ /opt/local/include
+ DOC "The directory where OpenImageIO/version.h resides")
+ FIND_LIBRARY(OIIO_LIBRARIES
+ NAMES OIIO OpenImageIO
+ PATHS
+ ${OIIO_LIBRARY_PATH}
+ ${OIIO_PATH}/lib/
+ /usr/lib64
+ /usr/lib
+ /usr/local/lib64
+ /usr/local/lib
+ /sw/lib
+ /opt/local/lib
+ DOC "The OIIO library")
+
+ if(OIIO_INCLUDES AND OIIO_LIBRARIES)
+ set(OIIO_FOUND TRUE)
+ message(STATUS "Found OIIO library ${OIIO_LIBRARIES}")
+ message(STATUS "Found OIIO includes ${OIIO_INCLUDES}")
+ else()
+ set(OIIO_FOUND FALSE)
+ message(STATUS "OIIO not found. Specify OIIO_PATH to locate it")
+ endif()
+ENDMACRO()
+
+MACRO(OCIOFindPython)
+ # Set the default python runtime
+ if(NOT PYTHON)
+ set(PYHELP "path to Python executable (also used to find headers against which to compile Python bindings)")
+ set(PYTHON_HEADER Python.h)
+ set(PYTHON python CACHE FILEPATH ${PYHELP} FORCE)
+ endif(NOT PYTHON)
+
+ if(CMAKE_FIRST_RUN)
+ message(STATUS "Setting python bin to: ${PYTHON}")
+ endif()
+
+ set(PYTHON_OK YES) # OK until something goes wrong
+
+ # Get Python version
+ execute_process(COMMAND ${PYTHON} -c "from distutils import sysconfig; print sysconfig.get_python_version()"
+ OUTPUT_VARIABLE PYTHON_VERSION
+ RESULT_VARIABLE PYTHON_RETURNVALUE
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ if(${PYTHON_RETURNVALUE} EQUAL 0)
+ # Everything is fine
+ else()
+ # TODO: These error strings clobber previous values
+ set(PYTHON_ERR "${PYTHON} returned ${PYTHON_RETURNVALUE} trying to determine version number.")
+ set(PYTHON_OK NO)
+ endif()
+
+
+ # Determine Python UCS version
+ execute_process(COMMAND ${PYTHON} -c "import sys; print sys.maxunicode > 65536 and 'ucs4' or 'ucs2'"
+ OUTPUT_VARIABLE PYTHON_UCS
+ RESULT_VARIABLE PYTHON_RETURNVALUE
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ if(${PYTHON_RETURNVALUE} EQUAL 0)
+ # Hurray
+ else()
+ set(PYTHON_OK NO)
+ set(PYTHON_ERR "${PYTHON} returned ${PYTHON_RETURNVALUE} trying to determine UCS version.")
+ endif()
+
+
+ # Locate headers
+ execute_process(COMMAND ${PYTHON} -c "from distutils import sysconfig; print ':'.join(set(sysconfig.get_config_var('INCLDIRSTOMAKE').split()))"
+ OUTPUT_VARIABLE PYTHON_INCLUDE_RAW
+ RESULT_VARIABLE PYTHON_RETURNVALUE
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ # Handle errors, and process include path
+ if(${PYTHON_RETURNVALUE} EQUAL 0)
+ file(TO_CMAKE_PATH "${PYTHON_INCLUDE_RAW}" PYTHON_INCLUDE)
+ else()
+ set(PYTHON_ERR "${PYTHON} returned ${PYTHON_RETURNVALUE} trying to determine header location.")
+ set(PYTHON_OK NO)
+ endif()
+
+
+ # Locate Python library
+ execute_process(COMMAND ${PYTHON} -c "from distutils import sysconfig; print ':'.join(set(sysconfig.get_config_var('LIBPL').split()))"
+ OUTPUT_VARIABLE PYTHON_LIBRARY_DIRS_RAW
+ RESULT_VARIABLE PYTHON_RETURNVALUE
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ # Handle errors, and process include path
+ if(${PYTHON_RETURNVALUE} EQUAL 0)
+ file(TO_CMAKE_PATH "${PYTHON_LIBRARY_DIRS_RAW}" PYTHON_LIBRARY_DIRS)
+
+ FIND_LIBRARY(PYTHON_LIBRARY
+ NAMES "python${PYTHON_VERSION}"
+ PATHS ${PYTHON_LIBRARY_DIRS}
+ NO_DEFAULT_PATH # Don't be "helpful" and randomly grab library from /usr/lib etc
+ )
+ message("Python library: ${PYTHON_LIBRARY}")
+ else()
+ set(PYTHON_ERR "${PYTHON} returned ${PYTHON_RETURNVALUE} trying to determine library path.")
+ set(PYTHON_OK NO)
+ endif()
+
+ # Construct variant path - a path that sufficiently identifies the
+ # ABI-compatbility of the built library. See Github issue #236
+ if(OCIO_PYGLUE_RESPECT_ABI)
+ # Respect Python major/minor version, and UCS version (unicode
+ # content system). E.g install into "lib/python2.6/ucs4/site-packages"
+ set(PYTHON_VARIANT_PATH "lib${LIB_SUFFIX}/python${PYTHON_VERSION}/${PYTHON_UCS}/site-packages")
+ else()
+ # Ignore UCS value and install into lib/python2.6/site-packages dir
+ set(PYTHON_VARIANT_PATH "lib${LIB_SUFFIX}/python${PYTHON_VERSION}/site-packages")
+ endif()
+
+ENDMACRO()
+
+MACRO(OCIOFindJava)
+ if(APPLE)
+
+ SET(_JAVA_HINTS $ENV{JAVA_HOME}/bin)
+ SET(_JAVA_PATHS /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands)
+
+ FIND_PROGRAM(Java_JAVA_EXECUTABLE
+ NAMES java
+ HINTS ${_JAVA_HINTS}
+ PATHS ${_JAVA_PATHS}
+ )
+
+ IF(Java_JAVA_EXECUTABLE)
+ EXECUTE_PROCESS(COMMAND ${Java_JAVA_EXECUTABLE} -version
+ RESULT_VARIABLE res
+ OUTPUT_VARIABLE var
+ ERROR_VARIABLE var # sun-java output to stderr
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_STRIP_TRAILING_WHITESPACE)
+ IF( res )
+ IF(${Java_FIND_REQUIRED})
+ MESSAGE( FATAL_ERROR "Error executing java -version" )
+ ELSE()
+ MESSAGE( STATUS "Warning, could not run java --version")
+ ENDIF()
+ ELSE()
+ # extract major/minor version and patch level from "java -version" output
+ # Tested on linux using
+ # 1. Sun / Sun OEM
+ # 2. OpenJDK 1.6
+ # 3. GCJ 1.5
+ # 4. Kaffe 1.4.2
+ IF(var MATCHES "java version \"[0-9]+\\.[0-9]+\\.[0-9_.]+[oem-]*\".*")
+ # This is most likely Sun / OpenJDK, or maybe GCJ-java compat layer
+ STRING( REGEX REPLACE ".* version \"([0-9]+\\.[0-9]+\\.[0-9_.]+)[oem-]*\".*"
+ "\\1" Java_VERSION_STRING "${var}" )
+ ELSEIF(var MATCHES "java full version \"kaffe-[0-9]+\\.[0-9]+\\.[0-9_]+\".*")
+ # Kaffe style
+ STRING( REGEX REPLACE "java full version \"kaffe-([0-9]+\\.[0-9]+\\.[0-9_]+).*"
+ "\\1" Java_VERSION_STRING "${var}" )
+ ELSE()
+ IF(NOT Java_FIND_QUIETLY)
+ message(WARNING "regex not supported: ${var}. Please report")
+ ENDIF(NOT Java_FIND_QUIETLY)
+ ENDIF()
+ STRING( REGEX REPLACE "([0-9]+).*" "\\1" Java_VERSION_MAJOR "${Java_VERSION_STRING}" )
+ STRING( REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" Java_VERSION_MINOR "${Java_VERSION_STRING}" )
+ STRING( REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" Java_VERSION_PATCH "${Java_VERSION_STRING}" )
+ # warning tweak version can be empty:
+ STRING( REGEX REPLACE "[0-9]+\\.[0-9]+\\.[0-9]+\\_?\\.?([0-9]*)$" "\\1" Java_VERSION_TWEAK "${Java_VERSION_STRING}" )
+ if( Java_VERSION_TWEAK STREQUAL "" ) # check case where tweak is not defined
+ set(Java_VERSION ${Java_VERSION_MAJOR}.${Java_VERSION_MINOR}.${Java_VERSION_PATCH})
+ else( )
+ set(Java_VERSION ${Java_VERSION_MAJOR}.${Java_VERSION_MINOR}.${Java_VERSION_PATCH}.${Java_VERSION_TWEAK})
+ endif( )
+ ENDIF()
+ ENDIF(Java_JAVA_EXECUTABLE)
+
+ FIND_PROGRAM(Java_JAR_EXECUTABLE
+ NAMES jar
+ HINTS ${_JAVA_HINTS}
+ PATHS ${_JAVA_PATHS}
+ )
+
+ FIND_PROGRAM(Java_JAVAC_EXECUTABLE
+ NAMES javac
+ HINTS ${_JAVA_HINTS}
+ PATHS ${_JAVA_PATHS}
+ )
+
+ FIND_PROGRAM(Java_JAVAH_EXECUTABLE
+ NAMES javah
+ HINTS ${_JAVA_HINTS}
+ PATHS ${_JAVA_PATHS}
+ )
+
+ FIND_PROGRAM(Java_JAVADOC_EXECUTABLE
+ NAMES javadoc
+ HINTS ${_JAVA_HINTS}
+ PATHS ${_JAVA_PATHS}
+ )
+
+ # Check for everything
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(Java
+ REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
+ Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE Java_VERSION)
+ set(Java_FOUND TRUE)
+
+ find_package(JNI)
+
+ else()
+
+ find_package(Java)
+ find_package(JNI)
+
+ endif()
+
+ENDMACRO()
+
+MACRO(ExtractRstCPP INFILE OUTFILE)
+ add_custom_command(
+ OUTPUT ${OUTFILE}
+ COMMAND ${CMAKE_SOURCE_DIR}/share/sphinx/ExtractRstFromSourceCPP.py ${INFILE} ${OUTFILE}
+ DEPENDS ${INFILE}
+ COMMENT "Extracting reStructuredText from ${INFILE} (using old process)"
+ )
+ENDMACRO()
+
+MACRO(ExtractRstSimple INFILE OUTFILE)
+ add_custom_command(
+ OUTPUT ${OUTFILE}
+ COMMAND ${CMAKE_SOURCE_DIR}/share/sphinx/ExtractRstFromSourceSimple.py ${INFILE} ${OUTFILE}
+ DEPENDS ${INFILE}
+ COMMENT "Extracting reStructuredText from ${INFILE}"
+ )
+ENDMACRO()
+
+
+MACRO(CopyFiles TARGET)
+ # parse the macro arguments
+ PARSE_ARGUMENTS(COPYFILES
+ "OUTDIR;"
+ "NOTUSED" ${ARGN})
+
+ # get the list of sources from the args
+ set(FILES ${COPYFILES_DEFAULT_ARGS})
+
+ # find the shader compiler
+ if(NOT COPYFILES_OUTDIR)
+ set(COPYFILES_OUTDIR ${CMAKE_CURRENT_BINARY_DIR})
+ endif()
+
+ set(${TARGET}_OUTPUT)
+ foreach(FILE ${FILES})
+ get_filename_component(_FILE_NAME ${FILE} NAME)
+ set(OUTFILENAME "${COPYFILES_OUTDIR}/${_FILE_NAME}")
+ list(APPEND ${TARGET}_OUTPUT ${OUTFILENAME})
+ add_custom_command(
+ OUTPUT ${OUTFILENAME}
+ COMMAND ${CMAKE_COMMAND} -E copy ${FILE} ${OUTFILENAME}
+ DEPENDS ${FILE}
+ COMMENT "Copying file ${FILE}\n to ${OUTFILENAME}"
+ )
+ endforeach()
+ENDMACRO()
diff --git a/share/cmake/ParseArguments.cmake b/share/cmake/ParseArguments.cmake
new file mode 100644
index 0000000..3e9c947
--- /dev/null
+++ b/share/cmake/ParseArguments.cmake
@@ -0,0 +1,57 @@
+#-------------------------------------------------------------------------------
+# The PARSE_ARGUMENTS macro will take the arguments of another macro and define
+# several variables. The first argument to PARSE_ARGUMENTS is a prefix to put
+# on all variables it creates. The second argument is a list of names, and the
+# third argument is a list of options. Both of these lists should be quoted.
+# The rest of the PARSE_ARGUMENTS args are arguments from another macro to be
+# parsed.
+#
+# PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...)
+#
+# For each item in options, PARSE_ARGUMENTS will create a variable with that
+# name, prefixed with prefix_. So, for example, if prefix is MY_MACRO and
+# options is OPTION1;OPTION2, then PARSE_ARGUMENTS will create the variables
+# MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These variables will be set to true if
+# the option exists in the command line or false otherwise.
+#
+# For each item in arg_names, PARSE_ARGUMENTS will create a variable with that
+# name, prefixed with prefix_. Each variable will be filled with the arguments
+# that occur after the given arg_name is encountered up to the next arg_name or
+# the end of the arguments. All options are removed from these lists.
+# PARSE_ARGUMENTS also creates a prefix_DEFAULT_ARGS variable containing the
+# list of all arguments up to the first arg_name encountered.
+#
+# Downloaded from: http://www.itk.org/Wiki/CMakeMacroParseArguments
+#
+
+cmake_minimum_required(VERSION 2.4.7)
+
+MACRO(PARSE_ARGUMENTS prefix arg_names option_names)
+ SET(DEFAULT_ARGS)
+ FOREACH(arg_name ${arg_names})
+ SET(${prefix}_${arg_name})
+ ENDFOREACH(arg_name)
+ FOREACH(option ${option_names})
+ SET(${prefix}_${option} FALSE)
+ ENDFOREACH(option)
+ SET(current_arg_name DEFAULT_ARGS)
+ SET(current_arg_list)
+ FOREACH(arg ${ARGN})
+ SET(larg_names ${arg_names})
+ LIST(FIND larg_names "${arg}" is_arg_name)
+ IF (is_arg_name GREATER -1)
+ SET(${prefix}_${current_arg_name} ${current_arg_list})
+ SET(current_arg_name ${arg})
+ SET(current_arg_list)
+ ELSE (is_arg_name GREATER -1)
+ SET(loption_names ${option_names})
+ LIST(FIND loption_names "${arg}" is_option)
+ IF (is_option GREATER -1)
+ SET(${prefix}_${arg} TRUE)
+ ELSE (is_option GREATER -1)
+ SET(current_arg_list ${current_arg_list} ${arg})
+ ENDIF (is_option GREATER -1)
+ ENDIF (is_arg_name GREATER -1)
+ ENDFOREACH(arg)
+ SET(${prefix}_${current_arg_name} ${current_arg_list})
+ENDMACRO(PARSE_ARGUMENTS)
diff --git a/share/cmake/TestForDDImageVersion.cxx b/share/cmake/TestForDDImageVersion.cxx
new file mode 100644
index 0000000..a94e2e0
--- /dev/null
+++ b/share/cmake/TestForDDImageVersion.cxx
@@ -0,0 +1,14 @@
+#include <iostream>
+#include "DDImage/ddImageVersionNumbers.h"
+int main(int, char*[])
+{
+ // Print a Nuke API identifier number, used to make the
+ // lib/nuke${API_NUMBER} directory
+
+ // Nuke aims to maintain API compatibilty between "v" releases, so
+ // compiling for 6.1v1 will work with 6.1v2 etc (but not
+ // 6.2v1). Only exception has been 5.1v5 and 5.1v6 (because it was
+ // supposed to be 5.2v1)
+ std::cout << kDDImageVersionMajorNum << "." << kDDImageVersionMinorNum;
+ return 0;
+}
diff --git a/share/cmake/andriod-toolchain.cmake b/share/cmake/andriod-toolchain.cmake
new file mode 100644
index 0000000..5ee3060
--- /dev/null
+++ b/share/cmake/andriod-toolchain.cmake
@@ -0,0 +1,61 @@
+
+set(NDK /Applications/android-ndk-r5b)
+set(NDK_LEVEL 9)
+set(NDK_ARCH arm)
+set(NDK_CPU_ABI armeabi-v7a) # armeabi, armeabi-v7a, x86
+
+set(NDK_SYSROOT ${NDK}/platforms/android-${NDK_LEVEL}/arch-${NDK_ARCH})
+set(NDK_TOOLCHAIN_PREFIX arm-linux-androideabi)
+set(NDK_TOOLCHAIN_NAME ${NDK_TOOLCHAIN_PREFIX}-4.4.3)
+set(NDK_TOOLCHAIN_SYSTEM darwin-x86)
+set(NDK_TOOLCHAIN ${NDK}/toolchains/${NDK_TOOLCHAIN_NAME}/prebuilt/${NDK_TOOLCHAIN_SYSTEM})
+
+set(CMAKE_FIND_ROOT_PATH "${NDK_TOOLCHAIN}" "${NDK_SYSROOT}" "${NDK}")
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+set(CMAKE_SYSTEM_NAME GNU)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_SYSTEM_PROCESSOR armv7-a)
+set(CMAKE_OSX_ARCHITECTURES armv7-a)
+
+set(CMAKE_C_COMPILER ${NDK_TOOLCHAIN_PREFIX}-gcc)
+set(CMAKE_CXX_COMPILER ${NDK_TOOLCHAIN_PREFIX}-g++)
+
+include_directories("${NDK}/sources/cxx-stl/gnu-libstdc++/libs/${NDK_CPU_ABI}/include")
+include_directories("${NDK}/sources/cxx-stl/gnu-libstdc++/include")
+include_directories("${NDK_SYSROOT}/usr/include")
+
+# TODO: work out if we need any of these compile flags
+# -DNDEBUG -MMD -MP -MF -fpic -ffunction-sections -funwind-tables
+# -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__
+# -D__ARM_ARCH_5TE__ -mtune=xscale -msoft-float -mthumb
+# -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi
+# -Wa,--noexecstack -Os -O2 -g
+
+set(NDK_COMPILE_FLAGS "-DANDROID -march=${CMAKE_SYSTEM_PROCESSOR} -mfloat-abi=softfp")
+
+# TODO: work out if we need any of these link flags
+# -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-z,noexecstack
+# -Wl,-rpath-link=${NDK_PLATFORM_ROOT}/usr/lib")
+
+set(NDK_LINK_FLAGS "-Wl,--fix-cortex-a8 --sysroot=${NDK_SYSROOT} -L${NDK_SYSROOT}/usr/lib -lsupc++ -lstdc++ -lm -lc -ldl")
+
+add_definitions(${NDK_COMPILE_FLAGS})
+set(CMAKE_C_LINK_FLAGS ${NDK_LINK_FLAGS})
+set(CMAKE_CXX_LINK_FLAGS ${NDK_LINK_FLAGS})
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(ANDROID TRUE)
+
+set(OCIO_BUILD_SHARED TRUE)
+set(OCIO_BUILD_STATIC FALSE)
+set(OCIO_BUILD_UNITTESTS FALSE)
+set(OCIO_BUILD_TRUELIGHT FALSE)
+set(OCIO_BUILD_TESTBED FALSE)
+set(OCIO_BUILD_APPS FALSE)
+set(OCIO_BUILD_NUKE FALSE)
+set(OCIO_BUILD_PYGLUE FALSE)
+set(OCIO_BUILD_JNIGLUE TRUE)
+set(OCIO_BUILD_SSE FALSE)
diff --git a/share/cmake/iPhone-armv6-toolchain.cmake b/share/cmake/iPhone-armv6-toolchain.cmake
new file mode 100644
index 0000000..27803e5
--- /dev/null
+++ b/share/cmake/iPhone-armv6-toolchain.cmake
@@ -0,0 +1,42 @@
+
+set(IPHONE_SDK "4.3")
+set(IPHONE_ROOT "/Developer/Platforms/iPhoneOS.platform/Developer")
+set(IPHONE_SDK_ROOT "${IPHONE_ROOT}/SDKs/iPhoneOS${IPHONE_SDK}.sdk")
+
+set(CMAKE_FIND_ROOT_PATH "${IPHONE_SDK_ROOT}" "${IPHONE_ROOT}")
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+set(CMAKE_SYSTEM_NAME "GNU")
+set(CMAKE_SYSTEM_PROCESSOR armv6)
+set(CMAKE_OSX_ARCHITECTURES armv6)
+
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+
+set(CMAKE_C_COMPILER gcc-4.2)
+set(CMAKE_CXX_COMPILER g++-4.2)
+
+add_definitions("-D__IPHONE__")
+add_definitions("-arch armv6 -pipe -no-cpp-precomp --sysroot=${IPHONE_SDK_ROOT} -miphoneos-version-min=${IPHONE_SDK}")
+set(CMAKE_C_LINK_FLAGS "-arch armv6 --isysroot=${IPHONE_SDK_ROOT} -miphoneos-version-min=${IPHONE_SDK} -L${IPHONE_SDK_ROOT}/usr/lib -L${IPHONE_SDK_ROOT}/usr/lib/system")
+set(CMAKE_CXX_LINK_FLAGS ${CMAKE_C_LINK_FLAGS})
+
+include_directories("${IPHONE_SDK_ROOT}/usr/include")
+include_directories("${IPHONE_SDK_ROOT}/usr/include/c++/4.2.1")
+include_directories("${IPHONE_SDK_ROOT}/usr/include/c++/4.2.1/armv6-apple-darwin10")
+
+link_directories("${IPHONE_SDK_ROOT}/usr/lib")
+link_directories("${IPHONE_SDK_ROOT}/usr/lib/system")
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(IPHONE TRUE)
+
+set(OCIO_BUILD_SHARED FALSE)
+set(OCIO_BUILD_STATIC TRUE)
+set(OCIO_BUILD_TRUELIGHT FALSE)
+set(OCIO_BUILD_TESTBED FALSE)
+set(OCIO_BUILD_APPS FALSE)
+set(OCIO_BUILD_NUKE FALSE)
+set(OCIO_BUILD_PYGLUE FALSE)
+set(OCIO_BUILD_SSE FALSE)
diff --git a/share/cmake/iPhone-toolchain.cmake b/share/cmake/iPhone-toolchain.cmake
new file mode 100644
index 0000000..70dd933
--- /dev/null
+++ b/share/cmake/iPhone-toolchain.cmake
@@ -0,0 +1,42 @@
+
+set(IPHONE_SDK "4.3")
+set(IPHONE_ROOT "/Developer/Platforms/iPhoneOS.platform/Developer")
+set(IPHONE_SDK_ROOT "${IPHONE_ROOT}/SDKs/iPhoneOS${IPHONE_SDK}.sdk")
+
+set(CMAKE_FIND_ROOT_PATH "${IPHONE_SDK_ROOT}" "${IPHONE_ROOT}")
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+set(CMAKE_SYSTEM_NAME "GNU")
+set(CMAKE_SYSTEM_PROCESSOR armv7)
+set(CMAKE_OSX_ARCHITECTURES armv7)
+
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+
+set(CMAKE_C_COMPILER gcc-4.2)
+set(CMAKE_CXX_COMPILER g++-4.2)
+
+add_definitions("-D__IPHONE__")
+add_definitions("-arch armv7 -pipe -no-cpp-precomp --sysroot=${IPHONE_SDK_ROOT} -miphoneos-version-min=${IPHONE_SDK}")
+set(CMAKE_C_LINK_FLAGS "-arch armv7 --isysroot=${IPHONE_SDK_ROOT} -miphoneos-version-min=${IPHONE_SDK} -L${IPHONE_SDK_ROOT}/usr/lib -L${IPHONE_SDK_ROOT}/usr/lib/system")
+set(CMAKE_CXX_LINK_FLAGS ${CMAKE_C_LINK_FLAGS})
+
+include_directories("${IPHONE_SDK_ROOT}/usr/include")
+include_directories("${IPHONE_SDK_ROOT}/usr/include/c++/4.2.1")
+include_directories("${IPHONE_SDK_ROOT}/usr/include/c++/4.2.1/armv7-apple-darwin10")
+
+link_directories("${IPHONE_SDK_ROOT}/usr/lib")
+link_directories("${IPHONE_SDK_ROOT}/usr/lib/system")
+
+set(CMAKE_CROSSCOMPILING TRUE)
+set(IPHONE TRUE)
+
+set(OCIO_BUILD_SHARED FALSE)
+set(OCIO_BUILD_STATIC TRUE)
+set(OCIO_BUILD_TRUELIGHT FALSE)
+set(OCIO_BUILD_APPS FALSE)
+set(OCIO_BUILD_NUKE FALSE)
+set(OCIO_BUILD_PYGLUE FALSE)
+set(OCIO_BUILD_JNIGLUE FALSE)
+set(OCIO_BUILD_SSE FALSE)
diff --git a/share/cmake/iPhoneSimulator-toolchain.cmake b/share/cmake/iPhoneSimulator-toolchain.cmake
new file mode 100644
index 0000000..07210b9
--- /dev/null
+++ b/share/cmake/iPhoneSimulator-toolchain.cmake
@@ -0,0 +1,43 @@
+
+set(IPHONE_SDK "4.3")
+set(IPHONE_ROOT "/Developer/Platforms/iPhoneSimulator.platform/Developer")
+set(IPHONE_SDK_ROOT "${IPHONE_ROOT}/SDKs/iPhoneSimulator${IPHONE_SDK}.sdk")
+
+set(CMAKE_FIND_ROOT_PATH "${IPHONE_SDK_ROOT}" "${IPHONE_ROOT}")
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_OSX_ARCHITECTURES i686)
+set(CMAKE_OSX_SYSROOT "${IPHONE_SDK_ROOT}")
+
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+
+set(CMAKE_C_COMPILER gcc-4.2)
+set(CMAKE_CXX_COMPILER g++-4.2)
+
+add_definitions("-D__IPHONE__")
+add_definitions("-arch i686 -pipe -no-cpp-precomp --sysroot=${IPHONE_SDK_ROOT} -miphoneos-version-min=${IPHONE_SDK}")
+set(CMAKE_C_LINK_FLAGS "-arch i686 --isysroot=${IPHONE_SDK_ROOT} -miphoneos-version-min=${IPHONE_SDK} -L${IPHONE_SDK_ROOT}/usr/lib -L${IPHONE_SDK_ROOT}/usr/lib/system")
+set(CMAKE_CXX_LINK_FLAGS ${CMAKE_C_LINK_FLAGS})
+
+include_directories("${IPHONE_SDK_ROOT}/usr/include")
+include_directories("${IPHONE_SDK_ROOT}/usr/include/c++/4.2.1")
+include_directories("${IPHONE_SDK_ROOT}/usr/include/c++/4.2.1/i686-apple-darwin10")
+
+link_directories("${IPHONE_SDK_ROOT}/usr/lib")
+link_directories("${IPHONE_SDK_ROOT}/usr/lib/system")
+
+set(IPHONE_BUILD TRUE)
+set(CMAKE_CROSSCOMPILING TRUE)
+
+set(OCIO_BUILD_SHARED FALSE)
+set(OCIO_BUILD_STATIC TRUE)
+set(OCIO_BUILD_TRUELIGHT FALSE)
+set(OCIO_BUILD_APPS FALSE)
+set(OCIO_BUILD_NUKE FALSE)
+set(OCIO_BUILD_PYGLUE FALSE)
+set(OCIO_BUILD_JNIGLUE FALSE)
+set(OCIO_BUILD_SSE FALSE)
diff --git a/share/nuke/examples/colorlookup_to_spi1d.py b/share/nuke/examples/colorlookup_to_spi1d.py
new file mode 100644
index 0000000..44fc8d6
--- /dev/null
+++ b/share/nuke/examples/colorlookup_to_spi1d.py
@@ -0,0 +1,24 @@
+
+def WriteSPI1D(filename, fromMin, fromMax, data):
+ f = file(filename,'w')
+ f.write("Version 1\n")
+ f.write("From %s %s\n" % (fromMin, fromMax))
+ f.write("Length %d\n" % len(data))
+ f.write("Components 1\n")
+ f.write("{\n")
+ for value in data:
+ f.write(" %s\n" % value)
+ f.write("}\n")
+ f.close()
+
+
+knob = nuke.selectedNode()['lut']
+
+SIZE = 2**10
+
+data = []
+for i in xrange(SIZE):
+ x = i/(SIZE-1.0)
+ data.append(knob.getValueAt(x))
+
+WriteSPI1D('/tmp/colorlookup.spi1d', 0.0, 1.0, data)
diff --git a/share/nuke/examples/ocio_to_colorlookup_all.py b/share/nuke/examples/ocio_to_colorlookup_all.py
new file mode 100644
index 0000000..84f23aa
--- /dev/null
+++ b/share/nuke/examples/ocio_to_colorlookup_all.py
@@ -0,0 +1,36 @@
+#import SpImport
+#OCIO = SpImport.SpComp2("PyOpenColorIO", 2)
+
+c = OCIO.GetCurrentConfig()
+
+cs_to_lin = c.getProcessor(OCIO.Constants.ROLE_COMPOSITING_LOG, OCIO.Constants.ROLE_SCENE_LINEAR)
+
+node = nuke.createNode("ColorLookup")
+node.setName("sm2_slg_to_ln")
+knob = node['lut']
+knob.removeKeyAt(0.0)
+knob.removeKeyAt(1.0)
+
+node2 = nuke.createNode("ColorLookup")
+node2.setName("sm2_ln_to_slg")
+knob2 = node2['lut']
+knob2.removeKeyAt(0.0)
+knob2.removeKeyAt(1.0)
+
+
+def Fit(value, fromMin, fromMax, toMin, toMax):
+ if fromMin == fromMax:
+ raise ValueError("fromMin == fromMax")
+ return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin
+
+SIZE = 2**10
+for i in xrange(SIZE):
+ x = i/(SIZE-1.0)
+
+ x = Fit(x, 0.0, 1.0, -0.125, 1.5)
+
+ y = cs_to_lin.applyRGB((x,x,x))[1]
+
+ knob.setValueAt(y,x)
+ knob2.setValueAt(x,y)
+
diff --git a/share/nuke/examples/ocio_to_colorlookup_rgb.py b/share/nuke/examples/ocio_to_colorlookup_rgb.py
new file mode 100644
index 0000000..efedbd7
--- /dev/null
+++ b/share/nuke/examples/ocio_to_colorlookup_rgb.py
@@ -0,0 +1,29 @@
+import SpImport
+OCIO = SpImport.SpComp2("PyOpenColorIO",2)
+#import PyOpenColorIO as OCIO
+
+c = OCIO.GetCurrentConfig()
+
+processor = c.getProcessor(OCIO.FileTransform('woz_qt_to_mxfva.spi1d', interpolation=OCIO.Constants.INTERP_LINEAR))
+
+node = nuke.createNode("ColorLookup")
+node.setName("woz_post_film")
+knob = node['lut']
+knob.removeKeyAt(0.0, 1)
+knob.removeKeyAt(1.0, 1)
+knob.removeKeyAt(0.0, 2)
+knob.removeKeyAt(1.0, 2)
+knob.removeKeyAt(0.0, 3)
+knob.removeKeyAt(1.0, 3)
+
+
+SIZE = 11
+for i in xrange(SIZE):
+ x = i/(SIZE-1.0)
+
+ y = processor.applyRGB((x,x,x))
+
+ knob.setValueAt(y[0],x, 1)
+ knob.setValueAt(y[1],x, 2)
+ knob.setValueAt(y[2],x, 3)
+
diff --git a/share/nuke/init.py b/share/nuke/init.py
new file mode 100644
index 0000000..6d3832c
--- /dev/null
+++ b/share/nuke/init.py
@@ -0,0 +1,26 @@
+import nuke
+
+EBANNER = "OCIO Error: "
+OCIO = None
+
+def load_ocio_plugins():
+ """Loads the PyOpenColorIO module and the OCIO-prefixed nodes
+ """
+
+ global OCIO
+ try:
+ import PyOpenColorIO as OCIO
+ except Exception, e:
+ print '%s%s\n%s' % (EBANNER, 'Loading OCIO python module', e)
+
+ allplugs = nuke.plugins(nuke.ALL | nuke.NODIR, "OCIO*.so", "OCIO*.dylib", "OCIO*.dll")
+
+ for p in allplugs:
+ try:
+ nuke.load(p)
+ except Exception, e:
+ print '%sLoading OCIO node %s\n%s' % (EBANNER, p, e)
+
+
+if __name__ == "__main__":
+ load_ocio_plugins()
diff --git a/share/nuke/menu.py b/share/nuke/menu.py
new file mode 100644
index 0000000..250a10c
--- /dev/null
+++ b/share/nuke/menu.py
@@ -0,0 +1,26 @@
+import os
+import nuke
+import ocionuke.cdl
+
+
+def ocio_populate_menu():
+ """Adds OCIO nodes to a menu in Color
+ """
+
+ m_nodes = nuke.toolbar('Nodes')
+ m_color = m_nodes.findItem("Color")
+ m_ocio = m_color.addMenu("OCIO", icon = "ocio_icon.png")
+
+ allplugs = nuke.plugins(nuke.ALL | nuke.NODIR, "OCIO*.so", "OCIO*.dylib", "OCIO*.dll")
+
+ for fname in allplugs:
+ p = os.path.splitext(fname)[0] # strip .so extension
+ m_ocio.addCommand(p, lambda p=p: nuke.createNode(p))
+
+ m_utils = m_ocio.addMenu("Utils")
+ m_utils.addCommand("Import .ccc to CDL nodes", ocionuke.cdl.import_multiple_from_ccc)
+ m_utils.addCommand("Export selected CDL's to .ccc", ocionuke.cdl.export_multiple_to_ccc)
+
+
+if __name__ == "__main__":
+ ocio_populate_menu()
diff --git a/share/nuke/ocio_icon.png b/share/nuke/ocio_icon.png
new file mode 100644
index 0000000..3972d66
--- /dev/null
+++ b/share/nuke/ocio_icon.png
Binary files differ
diff --git a/share/nuke/ocionuke/__init__.py b/share/nuke/ocionuke/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/share/nuke/ocionuke/__init__.py
diff --git a/share/nuke/ocionuke/cdl.py b/share/nuke/ocionuke/cdl.py
new file mode 100644
index 0000000..9ed76ae
--- /dev/null
+++ b/share/nuke/ocionuke/cdl.py
@@ -0,0 +1,269 @@
+"""Various utilities relating to the OCIOCDLTransform node
+"""
+
+import nuke
+import nukescripts
+import PyOpenColorIO as OCIO
+import xml.etree.ElementTree as ET
+
+
+def _node_to_cdltransform(node):
+ """From an OCIOCDLTransform node, returns a PyOpenColorIO
+ CDLTransform object, which could be used to write XML
+ """
+
+ # Color_Knob.value returns single float if control is not
+ # expanded, so use value(index=...) to always get three values
+ slope = [node['slope'].value(x) for x in range(3)]
+ offset = [node['offset'].value(x) for x in range(3)]
+ power = [node['power'].value(x) for x in range(3)]
+ sat = node['saturation'].value()
+ cccid = node['cccid'].value()
+
+ cdl = OCIO.CDLTransform()
+ cdl.setSlope(slope)
+ cdl.setOffset(offset)
+ cdl.setPower(power)
+ cdl.setSat(sat)
+ cdl.setID(cccid)
+
+ return cdl
+
+
+def _cdltransform_to_node(cdl, node):
+ """From an XML string, populates the parameters on an
+ OCIOCDLTransform node
+ """
+
+ # Treat "node" as a dictionary of knobs, as the "node" argument could be
+ # a the return value of PythonPanel.knob(), as in SelectCCCIDPanel
+
+ node['slope'].setValue(cdl.getSlope())
+ node['offset'].setValue(cdl.getOffset())
+ node['power'].setValue(cdl.getPower())
+ node['saturation'].setValue(cdl.getSat())
+ node['cccid'].setValue(cdl.getID())
+
+
+def _xml_to_cdltransforms(xml):
+ """Given some XML as a string, returns a list of CDLTransform
+ objects for each ColorCorrection (returns a one-item list for a
+ .cc file)
+ """
+
+ tree = ET.fromstring(xml)
+
+ # Strip away xmlns
+ for elem in tree.getiterator():
+ if elem.tag.startswith("{"):
+ elem.tag = elem.tag.partition("}")[2]
+
+ filetype = tree.tag
+
+ if filetype == "ColorCorrection":
+ ccxml = ET.tostring(tree)
+ cdl = OCIO.CDLTransform()
+ cdl.setXML(ccxml)
+ return [cdl]
+
+ elif filetype == "ColorCorrectionCollection":
+ allcdl = []
+ for cc in tree.getchildren():
+ if cc.tag != "ColorCorrection": continue
+ ccxml = ET.tostring(cc)
+ cdl = OCIO.CDLTransform()
+ cdl.setXML(ccxml)
+ allcdl.append(cdl)
+ return allcdl
+
+ else:
+ raise RuntimeError(
+ "The supplied file did not have the correct root element, expected"
+ " 'ColorCorrection' or 'ColorCorrectionCollection', got %r" % (filetype))
+
+
+def _cdltransforms_to_xml(allcc):
+ """Given a list of CDLTransform objects, returns an XML string
+ """
+
+ root = ET.Element("ColorCorrectionCollection")
+ root.attrib['xmlns'] = 'urn:ASC:CDL:v1.2'
+
+ for cc in allcc:
+ cur = ET.fromstring(cc.getXML())
+
+ # Strip away xmlns
+ for elem in cur.getiterator():
+ if elem.tag.startswith("{"):
+ elem.tag = elem.tag.partition("}")[2]
+ root.append(cur)
+
+ return ET.tostring(root)
+
+
+class SelectCCCIDPanel(nukescripts.PythonPanel):
+ """Allows the user to select from a list of CDLTransform
+ objects
+ """
+
+ def __init__(self, allcdl):
+ super(SelectCCCIDPanel, self).__init__()
+ self.available = {}
+ for cur in allcdl:
+ self.available[cur.getID()] = cur
+
+ self.addKnob(nuke.Enumeration_Knob("cccid", "cccid", self.available.keys()))
+ self.addKnob(nuke.Text_Knob("divider"))
+ self.addKnob(nuke.Color_Knob("slope"))
+ self.addKnob(nuke.Color_Knob("offset"))
+ self.addKnob(nuke.Color_Knob("power"))
+ self.addKnob(nuke.Double_Knob("saturation"))
+
+ def selected(self):
+ return self.available[self.knobs()['cccid'].value()]
+
+ def knobChanged(self, knob):
+ """When the user selects a cccid, a grade-preview knobs are set.
+
+ This method is triggered when any knob is changed, which has the
+ useful side-effect of preventing changing the preview values, while
+ keeping them selectable for copy-and-paste.
+ """
+ _cdltransform_to_node(self.selected(), self.knobs())
+
+
+def export_as_cc(node = None, filename = None):
+ """Export a OCIOCDLTransform node as a ColorCorrection XML file
+ (.cc)
+
+ If node is None, "nuke.thisNode()" will be used. If filename is
+ not specified, the user will be prompted.
+ """
+
+ if node is None:
+ node = nuke.thisNode()
+
+ cdl = _node_to_cdltransform(node)
+
+ if filename is None:
+ ccfilename = nuke.getFilename("Color Correction filename", pattern = "*.cc")
+ if ccfilename is None:
+ # User clicked cancel
+ return
+
+ xml = cdl.getXML()
+ print "Writing to %s - contents:\n%s" % (ccfilename, xml)
+ open(ccfilename, "w").write(xml)
+
+
+def import_cc_from_xml(node = None, filename = None):
+ """Import a ColorCorrection XML (.cc) into a OCIOCDLTransform node.
+
+ If node is None, "nuke.thisNode()" will be used. If filename is
+ not specified, the user will be prompted.
+ """
+
+ if node is None:
+ node = nuke.thisNode()
+
+ if filename is None:
+ ccfilename = nuke.getFilename("Color Correction filename", pattern = "*.cc *.ccc")
+ if ccfilename is None:
+ # User clicked cancel
+ return
+
+ xml = open(ccfilename).read()
+
+ allcc = _xml_to_cdltransforms(xml)
+
+ if len(allcc) == 1:
+ _cdltransform_to_node(allcc[0], node)
+ elif len(allcc) > 1:
+ do_selectcccid = nuke.ask(
+ "Selected a ColorCorrectionCollection, do you wish to select a ColorCorrection from this file?")
+ if do_selectcccid:
+ sel = SelectCCCIDPanel(allcc)
+ okayed = sel.showModalDialog()
+ if okayed:
+ cc = sel.selected()
+ _cdltransform_to_node(cc, node)
+ else:
+ return
+ else:
+ nuke.message("The supplied file (%r) contained no ColorCorrection's" % ccfilename)
+ return
+
+
+def export_multiple_to_ccc(filename = None):
+ """Exported all selected OCIOCDLTransform nodes to a
+ ColorCorrectionCollection XML file (.ccc)
+ """
+
+ if filename is None:
+ filename = nuke.getFilename("Color Correction XML file", pattern = "*.cc *.ccc")
+ if filename is None:
+ # User clicked cancel
+ return
+
+ allcc = []
+ for node in nuke.selectedNodes("OCIOCDLTransform"):
+ allcc.append(_node_to_cdltransform(node))
+
+ xml = _cdltransforms_to_xml(allcc)
+ print "Writing %r, contents:\n%s" % (filename, xml)
+ open(filename, "w").write(xml)
+
+
+def import_multiple_from_ccc(filename = None):
+ """Import a ColorCorrectionCollection file (.ccc) into multiple
+ OCIOCDLTransform nodes. Also creates a single node for a .cc file
+ """
+
+ if filename is None:
+ filename = nuke.getFilename("Color Correction XML file", pattern = "*.cc *.ccc")
+ if filename is None:
+ # User clicked cancel
+ return
+
+ xml = open(filename).read()
+ allcc = _xml_to_cdltransforms(xml)
+
+ def _make_node(cdl):
+ newnode = nuke.nodes.OCIOCDLTransform(inputs = nuke.selectedNodes()[:1])
+ _cdltransform_to_node(cdl, newnode)
+ newnode['label'].setValue("id: [value cccid]")
+
+ if len(allcc) > 0:
+ for cc in allcc:
+ _make_node(cc)
+ else:
+ nuke.message("The supplied file (%r) contained no ColorCorrection's" % filename)
+
+
+def select_cccid_for_filetransform(node = None, fileknob = 'file', cccidknob = 'cccid'):
+ """Select cccid button for the OCIOFileTransform node, also used
+ in OCIOCDLTransform. Presents user with list of cccid's within the
+ specified .ccc file, and sets the cccid knob to the selected ID.
+ """
+
+ if node is None:
+ node = nuke.thisNode()
+
+ filename = node[fileknob].value()
+
+ try:
+ xml = open(filename).read()
+ except IOError, e:
+ nuke.message("Error opening src file: %s" % e)
+ raise
+
+ allcc = _xml_to_cdltransforms(xml)
+
+ if len(allcc) == 0:
+ nuke.message("The file (%r) contains no ColorCorrection's")
+ return
+
+ sel = SelectCCCIDPanel(allcc)
+ okayed = sel.showModalDialog()
+ if okayed:
+ node[cccidknob].setValue(sel.selected().getID())
diff --git a/share/nuke/ocionuke/viewer.py b/share/nuke/ocionuke/viewer.py
new file mode 100644
index 0000000..883525a
--- /dev/null
+++ b/share/nuke/ocionuke/viewer.py
@@ -0,0 +1,50 @@
+import nuke
+
+
+def register_viewers(also_remove = "default"):
+ """Registers the a viewer process for each display device/view, and
+ sets the default viewer process.
+
+ ``also_remove`` can be set to either:
+
+ - "default" to remove the default sRGB/rec709 viewer processes
+ - "all" to remove all processes
+ - "none" to leave existing viewer processes untouched
+ """
+
+ if also_remove not in ("default", "none", "all"):
+ raise ValueError("also_remove should be set to 'default', 'none' or 'all'")
+
+ if also_remove == "default":
+ nuke.ViewerProcess.unregister('rec709')
+ nuke.ViewerProcess.unregister('sRGB')
+ nuke.ViewerProcess.unregister('None')
+ elif also_remove == "all":
+ # Unregister all processes, including None, which should be defined in config.ocio
+ for curname in nuke.ViewerProcess.registeredNames():
+ nuke.ViewerProcess.unregister(curname)
+
+ # Formats the display and transform, e.g "Film1D (sRGB)"
+ DISPLAY_UI_FORMAT = "%(view)s (%(display)s)"
+
+ import PyOpenColorIO as OCIO
+ config = OCIO.GetCurrentConfig()
+
+ # For every display, loop over every view
+ for display in config.getDisplays():
+ for view in config.getViews(display):
+ # Register the node
+ nuke.ViewerProcess.register(
+ name = DISPLAY_UI_FORMAT % {'view': view, "display": display},
+ call = nuke.nodes.OCIODisplay,
+ args = (),
+ kwargs = {"display": display, "view": view, "layer": "all"})
+
+
+ # Get the default display and view, set it as the default used on Nuke startup
+ defaultDisplay = config.getDefaultDisplay()
+ defaultView = config.getDefaultView(defaultDisplay)
+
+ nuke.knobDefault(
+ "Viewer.viewerProcess",
+ DISPLAY_UI_FORMAT % {'view': defaultView, "display": defaultDisplay})
diff --git a/share/ocio/setup_ocio.sh.in b/share/ocio/setup_ocio.sh.in
new file mode 100644
index 0000000..81a109c
--- /dev/null
+++ b/share/ocio/setup_ocio.sh.in
@@ -0,0 +1,14 @@
+#!/bin/sh
+OCIO_ROOT="@CMAKE_INSTALL_PREFIX@"
+OCIO_EXECROOT="@CMAKE_INSTALL_EXEC_PREFIX@"
+
+# For OS X
+export DYLD_LIBRARY_PATH="${OCIO_EXECROOT}/lib:${DYLD_LIBRARY_PATH}"
+
+# For Linux
+export LD_LIBRARY_PATH="${OCIO_EXECROOT}/lib:${LD_LIBRARY_PATH}"
+
+export PATH="${OCIO_EXECROOT}/bin:${PATH}"
+export PYTHONPATH="${OCIO_EXECROOT}/@PYTHON_VARIANT_PATH@:${PYTHONPATH}"
+export NUKE_PATH="${OCIO_EXECROOT}/lib/nuke@Nuke_API_VERSION@:${NUKE_PATH}"
+export NUKE_PATH="${OCIO_ROOT}/share/nuke:${NUKE_PATH}";
diff --git a/share/sphinx/ExtractRstFromSourceCPP.py b/share/sphinx/ExtractRstFromSourceCPP.py
new file mode 100755
index 0000000..54cc3d7
--- /dev/null
+++ b/share/sphinx/ExtractRstFromSourceCPP.py
@@ -0,0 +1,324 @@
+#!/usr/bin/python
+
+"""
+Small Script to extract reStructuredText from OCIO headers
+ - http://sphinx.pocoo.org/rest.html
+ - http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html
+"""
+
+# TODO: extract void foo() { blah = 0 }; signatures correctly
+# TODO: handle typedef and enums better
+# TODO: handle OCIOEXPORT macro better
+# TODO: handle thow() funcs better
+
+RUNTEST = False
+
+import re, sys
+
+single_rst_comment = r"//(?P<single_comment>(!cpp:|!rst::).*\n)"
+block_rst_comment = r"/\*(?P<block_comment>(!cpp:|!rst::)([^*]*\*+)+?/)"
+rst_comment_regex = re.compile(r"(%s)|(%s)" % (single_rst_comment, block_rst_comment), re.MULTILINE)
+func_signature_regex = re.compile(r"(?P<sig_name>[^ ]*\(.*\))")
+
+rst_types = ["!rst::", "!cpp:class::", "!cpp:function::", "!cpp:member::",
+ "!cpp:type::"]
+
+def getRstType(string):
+ for rtype in rst_types:
+ if string[0 : len(rtype)] == rtype:
+ return rtype[1:]
+ return None
+
+def getNextCodeLine(string, rst_type, from_pos):
+
+ end = from_pos
+ signature = ""
+
+ if rst_type == "rst::":
+ return signature, end
+
+ if rst_type == "cpp:class::":
+
+ class_open = False
+
+ # first non-blank line that starts with 'class'
+ found_signature = False
+
+ # loop till the end of the class '};'
+ ## skip other open/close '{' '}'
+ skip_close = False
+ x = end
+ while x < len(string):
+ if string[x] != '\n' and not found_signature:
+ signature += string[x]
+ if string[x] == '\n' and not found_signature:
+ signature = signature.strip()
+ if signature != '':
+ found_signature = True
+ signature = signature.replace("class", "")
+ # TODO: this seem a bit dirty
+ signature = signature.replace("OCIOEXPORT ", "")
+ signature = signature.strip()
+ signature = signature.split(' ', 1)[0]
+ if string[x] == '{' and not class_open:
+ class_open = True
+ elif string[x] == '{' and class_open:
+ skip_close = True
+ elif string[x] == '}' and skip_close:
+ skip_close = False
+ elif string[x] == '}':
+ end = x
+ break
+ x += 1
+ return signature, end
+
+ # else
+ skip = False
+ while string[end] != ";":
+ if string[end] != ' ' and skip:
+ skip = False
+ signature += ' '
+ if string[end] == '\n':
+ skip = True
+ if not skip:
+ signature += string[end]
+ end += 1
+ signature += string[end]
+ # TODO: this seem a bit dirty
+ signature = signature.replace("OCIOEXPORT ", "")
+ signature = signature.replace(" throw()", "")
+ signature = signature.strip()
+ if signature[len(signature)-1] == ';':
+ signature = signature[:len(signature)-1]
+
+ # hack hack hack
+ if rst_type == "cpp:type::":
+ if signature[:7] == "typedef":
+ bits = signature.split()
+ signature = bits[len(bits)-1]
+ if signature[:4] == "enum":
+ bits = signature.split()
+ signature = bits[1]
+
+ return signature, end
+
+def getNextCommentLine(string, from_pos, buffer = ""):
+ end = from_pos
+ tmp = ""
+ while string[end] != "\n":
+ tmp += string[end]
+ end += 1
+ tmp += string[end]
+ if tmp.lstrip()[:2] == "//":
+ if tmp.lstrip()[2:][0] == " ":
+ buffer += tmp.lstrip()[3:]
+ else:
+ buffer += tmp.lstrip()[2:]
+ buffer, end = getNextCommentLine(string, end+1, buffer)
+ else:
+ end = from_pos
+ return buffer, end
+
+class Comment:
+
+ def __init__(self, comment, start, end):
+ self.comment = comment
+ self.start = start
+ self.end = end
+
+ def getRstType(self):
+ return getRstType(self.comment)
+
+ def __str__(self):
+
+ buffer = self.comment
+ for rtype in rst_types:
+ if buffer[0 : len(rtype)] == rtype:
+ buffer = buffer[len(rtype):]
+
+ buffer_lines = buffer.splitlines()
+ buffer_lines[0] = buffer_lines[0].strip()
+
+ if self.getRstType() == "rst::":
+ buffer_lines.append('')
+ buffer = '\n'.join(buffer_lines)
+ return buffer
+
+ if buffer_lines[0] != '':
+ buffer_lines.insert(0, '')
+ for x in xrange(0, len(buffer_lines)):
+ buffer_lines[x] = " %s" % buffer_lines[x]
+ buffer_lines.append('')
+ buffer = '\n'.join(buffer_lines)
+
+ return buffer
+
+def ExtractRst(string, fileh):
+
+ items = []
+
+ for item in rst_comment_regex.finditer(string):
+ start, end = item.span()
+ itemdict = item.groupdict()
+ if itemdict["single_comment"] != None:
+ ##
+ buf = itemdict["single_comment"]
+ comment, end = getNextCommentLine(string, end)
+ buf += comment
+ ##
+ items.append(Comment(buf, start, end))
+
+ elif itemdict["block_comment"] != None:
+ ##
+ itemdict["block_comment"] = \
+ itemdict["block_comment"][:len(itemdict["block_comment"])-2]
+ buf_lines = itemdict["block_comment"].splitlines()
+ indent = 0
+ if len(buf_lines) > 1:
+ for char in buf_lines[1]:
+ if char != ' ':
+ break
+ indent += 1
+ # remove indent
+ bufa = [buf_lines[0]]
+ for x in xrange(1, len(buf_lines)):
+ bufa.append(buf_lines[x][indent:])
+ buf = '\n'.join(bufa) + '\n'
+ ##
+ items.append(Comment(buf, start, end))
+
+ ##
+ fileh.write('\n')
+ namespaces = []
+ for thing in items:
+ rst_type = thing.getRstType()
+
+ # .. cpp:function:: SomeClass::func2(const char * filename, std::istream& foo)
+ # this is some of the documentation
+ # for this function
+
+ signature, end = getNextCodeLine(string, rst_type, thing.end)
+
+ # if we are a class work out the begining and end so we can
+ # give function signatures the correct namespace
+ if rst_type == "cpp:class::":
+ tmp = { 'name': signature, 'start': thing.end, 'end': end }
+ namespaces.append(tmp)
+ fileh.write(".. %s %s\n" % (rst_type, signature) )
+ elif rst_type != "rst::":
+ for namespace in namespaces:
+ if end > namespace['start'] and end < namespace['end']:
+ func = func_signature_regex.search(signature)
+ funcpart = str(func.groupdict()["sig_name"])
+ signature = signature.replace(funcpart, "%s::%s" % (namespace['name'], funcpart))
+ break
+ fileh.write(".. %s %s\n" % (rst_type, signature) )
+
+ fileh.write(str(thing))
+
+ fileh.write('\n')
+
+ fileh.flush()
+
+if __name__ == "__main__":
+
+ if not RUNTEST:
+
+ if len(sys.argv) <= 2:
+ sys.stderr.write("\nYou need to specify an input and output file\n\n")
+ sys.exit(1)
+
+ src = open(sys.argv[1]).read()
+ output = file(sys.argv[2], 'w')
+ ExtractRst(src, output)
+ output.close()
+
+ elif RUNTEST:
+ testdata = """
+
+//!rst:: -------------
+
+// this comment should be ignored
+
+//!rst:: foobar
+// this is apart of the same
+// comment
+
+// this is also ignored
+
+/* this is
+a block comment which is
+ignored */
+
+//!cpp:class::
+// this is a comment about the class
+class FooBar : public std::exception
+{
+ ...
+};
+
+/*!cpp:class::
+this is also a comment about this class
+*/
+
+
+class FooBar2 : public std::exception
+{
+ ...
+};
+
+/*!cpp:class::
+this is also a comment about this class with no new line */
+class FooBar3 : public std::exception
+{
+ ...
+};
+
+//!cpp:class::
+class SomeClass
+{
+public:
+
+ //!cpp:function::
+ // this is some cool function for
+ // some purpose
+ // this line is indented
+ static fooPtr func1();
+
+ /*!cpp:function::
+ this is a much better func for some other
+ purpose
+ this is also indented */
+ static barPtr func2();
+
+ /*!cpp:function:: this func wraps over two
+ lines which needs
+ to be caught
+ */
+ static weePtr func2(const char * filename,
+ std::istream& foo);
+};
+
+//!cpp:function:: the class namespace should still get set correctly
+void foobar1();
+
+//!cpp:class:: this is some super informative
+// docs
+class SomeClass
+{
+public:
+ //!cpp:function:: the class namespace should still get set correctly
+ void foobar2();
+};
+
+//!cpp:function:: the class namespace should still get set correctly
+void foobar3();
+
+/*!rst:: this is a rst block
+**comment which needs**
+to be supported
+*/
+
+"""
+ ExtractRst(testdata)
+
diff --git a/share/sphinx/ExtractRstFromSourceSimple.py b/share/sphinx/ExtractRstFromSourceSimple.py
new file mode 100755
index 0000000..20d1bed
--- /dev/null
+++ b/share/sphinx/ExtractRstFromSourceSimple.py
@@ -0,0 +1,110 @@
+#!/usr/bin/python
+
+"""
+Small Script to extract reStructuredText from OCIO headers
+ - http://sphinx.pocoo.org/rest.html
+ - http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html
+
+This looks for the tokens:
+
+/*+doc
+and puts everything
+inside of them
+*/
+//+doc in the RST file.
+
+"""
+
+RUNTEST = False
+import sys, os, string
+
+
+# Remove the specified number of whitespace from the start of the string
+# If non-whitespace text is encountered in the 'indent' area, it is preserved
+def _RemoveIndent(s, indent):
+ firstcharindex = s.find(s.strip())
+ startindex = min(firstcharindex, indent)
+ return s[startindex:]
+
+def ExtractRst(inputstr, ofile):
+ inMultiline = False
+ onelineDocTag = '//+doc'
+ multilineDocTag = '/*+doc'
+ multilineEndTag = '*/'
+ multilineStartIndent = 0
+ newOutputFile = False
+
+ for line in inputstr.splitlines():
+ if inMultiline:
+ if multilineEndTag in line:
+ data = line[:line.index(multilineEndTag)]
+ ofile.write(_RemoveIndent(data, multilineStartIndent) + '\n\n')
+ inMultiline = False
+ multilineStartIndent = 0
+ else:
+ ofile.write(_RemoveIndent(line, multilineStartIndent) + '\n')
+ elif onelineDocTag in line:
+ docstring = line.split('//+doc', 1)[1]
+ # TODO: Add this part to the CPP extracting script
+ if "*New File*" in docstring:
+ filename = line.split('*New File*', 1)[1].strip()
+ # Make sure that the file name is valid here
+ if newOutputFile:
+ ofile.close()
+ ofile = file(filename, 'w')
+ newOutputFile = True
+ ofile.write(docstring.strip() + '\n')
+ else:
+ if multilineDocTag in line:
+ multilineStartIndent = line.index(multilineDocTag)
+ inMultiline = True
+ # TODO: Handle code after the multiline start tag?
+
+if __name__ == "__main__":
+
+ if not RUNTEST:
+
+ if len(sys.argv) <= 2:
+ sys.stderr.write("\nYou need to specify an input and output file\n\n")
+ sys.exit(1)
+
+ src = open(sys.argv[1]).read()
+ output = file(sys.argv[2], 'w')
+ ExtractRst(src, output)
+ output.close()
+
+ elif RUNTEST:
+ #print _RemoveIndent('',4)
+ #print _RemoveIndent('sfdfsd',4)
+ #print _RemoveIndent(' sfdfsd',4)
+ #print _RemoveIndent(' sfdfsd',4)
+
+ testdata = """
+
+#include <...>
+
+void Random C++ Code
+
+//+doc Some one-line doc. Everything on the line after the onelineDocTag gets added.
+
+/*+doc What should this do?
+!rst::This is a multi-line rst text
+
+there is a blank line above this
+ this is before the final endtag */
+
+class TestClass
+ /*+doc What should this do?
+ !rst::additional rst indented code
+ more indented code
+This is left indented
+ This is original indent
+ This is indented 4 spaces
+ */
+
+
+
+
+"""
+ ExtractRst(testdata, sys.stdout)
+
diff --git a/src/aftereffects/DrawbotBot.cpp b/src/aftereffects/DrawbotBot.cpp
new file mode 100644
index 0000000..3d6cee6
--- /dev/null
+++ b/src/aftereffects/DrawbotBot.cpp
@@ -0,0 +1,239 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "DrawbotBot.h"
+
+
+DrawbotBot::DrawbotBot(struct SPBasicSuite *pica_basicP, PF_ContextH contextH, A_long appl_id) :
+ suites(pica_basicP),
+ _appl_id(appl_id),
+ _suiteP(NULL),
+ _drawbot_ref(NULL),
+ _supplier_ref(NULL),
+ _surface_ref(NULL)
+{
+ suites.EffectCustomUISuite1()->PF_GetDrawingReference(contextH, &_drawbot_ref);
+
+ _suiteP = suites.SupplierSuiteCurrent();
+
+ suites.DrawbotSuiteCurrent()->GetSupplier(_drawbot_ref, &_supplier_ref);
+ suites.DrawbotSuiteCurrent()->GetSurface(_drawbot_ref, &_surface_ref);
+
+ _brush_pos.x = 0.f;
+ _brush_pos.y = 0.f;
+
+ SetColor(PF_App_Color_TEXT);
+
+ _suiteP->GetDefaultFontSize(_supplier_ref, &_font_size);
+}
+
+
+DrawbotBot::~DrawbotBot()
+{
+
+}
+
+
+void DrawbotBot::SetColor(PF_App_ColorType color, float a)
+{
+ if(_appl_id == 'FXTC')
+ {
+ PF_App_Color app_color;
+
+ suites.AppSuite4()->PF_AppGetColor(color, &app_color);
+
+ _brush_color.red = (float)app_color.red / (float)PF_MAX_CHAN16;
+ _brush_color.green = (float)app_color.green / (float)PF_MAX_CHAN16;
+ _brush_color.blue = (float)app_color.blue / (float)PF_MAX_CHAN16;
+ }
+ else
+ {
+ // Premiere isn't doing this properly, so I'll have to.
+ // Only supporting the colors I'm actually using at the moment.
+ switch(color)
+ {
+ case PF_App_Color_BLACK:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.f;
+ break;
+
+ case PF_App_Color_WHITE:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 1.f;
+ break;
+
+ case PF_App_Color_RED:
+ _brush_color.red = 1.f;
+ _brush_color.green = _brush_color.blue = 0.f;
+ break;
+
+ case PF_App_Color_TEXT_DISABLED:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.6f;
+ break;
+
+ case PF_App_Color_SHADOW:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.3f;
+ break;
+
+ case PF_App_Color_HILITE:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.8f;
+ break;
+
+ case PF_App_Color_LIGHT_TINGE:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.7f;
+ break;
+
+ case PF_App_Color_BUTTON_FILL:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.5f;
+ break;
+
+ case PF_App_Color_BUTTON_PRESSED_FILL:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.3f;
+ break;
+
+ case PF_App_Color_PANEL_BACKGROUND:
+ {
+ PF_App_Color app_color;
+ suites.AppSuite4()->PF_AppGetBgColor(&app_color);
+
+ _brush_color.red = (float)app_color.red / (float)65535;
+ _brush_color.green = (float)app_color.green / (float)65535;
+ _brush_color.blue = (float)app_color.blue / (float)65535;
+ }
+ break;
+
+ default:
+ _brush_color.red = _brush_color.green = _brush_color.blue = 0.9f;
+ break;
+ }
+ }
+
+ _brush_color.alpha = a;
+}
+
+
+void DrawbotBot::DrawLineTo(float x, float y, float brush_size)
+{
+ DRAWBOT_PathP pathP(_suiteP, _supplier_ref);
+ DRAWBOT_PenP penP(_suiteP, _supplier_ref, &_brush_color, brush_size);
+
+ suites.PathSuiteCurrent()->MoveTo(pathP.Get(), _brush_pos.x, _brush_pos.y);
+
+ suites.PathSuiteCurrent()->LineTo(pathP.Get(), x, y);
+
+ suites.SurfaceSuiteCurrent()->StrokePath(_surface_ref, penP.Get(), pathP.Get());
+
+ MoveTo(x, y);
+}
+
+
+void DrawbotBot::DrawRect(float w, float h, float brush_size) const
+{
+ DRAWBOT_PathP pathP(_suiteP, _supplier_ref);
+ DRAWBOT_PenP penP(_suiteP, _supplier_ref, &_brush_color, brush_size);
+
+ DRAWBOT_RectF32 rect;
+
+ rect.left = _brush_pos.x - 0.5f;
+ rect.top = _brush_pos.y - 0.5f;
+ rect.width = w;
+ rect.height = h;
+
+ suites.PathSuiteCurrent()->AddRect(pathP.Get(), &rect);
+
+ suites.SurfaceSuiteCurrent()->StrokePath(_surface_ref, penP.Get(), pathP.Get());
+}
+
+void DrawbotBot::PaintRect(float w, float h) const
+{
+ DRAWBOT_RectF32 rect;
+
+ rect.left = _brush_pos.x;
+ rect.top = _brush_pos.y;
+ rect.width = w;
+ rect.height = h;
+
+ suites.SurfaceSuiteCurrent()->PaintRect(_surface_ref, &_brush_color, &rect);
+}
+
+
+void DrawbotBot::PaintTriangle(float w, float h) const
+{
+ DRAWBOT_PathP pathP(_suiteP, _supplier_ref);
+ DRAWBOT_BrushP brushP(_suiteP, _supplier_ref, &_brush_color);
+
+ suites.PathSuiteCurrent()->MoveTo(pathP.Get(), _brush_pos.x, _brush_pos.y);
+
+ suites.PathSuiteCurrent()->LineTo(pathP.Get(), _brush_pos.x + w, _brush_pos.y);
+
+ suites.PathSuiteCurrent()->LineTo(pathP.Get(), _brush_pos.x + (w / 2.f),
+ _brush_pos.y + h);
+
+ suites.PathSuiteCurrent()->Close(pathP.Get());
+
+ suites.SurfaceSuiteCurrent()->FillPath(_surface_ref, brushP.Get(), pathP.Get(),
+ kDRAWBOT_FillType_Default);
+}
+
+
+void DrawbotBot::DrawString(
+ const DRAWBOT_UTF16Char *str,
+ DRAWBOT_TextAlignment align,
+ DRAWBOT_TextTruncation truncate,
+ float truncation_width) const
+{
+ DRAWBOT_BrushP brushP(_suiteP, _supplier_ref, &_brush_color);
+ DRAWBOT_FontP fontP(_suiteP, _supplier_ref, _font_size);
+
+ suites.SurfaceSuiteCurrent()->DrawString(_surface_ref, brushP.Get(), fontP.Get(), str,
+ &_brush_pos, align, truncate, truncation_width);
+}
+
+
+void DrawbotBot::DrawString(
+ const char *str,
+ DRAWBOT_TextAlignment align,
+ DRAWBOT_TextTruncation truncate,
+ float truncation_width) const
+{
+ DRAWBOT_UTF16Char u_str[256] = {'\0'};
+
+ DRAWBOT_UTF16Char *u = u_str;
+ const char *c = str;
+
+ if(*c != '\0')
+ {
+ do{
+ *u++ = *c++;
+
+ }while(*c != '\0');
+
+ *u = '\0';
+ }
+
+ DrawString(u_str, align, truncate, truncation_width);
+} \ No newline at end of file
diff --git a/src/aftereffects/DrawbotBot.h b/src/aftereffects/DrawbotBot.h
new file mode 100644
index 0000000..bd55ace
--- /dev/null
+++ b/src/aftereffects/DrawbotBot.h
@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _DRAWBOTBOT_H_
+#define _DRAWBOTBOT_H_
+
+#include "AEGP_SuiteHandler.h"
+
+
+class DrawbotBot
+{
+ public:
+
+ DrawbotBot(struct SPBasicSuite *pica_basicP, PF_ContextH contextH, A_long appl_id);
+ ~DrawbotBot();
+
+ void MoveTo(DRAWBOT_PointF32 pos) { _brush_pos = pos; }
+ void MoveTo(float x, float y) { _brush_pos.x = x; _brush_pos.y = y; }
+ void Move(float x = 0, float y = 0) { _brush_pos.x += x; _brush_pos.y += y; }
+
+ void SetColor(PF_App_ColorType color, float a = 1.f);
+ void SetColor(DRAWBOT_ColorRGBA color) { _brush_color = color; }
+ void SetColor(float r, float g, float b, float a = 1.f)
+ { _brush_color.red = r; _brush_color.green = g;
+ _brush_color.blue = b; _brush_color.alpha = a; }
+
+ DRAWBOT_PointF32 Pos() const { return _brush_pos; }
+ float FontSize() const { return _font_size; }
+
+ void DrawLineTo(float x, float y, float brush_size = 0.5f);
+
+ void DrawRect(float w, float h, float brush_size = 0.5f) const;
+ void PaintRect(float w, float h) const;
+
+ void PaintTriangle(float w, float h) const;
+
+ void DrawString(const DRAWBOT_UTF16Char *str,
+ DRAWBOT_TextAlignment align = kDRAWBOT_TextAlignment_Default,
+ DRAWBOT_TextTruncation truncate = kDRAWBOT_TextTruncation_None,
+ float truncation_width = 0.f) const;
+ void DrawString(const char *str,
+ DRAWBOT_TextAlignment align = kDRAWBOT_TextAlignment_Default,
+ DRAWBOT_TextTruncation truncate = kDRAWBOT_TextTruncation_None,
+ float truncation_width = 0.f) const;
+
+
+ private:
+ AEGP_SuiteHandler suites;
+ A_long _appl_id;
+
+ DRAWBOT_SupplierSuiteCurrent *_suiteP;
+
+ DRAWBOT_DrawRef _drawbot_ref;
+ DRAWBOT_SupplierRef _supplier_ref;
+ DRAWBOT_SurfaceRef _surface_ref;
+
+ DRAWBOT_PointF32 _brush_pos;
+ DRAWBOT_ColorRGBA _brush_color;
+ float _font_size;
+};
+
+
+#endif // _DRAWBOTBOT_H_ \ No newline at end of file
diff --git a/src/aftereffects/OpenColorIO_AE.cpp b/src/aftereffects/OpenColorIO_AE.cpp
new file mode 100755
index 0000000..cd89091
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE.cpp
@@ -0,0 +1,1133 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE.h"
+
+#include "OpenColorIO_AE_Context.h"
+#include "OpenColorIO_AE_Dialogs.h"
+
+#include "AEGP_SuiteHandler.h"
+
+// this lives in OpenColorIO_AE_UI.cpp
+std::string GetProjectDir(PF_InData *in_data);
+
+
+static PF_Err About(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ PF_SPRINTF( out_data->return_msg,
+ "OpenColorIO\r\r"
+ "opencolorio.org\r"
+ "version %s",
+ OCIO::GetVersion() );
+
+ return PF_Err_NONE;
+}
+
+
+static PF_Err GlobalSetup(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ out_data->my_version = PF_VERSION( MAJOR_VERSION,
+ MINOR_VERSION,
+ BUG_VERSION,
+ STAGE_VERSION,
+ BUILD_VERSION);
+
+ out_data->out_flags = PF_OutFlag_DEEP_COLOR_AWARE |
+ PF_OutFlag_PIX_INDEPENDENT |
+ PF_OutFlag_CUSTOM_UI |
+ PF_OutFlag_USE_OUTPUT_EXTENT |
+ PF_OutFlag_I_HAVE_EXTERNAL_DEPENDENCIES;
+
+ out_data->out_flags2 = PF_OutFlag2_PARAM_GROUP_START_COLLAPSED_FLAG |
+ PF_OutFlag2_SUPPORTS_SMART_RENDER |
+ PF_OutFlag2_FLOAT_COLOR_AWARE |
+ PF_OutFlag2_PPRO_DO_NOT_CLONE_SEQUENCE_DATA_FOR_RENDER;
+
+
+ GlobalSetup_GL();
+
+
+ if(in_data->appl_id == 'PrMr')
+ {
+ PF_PixelFormatSuite1 *pfS = NULL;
+
+ in_data->pica_basicP->AcquireSuite(kPFPixelFormatSuite,
+ kPFPixelFormatSuiteVersion1,
+ (const void **)&pfS);
+
+ if(pfS)
+ {
+ pfS->ClearSupportedPixelFormats(in_data->effect_ref);
+
+ pfS->AddSupportedPixelFormat(in_data->effect_ref,
+ PrPixelFormat_BGRA_4444_32f_Linear);
+
+ in_data->pica_basicP->ReleaseSuite(kPFPixelFormatSuite,
+ kPFPixelFormatSuiteVersion1);
+ }
+ }
+
+ return PF_Err_NONE;
+}
+
+
+static PF_Err GlobalSetdown(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ GlobalSetdown_GL();
+
+ return PF_Err_NONE;
+}
+
+
+static PF_Err ParamsSetup(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output)
+{
+ PF_Err err = PF_Err_NONE;
+ PF_ParamDef def;
+
+
+ // readout
+ AEFX_CLR_STRUCT(def);
+ // we can time_vary once we're willing to print and scan ArbData text
+ def.flags = PF_ParamFlag_CANNOT_TIME_VARY;
+
+ ArbNewDefault(in_data, out_data, NULL, &def.u.arb_d.dephault);
+
+ PF_ADD_ARBITRARY("OCIO",
+ UI_CONTROL_WIDTH,
+ UI_CONTROL_HEIGHT,
+ PF_PUI_CONTROL,
+ def.u.arb_d.dephault,
+ OCIO_DATA,
+ NULL);
+
+
+ AEFX_CLR_STRUCT(def);
+ PF_ADD_CHECKBOX("",
+ "Use GPU",
+ FALSE,
+ 0,
+ OCIO_GPU_ID);
+
+
+ out_data->num_params = OCIO_NUM_PARAMS;
+
+ // register custom UI
+ if (!err)
+ {
+ PF_CustomUIInfo ci;
+
+ AEFX_CLR_STRUCT(ci);
+
+ ci.events = PF_CustomEFlag_EFFECT;
+
+ ci.comp_ui_width = ci.comp_ui_height = 0;
+ ci.comp_ui_alignment = PF_UIAlignment_NONE;
+
+ ci.layer_ui_width = 0;
+ ci.layer_ui_height = 0;
+ ci.layer_ui_alignment = PF_UIAlignment_NONE;
+
+ ci.preview_ui_width = 0;
+ ci.preview_ui_height = 0;
+ ci.layer_ui_alignment = PF_UIAlignment_NONE;
+
+ err = (*(in_data->inter.register_ui))(in_data->effect_ref, &ci);
+ }
+
+
+ return err;
+}
+
+static PF_Err SequenceSetup(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ PF_Err err = PF_Err_NONE;
+
+ SequenceData *seq_data = NULL;
+
+ // set up sequence data
+ if( (in_data->sequence_data == NULL) )
+ {
+ out_data->sequence_data = PF_NEW_HANDLE( sizeof(SequenceData) );
+
+ seq_data = (SequenceData *)PF_LOCK_HANDLE(out_data->sequence_data);
+
+ seq_data->path[0] = '\0';
+ seq_data->relative_path[0] = '\0';
+ }
+ else // reset pre-existing sequence data
+ {
+ if( PF_GET_HANDLE_SIZE(in_data->sequence_data) != sizeof(SequenceData) )
+ {
+ PF_RESIZE_HANDLE(sizeof(SequenceData), &in_data->sequence_data);
+ }
+
+ seq_data = (SequenceData *)PF_LOCK_HANDLE(in_data->sequence_data);
+ }
+
+
+ seq_data->status = STATUS_UNKNOWN;
+ seq_data->gpu_err = GPU_ERR_NONE;
+ seq_data->prem_status = PREMIERE_UNKNOWN;
+ seq_data->context = NULL;
+
+
+ PF_UNLOCK_HANDLE(in_data->sequence_data);
+
+ return err;
+}
+
+
+static PF_Err SequenceSetdown(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(in_data->sequence_data)
+ {
+ SequenceData *seq_data = (SequenceData *)PF_LOCK_HANDLE(out_data->sequence_data);
+
+ if(seq_data->context)
+ {
+ delete seq_data->context;
+
+ seq_data->status = STATUS_UNKNOWN;
+ seq_data->gpu_err = GPU_ERR_NONE;
+ seq_data->prem_status = PREMIERE_UNKNOWN;
+ seq_data->context = NULL;
+ }
+
+ PF_DISPOSE_HANDLE(in_data->sequence_data);
+ }
+
+ return err;
+}
+
+
+static PF_Err SequenceFlatten(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(in_data->sequence_data)
+ {
+ SequenceData *seq_data = (SequenceData *)PF_LOCK_HANDLE(in_data->sequence_data);
+
+ if(seq_data->context)
+ {
+ delete seq_data->context;
+
+ seq_data->status = STATUS_UNKNOWN;
+ seq_data->gpu_err = GPU_ERR_NONE;
+ seq_data->prem_status = PREMIERE_UNKNOWN;
+ seq_data->context = NULL;
+ }
+
+ PF_UNLOCK_HANDLE(in_data->sequence_data);
+ }
+
+ return err;
+}
+
+
+
+static PF_Boolean IsEmptyRect(const PF_LRect *r){
+ return (r->left >= r->right) || (r->top >= r->bottom);
+}
+
+#ifndef mmin
+ #define mmin(a,b) ((a) < (b) ? (a) : (b))
+ #define mmax(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+
+static void UnionLRect(const PF_LRect *src, PF_LRect *dst)
+{
+ if (IsEmptyRect(dst)) {
+ *dst = *src;
+ } else if (!IsEmptyRect(src)) {
+ dst->left = mmin(dst->left, src->left);
+ dst->top = mmin(dst->top, src->top);
+ dst->right = mmax(dst->right, src->right);
+ dst->bottom = mmax(dst->bottom, src->bottom);
+ }
+}
+
+
+static PF_Err PreRender(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_PreRenderExtra *extra)
+{
+ PF_Err err = PF_Err_NONE;
+ PF_RenderRequest req = extra->input->output_request;
+ PF_CheckoutResult in_result;
+
+ req.preserve_rgb_of_zero_alpha = TRUE;
+
+ ERR(extra->cb->checkout_layer( in_data->effect_ref,
+ OCIO_INPUT,
+ OCIO_INPUT,
+ &req,
+ in_data->current_time,
+ in_data->time_step,
+ in_data->time_scale,
+ &in_result));
+
+
+ UnionLRect(&in_result.result_rect, &extra->output->result_rect);
+ UnionLRect(&in_result.max_result_rect, &extra->output->max_result_rect);
+
+ return err;
+}
+
+#pragma mark-
+
+
+template <typename InFormat, typename OutFormat>
+static inline OutFormat Convert(InFormat in);
+
+template <>
+static inline float Convert<A_u_char, float>(A_u_char in)
+{
+ return (float)in / (float)PF_MAX_CHAN8;
+}
+
+template <>
+static inline float Convert<A_u_short, float>(A_u_short in)
+{
+ return (float)in / (float)PF_MAX_CHAN16;
+}
+
+template <>
+static inline float Convert<float, float>(float in)
+{
+ return in;
+}
+
+static inline float Clamp(float in)
+{
+ return (in > 1.f ? 1.f : in < 0.f ? 0.f : in);
+}
+
+template <>
+static inline A_u_char Convert<float, A_u_char>(float in)
+{
+ return ( Clamp(in) * (float)PF_MAX_CHAN8 ) + 0.5f;
+}
+
+template <>
+static inline A_u_short Convert<float, A_u_short>(float in)
+{
+ return ( Clamp(in) * (float)PF_MAX_CHAN16 ) + 0.5f;
+}
+
+
+
+typedef struct {
+ PF_InData *in_data;
+ void *in_buffer;
+ A_long in_rowbytes;
+ void *out_buffer;
+ A_long out_rowbytes;
+ int width;
+} IterateData;
+
+template <typename InFormat, typename OutFormat>
+static PF_Err CopyWorld_Iterate(
+ void *refconPV,
+ A_long thread_indexL,
+ A_long i,
+ A_long iterationsL)
+{
+ PF_Err err = PF_Err_NONE;
+
+ IterateData *i_data = (IterateData *)refconPV;
+ PF_InData *in_data = i_data->in_data;
+
+ InFormat *in_pix = (InFormat *)((char *)i_data->in_buffer + (i * i_data->in_rowbytes));
+ OutFormat *out_pix = (OutFormat *)((char *)i_data->out_buffer + (i * i_data->out_rowbytes));
+
+#ifdef NDEBUG
+ if(thread_indexL == 0)
+ err = PF_ABORT(in_data);
+#endif
+
+ for(int x=0; x < i_data->width; x++)
+ {
+ *out_pix++ = Convert<InFormat, OutFormat>( *in_pix++ );
+ }
+
+ return err;
+}
+
+
+typedef struct {
+ PF_InData *in_data;
+ void *in_buffer;
+ A_long in_rowbytes;
+ int width;
+} SwapData;
+
+static PF_Err Swap_Iterate(
+ void *refconPV,
+ A_long thread_indexL,
+ A_long i,
+ A_long iterationsL)
+{
+ PF_Err err = PF_Err_NONE;
+
+ SwapData *i_data = (SwapData *)refconPV;
+ PF_InData *in_data = i_data->in_data;
+
+ PF_PixelFloat *pix = (PF_PixelFloat *)((char *)i_data->in_buffer + (i * i_data->in_rowbytes));
+
+#ifdef NDEBUG
+ if(thread_indexL == 0)
+ err = PF_ABORT(in_data);
+#endif
+
+ for(int x=0; x < i_data->width; x++)
+ {
+ float temp;
+
+ // BGRA -> ARGB
+ temp = pix->alpha; // BGRA temp B
+ pix->alpha = pix->blue; // AGRA temp B
+ pix->blue = temp; // AGRB temp B
+ temp = pix->red; // AGRB temp G
+ pix->red = pix->green; // ARRB temp G
+ pix->green = temp; // ARGB temp G
+
+ pix++;
+ }
+
+ return err;
+}
+
+
+typedef struct {
+ PF_InData *in_data;
+ void *buffer;
+ A_long rowbytes;
+ int width;
+ OpenColorIO_AE_Context *context;
+} ProcessData;
+
+static PF_Err Process_Iterate(
+ void *refconPV,
+ A_long thread_indexL,
+ A_long i,
+ A_long iterationsL)
+{
+ PF_Err err = PF_Err_NONE;
+
+ ProcessData *i_data = (ProcessData *)refconPV;
+ PF_InData *in_data = i_data->in_data;
+
+ PF_PixelFloat *pix = (PF_PixelFloat *)((char *)i_data->buffer + (i * i_data->rowbytes));
+
+#ifdef NDEBUG
+ if(thread_indexL == 0)
+ err = PF_ABORT(in_data);
+#endif
+
+ try
+ {
+ float *rOut = &pix->red;
+
+ OCIO::PackedImageDesc img(rOut, i_data->width, 1, 4);
+
+ i_data->context->processor()->apply(img);
+ }
+ catch(...)
+ {
+ err = PF_Err_INTERNAL_STRUCT_DAMAGED;
+ }
+
+
+ return err;
+}
+
+
+// two functions below to get Premiere to run my functions multi-threaded
+// because they couldn't bother to give me PF_Iterate8Suite1->iterate_generic
+
+typedef PF_Err (*GenericIterator)(void *refconPV,
+ A_long thread_indexL,
+ A_long i,
+ A_long iterationsL);
+
+typedef struct {
+ PF_InData *in_data;
+ GenericIterator fn_func;
+ void *refconPV;
+ A_long height;
+} FakeData;
+
+static PF_Err MyFakeIterator(
+ void *refcon,
+ A_long x,
+ A_long y,
+ PF_Pixel *in,
+ PF_Pixel *out)
+{
+ PF_Err err = PF_Err_NONE;
+
+ FakeData *i_data = (FakeData *)refcon;
+ PF_InData *in_data = i_data->in_data;
+
+ err = i_data->fn_func(i_data->refconPV, 1, y, i_data->height);
+
+ return err;
+}
+
+typedef PF_Err (*GenericIterateFunc)(
+ A_long iterationsL,
+ void *refconPV,
+ GenericIterator fn_func);
+
+static PF_Err MyGenericIterateFunc(
+ A_long iterationsL,
+ void *refconPV,
+ GenericIterator fn_func)
+{
+ PF_Err err = PF_Err_NONE;
+
+ PF_InData **in_dataH = (PF_InData **)refconPV; // always put PF_InData first
+ PF_InData *in_data = *in_dataH;
+
+ PF_Iterate8Suite1 *i8sP = NULL;
+ in_data->pica_basicP->AcquireSuite(kPFIterate8Suite, kPFIterate8SuiteVersion1, (const void **)&i8sP);
+
+ if(i8sP && i8sP->iterate)
+ {
+ PF_EffectWorld fake_world;
+ PF_NEW_WORLD(1, iterationsL, PF_NewWorldFlag_NONE, &fake_world);
+
+
+ FakeData i_data = { in_data, fn_func, refconPV, iterationsL };
+
+ err = i8sP->iterate(in_data, 0, iterationsL, &fake_world, NULL,
+ (void *)&i_data, MyFakeIterator, &fake_world);
+
+
+ PF_DISPOSE_WORLD(&fake_world);
+
+ in_data->pica_basicP->ReleaseSuite(kPFIterate8Suite, kPFIterate8SuiteVersion1);
+ }
+ else
+ {
+ for(int i=0; i < iterationsL && !err; i++)
+ {
+ err = fn_func(refconPV, 0, i, iterationsL);
+ }
+ }
+
+ return err;
+}
+
+
+static PF_Err DoRender(
+ PF_InData *in_data,
+ PF_EffectWorld *input,
+ PF_ParamDef *OCIO_data,
+ PF_ParamDef *OCIO_gpu,
+ PF_OutData *out_data,
+ PF_EffectWorld *output)
+{
+ PF_Err err = PF_Err_NONE;
+
+ AEGP_SuiteHandler suites(in_data->pica_basicP);
+
+ PF_PixelFormatSuite1 *pfS = NULL;
+ PF_WorldSuite2 *wsP = NULL;
+
+ err = in_data->pica_basicP->AcquireSuite(kPFPixelFormatSuite, kPFPixelFormatSuiteVersion1, (const void **)&pfS);
+ err = in_data->pica_basicP->AcquireSuite(kPFWorldSuite, kPFWorldSuiteVersion2, (const void **)&wsP);
+
+ if(!err)
+ {
+ ArbitraryData *arb_data = (ArbitraryData *)PF_LOCK_HANDLE(OCIO_data->u.arb_d.value);
+ SequenceData *seq_data = (SequenceData *)PF_LOCK_HANDLE(in_data->sequence_data);
+
+ try
+ {
+ seq_data->status = STATUS_OK;
+
+ std::string dir = GetProjectDir(in_data);
+
+ // must always verify that our context lines up with the parameters
+ // things like undo can change them without notice
+ if(seq_data->context != NULL)
+ {
+ bool verified = seq_data->context->Verify(arb_data, dir);
+
+ if(!verified)
+ {
+ delete seq_data->context;
+
+ seq_data->status = STATUS_UNKNOWN;
+ seq_data->context = NULL;
+ }
+ }
+
+
+ if(arb_data->action == OCIO_ACTION_NONE)
+ {
+ seq_data->status = STATUS_NO_FILE;
+ }
+ else if(seq_data->context == NULL)
+ {
+ seq_data->source = arb_data->source;
+
+ if(arb_data->source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ char *file = std::getenv("OCIO");
+
+ if(file == NULL)
+ seq_data->status = STATUS_FILE_MISSING;
+ }
+ else if(arb_data->source == OCIO_SOURCE_STANDARD)
+ {
+ std::string path = GetStdConfigPath(arb_data->path);
+
+ if( path.empty() )
+ {
+ seq_data->status = STATUS_FILE_MISSING;
+ }
+ else
+ {
+ strncpy(seq_data->path, arb_data->path, ARB_PATH_LEN);
+ strncpy(seq_data->relative_path, arb_data->relative_path, ARB_PATH_LEN);
+ }
+ }
+ else if(arb_data->source == OCIO_SOURCE_CUSTOM)
+ {
+ Path absolute_path(arb_data->path, dir);
+ Path relative_path(arb_data->relative_path, dir);
+ Path seq_absolute_path(seq_data->path, dir);
+ Path seq_relative_path(seq_data->relative_path, dir);
+
+ if( absolute_path.exists() )
+ {
+ seq_data->status = STATUS_USING_ABSOLUTE;
+
+ strncpy(seq_data->path, absolute_path.full_path().c_str(), ARB_PATH_LEN);
+ strncpy(seq_data->relative_path, absolute_path.relative_path(false).c_str(), ARB_PATH_LEN);
+ }
+ else if( relative_path.exists() )
+ {
+ seq_data->status = STATUS_USING_RELATIVE;
+
+ strncpy(seq_data->path, relative_path.full_path().c_str(), ARB_PATH_LEN);
+ strncpy(seq_data->relative_path, relative_path.relative_path(false).c_str(), ARB_PATH_LEN);
+ }
+ else if( seq_absolute_path.exists() )
+ {
+ // In some cases, we may have a good path in sequence options but not in
+ // the arbitrary parameter. An alert will not be provided because it is the
+ // sequence options that get checked. Therefore, we have to use the sequence
+ // options as a last resort. We copy the path back to arb data, but the change
+ // should not stick.
+ seq_data->status = STATUS_USING_ABSOLUTE;
+
+ strncpy(arb_data->path, seq_absolute_path.full_path().c_str(), ARB_PATH_LEN);
+ strncpy(arb_data->relative_path, seq_absolute_path.relative_path(false).c_str(), ARB_PATH_LEN);
+ }
+ else if( seq_relative_path.exists() )
+ {
+ seq_data->status = STATUS_USING_RELATIVE;
+
+ strncpy(arb_data->path, seq_relative_path.full_path().c_str(), ARB_PATH_LEN);
+ strncpy(arb_data->relative_path, seq_relative_path.relative_path(false).c_str(), ARB_PATH_LEN);
+ }
+ else
+ seq_data->status = STATUS_FILE_MISSING;
+ }
+
+
+ if(seq_data->status != STATUS_FILE_MISSING)
+ {
+ seq_data->context = new OpenColorIO_AE_Context(arb_data, dir);
+ }
+ }
+ }
+ catch(...)
+ {
+ seq_data->status = STATUS_OCIO_ERROR;
+ }
+
+
+ if(seq_data->status == STATUS_FILE_MISSING || seq_data->status == STATUS_OCIO_ERROR)
+ {
+ err = PF_Err_INTERNAL_STRUCT_DAMAGED;
+ }
+
+
+ if(!err)
+ {
+ if(seq_data->context == NULL || seq_data->context->processor()->isNoOp())
+ {
+ err = PF_COPY(input, output, NULL, NULL);
+ }
+ else
+ {
+ GenericIterateFunc iterate_generic = suites.Iterate8Suite1()->iterate_generic;
+
+ if(iterate_generic == NULL)
+ iterate_generic = MyGenericIterateFunc; // thanks a lot, Premiere
+
+ // OpenColorIO only does float worlds
+ // might have to create one
+ PF_EffectWorld *float_world = NULL;
+
+ PF_EffectWorld temp_world_data;
+ PF_EffectWorld *temp_world = NULL;
+ PF_Handle temp_worldH = NULL;
+
+
+ PF_PixelFormat format;
+ wsP->PF_GetPixelFormat(output, &format);
+
+ if(in_data->appl_id == 'PrMr' && pfS)
+ {
+ // the regular world suite function will give a bogus value for Premiere
+ pfS->GetPixelFormat(output, (PrPixelFormat *)&format);
+
+ seq_data->prem_status = (format == PrPixelFormat_BGRA_4444_32f_Linear ?
+ PREMIERE_LINEAR : PREMIERE_NON_LINEAR);
+ }
+
+
+ A_Boolean use_gpu = OCIO_gpu->u.bd.value;
+ seq_data->gpu_err = GPU_ERR_NONE;
+ A_long non_padded_rowbytes = sizeof(PF_PixelFloat) * output->width;
+
+
+ if(format == PF_PixelFormat_ARGB128 &&
+ (!use_gpu || output->rowbytes == non_padded_rowbytes)) // GPU doesn't do padding
+ {
+ err = PF_COPY(input, output, NULL, NULL);
+
+ float_world = output;
+ }
+ else
+ {
+ temp_worldH = PF_NEW_HANDLE(non_padded_rowbytes * (output->height + 1)); // little extra because we go over by a channel
+
+ if(temp_worldH)
+ {
+ temp_world_data.data = (PF_PixelPtr)PF_LOCK_HANDLE(temp_worldH);
+
+ temp_world_data.width = output->width;
+ temp_world_data.height = output->height;
+ temp_world_data.rowbytes = non_padded_rowbytes;
+
+ float_world = temp_world = &temp_world_data;
+
+ // convert to new temp float world
+ IterateData i_data = { in_data, input->data, input->rowbytes,
+ float_world->data, float_world->rowbytes,
+ float_world->width * 4 };
+
+ if(format == PF_PixelFormat_ARGB32 || format == PrPixelFormat_BGRA_4444_8u)
+ {
+ err = iterate_generic(float_world->height, &i_data,
+ CopyWorld_Iterate<A_u_char, float>);
+ }
+ else if(format == PF_PixelFormat_ARGB64)
+ {
+ err = iterate_generic(float_world->height, &i_data,
+ CopyWorld_Iterate<A_u_short, float>);
+ }
+ else if(format == PF_PixelFormat_ARGB128 ||
+ format == PrPixelFormat_BGRA_4444_32f ||
+ format == PrPixelFormat_BGRA_4444_32f_Linear)
+ {
+ err = iterate_generic(float_world->height, &i_data,
+ CopyWorld_Iterate<float, float>);
+ }
+
+ // switch BGRA to ARGB for premiere
+ if(!err &&
+ (format == PrPixelFormat_BGRA_4444_8u ||
+ format == PrPixelFormat_BGRA_4444_32f_Linear ||
+ format == PrPixelFormat_BGRA_4444_32f))
+ {
+ SwapData s_data = { in_data, float_world->data,
+ float_world->rowbytes, float_world->width };
+
+ err = iterate_generic(float_world->height, &s_data,
+ Swap_Iterate);
+ }
+ }
+ else
+ err = PF_Err_OUT_OF_MEMORY;
+ }
+
+
+ if(!err)
+ {
+ bool gpu_rendered = false;
+
+ // OpenColorIO processing
+ if(use_gpu)
+ {
+ if( HaveOpenGL() )
+ {
+ gpu_rendered = seq_data->context->ProcessWorldGL(float_world);
+
+ if(!gpu_rendered)
+ seq_data->gpu_err = GPU_ERR_RENDER_ERR;
+ }
+ else
+ seq_data->gpu_err = GPU_ERR_INSUFFICIENT;
+ }
+
+ if(!gpu_rendered)
+ {
+ ProcessData p_data = { in_data,
+ float_world->data,
+ float_world->rowbytes,
+ float_world->width,
+ seq_data->context };
+
+ err = iterate_generic(float_world->height, &p_data, Process_Iterate);
+ }
+ }
+
+
+ // copy back to non-float world and dispose
+ if(temp_world)
+ {
+ if(!err &&
+ (format == PrPixelFormat_BGRA_4444_8u ||
+ format == PrPixelFormat_BGRA_4444_32f_Linear ||
+ format == PrPixelFormat_BGRA_4444_32f))
+ {
+ SwapData s_data = { in_data, float_world->data,
+ float_world->rowbytes, float_world->width };
+
+ err = iterate_generic(float_world->height, &s_data, Swap_Iterate);
+ }
+
+ if(!err)
+ {
+ IterateData i_data = { in_data, float_world->data,
+ float_world->rowbytes, output->data,
+ output->rowbytes, output->width * 4 };
+
+ if(format == PF_PixelFormat_ARGB32 || format == PrPixelFormat_BGRA_4444_8u)
+ {
+ err = iterate_generic(output->height, &i_data,
+ CopyWorld_Iterate<float, A_u_char>);
+ }
+ else if(format == PF_PixelFormat_ARGB64)
+ {
+ err = iterate_generic(output->height, &i_data,
+ CopyWorld_Iterate<float, A_u_short>);
+ }
+ else if(format == PF_PixelFormat_ARGB128 ||
+ format == PrPixelFormat_BGRA_4444_32f ||
+ format == PrPixelFormat_BGRA_4444_32f_Linear)
+ {
+ err = iterate_generic(output->height, &i_data,
+ CopyWorld_Iterate<float, float>);
+ }
+
+ }
+
+ PF_DISPOSE_HANDLE(temp_worldH);
+ }
+
+
+ PF_UNLOCK_HANDLE(OCIO_data->u.arb_d.value);
+ PF_UNLOCK_HANDLE(in_data->sequence_data);
+
+
+ if(seq_data->gpu_err == GPU_ERR_INSUFFICIENT)
+ {
+ suites.AdvAppSuite2()->PF_AppendInfoText("OpenColorIO: GPU Insufficient");
+ }
+ else if(seq_data->gpu_err == GPU_ERR_RENDER_ERR)
+ {
+ suites.AdvAppSuite2()->PF_AppendInfoText("OpenColorIO: GPU Render Error");
+ }
+ }
+ }
+ }
+
+ if(pfS)
+ in_data->pica_basicP->ReleaseSuite(kPFPixelFormatSuite, kPFPixelFormatSuiteVersion1);
+
+ if(wsP)
+ in_data->pica_basicP->ReleaseSuite(kPFWorldSuite, kPFWorldSuiteVersion2);
+
+
+
+ return err;
+}
+
+
+static PF_Err SmartRender(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_SmartRenderExtra *extra)
+
+{
+ PF_Err err = PF_Err_NONE,
+ err2 = PF_Err_NONE;
+
+ PF_EffectWorld *input, *output;
+
+ PF_ParamDef OCIO_data, OCIO_gpu;
+
+ // zero-out parameters
+ AEFX_CLR_STRUCT(OCIO_data);
+ AEFX_CLR_STRUCT(OCIO_gpu);
+
+
+ // checkout input & output buffers.
+ ERR( extra->cb->checkout_layer_pixels( in_data->effect_ref, OCIO_INPUT, &input) );
+ ERR( extra->cb->checkout_output( in_data->effect_ref, &output) );
+
+
+ // bail before param checkout
+ if(err)
+ return err;
+
+#define PF_CHECKOUT_PARAM_NOW( PARAM, DEST ) \
+ PF_CHECKOUT_PARAM( in_data, (PARAM), in_data->current_time,\
+ in_data->time_step, in_data->time_scale, DEST )
+
+ // checkout the required params
+ ERR( PF_CHECKOUT_PARAM_NOW( OCIO_DATA, &OCIO_data ) );
+ ERR( PF_CHECKOUT_PARAM_NOW( OCIO_GPU, &OCIO_gpu ) );
+
+ ERR(DoRender( in_data,
+ input,
+ &OCIO_data,
+ &OCIO_gpu,
+ out_data,
+ output));
+
+ // Always check in, no matter what the error condition!
+ ERR2( PF_CHECKIN_PARAM(in_data, &OCIO_data ) );
+ ERR2( PF_CHECKIN_PARAM(in_data, &OCIO_gpu ) );
+
+
+ return err;
+
+}
+
+
+static PF_Err Render(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output )
+{
+ return DoRender(in_data,
+ &params[OCIO_INPUT]->u.ld,
+ params[OCIO_DATA],
+ params[OCIO_GPU],
+ out_data,
+ output);
+}
+
+
+static PF_Err GetExternalDependencies(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ExtDependenciesExtra *extra)
+
+{
+ PF_Err err = PF_Err_NONE;
+
+ SequenceData *seq_data = (SequenceData *)PF_LOCK_HANDLE(in_data->sequence_data);
+
+ if(seq_data == NULL)
+ return PF_Err_BAD_CALLBACK_PARAM;
+
+
+ std::string dependency;
+
+ if(seq_data->source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ if(extra->check_type == PF_DepCheckType_ALL_DEPENDENCIES)
+ {
+ dependency = "$OCIO environment variable";
+ }
+ else if(extra->check_type == PF_DepCheckType_MISSING_DEPENDENCIES)
+ {
+ char *file = std::getenv("OCIO");
+
+ if(!file)
+ dependency = "$OCIO environment variable";
+ }
+ }
+ else if(seq_data->source == OCIO_SOURCE_STANDARD)
+ {
+ if(extra->check_type == PF_DepCheckType_ALL_DEPENDENCIES)
+ {
+ dependency = "OCIO configuration " + std::string(seq_data->path);
+ }
+ else if(extra->check_type == PF_DepCheckType_MISSING_DEPENDENCIES)
+ {
+ std::string path = GetStdConfigPath(seq_data->path);
+
+ if( path.empty() )
+ dependency = "OCIO configuration " + std::string(seq_data->path);
+ }
+ }
+ else if(seq_data->source == OCIO_SOURCE_CUSTOM && seq_data->path[0] != '\0')
+ {
+ std::string dir = GetProjectDir(in_data);
+
+ Path absolute_path(seq_data->path, "");
+ Path relative_path(seq_data->relative_path, dir);
+
+ if(extra->check_type == PF_DepCheckType_ALL_DEPENDENCIES)
+ {
+ if( !absolute_path.exists() && relative_path.exists() )
+ {
+ dependency = relative_path.full_path();
+ }
+ else
+ dependency = absolute_path.full_path();
+ }
+ else if(extra->check_type == PF_DepCheckType_MISSING_DEPENDENCIES &&
+ !absolute_path.exists() && !relative_path.exists() )
+ {
+ dependency = absolute_path.full_path();
+ }
+ }
+
+
+ if( !dependency.empty() )
+ {
+ extra->dependencies_strH = PF_NEW_HANDLE(sizeof(char) * (dependency.size() + 1));
+
+ char *p = (char *)PF_LOCK_HANDLE(extra->dependencies_strH);
+
+ strcpy(p, dependency.c_str());
+ }
+
+
+ PF_UNLOCK_HANDLE(in_data->sequence_data);
+
+ return err;
+}
+
+
+DllExport PF_Err PluginMain(
+ PF_Cmd cmd,
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ void *extra)
+{
+ PF_Err err = PF_Err_NONE;
+
+ try {
+ switch(cmd) {
+ case PF_Cmd_ABOUT:
+ err = About(in_data,out_data,params,output);
+ break;
+ case PF_Cmd_GLOBAL_SETUP:
+ err = GlobalSetup(in_data,out_data,params,output);
+ break;
+ case PF_Cmd_GLOBAL_SETDOWN:
+ err = GlobalSetdown(in_data,out_data,params,output);
+ break;
+ case PF_Cmd_PARAMS_SETUP:
+ err = ParamsSetup(in_data,out_data,params,output);
+ break;
+ case PF_Cmd_SEQUENCE_SETUP:
+ case PF_Cmd_SEQUENCE_RESETUP:
+ err = SequenceSetup(in_data, out_data, params, output);
+ break;
+ case PF_Cmd_SEQUENCE_FLATTEN:
+ err = SequenceFlatten(in_data, out_data, params, output);
+ break;
+ case PF_Cmd_SEQUENCE_SETDOWN:
+ err = SequenceSetdown(in_data, out_data, params, output);
+ break;
+ case PF_Cmd_SMART_PRE_RENDER:
+ err = PreRender(in_data, out_data, (PF_PreRenderExtra*)extra);
+ break;
+ case PF_Cmd_SMART_RENDER:
+ err = SmartRender(in_data, out_data, (PF_SmartRenderExtra*)extra);
+ break;
+ case PF_Cmd_RENDER:
+ err = Render(in_data, out_data, params, output);
+ break;
+ case PF_Cmd_EVENT:
+ err = HandleEvent(in_data, out_data, params, output, (PF_EventExtra *)extra);
+ break;
+ case PF_Cmd_ARBITRARY_CALLBACK:
+ err = HandleArbitrary(in_data, out_data, params, output, (PF_ArbParamsExtra *)extra);
+ break;
+ case PF_Cmd_GET_EXTERNAL_DEPENDENCIES:
+ err = GetExternalDependencies(in_data, out_data, (PF_ExtDependenciesExtra *)extra);
+ break;
+ }
+ }
+ catch(PF_Err &thrown_err) { err = thrown_err; }
+ catch(...) { err = PF_Err_INTERNAL_STRUCT_DAMAGED; }
+
+ return err;
+}
diff --git a/src/aftereffects/OpenColorIO_AE.h b/src/aftereffects/OpenColorIO_AE.h
new file mode 100755
index 0000000..98eb314
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE.h
@@ -0,0 +1,227 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+
+#ifndef _OPENCOLORIO_AE_H_
+#define _OPENCOLORIO_AE_H_
+
+
+//#define PF_DEEP_COLOR_AWARE 1 // do we really still need this?
+
+#include "AEConfig.h"
+#include "entry.h"
+#include "SPTypes.h"
+#include "PrSDKAESupport.h"
+#include "AE_Macros.h"
+#include "Param_Utils.h"
+#include "AE_Effect.h"
+#include "AE_EffectUI.h"
+#include "AE_EffectCB.h"
+
+
+#ifdef MSWindows
+ #include <Windows.h>
+#else
+ #ifndef __MACH__
+ #include "string.h"
+ #endif
+#endif
+
+
+// Versioning information
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+#define BUG_VERSION 0
+#define STAGE_VERSION PF_Stage_RELEASE
+#define BUILD_VERSION 0
+
+// Paramater constants
+enum {
+ OCIO_INPUT = 0,
+ OCIO_DATA,
+ OCIO_GPU,
+
+ OCIO_NUM_PARAMS
+};
+
+enum {
+ OCIO_DATA_ID = 1,
+ OCIO_GPU_ID
+};
+
+
+// Our Arbitrary Data struct
+
+#define CURRENT_ARB_VERSION 1
+#define ARB_PATH_LEN 255
+#define ARB_SPACE_LEN 63
+
+enum {
+ OCIO_ACTION_NONE = 0,
+ OCIO_ACTION_LUT,
+ OCIO_ACTION_CONVERT,
+ OCIO_ACTION_DISPLAY
+};
+typedef A_u_char OCIO_Action;
+
+enum {
+ OCIO_STORAGE_NONE = 0,
+ OCIO_STORAGE_ZIP_FILE
+};
+typedef A_u_char OCIO_Storage;
+
+enum {
+ OCIO_SOURCE_NONE = 0,
+ OCIO_SOURCE_ENVIRONMENT,
+ OCIO_SOURCE_STANDARD,
+ OCIO_SOURCE_CUSTOM
+};
+typedef A_u_char OCIO_Source;
+
+enum {
+ OCIO_INTERP_UNKNOWN = 0,
+ OCIO_INTERP_NEAREST = 1,
+ OCIO_INTERP_LINEAR = 2,
+ OCIO_INTERP_TETRAHEDRAL = 3,
+ OCIO_INTERP_BEST = 255
+};
+typedef A_u_char OCIO_Interp;
+
+typedef struct {
+ A_u_char version; // version of this data structure
+ OCIO_Action action;
+ A_Boolean invert; // only used for LUTs
+ OCIO_Storage storage; // storage not used...yet
+ A_u_long storage_size;
+ OCIO_Source source;
+ OCIO_Interp interpolation;
+ A_u_char reserved[54]; // 64 pre-path bytes
+ char path[ARB_PATH_LEN+1];
+ char relative_path[ARB_PATH_LEN+1];
+ char input[ARB_SPACE_LEN+1];
+ char output[ARB_SPACE_LEN+1];
+ char transform[ARB_SPACE_LEN+1];
+ char device[ARB_SPACE_LEN+1];
+ char look[ARB_SPACE_LEN+1]; // not used currently
+ A_u_char storage_buf[1];
+} ArbitraryData;
+
+
+#ifdef __cplusplus
+
+class OpenColorIO_AE_Context;
+
+enum {
+ STATUS_UNKNOWN = 0,
+ STATUS_OK,
+ STATUS_NO_FILE,
+ STATUS_USING_ABSOLUTE,
+ STATUS_USING_RELATIVE,
+ STATUS_FILE_MISSING,
+ STATUS_OCIO_ERROR
+};
+typedef A_u_char FileStatus;
+
+enum {
+ GPU_ERR_NONE = 0,
+ GPU_ERR_INSUFFICIENT,
+ GPU_ERR_RENDER_ERR
+};
+typedef A_u_char GPUErr;
+
+enum {
+ PREMIERE_UNKNOWN = 0,
+ PREMIERE_LINEAR,
+ PREMIERE_NON_LINEAR
+};
+typedef A_u_char PremiereStatus;
+
+typedef struct {
+ FileStatus status;
+ GPUErr gpu_err;
+ PremiereStatus prem_status;
+ OCIO_Source source;
+ OpenColorIO_AE_Context *context;
+ char path[ARB_PATH_LEN+1];
+ char relative_path[ARB_PATH_LEN+1];
+} SequenceData;
+
+#endif
+
+
+
+#define UI_CONTROL_HEIGHT 200
+#define UI_CONTROL_WIDTH 500
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+// Prototypes
+
+DllExport PF_Err PluginMain(
+ PF_Cmd cmd,
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ void *extra) ;
+
+
+PF_Err HandleEvent(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *extra );
+
+
+PF_Err ArbNewDefault( // needed by ParamSetup()
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH *arbPH);
+
+PF_Err HandleArbitrary(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_ArbParamsExtra *extra);
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+
+#endif // _OPENCOLORIO_AE_H_ \ No newline at end of file
diff --git a/src/aftereffects/OpenColorIO_AE_ArbData.cpp b/src/aftereffects/OpenColorIO_AE_ArbData.cpp
new file mode 100644
index 0000000..0e55541
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_ArbData.cpp
@@ -0,0 +1,408 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE.h"
+
+#include "OpenColorIO_AE_Context.h"
+
+#include <assert.h>
+
+
+PF_Err ArbNewDefault(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH *arbPH)
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(arbPH)
+ {
+ *arbPH = PF_NEW_HANDLE( sizeof(ArbitraryData) );
+
+ if(*arbPH)
+ {
+ ArbitraryData *arb_data = (ArbitraryData *)PF_LOCK_HANDLE(*arbPH);
+
+ // set up defaults
+ arb_data->version = CURRENT_ARB_VERSION;
+
+ arb_data->action = OCIO_ACTION_NONE;
+ arb_data->invert = FALSE;
+
+ arb_data->storage = OCIO_STORAGE_NONE;
+ arb_data->storage_size = 0;
+ arb_data->source = OCIO_SOURCE_NONE;
+ arb_data->interpolation = OCIO_INTERP_LINEAR;
+
+ arb_data->path[0] = '\0';
+ arb_data->relative_path[0] = '\0';
+
+ arb_data->input[0] = '\0';
+ arb_data->output[0] = '\0';
+ arb_data->transform[0] = '\0';
+ arb_data->device[0] = '\0';
+ arb_data->look[0] = '\0';
+
+
+ // set default with environment variable if it's set
+ char *file = std::getenv("OCIO");
+
+ if(file)
+ {
+ try
+ {
+ OpenColorIO_AE_Context context(file, OCIO_SOURCE_ENVIRONMENT);
+
+ strncpy(arb_data->path, file, ARB_PATH_LEN);
+
+ arb_data->action = context.getAction();
+ arb_data->source = OCIO_SOURCE_ENVIRONMENT;
+
+ if(arb_data->action != OCIO_ACTION_LUT)
+ {
+ strncpy(arb_data->input, context.getInput().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->output, context.getOutput().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->transform, context.getTransform().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->device, context.getDevice().c_str(), ARB_SPACE_LEN);
+ }
+ }
+ catch(...) {}
+ }
+
+
+ PF_UNLOCK_HANDLE(*arbPH);
+ }
+ }
+
+ return err;
+}
+
+
+static PF_Err ArbDispose(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH arbH)
+{
+ if(arbH)
+ PF_DISPOSE_HANDLE(arbH);
+
+ return PF_Err_NONE;
+}
+
+
+static void CopyArbData(ArbitraryData *out_arb_data, ArbitraryData *in_arb_data)
+{
+ // copy contents
+ out_arb_data->version = in_arb_data->version;
+
+ out_arb_data->action = in_arb_data->action;
+
+ out_arb_data->invert = in_arb_data->invert;
+
+ out_arb_data->storage = in_arb_data->storage;
+ out_arb_data->storage_size = in_arb_data->storage_size;
+
+ out_arb_data->source = in_arb_data->source;
+
+ out_arb_data->interpolation = in_arb_data->interpolation;
+
+ strcpy(out_arb_data->path, in_arb_data->path);
+ strcpy(out_arb_data->relative_path, in_arb_data->relative_path);
+
+ strcpy(out_arb_data->input, in_arb_data->input);
+ strcpy(out_arb_data->output, in_arb_data->output);
+ strcpy(out_arb_data->transform, in_arb_data->transform);
+ strcpy(out_arb_data->device, in_arb_data->device);
+ strcpy(out_arb_data->look, in_arb_data->look);
+}
+
+
+static PF_Err ArbCopy(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH src_arbH,
+ PF_ArbitraryH *dst_arbPH)
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(src_arbH && dst_arbPH)
+ {
+ // allocate using the creation function
+ err = ArbNewDefault(in_data, out_data, refconPV, dst_arbPH);
+
+ if(!err)
+ {
+ ArbitraryData *in_arb_data = (ArbitraryData *)PF_LOCK_HANDLE(src_arbH),
+ *out_arb_data = (ArbitraryData *)PF_LOCK_HANDLE(*dst_arbPH);
+
+ CopyArbData(out_arb_data, in_arb_data);
+
+ PF_UNLOCK_HANDLE(src_arbH);
+ PF_UNLOCK_HANDLE(*dst_arbPH);
+ }
+ }
+
+ return err;
+}
+
+
+static PF_Err ArbFlatSize(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH arbH,
+ A_u_long *flat_data_sizePLu)
+{
+ // flat is the same size as inflated
+ if(arbH)
+ *flat_data_sizePLu = PF_GET_HANDLE_SIZE(arbH);
+
+ return PF_Err_NONE;
+}
+
+
+static void SwapArbData(ArbitraryData *arb_data)
+{
+
+}
+
+
+static PF_Err ArbFlatten(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH arbH,
+ A_u_long buf_sizeLu,
+ void *flat_dataPV)
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(arbH && flat_dataPV)
+ {
+ // they provide the buffer, we just move data
+ ArbitraryData *in_arb_data = (ArbitraryData *)PF_LOCK_HANDLE(arbH),
+ *out_arb_data = (ArbitraryData *)flat_dataPV;
+
+ assert(buf_sizeLu >= PF_GET_HANDLE_SIZE(arbH));
+
+ CopyArbData(out_arb_data, in_arb_data);
+
+ #ifdef AE_BIG_ENDIAN
+ // not that we're doing a PPC version of this...
+ SwapArbData(out_arb_data);
+ #endif
+
+ PF_UNLOCK_HANDLE(arbH);
+ }
+
+ return err;
+}
+
+
+static PF_Err ArbUnFlatten(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ A_u_long buf_sizeLu,
+ const void *flat_dataPV,
+ PF_ArbitraryH *arbPH)
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(arbPH && flat_dataPV)
+ {
+ // they provide a flat buffer, we have to make the handle
+ err = ArbNewDefault(in_data, out_data, refconPV, arbPH);
+
+ if(!err && *arbPH)
+ {
+ ArbitraryData *in_arb_data = (ArbitraryData *)flat_dataPV,
+ *out_arb_data = (ArbitraryData *)PF_LOCK_HANDLE(*arbPH);
+
+ assert(buf_sizeLu <= PF_GET_HANDLE_SIZE(*arbPH));
+
+ CopyArbData(out_arb_data, in_arb_data);
+
+ #ifdef AE_BIG_ENDIAN
+ SwapArbData(out_arb_data);
+ #endif
+
+ PF_UNLOCK_HANDLE(*arbPH);
+ }
+ }
+
+ return err;
+}
+
+static PF_Err ArbInterpolate(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH left_arbH,
+ PF_ArbitraryH right_arbH,
+ PF_FpLong tF,
+ PF_ArbitraryH *interpPH)
+{
+ PF_Err err = PF_Err_NONE;
+
+ assert(FALSE); // we shouldn't be doing this
+
+ if(left_arbH && right_arbH && interpPH)
+ {
+ // allocate using our own func
+ err = ArbNewDefault(in_data, out_data, refconPV, interpPH);
+
+ if(!err && *interpPH)
+ {
+ // we're just going to copy the left_data
+ ArbitraryData *in_arb_data = (ArbitraryData *)PF_LOCK_HANDLE(left_arbH),
+ *out_arb_data = (ArbitraryData *)PF_LOCK_HANDLE(*interpPH);
+
+ CopyArbData(out_arb_data, in_arb_data);
+
+ PF_UNLOCK_HANDLE(left_arbH);
+ PF_UNLOCK_HANDLE(*interpPH);
+ }
+ }
+
+ return err;
+}
+
+
+static PF_Err ArbCompare(PF_InData *in_data, PF_OutData *out_data,
+ void *refconPV,
+ PF_ArbitraryH a_arbH,
+ PF_ArbitraryH b_arbH,
+ PF_ArbCompareResult *compareP)
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(a_arbH && b_arbH)
+ {
+ ArbitraryData *a_data = (ArbitraryData *)PF_LOCK_HANDLE(a_arbH),
+ *b_data = (ArbitraryData *)PF_LOCK_HANDLE(b_arbH);
+
+
+ if( a_data->version == b_data->version &&
+ a_data->action == b_data->action &&
+ a_data->invert == b_data->invert &&
+ a_data->source == b_data->source &&
+ a_data->interpolation == b_data->interpolation &&
+ !strcmp(a_data->path, b_data->path) &&
+ !strcmp(a_data->input, b_data->input) &&
+ !strcmp(a_data->output, b_data->output) &&
+ !strcmp(a_data->transform, b_data->transform) &&
+ !strcmp(a_data->device, b_data->device) &&
+ !strcmp(a_data->look, b_data->look) )
+ {
+ *compareP = PF_ArbCompare_EQUAL;
+ }
+ else
+ {
+ *compareP = PF_ArbCompare_NOT_EQUAL;
+ }
+
+
+ PF_UNLOCK_HANDLE(a_arbH);
+ PF_UNLOCK_HANDLE(b_arbH);
+ }
+
+ return err;
+}
+
+
+PF_Err HandleArbitrary(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_ArbParamsExtra *extra)
+{
+ PF_Err err = PF_Err_NONE;
+
+ if(extra->id == OCIO_DATA_ID)
+ {
+ switch(extra->which_function)
+ {
+ case PF_Arbitrary_NEW_FUNC:
+ err = ArbNewDefault(in_data, out_data,
+ extra->u.new_func_params.refconPV,
+ extra->u.new_func_params.arbPH);
+ break;
+ case PF_Arbitrary_DISPOSE_FUNC:
+ err = ArbDispose(in_data, out_data,
+ extra->u.dispose_func_params.refconPV,
+ extra->u.dispose_func_params.arbH);
+ break;
+ case PF_Arbitrary_COPY_FUNC:
+ err = ArbCopy(in_data, out_data, extra->u.copy_func_params.refconPV,
+ extra->u.copy_func_params.src_arbH,
+ extra->u.copy_func_params.dst_arbPH);
+ break;
+ case PF_Arbitrary_FLAT_SIZE_FUNC:
+ err = ArbFlatSize(in_data, out_data,
+ extra->u.flat_size_func_params.refconPV,
+ extra->u.flat_size_func_params.arbH,
+ extra->u.flat_size_func_params.flat_data_sizePLu);
+ break;
+ case PF_Arbitrary_FLATTEN_FUNC:
+ err = ArbFlatten(in_data, out_data,
+ extra->u.flatten_func_params.refconPV,
+ extra->u.flatten_func_params.arbH,
+ extra->u.flatten_func_params.buf_sizeLu,
+ extra->u.flatten_func_params.flat_dataPV);
+ break;
+ case PF_Arbitrary_UNFLATTEN_FUNC:
+ err = ArbUnFlatten(in_data, out_data,
+ extra->u.unflatten_func_params.refconPV,
+ extra->u.unflatten_func_params.buf_sizeLu,
+ extra->u.unflatten_func_params.flat_dataPV,
+ extra->u.unflatten_func_params.arbPH);
+ break;
+ case PF_Arbitrary_INTERP_FUNC:
+ err = ArbInterpolate(in_data, out_data,
+ extra->u.interp_func_params.refconPV,
+ extra->u.interp_func_params.left_arbH,
+ extra->u.interp_func_params.right_arbH,
+ extra->u.interp_func_params.tF,
+ extra->u.interp_func_params.interpPH);
+ break;
+ case PF_Arbitrary_COMPARE_FUNC:
+ err = ArbCompare(in_data, out_data,
+ extra->u.compare_func_params.refconPV,
+ extra->u.compare_func_params.a_arbH,
+ extra->u.compare_func_params.b_arbH,
+ extra->u.compare_func_params.compareP);
+ break;
+ // these are necessary for copying and pasting keyframes
+ // for now, we better not be called to do this
+ case PF_Arbitrary_PRINT_SIZE_FUNC:
+ assert(FALSE);
+ break;
+ case PF_Arbitrary_PRINT_FUNC:
+ assert(FALSE);
+ break;
+ case PF_Arbitrary_SCAN_FUNC:
+ assert(FALSE);
+ break;
+ }
+ }
+
+
+ return err;
+}
diff --git a/src/aftereffects/OpenColorIO_AE_Context.cpp b/src/aftereffects/OpenColorIO_AE_Context.cpp
new file mode 100644
index 0000000..1da7ee8
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_Context.cpp
@@ -0,0 +1,1051 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE_Context.h"
+
+#include <fstream>
+#include <map>
+#include <sstream>
+
+#include "ocioicc.h"
+
+#include "OpenColorIO_AE_Dialogs.h"
+
+
+
+
+static const char mac_delimiter = '/';
+static const char win_delimiter = '\\';
+
+#ifdef WIN_ENV
+static const char delimiter = win_delimiter;
+#else
+static const char delimiter = mac_delimiter;
+#endif
+
+static const int LUT3D_EDGE_SIZE = 32;
+
+
+Path::Path(const std::string &path, const std::string &dir) :
+ _path(path),
+ _dir(dir)
+{
+
+}
+
+
+Path::Path(const Path &path)
+{
+ _path = path._path;
+ _dir = path._dir;
+}
+
+
+std::string Path::full_path() const
+{
+ if( is_relative(_path) && !_dir.empty() )
+ {
+ std::vector<std::string> path_vec = components( convert_delimiters(_path) );
+ std::vector<std::string> dir_vec = components(_dir);
+
+ int up_dirs = 0;
+ int down_dirs = 0;
+
+ while(down_dirs < path_vec.size() - 1 &&
+ (path_vec[down_dirs] == ".." || path_vec[down_dirs] == ".") )
+ {
+ down_dirs++;
+
+ if(path_vec[down_dirs] == "..")
+ up_dirs++;
+ }
+
+
+ std::string path;
+
+ if(path_type(_dir) == TYPE_MAC)
+ path += mac_delimiter;
+
+ for(int i=0; i < dir_vec.size() - up_dirs; i++)
+ {
+ path += dir_vec[i] + delimiter;
+ }
+
+ for(int i = down_dirs; i < path_vec.size() - 1; i++)
+ {
+ path += path_vec[i] + delimiter;
+ }
+
+ path += path_vec.back();
+
+ return path;
+ }
+ else
+ {
+ return _path;
+ }
+}
+
+
+std::string Path::relative_path(bool force) const
+{
+ if( is_relative(_path) || _dir.empty() || _path.empty() )
+ {
+ return _path;
+ }
+ else
+ {
+ std::vector<std::string> path_vec = components(_path);
+ std::vector<std::string> dir_vec = components(_dir);
+
+ int match_idx = 0;
+
+ while(match_idx < path_vec.size() &&
+ match_idx < dir_vec.size() &&
+ path_vec[match_idx] == dir_vec[match_idx])
+ match_idx++;
+
+ if(match_idx == 0)
+ {
+ // can't do relative path
+ if(force)
+ return _path;
+ else
+ return "";
+ }
+ else
+ {
+ std::string rel_path;
+
+ // is the file in a folder below or actually inside the dir?
+ if(match_idx == dir_vec.size())
+ {
+ rel_path += std::string(".") + delimiter;
+ }
+ else
+ {
+ for(int i = match_idx; i < dir_vec.size(); i++)
+ {
+ rel_path += std::string("..") + delimiter;
+ }
+ }
+
+ for(int i = match_idx; i < path_vec.size() - 1; i++)
+ {
+ rel_path += path_vec[i] + delimiter;
+ }
+
+ rel_path += path_vec.back();
+
+ return rel_path;
+ }
+ }
+}
+
+
+bool Path::exists() const
+{
+ std::string path = full_path();
+
+ if(path.empty())
+ return false;
+
+ std::ifstream f( path.c_str() );
+
+ return !!f;
+}
+
+
+Path::PathType Path::path_type(std::string path)
+{
+ if( path.empty() )
+ {
+ return TYPE_UNKNOWN;
+ }
+ if(path[0] == mac_delimiter)
+ {
+ return TYPE_MAC;
+ }
+ else if(path[1] == ':' && path[2] == win_delimiter)
+ {
+ return TYPE_WIN;
+ }
+ else if(path[0] == win_delimiter && path[1] == win_delimiter)
+ {
+ return TYPE_WIN;
+ }
+ else
+ {
+ size_t mac_pos = path.find(mac_delimiter);
+ size_t win_pos = path.find(win_delimiter);
+
+ if(mac_pos != std::string::npos && win_pos == std::string::npos)
+ {
+ return TYPE_MAC;
+ }
+ else if(mac_pos == std::string::npos && win_pos != std::string::npos)
+ {
+ return TYPE_WIN;
+ }
+ else if(mac_pos == std::string::npos && win_pos == std::string::npos)
+ {
+ return TYPE_UNKNOWN;
+ }
+ else // neither npos?
+ {
+ if(mac_pos < win_pos)
+ return TYPE_MAC;
+ else
+ return TYPE_WIN;
+ }
+ }
+}
+
+
+bool Path::is_relative(std::string path)
+{
+ Path::PathType type = path_type(path);
+
+ if(type == TYPE_MAC)
+ {
+ return (path[0] != mac_delimiter);
+ }
+ else if(type == TYPE_WIN)
+ {
+ return !( (path[1] == ':' && path[2] == win_delimiter) ||
+ (path[0] == win_delimiter && path[1] == win_delimiter) );
+ }
+ else
+ { // TYPE_UNKNOWN
+
+ // just a filename perhaps?
+ // should never have this: even a file in the same directory will be ./file.ocio
+ // we'll assume it's relative, but raise a stink during debugging
+ assert(type != TYPE_UNKNOWN);
+
+ return true;
+ }
+}
+
+
+std::string Path::convert_delimiters(std::string path)
+{
+#ifdef WIN_ENV
+ char search = mac_delimiter;
+ char replace = win_delimiter;
+#else
+ char search = win_delimiter;
+ char replace = mac_delimiter;
+#endif
+
+ for(int i=0; i < path.size(); i++)
+ {
+ if(path[i] == search)
+ path[i] = replace;
+ }
+
+ return path;
+}
+
+
+std::vector<std::string> Path::components(std::string path)
+{
+ std::vector<std::string> vec;
+
+ size_t pos = 0;
+ size_t len = path.size();
+
+ size_t start, finish;
+
+ while(path[pos] == delimiter && pos < len)
+ pos++;
+
+ while(pos < len)
+ {
+ start = pos;
+
+ while(path[pos] != delimiter && pos < len)
+ pos++;
+
+ finish = ((pos == len - 1) ? pos : pos - 1);
+
+ vec.push_back( path.substr(start, 1 + finish - start) );
+
+ while(path[pos] == delimiter && pos < len)
+ pos++;
+ }
+
+ return vec;
+}
+
+
+#pragma mark-
+
+
+OpenColorIO_AE_Context::OpenColorIO_AE_Context(const std::string &path, OCIO_Source source) :
+ _gl_init(false)
+{
+ _action = OCIO_ACTION_NONE;
+
+
+ _source = source;
+
+ if(_source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ char *file = getenv("OCIO");
+
+ if(file)
+ {
+ _path = file;
+ }
+ else
+ throw OCIO::Exception("No $OCIO environment variable.");
+ }
+ else if(_source == OCIO_SOURCE_STANDARD)
+ {
+ _config_name = path;
+
+ _path = GetStdConfigPath(_config_name);
+
+ if( _path.empty() )
+ throw OCIO::Exception("Error getting config.");
+ }
+ else
+ {
+ _path = path;
+ }
+
+
+ if(!_path.empty())
+ {
+ std::string the_extension = _path.substr( _path.find_last_of('.') + 1 );
+
+ if(the_extension == "ocio")
+ {
+ _config = OCIO::Config::CreateFromFile( _path.c_str() );
+
+ _config->sanityCheck();
+
+ for(int i=0; i < _config->getNumColorSpaces(); ++i)
+ {
+ _inputs.push_back( _config->getColorSpaceNameByIndex(i) );
+ }
+
+
+ for(int i=0; i < _config->getNumDisplays(); ++i)
+ {
+ _devices.push_back( _config->getDisplay(i) );
+ }
+
+ const char * defaultDisplay = _config->getDefaultDisplay();
+ const char * defaultTransform = _config->getDefaultView(defaultDisplay);
+
+ for(int i=0; i < _config->getNumViews(defaultDisplay); ++i)
+ {
+ _transforms.push_back( _config->getView(defaultDisplay, i) );
+ }
+
+
+ OCIO::ConstColorSpaceRcPtr defaultInput = _config->getColorSpace(OCIO::ROLE_SCENE_LINEAR);
+
+ const char *defaultInputName = (defaultInput ? defaultInput->getName() : OCIO::ROLE_SCENE_LINEAR);
+
+
+ setupConvert(defaultInputName, defaultInputName);
+
+ _transform = defaultTransform;
+ _device = defaultDisplay;
+ }
+ else
+ {
+ _config = OCIO::Config::Create();
+
+ setupLUT(false, OCIO_INTERP_LINEAR);
+ }
+ }
+ else
+ throw OCIO::Exception("Got nothin");
+}
+
+
+OpenColorIO_AE_Context::OpenColorIO_AE_Context(const ArbitraryData *arb_data, const std::string &dir) :
+ _gl_init(false)
+{
+ _action = OCIO_ACTION_NONE;
+
+
+ _source = arb_data->source;
+
+ if(_source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ char *file = getenv("OCIO");
+
+ if(file)
+ {
+ _path = file;
+ }
+ else
+ throw OCIO::Exception("No $OCIO environment variable.");
+ }
+ else if(_source == OCIO_SOURCE_STANDARD)
+ {
+ _config_name = arb_data->path;
+
+ _path = GetStdConfigPath(_config_name);
+
+ if( _path.empty() )
+ throw OCIO::Exception("Error getting config.");
+ }
+ else
+ {
+ Path absolute_path(arb_data->path, dir);
+ Path relative_path(arb_data->relative_path, dir);
+
+ if( absolute_path.exists() )
+ {
+ _path = absolute_path.full_path();
+ }
+ else
+ {
+ _path = relative_path.full_path();
+ }
+ }
+
+
+ if(!_path.empty())
+ {
+ std::string the_extension = _path.substr( _path.find_last_of('.') + 1 );
+
+ if(the_extension == "ocio")
+ {
+ _config = OCIO::Config::CreateFromFile( _path.c_str() );
+
+ _config->sanityCheck();
+
+ for(int i=0; i < _config->getNumColorSpaces(); ++i)
+ {
+ _inputs.push_back( _config->getColorSpaceNameByIndex(i) );
+ }
+
+
+ for(int i=0; i < _config->getNumDisplays(); ++i)
+ {
+ _devices.push_back( _config->getDisplay(i) );
+ }
+
+ const char * defaultDisplay = _config->getDefaultDisplay();
+ const char * defaultTransform = _config->getDefaultView(defaultDisplay);
+
+ for(int i=0; i < _config->getNumViews(defaultDisplay); ++i)
+ {
+ _transforms.push_back( _config->getView(defaultDisplay, i) );
+ }
+
+
+ if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ setupConvert(arb_data->input, arb_data->output);
+
+ _transform = arb_data->transform;
+ _device = arb_data->device;
+ }
+ else
+ {
+ setupDisplay(arb_data->input, arb_data->transform, arb_data->device);
+
+ _output = arb_data->output;
+ }
+ }
+ else
+ {
+ _config = OCIO::Config::Create();
+
+ setupLUT(arb_data->invert, arb_data->interpolation);
+ }
+ }
+ else
+ throw OCIO::Exception("Got nothin");
+}
+
+
+OpenColorIO_AE_Context::~OpenColorIO_AE_Context()
+{
+ if(_gl_init)
+ {
+ glDeleteShader(_fragShader);
+ glDeleteProgram(_program);
+ glDeleteTextures(1, &_imageTexID);
+
+ if(_bufferWidth != 0 && _bufferHeight != 0)
+ glDeleteRenderbuffersEXT(1, &_renderBuffer);
+ }
+}
+
+
+bool OpenColorIO_AE_Context::Verify(const ArbitraryData *arb_data, const std::string &dir)
+{
+ if(_source != arb_data->source)
+ return false;
+
+ if(_source == OCIO_SOURCE_STANDARD)
+ {
+ if(_config_name != arb_data->path)
+ return false;
+ }
+ else if(_source == OCIO_SOURCE_CUSTOM)
+ {
+ // comparing the paths, cheking relative path only if necessary
+ if(_path != arb_data->path)
+ {
+ std::string rel_path(arb_data->relative_path);
+
+ if( !dir.empty() && !rel_path.empty() )
+ {
+ Path relative_path(rel_path, dir);
+
+ if( _path != relative_path.full_path() )
+ return false;
+ }
+ else
+ return false;
+ }
+ }
+
+ // we can switch between Convert and Display, but not LUT and non-LUT
+ if((arb_data->action == OCIO_ACTION_NONE) ||
+ (_action == OCIO_ACTION_LUT && arb_data->action != OCIO_ACTION_LUT) ||
+ (_action != OCIO_ACTION_LUT && arb_data->action == OCIO_ACTION_LUT) )
+ {
+ return false;
+ }
+
+ bool force_reset = (_action != arb_data->action);
+
+
+ // If the type and path are compatible, we can patch up
+ // differences here and return true.
+ // Returning false means the context will be deleted and rebuilt.
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ if(_invert != (bool)arb_data->invert ||
+ _interpolation != arb_data->interpolation ||
+ force_reset)
+ {
+ setupLUT(arb_data->invert, arb_data->interpolation);
+ }
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ if(_input != arb_data->input ||
+ _output != arb_data->output ||
+ force_reset)
+ {
+ setupConvert(arb_data->input, arb_data->output);
+ }
+ }
+ else if(arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ if(_input != arb_data->input ||
+ _transform != arb_data->transform ||
+ _device != arb_data->device ||
+ force_reset)
+ {
+ setupDisplay(arb_data->input, arb_data->transform, arb_data->device);
+ }
+ }
+ else
+ throw OCIO::Exception("Bad OCIO type");
+
+
+ return true;
+}
+
+
+void OpenColorIO_AE_Context::setupConvert(const char *input, const char *output)
+{
+ OCIO::ColorSpaceTransformRcPtr transform = OCIO::ColorSpaceTransform::Create();
+
+ transform->setSrc(input);
+ transform->setDst(output);
+ transform->setDirection(OCIO::TRANSFORM_DIR_FORWARD);
+
+ _input = input;
+ _output = output;
+
+ _processor = _config->getProcessor(transform);
+
+ _action = OCIO_ACTION_CONVERT;
+
+ UpdateOCIOGLState();
+}
+
+
+void OpenColorIO_AE_Context::setupDisplay(const char *input, const char *xform, const char *device)
+{
+ OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
+
+ transform->setInputColorSpaceName(input);
+ transform->setView(xform);
+ transform->setDisplay(device);
+
+ _input = input;
+ _transform = xform;
+ _device = device;
+
+
+ _processor = _config->getProcessor(transform);
+
+ _action = OCIO_ACTION_DISPLAY;
+
+ UpdateOCIOGLState();
+}
+
+
+void OpenColorIO_AE_Context::setupLUT(bool invert, OCIO_Interp interpolation)
+{
+ OCIO::FileTransformRcPtr transform = OCIO::FileTransform::Create();
+
+ if(interpolation != OCIO_INTERP_NEAREST && interpolation != OCIO_INTERP_LINEAR &&
+ interpolation != OCIO_INTERP_TETRAHEDRAL && interpolation != OCIO_INTERP_BEST)
+ {
+ interpolation = OCIO_INTERP_LINEAR;
+ }
+
+ transform->setSrc( _path.c_str() );
+ transform->setInterpolation(static_cast<OCIO::Interpolation>(interpolation));
+ transform->setDirection(invert ? OCIO::TRANSFORM_DIR_INVERSE : OCIO::TRANSFORM_DIR_FORWARD);
+
+ _processor = _config->getProcessor(transform);
+
+ _invert = invert;
+ _interpolation = interpolation;
+
+ _action = OCIO_ACTION_LUT;
+
+ UpdateOCIOGLState();
+}
+
+
+bool OpenColorIO_AE_Context::ExportLUT(const std::string &path, const std::string &display_icc_path)
+{
+ std::string the_extension = path.substr( path.find_last_of('.') + 1 );
+
+ try{
+
+ if(the_extension == "icc")
+ {
+ int cubesize = 32;
+ int whitepointtemp = 6505;
+ std::string copyright = "OpenColorIO, Sony Imageworks";
+
+ // create a description tag from the filename
+ size_t filename_start = path.find_last_of(delimiter) + 1;
+ size_t filename_end = path.find_last_of('.') - 1;
+
+ std::string description = path.substr(path.find_last_of(delimiter) + 1,
+ 1 + filename_end - filename_start);
+
+ SaveICCProfileToFile(path, _processor, cubesize, whitepointtemp,
+ display_icc_path, description, copyright, false);
+ }
+ else
+ {
+ // this code lovingly pulled from ociobakelut
+
+ // need an extension->format map (yes, just did this one call up)
+ std::map<std::string, std::string> extensions;
+
+ for(int i=0; i < OCIO::Baker::getNumFormats(); ++i)
+ {
+ const char *extension = OCIO::Baker::getFormatExtensionByIndex(i);
+ const char *format = OCIO::Baker::getFormatNameByIndex(i);
+
+ extensions[ extension ] = format;
+ }
+
+ std::string format = extensions[ the_extension ];
+
+
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+
+ baker->setFormat(format.c_str());
+
+ if(_action == OCIO_ACTION_CONVERT)
+ {
+ baker->setConfig(_config);
+ baker->setInputSpace(_input.c_str());
+ baker->setTargetSpace(_output.c_str());
+
+ std::ofstream f(path.c_str());
+ baker->bake(f);
+ }
+ else if(_action == OCIO_ACTION_DISPLAY)
+ {
+ OCIO::ConfigRcPtr editableConfig = _config->createEditableCopy();
+
+ OCIO::ColorSpaceRcPtr inputColorSpace = OCIO::ColorSpace::Create();
+ std::string inputspace = "RawInput";
+ inputColorSpace->setName(inputspace.c_str());
+ editableConfig->addColorSpace(inputColorSpace);
+
+
+ OCIO::ColorSpaceRcPtr outputColorSpace = OCIO::ColorSpace::Create();
+ std::string outputspace = "ProcessedOutput";
+ outputColorSpace->setName(outputspace.c_str());
+
+ OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
+
+ transform->setInputColorSpaceName(_input.c_str());
+ transform->setView(_transform.c_str());
+ transform->setDisplay(_device.c_str());
+
+ outputColorSpace->setTransform(transform, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+
+ editableConfig->addColorSpace(outputColorSpace);
+
+
+ baker->setConfig(editableConfig);
+ baker->setInputSpace(inputspace.c_str());
+ baker->setTargetSpace(outputspace.c_str());
+
+ std::ofstream f(path.c_str());
+ baker->bake(f);
+ }
+ else if(_action == OCIO_ACTION_LUT)
+ {
+ OCIO::ConfigRcPtr editableConfig = OCIO::Config::Create();
+
+ OCIO::ColorSpaceRcPtr inputColorSpace = OCIO::ColorSpace::Create();
+ std::string inputspace = "RawInput";
+ inputColorSpace->setName(inputspace.c_str());
+ editableConfig->addColorSpace(inputColorSpace);
+
+
+ OCIO::ColorSpaceRcPtr outputColorSpace = OCIO::ColorSpace::Create();
+ std::string outputspace = "ProcessedOutput";
+ outputColorSpace->setName(outputspace.c_str());
+
+ OCIO::FileTransformRcPtr transform = OCIO::FileTransform::Create();
+
+ transform = OCIO::FileTransform::Create();
+ transform->setSrc(_path.c_str());
+ transform->setInterpolation(static_cast<OCIO::Interpolation>(_interpolation));
+ transform->setDirection(_invert ? OCIO::TRANSFORM_DIR_INVERSE : OCIO::TRANSFORM_DIR_FORWARD);
+
+ outputColorSpace->setTransform(transform, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+
+ editableConfig->addColorSpace(outputColorSpace);
+
+
+ baker->setConfig(editableConfig);
+ baker->setInputSpace(inputspace.c_str());
+ baker->setTargetSpace(outputspace.c_str());
+
+ std::ofstream f(path.c_str());
+ baker->bake(f);
+ }
+ }
+
+ }catch(...) { return false; }
+
+ return true;
+}
+
+
+void OpenColorIO_AE_Context::InitOCIOGL()
+{
+ if(!_gl_init)
+ {
+ SetPluginContext();
+
+ glGenTextures(1, &_imageTexID);
+ glGenTextures(1, &_lut3dTexID);
+
+ int num3Dentries = 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE;
+ _lut3d.resize(num3Dentries);
+ memset(&_lut3d[0], 0, sizeof(float)*num3Dentries);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_3D, _lut3dTexID);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F_ARB,
+ LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+ 0, GL_RGB,GL_FLOAT, &_lut3d[0]);
+
+ _fragShader = 0;
+ _program = 0;
+
+ _bufferWidth = _bufferHeight = 0;
+
+ _gl_init = true;
+
+ SetAEContext();
+ }
+}
+
+
+static const char * g_fragShaderText = ""
+"\n"
+"uniform sampler2D tex1;\n"
+"uniform sampler3D tex2;\n"
+"\n"
+"void main()\n"
+"{\n"
+" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
+" gl_FragColor = OCIODisplay(col, tex2);\n"
+"}\n";
+
+
+static GLuint CompileShaderText(GLenum shaderType, const char *text)
+{
+ GLuint shader;
+ GLint stat;
+
+ shader = glCreateShader(shaderType);
+ glShaderSource(shader, 1, (const GLchar **) &text, NULL);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
+
+ if (!stat)
+ {
+ GLchar log[1000];
+ GLsizei len;
+ glGetShaderInfoLog(shader, 1000, &len, log);
+ return 0;
+ }
+
+ return shader;
+}
+
+
+static GLuint LinkShaders(GLuint fragShader)
+{
+ if (!fragShader) return 0;
+
+ GLuint program = glCreateProgram();
+
+ if (fragShader)
+ glAttachShader(program, fragShader);
+
+ glLinkProgram(program);
+
+ // check link
+ {
+ GLint stat;
+ glGetProgramiv(program, GL_LINK_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetProgramInfoLog(program, 1000, &len, log);
+ //fprintf(stderr, "Shader link error:\n%s\n", log);
+ return 0;
+ }
+ }
+
+ return program;
+}
+
+
+void OpenColorIO_AE_Context::UpdateOCIOGLState()
+{
+ if(_gl_init)
+ {
+ SetPluginContext();
+
+ // Step 1: Create a GPU Shader Description
+ OCIO::GpuShaderDesc shaderDesc;
+ shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
+ shaderDesc.setFunctionName("OCIODisplay");
+ shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+
+ // Step 2: Compute the 3D LUT
+ std::string lut3dCacheID = _processor->getGpuLut3DCacheID(shaderDesc);
+ if(lut3dCacheID != _lut3dcacheid)
+ {
+ _lut3dcacheid = lut3dCacheID;
+ _processor->getGpuLut3D(&_lut3d[0], shaderDesc);
+ }
+
+ // Step 3: Compute the Shader
+ std::string shaderCacheID = _processor->getGpuShaderTextCacheID(shaderDesc);
+ if(_program == 0 || shaderCacheID != _shadercacheid)
+ {
+ _shadercacheid = shaderCacheID;
+
+ std::ostringstream os;
+ os << _processor->getGpuShaderText(shaderDesc) << "\n";
+ os << g_fragShaderText;
+
+ if(_fragShader) glDeleteShader(_fragShader);
+ _fragShader = CompileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+ if(_program) glDeleteProgram(_program);
+ _program = LinkShaders(_fragShader);
+ }
+
+ SetAEContext();
+ }
+}
+
+
+bool OpenColorIO_AE_Context::ProcessWorldGL(PF_EffectWorld *float_world)
+{
+ if(!_gl_init)
+ {
+ InitOCIOGL();
+ UpdateOCIOGLState();
+ }
+
+
+ if(_program == 0 || _fragShader == 0)
+ return false;
+
+
+ SetPluginContext();
+
+
+ GLint max;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
+
+ if(max < float_world->width || max < float_world->height || GL_NO_ERROR != glGetError())
+ {
+ SetAEContext();
+ return false;
+ }
+
+
+ PF_PixelFloat *pix = (PF_PixelFloat *)float_world->data;
+ float *rgba_origin = &pix->red;
+
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, _imageTexID);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, float_world->width, float_world->height, 0,
+ GL_RGBA, GL_FLOAT, rgba_origin);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+
+ glBindTexture(GL_TEXTURE_3D, _lut3dTexID);
+ glTexSubImage3D(GL_TEXTURE_3D, 0,
+ 0, 0, 0,
+ LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+ GL_RGB, GL_FLOAT, &_lut3d[0]);
+
+
+ glUseProgram(_program);
+ glUniform1i(glGetUniformLocation(_program, "tex1"), 0);
+ glUniform1i(glGetUniformLocation(_program, "tex2"), 1);
+
+
+ if(GL_NO_ERROR != glGetError())
+ {
+ SetAEContext();
+ return false;
+ }
+
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, GetFrameBuffer());
+
+ if(_bufferWidth != float_world->width || _bufferHeight != float_world->height)
+ {
+ if(_bufferWidth != 0 && _bufferHeight != 0)
+ glDeleteRenderbuffersEXT(1, &_renderBuffer);
+
+ _bufferWidth = float_world->width;
+ _bufferHeight = float_world->height;
+
+ glGenRenderbuffersEXT(1, &_renderBuffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _renderBuffer);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, _bufferWidth, _bufferHeight);
+
+ // attach renderbuffer to framebuffer
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, _renderBuffer);
+ }
+
+ if(GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
+ {
+ SetAEContext();
+ return false;
+ }
+
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+
+
+ glViewport(0, 0, float_world->width, float_world->height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, float_world->width, 0.0, float_world->height, -100.0, 100.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+
+ glEnable(GL_TEXTURE_2D);
+ glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColor3f(1, 1, 1);
+
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2f(0.0f, float_world->height);
+
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2f(0.0f, 0.0f);
+
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2f(float_world->width, 0.0f);
+
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2f(float_world->width, float_world->height);
+
+ glEnd();
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D);
+
+
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glReadPixels(0, 0, float_world->width, float_world->height,
+ GL_RGBA, GL_FLOAT, rgba_origin);
+
+
+ glFinish();
+
+
+ SetAEContext();
+
+ return true;
+}
diff --git a/src/aftereffects/OpenColorIO_AE_Context.h b/src/aftereffects/OpenColorIO_AE_Context.h
new file mode 100644
index 0000000..8a3bf42
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_Context.h
@@ -0,0 +1,153 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _OPENCOLORIO_AE_CONTEXT_H_
+#define _OPENCOLORIO_AE_CONTEXT_H_
+
+#include <string>
+#include <vector>
+
+#include "OpenColorIO_AE.h"
+#include "OpenColorIO_AE_GL.h"
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+
+// yeah, this probably could/should go in a seperate file
+class Path
+{
+ public:
+ Path(const std::string &path, const std::string &dir);
+ Path(const Path &path);
+ ~Path() {}
+
+ std::string full_path() const;
+ std::string relative_path(bool force) const;
+
+ bool exists() const;
+
+ private:
+ std::string _path;
+ std::string _dir;
+
+ typedef enum {
+ TYPE_UNKNOWN = 0,
+ TYPE_MAC,
+ TYPE_WIN
+ } PathType;
+
+ static PathType path_type(std::string path);
+ static bool is_relative(std::string path);
+ static std::string convert_delimiters(std::string path);
+ static std::vector<std::string> components(std::string path);
+};
+
+
+class OpenColorIO_AE_Context
+{
+ public:
+ OpenColorIO_AE_Context(const std::string &path, OCIO_Source source);
+ OpenColorIO_AE_Context(const ArbitraryData *arb_data, const std::string &dir);
+ ~OpenColorIO_AE_Context();
+
+ bool Verify(const ArbitraryData *arb_data, const std::string &dir);
+
+ void setupConvert(const char *input, const char *output);
+ void setupDisplay(const char *input, const char *transform, const char *device);
+ void setupLUT(bool invert, OCIO_Interp interpolation);
+
+ typedef std::vector<std::string> SpaceVec;
+
+ OCIO_Action getAction() const { return _action; }
+ const std::string & getInput() const { return _input; }
+ const std::string & getOutput() const { return _output; }
+ const std::string & getTransform() const { return _transform; }
+ const std::string & getDevice() const { return _device; }
+ const SpaceVec & getInputs() const { return _inputs; }
+ const SpaceVec & getTransforms() const { return _transforms; }
+ const SpaceVec & getDevices() const { return _devices; }
+
+ const OCIO::ConstProcessorRcPtr & processor() const { return _processor; }
+
+ bool ExportLUT(const std::string &path, const std::string &display_icc_path);
+
+ bool ProcessWorldGL(PF_EffectWorld *float_world);
+
+ private:
+ std::string _path;
+ OCIO_Source _source;
+ std::string _config_name;
+
+ OCIO_Action _action;
+
+ std::string _input;
+ std::string _output;
+ std::string _transform;
+ std::string _device;
+ SpaceVec _inputs;
+ SpaceVec _transforms;
+ SpaceVec _devices;
+
+ bool _invert;
+ OCIO_Interp _interpolation;
+
+
+ OCIO::ConstConfigRcPtr _config;
+ OCIO::ConstProcessorRcPtr _processor;
+
+
+ bool _gl_init;
+
+ GLuint _fragShader;
+ GLuint _program;
+
+ GLuint _imageTexID;
+
+ GLuint _lut3dTexID;
+ std::vector<float> _lut3d;
+ std::string _lut3dcacheid;
+ std::string _shadercacheid;
+
+ std::string _inputColorSpace;
+ std::string _display;
+ std::string _transformName;
+
+
+ GLuint _renderBuffer;
+ int _bufferWidth;
+ int _bufferHeight;
+
+ void InitOCIOGL();
+ void UpdateOCIOGLState();
+};
+
+
+#endif // _OPENCOLORIO_AE_CONTEXT_H_ \ No newline at end of file
diff --git a/src/aftereffects/OpenColorIO_AE_Dialogs.h b/src/aftereffects/OpenColorIO_AE_Dialogs.h
new file mode 100644
index 0000000..a2e9f26
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_Dialogs.h
@@ -0,0 +1,60 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _OPENCOLORIC_AE_DIALOG_H_
+#define _OPENCOLORIC_AE_DIALOG_H_
+
+#include <string>
+#include <map>
+#include <vector>
+
+typedef std::map<std::string, std::string> ExtensionMap; // map[ ext ] = format
+
+bool OpenFile(char *path, int buf_len, const ExtensionMap &extensions, const void *hwnd);
+
+bool SaveFile(char *path, int buf_len, const ExtensionMap &extensions, const void *hwnd);
+
+bool GetMonitorProfile(char *path, int buf_len, const void *hwnd);
+
+
+typedef std::vector<std::string> ConfigVec;
+
+void GetStdConfigs(ConfigVec &configs);
+
+std::string GetStdConfigPath(const std::string &name);
+
+
+typedef std::vector<std::string> MenuVec;
+
+int PopUpMenu(const MenuVec &menu_items, int selected_index, const void *hwnd);
+
+
+void ErrorMessage(const char *message, const void *hwnd);
+
+
+#endif // _OPENCOLORIC_AE_DIALOG_H_ \ No newline at end of file
diff --git a/src/aftereffects/OpenColorIO_AE_GL.h b/src/aftereffects/OpenColorIO_AE_GL.h
new file mode 100644
index 0000000..2c9683c
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_GL.h
@@ -0,0 +1,61 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _OPENCOLORIO_AE_GL_H_
+#define _OPENCOLORIO_AE_GL_H_
+
+#include "AEConfig.h"
+
+#ifdef AE_OS_WIN
+ #include <GL/glew.h>
+ #include <GL/wglew.h>
+#elif defined(AE_OS_MAC)
+ #include <OpenGL/OpenGL.h>
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glu.h>
+ #include <OpenGL/glext.h>
+ #include <AGL/agl.h>
+#endif
+
+
+void GlobalSetup_GL();
+
+bool HaveOpenGL();
+
+// must surround plug-in OpenGL calls with these functions so that AE
+// doesn't know we're borrowing the OpenGL renderer
+void SetPluginContext();
+void SetAEContext();
+
+GLuint GetFrameBuffer();
+
+void GlobalSetdown_GL();
+
+
+#endif // _OPENCOLORIO_AE_GL_H_ \ No newline at end of file
diff --git a/src/aftereffects/OpenColorIO_AE_PiPL.r b/src/aftereffects/OpenColorIO_AE_PiPL.r
new file mode 100644
index 0000000..3d08070
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_PiPL.r
@@ -0,0 +1,102 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "AEConfig.h"
+
+#include "AE_EffectVers.h"
+
+#ifndef AE_OS_WIN
+ #include "AE_General.r"
+#endif
+
+resource 'PiPL' (16000) {
+ { /* array properties: 12 elements */
+ /* [1] */
+ Kind {
+ AEEffect
+ },
+ /* [2] */
+ Name {
+ "OpenColorIO"
+ },
+ /* [3] */
+ Category {
+ "Utility"
+ },
+
+#ifdef AE_OS_WIN
+ #ifdef AE_PROC_INTELx64
+ CodeWin64X86 {"PluginMain"},
+ #else
+ CodeWin32X86 {"PluginMain"},
+ #endif
+#else
+ #ifdef AE_PROC_INTELx64
+ CodeMacIntel64 {"PluginMain"},
+ #else
+ CodeMachOPowerPC {"PluginMain"},
+ CodeMacIntel32 {"PluginMain"},
+ #endif
+#endif /* [6] */
+ AE_PiPL_Version {
+ 2,
+ 0
+ },
+ /* [7] */
+ AE_Effect_Spec_Version {
+ PF_PLUG_IN_VERSION,
+ PF_PLUG_IN_SUBVERS
+ },
+ /* [8] */
+ AE_Effect_Version {
+ 525824 /* 2.0 */
+ },
+ /* [9] */
+ AE_Effect_Info_Flags {
+ 0
+ },
+ /* [10] */
+ AE_Effect_Global_OutFlags {
+ 50365504
+ },
+ AE_Effect_Global_OutFlags_2 {
+ 37896
+ },
+ /* [11] */
+ AE_Effect_Match_Name {
+ "OpenColorIO"
+ },
+ /* [12] */
+ AE_Reserved_Info {
+ 0
+ }
+ }
+};
+
+
+
diff --git a/src/aftereffects/OpenColorIO_AE_UI.cpp b/src/aftereffects/OpenColorIO_AE_UI.cpp
new file mode 100644
index 0000000..b5634bf
--- /dev/null
+++ b/src/aftereffects/OpenColorIO_AE_UI.cpp
@@ -0,0 +1,1229 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE.h"
+
+#include "OpenColorIO_AE_Context.h"
+#include "OpenColorIO_AE_Dialogs.h"
+
+#include "DrawbotBot.h"
+
+
+
+// UI drawing constants
+
+#define LEFT_MARGIN 5
+#define TOP_MARGIN 5
+#define RIGHT_MARGIN 50
+
+#define FILE_LABEL_WIDTH 35
+
+#define FIELD_HEIGHT 22
+
+#define FIELD_TEXT_INDENT_H 10
+#define FIELD_TEXT_INDENT_V 4
+
+#define BUTTONS_INDENT_H (LEFT_MARGIN + 70)
+
+#define BUTTONS_GAP_V 20
+#define BUTTONS_GAP_H 30
+
+#define BUTTON_HEIGHT 20
+#define BUTTON_WIDTH 80
+
+#define BUTTON_TEXT_INDENT_V 2
+
+#define MENUS_INDENT_H 0
+
+#define MENUS_GAP_V 20
+
+#define MENU_LABEL_WIDTH 100
+#define MENU_LABEL_SPACE 5
+
+#define MENU_WIDTH 150
+#define MENU_HEIGHT 20
+
+#define MENU_TEXT_INDENT_H 10
+#define MENU_TEXT_INDENT_V 2
+
+#define MENU_ARROW_WIDTH 14
+#define MENU_ARROW_HEIGHT 7
+
+#define MENU_ARROW_SPACE_H 8
+#define MENU_ARROW_SPACE_V 7
+
+#define MENU_SHADOW_OFFSET 3
+
+#define MENU_SPACE_V 20
+
+#define TEXT_COLOR PF_App_Color_TEXT_DISABLED
+
+
+
+typedef enum {
+ REGION_NONE=0,
+ REGION_CONFIG_MENU,
+ REGION_PATH,
+ REGION_CONVERT_BUTTON,
+ REGION_DISPLAY_BUTTON,
+ REGION_EXPORT_BUTTON,
+ REGION_MENU1,
+ REGION_MENU2,
+ REGION_MENU3
+} UIRegion;
+
+
+static UIRegion WhichRegion(PF_Point ui_point, bool menus, bool third_menu)
+{
+ int field_top = TOP_MARGIN;
+ int field_bottom = field_top + FIELD_HEIGHT;
+
+ if(ui_point.v >= field_top && ui_point.v <= field_bottom)
+ {
+ int menu_left = LEFT_MARGIN + MENUS_INDENT_H + MENU_LABEL_WIDTH;
+ int menu_right = menu_left + MENU_WIDTH;
+
+ if(ui_point.h >= menu_left && ui_point.h <= menu_right)
+ {
+ return REGION_CONFIG_MENU;
+ }
+ else
+ {
+ int field_left = MENUS_INDENT_H + MENU_LABEL_WIDTH + MENU_LABEL_SPACE +
+ MENU_WIDTH + FIELD_TEXT_INDENT_H;
+
+ if(ui_point.h >= field_left)
+ return REGION_PATH;
+ }
+ }
+ else
+ {
+ int buttons_top = field_bottom + BUTTONS_GAP_V;
+ int buttons_bottom = buttons_top + BUTTON_HEIGHT;
+
+ if(ui_point.v >= buttons_top && ui_point.v <= buttons_bottom)
+ {
+ int convert_left = BUTTONS_INDENT_H;
+ int convert_right = convert_left + BUTTON_WIDTH;
+ int display_left = convert_right + BUTTONS_GAP_H;
+ int display_right = display_left + BUTTON_WIDTH;
+ int export_left = display_right + BUTTONS_GAP_H;
+ int export_right = export_left + BUTTON_WIDTH;
+
+ if(ui_point.h >= convert_left && ui_point.h <= convert_right)
+ return REGION_CONVERT_BUTTON;
+ else if(ui_point.h >= display_left && ui_point.h <= display_right)
+ return REGION_DISPLAY_BUTTON;
+ else if(ui_point.h >= export_left && ui_point.h <= export_right)
+ return REGION_EXPORT_BUTTON;
+ }
+ else if(menus)
+ {
+ int menu_left = LEFT_MARGIN + MENUS_INDENT_H + MENU_LABEL_WIDTH;
+ int menu_right = menu_left + MENU_WIDTH;
+
+ if(ui_point.h >= menu_left && ui_point.h <= menu_right)
+ {
+ int menu1_top = buttons_bottom + MENUS_GAP_V;
+ int menu1_bottom = menu1_top + MENU_HEIGHT;
+ int menu2_top = menu1_bottom + MENU_SPACE_V;
+ int menu2_bottom = menu2_top + MENU_HEIGHT;
+ int menu3_top = menu2_bottom + MENU_SPACE_V;
+ int menu3_bottom = menu3_top + MENU_HEIGHT;
+
+ if(ui_point.v >= menu1_top && ui_point.v <= menu1_bottom)
+ return REGION_MENU1;
+ else if(ui_point.v >= menu2_top && ui_point.v <= menu2_bottom)
+ return REGION_MENU2;
+ else if(third_menu && ui_point.v >= menu3_top && ui_point.v <= menu3_bottom)
+ return REGION_MENU3;
+ }
+ }
+ }
+
+ return REGION_NONE;
+}
+
+
+static void DrawMenu(DrawbotBot &bot, const char *label, const char *item)
+{
+ DRAWBOT_PointF32 original = bot.Pos();
+
+ float text_height = bot.FontSize();
+
+ bot.Move(MENU_LABEL_WIDTH, MENU_TEXT_INDENT_V + text_height);
+
+ bot.SetColor(TEXT_COLOR);
+ bot.DrawString(label, kDRAWBOT_TextAlignment_Right);
+
+ bot.Move(MENU_LABEL_SPACE, -(MENU_TEXT_INDENT_V + text_height));
+
+ DRAWBOT_PointF32 menu_corner = bot.Pos();
+
+ bot.Move(MENU_SHADOW_OFFSET, MENU_SHADOW_OFFSET);
+ bot.SetColor(PF_App_Color_BLACK, 0.3f);
+ bot.PaintRect(MENU_WIDTH, MENU_HEIGHT);
+ bot.MoveTo(menu_corner);
+
+ bot.SetColor(PF_App_Color_SHADOW);
+ bot.PaintRect(MENU_WIDTH, MENU_HEIGHT);
+
+ bot.SetColor(PF_App_Color_HILITE);
+ bot.DrawRect(MENU_WIDTH, MENU_HEIGHT);
+
+ bot.Move(MENU_TEXT_INDENT_H, MENU_TEXT_INDENT_V + text_height);
+
+ bot.SetColor(TEXT_COLOR);
+ bot.DrawString(item,
+ kDRAWBOT_TextAlignment_Left,
+ kDRAWBOT_TextTruncation_EndEllipsis,
+ MENU_WIDTH - MENU_TEXT_INDENT_H - MENU_TEXT_INDENT_H -
+ MENU_ARROW_WIDTH - MENU_ARROW_SPACE_H - MENU_ARROW_SPACE_H);
+
+ bot.MoveTo(menu_corner.x + MENU_WIDTH - MENU_ARROW_SPACE_H - MENU_ARROW_WIDTH,
+ menu_corner.y + MENU_ARROW_SPACE_V);
+
+ bot.SetColor(PF_App_Color_LIGHT_TINGE);
+ bot.PaintTriangle(MENU_ARROW_WIDTH, MENU_ARROW_HEIGHT);
+
+ bot.MoveTo(original);
+}
+
+
+static void DrawButton(DrawbotBot &bot, const char *label, int width, bool pressed)
+{
+ DRAWBOT_PointF32 original = bot.Pos();
+
+ float text_height = bot.FontSize();
+
+
+ PF_App_ColorType button_color = (pressed ? PF_App_Color_BUTTON_PRESSED_FILL : PF_App_Color_BUTTON_FILL);
+ PF_App_ColorType button_hilite = (pressed ? PF_App_Color_BLACK : PF_App_Color_HILITE);
+ PF_App_ColorType button_lowlite = (pressed ? PF_App_Color_HILITE : PF_App_Color_BLACK);
+
+
+ bot.SetColor(button_color);
+ bot.PaintRect(width, BUTTON_HEIGHT);
+
+ float brush_size = (pressed ? 1.f : 0.5f);
+
+ bot.SetColor(button_hilite);
+ bot.MoveTo(original.x + 1, original.y + BUTTON_HEIGHT - 1);
+
+ bot.DrawLineTo(original.x + 1, original.y + 1, brush_size);
+ bot.DrawLineTo(original.x + width - 1, original.y + 1, brush_size);
+
+ bot.MoveTo(original); // annoying corner pixel
+ bot.SetColor(button_hilite, 0.3f);
+ bot.PaintRect(1, 1);
+
+
+ brush_size = (pressed ? 0.5f : 1.f);
+
+ bot.SetColor(button_lowlite);
+ bot.MoveTo(original.x + 1, original.y + BUTTON_HEIGHT - 1);
+
+ bot.DrawLineTo(original.x + width - 1, original.y + BUTTON_HEIGHT - 1, brush_size);
+ bot.DrawLineTo(original.x + width - 1, original.y + 2, brush_size);
+
+ bot.MoveTo(original.x + width - 1, original.y + BUTTON_HEIGHT - 1); // corner
+ bot.SetColor(button_lowlite, 0.3f);
+ bot.PaintRect(1, 1);
+
+
+ bot.MoveTo(original.x + (width / 2), original.y + text_height + BUTTON_TEXT_INDENT_V);
+
+ if(pressed)
+ bot.Move(2, 2);
+
+ bot.SetColor(TEXT_COLOR);
+ bot.DrawString(label, kDRAWBOT_TextAlignment_Center);
+
+ bot.MoveTo(original);
+}
+
+
+static PF_Err DrawEvent(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra)
+{
+ PF_Err err = PF_Err_NONE;
+
+
+ if(!(event_extra->evt_in_flags & PF_EI_DONT_DRAW) &&
+ params[OCIO_DATA]->u.arb_d.value != NULL)
+ {
+ if(event_extra->effect_win.area == PF_EA_CONTROL)
+ {
+ ArbitraryData *arb_data = (ArbitraryData *)PF_LOCK_HANDLE(params[OCIO_DATA]->u.arb_d.value);
+ SequenceData *seq_data = (SequenceData *)PF_LOCK_HANDLE(in_data->sequence_data);
+
+ DrawbotBot bot(in_data->pica_basicP, event_extra->contextH, in_data->appl_id);
+
+
+ int panel_left = event_extra->effect_win.current_frame.left;
+ int panel_top = event_extra->effect_win.current_frame.top;
+ int panel_width = event_extra->effect_win.current_frame.right;
+ int panel_height = event_extra->effect_win.current_frame.bottom;
+ float text_height = bot.FontSize();
+
+ if(in_data->appl_id != 'FXTC')
+ {
+ // for Premiere we need to paint the background first
+ bot.SetColor(PF_App_Color_PANEL_BACKGROUND);
+ bot.MoveTo(panel_left, panel_top);
+ bot.PaintRect(panel_width, panel_height);
+ }
+
+
+ // configuration menu
+ bot.MoveTo(panel_left + MENUS_INDENT_H, panel_top + TOP_MARGIN);
+
+ std::string config_menu_text = arb_data->path;
+
+ if(arb_data->source == OCIO_SOURCE_NONE)
+ {
+ config_menu_text = "(none)";
+ }
+ if(arb_data->source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ config_menu_text = "$OCIO";
+ }
+ else if(arb_data->source == OCIO_SOURCE_CUSTOM)
+ {
+ config_menu_text = (arb_data->action == OCIO_ACTION_LUT ? "LUT" : "Custom");
+ }
+
+ DrawMenu(bot, "Configuration:", config_menu_text.c_str());
+
+
+ if(arb_data->source == OCIO_SOURCE_CUSTOM ||
+ arb_data->source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ // path text field
+ int field_left = panel_left + MENUS_INDENT_H + MENU_LABEL_WIDTH +
+ MENU_LABEL_SPACE + MENU_WIDTH + FIELD_TEXT_INDENT_H;
+
+ bot.MoveTo(field_left, panel_top + TOP_MARGIN);
+
+ int field_width = MAX(panel_width - field_left + panel_left - RIGHT_MARGIN, 60);
+
+ bot.SetColor(PF_App_Color_SHADOW);
+ bot.PaintRect(field_width, FIELD_HEIGHT);
+ bot.SetColor(PF_App_Color_BLACK);
+ bot.DrawRect(field_width, FIELD_HEIGHT);
+
+ bot.Move(FIELD_TEXT_INDENT_H, FIELD_TEXT_INDENT_V + text_height);
+
+ bot.SetColor(TEXT_COLOR);
+
+ std::string file_string = "(none)";
+
+ if(arb_data->source == OCIO_SOURCE_ENVIRONMENT)
+ {
+ char *file = std::getenv("OCIO");
+
+ if(file)
+ file_string = file;
+ }
+ else
+ {
+ file_string = (seq_data->status == STATUS_USING_RELATIVE ?
+ arb_data->relative_path : arb_data->path);
+ }
+
+
+ bot.DrawString(file_string.c_str(),
+ kDRAWBOT_TextAlignment_Default,
+ kDRAWBOT_TextTruncation_PathEllipsis,
+ field_width - (2 * FIELD_TEXT_INDENT_H));
+ }
+
+
+ if(seq_data->status == STATUS_FILE_MISSING)
+ {
+ bot.MoveTo(panel_left + MENU_LABEL_WIDTH + MENU_LABEL_SPACE,
+ panel_top + MENU_HEIGHT + BUTTONS_GAP_V + BUTTON_HEIGHT + BUTTONS_GAP_V);
+
+ bot.SetColor(PF_App_Color_RED);
+ bot.PaintRect(200, 50);
+
+ bot.Move(100, 25 + (bot.FontSize() / 2));
+ bot.SetColor(PF_App_Color_WHITE);
+
+ if(arb_data->source == OCIO_SOURCE_ENVIRONMENT)
+ bot.DrawString("$OCIO NOT SET", kDRAWBOT_TextAlignment_Center);
+ else
+ bot.DrawString("FILE MISSING", kDRAWBOT_TextAlignment_Center);
+ }
+ else
+ {
+ // buttons
+ int field_bottom = panel_top + TOP_MARGIN + FIELD_HEIGHT;
+ int buttons_top = field_bottom + BUTTONS_GAP_V;
+
+ // GPU alert
+ if(seq_data->gpu_err != GPU_ERR_NONE)
+ {
+ bot.MoveTo(panel_left + MENU_LABEL_WIDTH + MENU_LABEL_SPACE,
+ field_bottom + bot.FontSize() + BUTTON_TEXT_INDENT_V);
+
+ if(seq_data->gpu_err == GPU_ERR_INSUFFICIENT)
+ {
+ bot.DrawString("GPU Insufficient");
+ }
+ else if(seq_data->gpu_err == GPU_ERR_RENDER_ERR)
+ {
+ bot.DrawString("GPU Render Error");
+ }
+ }
+
+ #ifndef NDEBUG
+ // Premiere color space (only for debugging purposes)
+ if(in_data->appl_id == 'PrMr' && seq_data->prem_status != PREMIERE_UNKNOWN)
+ {
+ bot.MoveTo(panel_left + MENU_LABEL_WIDTH + MENU_LABEL_SPACE + 200,
+ field_bottom + bot.FontSize() + BUTTON_TEXT_INDENT_V);
+
+ bot.SetColor(PF_App_Color_WHITE);
+
+ if(seq_data->prem_status == PREMIERE_LINEAR)
+ {
+ bot.DrawString("Linear Float");
+ }
+ else if(seq_data->prem_status == PREMIERE_NON_LINEAR)
+ {
+ bot.DrawString("Non-Linear Float");
+ }
+ }
+ #endif
+
+ // Export button
+ if(arb_data->action != OCIO_ACTION_NONE)
+ {
+ bot.MoveTo(panel_left + BUTTONS_INDENT_H + (2 * (BUTTON_WIDTH + BUTTONS_GAP_H)), buttons_top);
+
+ DrawButton(bot, "Export...", BUTTON_WIDTH, false);
+ }
+
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ // Invert button
+ bot.MoveTo(panel_left + BUTTONS_INDENT_H, buttons_top);
+
+ DrawButton(bot, "Invert", BUTTON_WIDTH, arb_data->invert);
+
+ // interpolation menu
+ int buttons_bottom = buttons_top + BUTTON_HEIGHT;
+
+ bot.MoveTo(panel_left + MENUS_INDENT_H, buttons_bottom + MENUS_GAP_V);
+
+ const char *txt = arb_data->interpolation == OCIO_INTERP_NEAREST ? "Nearest Neighbor" :
+ arb_data->interpolation == OCIO_INTERP_LINEAR ? "Linear" :
+ arb_data->interpolation == OCIO_INTERP_TETRAHEDRAL ? "Tetrahedral" :
+ arb_data->interpolation == OCIO_INTERP_BEST ? "Best" :
+ "Unknown";
+
+ DrawMenu(bot, "Interpolation:", txt);
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT ||
+ arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ // Convert/Display buttons
+ bot.MoveTo(panel_left + BUTTONS_INDENT_H, buttons_top);
+
+ DrawButton(bot, "Convert", BUTTON_WIDTH,
+ arb_data->action == OCIO_ACTION_CONVERT);
+
+ bot.Move(BUTTON_WIDTH + BUTTONS_GAP_H);
+
+ DrawButton(bot, "Display", BUTTON_WIDTH,
+ arb_data->action == OCIO_ACTION_DISPLAY);
+
+
+ // menus
+ int buttons_bottom = buttons_top + BUTTON_HEIGHT;
+
+ bot.MoveTo(panel_left + MENUS_INDENT_H, buttons_bottom + MENUS_GAP_V);
+
+ if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ DrawMenu(bot, "Input Space:", arb_data->input);
+
+ bot.Move(0, MENU_HEIGHT + MENU_SPACE_V);
+
+ DrawMenu(bot, "Output Space:", arb_data->output);
+ }
+ else if(arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ // color space transformations
+ DrawMenu(bot, "Input Space:", arb_data->input);
+
+ bot.Move(0, MENU_HEIGHT + MENU_SPACE_V);
+
+ DrawMenu(bot, "Transform:", arb_data->transform);
+
+ bot.Move(0, MENU_HEIGHT + MENU_SPACE_V);
+
+ DrawMenu(bot, "Device:", arb_data->device);
+ }
+ }
+ }
+
+
+ event_extra->evt_out_flags = PF_EO_HANDLED_EVENT;
+
+ PF_UNLOCK_HANDLE(params[OCIO_DATA]->u.arb_d.value);
+ PF_UNLOCK_HANDLE(in_data->sequence_data);
+ }
+ }
+
+ return err;
+}
+
+
+std::string GetProjectDir(PF_InData *in_data)
+{
+ if(in_data->appl_id == 'PrMr')
+ return std::string("");
+
+ AEGP_SuiteHandler suites(in_data->pica_basicP);
+
+ AEGP_ProjectH projH = NULL;
+ suites.ProjSuite5()->AEGP_GetProjectByIndex(0, &projH);
+
+ AEGP_MemHandle pathH = NULL;
+ suites.ProjSuite5()->AEGP_GetProjectPath(projH, &pathH);
+
+ if(pathH)
+ {
+ std::string proj_dir;
+
+ A_UTF16Char *path = NULL;
+ suites.MemorySuite1()->AEGP_LockMemHandle(pathH, (void **)&path);
+
+ if(path)
+ {
+ // poor-man's unicode copy
+ char c_path[AEGP_MAX_PATH_SIZE];
+
+ char *c = c_path;
+ A_UTF16Char *s = path;
+
+ do{
+ *c++ = *s;
+ }while(*s++ != '\0');
+
+#ifdef WIN_ENV
+#define PATH_DELIMITER '\\'
+#else
+#define PATH_DELIMITER '/'
+#endif
+
+ std::string proj_path(c_path);
+
+ if(proj_path.find_last_of(PATH_DELIMITER) != std::string::npos)
+ {
+ proj_dir = proj_path.substr(0, proj_path.find_last_of(PATH_DELIMITER));
+ }
+ }
+
+ suites.MemorySuite1()->AEGP_FreeMemHandle(pathH);
+
+ return proj_dir;
+ }
+
+ return std::string("");
+}
+
+
+static int FindInVec(const std::vector<std::string> &vec, const std::string val)
+{
+ for(int i=0; i < vec.size(); i++)
+ {
+ if(vec[i] == val)
+ return i;
+ }
+
+ return -1;
+}
+
+
+static void DoClickPath(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra,
+ ArbitraryData *arb_data,
+ SequenceData *seq_data)
+{
+ ExtensionMap extensions;
+
+ for(int i=0; i < OCIO::FileTransform::getNumFormats(); i++)
+ {
+ const char *extension = OCIO::FileTransform::getFormatExtensionByIndex(i);
+ const char *format = OCIO::FileTransform::getFormatNameByIndex(i);
+
+ extensions[ extension ] = format;
+ }
+
+ extensions[ "ocio" ] = "OCIO Format";
+
+
+ void *hwndOwner = NULL;
+
+#ifdef WIN_ENV
+ PF_GET_PLATFORM_DATA(PF_PlatData_MAIN_WND, &hwndOwner);
+#endif
+
+ char c_path[ARB_PATH_LEN + 1] = { '\0' };
+
+ bool result = OpenFile(c_path, ARB_PATH_LEN, extensions, hwndOwner);
+
+
+ if(result)
+ {
+ Path path(c_path, GetProjectDir(in_data));
+
+ OpenColorIO_AE_Context *new_context = new OpenColorIO_AE_Context(path.full_path(),
+ OCIO_SOURCE_CUSTOM);
+
+ if(new_context == NULL)
+ throw OCIO::Exception("WTF?");
+
+
+ if(seq_data->context)
+ {
+ delete seq_data->context;
+ }
+
+ seq_data->context = new_context;
+
+ arb_data->source = seq_data->source = OCIO_SOURCE_CUSTOM;
+
+ strncpy(arb_data->path, path.full_path().c_str(), ARB_PATH_LEN);
+ strncpy(arb_data->relative_path, path.relative_path(false).c_str(), ARB_PATH_LEN);
+
+ strncpy(seq_data->path, arb_data->path, ARB_PATH_LEN);
+ strncpy(seq_data->relative_path, arb_data->relative_path, ARB_PATH_LEN);
+
+
+ // try to retain settings if it looks like the same situation,
+ // possibly fixing a moved path
+ if(OCIO_ACTION_NONE == arb_data->action ||
+ (OCIO_ACTION_LUT == new_context->getAction() && OCIO_ACTION_LUT != arb_data->action) ||
+ (OCIO_ACTION_LUT != new_context->getAction() && OCIO_ACTION_LUT == arb_data->action) ||
+ (OCIO_ACTION_LUT != new_context->getAction() &&
+ (-1 == FindInVec(new_context->getInputs(), arb_data->input) ||
+ -1 == FindInVec(new_context->getInputs(), arb_data->output) ||
+ -1 == FindInVec(new_context->getTransforms(), arb_data->transform) ||
+ -1 == FindInVec(new_context->getDevices(), arb_data->device) ) ) )
+ {
+ // Configuration is different, so initialize defaults
+ arb_data->action = seq_data->context->getAction();
+
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ arb_data->invert = FALSE;
+ arb_data->interpolation = OCIO_INTERP_LINEAR;
+ }
+ else
+ {
+ strncpy(arb_data->input, seq_data->context->getInput().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->output, seq_data->context->getOutput().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->transform, seq_data->context->getTransform().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->device, seq_data->context->getDevice().c_str(), ARB_SPACE_LEN);
+ }
+ }
+ else
+ {
+ // Configuration is the same, retain current settings
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ seq_data->context->setupLUT(arb_data->invert, arb_data->interpolation);
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ seq_data->context->setupConvert(arb_data->input, arb_data->output);
+ }
+ else if(arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ seq_data->context->setupDisplay(arb_data->input, arb_data->transform, arb_data->device);
+ }
+ }
+
+ params[OCIO_DATA]->uu.change_flags = PF_ChangeFlag_CHANGED_VALUE;
+
+ seq_data->status = STATUS_USING_ABSOLUTE;
+ }
+}
+
+
+static void DoClickConfig(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra,
+ ArbitraryData *arb_data,
+ SequenceData *seq_data)
+{
+ void *hwndOwner = NULL;
+
+#ifdef WIN_ENV
+ PF_GET_PLATFORM_DATA(PF_PlatData_MAIN_WND, &hwndOwner);
+#endif
+
+ ConfigVec configs;
+ GetStdConfigs(configs);
+
+ if(configs.size() == 0)
+ configs.push_back("(nada)"); // menu makes a gray entry that says "No configs in $PATH"
+
+
+ MenuVec menu_items;
+ int selected = 0;
+
+ menu_items.push_back("$OCIO"); // menu will gray this out if $OCIO is not defined
+
+ menu_items.push_back("(-"); // this tells the menu to make a seperator
+
+ for(ConfigVec::const_iterator i = configs.begin(); i != configs.end(); ++i)
+ {
+ menu_items.push_back( *i );
+
+ if(arb_data->source == OCIO_SOURCE_STANDARD && arb_data->path == *i)
+ {
+ selected = menu_items.size() - 1;
+ }
+ }
+
+ menu_items.push_back("(-");
+
+ menu_items.push_back("Custom...");
+
+ int custom_choice = menu_items.size() - 1;
+
+ if(arb_data->source == OCIO_SOURCE_CUSTOM)
+ {
+ selected = -1;
+ }
+
+
+ int choice = PopUpMenu(menu_items, selected, hwndOwner);
+
+
+ if(choice == custom_choice)
+ {
+ // custom is the same as clicking the path
+ DoClickPath(in_data, out_data, params, output, event_extra, arb_data, seq_data);
+ }
+ else if(choice != selected)
+ {
+ OpenColorIO_AE_Context *new_context = NULL;
+
+ if(choice == 0)
+ {
+ // $OCIO
+ char *file = std::getenv("OCIO");
+
+ if(file)
+ {
+ Path path(file, GetProjectDir(in_data));
+
+ new_context = new OpenColorIO_AE_Context(path.full_path(),
+ OCIO_SOURCE_ENVIRONMENT);
+
+ arb_data->source = seq_data->source = OCIO_SOURCE_ENVIRONMENT;
+
+ strncpy(arb_data->path, path.full_path().c_str(), ARB_PATH_LEN);
+ strncpy(arb_data->relative_path, path.relative_path(false).c_str(), ARB_PATH_LEN);
+ }
+ else
+ throw OCIO::Exception("No $OCIO environment variable defined.");
+ }
+ else
+ {
+ // standard configs
+ std::string config = configs[choice - 2];
+
+ std::string path = GetStdConfigPath(config);
+
+ if( !path.empty() )
+ {
+ new_context = new OpenColorIO_AE_Context(config, OCIO_SOURCE_STANDARD);
+
+ arb_data->source = seq_data->source = OCIO_SOURCE_STANDARD;
+
+ strncpy(arb_data->path, config.c_str(), ARB_PATH_LEN);
+ strncpy(arb_data->relative_path, path.c_str(), ARB_PATH_LEN);
+ }
+ else
+ throw OCIO::Exception("Problem loading OCIO configuration.");
+ }
+
+
+ if(new_context)
+ {
+ if(seq_data->context)
+ {
+ delete seq_data->context;
+ }
+
+ seq_data->context = new_context;
+
+
+ strncpy(seq_data->path, arb_data->path, ARB_PATH_LEN);
+ strncpy(seq_data->relative_path, arb_data->relative_path, ARB_PATH_LEN);
+
+ // try to retain settings if it looks like the same situation,
+ // possibly fixing a moved path
+ if(OCIO_ACTION_NONE == arb_data->action ||
+ (OCIO_ACTION_LUT == new_context->getAction() && OCIO_ACTION_LUT != arb_data->action) ||
+ (OCIO_ACTION_LUT != new_context->getAction() && OCIO_ACTION_LUT == arb_data->action) ||
+ (OCIO_ACTION_LUT != new_context->getAction() &&
+ (-1 == FindInVec(new_context->getInputs(), arb_data->input) ||
+ -1 == FindInVec(new_context->getInputs(), arb_data->output) ||
+ -1 == FindInVec(new_context->getTransforms(), arb_data->transform) ||
+ -1 == FindInVec(new_context->getDevices(), arb_data->device) ) ) )
+ {
+ // Configuration is different, so initialize defaults
+ arb_data->action = seq_data->context->getAction();
+
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ arb_data->invert = FALSE;
+ arb_data->interpolation = OCIO_INTERP_LINEAR;
+ }
+ else
+ {
+ strncpy(arb_data->input, seq_data->context->getInput().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->output, seq_data->context->getOutput().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->transform, seq_data->context->getTransform().c_str(), ARB_SPACE_LEN);
+ strncpy(arb_data->device, seq_data->context->getDevice().c_str(), ARB_SPACE_LEN);
+ }
+ }
+ else
+ {
+ // Configuration is the same, retain current settings
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ seq_data->context->setupLUT(arb_data->invert, arb_data->interpolation);
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ seq_data->context->setupConvert(arb_data->input, arb_data->output);
+ }
+ else if(arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ seq_data->context->setupDisplay(arb_data->input, arb_data->transform, arb_data->device);
+ }
+ }
+
+ params[OCIO_DATA]->uu.change_flags = PF_ChangeFlag_CHANGED_VALUE;
+
+ seq_data->status = STATUS_OK;
+ }
+ }
+}
+
+
+static void DoClickConvertDisplay(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra,
+ ArbitraryData *arb_data,
+ SequenceData *seq_data,
+ UIRegion reg )
+{
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ if(reg == REGION_CONVERT_BUTTON) // i.e. Invert
+ {
+ // doing it this way so that any exceptions thrown by setupLUT
+ // because the LUT can't be inverted are thrown before
+ // I actually chenge the ArbData setting
+ seq_data->context->setupLUT(!arb_data->invert, arb_data->interpolation);
+
+ arb_data->invert = !arb_data->invert;
+
+ params[OCIO_DATA]->uu.change_flags = PF_ChangeFlag_CHANGED_VALUE;
+ }
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT || arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ if(reg == REGION_CONVERT_BUTTON && arb_data->action != OCIO_ACTION_CONVERT)
+ {
+ arb_data->action = OCIO_ACTION_CONVERT;
+
+ seq_data->context->setupConvert(arb_data->input, arb_data->output);
+
+ params[OCIO_DATA]->uu.change_flags = PF_ChangeFlag_CHANGED_VALUE;
+ }
+ else if(reg == REGION_DISPLAY_BUTTON && arb_data->action != OCIO_ACTION_DISPLAY)
+ {
+ arb_data->action = OCIO_ACTION_DISPLAY;
+
+ seq_data->context->setupDisplay(arb_data->input, arb_data->transform, arb_data->device);
+
+ params[OCIO_DATA]->uu.change_flags = PF_ChangeFlag_CHANGED_VALUE;
+ }
+ }
+}
+
+
+static void DoClickExport(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra,
+ ArbitraryData *arb_data,
+ SequenceData *seq_data,
+ UIRegion reg )
+{
+ ExtensionMap extensions;
+
+ for(int i=0; i < OCIO::Baker::getNumFormats(); ++i)
+ {
+ const char *extension = OCIO::Baker::getFormatExtensionByIndex(i);
+ const char *format = OCIO::Baker::getFormatNameByIndex(i);
+
+ extensions[ extension ] = format;
+ }
+
+ extensions[ "icc" ] = "ICC Profile";
+
+
+ void *hwndOwner = NULL;
+
+#ifdef WIN_ENV
+ PF_GET_PLATFORM_DATA(PF_PlatData_MAIN_WND, &hwndOwner);
+#endif
+
+ char path[256] = { '\0' };
+
+ bool result = SaveFile(path, 255, extensions, hwndOwner);
+
+
+ if(result)
+ {
+ std::string the_path(path);
+ std::string the_extension = the_path.substr( the_path.find_last_of('.') + 1 );
+
+ bool do_export = true;
+
+ std::string monitor_icc_path;
+
+ if(the_extension == "icc")
+ {
+ char monitor_path[256] = {'\0'};
+
+ do_export = GetMonitorProfile(monitor_path, 255, hwndOwner);
+
+ if(monitor_path[0] != '\0')
+ monitor_icc_path = monitor_path;
+ }
+
+ if(do_export)
+ seq_data->context->ExportLUT(the_path, monitor_icc_path);
+ }
+}
+
+
+static void DoClickMenus(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra,
+ ArbitraryData *arb_data,
+ SequenceData *seq_data,
+ UIRegion reg )
+{
+ if(seq_data->context != NULL && arb_data->action == seq_data->context->getAction())
+ {
+ MenuVec menu_items;
+ int selected_item;
+
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ if(reg == REGION_MENU1)
+ {
+ menu_items.push_back("Nearest Neighbor");
+ menu_items.push_back("Linear");
+ menu_items.push_back("Tetrahedral");
+ menu_items.push_back("(-");
+ menu_items.push_back("Best");
+
+ selected_item = arb_data->interpolation == OCIO_INTERP_NEAREST ? 0 :
+ arb_data->interpolation == OCIO_INTERP_LINEAR ? 1 :
+ arb_data->interpolation == OCIO_INTERP_TETRAHEDRAL ? 2 :
+ arb_data->interpolation == OCIO_INTERP_BEST ? 4 :
+ -1;
+ }
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ menu_items = seq_data->context->getInputs();
+
+ if(reg == REGION_MENU1)
+ {
+ selected_item = FindInVec(menu_items, arb_data->input);
+ }
+ else
+ {
+ selected_item = FindInVec(menu_items, arb_data->output);
+ }
+ }
+ else if(arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ if(reg == REGION_MENU1)
+ {
+ menu_items = seq_data->context->getInputs();
+
+ selected_item = FindInVec(menu_items, arb_data->input);
+ }
+ else if(reg == REGION_MENU2)
+ {
+ menu_items = seq_data->context->getTransforms();
+
+ selected_item = FindInVec(menu_items, arb_data->transform);
+ }
+ else if(reg == REGION_MENU3)
+ {
+ menu_items = seq_data->context->getDevices();
+
+ selected_item = FindInVec(menu_items, arb_data->device);
+ }
+ }
+
+
+
+ void *hwndOwner = NULL;
+
+ #ifdef WIN_ENV
+ PF_GET_PLATFORM_DATA(PF_PlatData_MAIN_WND, &hwndOwner);
+ #endif
+
+ int result = PopUpMenu(menu_items, selected_item, hwndOwner);
+
+
+ if(result != selected_item)
+ {
+ std::string color_space = menu_items[ result ];
+
+ if(arb_data->action == OCIO_ACTION_LUT)
+ {
+ if(reg == REGION_MENU1)
+ {
+ arb_data->interpolation = result == 0 ? OCIO_INTERP_NEAREST :
+ result == 2 ? OCIO_INTERP_TETRAHEDRAL :
+ result == 4 ? OCIO_INTERP_BEST :
+ OCIO_INTERP_LINEAR;
+
+ seq_data->context->setupLUT(arb_data->invert, arb_data->interpolation);
+ }
+ }
+ else if(arb_data->action == OCIO_ACTION_CONVERT)
+ {
+ if(reg == REGION_MENU1)
+ {
+ strncpy(arb_data->input, color_space.c_str(), ARB_SPACE_LEN);
+ }
+ else if(reg == REGION_MENU2)
+ {
+ strncpy(arb_data->output, color_space.c_str(), ARB_SPACE_LEN);
+ }
+
+ seq_data->context->setupConvert(arb_data->input, arb_data->output);
+ }
+ else if(arb_data->action == OCIO_ACTION_DISPLAY)
+ {
+ if(reg == REGION_MENU1)
+ {
+ strncpy(arb_data->input, color_space.c_str(), ARB_SPACE_LEN);
+ }
+ else if(reg == REGION_MENU2)
+ {
+ strncpy(arb_data->transform, color_space.c_str(), ARB_SPACE_LEN);
+ }
+ else if(reg == REGION_MENU3)
+ {
+ strncpy(arb_data->device, color_space.c_str(), ARB_SPACE_LEN);
+ }
+
+ seq_data->context->setupDisplay(arb_data->input, arb_data->transform, arb_data->device);
+ }
+
+ params[OCIO_DATA]->uu.change_flags = PF_ChangeFlag_CHANGED_VALUE;
+ }
+ }
+}
+
+
+static PF_Err DoClick(
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *event_extra )
+{
+ PF_Err err = PF_Err_NONE;
+
+ ArbitraryData *arb_data = (ArbitraryData *)PF_LOCK_HANDLE(params[OCIO_DATA]->u.arb_d.value);
+ SequenceData *seq_data = (SequenceData *)PF_LOCK_HANDLE(in_data->sequence_data);
+
+
+ if(event_extra->effect_win.area == PF_EA_CONTROL)
+ {
+ bool menus_visible = (arb_data->action != OCIO_ACTION_NONE);
+ bool third_menu = (arb_data->action == OCIO_ACTION_DISPLAY);
+
+ PF_Point local_point;
+
+ local_point.h = event_extra->u.do_click.screen_point.h - event_extra->effect_win.current_frame.left;
+ local_point.v = event_extra->u.do_click.screen_point.v - event_extra->effect_win.current_frame.top;
+
+ UIRegion reg = WhichRegion(local_point, menus_visible, third_menu);
+
+ if(reg != REGION_NONE)
+ {
+ try
+ {
+ if(reg == REGION_CONFIG_MENU)
+ {
+ DoClickConfig(in_data, out_data, params, output,
+ event_extra, arb_data, seq_data);
+ }
+ else if(reg == REGION_PATH)
+ {
+ if(arb_data->source == OCIO_SOURCE_CUSTOM)
+ {
+ DoClickPath(in_data, out_data, params, output,
+ event_extra, arb_data, seq_data);
+ }
+ }
+ else if(arb_data->action != OCIO_ACTION_NONE &&
+ seq_data->status != STATUS_FILE_MISSING)
+ {
+ if(seq_data->context == NULL)
+ {
+ seq_data->context = new OpenColorIO_AE_Context(arb_data,
+ GetProjectDir(in_data) );
+ }
+
+ if(reg == REGION_CONVERT_BUTTON || reg == REGION_DISPLAY_BUTTON)
+ {
+ DoClickConvertDisplay(in_data, out_data, params, output,
+ event_extra, arb_data, seq_data, reg);
+ }
+ else if(reg == REGION_EXPORT_BUTTON)
+ {
+ DoClickExport(in_data, out_data, params, output,
+ event_extra, arb_data, seq_data, reg);
+ }
+ else // must be a menu then
+ {
+ DoClickMenus(in_data, out_data, params, output,
+ event_extra, arb_data, seq_data, reg);
+ }
+ }
+ }
+ catch(std::exception &e)
+ {
+ if(in_data->appl_id == 'FXTC')
+ {
+ PF_SPRINTF(out_data->return_msg, e.what());
+
+ out_data->out_flags |= PF_OutFlag_DISPLAY_ERROR_MESSAGE;
+ }
+ else
+ {
+ void *hwndOwner = NULL;
+
+ #ifdef WIN_ENV
+ PF_GET_PLATFORM_DATA(PF_PlatData_MAIN_WND, &hwndOwner);
+ #endif
+
+ ErrorMessage(e.what(), hwndOwner);
+ }
+ }
+ catch(...)
+ {
+ PF_SPRINTF(out_data->return_msg, "Unknown error");
+
+ out_data->out_flags |= PF_OutFlag_DISPLAY_ERROR_MESSAGE;
+ }
+ }
+ }
+
+
+ PF_UNLOCK_HANDLE(params[OCIO_DATA]->u.arb_d.value);
+ PF_UNLOCK_HANDLE(in_data->sequence_data);
+
+ event_extra->evt_out_flags = PF_EO_HANDLED_EVENT;
+
+ return err;
+}
+
+
+PF_Err HandleEvent (
+ PF_InData *in_data,
+ PF_OutData *out_data,
+ PF_ParamDef *params[],
+ PF_LayerDef *output,
+ PF_EventExtra *extra )
+{
+ PF_Err err = PF_Err_NONE;
+
+ extra->evt_out_flags = 0;
+
+ if(!err)
+ {
+ switch(extra->e_type)
+ {
+ case PF_Event_DRAW:
+ err = DrawEvent(in_data, out_data, params, output, extra);
+ break;
+
+ case PF_Event_DO_CLICK:
+ err = DoClick(in_data, out_data, params, output, extra);
+ break;
+ }
+ }
+
+ return err;
+}
diff --git a/src/aftereffects/mac/OpenColorIO_AE.plugin-Info.plist b/src/aftereffects/mac/OpenColorIO_AE.plugin-Info.plist
new file mode 100755
index 0000000..45ad29d
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE.plugin-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleIdentifier</key>
+ <string>org.OpenColorIO.AfterEffects</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>OpenColorIO</string>
+ <key>CFBundleExecutable</key>
+ <string>OpenColorIO</string>
+ <key>CFBundlePackageType</key>
+ <string>eFKT</string>
+ <key>CFBundleSignature</key>
+ <string>FXTC</string>
+ <key>NSAppleScriptEnabled</key>
+ <string>No</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>© 2011 OpenColorIO</string>
+ <key>LSRequiresCarbon</key>
+ <true/>
+</dict>
+</plist>
diff --git a/src/aftereffects/mac/OpenColorIO_AE_Dialogs_Cocoa.mm b/src/aftereffects/mac/OpenColorIO_AE_Dialogs_Cocoa.mm
new file mode 100644
index 0000000..24a048f
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_Dialogs_Cocoa.mm
@@ -0,0 +1,237 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "OpenColorIO_AE_Dialogs.h"
+
+#import "OpenColorIO_AE_MonitorProfileChooser_Controller.h"
+
+#import "OpenColorIO_AE_Menu.h"
+
+
+bool OpenFile(char *path, int buf_len, const ExtensionMap &extensions, const void *hwnd)
+{
+ NSOpenPanel *panel = [NSOpenPanel openPanel];
+
+ [panel setTitle:@"OpenColorIO"];
+
+
+ NSMutableArray *extension_array = [[NSMutableArray alloc] init];
+ std::string message = "Formats: ";
+ bool first_one = true;
+
+ for(ExtensionMap::const_iterator i = extensions.begin(); i != extensions.end(); i++)
+ {
+ [extension_array addObject:[NSString stringWithUTF8String:i->first.c_str()]];
+
+ if(first_one)
+ first_one = false;
+ else
+ message += ", ";
+
+ message += "." + i->first;
+ }
+
+ [panel setMessage:[NSString stringWithUTF8String:message.c_str()]];
+
+
+ NSInteger result = [panel runModalForTypes:extension_array];
+
+
+ [extension_array release];
+
+
+ if(result == NSOKButton)
+ {
+ return [[panel filename] getCString:path
+ maxLength:buf_len
+ encoding:NSASCIIStringEncoding];
+ }
+ else
+ return false;
+}
+
+
+bool SaveFile(char *path, int buf_len, const ExtensionMap &extensions, const void *hwnd)
+{
+ NSSavePanel *panel = [NSSavePanel savePanel];
+
+ [panel setTitle:@"OpenColorIO"];
+
+
+ NSMutableArray *extension_array = [[NSMutableArray alloc] init];
+ std::string message = "Formats: ";
+ bool first_one = true;
+
+ for(ExtensionMap::const_iterator i = extensions.begin(); i != extensions.end(); i++)
+ {
+ [extension_array addObject:[NSString stringWithUTF8String:i->first.c_str()]];
+
+ if(first_one)
+ first_one = false;
+ else
+ message += ", ";
+
+ message += i->second + " (." + i->first + ")";
+ }
+
+ [panel setAllowedFileTypes:extension_array];
+ [panel setMessage:[NSString stringWithUTF8String:message.c_str()]];
+
+
+ NSInteger result = [panel runModal];
+
+
+ [extension_array release];
+
+
+ if(result == NSOKButton)
+ {
+ return [[panel filename] getCString:path
+ maxLength:buf_len
+ encoding:NSASCIIStringEncoding];
+ }
+ else
+ return false;
+}
+
+
+bool GetMonitorProfile(char *path, int buf_len, const void *hwnd)
+{
+ bool hit_ok = false;
+
+ Class ui_controller_class = [[NSBundle bundleWithIdentifier:@"org.OpenColorIO.AfterEffects"]
+ classNamed:@"OpenColorIO_AE_MonitorProfileChooser_Controller"];
+
+ if(ui_controller_class)
+ {
+ OpenColorIO_AE_MonitorProfileChooser_Controller *ui_controller = [[ui_controller_class alloc] init];
+
+ if(ui_controller)
+ {
+ NSWindow *my_window = [ui_controller getWindow];
+
+ if(my_window)
+ {
+ NSInteger result = [NSApp runModalForWindow:my_window];
+
+ if(result == NSRunStoppedResponse)
+ {
+ [ui_controller getMonitorProfile:path bufferSize:buf_len];
+
+ hit_ok = true;
+ }
+
+ [my_window release];
+ }
+
+ [ui_controller release];
+ }
+ }
+
+ return hit_ok;
+}
+
+
+void GetStdConfigs(ConfigVec &configs)
+{
+ const char *ocio_dir = "/Library/Application Support/OpenColorIO/";
+
+ NSFileManager *man = [NSFileManager defaultManager];
+
+ NSDirectoryEnumerator *enumerator = [man enumeratorAtPath:[NSString stringWithUTF8String:ocio_dir]];
+
+ for(NSString *file in enumerator)
+ {
+ std::string config_path(ocio_dir);
+
+ config_path += [file UTF8String];
+
+ config_path += "/config.ocio";
+
+ [enumerator skipDescendents];
+
+ if([man fileExistsAtPath:[NSString stringWithUTF8String:config_path.c_str()]])
+ {
+ configs.push_back( [file UTF8String] );
+ }
+ }
+}
+
+
+std::string GetStdConfigPath(const std::string &name)
+{
+ const char *ocio_dir = "/Library/Application Support/OpenColorIO/";
+
+ std::string config_path = ocio_dir + name + "/config.ocio";
+
+ if( [[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:config_path.c_str()]] )
+ {
+ return config_path;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+
+int PopUpMenu(const MenuVec &menu_items, int selected_index, const void *hwnd)
+{
+ NSMutableArray *item_array = [[NSMutableArray alloc] init];
+
+ for(MenuVec::const_iterator i = menu_items.begin(); i != menu_items.end(); i++)
+ {
+ [item_array addObject:[NSString stringWithUTF8String:i->c_str()]];
+ }
+
+
+ OpenColorIO_AE_Menu *menu = [[OpenColorIO_AE_Menu alloc] init:item_array
+ selectedItem:selected_index];
+
+ [menu showMenu];
+
+ NSInteger item = [menu selectedItem];
+
+ [menu release];
+ [item_array release];
+
+ return item;
+}
+
+
+void ErrorMessage(const char *message, const void *hwnd)
+{
+ NSAlert *alert = [[NSAlert alloc] init];
+
+ [alert setMessageText:[NSString stringWithUTF8String:message]];
+
+ [alert runModal];
+
+ [alert release];
+}
+
diff --git a/src/aftereffects/mac/OpenColorIO_AE_GL_Cocoa.mm b/src/aftereffects/mac/OpenColorIO_AE_GL_Cocoa.mm
new file mode 100644
index 0000000..3fc3797
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_GL_Cocoa.mm
@@ -0,0 +1,178 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE_GL.h"
+
+#import <Cocoa/Cocoa.h>
+
+
+
+static NSWindow *g_win = nil;
+static AGLContext g_context = NULL;
+static GLuint g_framebuffer;
+
+
+static bool HaveRequiredExtensions()
+{
+ const GLubyte *strVersion = glGetString(GL_VERSION);
+ const GLubyte *strExt = glGetString(GL_EXTENSIONS);
+
+ if(strVersion == NULL || strExt == NULL)
+ return false;
+
+ float gl_version;
+ sscanf((char *)strVersion, "%f", &gl_version);
+
+#define CheckExtension(N) gluCheckExtension((const GLubyte *)N, strExt)
+
+ return (gl_version >= 2.0 &&
+ CheckExtension("GL_ARB_color_buffer_float") &&
+ CheckExtension("GL_ARB_texture_float") &&
+ CheckExtension("GL_ARB_vertex_program") &&
+ CheckExtension("GL_ARB_vertex_shader") &&
+ CheckExtension("GL_ARB_texture_cube_map") &&
+ CheckExtension("GL_ARB_fragment_shader") &&
+ CheckExtension("GL_ARB_draw_buffers") &&
+ CheckExtension("GL_ARB_framebuffer_object") );
+}
+
+
+void GlobalSetup_GL()
+{
+ GLint aAttribs[64];
+ u_short nIndexS= -1;
+
+ aAttribs[++nIndexS] = AGL_RGBA;
+ aAttribs[++nIndexS] = AGL_DOUBLEBUFFER;
+ aAttribs[++nIndexS] = AGL_COLOR_FLOAT;
+
+ aAttribs[++nIndexS] = AGL_RED_SIZE;
+ aAttribs[++nIndexS] = 32;
+ aAttribs[++nIndexS] = AGL_GREEN_SIZE;
+ aAttribs[++nIndexS] = 32;
+ aAttribs[++nIndexS] = AGL_BLUE_SIZE;
+ aAttribs[++nIndexS] = 32;
+ aAttribs[++nIndexS] = AGL_ALPHA_SIZE;
+ aAttribs[++nIndexS] = 32;
+
+ aAttribs[++nIndexS] = AGL_NONE;
+
+
+ AGLPixelFormat oPixelFormat = aglChoosePixelFormat(NULL, 0, aAttribs);
+
+ if(oPixelFormat)
+ {
+ g_context = aglCreateContext(oPixelFormat, NULL);
+
+ aglDestroyPixelFormat(oPixelFormat);
+ }
+
+
+ if(g_context == NULL)
+ return;
+
+
+ g_win = [[NSWindow alloc] initWithContentRect:NSZeroRect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+
+
+ aglSetDrawable(g_context, (AGLDrawable)[[g_win graphicsContext] graphicsPort]);
+
+ glFlush();
+
+
+ SetPluginContext();
+
+
+
+ GLint units;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS, &units);
+
+
+ if( !HaveRequiredExtensions() || units < 2)
+ {
+ GlobalSetdown_GL();
+ SetAEContext();
+ return;
+ }
+
+ glGenFramebuffersEXT(1, &g_framebuffer);
+
+
+ SetAEContext();
+}
+
+
+bool HaveOpenGL()
+{
+ return (g_context != NULL && g_win != nil);
+}
+
+
+static AGLContext g_ae_context;
+
+void SetPluginContext()
+{
+ g_ae_context = aglGetCurrentContext();
+
+ aglSetCurrentContext(g_context);
+}
+
+
+void SetAEContext()
+{
+ // g_ae_context might be NULL...so be it
+ aglSetCurrentContext(g_ae_context);
+}
+
+
+GLuint GetFrameBuffer()
+{
+ return g_framebuffer;
+}
+
+
+void GlobalSetdown_GL()
+{
+ if(g_context)
+ {
+ aglDestroyContext(g_context);
+ g_context = NULL;
+
+ glDeleteFramebuffersEXT(1, &g_framebuffer);
+ }
+
+ if(g_win)
+ {
+ [g_win release];
+ g_win = nil;
+ }
+}
diff --git a/src/aftereffects/mac/OpenColorIO_AE_Menu.h b/src/aftereffects/mac/OpenColorIO_AE_Menu.h
new file mode 100644
index 0000000..e8920fa
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_Menu.h
@@ -0,0 +1,45 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface OpenColorIO_AE_Menu : NSView {
+ NSArray *menu_items;
+ NSInteger chosen_item;
+}
+
+- (id)init:(NSArray *)menuItems selectedItem:(NSInteger)selected;
+
+- (void)showMenu;
+
+- (IBAction)menuItemAction:(id)sender;
+
+- (NSInteger)selectedItem;
+
+@end
diff --git a/src/aftereffects/mac/OpenColorIO_AE_Menu.m b/src/aftereffects/mac/OpenColorIO_AE_Menu.m
new file mode 100644
index 0000000..6d0a44b
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_Menu.m
@@ -0,0 +1,114 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#import "OpenColorIO_AE_Menu.h"
+
+
+@implementation OpenColorIO_AE_Menu
+
+- (id)init:(NSArray *)menuItems selectedItem:(NSInteger)selected {
+ self = [super init];
+
+ menu_items = menuItems;
+ chosen_item = selected;
+
+ return self;
+}
+
+- (void)showMenu {
+
+ // Doing some pretty weird stuff here.
+ // I need to bring up a contextual menu without AE giving me an NSView.
+ // To get the screen position, I use global NSApp methods.
+ // And I need to make an NSView to give to popUpContextMenu:
+ // so I can catch the selectors it sends, so I made this an NSView subclass.
+
+ NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Pop-Up"];
+
+ [menu setAutoenablesItems:FALSE];
+
+
+ NSUInteger i;
+
+ for(i=0; i < [menu_items count]; i++)
+ {
+ if( [[menu_items objectAtIndex:i] isEqualToString:@"(-"] )
+ {
+ [menu addItem:[NSMenuItem separatorItem]];
+ }
+ else
+ {
+ NSMenuItem *item = [menu addItemWithTitle:[menu_items objectAtIndex:i]
+ action:@selector(menuItemAction:)
+ keyEquivalent:@""];
+
+ [item setTag:i];
+
+ if(i == chosen_item)
+ [item setState:NSOnState];
+
+ if([[menu_items objectAtIndex:i] isEqualToString:@"$OCIO"] && NULL == getenv("OCIO"))
+ {
+ [item setEnabled:FALSE];
+ [item setState:NSOffState];
+ }
+ else if([[menu_items objectAtIndex:i] isEqualToString:@"(nada)"])
+ {
+ [item setTitle:@"No configs in /Library/Application Support/OpenColorIO/"];
+ [item setEnabled:FALSE];
+ }
+ }
+ }
+
+
+ id fakeMouseEvent=[NSEvent mouseEventWithType:NSLeftMouseDown
+ location: [[NSApp keyWindow] convertScreenToBase:[NSEvent mouseLocation]]
+ modifierFlags:0
+ timestamp:0
+ windowNumber: [[NSApp keyWindow] windowNumber]
+ context:nil
+ eventNumber:0
+ clickCount:1
+ pressure:0];
+
+ [NSMenu popUpContextMenu:menu withEvent:fakeMouseEvent forView:self];
+
+ [menu release];
+}
+
+- (IBAction)menuItemAction:(id)sender {
+ NSMenuItem *item = (NSMenuItem *)sender;
+
+ chosen_item = [item tag];
+}
+
+- (NSInteger)selectedItem {
+ return chosen_item;
+}
+
+@end
diff --git a/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser.xib b/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser.xib
new file mode 100644
index 0000000..4e18dbe
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser.xib
@@ -0,0 +1,494 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">10K549</string>
+ <string key="IBDocument.InterfaceBuilderVersion">851</string>
+ <string key="IBDocument.AppKitVersion">1038.36</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="NS.object.0">851</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">OpenColorIO_AE_MonitorProfileChooser_Controller</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="1005">
+ <int key="NSWindowStyleMask">1</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 369}, {364, 141}}</string>
+ <int key="NSWTFlags">544735232</int>
+ <string key="NSWindowTitle">OpenColorIO</string>
+ <string key="NSWindowClass">NSWindow</string>
+ <nil key="NSViewClass"/>
+ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ <object class="NSView" key="NSWindowView" id="1006">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSPopUpButton" id="313635640">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{125, 87}, {222, 26}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSPopUpButtonCell" key="NSCell" id="127421210">
+ <int key="NSCellFlags">-2076049856</int>
+ <int key="NSCellFlags2">2048</int>
+ <object class="NSFont" key="NSSupport" id="928433575">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">13</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="313635640"/>
+ <int key="NSButtonFlags">109199615</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">400</int>
+ <int key="NSPeriodicInterval">75</int>
+ <nil key="NSMenuItem"/>
+ <bool key="NSMenuItemRespectAlignment">YES</bool>
+ <object class="NSMenu" key="NSMenu" id="39894973">
+ <string key="NSTitle">OtherViews</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="NSMenuFont" ref="928433575"/>
+ </object>
+ <int key="NSSelectedIndex">-1</int>
+ <int key="NSPreferredEdge">1</int>
+ <bool key="NSUsesItemFromMenu">YES</bool>
+ <bool key="NSAltersState">YES</bool>
+ <int key="NSArrowPosition">2</int>
+ </object>
+ </object>
+ <object class="NSTextField" id="116991834">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{17, 94}, {106, 17}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="292780847">
+ <int key="NSCellFlags">68288064</int>
+ <int key="NSCellFlags2">138413056</int>
+ <string key="NSContents">Monitor Profile:</string>
+ <reference key="NSSupport" ref="928433575"/>
+ <reference key="NSControlView" ref="116991834"/>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2ODY1AA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlTextColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSButton" id="995505874">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{254, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="15784021">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">OK</string>
+ <reference key="NSSupport" ref="928433575"/>
+ <reference key="NSControlView" ref="995505874"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ <object class="NSButton" id="1070422003">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{158, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="393092215">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">Cancel</string>
+ <reference key="NSSupport" ref="928433575"/>
+ <reference key="NSControlView" ref="1070422003"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string type="base64-UTF8" key="NSKeyEquivalent">Gw</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{364, 141}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">profileMenu</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="313635640"/>
+ </object>
+ <int key="connectionID">15</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">16</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">clickCancel:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1070422003"/>
+ </object>
+ <int key="connectionID">17</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">clickOK:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="995505874"/>
+ </object>
+ <int key="connectionID">18</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="1005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1006"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="1006"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="313635640"/>
+ <reference ref="116991834"/>
+ <reference ref="995505874"/>
+ <reference ref="1070422003"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="313635640"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="127421210"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="127421210"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="39894973"/>
+ </object>
+ <reference key="parent" ref="313635640"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="39894973"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="parent" ref="127421210"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="116991834"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="292780847"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">10</int>
+ <reference key="object" ref="292780847"/>
+ <reference key="parent" ref="116991834"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">11</int>
+ <reference key="object" ref="995505874"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="15784021"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">12</int>
+ <reference key="object" ref="15784021"/>
+ <reference key="parent" ref="995505874"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">13</int>
+ <reference key="object" ref="1070422003"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="393092215"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">14</int>
+ <reference key="object" ref="393092215"/>
+ <reference key="parent" ref="1070422003"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>1.IBWindowTemplateEditedContentRect</string>
+ <string>1.NSWindowTemplate.visibleAtLaunch</string>
+ <string>1.WindowOrigin</string>
+ <string>1.editorWindowContentRectSynchronizationRect</string>
+ <string>10.IBPluginDependency</string>
+ <string>11.IBPluginDependency</string>
+ <string>11.IBViewBoundsToFrameTransform</string>
+ <string>12.IBPluginDependency</string>
+ <string>13.IBPluginDependency</string>
+ <string>13.IBViewBoundsToFrameTransform</string>
+ <string>14.IBPluginDependency</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.IBPluginDependency</string>
+ <string>3.IBViewBoundsToFrameTransform</string>
+ <string>4.IBPluginDependency</string>
+ <string>5.IBEditorWindowLastContentRect</string>
+ <string>5.IBPluginDependency</string>
+ <string>9.IBPluginDependency</string>
+ <string>9.IBViewBoundsToFrameTransform</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>{{498, 559}, {364, 141}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{498, 559}, {364, 141}}</string>
+ <boolean value="NO"/>
+ <string>{196, 240}</string>
+ <string>{{202, 428}, {480, 270}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABDfgAAwigAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABDfgAAwigAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABDFAAAw1oAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{598, 628}, {110, 4}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABCIAAAw1gAAA</bytes>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">18</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">OpenColorIO_AE_MonitorProfileChooser_Controller</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="actions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>clickCancel:</string>
+ <string>clickOK:</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>clickCancel:</string>
+ <string>clickOK:</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBActionInfo">
+ <string key="name">clickCancel:</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">clickOK:</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>profileMenu</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSPopUpButton</string>
+ <string>NSWindow</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>profileMenu</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">profileMenu</string>
+ <string key="candidateClassName">NSPopUpButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">window</string>
+ <string key="candidateClassName">NSWindow</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">OpenColorIO_AE_MonitorProfileChooser_Controller.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <integer value="1050" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">OpenColorIO_AE.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.h b/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.h
new file mode 100644
index 0000000..024fa29
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#import <Cocoa/Cocoa.h>
+
+@interface OpenColorIO_AE_MonitorProfileChooser_Controller : NSObject {
+ IBOutlet NSPopUpButton *profileMenu;
+ IBOutlet NSWindow *window;
+
+ NSMutableArray *name_array;
+ NSMapTable *profile_map;
+}
+
+- (IBAction)clickOK:(NSButton *)sender;
+- (IBAction)clickCancel:(NSButton *)sender;
+
+- (NSWindow *)getWindow;
+
+- (BOOL)getMonitorProfile:(char *)path bufferSize:(int)buf_len;
+
+@end
diff --git a/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.m b/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.m
new file mode 100644
index 0000000..323a83c
--- /dev/null
+++ b/src/aftereffects/mac/OpenColorIO_AE_MonitorProfileChooser_Controller.m
@@ -0,0 +1,195 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#import "OpenColorIO_AE_MonitorProfileChooser_Controller.h"
+
+
+typedef struct {
+ NSMutableArray *name_array;
+ NSMapTable *profile_map;
+ const char *monitor_profile_path;
+ char *monitor_profile_name;
+} IterateData;
+
+static OSErr profIterateProc(CMProfileIterateData* data, void* refcon)
+{
+ OSErr err = noErr;
+
+ IterateData *i_data = (IterateData *)refcon;
+
+ if(data->header.dataColorSpace == cmRGBData && data->location.locType == cmPathBasedProfile)
+ {
+ [i_data->name_array addObject:[NSString stringWithUTF8String:data->asciiName]];
+
+ [i_data->profile_map setObject:[NSString stringWithUTF8String:data->location.u.pathLoc.path]
+ forKey:[NSString stringWithUTF8String:data->asciiName] ];
+
+ if( i_data->monitor_profile_path &&
+ !strcmp(data->location.u.pathLoc.path, i_data->monitor_profile_path) )
+ {
+ strncpy(i_data->monitor_profile_name, data->asciiName, 255);
+ }
+ }
+
+ return err;
+}
+
+
+
+@implementation OpenColorIO_AE_MonitorProfileChooser_Controller
+
+- (id)init {
+ self = [super init];
+
+ if(!([NSBundle loadNibNamed:@"OpenColorIO_AE_MonitorProfileChooser" owner:self]))
+ return nil;
+
+
+ [window center];
+
+ // Originally tried to implement this with two NSArrays, one with paths and
+ // one with profile names (ICC descriptions). The problem is that when you
+ // add items to NSArrays one at a time, they auto-sort. But then it turns out I
+ // WANT them to sort because the profiles come in random order and the menu looks
+ // terrible if they're not sorted.
+
+ // So I make an NSArray to set up the menu and an NSMapTable to convert from the
+ // selected menu item to the actual path. Got that?
+
+
+ name_array = [[NSMutableArray alloc] init];
+ profile_map = [[NSMapTable alloc] init];
+
+
+ // get monitor profile path
+
+ // Oddly enough, the "Name" given to me by ColorSync for this is often "Display",
+ // but if you get the profile's description, you get something like
+ // "Apple Cinema HD Display". So to see if ColorSync runs accross the the monitor's
+ // profile so I can select it, I have to compare the paths, and then save the name
+ // I'm currently getting.
+
+ CMProfileRef prof;
+ CMProfileLocation profLoc;
+
+ UInt32 locationSize = cmCurrentProfileLocationSize;
+
+ // Get the main GDevice.
+ CGDirectDisplayID theAVID = CGMainDisplayID();
+
+ // Get the profile for that AVID.
+ CMError err = CMGetProfileByAVID(theAVID, &prof);
+
+ // Get location (FSRef) for that profile
+ err = NCMGetProfileLocation(prof, &profLoc, &locationSize);
+
+ const char *monitor_profile_path = NULL;
+ char monitor_profile_name[256] = { '\0' };
+
+ if(profLoc.locType == cmPathBasedProfile)
+ {
+ monitor_profile_path = profLoc.u.pathLoc.path;
+ }
+
+
+
+ // build profile map and name array
+ IterateData i_data = { name_array, profile_map, monitor_profile_path, monitor_profile_name };
+
+ UInt32 seed = 0;
+ UInt32 count;
+
+ CMProfileIterateUPP iterateUPP;
+ iterateUPP = NewCMProfileIterateUPP((CMProfileIterateProcPtr)&profIterateProc);
+
+ err = CMIterateColorSyncFolder(iterateUPP, &seed, &count, (void *)&i_data);
+
+ DisposeCMProfileIterateUPP(iterateUPP);
+
+
+
+ // set up menu with array
+ [profileMenu addItemsWithTitles:name_array];
+
+
+
+ // choose the display profile name if we have it (usually "Display")
+ if(monitor_profile_name[0] != '\0')
+ {
+ [profileMenu selectItemWithTitle:[NSString stringWithUTF8String:monitor_profile_name]];
+ }
+ else if(monitor_profile_path != NULL)
+ {
+ // somehow the display profile wasn't found during iteration
+ // so let's add it
+ CFStringRef m_name;
+
+ err = CMCopyProfileDescriptionString(prof, &m_name);
+
+ NSString *ns_name = (NSString *)monitor_profile_name;
+
+ [profile_map setObject:[NSString stringWithUTF8String:monitor_profile_path]
+ forKey:ns_name ];
+
+ [profileMenu addItemWithTitle:ns_name];
+
+ [profileMenu selectItemWithTitle:ns_name];
+
+ CFRelease(m_name);
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ [name_array release];
+ [profile_map release];
+
+ [super dealloc];
+}
+
+- (IBAction)clickOK:(NSButton *)sender {
+ [NSApp stopModal];
+}
+
+- (IBAction)clickCancel:(NSButton *)sender {
+ [NSApp abortModal];
+}
+
+- (NSWindow *)getWindow {
+ return window;
+}
+
+- (BOOL)getMonitorProfile:(char *)path bufferSize:(int)buf_len {
+ NSString *icc_name = [[profileMenu selectedItem] title];
+ NSString *icc_path = [profile_map objectForKey:icc_name];
+
+ return [icc_path getCString:path maxLength:buf_len encoding:NSMacOSRomanStringEncoding];
+}
+
+@end
diff --git a/src/aftereffects/vc/vc9/OpenColorABI.h b/src/aftereffects/vc/vc9/OpenColorABI.h
new file mode 100644
index 0000000..acbb8b4
--- /dev/null
+++ b/src/aftereffects/vc/vc9/OpenColorABI.h
@@ -0,0 +1,100 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_OPENCOLORABI_H
+#define INCLUDED_OCIO_OPENCOLORABI_H
+
+// Makefile configuration options
+#define OCIO_NAMESPACE OpenColorIO
+#define OCIO_USE_BOOST_PTR 1
+#define OCIO_VERSION "1.0.7"
+#define OCIO_VERSION_NS v1
+
+/* Version as a single 4-byte hex number, e.g. 0x01050200 == 1.5.2
+ Use this for numeric comparisons, e.g. #if OCIO_VERSION_HEX >= ...
+ Note: in the case where SOVERSION is overridden at compile-time,
+ this will reflect the original API version number.
+ */
+#define OCIO_VERSION_HEX ((1 << 24) | \
+ (0 << 16) | \
+ (7 << 8))
+
+
+// Namespace / version mojo
+#define OCIO_NAMESPACE_ENTER namespace OCIO_NAMESPACE { namespace OCIO_VERSION_NS
+#define OCIO_NAMESPACE_EXIT using namespace OCIO_VERSION_NS; }
+#define OCIO_NAMESPACE_USING using namespace OCIO_NAMESPACE;
+
+// shared_ptr / dynamic_pointer_cast
+#if OCIO_USE_BOOST_PTR
+#include <boost/shared_ptr.hpp>
+#define OCIO_SHARED_PTR boost::shared_ptr
+#define OCIO_DYNAMIC_POINTER_CAST boost::dynamic_pointer_cast
+#elif __GNUC__ >= 4
+#include <tr1/memory>
+#define OCIO_SHARED_PTR std::tr1::shared_ptr
+#define OCIO_DYNAMIC_POINTER_CAST std::tr1::dynamic_pointer_cast
+#else
+#error OCIO needs gcc 4 or later to get access to <tr1/memory> (or specify USE_BOOST_PTR instead)
+#endif
+
+#ifdef OpenColorIO_SHARED
+ // If supported, define OCIOEXPORT, OCIOHIDDEN
+ // (used to choose which symbols to export from OpenColorIO)
+ #if defined __linux__ || __APPLE__
+ #if __GNUC__ >= 4
+ #define OCIOEXPORT __attribute__ ((visibility("default")))
+ #define OCIOHIDDEN __attribute__ ((visibility("hidden")))
+ #else
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+ #endif
+ #elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+ // Windows requires you to export from the main library and then import in any others
+ #if defined OpenColorIO_EXPORTS
+ #define OCIOEXPORT __declspec(dllexport)
+ #else
+ #define OCIOEXPORT __declspec(dllimport)
+ #endif
+ #define OCIOHIDDEN
+ #else // Others platforms not supported atm
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+ #endif
+#else
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+#endif
+
+// Windows defines these troublesome macros that collide with std::limits
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+#undef min
+#undef max
+#endif
+
+#endif // INCLUDED_OCIO_OPENCOLORABI_H
diff --git a/src/aftereffects/vc/vc9/OpenColorIO.vcproj b/src/aftereffects/vc/vc9/OpenColorIO.vcproj
new file mode 100644
index 0000000..45b17d2
--- /dev/null
+++ b/src/aftereffects/vc/vc9/OpenColorIO.vcproj
@@ -0,0 +1,667 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="OpenColorIO"
+ ProjectGUID="{8B308357-C548-49D9-9134-8A61D57D524C}"
+ RootNamespace="OpenColorIO"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\export;..\..\..\..\src\core;..\..\..\..\ext\boost_1_48_0;..\..\..\..\ext\tinyxml;&quot;..\..\..\..\ext\yaml-cpp\include&quot;;.\"
+ PreprocessorDefinitions="TIXML_USE_STL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\export;..\..\..\..\src\core;..\..\..\..\ext\boost_1_48_0;..\..\..\..\ext\tinyxml;&quot;..\..\..\..\ext\yaml-cpp\include&quot;;.\"
+ PreprocessorDefinitions="TIXML_USE_STL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\export;..\..\..\..\src\core;..\..\..\..\ext\boost_1_48_0;..\..\..\..\ext\tinyxml;&quot;..\..\..\..\ext\yaml-cpp\include&quot;;.\"
+ PreprocessorDefinitions="NDEBUG;TIXML_USE_STL"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\export;..\..\..\..\src\core;..\..\..\..\ext\boost_1_48_0;..\..\..\..\ext\tinyxml;&quot;..\..\..\..\ext\yaml-cpp\include&quot;;.\"
+ PreprocessorDefinitions="NDEBUG;TIXML_USE_STL"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\..\src\core\AllocationOp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\AllocationTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Baker.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Caching.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\CDLTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ColorSpace.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ColorSpaceTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Config.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Context.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\DisplayTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Exception.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ExponentOps.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ExponentTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormat3DL.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatCC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatCCC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatCSP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatHDL.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatIridasCube.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatIridasItx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\core\FileFormatIridasLook.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatPandora.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatSpi1D.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatSpi3D.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatSpiMtx.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatTruelight.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileFormatVF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\GpuShaderDesc.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\GpuShaderUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\GroupTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\HashUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ImageDesc.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ImagePacking.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Logging.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\LogOps.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\LogTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Look.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\core\LookParse.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\LookTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Lut1DOp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Lut3DOp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\MathUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\MatrixOps.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\MatrixTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\md5\md5.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\core\NoOps.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\OCIOYaml.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Op.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\core\OpOptimizers.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ParseUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\PathUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Processor.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\pystring\pystring.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ScanlineHelper.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Transform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\TruelightOp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\TruelightTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\UnitTest.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\..\src\core\AllocationOp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\CDLTransform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ExponentOps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\FileTransform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\GpuShaderUtils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\HashUtils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ImagePacking.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Logging.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\LogOps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\core\LookParse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Lut1DOp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Lut3DOp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\MathUtils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\MatrixOps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\md5\md5.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Mutex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\core\NoOps.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\OCIOYaml.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Op.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\OpBuilders.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\export\OpenColorIO\OpenColorIO.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\export\OpenColorIO\OpenColorTransforms.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\export\OpenColorIO\OpenColorTypes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ParseUtils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\PathUtils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Platform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\PrivateTypes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\Processor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\pystring\pystring.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\ScanlineHelper.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\SSE.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\TruelightOp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\src\core\UnitTest.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.sln b/src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.sln
new file mode 100644
index 0000000..61155eb
--- /dev/null
+++ b/src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.sln
@@ -0,0 +1,57 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenColorIO_AE", "OpenColorIO_AE.vcproj", "{78FCC6BC-06A9-43AE-827A-1B68FFB7D75F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {069FB60C-57CE-4D0F-9EC2-068E2A3F2930} = {069FB60C-57CE-4D0F-9EC2-068E2A3F2930}
+ {8B308357-C548-49D9-9134-8A61D57D524C} = {8B308357-C548-49D9-9134-8A61D57D524C}
+ {A19BA95E-D8ED-4958-883B-32561AF905EA} = {A19BA95E-D8ED-4958-883B-32561AF905EA}
+ {CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED} = {CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}
+ {F1DAC6DE-348A-4215-87B2-7584578291AC} = {F1DAC6DE-348A-4215-87B2-7584578291AC}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenColorIO", "..\OpenColorIO.vcproj", "{8B308357-C548-49D9-9134-8A61D57D524C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lcms", "..\ext\lcms.vcproj", "{069FB60C-57CE-4D0F-9EC2-068E2A3F2930}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml", "..\ext\tinyxml.vcproj", "{A19BA95E-D8ED-4958-883B-32561AF905EA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml", "..\ext\yaml.vcproj", "{F1DAC6DE-348A-4215-87B2-7584578291AC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew", "..\ext\glew.vcproj", "{CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {78FCC6BC-06A9-43AE-827A-1B68FFB7D75F}.Debug|x64.ActiveCfg = Debug|x64
+ {78FCC6BC-06A9-43AE-827A-1B68FFB7D75F}.Debug|x64.Build.0 = Debug|x64
+ {78FCC6BC-06A9-43AE-827A-1B68FFB7D75F}.Release|x64.ActiveCfg = Release|x64
+ {78FCC6BC-06A9-43AE-827A-1B68FFB7D75F}.Release|x64.Build.0 = Release|x64
+ {8B308357-C548-49D9-9134-8A61D57D524C}.Debug|x64.ActiveCfg = Debug|x64
+ {8B308357-C548-49D9-9134-8A61D57D524C}.Debug|x64.Build.0 = Debug|x64
+ {8B308357-C548-49D9-9134-8A61D57D524C}.Release|x64.ActiveCfg = Release|x64
+ {8B308357-C548-49D9-9134-8A61D57D524C}.Release|x64.Build.0 = Release|x64
+ {069FB60C-57CE-4D0F-9EC2-068E2A3F2930}.Debug|x64.ActiveCfg = Debug|x64
+ {069FB60C-57CE-4D0F-9EC2-068E2A3F2930}.Debug|x64.Build.0 = Debug|x64
+ {069FB60C-57CE-4D0F-9EC2-068E2A3F2930}.Release|x64.ActiveCfg = Release|x64
+ {069FB60C-57CE-4D0F-9EC2-068E2A3F2930}.Release|x64.Build.0 = Release|x64
+ {A19BA95E-D8ED-4958-883B-32561AF905EA}.Debug|x64.ActiveCfg = Debug|x64
+ {A19BA95E-D8ED-4958-883B-32561AF905EA}.Debug|x64.Build.0 = Debug|x64
+ {A19BA95E-D8ED-4958-883B-32561AF905EA}.Release|x64.ActiveCfg = Release|x64
+ {A19BA95E-D8ED-4958-883B-32561AF905EA}.Release|x64.Build.0 = Release|x64
+ {F1DAC6DE-348A-4215-87B2-7584578291AC}.Debug|x64.ActiveCfg = Debug|x64
+ {F1DAC6DE-348A-4215-87B2-7584578291AC}.Debug|x64.Build.0 = Debug|x64
+ {F1DAC6DE-348A-4215-87B2-7584578291AC}.Release|x64.ActiveCfg = Release|x64
+ {F1DAC6DE-348A-4215-87B2-7584578291AC}.Release|x64.Build.0 = Release|x64
+ {CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}.Debug|x64.ActiveCfg = Debug|x64
+ {CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}.Debug|x64.Build.0 = Debug|x64
+ {CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}.Release|x64.ActiveCfg = Release|x64
+ {CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.vcproj b/src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.vcproj
new file mode 100644
index 0000000..c95c0b0
--- /dev/null
+++ b/src/aftereffects/vc/vc9/aftereffects/OpenColorIO_AE.vcproj
@@ -0,0 +1,448 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="OpenColorIO_AE"
+ ProjectGUID="{78FCC6BC-06A9-43AE-827A-1B68FFB7D75F}"
+ RootNamespace="OpenColorIO_AE"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="3"
+ TypeLibraryName=".\Debug/OpenColorIO_AE.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\;..\..\..;..\..\..\..\apps\ociobakelut;..\..\..\..\..\export;..\..\..\..\..\ext\boost_1_48_0;&quot;..\..\..\..\..\ext\lcms2-2.1\include&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers\SP&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers\Win&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Resources&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Util&quot;;&quot;..\..\..\..\..\ext\glew-1.7.0\include&quot;"
+ PreprocessorDefinitions="MSWindows;WIN32;_DEBUG;_WINDOWS;GLEW_STATIC"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderThrough="AE_Effect.h"
+ AssemblerOutput="4"
+ BrowseInformation="1"
+ WarningLevel="2"
+ WarnAsError="false"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories=""
+ ShowProgress="true"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="Mscms.lib opengl32.lib"
+ ShowProgress="0"
+ OutputFile="C:\Program Files\Adobe\Adobe After Effects CS6\Support Files\Plug-ins\OpenColorIO.aex"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="libcmt.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(IntDir)\OpenColorIO_AE.pdb"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)\OpenColorIO_AE.lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ UseFAT32Workaround="true"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="3"
+ TypeLibraryName=".\Debug/OpenColorIO_AE.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories="..\;..\..\..;..\..\..\..\apps\ociobakelut;..\..\..\..\..\export;..\..\..\..\..\ext\boost_1_48_0;&quot;..\..\..\..\..\ext\lcms2-2.1\include&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers\SP&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers\Win&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Resources&quot;;&quot;..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Util&quot;;&quot;..\..\..\..\..\ext\glew-1.7.0\include&quot;"
+ PreprocessorDefinitions="MSWindows;WIN32;NDEBUG;_WINDOWS;GLEW_STATIC"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderThrough="AE_Effect.h"
+ AssemblerOutput="4"
+ BrowseInformation="1"
+ WarningLevel="2"
+ WarnAsError="false"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="0"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories=""
+ ShowProgress="true"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="Mscms.lib opengl32.lib"
+ ShowProgress="0"
+ OutputFile="$(OutDir)\OpenColorIO.aex"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="libcmt.lib"
+ GenerateDebugInformation="false"
+ ProgramDatabaseFile="$(IntDir)\OpenColorIO_AE.pdb"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)\OpenColorIO_AE.lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ UseFAT32Workaround="true"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Supporting Code"
+ Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Util\AEGP_SuiteHandler.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Util\MissingSuiteError.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\apps\ociobakelut\ocioicc.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;fi;fd"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Util\AEGP_SuiteHandler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\DrawbotBot.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\apps\ociobakelut\ocioicc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\OpenColorABI.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_Context.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_Dialogs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_GL.h"
+ >
+ </File>
+ <Filter
+ Name="AE"
+ >
+ <File
+ RelativePath="..\..\..\Headers\A.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_AdvEffectSuites.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_Effect.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_EffectCB.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_EffectCBSuites.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_EffectSuites.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Util\AE_EffectSuitesHelper.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_EffectUI.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_GeneralPlug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_GeneralPlugOld.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_IO.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\AE_Macros.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Util\AEFX_ArbParseHelper.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Util\AEGP_SuiteHandler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Util\entry.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\FIEL_Public.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Util\Param_Utils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\PF_Masks.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\PR_Public.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Headers\PT_Public.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\Util\String_Utils.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="..\..\..\win\OpenColorIO.rc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_PiPL.r"
+ >
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Compiling the PiPL"
+ CommandLine="cl /I &quot;$(ProjectDir)..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers&quot; /D USE_AE_EFFECT_VERS /EP &quot;..\..\..\$(InputName).r&quot; &gt; &quot;$(IntDir)&quot;\\&quot;$(InputName).rr&quot;&#x0D;&#x0A;&quot;$(ProjectDir)..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Resources\PiPLTool&quot; &quot;$(IntDir)\$(InputName).rr&quot; &quot;$(IntDir)\$(InputName).rrc&quot;&#x0D;&#x0A;cl /D &quot;MSWindows&quot; /EP $(IntDir)\$(InputName).rrc &gt; &quot;$(ProjectDir)&quot;\\&quot;$(InputName)&quot;.rc&#x0D;&#x0A;"
+ Outputs="$(ProjectDir)\$(InputName).rc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Compiling the PiPL"
+ CommandLine="cl /I &quot;$(ProjectDir)..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Headers&quot; /D USE_AE_EFFECT_VERS /EP &quot;..\..\..\$(InputName).r&quot; &gt; &quot;$(IntDir)&quot;\\&quot;$(InputName).rr&quot;&#x0D;&#x0A;&quot;$(ProjectDir)..\..\..\..\..\ext\Adobe After Effects CS5 SDK\Examples\Resources\PiPLTool&quot; &quot;$(IntDir)\$(InputName).rr&quot; &quot;$(IntDir)\$(InputName).rrc&quot;&#x0D;&#x0A;cl /D &quot;MSWindows&quot; /EP $(IntDir)\$(InputName).rrc &gt; &quot;$(ProjectDir)&quot;\\&quot;$(InputName)&quot;.rc&#x0D;&#x0A;"
+ Outputs="$(ProjectDir)\$(InputName).rc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\OpenColorIO_AE_PiPL.rc"
+ >
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""
+ ShowProgress="true"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""
+ ShowProgress="true"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\..\DrawbotBot.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_ArbData.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_Context.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\win\OpenColorIO_AE_Dialogs_Win.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\win\OpenColorIO_AE_GL_Win.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\OpenColorIO_AE_UI.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/aftereffects/vc/vc9/ext/glew.vcproj b/src/aftereffects/vc/vc9/ext/glew.vcproj
new file mode 100644
index 0000000..dad7be7
--- /dev/null
+++ b/src/aftereffects/vc/vc9/ext/glew.vcproj
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="glew"
+ ProjectGUID="{CC244BA5-4CA8-4B4F-B4CA-3394BF9E9FED}"
+ RootNamespace="glew"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\glew-1.7.0\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;GLEW_STATIC"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\glew-1.7.0\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;GLEW_STATIC"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\glew-1.7.0\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;GLEW_STATIC"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\glew-1.7.0\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;GLEW_STATIC"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\glew-1.7.0\src\glew.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\glew-1.7.0\src\glewinfo.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\glew-1.7.0\include\GL\glew.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\glew-1.7.0\include\GL\glxew.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\glew-1.7.0\include\GL\wglew.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/aftereffects/vc/vc9/ext/lcms.vcproj b/src/aftereffects/vc/vc9/ext/lcms.vcproj
new file mode 100644
index 0000000..d8dfbb4
--- /dev/null
+++ b/src/aftereffects/vc/vc9/ext/lcms.vcproj
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="lcms"
+ ProjectGUID="{069FB60C-57CE-4D0F-9EC2-068E2A3F2930}"
+ RootNamespace="lcms"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\lcms2-2.1\include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\lcms2-2.1\include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\lcms2-2.1\include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\lcms2-2.1\include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmscam02.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmscgats.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmscnvrt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmserr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsgamma.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsgmt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsintrp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsio0.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsio1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmslut.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsmd5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsmtrx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsnamed.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsopt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmspack.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmspcs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsplugin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsps2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmssamp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmssm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmstypes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsvirt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmswtpnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\cmsxform.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\include\lcms2.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\src\lcms2_internal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\lcms2-2.1\include\lcms2_plugin.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/aftereffects/vc/vc9/ext/tinyxml.vcproj b/src/aftereffects/vc/vc9/ext/tinyxml.vcproj
new file mode 100644
index 0000000..691f399
--- /dev/null
+++ b/src/aftereffects/vc/vc9/ext/tinyxml.vcproj
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="tinyxml"
+ ProjectGUID="{A19BA95E-D8ED-4958-883B-32561AF905EA}"
+ RootNamespace="tinyxml"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\tinyxml"
+ PreprocessorDefinitions="TIXML_USE_STL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\tinyxml"
+ PreprocessorDefinitions="TIXML_USE_STL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\tinyxml"
+ PreprocessorDefinitions="NDEBUG;TIXML_USE_STL"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\..\ext\tinyxml"
+ PreprocessorDefinitions="NDEBUG;TIXML_USE_STL"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\tinyxml\tinystr.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\tinyxml\tinyxml.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\tinyxml\tinyxmlerror.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\tinyxml\tinyxmlparser.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\tinyxml\tinystr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\tinyxml\tinyxml.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/aftereffects/vc/vc9/ext/yaml.vcproj b/src/aftereffects/vc/vc9/ext/yaml.vcproj
new file mode 100644
index 0000000..46a0fe5
--- /dev/null
+++ b/src/aftereffects/vc/vc9/ext/yaml.vcproj
@@ -0,0 +1,603 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="yaml"
+ ProjectGUID="{F1DAC6DE-348A-4215-87B2-7584578291AC}"
+ RootNamespace="yaml"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\yaml-cpp\include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\yaml-cpp\include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\yaml-cpp\include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="build\$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="&quot;..\..\..\..\..\ext\yaml-cpp\include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\aliasmanager.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\binary.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\conversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\directives.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\emitfromevents.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\emitter.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\emitterstate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\emitterutils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\exp.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\contrib\graphbuilder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\contrib\graphbuilderadapter.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\contrib\graphbuilderadapter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\iterator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\node.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\nodebuilder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\nodeownership.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\null.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\ostream.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\parser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\regex.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scanner.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scanscalar.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scantag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scantoken.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\simplekey.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\singledocparser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\stream.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\tag.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\aliasmanager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\anchor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\contrib\anchordict.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\collectionstack.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\conversion.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\directives.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\dll.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\emitfromevents.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\emitter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\emittermanip.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\emitterstate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\emitterutils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\eventhandler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\exceptions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\exp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\contrib\graphbuilder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\indentation.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\iterator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\iterpriv.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\ltnode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\mark.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\node.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\nodebuilder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\nodeimpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\nodeownership.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\nodereadimpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\nodeutil.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\noncopyable.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\null.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\ostream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\parser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\ptr_stack.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\ptr_vector.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\regex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\regeximpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scanner.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scanscalar.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\scantag.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\setting.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\singledocparser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\stlemitter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\stlnode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\streamcharsource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\stringsource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\tag.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\src\token.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\traits.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\ext\yaml-cpp\include\yaml-cpp\yaml.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/aftereffects/win/OpenColorIO.rc b/src/aftereffects/win/OpenColorIO.rc
new file mode 100644
index 0000000..e93fa8c
--- /dev/null
+++ b/src/aftereffects/win/OpenColorIO.rc
@@ -0,0 +1,99 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+PROFILEDIALOG DIALOGEX 0, 0, 233, 78
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "OpenColorIO"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,176,57,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,117,57,50,14
+ COMBOBOX 3,74,20,133,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Monitor Profile:",IDC_STATIC,15,20,55,12,SS_CENTERIMAGE,WS_EX_RIGHT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ "PROFILEDIALOG", DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 226
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 71
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/aftereffects/win/OpenColorIO_AE_Dialogs_Win.cpp b/src/aftereffects/win/OpenColorIO_AE_Dialogs_Win.cpp
new file mode 100644
index 0000000..78e8648
--- /dev/null
+++ b/src/aftereffects/win/OpenColorIO_AE_Dialogs_Win.cpp
@@ -0,0 +1,564 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE_Dialogs.h"
+
+#include <list>
+
+#include <Windows.h>
+#include <Shlobj.h>
+#include <Icm.h>
+
+
+#include "lcms2.h"
+
+
+HINSTANCE hDllInstance = NULL;
+
+static void AppendString(char *text, int &length, const char *str, int len = -1)
+{
+ if(len < 0)
+ len = strlen(str);
+
+ const char *in = str;
+ char *out = &text[length];
+
+ for(int i=0; i < len; i++)
+ {
+ *out++ = *in++;
+
+ length++;
+ }
+}
+
+static void AppendNull(char *text, int &length)
+{
+ AppendString(text, length, "\0\0", 1);
+}
+
+static void MakeFilterText(char *filter_text,
+ const ExtensionMap &extensions,
+ bool do_combined)
+{
+ // Construct the Windows file dialog filter string, which looks like this:
+ //
+ // "All OCIO files\0"
+ // "*.ocio;*.cube;*.vf;*.mga\0"
+ // "OpenColorIO (*.ocio)\0"
+ // "*.ocio\0"
+ // "Iridas (*.cube)\0"
+ // "*.cube\0"
+ // "Nuke Vectorfield (*.vf)\0"
+ // "*.vf\0"
+ // "Apple Color (*.mga)\0"
+ // "*.mga\0"
+ // "\0";
+ //
+ // Note the inline nulls and final double-null, which foil regular string functions.
+
+ char combined_entry[512];
+ int combined_length = 0;
+
+ char seperate_entries[512];
+ int seperate_length = 0;
+
+ AppendString(combined_entry, combined_length, "All OCIO files");
+ AppendNull(combined_entry, combined_length);
+
+ for(ExtensionMap::const_iterator i = extensions.begin(); i != extensions.end(); i++)
+ {
+ std::string extension = i->first;
+ std::string format = i->second;
+
+ std::string format_part = format + " (*." + extension + ")";
+ std::string extension_part = "*." + extension;
+ std::string combined_part = extension_part + ";";
+
+ AppendString(seperate_entries, seperate_length, format_part.c_str(), format_part.size());
+ AppendNull(seperate_entries, seperate_length);
+ AppendString(seperate_entries, seperate_length, extension_part.c_str(), extension_part.size());
+ AppendNull(seperate_entries, seperate_length);
+
+ AppendString(combined_entry, combined_length, combined_part.c_str(), combined_part.size());
+ }
+
+ AppendNull(seperate_entries, seperate_length);
+ AppendNull(combined_entry, combined_length);
+
+
+ char *in = combined_entry;
+ char *out = filter_text;
+
+ if(do_combined)
+ {
+ for(int i=0; i < combined_length; i++)
+ *out++ = *in++;
+ }
+
+ in = seperate_entries;
+
+ for(int i=0; i < seperate_length; i++)
+ *out++ = *in++;
+}
+
+
+bool OpenFile(char *path, int buf_len, const ExtensionMap &extensions, const void *hwnd)
+{
+ const char *my_lpstrTitle = "Import OCIO";
+ const char *my_lpstrDefExt = "ocio";
+
+ char my_lpstrFilter[512];
+ MakeFilterText(my_lpstrFilter, extensions, true);
+
+
+ OPENFILENAME lpofn;
+
+ lpofn.lStructSize = sizeof(lpofn);
+ lpofn.hwndOwner = (HWND)hwnd;
+ lpofn.hInstance = hDllInstance;
+ lpofn.lpstrFilter = my_lpstrFilter;
+ lpofn.lpstrCustomFilter = NULL;
+ lpofn.nMaxCustFilter = 0;
+ lpofn.nFilterIndex = 0;
+ lpofn.lpstrFile = path;
+ lpofn.nMaxFile = buf_len;
+ lpofn.lpstrFileTitle = path;
+ lpofn.nMaxFileTitle = buf_len;
+ lpofn.lpstrInitialDir = NULL;
+ lpofn.lpstrTitle = my_lpstrTitle;
+ lpofn.Flags = OFN_LONGNAMES |
+ OFN_HIDEREADONLY |
+ OFN_PATHMUSTEXIST |
+ OFN_OVERWRITEPROMPT;
+ lpofn.nFileOffset = 0;
+ lpofn.nFileExtension = 0;
+ lpofn.lpstrDefExt = my_lpstrDefExt;
+ lpofn.lCustData = 0;
+ lpofn.lpfnHook = NULL;
+ lpofn.lpTemplateName = NULL;
+ lpofn.lStructSize = sizeof(lpofn);
+
+ return GetOpenFileName(&lpofn);
+}
+
+
+bool SaveFile(char *path, int buf_len, const ExtensionMap &extensions, const void *hwnd)
+{
+ const char *my_lpstrTitle = "Export OCIO";
+ const char *my_lpstrDefExt = "icc";
+
+ char my_lpstrFilter[256];
+ MakeFilterText(my_lpstrFilter, extensions, false);
+
+
+ OPENFILENAME lpofn;
+
+ lpofn.lStructSize = sizeof(lpofn);
+ lpofn.hwndOwner = (HWND)hwnd;
+ lpofn.hInstance = hDllInstance;
+ lpofn.lpstrFilter = my_lpstrFilter;
+ lpofn.lpstrCustomFilter = NULL;
+ lpofn.nMaxCustFilter = 0;
+ lpofn.nFilterIndex = 0;
+ lpofn.lpstrFile = path;
+ lpofn.nMaxFile = buf_len;
+ lpofn.lpstrFileTitle = path;
+ lpofn.nMaxFileTitle = buf_len;
+ lpofn.lpstrInitialDir = NULL;
+ lpofn.lpstrTitle = my_lpstrTitle;
+ lpofn.Flags = OFN_LONGNAMES |
+ OFN_HIDEREADONLY |
+ OFN_PATHMUSTEXIST |
+ OFN_OVERWRITEPROMPT;
+ lpofn.nFileOffset = 0;
+ lpofn.nFileExtension = 0;
+ lpofn.lpstrDefExt = my_lpstrDefExt;
+ lpofn.lCustData = 0;
+ lpofn.lpfnHook = NULL;
+ lpofn.lpTemplateName = NULL;
+ lpofn.lStructSize = sizeof(lpofn);
+
+ return GetSaveFileName(&lpofn);
+}
+
+// dialog item IDs
+enum {
+ DLOG_noUI = -1,
+ DLOG_OK = IDOK, // was 1
+ DLOG_Cancel = IDCANCEL, // was 2
+ DLOG_Profile_Menu = 3
+};
+
+
+static std::vector<std::string> *g_profile_vec = NULL;
+static int g_selected_item = DLOG_noUI;
+
+static WORD g_item_clicked = 0;
+
+static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ BOOL fError;
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ do{
+ // add profile list to combo boxe
+ HWND menu = GetDlgItem(hwndDlg, DLOG_Profile_Menu);
+
+ for(int i=0; i < g_profile_vec->size(); i++)
+ {
+ SendMessage(menu, (UINT)CB_ADDSTRING,
+ (WPARAM)wParam, (LPARAM)(LPCTSTR)g_profile_vec->at(i).c_str() );
+
+ SendMessage(menu,(UINT)CB_SETITEMDATA,
+ (WPARAM)i, (LPARAM)(DWORD)i); // channel index number
+
+ if( g_selected_item == i )
+ SendMessage(menu, CB_SETCURSEL, (WPARAM)i, (LPARAM)0);
+ }
+ }while(0);
+ return FALSE;
+
+ case WM_COMMAND:
+ g_item_clicked = LOWORD(wParam);
+
+ switch(LOWORD(wParam))
+ {
+ case DLOG_OK:
+ case DLOG_Cancel: // do the same thing, but g_item_clicked differ
+ do{
+ HWND menu = GetDlgItem(hwndDlg, DLOG_Profile_Menu);
+
+ LRESULT cur_sel = SendMessage(menu, (UINT)CB_GETCURSEL,
+ (WPARAM)0, (LPARAM)0);
+
+ g_selected_item = SendMessage(menu, (UINT)CB_GETITEMDATA,
+ (WPARAM)cur_sel, (LPARAM)0);
+
+ }while(0);
+
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool GetMonitorProfile(char *path, int buf_len, const void *hwnd)
+{
+ std::list<std::string> profile_descriptions;
+ std::map<std::string, std::string> profile_paths;
+
+ // path to the monitor's profile
+ char monitor_profile_path[256] = { '\0' };
+ DWORD path_size = 256;
+ BOOL get_icm_result = GetICMProfile(GetDC((HWND)hwnd), &path_size, monitor_profile_path);
+
+ // directory where Windows stores its profiles
+ char profile_directory[256] = { '\0' };
+ DWORD dir_name_size = 256;
+ BOOL get_color_dir_result = GetColorDirectory(NULL, profile_directory, &dir_name_size);
+
+ // Get the profile file names from Windows
+ ENUMTYPE enum_type;
+ enum_type.dwSize = sizeof(ENUMTYPE);
+ enum_type.dwVersion = ENUM_TYPE_VERSION;
+ enum_type.dwFields = ET_DEVICECLASS; // alternately could use ET_CLASS
+ enum_type.dwDeviceClass = CLASS_MONITOR;
+
+ BYTE *buf = NULL;
+ DWORD buf_size = 0;
+ DWORD num_profiles = 0;
+
+ BOOL other_enum_result = EnumColorProfiles(NULL, &enum_type,
+ buf, &buf_size, &num_profiles);
+
+ if(buf_size > 0 && num_profiles > 0)
+ {
+ buf = (BYTE *)malloc(buf_size);
+
+ other_enum_result = EnumColorProfiles(NULL, &enum_type,
+ buf, &buf_size, &num_profiles);
+
+ if(other_enum_result)
+ {
+ // build a list of the profile descriptions
+ // and a map to return the paths
+ char *prof_name = (char *)buf;
+
+ for(int i=0; i < num_profiles; i++)
+ {
+ std::string prof = prof_name;
+ std::string prof_path = std::string(profile_directory) + "\\" + prof_name;
+
+ cmsHPROFILE hProfile = cmsOpenProfileFromFile(prof_path.c_str(), "r");
+
+ // Note: Windows will give us profiles that aren't ICC (.cdmp for example).
+ // Don't worry, LittleCMS will just return NULL for those.
+ if(hProfile)
+ {
+ char profile_description[256];
+
+ cmsUInt32Number got_desc = cmsGetProfileInfoASCII(hProfile,
+ cmsInfoDescription,
+ "en", "US",
+ profile_description,
+ 256);
+
+ if(got_desc)
+ {
+ profile_descriptions.push_back(profile_description);
+
+ profile_paths[ profile_description ] = prof_path;
+ }
+
+ cmsCloseProfile(hProfile);
+ }
+
+ prof_name += strlen(prof_name) + 1;
+ }
+ }
+
+ free(buf);
+ }
+
+
+ if(profile_descriptions.size() > 0)
+ {
+ // set a vector and selected index for building the profile menu
+ profile_descriptions.sort();
+ profile_descriptions.unique();
+
+ std::vector<std::string> profile_vec;
+ int selected = 0;
+
+ for(std::list<std::string>::const_iterator i = profile_descriptions.begin(); i != profile_descriptions.end(); i++)
+ {
+ profile_vec.push_back( *i );
+
+ if( profile_paths[ *i ] == monitor_profile_path)
+ {
+ selected = profile_vec.size() - 1;
+ }
+ }
+
+ // run the dialog
+ g_profile_vec = &profile_vec;
+ g_selected_item = selected;
+
+ int status = DialogBox(hDllInstance, (LPSTR)"PROFILEDIALOG",
+ (HWND)hwnd, (DLGPROC)DialogProc);
+
+
+ if(status == -1)
+ {
+ // dialog didn't open, my bad
+ return true;
+ }
+ else if(g_item_clicked == DLOG_Cancel)
+ {
+ return false;
+ }
+ else
+ {
+ strncpy(path, profile_paths[ profile_vec[ g_selected_item ] ].c_str(), buf_len);
+
+ return true;
+ }
+ }
+ else
+ return true;
+}
+
+
+int PopUpMenu(const MenuVec &menu_items, int selected_index, const void *hwnd)
+{
+ HMENU menu = CreatePopupMenu();
+
+ if(menu)
+ {
+ for(int i=0; i < menu_items.size(); i++)
+ {
+ std::string label = menu_items[i];
+
+ UINT flags = (i == selected_index ? (MF_STRING | MF_CHECKED) : MF_STRING);
+
+ if(label == "(-")
+ {
+ flags |= MF_SEPARATOR;
+ }
+ else if(label == "$OCIO")
+ {
+ char *file = std::getenv("OCIO");
+
+ if(file == NULL)
+ flags |= MF_GRAYED;
+ }
+ else if(label == "(nada)")
+ {
+ flags |= MF_GRAYED;
+
+ char appdata_path[MAX_PATH];
+ HRESULT result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, appdata_path);
+
+ if(result == S_OK)
+ {
+ label = "No configs in " + std::string(appdata_path) + "\\OpenColorIO\\";
+ }
+ }
+
+ AppendMenu(menu, flags, i + 1, label.c_str());
+ }
+
+ POINT pos;
+ GetCursorPos(&pos);
+
+ int result = TrackPopupMenuEx(menu,
+ (TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD),
+ pos.x, pos.y, (HWND)hwnd, NULL);
+
+ DestroyMenu(menu);
+
+ if(result == 0)
+ {
+ // means the user clicked off the menu
+ return selected_index;
+ }
+ else
+ return result - 1;
+ }
+ else
+ return selected_index;
+}
+
+
+void GetStdConfigs(ConfigVec &configs)
+{
+ char appdata_path[MAX_PATH];
+
+ HRESULT result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, appdata_path);
+
+ if(result == S_OK)
+ {
+ std::string dir_path = std::string(appdata_path) + "\\OpenColorIO\\";
+
+ std::string search_path = dir_path + "*";
+
+ WIN32_FIND_DATA find_data;
+
+ HANDLE searchH = FindFirstFile(search_path.c_str(), &find_data);
+
+ if(searchH != INVALID_HANDLE_VALUE)
+ {
+ if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ std::string config_path = dir_path + find_data.cFileName + "\\config.ocio";
+
+ WIN32_FIND_DATA find_data_temp;
+
+ HANDLE fileH = FindFirstFile(config_path.c_str(), &find_data_temp);
+
+ if(fileH != INVALID_HANDLE_VALUE)
+ {
+ configs.push_back(find_data.cFileName);
+
+ FindClose(fileH);
+ }
+ }
+
+ while( FindNextFile(searchH, &find_data) )
+ {
+ if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ std::string config_path = dir_path + find_data.cFileName + "\\config.ocio";
+
+ WIN32_FIND_DATA find_data_temp;
+
+ HANDLE fileH = FindFirstFile(config_path.c_str(), &find_data_temp);
+
+ if(fileH != INVALID_HANDLE_VALUE)
+ {
+ configs.push_back(find_data.cFileName);
+
+ FindClose(fileH);
+ }
+ }
+ }
+
+ FindClose(searchH);
+ }
+ }
+}
+
+
+std::string GetStdConfigPath(const std::string &name)
+{
+ char appdata_path[MAX_PATH];
+
+ HRESULT result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
+ SHGFP_TYPE_CURRENT, appdata_path);
+
+ if(result == S_OK)
+ {
+ std::string config_path = std::string(appdata_path) + "\\OpenColorIO\\" +
+ name + "\\config.ocio";
+
+ WIN32_FIND_DATA find_data;
+
+ HANDLE searchH = FindFirstFile(config_path.c_str(), &find_data);
+
+ if(searchH != INVALID_HANDLE_VALUE)
+ {
+ FindClose(searchH);
+
+ return config_path;
+ }
+ }
+
+ return "";
+}
+
+
+void ErrorMessage(const char *message , const void *hwnd)
+{
+ MessageBox((HWND)hwnd, message, "OpenColorIO", MB_OK);
+}
+
+
+BOOL WINAPI DllMain(HANDLE hInstance, DWORD fdwReason, LPVOID lpReserved)
+{
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ hDllInstance = (HINSTANCE)hInstance;
+
+ return TRUE;
+}
diff --git a/src/aftereffects/win/OpenColorIO_AE_GL_Win.cpp b/src/aftereffects/win/OpenColorIO_AE_GL_Win.cpp
new file mode 100644
index 0000000..867522a
--- /dev/null
+++ b/src/aftereffects/win/OpenColorIO_AE_GL_Win.cpp
@@ -0,0 +1,212 @@
+/*
+Copyright (c) 2003-2012 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "OpenColorIO_AE_GL.h"
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static HWND g_win = NULL;
+static HDC g_hdc = NULL;
+static HGLRC g_context = NULL;
+static GLuint g_framebuffer;
+
+
+static bool HaveRequiredExtensions()
+{
+ const GLubyte *strVersion = glGetString(GL_VERSION);
+ const GLubyte *strExt = glGetString(GL_EXTENSIONS);
+
+ if(strVersion == NULL)
+ return false;
+
+#define CheckExtension(N) glewIsExtensionSupported(N)
+
+ return (GLEW_VERSION_2_0 &&
+ CheckExtension("GL_ARB_color_buffer_float") &&
+ CheckExtension("GL_ARB_texture_float") &&
+ CheckExtension("GL_ARB_vertex_program") &&
+ CheckExtension("GL_ARB_vertex_shader") &&
+ CheckExtension("GL_ARB_texture_cube_map") &&
+ CheckExtension("GL_ARB_fragment_shader") &&
+ CheckExtension("GL_ARB_draw_buffers") &&
+ CheckExtension("GL_ARB_framebuffer_object") );
+}
+
+
+void GlobalSetup_GL()
+{
+ GLenum init = glewInit();
+
+ if(init != GLEW_OK)
+ return;
+
+
+ WNDCLASSEX winClass;
+ MSG uMsg;
+
+ memset(&uMsg,0,sizeof(uMsg));
+
+ winClass.lpszClassName = "OpenColorIO_AE_Win_Class";
+ winClass.cbSize = sizeof(WNDCLASSEX);
+ winClass.style = CS_HREDRAW | CS_VREDRAW;
+ winClass.lpfnWndProc = DefWindowProc;
+ winClass.hInstance = NULL;
+ winClass.hIcon = NULL;
+ winClass.hIconSm = NULL;
+ winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ winClass.lpszMenuName = NULL;
+ winClass.cbClsExtra = 0;
+ winClass.cbWndExtra = 0;
+
+ if( !( RegisterClassEx(&winClass) ) )
+ return;
+
+ g_win = CreateWindowEx( NULL, "OpenColorIO_AE_Win_Class",
+ "OpenGL-using FBOs in AE",
+ 0, 0,
+ 0, 50, 50,
+ NULL,
+ NULL,
+ NULL,
+ NULL );
+
+ if(g_win == NULL)
+ return;
+
+ g_hdc = GetDC(g_win);
+
+
+ int pixelFormat;
+
+ PIXELFORMATDESCRIPTOR pfd;
+ ZeroMemory( &pfd, sizeof( pfd ) );
+
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 128;
+ pfd.cDepthBits = 32;
+ pfd.cStencilBits = 32;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ pixelFormat = ChoosePixelFormat(g_hdc, &pfd);
+
+ BOOL set_format = SetPixelFormat(g_hdc, pixelFormat, &pfd);
+
+ if(!set_format)
+ {
+ GlobalSetdown_GL();
+ return;
+ }
+
+ g_context = wglCreateContext(g_hdc);
+
+ glFlush();
+
+ if(g_context == NULL)
+ {
+ GlobalSetdown_GL();
+ return;
+ }
+
+
+ SetPluginContext();
+
+
+ GLint units;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS, &units);
+
+
+ if( !HaveRequiredExtensions() || units < 2)
+ {
+ GlobalSetdown_GL();
+ SetAEContext();
+ return;
+ }
+
+ glGenFramebuffersEXT(1, &g_framebuffer);
+
+
+ SetAEContext();
+}
+
+
+bool HaveOpenGL()
+{
+ return (g_context != NULL && g_win != NULL);
+}
+
+
+static HDC g_ae_hdc;
+static HGLRC g_ae_context;
+
+void SetPluginContext()
+{
+ g_ae_hdc = wglGetCurrentDC();
+ g_ae_context = wglGetCurrentContext();
+
+ wglMakeCurrent(g_hdc, g_context);
+}
+
+
+void SetAEContext()
+{
+ wglMakeCurrent(g_ae_hdc, g_ae_context);
+}
+
+
+GLuint GetFrameBuffer()
+{
+ return g_framebuffer;
+}
+
+
+void GlobalSetdown_GL()
+{
+ if(g_context)
+ {
+ wglDeleteContext(g_context);
+ g_context = NULL;
+
+ glDeleteFramebuffersEXT(1, &g_framebuffer);
+ }
+
+ if(g_win)
+ {
+ ReleaseDC(g_win, g_hdc);
+ g_win = NULL;
+ g_hdc = NULL;
+
+ UnregisterClass("OpenColorIO_AE_Win_Class", NULL);
+ }
+}
diff --git a/src/aftereffects/win/resource.h b/src/aftereffects/win/resource.h
new file mode 100644
index 0000000..2191cce
--- /dev/null
+++ b/src/aftereffects/win/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by OpenColorIO.rc
+//
+#define IDB_BITMAP1 102
+#define BANNER1 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/aftereffects/xcode/OpenColorABI.h b/src/aftereffects/xcode/OpenColorABI.h
new file mode 100644
index 0000000..a3ce756
--- /dev/null
+++ b/src/aftereffects/xcode/OpenColorABI.h
@@ -0,0 +1,100 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_OPENCOLORABI_H
+#define INCLUDED_OCIO_OPENCOLORABI_H
+
+// Makefile configuration options
+#define OCIO_NAMESPACE OpenColorIO
+#define OCIO_USE_BOOST_PTR 0
+#define OCIO_VERSION "1.0.7"
+#define OCIO_VERSION_NS v1
+
+/* Version as a single 4-byte hex number, e.g. 0x01050200 == 1.5.2
+ Use this for numeric comparisons, e.g. #if OCIO_VERSION_HEX >= ...
+ Note: in the case where SOVERSION is overridden at compile-time,
+ this will reflect the original API version number.
+ */
+#define OCIO_VERSION_HEX ((1 << 24) | \
+ (0 << 16) | \
+ (7 << 8))
+
+
+// Namespace / version mojo
+#define OCIO_NAMESPACE_ENTER namespace OCIO_NAMESPACE { namespace OCIO_VERSION_NS
+#define OCIO_NAMESPACE_EXIT using namespace OCIO_VERSION_NS; }
+#define OCIO_NAMESPACE_USING using namespace OCIO_NAMESPACE;
+
+// shared_ptr / dynamic_pointer_cast
+#if OCIO_USE_BOOST_PTR
+#include <boost/shared_ptr.hpp>
+#define OCIO_SHARED_PTR boost::shared_ptr
+#define OCIO_DYNAMIC_POINTER_CAST boost::dynamic_pointer_cast
+#elif __GNUC__ >= 4
+#include <tr1/memory>
+#define OCIO_SHARED_PTR std::tr1::shared_ptr
+#define OCIO_DYNAMIC_POINTER_CAST std::tr1::dynamic_pointer_cast
+#else
+#error OCIO needs gcc 4 or later to get access to <tr1/memory> (or specify USE_BOOST_PTR instead)
+#endif
+
+#ifdef OpenColorIO_SHARED
+ // If supported, define OCIOEXPORT, OCIOHIDDEN
+ // (used to choose which symbols to export from OpenColorIO)
+ #if defined __linux__ || __APPLE__
+ #if __GNUC__ >= 4
+ #define OCIOEXPORT __attribute__ ((visibility("default")))
+ #define OCIOHIDDEN __attribute__ ((visibility("hidden")))
+ #else
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+ #endif
+ #elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+ // Windows requires you to export from the main library and then import in any others
+ #if defined OpenColorIO_EXPORTS
+ #define OCIOEXPORT __declspec(dllexport)
+ #else
+ #define OCIOEXPORT __declspec(dllimport)
+ #endif
+ #define OCIOHIDDEN
+ #else // Others platforms not supported atm
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+ #endif
+#else
+ #define OCIOEXPORT
+ #define OCIOHIDDEN
+#endif
+
+// Windows defines these troublesome macros that collide with std::limits
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+#undef min
+#undef max
+#endif
+
+#endif // INCLUDED_OCIO_OPENCOLORABI_H
diff --git a/src/aftereffects/xcode/OpenColorIO.xcodeproj/project.pbxproj b/src/aftereffects/xcode/OpenColorIO.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..eb84949
--- /dev/null
+++ b/src/aftereffects/xcode/OpenColorIO.xcodeproj/project.pbxproj
@@ -0,0 +1,589 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2A7CACBB15536CD700F52C98 /* FileFormatIridasLook.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7CACB515536CD700F52C98 /* FileFormatIridasLook.cpp */; };
+ 2A7CACBC15536CD700F52C98 /* LookParse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7CACB615536CD700F52C98 /* LookParse.cpp */; };
+ 2A7CACBD15536CD700F52C98 /* LookParse.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A7CACB715536CD700F52C98 /* LookParse.h */; };
+ 2A7CACBE15536CD700F52C98 /* NoOps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7CACB815536CD700F52C98 /* NoOps.cpp */; };
+ 2A7CACBF15536CD700F52C98 /* NoOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A7CACB915536CD700F52C98 /* NoOps.h */; };
+ 2A7CACC015536CD700F52C98 /* OpOptimizers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7CACBA15536CD700F52C98 /* OpOptimizers.cpp */; };
+ 2ACF56CC14776A1E00991ED5 /* AllocationOp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567614776A1E00991ED5 /* AllocationOp.cpp */; };
+ 2ACF56CD14776A1E00991ED5 /* AllocationOp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF567714776A1E00991ED5 /* AllocationOp.h */; };
+ 2ACF56CE14776A1E00991ED5 /* AllocationTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567814776A1E00991ED5 /* AllocationTransform.cpp */; };
+ 2ACF56CF14776A1E00991ED5 /* Baker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567914776A1E00991ED5 /* Baker.cpp */; };
+ 2ACF56D014776A1E00991ED5 /* Caching.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567A14776A1E00991ED5 /* Caching.cpp */; };
+ 2ACF56D114776A1E00991ED5 /* CDLTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567B14776A1E00991ED5 /* CDLTransform.cpp */; };
+ 2ACF56D214776A1E00991ED5 /* CDLTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF567C14776A1E00991ED5 /* CDLTransform.h */; };
+ 2ACF56D314776A1E00991ED5 /* ColorSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567D14776A1E00991ED5 /* ColorSpace.cpp */; };
+ 2ACF56D414776A1E00991ED5 /* ColorSpaceTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567E14776A1E00991ED5 /* ColorSpaceTransform.cpp */; };
+ 2ACF56D514776A1E00991ED5 /* Config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF567F14776A1E00991ED5 /* Config.cpp */; };
+ 2ACF56D614776A1E00991ED5 /* Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568014776A1E00991ED5 /* Context.cpp */; };
+ 2ACF56D714776A1E00991ED5 /* DisplayTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568114776A1E00991ED5 /* DisplayTransform.cpp */; };
+ 2ACF56D814776A1E00991ED5 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568214776A1E00991ED5 /* Exception.cpp */; };
+ 2ACF56D914776A1E00991ED5 /* ExponentOps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568314776A1E00991ED5 /* ExponentOps.cpp */; };
+ 2ACF56DA14776A1E00991ED5 /* ExponentOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF568414776A1E00991ED5 /* ExponentOps.h */; };
+ 2ACF56DB14776A1E00991ED5 /* ExponentTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568514776A1E00991ED5 /* ExponentTransform.cpp */; };
+ 2ACF56DC14776A1E00991ED5 /* FileFormat3DL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568614776A1E00991ED5 /* FileFormat3DL.cpp */; };
+ 2ACF56DD14776A1E00991ED5 /* FileFormatCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568714776A1E00991ED5 /* FileFormatCC.cpp */; };
+ 2ACF56DE14776A1E00991ED5 /* FileFormatCCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568814776A1E00991ED5 /* FileFormatCCC.cpp */; };
+ 2ACF56DF14776A1E00991ED5 /* FileFormatCSP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568914776A1E00991ED5 /* FileFormatCSP.cpp */; };
+ 2ACF56E014776A1E00991ED5 /* FileFormatHDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568A14776A1E00991ED5 /* FileFormatHDL.cpp */; };
+ 2ACF56E114776A1E00991ED5 /* FileFormatIridasCube.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568B14776A1E00991ED5 /* FileFormatIridasCube.cpp */; };
+ 2ACF56E214776A1E00991ED5 /* FileFormatIridasItx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568C14776A1E00991ED5 /* FileFormatIridasItx.cpp */; };
+ 2ACF56E314776A1E00991ED5 /* FileFormatPandora.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568D14776A1E00991ED5 /* FileFormatPandora.cpp */; };
+ 2ACF56E414776A1E00991ED5 /* FileFormatSpi1D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568E14776A1E00991ED5 /* FileFormatSpi1D.cpp */; };
+ 2ACF56E514776A1E00991ED5 /* FileFormatSpi3D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF568F14776A1E00991ED5 /* FileFormatSpi3D.cpp */; };
+ 2ACF56E614776A1E00991ED5 /* FileFormatSpiMtx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569014776A1E00991ED5 /* FileFormatSpiMtx.cpp */; };
+ 2ACF56E714776A1E00991ED5 /* FileFormatTruelight.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569114776A1E00991ED5 /* FileFormatTruelight.cpp */; };
+ 2ACF56E814776A1E00991ED5 /* FileFormatVF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569214776A1E00991ED5 /* FileFormatVF.cpp */; };
+ 2ACF56E914776A1E00991ED5 /* FileTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569314776A1E00991ED5 /* FileTransform.cpp */; };
+ 2ACF56EA14776A1E00991ED5 /* FileTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF569414776A1E00991ED5 /* FileTransform.h */; };
+ 2ACF56EC14776A1E00991ED5 /* GpuShaderDesc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569614776A1E00991ED5 /* GpuShaderDesc.cpp */; };
+ 2ACF56ED14776A1E00991ED5 /* GpuShaderUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569714776A1E00991ED5 /* GpuShaderUtils.cpp */; };
+ 2ACF56EE14776A1E00991ED5 /* GpuShaderUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF569814776A1E00991ED5 /* GpuShaderUtils.h */; };
+ 2ACF56EF14776A1E00991ED5 /* GroupTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569914776A1E00991ED5 /* GroupTransform.cpp */; };
+ 2ACF56F014776A1E00991ED5 /* HashUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569A14776A1E00991ED5 /* HashUtils.cpp */; };
+ 2ACF56F114776A1E00991ED5 /* HashUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF569B14776A1E00991ED5 /* HashUtils.h */; };
+ 2ACF56F214776A1E00991ED5 /* ImageDesc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569C14776A1E00991ED5 /* ImageDesc.cpp */; };
+ 2ACF56F314776A1E00991ED5 /* ImagePacking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569D14776A1E00991ED5 /* ImagePacking.cpp */; };
+ 2ACF56F414776A1E00991ED5 /* ImagePacking.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF569E14776A1E00991ED5 /* ImagePacking.h */; };
+ 2ACF56F514776A1E00991ED5 /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF569F14776A1E00991ED5 /* Logging.cpp */; };
+ 2ACF56F614776A1E00991ED5 /* Logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56A014776A1E00991ED5 /* Logging.h */; };
+ 2ACF56F714776A1E00991ED5 /* LogOps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56A114776A1E00991ED5 /* LogOps.cpp */; };
+ 2ACF56F814776A1E00991ED5 /* LogOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56A214776A1E00991ED5 /* LogOps.h */; };
+ 2ACF56F914776A1E00991ED5 /* LogTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56A314776A1E00991ED5 /* LogTransform.cpp */; };
+ 2ACF56FA14776A1E00991ED5 /* Look.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56A414776A1E00991ED5 /* Look.cpp */; };
+ 2ACF56FB14776A1E00991ED5 /* LookTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56A514776A1E00991ED5 /* LookTransform.cpp */; };
+ 2ACF56FC14776A1E00991ED5 /* Lut1DOp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56A614776A1E00991ED5 /* Lut1DOp.cpp */; };
+ 2ACF56FD14776A1E00991ED5 /* Lut1DOp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56A714776A1E00991ED5 /* Lut1DOp.h */; };
+ 2ACF56FE14776A1E00991ED5 /* Lut3DOp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56A814776A1E00991ED5 /* Lut3DOp.cpp */; };
+ 2ACF56FF14776A1E00991ED5 /* Lut3DOp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56A914776A1E00991ED5 /* Lut3DOp.h */; };
+ 2ACF570014776A1E00991ED5 /* MathUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56AA14776A1E00991ED5 /* MathUtils.cpp */; };
+ 2ACF570114776A1E00991ED5 /* MathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56AB14776A1E00991ED5 /* MathUtils.h */; };
+ 2ACF570214776A1E00991ED5 /* MatrixOps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56AC14776A1E00991ED5 /* MatrixOps.cpp */; };
+ 2ACF570314776A1E00991ED5 /* MatrixOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56AD14776A1E00991ED5 /* MatrixOps.h */; };
+ 2ACF570414776A1E00991ED5 /* MatrixTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56AE14776A1E00991ED5 /* MatrixTransform.cpp */; };
+ 2ACF570514776A1E00991ED5 /* md5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56B014776A1E00991ED5 /* md5.cpp */; };
+ 2ACF570614776A1E00991ED5 /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56B114776A1E00991ED5 /* md5.h */; };
+ 2ACF570714776A1E00991ED5 /* Mutex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56B214776A1E00991ED5 /* Mutex.h */; };
+ 2ACF570814776A1E00991ED5 /* OCIOYaml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56B314776A1E00991ED5 /* OCIOYaml.cpp */; };
+ 2ACF570914776A1E00991ED5 /* OCIOYaml.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56B414776A1E00991ED5 /* OCIOYaml.h */; };
+ 2ACF570A14776A1E00991ED5 /* Op.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56B514776A1E00991ED5 /* Op.cpp */; };
+ 2ACF570B14776A1E00991ED5 /* Op.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56B614776A1E00991ED5 /* Op.h */; };
+ 2ACF570C14776A1E00991ED5 /* OpBuilders.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56B714776A1E00991ED5 /* OpBuilders.h */; };
+ 2ACF570D14776A1E00991ED5 /* ParseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56B814776A1E00991ED5 /* ParseUtils.cpp */; };
+ 2ACF570E14776A1E00991ED5 /* ParseUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56B914776A1E00991ED5 /* ParseUtils.h */; };
+ 2ACF570F14776A1E00991ED5 /* PathUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56BA14776A1E00991ED5 /* PathUtils.cpp */; };
+ 2ACF571014776A1E00991ED5 /* PathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56BB14776A1E00991ED5 /* PathUtils.h */; };
+ 2ACF571114776A1E00991ED5 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56BC14776A1E00991ED5 /* Platform.h */; };
+ 2ACF571214776A1E00991ED5 /* PrivateTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56BD14776A1E00991ED5 /* PrivateTypes.h */; };
+ 2ACF571314776A1E00991ED5 /* Processor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56BE14776A1E00991ED5 /* Processor.cpp */; };
+ 2ACF571414776A1E00991ED5 /* Processor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56BF14776A1E00991ED5 /* Processor.h */; };
+ 2ACF571514776A1E00991ED5 /* pystring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56C114776A1E00991ED5 /* pystring.cpp */; };
+ 2ACF571614776A1E00991ED5 /* pystring.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56C214776A1E00991ED5 /* pystring.h */; };
+ 2ACF571714776A1E00991ED5 /* ScanlineHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56C314776A1E00991ED5 /* ScanlineHelper.cpp */; };
+ 2ACF571814776A1E00991ED5 /* ScanlineHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56C414776A1E00991ED5 /* ScanlineHelper.h */; };
+ 2ACF571914776A1E00991ED5 /* SSE.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56C514776A1E00991ED5 /* SSE.h */; };
+ 2ACF571A14776A1E00991ED5 /* Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56C614776A1E00991ED5 /* Transform.cpp */; };
+ 2ACF571B14776A1E00991ED5 /* TruelightOp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56C714776A1E00991ED5 /* TruelightOp.cpp */; };
+ 2ACF571C14776A1E00991ED5 /* TruelightOp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56C814776A1E00991ED5 /* TruelightOp.h */; };
+ 2ACF571D14776A1E00991ED5 /* TruelightTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56C914776A1E00991ED5 /* TruelightTransform.cpp */; };
+ 2ACF571E14776A1E00991ED5 /* UnitTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF56CA14776A1E00991ED5 /* UnitTest.cpp */; };
+ 2ACF571F14776A1E00991ED5 /* UnitTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF56CB14776A1E00991ED5 /* UnitTest.h */; };
+ 2ACF573F14776B7000991ED5 /* OpenColorABI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF573E14776B7000991ED5 /* OpenColorABI.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 2A7CACB515536CD700F52C98 /* FileFormatIridasLook.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatIridasLook.cpp; sourceTree = "<group>"; };
+ 2A7CACB615536CD700F52C98 /* LookParse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LookParse.cpp; sourceTree = "<group>"; };
+ 2A7CACB715536CD700F52C98 /* LookParse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LookParse.h; sourceTree = "<group>"; };
+ 2A7CACB815536CD700F52C98 /* NoOps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NoOps.cpp; sourceTree = "<group>"; };
+ 2A7CACB915536CD700F52C98 /* NoOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoOps.h; sourceTree = "<group>"; };
+ 2A7CACBA15536CD700F52C98 /* OpOptimizers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpOptimizers.cpp; sourceTree = "<group>"; };
+ 2ACF567114776A0A00991ED5 /* libOpenColorIO.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libOpenColorIO.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2ACF567614776A1E00991ED5 /* AllocationOp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllocationOp.cpp; sourceTree = "<group>"; };
+ 2ACF567714776A1E00991ED5 /* AllocationOp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocationOp.h; sourceTree = "<group>"; };
+ 2ACF567814776A1E00991ED5 /* AllocationTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllocationTransform.cpp; sourceTree = "<group>"; };
+ 2ACF567914776A1E00991ED5 /* Baker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Baker.cpp; sourceTree = "<group>"; };
+ 2ACF567A14776A1E00991ED5 /* Caching.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Caching.cpp; sourceTree = "<group>"; };
+ 2ACF567B14776A1E00991ED5 /* CDLTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDLTransform.cpp; sourceTree = "<group>"; };
+ 2ACF567C14776A1E00991ED5 /* CDLTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDLTransform.h; sourceTree = "<group>"; };
+ 2ACF567D14776A1E00991ED5 /* ColorSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorSpace.cpp; sourceTree = "<group>"; };
+ 2ACF567E14776A1E00991ED5 /* ColorSpaceTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorSpaceTransform.cpp; sourceTree = "<group>"; };
+ 2ACF567F14776A1E00991ED5 /* Config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Config.cpp; sourceTree = "<group>"; };
+ 2ACF568014776A1E00991ED5 /* Context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Context.cpp; sourceTree = "<group>"; };
+ 2ACF568114776A1E00991ED5 /* DisplayTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayTransform.cpp; sourceTree = "<group>"; };
+ 2ACF568214776A1E00991ED5 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = "<group>"; };
+ 2ACF568314776A1E00991ED5 /* ExponentOps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExponentOps.cpp; sourceTree = "<group>"; };
+ 2ACF568414776A1E00991ED5 /* ExponentOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExponentOps.h; sourceTree = "<group>"; };
+ 2ACF568514776A1E00991ED5 /* ExponentTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExponentTransform.cpp; sourceTree = "<group>"; };
+ 2ACF568614776A1E00991ED5 /* FileFormat3DL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormat3DL.cpp; sourceTree = "<group>"; };
+ 2ACF568714776A1E00991ED5 /* FileFormatCC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatCC.cpp; sourceTree = "<group>"; };
+ 2ACF568814776A1E00991ED5 /* FileFormatCCC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatCCC.cpp; sourceTree = "<group>"; };
+ 2ACF568914776A1E00991ED5 /* FileFormatCSP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatCSP.cpp; sourceTree = "<group>"; };
+ 2ACF568A14776A1E00991ED5 /* FileFormatHDL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatHDL.cpp; sourceTree = "<group>"; };
+ 2ACF568B14776A1E00991ED5 /* FileFormatIridasCube.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatIridasCube.cpp; sourceTree = "<group>"; };
+ 2ACF568C14776A1E00991ED5 /* FileFormatIridasItx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatIridasItx.cpp; sourceTree = "<group>"; };
+ 2ACF568D14776A1E00991ED5 /* FileFormatPandora.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatPandora.cpp; sourceTree = "<group>"; };
+ 2ACF568E14776A1E00991ED5 /* FileFormatSpi1D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatSpi1D.cpp; sourceTree = "<group>"; };
+ 2ACF568F14776A1E00991ED5 /* FileFormatSpi3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatSpi3D.cpp; sourceTree = "<group>"; };
+ 2ACF569014776A1E00991ED5 /* FileFormatSpiMtx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatSpiMtx.cpp; sourceTree = "<group>"; };
+ 2ACF569114776A1E00991ED5 /* FileFormatTruelight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatTruelight.cpp; sourceTree = "<group>"; };
+ 2ACF569214776A1E00991ED5 /* FileFormatVF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileFormatVF.cpp; sourceTree = "<group>"; };
+ 2ACF569314776A1E00991ED5 /* FileTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileTransform.cpp; sourceTree = "<group>"; };
+ 2ACF569414776A1E00991ED5 /* FileTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileTransform.h; sourceTree = "<group>"; };
+ 2ACF569614776A1E00991ED5 /* GpuShaderDesc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GpuShaderDesc.cpp; sourceTree = "<group>"; };
+ 2ACF569714776A1E00991ED5 /* GpuShaderUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GpuShaderUtils.cpp; sourceTree = "<group>"; };
+ 2ACF569814776A1E00991ED5 /* GpuShaderUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GpuShaderUtils.h; sourceTree = "<group>"; };
+ 2ACF569914776A1E00991ED5 /* GroupTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GroupTransform.cpp; sourceTree = "<group>"; };
+ 2ACF569A14776A1E00991ED5 /* HashUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashUtils.cpp; sourceTree = "<group>"; };
+ 2ACF569B14776A1E00991ED5 /* HashUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashUtils.h; sourceTree = "<group>"; };
+ 2ACF569C14776A1E00991ED5 /* ImageDesc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDesc.cpp; sourceTree = "<group>"; };
+ 2ACF569D14776A1E00991ED5 /* ImagePacking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImagePacking.cpp; sourceTree = "<group>"; };
+ 2ACF569E14776A1E00991ED5 /* ImagePacking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImagePacking.h; sourceTree = "<group>"; };
+ 2ACF569F14776A1E00991ED5 /* Logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Logging.cpp; sourceTree = "<group>"; };
+ 2ACF56A014776A1E00991ED5 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
+ 2ACF56A114776A1E00991ED5 /* LogOps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogOps.cpp; sourceTree = "<group>"; };
+ 2ACF56A214776A1E00991ED5 /* LogOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogOps.h; sourceTree = "<group>"; };
+ 2ACF56A314776A1E00991ED5 /* LogTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogTransform.cpp; sourceTree = "<group>"; };
+ 2ACF56A414776A1E00991ED5 /* Look.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Look.cpp; sourceTree = "<group>"; };
+ 2ACF56A514776A1E00991ED5 /* LookTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LookTransform.cpp; sourceTree = "<group>"; };
+ 2ACF56A614776A1E00991ED5 /* Lut1DOp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lut1DOp.cpp; sourceTree = "<group>"; };
+ 2ACF56A714776A1E00991ED5 /* Lut1DOp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lut1DOp.h; sourceTree = "<group>"; };
+ 2ACF56A814776A1E00991ED5 /* Lut3DOp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lut3DOp.cpp; sourceTree = "<group>"; };
+ 2ACF56A914776A1E00991ED5 /* Lut3DOp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lut3DOp.h; sourceTree = "<group>"; };
+ 2ACF56AA14776A1E00991ED5 /* MathUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathUtils.cpp; sourceTree = "<group>"; };
+ 2ACF56AB14776A1E00991ED5 /* MathUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathUtils.h; sourceTree = "<group>"; };
+ 2ACF56AC14776A1E00991ED5 /* MatrixOps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MatrixOps.cpp; sourceTree = "<group>"; };
+ 2ACF56AD14776A1E00991ED5 /* MatrixOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatrixOps.h; sourceTree = "<group>"; };
+ 2ACF56AE14776A1E00991ED5 /* MatrixTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MatrixTransform.cpp; sourceTree = "<group>"; };
+ 2ACF56B014776A1E00991ED5 /* md5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = md5.cpp; sourceTree = "<group>"; };
+ 2ACF56B114776A1E00991ED5 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = "<group>"; };
+ 2ACF56B214776A1E00991ED5 /* Mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mutex.h; sourceTree = "<group>"; };
+ 2ACF56B314776A1E00991ED5 /* OCIOYaml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OCIOYaml.cpp; sourceTree = "<group>"; };
+ 2ACF56B414776A1E00991ED5 /* OCIOYaml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCIOYaml.h; sourceTree = "<group>"; };
+ 2ACF56B514776A1E00991ED5 /* Op.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Op.cpp; sourceTree = "<group>"; };
+ 2ACF56B614776A1E00991ED5 /* Op.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Op.h; sourceTree = "<group>"; };
+ 2ACF56B714776A1E00991ED5 /* OpBuilders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpBuilders.h; sourceTree = "<group>"; };
+ 2ACF56B814776A1E00991ED5 /* ParseUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParseUtils.cpp; sourceTree = "<group>"; };
+ 2ACF56B914776A1E00991ED5 /* ParseUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseUtils.h; sourceTree = "<group>"; };
+ 2ACF56BA14776A1E00991ED5 /* PathUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathUtils.cpp; sourceTree = "<group>"; };
+ 2ACF56BB14776A1E00991ED5 /* PathUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathUtils.h; sourceTree = "<group>"; };
+ 2ACF56BC14776A1E00991ED5 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Platform.h; sourceTree = "<group>"; };
+ 2ACF56BD14776A1E00991ED5 /* PrivateTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivateTypes.h; sourceTree = "<group>"; };
+ 2ACF56BE14776A1E00991ED5 /* Processor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Processor.cpp; sourceTree = "<group>"; };
+ 2ACF56BF14776A1E00991ED5 /* Processor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Processor.h; sourceTree = "<group>"; };
+ 2ACF56C114776A1E00991ED5 /* pystring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pystring.cpp; sourceTree = "<group>"; };
+ 2ACF56C214776A1E00991ED5 /* pystring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pystring.h; sourceTree = "<group>"; };
+ 2ACF56C314776A1E00991ED5 /* ScanlineHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScanlineHelper.cpp; sourceTree = "<group>"; };
+ 2ACF56C414776A1E00991ED5 /* ScanlineHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanlineHelper.h; sourceTree = "<group>"; };
+ 2ACF56C514776A1E00991ED5 /* SSE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSE.h; sourceTree = "<group>"; };
+ 2ACF56C614776A1E00991ED5 /* Transform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Transform.cpp; sourceTree = "<group>"; };
+ 2ACF56C714776A1E00991ED5 /* TruelightOp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TruelightOp.cpp; sourceTree = "<group>"; };
+ 2ACF56C814776A1E00991ED5 /* TruelightOp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TruelightOp.h; sourceTree = "<group>"; };
+ 2ACF56C914776A1E00991ED5 /* TruelightTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TruelightTransform.cpp; sourceTree = "<group>"; };
+ 2ACF56CA14776A1E00991ED5 /* UnitTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnitTest.cpp; sourceTree = "<group>"; };
+ 2ACF56CB14776A1E00991ED5 /* UnitTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitTest.h; sourceTree = "<group>"; };
+ 2ACF573E14776B7000991ED5 /* OpenColorABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenColorABI.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2ACF566F14776A0A00991ED5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF567114776A0A00991ED5 /* libOpenColorIO.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* OpenColorIO */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF573E14776B7000991ED5 /* OpenColorABI.h */,
+ 2ACF567514776A1E00991ED5 /* core */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = OpenColorIO;
+ sourceTree = "<group>";
+ };
+ 2ACF567514776A1E00991ED5 /* core */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF567614776A1E00991ED5 /* AllocationOp.cpp */,
+ 2ACF567714776A1E00991ED5 /* AllocationOp.h */,
+ 2ACF567814776A1E00991ED5 /* AllocationTransform.cpp */,
+ 2ACF567914776A1E00991ED5 /* Baker.cpp */,
+ 2ACF567A14776A1E00991ED5 /* Caching.cpp */,
+ 2ACF567B14776A1E00991ED5 /* CDLTransform.cpp */,
+ 2ACF567C14776A1E00991ED5 /* CDLTransform.h */,
+ 2ACF567D14776A1E00991ED5 /* ColorSpace.cpp */,
+ 2ACF567E14776A1E00991ED5 /* ColorSpaceTransform.cpp */,
+ 2ACF567F14776A1E00991ED5 /* Config.cpp */,
+ 2ACF568014776A1E00991ED5 /* Context.cpp */,
+ 2ACF568114776A1E00991ED5 /* DisplayTransform.cpp */,
+ 2ACF568214776A1E00991ED5 /* Exception.cpp */,
+ 2ACF568314776A1E00991ED5 /* ExponentOps.cpp */,
+ 2ACF568414776A1E00991ED5 /* ExponentOps.h */,
+ 2ACF568514776A1E00991ED5 /* ExponentTransform.cpp */,
+ 2ACF568614776A1E00991ED5 /* FileFormat3DL.cpp */,
+ 2ACF568714776A1E00991ED5 /* FileFormatCC.cpp */,
+ 2ACF568814776A1E00991ED5 /* FileFormatCCC.cpp */,
+ 2ACF568914776A1E00991ED5 /* FileFormatCSP.cpp */,
+ 2ACF568A14776A1E00991ED5 /* FileFormatHDL.cpp */,
+ 2ACF568B14776A1E00991ED5 /* FileFormatIridasCube.cpp */,
+ 2ACF568C14776A1E00991ED5 /* FileFormatIridasItx.cpp */,
+ 2A7CACB515536CD700F52C98 /* FileFormatIridasLook.cpp */,
+ 2ACF568D14776A1E00991ED5 /* FileFormatPandora.cpp */,
+ 2ACF568E14776A1E00991ED5 /* FileFormatSpi1D.cpp */,
+ 2ACF568F14776A1E00991ED5 /* FileFormatSpi3D.cpp */,
+ 2ACF569014776A1E00991ED5 /* FileFormatSpiMtx.cpp */,
+ 2ACF569114776A1E00991ED5 /* FileFormatTruelight.cpp */,
+ 2ACF569214776A1E00991ED5 /* FileFormatVF.cpp */,
+ 2ACF569314776A1E00991ED5 /* FileTransform.cpp */,
+ 2ACF569414776A1E00991ED5 /* FileTransform.h */,
+ 2ACF569614776A1E00991ED5 /* GpuShaderDesc.cpp */,
+ 2ACF569714776A1E00991ED5 /* GpuShaderUtils.cpp */,
+ 2ACF569814776A1E00991ED5 /* GpuShaderUtils.h */,
+ 2ACF569914776A1E00991ED5 /* GroupTransform.cpp */,
+ 2ACF569A14776A1E00991ED5 /* HashUtils.cpp */,
+ 2ACF569B14776A1E00991ED5 /* HashUtils.h */,
+ 2ACF569C14776A1E00991ED5 /* ImageDesc.cpp */,
+ 2ACF569D14776A1E00991ED5 /* ImagePacking.cpp */,
+ 2ACF569E14776A1E00991ED5 /* ImagePacking.h */,
+ 2ACF569F14776A1E00991ED5 /* Logging.cpp */,
+ 2ACF56A014776A1E00991ED5 /* Logging.h */,
+ 2ACF56A114776A1E00991ED5 /* LogOps.cpp */,
+ 2ACF56A214776A1E00991ED5 /* LogOps.h */,
+ 2A7CACB615536CD700F52C98 /* LookParse.cpp */,
+ 2A7CACB715536CD700F52C98 /* LookParse.h */,
+ 2ACF56A314776A1E00991ED5 /* LogTransform.cpp */,
+ 2ACF56A414776A1E00991ED5 /* Look.cpp */,
+ 2ACF56A514776A1E00991ED5 /* LookTransform.cpp */,
+ 2ACF56A614776A1E00991ED5 /* Lut1DOp.cpp */,
+ 2ACF56A714776A1E00991ED5 /* Lut1DOp.h */,
+ 2ACF56A814776A1E00991ED5 /* Lut3DOp.cpp */,
+ 2ACF56A914776A1E00991ED5 /* Lut3DOp.h */,
+ 2ACF56AA14776A1E00991ED5 /* MathUtils.cpp */,
+ 2ACF56AB14776A1E00991ED5 /* MathUtils.h */,
+ 2ACF56AC14776A1E00991ED5 /* MatrixOps.cpp */,
+ 2ACF56AD14776A1E00991ED5 /* MatrixOps.h */,
+ 2ACF56AE14776A1E00991ED5 /* MatrixTransform.cpp */,
+ 2ACF56AF14776A1E00991ED5 /* md5 */,
+ 2ACF56B214776A1E00991ED5 /* Mutex.h */,
+ 2A7CACB815536CD700F52C98 /* NoOps.cpp */,
+ 2A7CACB915536CD700F52C98 /* NoOps.h */,
+ 2ACF56B314776A1E00991ED5 /* OCIOYaml.cpp */,
+ 2ACF56B414776A1E00991ED5 /* OCIOYaml.h */,
+ 2ACF56B514776A1E00991ED5 /* Op.cpp */,
+ 2ACF56B614776A1E00991ED5 /* Op.h */,
+ 2ACF56B714776A1E00991ED5 /* OpBuilders.h */,
+ 2A7CACBA15536CD700F52C98 /* OpOptimizers.cpp */,
+ 2ACF56B814776A1E00991ED5 /* ParseUtils.cpp */,
+ 2ACF56B914776A1E00991ED5 /* ParseUtils.h */,
+ 2ACF56BA14776A1E00991ED5 /* PathUtils.cpp */,
+ 2ACF56BB14776A1E00991ED5 /* PathUtils.h */,
+ 2ACF56BC14776A1E00991ED5 /* Platform.h */,
+ 2ACF56BD14776A1E00991ED5 /* PrivateTypes.h */,
+ 2ACF56BE14776A1E00991ED5 /* Processor.cpp */,
+ 2ACF56BF14776A1E00991ED5 /* Processor.h */,
+ 2ACF56C014776A1E00991ED5 /* pystring */,
+ 2ACF56C314776A1E00991ED5 /* ScanlineHelper.cpp */,
+ 2ACF56C414776A1E00991ED5 /* ScanlineHelper.h */,
+ 2ACF56C514776A1E00991ED5 /* SSE.h */,
+ 2ACF56C614776A1E00991ED5 /* Transform.cpp */,
+ 2ACF56C714776A1E00991ED5 /* TruelightOp.cpp */,
+ 2ACF56C814776A1E00991ED5 /* TruelightOp.h */,
+ 2ACF56C914776A1E00991ED5 /* TruelightTransform.cpp */,
+ 2ACF56CA14776A1E00991ED5 /* UnitTest.cpp */,
+ 2ACF56CB14776A1E00991ED5 /* UnitTest.h */,
+ );
+ name = core;
+ path = ../../core;
+ sourceTree = SOURCE_ROOT;
+ };
+ 2ACF56AF14776A1E00991ED5 /* md5 */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF56B014776A1E00991ED5 /* md5.cpp */,
+ 2ACF56B114776A1E00991ED5 /* md5.h */,
+ );
+ path = md5;
+ sourceTree = "<group>";
+ };
+ 2ACF56C014776A1E00991ED5 /* pystring */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF56C114776A1E00991ED5 /* pystring.cpp */,
+ 2ACF56C214776A1E00991ED5 /* pystring.h */,
+ );
+ path = pystring;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 2ACF566D14776A0A00991ED5 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF56CD14776A1E00991ED5 /* AllocationOp.h in Headers */,
+ 2ACF56D214776A1E00991ED5 /* CDLTransform.h in Headers */,
+ 2ACF56DA14776A1E00991ED5 /* ExponentOps.h in Headers */,
+ 2ACF56EA14776A1E00991ED5 /* FileTransform.h in Headers */,
+ 2ACF56EE14776A1E00991ED5 /* GpuShaderUtils.h in Headers */,
+ 2ACF56F114776A1E00991ED5 /* HashUtils.h in Headers */,
+ 2ACF56F414776A1E00991ED5 /* ImagePacking.h in Headers */,
+ 2ACF56F614776A1E00991ED5 /* Logging.h in Headers */,
+ 2ACF56F814776A1E00991ED5 /* LogOps.h in Headers */,
+ 2ACF56FD14776A1E00991ED5 /* Lut1DOp.h in Headers */,
+ 2ACF56FF14776A1E00991ED5 /* Lut3DOp.h in Headers */,
+ 2ACF570114776A1E00991ED5 /* MathUtils.h in Headers */,
+ 2ACF570314776A1E00991ED5 /* MatrixOps.h in Headers */,
+ 2ACF570614776A1E00991ED5 /* md5.h in Headers */,
+ 2ACF570714776A1E00991ED5 /* Mutex.h in Headers */,
+ 2ACF570914776A1E00991ED5 /* OCIOYaml.h in Headers */,
+ 2ACF570B14776A1E00991ED5 /* Op.h in Headers */,
+ 2ACF570C14776A1E00991ED5 /* OpBuilders.h in Headers */,
+ 2ACF570E14776A1E00991ED5 /* ParseUtils.h in Headers */,
+ 2ACF571014776A1E00991ED5 /* PathUtils.h in Headers */,
+ 2ACF571114776A1E00991ED5 /* Platform.h in Headers */,
+ 2ACF571214776A1E00991ED5 /* PrivateTypes.h in Headers */,
+ 2ACF571414776A1E00991ED5 /* Processor.h in Headers */,
+ 2ACF571614776A1E00991ED5 /* pystring.h in Headers */,
+ 2ACF571814776A1E00991ED5 /* ScanlineHelper.h in Headers */,
+ 2ACF571914776A1E00991ED5 /* SSE.h in Headers */,
+ 2ACF571C14776A1E00991ED5 /* TruelightOp.h in Headers */,
+ 2ACF571F14776A1E00991ED5 /* UnitTest.h in Headers */,
+ 2ACF573F14776B7000991ED5 /* OpenColorABI.h in Headers */,
+ 2A7CACBD15536CD700F52C98 /* LookParse.h in Headers */,
+ 2A7CACBF15536CD700F52C98 /* NoOps.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 2ACF567014776A0A00991ED5 /* OpenColorIO */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2ACF567414776A1300991ED5 /* Build configuration list for PBXNativeTarget "OpenColorIO" */;
+ buildPhases = (
+ 2ACF566D14776A0A00991ED5 /* Headers */,
+ 2ACF566E14776A0A00991ED5 /* Sources */,
+ 2ACF566F14776A0A00991ED5 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = OpenColorIO;
+ productName = OpenColorIO;
+ productReference = 2ACF567114776A0A00991ED5 /* libOpenColorIO.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "OpenColorIO" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 0867D691FE84028FC02AAC07 /* OpenColorIO */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 2ACF567014776A0A00991ED5 /* OpenColorIO */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 2ACF566E14776A0A00991ED5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF56CC14776A1E00991ED5 /* AllocationOp.cpp in Sources */,
+ 2ACF56CE14776A1E00991ED5 /* AllocationTransform.cpp in Sources */,
+ 2ACF56CF14776A1E00991ED5 /* Baker.cpp in Sources */,
+ 2ACF56D014776A1E00991ED5 /* Caching.cpp in Sources */,
+ 2ACF56D114776A1E00991ED5 /* CDLTransform.cpp in Sources */,
+ 2ACF56D314776A1E00991ED5 /* ColorSpace.cpp in Sources */,
+ 2ACF56D414776A1E00991ED5 /* ColorSpaceTransform.cpp in Sources */,
+ 2ACF56D514776A1E00991ED5 /* Config.cpp in Sources */,
+ 2ACF56D614776A1E00991ED5 /* Context.cpp in Sources */,
+ 2ACF56D714776A1E00991ED5 /* DisplayTransform.cpp in Sources */,
+ 2ACF56D814776A1E00991ED5 /* Exception.cpp in Sources */,
+ 2ACF56D914776A1E00991ED5 /* ExponentOps.cpp in Sources */,
+ 2ACF56DB14776A1E00991ED5 /* ExponentTransform.cpp in Sources */,
+ 2ACF56DC14776A1E00991ED5 /* FileFormat3DL.cpp in Sources */,
+ 2ACF56DD14776A1E00991ED5 /* FileFormatCC.cpp in Sources */,
+ 2ACF56DE14776A1E00991ED5 /* FileFormatCCC.cpp in Sources */,
+ 2ACF56DF14776A1E00991ED5 /* FileFormatCSP.cpp in Sources */,
+ 2ACF56E014776A1E00991ED5 /* FileFormatHDL.cpp in Sources */,
+ 2ACF56E114776A1E00991ED5 /* FileFormatIridasCube.cpp in Sources */,
+ 2ACF56E214776A1E00991ED5 /* FileFormatIridasItx.cpp in Sources */,
+ 2ACF56E314776A1E00991ED5 /* FileFormatPandora.cpp in Sources */,
+ 2ACF56E414776A1E00991ED5 /* FileFormatSpi1D.cpp in Sources */,
+ 2ACF56E514776A1E00991ED5 /* FileFormatSpi3D.cpp in Sources */,
+ 2ACF56E614776A1E00991ED5 /* FileFormatSpiMtx.cpp in Sources */,
+ 2ACF56E714776A1E00991ED5 /* FileFormatTruelight.cpp in Sources */,
+ 2ACF56E814776A1E00991ED5 /* FileFormatVF.cpp in Sources */,
+ 2ACF56E914776A1E00991ED5 /* FileTransform.cpp in Sources */,
+ 2ACF56EC14776A1E00991ED5 /* GpuShaderDesc.cpp in Sources */,
+ 2ACF56ED14776A1E00991ED5 /* GpuShaderUtils.cpp in Sources */,
+ 2ACF56EF14776A1E00991ED5 /* GroupTransform.cpp in Sources */,
+ 2ACF56F014776A1E00991ED5 /* HashUtils.cpp in Sources */,
+ 2ACF56F214776A1E00991ED5 /* ImageDesc.cpp in Sources */,
+ 2ACF56F314776A1E00991ED5 /* ImagePacking.cpp in Sources */,
+ 2ACF56F514776A1E00991ED5 /* Logging.cpp in Sources */,
+ 2ACF56F714776A1E00991ED5 /* LogOps.cpp in Sources */,
+ 2ACF56F914776A1E00991ED5 /* LogTransform.cpp in Sources */,
+ 2ACF56FA14776A1E00991ED5 /* Look.cpp in Sources */,
+ 2ACF56FB14776A1E00991ED5 /* LookTransform.cpp in Sources */,
+ 2ACF56FC14776A1E00991ED5 /* Lut1DOp.cpp in Sources */,
+ 2ACF56FE14776A1E00991ED5 /* Lut3DOp.cpp in Sources */,
+ 2ACF570014776A1E00991ED5 /* MathUtils.cpp in Sources */,
+ 2ACF570214776A1E00991ED5 /* MatrixOps.cpp in Sources */,
+ 2ACF570414776A1E00991ED5 /* MatrixTransform.cpp in Sources */,
+ 2ACF570514776A1E00991ED5 /* md5.cpp in Sources */,
+ 2ACF570814776A1E00991ED5 /* OCIOYaml.cpp in Sources */,
+ 2ACF570A14776A1E00991ED5 /* Op.cpp in Sources */,
+ 2ACF570D14776A1E00991ED5 /* ParseUtils.cpp in Sources */,
+ 2ACF570F14776A1E00991ED5 /* PathUtils.cpp in Sources */,
+ 2ACF571314776A1E00991ED5 /* Processor.cpp in Sources */,
+ 2ACF571514776A1E00991ED5 /* pystring.cpp in Sources */,
+ 2ACF571714776A1E00991ED5 /* ScanlineHelper.cpp in Sources */,
+ 2ACF571A14776A1E00991ED5 /* Transform.cpp in Sources */,
+ 2ACF571B14776A1E00991ED5 /* TruelightOp.cpp in Sources */,
+ 2ACF571D14776A1E00991ED5 /* TruelightTransform.cpp in Sources */,
+ 2ACF571E14776A1E00991ED5 /* UnitTest.cpp in Sources */,
+ 2A7CACBB15536CD700F52C98 /* FileFormatIridasLook.cpp in Sources */,
+ 2A7CACBC15536CD700F52C98 /* LookParse.cpp in Sources */,
+ 2A7CACBE15536CD700F52C98 /* NoOps.cpp in Sources */,
+ 2A7CACC015536CD700F52C98 /* OpOptimizers.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB916508733D950010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = TIXML_USE_STL;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../../export,
+ ../../../ext/tinyxml,
+ "../../../ext/yaml-cpp/include",
+ );
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ 1DEB916608733D950010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ NDEBUG,
+ TIXML_USE_STL,
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../../export,
+ ../../../ext/tinyxml,
+ "../../../ext/yaml-cpp/include",
+ );
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+ 2ACF567214776A0A00991ED5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = OpenColorIO;
+ };
+ name = Debug;
+ };
+ 2ACF567314776A0A00991ED5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = OpenColorIO;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "OpenColorIO" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB916508733D950010E9CD /* Debug */,
+ 1DEB916608733D950010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2ACF567414776A1300991ED5 /* Build configuration list for PBXNativeTarget "OpenColorIO" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2ACF567214776A0A00991ED5 /* Debug */,
+ 2ACF567314776A0A00991ED5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/src/aftereffects/xcode/aftereffects/OpenColorIO_AE.xcodeproj/project.pbxproj b/src/aftereffects/xcode/aftereffects/OpenColorIO_AE.xcodeproj/project.pbxproj
new file mode 100755
index 0000000..84253ae
--- /dev/null
+++ b/src/aftereffects/xcode/aftereffects/OpenColorIO_AE.xcodeproj/project.pbxproj
@@ -0,0 +1,509 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 44;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2A180A6914801EB90000D11A /* OpenColorIO_AE_MonitorProfileChooser.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A180A6814801EB90000D11A /* OpenColorIO_AE_MonitorProfileChooser.xib */; };
+ 2A180A6D14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A180A6B14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.m */; };
+ 2A3BAA7110C0F40600AD32F2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A3BAA7010C0F40600AD32F2 /* Cocoa.framework */; };
+ 2A4A0AF61554679400D5AEB7 /* ocioicc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A4A0AF41554679400D5AEB7 /* ocioicc.cpp */; };
+ 2A60CADB1491A51C009D6DBF /* OpenColorIO_AE_GL_Cocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A60CADA1491A51C009D6DBF /* OpenColorIO_AE_GL_Cocoa.mm */; };
+ 2A60CB091491A9FF009D6DBF /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A60CB081491A9FF009D6DBF /* AGL.framework */; };
+ 2A60CB0B1491A9FF009D6DBF /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A60CB0A1491A9FF009D6DBF /* OpenGL.framework */; };
+ 2AF56B96147A431100F9968C /* OpenColorIO_AE_ArbData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56B8F147A431100F9968C /* OpenColorIO_AE_ArbData.cpp */; };
+ 2AF56B99147A431100F9968C /* OpenColorIO_AE_PiPL.r in Rez */ = {isa = PBXBuildFile; fileRef = 2AF56B92147A431100F9968C /* OpenColorIO_AE_PiPL.r */; };
+ 2AF56B9A147A431100F9968C /* OpenColorIO_AE_UI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56B93147A431100F9968C /* OpenColorIO_AE_UI.cpp */; };
+ 2AF56B9B147A431100F9968C /* OpenColorIO_AE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56B94147A431100F9968C /* OpenColorIO_AE.cpp */; };
+ 2AF56BA0147A458800F9968C /* AEGP_SuiteHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56B9D147A458800F9968C /* AEGP_SuiteHandler.cpp */; };
+ 2AF56BA1147A458800F9968C /* MissingSuiteError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56B9F147A458800F9968C /* MissingSuiteError.cpp */; };
+ 2AF56C24147A54A300F9968C /* OpenColorIO_AE_Dialogs_Cocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56B90147A431100F9968C /* OpenColorIO_AE_Dialogs_Cocoa.mm */; };
+ 2AF56D06147AB5C900F9968C /* DrawbotBot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF56D04147AB5C900F9968C /* DrawbotBot.cpp */; };
+ 2AF56EE8147AD11200F9968C /* libOpenColorIO.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AF56EE7147AD10E00F9968C /* libOpenColorIO.a */; };
+ 2AF57004147AE17200F9968C /* libtinyxml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AF56FFB147AE16A00F9968C /* libtinyxml.a */; };
+ 2AF57005147AE17400F9968C /* libyaml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AF57001147AE16A00F9968C /* libyaml.a */; };
+ 2AF57B93147C6FE000F9968C /* OpenColorIO_AE_Menu.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF57B92147C6FE000F9968C /* OpenColorIO_AE_Menu.m */; };
+ 2AF57D20147C994100F9968C /* OpenColorIO_AE_Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF57D1F147C994100F9968C /* OpenColorIO_AE_Context.cpp */; };
+ 2AF999CB147E1DD200FEB83B /* liblcms.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AF999C8147E1DCA00FEB83B /* liblcms.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 2AF56EE6147AD10E00F9968C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF56EE2147AD10E00F9968C /* OpenColorIO.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 2ACF567114776A0A00991ED5;
+ remoteInfo = OpenColorIO;
+ };
+ 2AF56FFA147AE16A00F9968C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF56FF0147AE16A00F9968C /* tinyxml.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 2ACF55441477682B00991ED5;
+ remoteInfo = tinyxml;
+ };
+ 2AF57000147AE16A00F9968C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF56FF3147AE16A00F9968C /* yaml.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 2ACF559C1477692300991ED5;
+ remoteInfo = yaml;
+ };
+ 2AF57012147AE18600F9968C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF56FF0147AE16A00F9968C /* tinyxml.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 2ACF55431477682B00991ED5;
+ remoteInfo = tinyxml;
+ };
+ 2AF57014147AE18600F9968C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF56FF3147AE16A00F9968C /* yaml.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 2ACF559B1477692300991ED5;
+ remoteInfo = yaml;
+ };
+ 2AF57016147AE18600F9968C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF56EE2147AD10E00F9968C /* OpenColorIO.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 2ACF567014776A0A00991ED5;
+ remoteInfo = OpenColorIO;
+ };
+ 2AF999C7147E1DCA00FEB83B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF999C0147E1DCA00FEB83B /* lcms.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 2ACF9E56147824F500991ED5;
+ remoteInfo = lcms;
+ };
+ 2AF999CC147E1DDB00FEB83B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2AF999C0147E1DCA00FEB83B /* lcms.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 2ACF9E55147824F500991ED5;
+ remoteInfo = lcms;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 2A180A6814801EB90000D11A /* OpenColorIO_AE_MonitorProfileChooser.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = OpenColorIO_AE_MonitorProfileChooser.xib; path = ../../mac/OpenColorIO_AE_MonitorProfileChooser.xib; sourceTree = "<group>"; };
+ 2A180A6B14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenColorIO_AE_MonitorProfileChooser_Controller.m; path = ../../mac/OpenColorIO_AE_MonitorProfileChooser_Controller.m; sourceTree = "<group>"; usesTabs = 0; };
+ 2A180A6C14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenColorIO_AE_MonitorProfileChooser_Controller.h; path = ../../mac/OpenColorIO_AE_MonitorProfileChooser_Controller.h; sourceTree = "<group>"; usesTabs = 0; };
+ 2A3BAA7010C0F40600AD32F2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ 2A4A0AF41554679400D5AEB7 /* ocioicc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ocioicc.cpp; path = ../../../apps/ociobakelut/ocioicc.cpp; sourceTree = SOURCE_ROOT; };
+ 2A4A0AF51554679400D5AEB7 /* ocioicc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ocioicc.h; path = ../../../apps/ociobakelut/ocioicc.h; sourceTree = SOURCE_ROOT; };
+ 2A60CAD91491A506009D6DBF /* OpenColorIO_AE_GL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenColorIO_AE_GL.h; path = ../../OpenColorIO_AE_GL.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2A60CADA1491A51C009D6DBF /* OpenColorIO_AE_GL_Cocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = OpenColorIO_AE_GL_Cocoa.mm; path = ../../mac/OpenColorIO_AE_GL_Cocoa.mm; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2A60CB081491A9FF009D6DBF /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = System/Library/Frameworks/AGL.framework; sourceTree = SDKROOT; };
+ 2A60CB0A1491A9FF009D6DBF /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
+ 2AF56B8F147A431100F9968C /* OpenColorIO_AE_ArbData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenColorIO_AE_ArbData.cpp; path = ../../OpenColorIO_AE_ArbData.cpp; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B90147A431100F9968C /* OpenColorIO_AE_Dialogs_Cocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = OpenColorIO_AE_Dialogs_Cocoa.mm; path = ../../mac/OpenColorIO_AE_Dialogs_Cocoa.mm; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B92147A431100F9968C /* OpenColorIO_AE_PiPL.r */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.rez; name = OpenColorIO_AE_PiPL.r; path = ../../OpenColorIO_AE_PiPL.r; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B93147A431100F9968C /* OpenColorIO_AE_UI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenColorIO_AE_UI.cpp; path = ../../OpenColorIO_AE_UI.cpp; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B94147A431100F9968C /* OpenColorIO_AE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenColorIO_AE.cpp; path = ../../OpenColorIO_AE.cpp; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B95147A431100F9968C /* OpenColorIO_AE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenColorIO_AE.h; path = ../../OpenColorIO_AE.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B9D147A458800F9968C /* AEGP_SuiteHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AEGP_SuiteHandler.cpp; path = "../../../../ext/Adobe After Effects CS5 SDK/Examples/Util/AEGP_SuiteHandler.cpp"; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B9E147A458800F9968C /* AEGP_SuiteHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AEGP_SuiteHandler.h; path = "../../../../ext/Adobe After Effects CS5 SDK/Examples/Util/AEGP_SuiteHandler.h"; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56B9F147A458800F9968C /* MissingSuiteError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MissingSuiteError.cpp; path = "../../../../ext/Adobe After Effects CS5 SDK/Examples/Util/MissingSuiteError.cpp"; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56D04147AB5C900F9968C /* DrawbotBot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DrawbotBot.cpp; path = ../../DrawbotBot.cpp; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56D05147AB5C900F9968C /* DrawbotBot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DrawbotBot.h; path = ../../DrawbotBot.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF56EE2147AD10E00F9968C /* OpenColorIO.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OpenColorIO.xcodeproj; path = ../OpenColorIO.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 2AF56FF0147AE16A00F9968C /* tinyxml.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = tinyxml.xcodeproj; path = ../ext/tinyxml.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 2AF56FF3147AE16A00F9968C /* yaml.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = yaml.xcodeproj; path = ../ext/yaml.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 2AF57171147B36F300F9968C /* OpenColorIO_AE_Dialogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenColorIO_AE_Dialogs.h; path = ../../OpenColorIO_AE_Dialogs.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF57B91147C6FE000F9968C /* OpenColorIO_AE_Menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenColorIO_AE_Menu.h; path = ../../mac/OpenColorIO_AE_Menu.h; sourceTree = "<group>"; usesTabs = 0; };
+ 2AF57B92147C6FE000F9968C /* OpenColorIO_AE_Menu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenColorIO_AE_Menu.m; path = ../../mac/OpenColorIO_AE_Menu.m; sourceTree = "<group>"; usesTabs = 0; };
+ 2AF57D1E147C994100F9968C /* OpenColorIO_AE_Context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenColorIO_AE_Context.h; path = ../../OpenColorIO_AE_Context.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF57D1F147C994100F9968C /* OpenColorIO_AE_Context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenColorIO_AE_Context.cpp; path = ../../OpenColorIO_AE_Context.cpp; sourceTree = SOURCE_ROOT; usesTabs = 0; };
+ 2AF999C0147E1DCA00FEB83B /* lcms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = lcms.xcodeproj; path = ../ext/lcms.xcodeproj; sourceTree = SOURCE_ROOT; };
+ C4E618CC095A3CE80012CA3F /* OpenColorIO.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenColorIO.plugin; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ C4E618CA095A3CE80012CA3F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2A3BAA7110C0F40600AD32F2 /* Cocoa.framework in Frameworks */,
+ 2AF56EE8147AD11200F9968C /* libOpenColorIO.a in Frameworks */,
+ 2AF57004147AE17200F9968C /* libtinyxml.a in Frameworks */,
+ 2AF57005147AE17400F9968C /* libyaml.a in Frameworks */,
+ 2AF999CB147E1DD200FEB83B /* liblcms.a in Frameworks */,
+ 2A60CB091491A9FF009D6DBF /* AGL.framework in Frameworks */,
+ 2A60CB0B1491A9FF009D6DBF /* OpenGL.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 2AF56EE3147AD10E00F9968C /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2AF56EE7147AD10E00F9968C /* libOpenColorIO.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 2AF56FF1147AE16A00F9968C /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2AF56FFB147AE16A00F9968C /* libtinyxml.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 2AF56FF4147AE16A00F9968C /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2AF57001147AE16A00F9968C /* libyaml.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 2AF999C1147E1DCA00FEB83B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2AF999C8147E1DCA00FEB83B /* liblcms.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C4E6187C095A3C800012CA3F = {
+ isa = PBXGroup;
+ children = (
+ 2AF56B95147A431100F9968C /* OpenColorIO_AE.h */,
+ 2AF56B94147A431100F9968C /* OpenColorIO_AE.cpp */,
+ 2AF57D1E147C994100F9968C /* OpenColorIO_AE_Context.h */,
+ 2AF57D1F147C994100F9968C /* OpenColorIO_AE_Context.cpp */,
+ 2AF56B8F147A431100F9968C /* OpenColorIO_AE_ArbData.cpp */,
+ 2AF56B93147A431100F9968C /* OpenColorIO_AE_UI.cpp */,
+ 2A60CAD91491A506009D6DBF /* OpenColorIO_AE_GL.h */,
+ 2A60CADA1491A51C009D6DBF /* OpenColorIO_AE_GL_Cocoa.mm */,
+ 2AF57171147B36F300F9968C /* OpenColorIO_AE_Dialogs.h */,
+ 2AF56B90147A431100F9968C /* OpenColorIO_AE_Dialogs_Cocoa.mm */,
+ 2AF57B91147C6FE000F9968C /* OpenColorIO_AE_Menu.h */,
+ 2AF57B92147C6FE000F9968C /* OpenColorIO_AE_Menu.m */,
+ 2AF56B92147A431100F9968C /* OpenColorIO_AE_PiPL.r */,
+ 2AF56B9E147A458800F9968C /* AEGP_SuiteHandler.h */,
+ 2AF56B9D147A458800F9968C /* AEGP_SuiteHandler.cpp */,
+ 2AF56B9F147A458800F9968C /* MissingSuiteError.cpp */,
+ 2AF56D05147AB5C900F9968C /* DrawbotBot.h */,
+ 2AF56D04147AB5C900F9968C /* DrawbotBot.cpp */,
+ 2A4A0AF51554679400D5AEB7 /* ocioicc.h */,
+ 2A4A0AF41554679400D5AEB7 /* ocioicc.cpp */,
+ 2A180A6814801EB90000D11A /* OpenColorIO_AE_MonitorProfileChooser.xib */,
+ 2A180A6C14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.h */,
+ 2A180A6B14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.m */,
+ 2AF56EE2147AD10E00F9968C /* OpenColorIO.xcodeproj */,
+ 2AF56FF0147AE16A00F9968C /* tinyxml.xcodeproj */,
+ 2AF56FF3147AE16A00F9968C /* yaml.xcodeproj */,
+ 2AF999C0147E1DCA00FEB83B /* lcms.xcodeproj */,
+ C4E6188C095A3C800012CA3F /* Products */,
+ 2A3BAA7010C0F40600AD32F2 /* Cocoa.framework */,
+ 2A60CB081491A9FF009D6DBF /* AGL.framework */,
+ 2A60CB0A1491A9FF009D6DBF /* OpenGL.framework */,
+ );
+ comments = "SDK Backwards is some pretty rudimentary audio processing, but the flags and params are handled in an appropriate manner.";
+ sourceTree = "<group>";
+ };
+ C4E6188C095A3C800012CA3F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ C4E618CC095A3CE80012CA3F /* OpenColorIO.plugin */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ C4E618CB095A3CE80012CA3F /* OpenColorIO */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = C4E618CE095A3CE90012CA3F /* Build configuration list for PBXNativeTarget "OpenColorIO" */;
+ buildPhases = (
+ C4E618C8095A3CE80012CA3F /* Resources */,
+ C4E618C9095A3CE80012CA3F /* Sources */,
+ C4E618CA095A3CE80012CA3F /* Frameworks */,
+ C4E618EA095A3E040012CA3F /* Rez */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 2AF57013147AE18600F9968C /* PBXTargetDependency */,
+ 2AF57015147AE18600F9968C /* PBXTargetDependency */,
+ 2AF57017147AE18600F9968C /* PBXTargetDependency */,
+ 2AF999CD147E1DDB00FEB83B /* PBXTargetDependency */,
+ );
+ name = OpenColorIO;
+ productName = SDK_Backwards.plugin;
+ productReference = C4E618CC095A3CE80012CA3F /* OpenColorIO.plugin */;
+ productType = "com.apple.product-type.bundle";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ C4E6187E095A3C800012CA3F /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = C4E6187F095A3C800012CA3F /* Build configuration list for PBXProject "OpenColorIO_AE" */;
+ compatibilityVersion = "Xcode 3.0";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = C4E6187C095A3C800012CA3F;
+ productRefGroup = C4E6188C095A3C800012CA3F /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 2AF999C1147E1DCA00FEB83B /* Products */;
+ ProjectRef = 2AF999C0147E1DCA00FEB83B /* lcms.xcodeproj */;
+ },
+ {
+ ProductGroup = 2AF56EE3147AD10E00F9968C /* Products */;
+ ProjectRef = 2AF56EE2147AD10E00F9968C /* OpenColorIO.xcodeproj */;
+ },
+ {
+ ProductGroup = 2AF56FF1147AE16A00F9968C /* Products */;
+ ProjectRef = 2AF56FF0147AE16A00F9968C /* tinyxml.xcodeproj */;
+ },
+ {
+ ProductGroup = 2AF56FF4147AE16A00F9968C /* Products */;
+ ProjectRef = 2AF56FF3147AE16A00F9968C /* yaml.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ C4E618CB095A3CE80012CA3F /* OpenColorIO */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 2AF56EE7147AD10E00F9968C /* libOpenColorIO.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libOpenColorIO.a;
+ remoteRef = 2AF56EE6147AD10E00F9968C /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 2AF56FFB147AE16A00F9968C /* libtinyxml.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libtinyxml.a;
+ remoteRef = 2AF56FFA147AE16A00F9968C /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 2AF57001147AE16A00F9968C /* libyaml.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libyaml.a;
+ remoteRef = 2AF57000147AE16A00F9968C /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 2AF999C8147E1DCA00FEB83B /* liblcms.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = liblcms.a;
+ remoteRef = 2AF999C7147E1DCA00FEB83B /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ C4E618C8095A3CE80012CA3F /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2A180A6914801EB90000D11A /* OpenColorIO_AE_MonitorProfileChooser.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+ C4E618EA095A3E040012CA3F /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2AF56B99147A431100F9968C /* OpenColorIO_AE_PiPL.r in Rez */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ C4E618C9095A3CE80012CA3F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2AF56B96147A431100F9968C /* OpenColorIO_AE_ArbData.cpp in Sources */,
+ 2AF56B9A147A431100F9968C /* OpenColorIO_AE_UI.cpp in Sources */,
+ 2AF56B9B147A431100F9968C /* OpenColorIO_AE.cpp in Sources */,
+ 2AF56BA0147A458800F9968C /* AEGP_SuiteHandler.cpp in Sources */,
+ 2AF56BA1147A458800F9968C /* MissingSuiteError.cpp in Sources */,
+ 2AF56C24147A54A300F9968C /* OpenColorIO_AE_Dialogs_Cocoa.mm in Sources */,
+ 2AF56D06147AB5C900F9968C /* DrawbotBot.cpp in Sources */,
+ 2AF57B93147C6FE000F9968C /* OpenColorIO_AE_Menu.m in Sources */,
+ 2AF57D20147C994100F9968C /* OpenColorIO_AE_Context.cpp in Sources */,
+ 2A180A6D14801FFA0000D11A /* OpenColorIO_AE_MonitorProfileChooser_Controller.m in Sources */,
+ 2A60CADB1491A51C009D6DBF /* OpenColorIO_AE_GL_Cocoa.mm in Sources */,
+ 2A4A0AF61554679400D5AEB7 /* ocioicc.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 2AF57013147AE18600F9968C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = tinyxml;
+ targetProxy = 2AF57012147AE18600F9968C /* PBXContainerItemProxy */;
+ };
+ 2AF57015147AE18600F9968C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = yaml;
+ targetProxy = 2AF57014147AE18600F9968C /* PBXContainerItemProxy */;
+ };
+ 2AF57017147AE18600F9968C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = OpenColorIO;
+ targetProxy = 2AF57016147AE18600F9968C /* PBXContainerItemProxy */;
+ };
+ 2AF999CD147E1DDB00FEB83B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = lcms;
+ targetProxy = 2AF999CC147E1DDB00FEB83B /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 2A1BAC2310C3C82A00244D12 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ AE_SDK = "\"../../../../ext/Adobe After Effects CS5 SDK\"";
+ "AE_SDK[arch=i386]" = "\"../../../../ext/Adobe After Effects CS3 SDK\"";
+ "AE_SDK[arch=ppc]" = "\"../../../../ext/Adobe After Effects CS3 SDK\"";
+ ARCHS = x86_64;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = "";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ HEADER_SEARCH_PATHS = (
+ ../,
+ "$(AE_SDK)/Examples/Headers",
+ "$(AE_SDK)/Examples/Util",
+ "$(AE_SDK)/Examples/Headers/SP",
+ "$(AE_SDK)/Examples/Resources",
+ ../../../../export,
+ ../../../../src/core,
+ ../../../../ext/tinyxml,
+ "../../../../ext/yaml-cpp/include",
+ "../../../../ext/lcms2-2.1/include",
+ );
+ REZ_PREPROCESSOR_DEFINITIONS = __MACH__;
+ REZ_SEARCH_PATHS = "$(SDK_PATH)/Developer/Headers/FlatCarbon";
+ SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
+ };
+ name = Release;
+ };
+ 2A1BAC2410C3C82A00244D12 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SDKROOT)/System/Library/Frameworks/Carbon.framework/Headers/Carbon.h";
+ GENERATE_PKGINFO_FILE = YES;
+ INFOPLIST_FILE = "../../mac/OpenColorIO_AE.plugin-Info.plist";
+ INSTALL_PATH = "$(HOME)/Library/Bundles";
+ LINK_WITH_STANDARD_LIBRARIES = YES;
+ PREBINDING = NO;
+ PRODUCT_NAME = OpenColorIO;
+ WRAPPER_EXTENSION = plugin;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ C4E61880095A3C800012CA3F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ AE_SDK = "\"../../../../ext/Adobe After Effects CS5 SDK\"";
+ "AE_SDK[arch=i386]" = "\"../../../../ext/Adobe After Effects CS3 SDK\"";
+ "AE_SDK[arch=ppc]" = "\"../../../../ext/Adobe After Effects CS3 SDK\"";
+ ARCHS = x86_64;
+ COPY_PHASE_STRIP = NO;
+ GCC_MODEL_TUNING = "";
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ HEADER_SEARCH_PATHS = (
+ ../,
+ "$(AE_SDK)/Examples/Headers",
+ "$(AE_SDK)/Examples/Util",
+ "$(AE_SDK)/Examples/Headers/SP",
+ "$(AE_SDK)/Examples/Resources",
+ ../../../../export,
+ ../../../../src/core,
+ ../../../../ext/tinyxml,
+ "../../../../ext/yaml-cpp/include",
+ "../../../../ext/lcms2-2.1/include",
+ );
+ REZ_PREPROCESSOR_DEFINITIONS = __MACH__;
+ REZ_SEARCH_PATHS = "$(SDK_PATH)/Developer/Headers/FlatCarbon";
+ SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ C4E618CF095A3CE90012CA3F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SDKROOT)/System/Library/Frameworks/Carbon.framework/Headers/Carbon.h";
+ GENERATE_PKGINFO_FILE = YES;
+ INFOPLIST_FILE = "../../mac/OpenColorIO_AE.plugin-Info.plist";
+ INSTALL_PATH = "$(HOME)/Library/Bundles";
+ LINK_WITH_STANDARD_LIBRARIES = YES;
+ PREBINDING = NO;
+ PRODUCT_NAME = OpenColorIO;
+ WRAPPER_EXTENSION = plugin;
+ ZERO_LINK = NO;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ C4E6187F095A3C800012CA3F /* Build configuration list for PBXProject "OpenColorIO_AE" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C4E61880095A3C800012CA3F /* Debug */,
+ 2A1BAC2310C3C82A00244D12 /* Release */,
+ );
+ defaultConfigurationIsVisible = 1;
+ defaultConfigurationName = Debug;
+ };
+ C4E618CE095A3CE90012CA3F /* Build configuration list for PBXNativeTarget "OpenColorIO" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C4E618CF095A3CE90012CA3F /* Debug */,
+ 2A1BAC2410C3C82A00244D12 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = C4E6187E095A3C800012CA3F /* Project object */;
+}
diff --git a/src/aftereffects/xcode/ext/lcms.xcodeproj/project.pbxproj b/src/aftereffects/xcode/ext/lcms.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..42e7bda
--- /dev/null
+++ b/src/aftereffects/xcode/ext/lcms.xcodeproj/project.pbxproj
@@ -0,0 +1,343 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2ACF9F2C1478251500991ED5 /* lcms2.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF9E6D1478251500991ED5 /* lcms2.h */; };
+ 2ACF9F2D1478251500991ED5 /* lcms2_plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF9E6E1478251500991ED5 /* lcms2_plugin.h */; };
+ 2ACF9F311478251500991ED5 /* cmscam02.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ECE1478251500991ED5 /* cmscam02.c */; };
+ 2ACF9F321478251500991ED5 /* cmscgats.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ECF1478251500991ED5 /* cmscgats.c */; };
+ 2ACF9F331478251500991ED5 /* cmscnvrt.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED01478251500991ED5 /* cmscnvrt.c */; };
+ 2ACF9F341478251500991ED5 /* cmserr.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED11478251500991ED5 /* cmserr.c */; };
+ 2ACF9F351478251500991ED5 /* cmsgamma.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED21478251500991ED5 /* cmsgamma.c */; };
+ 2ACF9F361478251500991ED5 /* cmsgmt.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED31478251500991ED5 /* cmsgmt.c */; };
+ 2ACF9F371478251500991ED5 /* cmsintrp.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED41478251500991ED5 /* cmsintrp.c */; };
+ 2ACF9F381478251500991ED5 /* cmsio0.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED51478251500991ED5 /* cmsio0.c */; };
+ 2ACF9F391478251500991ED5 /* cmsio1.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED61478251500991ED5 /* cmsio1.c */; };
+ 2ACF9F3A1478251500991ED5 /* cmslut.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED71478251500991ED5 /* cmslut.c */; };
+ 2ACF9F3B1478251500991ED5 /* cmsmd5.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED81478251500991ED5 /* cmsmd5.c */; };
+ 2ACF9F3C1478251500991ED5 /* cmsmtrx.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9ED91478251500991ED5 /* cmsmtrx.c */; };
+ 2ACF9F3D1478251500991ED5 /* cmsnamed.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EDA1478251500991ED5 /* cmsnamed.c */; };
+ 2ACF9F3E1478251500991ED5 /* cmsopt.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EDB1478251500991ED5 /* cmsopt.c */; };
+ 2ACF9F3F1478251500991ED5 /* cmspack.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EDC1478251500991ED5 /* cmspack.c */; };
+ 2ACF9F401478251500991ED5 /* cmspcs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EDD1478251500991ED5 /* cmspcs.c */; };
+ 2ACF9F411478251500991ED5 /* cmsplugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EDE1478251500991ED5 /* cmsplugin.c */; };
+ 2ACF9F421478251500991ED5 /* cmsps2.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EDF1478251500991ED5 /* cmsps2.c */; };
+ 2ACF9F431478251500991ED5 /* cmssamp.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EE01478251500991ED5 /* cmssamp.c */; };
+ 2ACF9F441478251500991ED5 /* cmssm.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EE11478251500991ED5 /* cmssm.c */; };
+ 2ACF9F451478251500991ED5 /* cmstypes.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EE21478251500991ED5 /* cmstypes.c */; };
+ 2ACF9F461478251500991ED5 /* cmsvirt.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EE31478251500991ED5 /* cmsvirt.c */; };
+ 2ACF9F471478251500991ED5 /* cmswtpnt.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EE41478251500991ED5 /* cmswtpnt.c */; };
+ 2ACF9F481478251500991ED5 /* cmsxform.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF9EE51478251500991ED5 /* cmsxform.c */; };
+ 2ACF9F491478251500991ED5 /* lcms2_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF9EE71478251500991ED5 /* lcms2_internal.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 2ACF9E56147824F500991ED5 /* liblcms.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblcms.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2ACF9E6D1478251500991ED5 /* lcms2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lcms2.h; sourceTree = "<group>"; };
+ 2ACF9E6E1478251500991ED5 /* lcms2_plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lcms2_plugin.h; sourceTree = "<group>"; };
+ 2ACF9ECE1478251500991ED5 /* cmscam02.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmscam02.c; sourceTree = "<group>"; };
+ 2ACF9ECF1478251500991ED5 /* cmscgats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmscgats.c; sourceTree = "<group>"; };
+ 2ACF9ED01478251500991ED5 /* cmscnvrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmscnvrt.c; sourceTree = "<group>"; };
+ 2ACF9ED11478251500991ED5 /* cmserr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmserr.c; sourceTree = "<group>"; };
+ 2ACF9ED21478251500991ED5 /* cmsgamma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsgamma.c; sourceTree = "<group>"; };
+ 2ACF9ED31478251500991ED5 /* cmsgmt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsgmt.c; sourceTree = "<group>"; };
+ 2ACF9ED41478251500991ED5 /* cmsintrp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsintrp.c; sourceTree = "<group>"; };
+ 2ACF9ED51478251500991ED5 /* cmsio0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsio0.c; sourceTree = "<group>"; };
+ 2ACF9ED61478251500991ED5 /* cmsio1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsio1.c; sourceTree = "<group>"; };
+ 2ACF9ED71478251500991ED5 /* cmslut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmslut.c; sourceTree = "<group>"; };
+ 2ACF9ED81478251500991ED5 /* cmsmd5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsmd5.c; sourceTree = "<group>"; };
+ 2ACF9ED91478251500991ED5 /* cmsmtrx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsmtrx.c; sourceTree = "<group>"; };
+ 2ACF9EDA1478251500991ED5 /* cmsnamed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsnamed.c; sourceTree = "<group>"; };
+ 2ACF9EDB1478251500991ED5 /* cmsopt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsopt.c; sourceTree = "<group>"; };
+ 2ACF9EDC1478251500991ED5 /* cmspack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmspack.c; sourceTree = "<group>"; };
+ 2ACF9EDD1478251500991ED5 /* cmspcs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmspcs.c; sourceTree = "<group>"; };
+ 2ACF9EDE1478251500991ED5 /* cmsplugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsplugin.c; sourceTree = "<group>"; };
+ 2ACF9EDF1478251500991ED5 /* cmsps2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsps2.c; sourceTree = "<group>"; };
+ 2ACF9EE01478251500991ED5 /* cmssamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmssamp.c; sourceTree = "<group>"; };
+ 2ACF9EE11478251500991ED5 /* cmssm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmssm.c; sourceTree = "<group>"; };
+ 2ACF9EE21478251500991ED5 /* cmstypes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmstypes.c; sourceTree = "<group>"; };
+ 2ACF9EE31478251500991ED5 /* cmsvirt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsvirt.c; sourceTree = "<group>"; };
+ 2ACF9EE41478251500991ED5 /* cmswtpnt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmswtpnt.c; sourceTree = "<group>"; };
+ 2ACF9EE51478251500991ED5 /* cmsxform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmsxform.c; sourceTree = "<group>"; };
+ 2ACF9EE71478251500991ED5 /* lcms2_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lcms2_internal.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2ACF9E54147824F500991ED5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF9E56147824F500991ED5 /* liblcms.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* lcms */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF9E5A1478251500991ED5 /* lcms2-2.1 */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = lcms;
+ sourceTree = "<group>";
+ };
+ 2ACF9E5A1478251500991ED5 /* lcms2-2.1 */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF9E6C1478251500991ED5 /* include */,
+ 2ACF9ECD1478251500991ED5 /* src */,
+ );
+ name = "lcms2-2.1";
+ path = "../../../../ext/lcms2-2.1";
+ sourceTree = SOURCE_ROOT;
+ };
+ 2ACF9E6C1478251500991ED5 /* include */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF9E6D1478251500991ED5 /* lcms2.h */,
+ 2ACF9E6E1478251500991ED5 /* lcms2_plugin.h */,
+ );
+ path = include;
+ sourceTree = "<group>";
+ };
+ 2ACF9ECD1478251500991ED5 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF9ECE1478251500991ED5 /* cmscam02.c */,
+ 2ACF9ECF1478251500991ED5 /* cmscgats.c */,
+ 2ACF9ED01478251500991ED5 /* cmscnvrt.c */,
+ 2ACF9ED11478251500991ED5 /* cmserr.c */,
+ 2ACF9ED21478251500991ED5 /* cmsgamma.c */,
+ 2ACF9ED31478251500991ED5 /* cmsgmt.c */,
+ 2ACF9ED41478251500991ED5 /* cmsintrp.c */,
+ 2ACF9ED51478251500991ED5 /* cmsio0.c */,
+ 2ACF9ED61478251500991ED5 /* cmsio1.c */,
+ 2ACF9ED71478251500991ED5 /* cmslut.c */,
+ 2ACF9ED81478251500991ED5 /* cmsmd5.c */,
+ 2ACF9ED91478251500991ED5 /* cmsmtrx.c */,
+ 2ACF9EDA1478251500991ED5 /* cmsnamed.c */,
+ 2ACF9EDB1478251500991ED5 /* cmsopt.c */,
+ 2ACF9EDC1478251500991ED5 /* cmspack.c */,
+ 2ACF9EDD1478251500991ED5 /* cmspcs.c */,
+ 2ACF9EDE1478251500991ED5 /* cmsplugin.c */,
+ 2ACF9EDF1478251500991ED5 /* cmsps2.c */,
+ 2ACF9EE01478251500991ED5 /* cmssamp.c */,
+ 2ACF9EE11478251500991ED5 /* cmssm.c */,
+ 2ACF9EE21478251500991ED5 /* cmstypes.c */,
+ 2ACF9EE31478251500991ED5 /* cmsvirt.c */,
+ 2ACF9EE41478251500991ED5 /* cmswtpnt.c */,
+ 2ACF9EE51478251500991ED5 /* cmsxform.c */,
+ 2ACF9EE71478251500991ED5 /* lcms2_internal.h */,
+ );
+ path = src;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 2ACF9E52147824F500991ED5 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF9F2C1478251500991ED5 /* lcms2.h in Headers */,
+ 2ACF9F2D1478251500991ED5 /* lcms2_plugin.h in Headers */,
+ 2ACF9F491478251500991ED5 /* lcms2_internal.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 2ACF9E55147824F500991ED5 /* lcms */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2ACF9E59147824FB00991ED5 /* Build configuration list for PBXNativeTarget "lcms" */;
+ buildPhases = (
+ 2AF569A814799AF900F9968C /* Unpack lcms2 */,
+ 2ACF9E52147824F500991ED5 /* Headers */,
+ 2ACF9E53147824F500991ED5 /* Sources */,
+ 2ACF9E54147824F500991ED5 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = lcms;
+ productName = lcms;
+ productReference = 2ACF9E56147824F500991ED5 /* liblcms.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "lcms" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 0867D691FE84028FC02AAC07 /* lcms */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 2ACF9E55147824F500991ED5 /* lcms */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 2AF569A814799AF900F9968C /* Unpack lcms2 */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/../../../../ext/lcms2-2.1.tar.gz",
+ );
+ name = "Unpack lcms2";
+ outputPaths = (
+ "$(SRCROOT)/../../../../ext/lcms2-2.1",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "cd $SRCROOT/../../../../ext\n\nif [ ! -d lcms2-2.1 ]\nthen\n\ttar -xzf lcms2-2.1.tar.gz\nfi\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 2ACF9E53147824F500991ED5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF9F311478251500991ED5 /* cmscam02.c in Sources */,
+ 2ACF9F321478251500991ED5 /* cmscgats.c in Sources */,
+ 2ACF9F331478251500991ED5 /* cmscnvrt.c in Sources */,
+ 2ACF9F341478251500991ED5 /* cmserr.c in Sources */,
+ 2ACF9F351478251500991ED5 /* cmsgamma.c in Sources */,
+ 2ACF9F361478251500991ED5 /* cmsgmt.c in Sources */,
+ 2ACF9F371478251500991ED5 /* cmsintrp.c in Sources */,
+ 2ACF9F381478251500991ED5 /* cmsio0.c in Sources */,
+ 2ACF9F391478251500991ED5 /* cmsio1.c in Sources */,
+ 2ACF9F3A1478251500991ED5 /* cmslut.c in Sources */,
+ 2ACF9F3B1478251500991ED5 /* cmsmd5.c in Sources */,
+ 2ACF9F3C1478251500991ED5 /* cmsmtrx.c in Sources */,
+ 2ACF9F3D1478251500991ED5 /* cmsnamed.c in Sources */,
+ 2ACF9F3E1478251500991ED5 /* cmsopt.c in Sources */,
+ 2ACF9F3F1478251500991ED5 /* cmspack.c in Sources */,
+ 2ACF9F401478251500991ED5 /* cmspcs.c in Sources */,
+ 2ACF9F411478251500991ED5 /* cmsplugin.c in Sources */,
+ 2ACF9F421478251500991ED5 /* cmsps2.c in Sources */,
+ 2ACF9F431478251500991ED5 /* cmssamp.c in Sources */,
+ 2ACF9F441478251500991ED5 /* cmssm.c in Sources */,
+ 2ACF9F451478251500991ED5 /* cmstypes.c in Sources */,
+ 2ACF9F461478251500991ED5 /* cmsvirt.c in Sources */,
+ 2ACF9F471478251500991ED5 /* cmswtpnt.c in Sources */,
+ 2ACF9F481478251500991ED5 /* cmsxform.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB916508733D950010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ 1DEB916608733D950010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+ 2ACF9E57147824F600991ED5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = lcms;
+ };
+ name = Debug;
+ };
+ 2ACF9E58147824F600991ED5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = lcms;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "lcms" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB916508733D950010E9CD /* Debug */,
+ 1DEB916608733D950010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2ACF9E59147824FB00991ED5 /* Build configuration list for PBXNativeTarget "lcms" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2ACF9E57147824F600991ED5 /* Debug */,
+ 2ACF9E58147824F600991ED5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/src/aftereffects/xcode/ext/tinyxml.xcodeproj/project.pbxproj b/src/aftereffects/xcode/ext/tinyxml.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..2f07451
--- /dev/null
+++ b/src/aftereffects/xcode/ext/tinyxml.xcodeproj/project.pbxproj
@@ -0,0 +1,248 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2ACF55501477685000991ED5 /* tinystr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF554A1477685000991ED5 /* tinystr.cpp */; };
+ 2ACF55511477685000991ED5 /* tinystr.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF554B1477685000991ED5 /* tinystr.h */; };
+ 2ACF55521477685000991ED5 /* tinyxml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF554C1477685000991ED5 /* tinyxml.cpp */; };
+ 2ACF55531477685000991ED5 /* tinyxml.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF554D1477685000991ED5 /* tinyxml.h */; };
+ 2ACF55541477685000991ED5 /* tinyxmlerror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF554E1477685000991ED5 /* tinyxmlerror.cpp */; };
+ 2ACF55551477685000991ED5 /* tinyxmlparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF554F1477685000991ED5 /* tinyxmlparser.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 2ACF55441477682B00991ED5 /* libtinyxml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtinyxml.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2ACF554A1477685000991ED5 /* tinystr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinystr.cpp; sourceTree = "<group>"; };
+ 2ACF554B1477685000991ED5 /* tinystr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinystr.h; sourceTree = "<group>"; };
+ 2ACF554C1477685000991ED5 /* tinyxml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxml.cpp; sourceTree = "<group>"; };
+ 2ACF554D1477685000991ED5 /* tinyxml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyxml.h; sourceTree = "<group>"; };
+ 2ACF554E1477685000991ED5 /* tinyxmlerror.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxmlerror.cpp; sourceTree = "<group>"; };
+ 2ACF554F1477685000991ED5 /* tinyxmlparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxmlparser.cpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2ACF55421477682B00991ED5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55441477682B00991ED5 /* libtinyxml.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* tinyxml */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55481477685000991ED5 /* tinyxml */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = tinyxml;
+ sourceTree = "<group>";
+ };
+ 2ACF55481477685000991ED5 /* tinyxml */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF554A1477685000991ED5 /* tinystr.cpp */,
+ 2ACF554B1477685000991ED5 /* tinystr.h */,
+ 2ACF554C1477685000991ED5 /* tinyxml.cpp */,
+ 2ACF554D1477685000991ED5 /* tinyxml.h */,
+ 2ACF554E1477685000991ED5 /* tinyxmlerror.cpp */,
+ 2ACF554F1477685000991ED5 /* tinyxmlparser.cpp */,
+ );
+ name = tinyxml;
+ path = ../../../../ext/tinyxml;
+ sourceTree = SOURCE_ROOT;
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 2ACF55401477682B00991ED5 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF55511477685000991ED5 /* tinystr.h in Headers */,
+ 2ACF55531477685000991ED5 /* tinyxml.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 2ACF55431477682B00991ED5 /* tinyxml */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2ACF55471477683C00991ED5 /* Build configuration list for PBXNativeTarget "tinyxml" */;
+ buildPhases = (
+ 2AF569961479999900F9968C /* Unpack tinyxml */,
+ 2ACF55401477682B00991ED5 /* Headers */,
+ 2ACF55411477682B00991ED5 /* Sources */,
+ 2ACF55421477682B00991ED5 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = tinyxml;
+ productName = tinyxml;
+ productReference = 2ACF55441477682B00991ED5 /* libtinyxml.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "tinyxml" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 0867D691FE84028FC02AAC07 /* tinyxml */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 2ACF55431477682B00991ED5 /* tinyxml */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 2AF569961479999900F9968C /* Unpack tinyxml */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/../../../../ext/tinyxml_2_6_1.tar.gz",
+ "$(SRCROOT)/../../../../ext/tinyxml_2_6_1.patch",
+ );
+ name = "Unpack tinyxml";
+ outputPaths = (
+ "$(SRCROOT)/../../../../ext/tinyxml",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "cd $SRCROOT/../../../../ext\n\nif [ ! -d tinyxml ]\nthen\n\ttar -xzf tinyxml_2_6_1.tar.gz\n\tpatch -p0 < tinyxml_2_6_1.patch\nfi\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 2ACF55411477682B00991ED5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF55501477685000991ED5 /* tinystr.cpp in Sources */,
+ 2ACF55521477685000991ED5 /* tinyxml.cpp in Sources */,
+ 2ACF55541477685000991ED5 /* tinyxmlerror.cpp in Sources */,
+ 2ACF55551477685000991ED5 /* tinyxmlparser.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB916508733D950010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = TIXML_USE_STL;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ 1DEB916608733D950010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ NDEBUG,
+ TIXML_USE_STL,
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+ 2ACF55451477682B00991ED5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = tinyxml;
+ };
+ name = Debug;
+ };
+ 2ACF55461477682B00991ED5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = tinyxml;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "tinyxml" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB916508733D950010E9CD /* Debug */,
+ 1DEB916608733D950010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2ACF55471477683C00991ED5 /* Build configuration list for PBXNativeTarget "tinyxml" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2ACF55451477682B00991ED5 /* Debug */,
+ 2ACF55461477682B00991ED5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/src/aftereffects/xcode/ext/yaml.xcodeproj/project.pbxproj b/src/aftereffects/xcode/ext/yaml.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..2dc9cbc
--- /dev/null
+++ b/src/aftereffects/xcode/ext/yaml.xcodeproj/project.pbxproj
@@ -0,0 +1,571 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2AB6B01315538484007C3547 /* binary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AB6B01215538484007C3547 /* binary.cpp */; };
+ 2ACF55F21477693B00991ED5 /* aliasmanager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55A31477693B00991ED5 /* aliasmanager.h */; };
+ 2ACF55F31477693B00991ED5 /* anchor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55A41477693B00991ED5 /* anchor.h */; };
+ 2ACF55F41477693B00991ED5 /* anchordict.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55A61477693B00991ED5 /* anchordict.h */; };
+ 2ACF55F51477693B00991ED5 /* graphbuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55A71477693B00991ED5 /* graphbuilder.h */; };
+ 2ACF55F61477693B00991ED5 /* conversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55A81477693B00991ED5 /* conversion.h */; };
+ 2ACF55F71477693B00991ED5 /* dll.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55A91477693B00991ED5 /* dll.h */; };
+ 2ACF55F81477693B00991ED5 /* emitfromevents.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55AA1477693B00991ED5 /* emitfromevents.h */; };
+ 2ACF55F91477693B00991ED5 /* emitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55AB1477693B00991ED5 /* emitter.h */; };
+ 2ACF55FA1477693B00991ED5 /* emittermanip.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55AC1477693B00991ED5 /* emittermanip.h */; };
+ 2ACF55FB1477693B00991ED5 /* eventhandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55AD1477693B00991ED5 /* eventhandler.h */; };
+ 2ACF55FC1477693B00991ED5 /* exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55AE1477693B00991ED5 /* exceptions.h */; };
+ 2ACF55FD1477693B00991ED5 /* iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55AF1477693B00991ED5 /* iterator.h */; };
+ 2ACF55FE1477693B00991ED5 /* ltnode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B01477693B00991ED5 /* ltnode.h */; };
+ 2ACF55FF1477693B00991ED5 /* mark.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B11477693B00991ED5 /* mark.h */; };
+ 2ACF56001477693B00991ED5 /* node.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B21477693B00991ED5 /* node.h */; };
+ 2ACF56011477693B00991ED5 /* nodeimpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B31477693B00991ED5 /* nodeimpl.h */; };
+ 2ACF56021477693B00991ED5 /* nodereadimpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B41477693B00991ED5 /* nodereadimpl.h */; };
+ 2ACF56031477693B00991ED5 /* nodeutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B51477693B00991ED5 /* nodeutil.h */; };
+ 2ACF56041477693B00991ED5 /* noncopyable.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B61477693B00991ED5 /* noncopyable.h */; };
+ 2ACF56051477693B00991ED5 /* null.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B71477693B00991ED5 /* null.h */; };
+ 2ACF56061477693B00991ED5 /* ostream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B81477693B00991ED5 /* ostream.h */; };
+ 2ACF56071477693B00991ED5 /* parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55B91477693B00991ED5 /* parser.h */; };
+ 2ACF56081477693B00991ED5 /* stlemitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55BA1477693B00991ED5 /* stlemitter.h */; };
+ 2ACF56091477693B00991ED5 /* stlnode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55BB1477693B00991ED5 /* stlnode.h */; };
+ 2ACF560A1477693B00991ED5 /* traits.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55BC1477693B00991ED5 /* traits.h */; };
+ 2ACF560B1477693B00991ED5 /* yaml.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55BD1477693B00991ED5 /* yaml.h */; };
+ 2ACF560C1477693B00991ED5 /* aliasmanager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55BF1477693B00991ED5 /* aliasmanager.cpp */; };
+ 2ACF560D1477693B00991ED5 /* collectionstack.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55C01477693B00991ED5 /* collectionstack.h */; };
+ 2ACF560E1477693B00991ED5 /* graphbuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55C21477693B00991ED5 /* graphbuilder.cpp */; };
+ 2ACF560F1477693B00991ED5 /* graphbuilderadapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55C31477693B00991ED5 /* graphbuilderadapter.cpp */; };
+ 2ACF56101477693B00991ED5 /* graphbuilderadapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55C41477693B00991ED5 /* graphbuilderadapter.h */; };
+ 2ACF56111477693B00991ED5 /* conversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55C51477693B00991ED5 /* conversion.cpp */; };
+ 2ACF56121477693B00991ED5 /* directives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55C61477693B00991ED5 /* directives.cpp */; };
+ 2ACF56131477693B00991ED5 /* directives.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55C71477693B00991ED5 /* directives.h */; };
+ 2ACF56141477693B00991ED5 /* emitfromevents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55C81477693B00991ED5 /* emitfromevents.cpp */; };
+ 2ACF56151477693B00991ED5 /* emitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55C91477693B00991ED5 /* emitter.cpp */; };
+ 2ACF56161477693B00991ED5 /* emitterstate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55CA1477693B00991ED5 /* emitterstate.cpp */; };
+ 2ACF56171477693B00991ED5 /* emitterstate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55CB1477693B00991ED5 /* emitterstate.h */; };
+ 2ACF56181477693B00991ED5 /* emitterutils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55CC1477693B00991ED5 /* emitterutils.cpp */; };
+ 2ACF56191477693B00991ED5 /* emitterutils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55CD1477693B00991ED5 /* emitterutils.h */; };
+ 2ACF561A1477693B00991ED5 /* exp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55CE1477693B00991ED5 /* exp.cpp */; };
+ 2ACF561B1477693B00991ED5 /* exp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55CF1477693B00991ED5 /* exp.h */; };
+ 2ACF561C1477693B00991ED5 /* indentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55D01477693B00991ED5 /* indentation.h */; };
+ 2ACF561D1477693B00991ED5 /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55D11477693B00991ED5 /* iterator.cpp */; };
+ 2ACF561E1477693B00991ED5 /* iterpriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55D21477693B00991ED5 /* iterpriv.h */; };
+ 2ACF561F1477693B00991ED5 /* node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55D31477693B00991ED5 /* node.cpp */; };
+ 2ACF56201477693B00991ED5 /* nodebuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55D41477693B00991ED5 /* nodebuilder.cpp */; };
+ 2ACF56211477693B00991ED5 /* nodebuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55D51477693B00991ED5 /* nodebuilder.h */; };
+ 2ACF56221477693B00991ED5 /* nodeownership.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55D61477693B00991ED5 /* nodeownership.cpp */; };
+ 2ACF56231477693B00991ED5 /* nodeownership.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55D71477693B00991ED5 /* nodeownership.h */; };
+ 2ACF56241477693B00991ED5 /* null.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55D81477693B00991ED5 /* null.cpp */; };
+ 2ACF56251477693B00991ED5 /* ostream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55D91477693B00991ED5 /* ostream.cpp */; };
+ 2ACF56261477693B00991ED5 /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55DA1477693B00991ED5 /* parser.cpp */; };
+ 2ACF56271477693B00991ED5 /* ptr_stack.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55DB1477693B00991ED5 /* ptr_stack.h */; };
+ 2ACF56281477693B00991ED5 /* ptr_vector.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55DC1477693B00991ED5 /* ptr_vector.h */; };
+ 2ACF56291477693B00991ED5 /* regex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55DD1477693B00991ED5 /* regex.cpp */; };
+ 2ACF562A1477693B00991ED5 /* regex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55DE1477693B00991ED5 /* regex.h */; };
+ 2ACF562B1477693B00991ED5 /* regeximpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55DF1477693B00991ED5 /* regeximpl.h */; };
+ 2ACF562C1477693B00991ED5 /* scanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55E01477693B00991ED5 /* scanner.cpp */; };
+ 2ACF562D1477693B00991ED5 /* scanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55E11477693B00991ED5 /* scanner.h */; };
+ 2ACF562E1477693B00991ED5 /* scanscalar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55E21477693B00991ED5 /* scanscalar.cpp */; };
+ 2ACF562F1477693B00991ED5 /* scanscalar.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55E31477693B00991ED5 /* scanscalar.h */; };
+ 2ACF56301477693B00991ED5 /* scantag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55E41477693B00991ED5 /* scantag.cpp */; };
+ 2ACF56311477693B00991ED5 /* scantag.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55E51477693B00991ED5 /* scantag.h */; };
+ 2ACF56321477693B00991ED5 /* scantoken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55E61477693B00991ED5 /* scantoken.cpp */; };
+ 2ACF56331477693B00991ED5 /* setting.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55E71477693B00991ED5 /* setting.h */; };
+ 2ACF56341477693B00991ED5 /* simplekey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55E81477693B00991ED5 /* simplekey.cpp */; };
+ 2ACF56351477693B00991ED5 /* singledocparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55E91477693B00991ED5 /* singledocparser.cpp */; };
+ 2ACF56361477693B00991ED5 /* singledocparser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55EA1477693B00991ED5 /* singledocparser.h */; };
+ 2ACF56371477693B00991ED5 /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55EB1477693B00991ED5 /* stream.cpp */; };
+ 2ACF56381477693B00991ED5 /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55EC1477693B00991ED5 /* stream.h */; };
+ 2ACF56391477693B00991ED5 /* streamcharsource.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55ED1477693B00991ED5 /* streamcharsource.h */; };
+ 2ACF563A1477693B00991ED5 /* stringsource.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55EE1477693B00991ED5 /* stringsource.h */; };
+ 2ACF563B1477693B00991ED5 /* tag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF55EF1477693B00991ED5 /* tag.cpp */; };
+ 2ACF563C1477693B00991ED5 /* tag.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55F01477693B00991ED5 /* tag.h */; };
+ 2ACF563D1477693B00991ED5 /* token.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACF55F11477693B00991ED5 /* token.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 2AB6B01215538484007C3547 /* binary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = binary.cpp; sourceTree = "<group>"; };
+ 2ACF559C1477692300991ED5 /* libyaml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libyaml.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2ACF55A31477693B00991ED5 /* aliasmanager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aliasmanager.h; sourceTree = "<group>"; };
+ 2ACF55A41477693B00991ED5 /* anchor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anchor.h; sourceTree = "<group>"; };
+ 2ACF55A61477693B00991ED5 /* anchordict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anchordict.h; sourceTree = "<group>"; };
+ 2ACF55A71477693B00991ED5 /* graphbuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graphbuilder.h; sourceTree = "<group>"; };
+ 2ACF55A81477693B00991ED5 /* conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = conversion.h; sourceTree = "<group>"; };
+ 2ACF55A91477693B00991ED5 /* dll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dll.h; sourceTree = "<group>"; };
+ 2ACF55AA1477693B00991ED5 /* emitfromevents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emitfromevents.h; sourceTree = "<group>"; };
+ 2ACF55AB1477693B00991ED5 /* emitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emitter.h; sourceTree = "<group>"; };
+ 2ACF55AC1477693B00991ED5 /* emittermanip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emittermanip.h; sourceTree = "<group>"; };
+ 2ACF55AD1477693B00991ED5 /* eventhandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eventhandler.h; sourceTree = "<group>"; };
+ 2ACF55AE1477693B00991ED5 /* exceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exceptions.h; sourceTree = "<group>"; };
+ 2ACF55AF1477693B00991ED5 /* iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterator.h; sourceTree = "<group>"; };
+ 2ACF55B01477693B00991ED5 /* ltnode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ltnode.h; sourceTree = "<group>"; };
+ 2ACF55B11477693B00991ED5 /* mark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mark.h; sourceTree = "<group>"; };
+ 2ACF55B21477693B00991ED5 /* node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = node.h; sourceTree = "<group>"; };
+ 2ACF55B31477693B00991ED5 /* nodeimpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nodeimpl.h; sourceTree = "<group>"; };
+ 2ACF55B41477693B00991ED5 /* nodereadimpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nodereadimpl.h; sourceTree = "<group>"; };
+ 2ACF55B51477693B00991ED5 /* nodeutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nodeutil.h; sourceTree = "<group>"; };
+ 2ACF55B61477693B00991ED5 /* noncopyable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = noncopyable.h; sourceTree = "<group>"; };
+ 2ACF55B71477693B00991ED5 /* null.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = null.h; sourceTree = "<group>"; };
+ 2ACF55B81477693B00991ED5 /* ostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ostream.h; sourceTree = "<group>"; };
+ 2ACF55B91477693B00991ED5 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
+ 2ACF55BA1477693B00991ED5 /* stlemitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stlemitter.h; sourceTree = "<group>"; };
+ 2ACF55BB1477693B00991ED5 /* stlnode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stlnode.h; sourceTree = "<group>"; };
+ 2ACF55BC1477693B00991ED5 /* traits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = traits.h; sourceTree = "<group>"; };
+ 2ACF55BD1477693B00991ED5 /* yaml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yaml.h; sourceTree = "<group>"; };
+ 2ACF55BF1477693B00991ED5 /* aliasmanager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = aliasmanager.cpp; sourceTree = "<group>"; };
+ 2ACF55C01477693B00991ED5 /* collectionstack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = collectionstack.h; sourceTree = "<group>"; };
+ 2ACF55C21477693B00991ED5 /* graphbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = graphbuilder.cpp; sourceTree = "<group>"; };
+ 2ACF55C31477693B00991ED5 /* graphbuilderadapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = graphbuilderadapter.cpp; sourceTree = "<group>"; };
+ 2ACF55C41477693B00991ED5 /* graphbuilderadapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graphbuilderadapter.h; sourceTree = "<group>"; };
+ 2ACF55C51477693B00991ED5 /* conversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = conversion.cpp; sourceTree = "<group>"; };
+ 2ACF55C61477693B00991ED5 /* directives.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = directives.cpp; sourceTree = "<group>"; };
+ 2ACF55C71477693B00991ED5 /* directives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = directives.h; sourceTree = "<group>"; };
+ 2ACF55C81477693B00991ED5 /* emitfromevents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emitfromevents.cpp; sourceTree = "<group>"; };
+ 2ACF55C91477693B00991ED5 /* emitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emitter.cpp; sourceTree = "<group>"; };
+ 2ACF55CA1477693B00991ED5 /* emitterstate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emitterstate.cpp; sourceTree = "<group>"; };
+ 2ACF55CB1477693B00991ED5 /* emitterstate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emitterstate.h; sourceTree = "<group>"; };
+ 2ACF55CC1477693B00991ED5 /* emitterutils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emitterutils.cpp; sourceTree = "<group>"; };
+ 2ACF55CD1477693B00991ED5 /* emitterutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emitterutils.h; sourceTree = "<group>"; };
+ 2ACF55CE1477693B00991ED5 /* exp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exp.cpp; sourceTree = "<group>"; };
+ 2ACF55CF1477693B00991ED5 /* exp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exp.h; sourceTree = "<group>"; };
+ 2ACF55D01477693B00991ED5 /* indentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indentation.h; sourceTree = "<group>"; };
+ 2ACF55D11477693B00991ED5 /* iterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iterator.cpp; sourceTree = "<group>"; };
+ 2ACF55D21477693B00991ED5 /* iterpriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterpriv.h; sourceTree = "<group>"; };
+ 2ACF55D31477693B00991ED5 /* node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node.cpp; sourceTree = "<group>"; };
+ 2ACF55D41477693B00991ED5 /* nodebuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nodebuilder.cpp; sourceTree = "<group>"; };
+ 2ACF55D51477693B00991ED5 /* nodebuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nodebuilder.h; sourceTree = "<group>"; };
+ 2ACF55D61477693B00991ED5 /* nodeownership.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nodeownership.cpp; sourceTree = "<group>"; };
+ 2ACF55D71477693B00991ED5 /* nodeownership.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nodeownership.h; sourceTree = "<group>"; };
+ 2ACF55D81477693B00991ED5 /* null.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = null.cpp; sourceTree = "<group>"; };
+ 2ACF55D91477693B00991ED5 /* ostream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ostream.cpp; sourceTree = "<group>"; };
+ 2ACF55DA1477693B00991ED5 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; };
+ 2ACF55DB1477693B00991ED5 /* ptr_stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ptr_stack.h; sourceTree = "<group>"; };
+ 2ACF55DC1477693B00991ED5 /* ptr_vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ptr_vector.h; sourceTree = "<group>"; };
+ 2ACF55DD1477693B00991ED5 /* regex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = regex.cpp; sourceTree = "<group>"; };
+ 2ACF55DE1477693B00991ED5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
+ 2ACF55DF1477693B00991ED5 /* regeximpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regeximpl.h; sourceTree = "<group>"; };
+ 2ACF55E01477693B00991ED5 /* scanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner.cpp; sourceTree = "<group>"; };
+ 2ACF55E11477693B00991ED5 /* scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
+ 2ACF55E21477693B00991ED5 /* scanscalar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanscalar.cpp; sourceTree = "<group>"; };
+ 2ACF55E31477693B00991ED5 /* scanscalar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanscalar.h; sourceTree = "<group>"; };
+ 2ACF55E41477693B00991ED5 /* scantag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scantag.cpp; sourceTree = "<group>"; };
+ 2ACF55E51477693B00991ED5 /* scantag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scantag.h; sourceTree = "<group>"; };
+ 2ACF55E61477693B00991ED5 /* scantoken.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scantoken.cpp; sourceTree = "<group>"; };
+ 2ACF55E71477693B00991ED5 /* setting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = setting.h; sourceTree = "<group>"; };
+ 2ACF55E81477693B00991ED5 /* simplekey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = simplekey.cpp; sourceTree = "<group>"; };
+ 2ACF55E91477693B00991ED5 /* singledocparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = singledocparser.cpp; sourceTree = "<group>"; };
+ 2ACF55EA1477693B00991ED5 /* singledocparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = singledocparser.h; sourceTree = "<group>"; };
+ 2ACF55EB1477693B00991ED5 /* stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stream.cpp; sourceTree = "<group>"; };
+ 2ACF55EC1477693B00991ED5 /* stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stream.h; sourceTree = "<group>"; };
+ 2ACF55ED1477693B00991ED5 /* streamcharsource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streamcharsource.h; sourceTree = "<group>"; };
+ 2ACF55EE1477693B00991ED5 /* stringsource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stringsource.h; sourceTree = "<group>"; };
+ 2ACF55EF1477693B00991ED5 /* tag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tag.cpp; sourceTree = "<group>"; };
+ 2ACF55F01477693B00991ED5 /* tag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tag.h; sourceTree = "<group>"; };
+ 2ACF55F11477693B00991ED5 /* token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = token.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2ACF559A1477692300991ED5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF559C1477692300991ED5 /* libyaml.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* yaml */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55A01477693B00991ED5 /* yaml-cpp */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = yaml;
+ sourceTree = "<group>";
+ };
+ 2ACF55A01477693B00991ED5 /* yaml-cpp */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55A11477693B00991ED5 /* include */,
+ 2ACF55BE1477693B00991ED5 /* src */,
+ );
+ name = "yaml-cpp";
+ path = "../../../../ext/yaml-cpp";
+ sourceTree = SOURCE_ROOT;
+ };
+ 2ACF55A11477693B00991ED5 /* include */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55A21477693B00991ED5 /* yaml-cpp */,
+ );
+ path = include;
+ sourceTree = "<group>";
+ };
+ 2ACF55A21477693B00991ED5 /* yaml-cpp */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55A31477693B00991ED5 /* aliasmanager.h */,
+ 2ACF55A41477693B00991ED5 /* anchor.h */,
+ 2ACF55A51477693B00991ED5 /* contrib */,
+ 2ACF55A81477693B00991ED5 /* conversion.h */,
+ 2ACF55A91477693B00991ED5 /* dll.h */,
+ 2ACF55AA1477693B00991ED5 /* emitfromevents.h */,
+ 2ACF55AB1477693B00991ED5 /* emitter.h */,
+ 2ACF55AC1477693B00991ED5 /* emittermanip.h */,
+ 2ACF55AD1477693B00991ED5 /* eventhandler.h */,
+ 2ACF55AE1477693B00991ED5 /* exceptions.h */,
+ 2ACF55AF1477693B00991ED5 /* iterator.h */,
+ 2ACF55B01477693B00991ED5 /* ltnode.h */,
+ 2ACF55B11477693B00991ED5 /* mark.h */,
+ 2ACF55B21477693B00991ED5 /* node.h */,
+ 2ACF55B31477693B00991ED5 /* nodeimpl.h */,
+ 2ACF55B41477693B00991ED5 /* nodereadimpl.h */,
+ 2ACF55B51477693B00991ED5 /* nodeutil.h */,
+ 2ACF55B61477693B00991ED5 /* noncopyable.h */,
+ 2ACF55B71477693B00991ED5 /* null.h */,
+ 2ACF55B81477693B00991ED5 /* ostream.h */,
+ 2ACF55B91477693B00991ED5 /* parser.h */,
+ 2ACF55BA1477693B00991ED5 /* stlemitter.h */,
+ 2ACF55BB1477693B00991ED5 /* stlnode.h */,
+ 2ACF55BC1477693B00991ED5 /* traits.h */,
+ 2ACF55BD1477693B00991ED5 /* yaml.h */,
+ );
+ path = "yaml-cpp";
+ sourceTree = "<group>";
+ };
+ 2ACF55A51477693B00991ED5 /* contrib */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55A61477693B00991ED5 /* anchordict.h */,
+ 2ACF55A71477693B00991ED5 /* graphbuilder.h */,
+ );
+ path = contrib;
+ sourceTree = "<group>";
+ };
+ 2ACF55BE1477693B00991ED5 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55BF1477693B00991ED5 /* aliasmanager.cpp */,
+ 2AB6B01215538484007C3547 /* binary.cpp */,
+ 2ACF55C01477693B00991ED5 /* collectionstack.h */,
+ 2ACF55C11477693B00991ED5 /* contrib */,
+ 2ACF55C51477693B00991ED5 /* conversion.cpp */,
+ 2ACF55C61477693B00991ED5 /* directives.cpp */,
+ 2ACF55C71477693B00991ED5 /* directives.h */,
+ 2ACF55C81477693B00991ED5 /* emitfromevents.cpp */,
+ 2ACF55C91477693B00991ED5 /* emitter.cpp */,
+ 2ACF55CA1477693B00991ED5 /* emitterstate.cpp */,
+ 2ACF55CB1477693B00991ED5 /* emitterstate.h */,
+ 2ACF55CC1477693B00991ED5 /* emitterutils.cpp */,
+ 2ACF55CD1477693B00991ED5 /* emitterutils.h */,
+ 2ACF55CE1477693B00991ED5 /* exp.cpp */,
+ 2ACF55CF1477693B00991ED5 /* exp.h */,
+ 2ACF55D01477693B00991ED5 /* indentation.h */,
+ 2ACF55D11477693B00991ED5 /* iterator.cpp */,
+ 2ACF55D21477693B00991ED5 /* iterpriv.h */,
+ 2ACF55D31477693B00991ED5 /* node.cpp */,
+ 2ACF55D41477693B00991ED5 /* nodebuilder.cpp */,
+ 2ACF55D51477693B00991ED5 /* nodebuilder.h */,
+ 2ACF55D61477693B00991ED5 /* nodeownership.cpp */,
+ 2ACF55D71477693B00991ED5 /* nodeownership.h */,
+ 2ACF55D81477693B00991ED5 /* null.cpp */,
+ 2ACF55D91477693B00991ED5 /* ostream.cpp */,
+ 2ACF55DA1477693B00991ED5 /* parser.cpp */,
+ 2ACF55DB1477693B00991ED5 /* ptr_stack.h */,
+ 2ACF55DC1477693B00991ED5 /* ptr_vector.h */,
+ 2ACF55DD1477693B00991ED5 /* regex.cpp */,
+ 2ACF55DE1477693B00991ED5 /* regex.h */,
+ 2ACF55DF1477693B00991ED5 /* regeximpl.h */,
+ 2ACF55E01477693B00991ED5 /* scanner.cpp */,
+ 2ACF55E11477693B00991ED5 /* scanner.h */,
+ 2ACF55E21477693B00991ED5 /* scanscalar.cpp */,
+ 2ACF55E31477693B00991ED5 /* scanscalar.h */,
+ 2ACF55E41477693B00991ED5 /* scantag.cpp */,
+ 2ACF55E51477693B00991ED5 /* scantag.h */,
+ 2ACF55E61477693B00991ED5 /* scantoken.cpp */,
+ 2ACF55E71477693B00991ED5 /* setting.h */,
+ 2ACF55E81477693B00991ED5 /* simplekey.cpp */,
+ 2ACF55E91477693B00991ED5 /* singledocparser.cpp */,
+ 2ACF55EA1477693B00991ED5 /* singledocparser.h */,
+ 2ACF55EB1477693B00991ED5 /* stream.cpp */,
+ 2ACF55EC1477693B00991ED5 /* stream.h */,
+ 2ACF55ED1477693B00991ED5 /* streamcharsource.h */,
+ 2ACF55EE1477693B00991ED5 /* stringsource.h */,
+ 2ACF55EF1477693B00991ED5 /* tag.cpp */,
+ 2ACF55F01477693B00991ED5 /* tag.h */,
+ 2ACF55F11477693B00991ED5 /* token.h */,
+ );
+ path = src;
+ sourceTree = "<group>";
+ };
+ 2ACF55C11477693B00991ED5 /* contrib */ = {
+ isa = PBXGroup;
+ children = (
+ 2ACF55C21477693B00991ED5 /* graphbuilder.cpp */,
+ 2ACF55C31477693B00991ED5 /* graphbuilderadapter.cpp */,
+ 2ACF55C41477693B00991ED5 /* graphbuilderadapter.h */,
+ );
+ path = contrib;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 2ACF55981477692300991ED5 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF55F21477693B00991ED5 /* aliasmanager.h in Headers */,
+ 2ACF55F31477693B00991ED5 /* anchor.h in Headers */,
+ 2ACF55F41477693B00991ED5 /* anchordict.h in Headers */,
+ 2ACF55F51477693B00991ED5 /* graphbuilder.h in Headers */,
+ 2ACF55F61477693B00991ED5 /* conversion.h in Headers */,
+ 2ACF55F71477693B00991ED5 /* dll.h in Headers */,
+ 2ACF55F81477693B00991ED5 /* emitfromevents.h in Headers */,
+ 2ACF55F91477693B00991ED5 /* emitter.h in Headers */,
+ 2ACF55FA1477693B00991ED5 /* emittermanip.h in Headers */,
+ 2ACF55FB1477693B00991ED5 /* eventhandler.h in Headers */,
+ 2ACF55FC1477693B00991ED5 /* exceptions.h in Headers */,
+ 2ACF55FD1477693B00991ED5 /* iterator.h in Headers */,
+ 2ACF55FE1477693B00991ED5 /* ltnode.h in Headers */,
+ 2ACF55FF1477693B00991ED5 /* mark.h in Headers */,
+ 2ACF56001477693B00991ED5 /* node.h in Headers */,
+ 2ACF56011477693B00991ED5 /* nodeimpl.h in Headers */,
+ 2ACF56021477693B00991ED5 /* nodereadimpl.h in Headers */,
+ 2ACF56031477693B00991ED5 /* nodeutil.h in Headers */,
+ 2ACF56041477693B00991ED5 /* noncopyable.h in Headers */,
+ 2ACF56051477693B00991ED5 /* null.h in Headers */,
+ 2ACF56061477693B00991ED5 /* ostream.h in Headers */,
+ 2ACF56071477693B00991ED5 /* parser.h in Headers */,
+ 2ACF56081477693B00991ED5 /* stlemitter.h in Headers */,
+ 2ACF56091477693B00991ED5 /* stlnode.h in Headers */,
+ 2ACF560A1477693B00991ED5 /* traits.h in Headers */,
+ 2ACF560B1477693B00991ED5 /* yaml.h in Headers */,
+ 2ACF560D1477693B00991ED5 /* collectionstack.h in Headers */,
+ 2ACF56101477693B00991ED5 /* graphbuilderadapter.h in Headers */,
+ 2ACF56131477693B00991ED5 /* directives.h in Headers */,
+ 2ACF56171477693B00991ED5 /* emitterstate.h in Headers */,
+ 2ACF56191477693B00991ED5 /* emitterutils.h in Headers */,
+ 2ACF561B1477693B00991ED5 /* exp.h in Headers */,
+ 2ACF561C1477693B00991ED5 /* indentation.h in Headers */,
+ 2ACF561E1477693B00991ED5 /* iterpriv.h in Headers */,
+ 2ACF56211477693B00991ED5 /* nodebuilder.h in Headers */,
+ 2ACF56231477693B00991ED5 /* nodeownership.h in Headers */,
+ 2ACF56271477693B00991ED5 /* ptr_stack.h in Headers */,
+ 2ACF56281477693B00991ED5 /* ptr_vector.h in Headers */,
+ 2ACF562A1477693B00991ED5 /* regex.h in Headers */,
+ 2ACF562B1477693B00991ED5 /* regeximpl.h in Headers */,
+ 2ACF562D1477693B00991ED5 /* scanner.h in Headers */,
+ 2ACF562F1477693B00991ED5 /* scanscalar.h in Headers */,
+ 2ACF56311477693B00991ED5 /* scantag.h in Headers */,
+ 2ACF56331477693B00991ED5 /* setting.h in Headers */,
+ 2ACF56361477693B00991ED5 /* singledocparser.h in Headers */,
+ 2ACF56381477693B00991ED5 /* stream.h in Headers */,
+ 2ACF56391477693B00991ED5 /* streamcharsource.h in Headers */,
+ 2ACF563A1477693B00991ED5 /* stringsource.h in Headers */,
+ 2ACF563C1477693B00991ED5 /* tag.h in Headers */,
+ 2ACF563D1477693B00991ED5 /* token.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 2ACF559B1477692300991ED5 /* yaml */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2ACF559F1477692B00991ED5 /* Build configuration list for PBXNativeTarget "yaml" */;
+ buildPhases = (
+ 2AF56976147991F700F9968C /* Unpack yaml */,
+ 2ACF55981477692300991ED5 /* Headers */,
+ 2ACF55991477692300991ED5 /* Sources */,
+ 2ACF559A1477692300991ED5 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = yaml;
+ productName = yaml;
+ productReference = 2ACF559C1477692300991ED5 /* libyaml.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "yaml" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 0867D691FE84028FC02AAC07 /* yaml */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 2ACF559B1477692300991ED5 /* yaml */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 2AF56976147991F700F9968C /* Unpack yaml */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/../../../../ext/yaml-cpp-0.3.0.tar.gz",
+ "$(SRCROOT)/../../../../ext/yaml-cpp-0.3.0.patch",
+ );
+ name = "Unpack yaml";
+ outputPaths = (
+ "$(SRCROOT)/../../../../ext/yaml-cpp",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "cd $SRCROOT/../../../../ext\n\nif [ ! -d yaml-cpp ]\nthen\n\ttar -xzf yaml-cpp-0.3.0.tar.gz\n\tpatch -p0 < yaml-cpp-0.3.0.patch\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 2ACF55991477692300991ED5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2ACF560C1477693B00991ED5 /* aliasmanager.cpp in Sources */,
+ 2ACF560E1477693B00991ED5 /* graphbuilder.cpp in Sources */,
+ 2ACF560F1477693B00991ED5 /* graphbuilderadapter.cpp in Sources */,
+ 2ACF56111477693B00991ED5 /* conversion.cpp in Sources */,
+ 2ACF56121477693B00991ED5 /* directives.cpp in Sources */,
+ 2ACF56141477693B00991ED5 /* emitfromevents.cpp in Sources */,
+ 2ACF56151477693B00991ED5 /* emitter.cpp in Sources */,
+ 2ACF56161477693B00991ED5 /* emitterstate.cpp in Sources */,
+ 2ACF56181477693B00991ED5 /* emitterutils.cpp in Sources */,
+ 2ACF561A1477693B00991ED5 /* exp.cpp in Sources */,
+ 2ACF561D1477693B00991ED5 /* iterator.cpp in Sources */,
+ 2ACF561F1477693B00991ED5 /* node.cpp in Sources */,
+ 2ACF56201477693B00991ED5 /* nodebuilder.cpp in Sources */,
+ 2ACF56221477693B00991ED5 /* nodeownership.cpp in Sources */,
+ 2ACF56241477693B00991ED5 /* null.cpp in Sources */,
+ 2ACF56251477693B00991ED5 /* ostream.cpp in Sources */,
+ 2ACF56261477693B00991ED5 /* parser.cpp in Sources */,
+ 2ACF56291477693B00991ED5 /* regex.cpp in Sources */,
+ 2ACF562C1477693B00991ED5 /* scanner.cpp in Sources */,
+ 2ACF562E1477693B00991ED5 /* scanscalar.cpp in Sources */,
+ 2ACF56301477693B00991ED5 /* scantag.cpp in Sources */,
+ 2ACF56321477693B00991ED5 /* scantoken.cpp in Sources */,
+ 2ACF56341477693B00991ED5 /* simplekey.cpp in Sources */,
+ 2ACF56351477693B00991ED5 /* singledocparser.cpp in Sources */,
+ 2ACF56371477693B00991ED5 /* stream.cpp in Sources */,
+ 2ACF563B1477693B00991ED5 /* tag.cpp in Sources */,
+ 2AB6B01315538484007C3547 /* binary.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB916508733D950010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "../../../../ext/yaml-cpp/include";
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ 1DEB916608733D950010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "../../../../ext/yaml-cpp/include";
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+ 2ACF559D1477692300991ED5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = yaml;
+ };
+ name = Debug;
+ };
+ 2ACF559E1477692300991ED5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/lib;
+ PREBINDING = NO;
+ PRODUCT_NAME = yaml;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "yaml" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB916508733D950010E9CD /* Debug */,
+ 1DEB916608733D950010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2ACF559F1477692B00991ED5 /* Build configuration list for PBXNativeTarget "yaml" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2ACF559D1477692300991ED5 /* Debug */,
+ 2ACF559E1477692300991ED5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/src/apps/ociobakelut/CMakeLists.txt b/src/apps/ociobakelut/CMakeLists.txt
new file mode 100644
index 0000000..c15d156
--- /dev/null
+++ b/src/apps/ociobakelut/CMakeLists.txt
@@ -0,0 +1,46 @@
+# LCMS
+include(FindPkgConfig FindPackageMessage)
+pkg_check_modules(LCMS QUIET lcms2)
+if(LCMS_FOUND AND (LCMS_VERSION VERSION_EQUAL 2.1 OR LCMS_VERSION VERSION_GREATER 2.1))
+ FIND_PACKAGE_MESSAGE(LCMS "Found lcms: ${LCMS_LIBRARIES}"
+ "${LCMS_INCLUDE_DIR}")
+else()
+ message(STATUS "Using bundled lcms.")
+ set(LCMS_VERSION 2.1)
+ set(LCMS_BUNDLED TRUE)
+ ExternalProject_Add(LCMS
+ URL ${CMAKE_SOURCE_DIR}/ext/lcms2-${LCMS_VERSION}.tar.gz
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND ./configure --prefix=${PROJECT_BINARY_DIR}/ext/dist --without-jpeg --without-tiff --without-zlib
+ BUILD_COMMAND make
+ INSTALL_COMMAND make install
+ )
+ set(LCMS_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/ext/dist/include)
+ set(LCMS_LIBRARY_DIRS ${PROJECT_BINARY_DIR}/ext/dist/lib)
+ set(LCMS_LIBRARIES ${PROJECT_BINARY_DIR}/ext/dist/lib/liblcms2.a)
+endif()
+
+file(GLOB_RECURSE share_src_files "${CMAKE_SOURCE_DIR}/src/apps/share/*.cpp")
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${CMAKE_SOURCE_DIR}/src/apps/share/
+ ${LCMS_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${LCMS_LIBRARY_DIRS}
+)
+
+add_executable(ociobakelut ${share_src_files} main.cpp ocioicc.cpp)
+
+if(LCMS_BUNDLED)
+ add_dependencies(ociobakelut LCMS)
+endif()
+
+target_link_libraries(ociobakelut
+ ${LCMS_LIBRARIES}
+ OpenColorIO)
+
+install(TARGETS ociobakelut DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/bin)
diff --git a/src/apps/ociobakelut/main.cpp b/src/apps/ociobakelut/main.cpp
new file mode 100644
index 0000000..265d464
--- /dev/null
+++ b/src/apps/ociobakelut/main.cpp
@@ -0,0 +1,537 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+#include "argparse.h"
+#include "ocioicc.h"
+
+static std::string outputfile;
+
+static int
+parse_end_args(int argc, const char *argv[])
+{
+ if(argc>0)
+ {
+ outputfile = argv[0];
+ }
+
+ return 0;
+}
+
+OCIO::GroupTransformRcPtr
+parse_luts(int argc, const char *argv[]);
+
+int main (int argc, const char* argv[])
+{
+
+ bool help = false;
+ int cubesize = -1;
+ int shapersize = -1; // cubsize^2
+ std::string format;
+ std::string inputconfig;
+ std::string inputspace;
+ std::string shaperspace;
+ std::string looks;
+ std::string outputspace;
+ bool usestdout = false;
+ bool verbose = false;
+
+ int whitepointtemp = 6505;
+ std::string displayicc;
+ std::string description;
+ std::string copyright = "OpenColorIO (Sony Imageworks)";
+
+ // What are the allowed baker output formats?
+ std::ostringstream formats;
+ formats << "the lut format to bake: ";
+ for(int i=0; i<OCIO::Baker::getNumFormats(); ++i)
+ {
+ if(i!=0) formats << ", ";
+ formats << OCIO::Baker::getFormatNameByIndex(i);
+ formats << " (." << OCIO::Baker::getFormatExtensionByIndex(i) << ")";
+ }
+ formats << ", icc (.icc)";
+
+ std::string formatstr = formats.str();
+
+ std::string dummystr;
+ float dummyf1, dummyf2, dummyf3;
+
+ ArgParse ap;
+ ap.options("ociobakelut -- create a new LUT or icc profile from an OCIO config or lut file(s)\n\n"
+ "usage: ociobakelut [options] <OUTPUTFILE.LUT>\n\n"
+ "example: ociobakelut --inputspace lg10 --outputspace srgb8 --format flame lg_to_srgb.3dl\n"
+ "example: ociobakelut --lut filmlut.3dl --lut calibration.3dl --format flame display.3dl\n"
+ "example: ociobakelut --lut look.3dl --offset 0.01 -0.02 0.03 --lut display.3dl --format flame display_with_look.3dl\n"
+ "example: ociobakelut --inputspace lg10 --outputspace srgb8 --format icc ~/Library/ColorSync/Profiles/test.icc\n"
+ "example: ociobakelut --lut filmlut.3dl --lut calibration.3dl --format icc ~/Library/ColorSync/Profiles/test.icc\n\n",
+ "%*", parse_end_args, "",
+ "<SEPARATOR>", "Using Existing OCIO Configurations",
+ "--inputspace %s", &inputspace, "Input OCIO ColorSpace (or Role)",
+ "--outputspace %s", &outputspace, "Output OCIO ColorSpace (or Role)",
+ "--shaperspace %s", &shaperspace, "the OCIO ColorSpace or Role, for the shaper",
+ "--looks %s", &looks, "the OCIO looks to apply",
+ "--iconfig %s", &inputconfig, "Input .ocio configuration file (default: $OCIO)\n",
+ "<SEPARATOR>", "Config-Free LUT Baking",
+ "<SEPARATOR>", " (all options can be specified multiple times, each is applied in order)",
+ "--lut %s", &dummystr, "Specify a LUT (forward direction)",
+ "--invlut %s", &dummystr, "Specify a LUT (inverse direction)",
+ "--slope %f %f %f", &dummyf1, &dummyf2, &dummyf3, "slope",
+ "--offset %f %f %f", &dummyf1, &dummyf2, &dummyf3, "offset (float)",
+ "--offset10 %f %f %f", &dummyf1, &dummyf2, &dummyf3, "offset (10-bit)",
+ "--power %f %f %f", &dummyf1, &dummyf2, &dummyf3, "power",
+ "--sat %f", &dummyf1, "saturation (ASC-CDL luma coefficients)\n",
+ "<SEPARATOR>", "Baking Options",
+ "--format %s", &format, formatstr.c_str(),
+ "--shapersize %d", &shapersize, "size of the shaper (default: format specific)",
+ "--cubesize %d", &cubesize, "size of the cube (default: format specific)",
+ "--stdout", &usestdout, "Write to stdout (rather than file)",
+ "--v", &verbose, "Verbose",
+ "--help", &help, "Print help message\n",
+ "<SEPARATOR>", "ICC Options",
+ //"--cubesize %d", &cubesize, "size of the icc CLUT cube (default: 32)",
+ "--whitepoint %d", &whitepointtemp, "whitepoint for the profile (default: 6505)",
+ "--displayicc %s", &displayicc , "an icc profile which matches the OCIO profiles target display",
+ "--description %s", &description , "a meaningful description, this will show up in UI like photoshop",
+ "--copyright %s", &copyright , "a copyright field\n",
+ // TODO: add --metadata option
+ NULL);
+
+ if (ap.parse(argc, argv) < 0)
+ {
+ std::cout << ap.geterror() << std::endl;
+ ap.usage();
+ std::cout << "\n";
+ return 1;
+ }
+
+ if (help || (argc == 1 ))
+ {
+ ap.usage();
+ std::cout << "\n";
+ return 1;
+ }
+
+ // If we're printing to stdout, disable verbose printouts
+ if(usestdout)
+ {
+ verbose = false;
+ }
+
+ // Create the OCIO processor for the specified transform.
+ OCIO::ConstConfigRcPtr config;
+
+
+ OCIO::GroupTransformRcPtr groupTransform;
+
+ try
+ {
+ groupTransform = parse_luts(argc, argv);
+ }
+ catch(const OCIO::Exception & e)
+ {
+ std::cerr << "\nERROR: " << e.what() << std::endl;
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+ catch(...)
+ {
+ std::cerr << "\nERROR: An unknown error occurred in parse_luts" << std::endl;
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(!groupTransform)
+ {
+ std::cerr << "\nERROR: parse_luts returned null transform" << std::endl;
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ // If --luts have been specified, synthesize a new (temporary) configuration
+ // with the transformation embedded in a colorspace.
+ if(!groupTransform->empty())
+ {
+ if(!inputspace.empty())
+ {
+ std::cerr << "\nERROR: --inputspace is not allowed when using --lut\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+ if(!outputspace.empty())
+ {
+ std::cerr << "\nERROR: --outputspace is not allowed when using --lut\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+ if(!looks.empty())
+ {
+ std::cerr << "\nERROR: --looks is not allowed when using --lut\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+ if(!shaperspace.empty())
+ {
+ std::cerr << "\nERROR: --shaperspace is not allowed when using --lut\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ OCIO::ConfigRcPtr editableConfig = OCIO::Config::Create();
+
+ OCIO::ColorSpaceRcPtr inputColorSpace = OCIO::ColorSpace::Create();
+ inputspace = "RawInput";
+ inputColorSpace->setName(inputspace.c_str());
+ editableConfig->addColorSpace(inputColorSpace);
+
+ OCIO::ColorSpaceRcPtr outputColorSpace = OCIO::ColorSpace::Create();
+ outputspace = "ProcessedOutput";
+ outputColorSpace->setName(outputspace.c_str());
+
+ outputColorSpace->setTransform(groupTransform,
+ OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+
+ if(verbose)
+ {
+ std::cout << "[OpenColorIO DEBUG]: Specified Transform:";
+ std::cout << *groupTransform;
+ std::cout << "\n";
+ }
+
+ editableConfig->addColorSpace(outputColorSpace);
+ config = editableConfig;
+ }
+ else
+ {
+
+ if(inputspace.empty())
+ {
+ std::cerr << "\nERROR: You must specify the --inputspace.\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(outputspace.empty())
+ {
+ std::cerr << "\nERROR: You must specify the --outputspace.\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(format.empty())
+ {
+ std::cerr << "\nERROR: You must specify the lut format using --format.\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(!inputconfig.empty())
+ {
+ if(!usestdout && verbose)
+ std::cout << "[OpenColorIO INFO]: Loading " << inputconfig << std::endl;
+ config = OCIO::Config::CreateFromFile(inputconfig.c_str());
+ }
+ else if(getenv("OCIO"))
+ {
+ if(!usestdout && verbose)
+ std::cout << "[OpenColorIO INFO]: Loading $OCIO " << getenv("OCIO") << std::endl;
+ config = OCIO::Config::CreateFromEnv();
+ }
+ else
+ {
+ std::cerr << "ERROR: You must specify an input ocio configuration ";
+ std::cerr << "(either with --iconfig or $OCIO).\n\n";
+ ap.usage ();
+ return 1;
+ }
+ }
+
+ if(outputfile.empty() && !usestdout)
+ {
+ std::cerr << "\nERROR: You must specify the outputfile or --stdout.\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ if(format == "icc")
+ {
+ if(usestdout)
+ {
+ std::cerr << "\nERROR: --stdout not supported when writing icc profiles.\n\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(outputfile.empty())
+ {
+ std::cerr << "ERROR: you need to specify a output icc path\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(copyright.empty())
+ {
+ std::cerr << "ERROR: need to specify a --copyright to embed in the icc profile\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ if(cubesize<2) cubesize = 32; // default
+
+ OCIO::ConstProcessorRcPtr processor;
+ if (!looks.empty())
+ {
+ OCIO::LookTransformRcPtr transform =
+ OCIO::LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(inputspace.c_str());
+ transform->setDst(outputspace.c_str());
+ processor = config->getProcessor(transform,
+ OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ processor = config->getProcessor(inputspace.c_str(),
+ outputspace.c_str());
+ }
+
+ SaveICCProfileToFile(outputfile,
+ processor,
+ cubesize,
+ whitepointtemp,
+ displayicc,
+ description,
+ copyright,
+ verbose);
+ }
+ else
+ {
+
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+
+ // setup the baker for our lut type
+ baker->setConfig(config);
+ baker->setFormat(format.c_str());
+ baker->setInputSpace(inputspace.c_str());
+ baker->setShaperSpace(shaperspace.c_str());
+ baker->setLooks(looks.c_str());
+ baker->setTargetSpace(outputspace.c_str());
+ if(shapersize!=-1) baker->setShaperSize(shapersize);
+ if(cubesize!=-1) baker->setCubeSize(cubesize);
+
+ // output lut
+ std::ostringstream output;
+
+ if(!usestdout && verbose)
+ std::cout << "[OpenColorIO INFO]: Baking '" << format << "' lut" << std::endl;
+
+ if(usestdout)
+ {
+ baker->bake(std::cout);
+ }
+ else
+ {
+ std::ofstream f(outputfile.c_str());
+ baker->bake(f);
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Wrote '" << outputfile << "'" << std::endl;
+ }
+ }
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cerr << "OCIO Error: " << exception.what() << std::endl;
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+ catch (std::exception& exception)
+ {
+ std::cerr << "Error: " << exception.what() << "\n";
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+ catch(...)
+ {
+ std::cerr << "Unknown OCIO error encountered." << std::endl;
+ std::cerr << "See --help for more info." << std::endl;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+// TODO: Replace this dirty argument parsing code with a clean version
+// that leverages the same codepath for the standard arguments. If
+// the OIIO derived argparse does not suffice, options we may want to consider
+// include simpleopt, tclap, ultraopt
+
+// TODO: Use better input validation, instead of atof.
+// If too few arguments are provides for scale (let's say only two) and
+// the following argument is the start of another flag (let's say "--invlut")
+// then atof() will likely try to convert "--invlut" to its double equivalent,
+// resulting in an invalid (or at least undesired) scale value.
+
+OCIO::GroupTransformRcPtr
+parse_luts(int argc, const char *argv[])
+{
+ OCIO::GroupTransformRcPtr groupTransform = OCIO::GroupTransform::Create();
+
+ for(int i=0; i<argc; ++i)
+ {
+ std::string arg(argv[i]);
+
+ if(arg == "--lut" || arg == "-lut")
+ {
+ if(i+1>=argc)
+ {
+ throw OCIO::Exception("Error parsing --lut. Invalid num args");
+ }
+
+ OCIO::FileTransformRcPtr t = OCIO::FileTransform::Create();
+ t->setSrc(argv[i+1]);
+ t->setInterpolation(OCIO::INTERP_BEST);
+ groupTransform->push_back(t);
+
+ i += 1;
+ }
+ else if(arg == "--invlut" || arg == "-invlut")
+ {
+ if(i+1>=argc)
+ {
+ throw OCIO::Exception("Error parsing --invlut. Invalid num args");
+ }
+
+ OCIO::FileTransformRcPtr t = OCIO::FileTransform::Create();
+ t->setSrc(argv[i+1]);
+ t->setInterpolation(OCIO::INTERP_BEST);
+ t->setDirection(OCIO::TRANSFORM_DIR_INVERSE);
+ groupTransform->push_back(t);
+
+ i += 1;
+ }
+ else if(arg == "--slope" || arg == "-slope")
+ {
+ if(i+3>=argc)
+ {
+ throw OCIO::Exception("Error parsing --slope. Invalid num args");
+ }
+
+ OCIO::CDLTransformRcPtr t = OCIO::CDLTransform::Create();
+
+ float scale[3];
+ scale[0] = (float) atof(argv[i+1]);
+ scale[1] = (float) atof(argv[i+2]);
+ scale[2] = (float) atof(argv[i+3]);
+ t->setSlope(scale);
+ groupTransform->push_back(t);
+
+ i += 3;
+ }
+ else if(arg == "--offset" || arg == "-offset")
+ {
+ if(i+3>=argc)
+ {
+ throw OCIO::Exception("Error parsing --offset. Invalid num args");
+ }
+
+ OCIO::CDLTransformRcPtr t = OCIO::CDLTransform::Create();
+
+ float offset[3];
+ offset[0] = (float) atof(argv[i+1]);
+ offset[1] = (float) atof(argv[i+2]);
+ offset[2] = (float) atof(argv[i+3]);
+ t->setOffset(offset);
+ groupTransform->push_back(t);
+
+ i += 3;
+ }
+ else if(arg == "--offset10" || arg == "-offset10")
+ {
+ if(i+3>=argc)
+ {
+ throw OCIO::Exception("Error parsing --offset10. Invalid num args");
+ }
+
+ OCIO::CDLTransformRcPtr t = OCIO::CDLTransform::Create();
+
+ float offset[3];
+ offset[0] = (float) atof(argv[i+1]) / 1023.0f;
+ offset[1] = (float) atof(argv[i+2]) / 1023.0f;
+ offset[2] = (float) atof(argv[i+3]) / 1023.0f;
+ t->setOffset(offset);
+ groupTransform->push_back(t);
+ i += 3;
+ }
+ else if(arg == "--power" || arg == "-power")
+ {
+ if(i+3>=argc)
+ {
+ throw OCIO::Exception("Error parsing --power. Invalid num args");
+ }
+
+ OCIO::CDLTransformRcPtr t = OCIO::CDLTransform::Create();
+
+ float power[3];
+ power[0] = (float) atof(argv[i+1]);
+ power[1] = (float) atof(argv[i+2]);
+ power[2] = (float) atof(argv[i+3]);
+ t->setPower(power);
+ groupTransform->push_back(t);
+
+ i += 3;
+ }
+ else if(arg == "--sat" || arg == "-sat")
+ {
+ if(i+1>=argc)
+ {
+ throw OCIO::Exception("Error parsing --sat. Invalid num args");
+ }
+
+ OCIO::CDLTransformRcPtr t = OCIO::CDLTransform::Create();
+ t->setSat((float) atof(argv[i+1]));
+ groupTransform->push_back(t);
+
+ i += 1;
+ }
+ }
+
+ return groupTransform;
+}
+
diff --git a/src/apps/ociobakelut/ocioicc.cpp b/src/apps/ociobakelut/ocioicc.cpp
new file mode 100644
index 0000000..2975f4a
--- /dev/null
+++ b/src/apps/ociobakelut/ocioicc.cpp
@@ -0,0 +1,251 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "ocioicc.h"
+
+#include "lcms2.h"
+#include "lcms2_plugin.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+
+namespace
+{
+void ErrorHandler(cmsContext /*ContextID*/, cmsUInt32Number /*ErrorCode*/, const char *Text)
+{
+ std::cerr << "OCIO Error: " << Text << "\n";
+ return;
+}
+
+typedef struct
+{
+ cmsHTRANSFORM to_PCS16;
+ cmsHTRANSFORM from_PCS16;
+ //OCIO::ConstProcessorRcPtr shaper_processor;
+ OCIO::ConstProcessorRcPtr processor;
+} SamplerData;
+
+static void Add3GammaCurves(cmsPipeline* lut, cmsFloat64Number Curve)
+{
+ cmsToneCurve* id = cmsBuildGamma(NULL, Curve);
+ cmsToneCurve* id3[3];
+ id3[0] = id;
+ id3[1] = id;
+ id3[2] = id;
+ cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(NULL, 3, id3));
+ cmsFreeToneCurve(id);
+}
+
+static void AddIdentityMatrix(cmsPipeline* lut)
+{
+ const cmsFloat64Number Identity[] = {
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1,
+ 0, 0, 0 };
+ cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocMatrix(NULL, 3, 3, Identity, NULL));
+}
+
+static cmsInt32Number Display2PCS_Sampler16(const cmsUInt16Number in[], cmsUInt16Number out[], void* userdata)
+{
+ //std::cout << "r" << in[0] << " g" << in[1] << " b" << in[2] << "\n";
+ SamplerData* data = (SamplerData*) userdata;
+ cmsFloat32Number pix[3] = { static_cast<float>(in[0])/65535.f,
+ static_cast<float>(in[1])/65535.f,
+ static_cast<float>(in[2])/65535.f};
+ data->processor->applyRGB(pix);
+ out[0] = (cmsUInt16Number)std::max(std::min(pix[0] * 65535.f, 65535.f), 0.f);
+ out[1] = (cmsUInt16Number)std::max(std::min(pix[1] * 65535.f, 65535.f), 0.f);
+ out[2] = (cmsUInt16Number)std::max(std::min(pix[2] * 65535.f, 65535.f), 0.f);
+ cmsDoTransform(data->to_PCS16, out, out, 1);
+ return 1;
+}
+
+static cmsInt32Number PCS2Display_Sampler16(const cmsUInt16Number in[], cmsUInt16Number out[], void* userdata)
+{
+ //std::cout << "r" << in[0] << " g" << in[1] << " b" << in[2] << "\n";
+ SamplerData* data = (SamplerData*) userdata;
+ cmsDoTransform(data->from_PCS16, in, out, 1);
+ // we don't have a reverse Lab -> Display transform
+ return 1;
+}
+} // anon namespace
+
+
+void SaveICCProfileToFile(const std::string & outputfile,
+ ConstProcessorRcPtr & processor,
+ int cubesize,
+ int whitepointtemp,
+ const std::string & displayicc,
+ const std::string & description,
+ const std::string & copyright,
+ bool verbose)
+{
+
+ // Create the ICC Profile
+
+ // Setup the Error Handler
+ cmsSetLogErrorHandler(ErrorHandler);
+
+ // D65 white point
+ cmsCIExyY whitePoint;
+ cmsWhitePointFromTemp(&whitePoint, whitepointtemp);
+
+ // LAB PCS
+ cmsHPROFILE labProfile = cmsCreateLab4ProfileTHR(NULL, &whitePoint);
+
+ // Display (OCIO sRGB cube -> LAB)
+ cmsHPROFILE DisplayProfile;
+ if(displayicc != "") DisplayProfile = cmsOpenProfileFromFile(displayicc.c_str(), "r");
+ else DisplayProfile = cmsCreate_sRGBProfileTHR(NULL);
+
+ // Create an empty RGB Profile
+ cmsHPROFILE hProfile = cmsCreateRGBProfileTHR(NULL, &whitePoint, NULL, NULL);
+
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Setting up Profile: " << outputfile << "\n";
+
+ // Added Header fields
+ cmsSetProfileVersion(hProfile, 4.2);
+ cmsSetDeviceClass(hProfile, cmsSigDisplayClass);
+ cmsSetColorSpace(hProfile, cmsSigRgbData);
+ cmsSetPCS(hProfile, cmsSigLabData);
+ cmsSetHeaderRenderingIntent(hProfile, INTENT_PERCEPTUAL);
+
+ //
+ cmsMLU* DescriptionMLU = cmsMLUalloc(NULL, 1);
+ cmsMLU* CopyrightMLU = cmsMLUalloc(NULL, 1);
+ cmsMLUsetASCII(DescriptionMLU, "en", "US", description.c_str());
+ cmsMLUsetASCII(CopyrightMLU, "en", "US", copyright.c_str());
+ cmsWriteTag(hProfile, cmsSigProfileDescriptionTag, DescriptionMLU);
+ cmsWriteTag(hProfile, cmsSigCopyrightTag, CopyrightMLU);
+
+ //
+ SamplerData data;
+ data.processor = processor;
+
+ // 16Bit
+ data.to_PCS16 = cmsCreateTransform(DisplayProfile, TYPE_RGB_16, labProfile, TYPE_LabV2_16,
+ INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
+ data.from_PCS16 = cmsCreateTransform(labProfile, TYPE_LabV2_16, DisplayProfile, TYPE_RGB_16,
+ INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
+
+ //
+ // AToB0Tag - Device to PCS (16-bit) intent of 0 (perceptual)
+ //
+ // cmsSigCurveSetElemType
+ // `- cmsSigCLutElemType
+ // `- cmsSigCurveSetElemType
+ // `- cmsSigMatrixElemType
+ // `- cmsSigCurveSetElemType
+ //
+
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Adding AToB0Tag\n";
+ cmsPipeline* AToB0Tag = cmsPipelineAlloc(NULL, 3, 3);
+
+ Add3GammaCurves(AToB0Tag, 1.f); // cmsSigCurveSetElemType
+
+ // cmsSigCLutElemType
+ cmsStage* AToB0Clut = cmsStageAllocCLut16bit(NULL, cubesize, 3, 3, NULL);
+
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Sampling AToB0 CLUT from Display to Lab\n";
+ cmsStageSampleCLut16bit(AToB0Clut, Display2PCS_Sampler16, &data, 0);
+ cmsPipelineInsertStage(AToB0Tag, cmsAT_END, AToB0Clut);
+
+ Add3GammaCurves(AToB0Tag, 1.f); // cmsSigCurveSetElemType
+ AddIdentityMatrix(AToB0Tag); // cmsSigMatrixElemType
+ Add3GammaCurves(AToB0Tag, 1.f); // cmsSigCurveSetElemType
+
+ // Add AToB0Tag
+ cmsWriteTag(hProfile, cmsSigAToB0Tag, AToB0Tag);
+ cmsPipelineFree(AToB0Tag);
+
+ //
+ // BToA0Tag - PCS to Device space (16-bit) intent of 0 (perceptual)
+ //
+ // cmsSigCurveSetElemType
+ // `- cmsSigMatrixElemType
+ // `- cmsSigCurveSetElemType
+ // `- cmsSigCLutElemType
+ // `- cmsSigCurveSetElemType
+ //
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Adding BToA0Tag\n";
+ cmsPipeline* BToA0Tag = cmsPipelineAlloc(NULL, 3, 3);
+
+ Add3GammaCurves(BToA0Tag, 1.f); // cmsSigCurveSetElemType
+ AddIdentityMatrix(BToA0Tag); // cmsSigMatrixElemType
+ Add3GammaCurves(BToA0Tag, 1.f); // cmsSigCurveSetElemType
+
+ // cmsSigCLutElemType
+ cmsStage* BToA0Clut = cmsStageAllocCLut16bit(NULL, cubesize, 3, 3, NULL);
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Sampling BToA0 CLUT from Lab to Display\n";
+ cmsStageSampleCLut16bit(BToA0Clut, PCS2Display_Sampler16, &data, 0);
+ cmsPipelineInsertStage(BToA0Tag, cmsAT_END, BToA0Clut);
+
+ Add3GammaCurves(BToA0Tag, 1.f); // cmsSigCurveSetElemType
+
+ // Add BToA0Tag
+ cmsWriteTag(hProfile, cmsSigBToA0Tag, BToA0Tag);
+ cmsPipelineFree(BToA0Tag);
+
+ //
+ // D2Bx - Device to PCS (float) (Not Yet Impl)
+ //
+
+ //
+ // B2Dx - PCS to Device (float) (Not Yet Impl)
+ //
+
+ //
+ // Write
+ //
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Writing " << outputfile << std::endl;
+ cmsSaveProfileToFile(hProfile, outputfile.c_str());
+ cmsCloseProfile(hProfile);
+
+ if(verbose)
+ std::cout << "[OpenColorIO INFO]: Finished\n";
+}
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/apps/ociobakelut/ocioicc.h b/src/apps/ociobakelut/ocioicc.h
new file mode 100644
index 0000000..030fbe3
--- /dev/null
+++ b/src/apps/ociobakelut/ocioicc.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_OCIOICC_H
+#define INCLUDED_OCIO_OCIOICC_H
+
+#include <string>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+OCIO_NAMESPACE_ENTER
+{
+
+//
+// Build an ICC profile for doing soft proofing
+//
+// N-component LUT-based display profile required tags
+// ------------------------------------------------------------------------------
+// Tag Name General Description
+// ------------------------------------------------------------------------------
+// profileDescriptionTag Structure containing invariant and localizable
+// versions of the profile name for display
+// AToB0Tag Device to PCS: 8-bit or 16-bit data: intent of 0
+// BToA0Tag PCS to Device space: 8-bit or 16-bit data: intent of 0
+// mediaWhitePointTag Media XYZ white point
+// copyrightTag Profile copyright information
+// chromaticAdaptationTag Converts XYZ colour from the actual illumination
+// source to PCS illuminant. Required only if the actual
+// illumination source is not D50.
+
+void SaveICCProfileToFile(const std::string & outputfile,
+ ConstProcessorRcPtr & processor,
+ int cubesize,
+ int whitepointtemp,
+ const std::string & displayicc,
+ const std::string & description,
+ const std::string & copyright,
+ bool verbose);
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
+
diff --git a/src/apps/ociocheck/CMakeLists.txt b/src/apps/ociocheck/CMakeLists.txt
new file mode 100644
index 0000000..f8902e4
--- /dev/null
+++ b/src/apps/ociocheck/CMakeLists.txt
@@ -0,0 +1,17 @@
+file(GLOB_RECURSE share_src_files "${CMAKE_SOURCE_DIR}/src/apps/share/*.cpp")
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${CMAKE_SOURCE_DIR}/src/apps/share/
+ )
+
+add_executable(ociocheck
+ main.cpp
+ ${share_src_files})
+
+target_link_libraries(ociocheck
+ OpenColorIO
+ )
+
+install(TARGETS ociocheck DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/bin)
diff --git a/src/apps/ociocheck/main.cpp b/src/apps/ociocheck/main.cpp
new file mode 100644
index 0000000..725985e
--- /dev/null
+++ b/src/apps/ociocheck/main.cpp
@@ -0,0 +1,301 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <set>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+#include "argparse.h"
+
+
+const char * DESC_STRING = "\n\n"
+"ociocheck is useful to validate that the specified .ocio configuration\n"
+"is valid, and that all the color transforms are defined.\n"
+"For example, it is possible that the configuration may reference\n"
+"lookup tables that do not exist. ociocheck will find these cases.\n\n"
+"ociocheck can also be used to clean up formatting on an existing profile\n"
+"that has been manually edited, using the '-o' option.\n";
+
+int main(int argc, const char **argv)
+{
+ bool help = false;
+ int errorcount = 0;
+ std::string inputconfig;
+ std::string outputconfig;
+
+ ArgParse ap;
+ ap.options("ociocheck -- validate an OpenColorIO configuration\n\n"
+ "usage: ociocheck [options]\n",
+ "--help", &help, "Print help message",
+ "--iconfig %s", &inputconfig, "Input .ocio configuration file (default: $OCIO)",
+ "--oconfig %s", &outputconfig, "Output .ocio file",
+ NULL);
+
+ if (ap.parse(argc, argv) < 0)
+ {
+ std::cout << ap.geterror() << std::endl;
+ ap.usage();
+ std::cout << DESC_STRING;
+ return 1;
+ }
+
+ if (help)
+ {
+ ap.usage();
+ std::cout << DESC_STRING;
+ return 1;
+ }
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config;
+
+ std::cout << std::endl;
+ std::cout << "OpenColorIO Library Version: " << OCIO::GetVersion() << std::endl;
+ std::cout << "OpenColorIO Library VersionHex: " << OCIO::GetVersionHex() << std::endl;
+
+ if(!inputconfig.empty())
+ {
+ std::cout << "Loading " << inputconfig << std::endl;
+ config = OCIO::Config::CreateFromFile(inputconfig.c_str());
+ }
+ else if(getenv("OCIO"))
+ {
+ std::cout << "Loading $OCIO " << getenv("OCIO") << std::endl;
+ config = OCIO::Config::CreateFromEnv();
+ }
+ else
+ {
+ std::cout << "ERROR: You must specify an input ocio configuration ";
+ std::cout << "(either with --iconfig or $OCIO).\n";
+ ap.usage ();
+ std::cout << DESC_STRING;
+ return 1;
+ }
+
+ std::cout << std::endl;
+ std::cout << "** General **" << std::endl;
+ std::cout << "Search Path: " << config->getSearchPath() << std::endl;
+ std::cout << "Working Dir: " << config->getWorkingDir() << std::endl;
+
+ std::cout << std::endl;
+ std::cout << "Default Display: " << config->getDefaultDisplay() << std::endl;
+ std::cout << "Default View: " << config->getDefaultView(config->getDefaultDisplay()) << std::endl;
+
+ {
+ std::cout << std::endl;
+ std::cout << "** Roles **" << std::endl;
+
+ std::set<std::string> usedroles;
+ const char * allroles[] = { OCIO::ROLE_DEFAULT, OCIO::ROLE_SCENE_LINEAR,
+ OCIO::ROLE_DATA, OCIO::ROLE_REFERENCE,
+ OCIO::ROLE_COMPOSITING_LOG, OCIO::ROLE_COLOR_TIMING,
+ OCIO::ROLE_COLOR_PICKING,
+ OCIO::ROLE_TEXTURE_PAINT, OCIO::ROLE_MATTE_PAINT,
+ NULL };
+ int MAXROLES=256;
+ for(int i=0;i<MAXROLES; ++i)
+ {
+ const char * role = allroles[i];
+ if(!role) break;
+ usedroles.insert(role);
+
+ OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(role);
+ if(cs)
+ {
+ std::cout << cs->getName() << " (" << role << ")" << std::endl;
+ }
+ else
+ {
+ std::cout << "ERROR: NOT DEFINED" << " (" << role << ")" << std::endl;
+ errorcount += 1;
+ }
+ }
+
+ for(int i=0; i<config->getNumRoles(); ++i)
+ {
+ const char * role = config->getRoleName(i);
+ if(usedroles.find(role) != usedroles.end()) continue;
+
+ OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(role);
+ if(cs)
+ {
+ std::cout << cs->getName() << " (" << role << ": user)" << std::endl;
+ }
+ else
+ {
+ std::cout << "ERROR: NOT DEFINED" << " (" << role << ")" << std::endl;
+ errorcount += 1;
+ }
+
+ }
+ }
+
+ std::cout << std::endl;
+ std::cout << "** ColorSpaces **" << std::endl;
+ OCIO::ConstColorSpaceRcPtr lin = config->getColorSpace(OCIO::ROLE_SCENE_LINEAR);
+ if(!lin)
+ {
+ std::cout << "Error: scene_linear role must be defined." << std::endl;
+ errorcount += 1;
+ }
+ else
+ {
+ for(int i=0; i<config->getNumColorSpaces(); ++i)
+ {
+ OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(config->getColorSpaceNameByIndex(i));
+
+ bool convertsToLinear = true;
+ std::string convertsToLinearErrorText;
+
+ bool convertsFromLinear = true;
+ std::string convertsFromLinearErrorText;
+
+ try
+ {
+ OCIO::ConstProcessorRcPtr p = config->getProcessor(cs, lin);
+ }
+ catch(OCIO::Exception & exception)
+ {
+ convertsToLinear = false;
+ convertsToLinearErrorText = exception.what();
+ }
+
+ try
+ {
+ OCIO::ConstProcessorRcPtr p = config->getProcessor(lin, cs);
+ }
+ catch(OCIO::Exception & exception)
+ {
+ convertsFromLinear = false;
+ convertsFromLinearErrorText = exception.what();
+ }
+
+ if(convertsToLinear && convertsFromLinear)
+ {
+ std::cout << cs->getName() << std::endl;
+ }
+ else if(!convertsToLinear && !convertsFromLinear)
+ {
+ std::cout << cs->getName();
+ std::cout << " -- error" << std::endl;
+ std::cout << "\t" << convertsToLinearErrorText << std::endl;
+ std::cout << "\t" << convertsFromLinearErrorText << std::endl;
+
+ errorcount += 1;
+ }
+ else if(convertsToLinear)
+ {
+ std::cout << cs->getName();
+ std::cout << " -- input only" << std::endl;
+ }
+ else if(convertsFromLinear)
+ {
+ std::cout << cs->getName();
+ std::cout << " -- output only" << std::endl;
+ }
+ }
+ }
+
+ std::cout << std::endl;
+ std::cout << "** Looks **" << std::endl;
+ if(config->getNumLooks()>0)
+ {
+ for(int i=0; i<config->getNumLooks(); ++i)
+ {
+ std::cout << config->getLookNameByIndex(i) << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "no looks defined" << std::endl;
+ }
+ std::cout << std::endl;
+ std::cout << "** Sanity Check **" << std::endl;
+
+ try
+ {
+ config->sanityCheck();
+ std::cout << "passed" << std::endl;
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cout << "ERROR" << std::endl;
+ errorcount += 1;
+ std::cout << exception.what() << std::endl;
+ }
+
+ if(!outputconfig.empty())
+ {
+ std::ofstream output;
+ output.open(outputconfig.c_str());
+
+ if(!output.is_open())
+ {
+ std::cout << "Error opening " << outputconfig << " for writing." << std::endl;
+ }
+ else
+ {
+ config->serialize(output);
+ output.close();
+ std::cout << "Wrote " << outputconfig << std::endl;
+ }
+ }
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cout << "ERROR: " << exception.what() << std::endl;
+ return 1;
+ } catch (std::exception& exception) {
+ std::cout << "ERROR: " << exception.what() << "\n";
+ return 1;
+ }
+ catch(...)
+ {
+ std::cout << "Unknown error encountered." << std::endl;
+ return 1;
+ }
+
+
+ std::cout << std::endl;
+ if(errorcount == 0)
+ {
+ std::cout << "Tests complete." << std::endl << std::endl;
+ return 0;
+ }
+ else
+ {
+ std::cout << errorcount << " tests failed." << std::endl << std::endl;
+ return 1;
+ }
+}
diff --git a/src/apps/ocioconvert/CMakeLists.txt b/src/apps/ocioconvert/CMakeLists.txt
new file mode 100644
index 0000000..5c5eb76
--- /dev/null
+++ b/src/apps/ocioconvert/CMakeLists.txt
@@ -0,0 +1,16 @@
+if (OIIO_FOUND)
+ include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${CMAKE_SOURCE_DIR}/src/apps/share/
+ ${OIIO_INCLUDES}
+ )
+
+ file(GLOB_RECURSE share_src_files "${CMAKE_SOURCE_DIR}/src/apps/share/*.cpp")
+
+ add_executable(ocioconvert ${share_src_files} main.cpp)
+
+ target_link_libraries(ocioconvert ${OIIO_LIBRARIES} OpenColorIO dl)
+
+ install(TARGETS ocioconvert DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/bin)
+endif()
diff --git a/src/apps/ocioconvert/main.cpp b/src/apps/ocioconvert/main.cpp
new file mode 100644
index 0000000..32a3c34
--- /dev/null
+++ b/src/apps/ocioconvert/main.cpp
@@ -0,0 +1,309 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <OpenImageIO/imageio.h>
+#include <OpenImageIO/typedesc.h>
+#if (OIIO_VERSION < 10100)
+namespace OIIO = OIIO_NAMESPACE;
+#endif
+
+
+#include "argparse.h"
+
+// array of non openimageIO arguments
+static std::vector<std::string> args;
+
+
+// fill 'args' array with openimageIO arguments
+static int
+parse_end_args(int argc, const char *argv[])
+{
+ while(argc>0)
+ {
+ args.push_back(argv[0]);
+ argc--;
+ argv++;
+ }
+
+ return 0;
+}
+
+
+bool ParseNameValuePair(std::string& name, std::string& value,
+ const std::string& input);
+
+bool StringToFloat(float * fval, const char * str);
+
+bool StringToInt(int * ival, const char * str);
+
+int main(int argc, const char **argv)
+{
+ ArgParse ap;
+
+ std::vector<std::string> floatAttrs;
+ std::vector<std::string> intAttrs;
+ std::vector<std::string> stringAttrs;
+
+ ap.options("ocioconvert -- apply colorspace transform to an image \n\n"
+ "usage: ocioconvert [options] inputimage inputcolorspace outputimage outputcolorspace\n\n",
+ "%*", parse_end_args, "",
+ "<SEPARATOR>", "OpenImageIO options",
+ "--float-attribute %L", &floatAttrs, "name=float pair defining OIIO float attribute",
+ "--int-attribute %L", &intAttrs, "name=int pair defining OIIO int attribute",
+ "--string-attribute %L", &stringAttrs, "name=string pair defining OIIO string attribute",
+ NULL
+ );
+ if (ap.parse (argc, argv) < 0) {
+ std::cerr << ap.geterror() << std::endl;
+ ap.usage ();
+ exit(1);
+ }
+
+ if(args.size()!=4)
+ {
+ ap.usage();
+ exit(1);
+ }
+
+ const char * inputimage = args[0].c_str();
+ const char * inputcolorspace = args[1].c_str();
+ const char * outputimage = args[2].c_str();
+ const char * outputcolorspace = args[3].c_str();
+
+ OIIO::ImageSpec spec;
+ std::vector<float> img;
+ int imgwidth = 0;
+ int imgheight = 0;
+ int components = 0;
+
+
+ // Load the image
+ std::cerr << "Loading " << inputimage << std::endl;
+ try
+ {
+ OIIO::ImageInput* f = OIIO::ImageInput::create(inputimage);
+ if(!f)
+ {
+ std::cerr << "Could not create image input." << std::endl;
+ exit(1);
+ }
+
+ f->open(inputimage, spec);
+
+ std::string error = f->geterror();
+ if(!error.empty())
+ {
+ std::cerr << "Error loading image " << error << std::endl;
+ exit(1);
+ }
+
+ imgwidth = spec.width;
+ imgheight = spec.height;
+ components = spec.nchannels;
+
+ img.resize(imgwidth*imgheight*components);
+ memset(&img[0], 0, imgwidth*imgheight*components*sizeof(float));
+
+ f->read_image(OIIO::TypeDesc::TypeFloat, &img[0]);
+ delete f;
+
+ }
+ catch(...)
+ {
+ std::cerr << "Error loading file.";
+ exit(1);
+ }
+
+ // Process the image
+ try
+ {
+ // Load the current config.
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ // Get the processor
+ OCIO::ConstProcessorRcPtr processor = config->getProcessor(inputcolorspace, outputcolorspace);
+
+ // Wrap the image in a light-weight ImageDescription
+ OCIO::PackedImageDesc imageDesc(&img[0], imgwidth, imgheight, components);
+
+ // Apply the color transformation (in place)
+ processor->apply(imageDesc);
+ }
+ catch(OCIO::Exception & exception)
+ {
+ std::cerr << "OCIO Error: " << exception.what() << std::endl;
+ exit(1);
+ }
+ catch(...)
+ {
+ std::cerr << "Unknown OCIO error encountered." << std::endl;
+ exit(1);
+ }
+
+
+
+ //
+ // set the provided OpenImageIO attributes
+ //
+ bool parseerror = false;
+ for(unsigned int i=0; i<floatAttrs.size(); ++i)
+ {
+ std::string name, value;
+ float fval = 0.0f;
+
+ if(!ParseNameValuePair(name, value, floatAttrs[i]) ||
+ !StringToFloat(&fval,value.c_str()))
+ {
+ std::cerr << "Error: attribute string '" << floatAttrs[i] << "' should be in the form name=floatvalue\n";
+ parseerror = true;
+ continue;
+ }
+
+ spec.attribute(name, fval);
+ }
+
+ for(unsigned int i=0; i<intAttrs.size(); ++i)
+ {
+ std::string name, value;
+ int ival = 0;
+ if(!ParseNameValuePair(name, value, intAttrs[i]) ||
+ !StringToInt(&ival,value.c_str()))
+ {
+ std::cerr << "Error: attribute string '" << intAttrs[i] << "' should be in the form name=intvalue\n";
+ parseerror = true;
+ continue;
+ }
+
+ spec.attribute(name, ival);
+ }
+
+ for(unsigned int i=0; i<stringAttrs.size(); ++i)
+ {
+ std::string name, value;
+ if(!ParseNameValuePair(name, value, stringAttrs[i]))
+ {
+ std::cerr << "Error: attribute string '" << stringAttrs[i] << "' should be in the form name=value\n";
+ parseerror = true;
+ continue;
+ }
+
+ spec.attribute(name, value);
+ }
+
+ if(parseerror)
+ {
+ exit(1);
+ }
+
+
+
+
+ // Write out the result
+ try
+ {
+ OIIO::ImageOutput* f = OIIO::ImageOutput::create(outputimage);
+ if(!f)
+ {
+ std::cerr << "Could not create output input." << std::endl;
+ exit(1);
+ }
+
+ f->open(outputimage, spec);
+ f->write_image(OIIO::TypeDesc::FLOAT, &img[0]);
+ f->close();
+ delete f;
+ }
+ catch(...)
+ {
+ std::cerr << "Error loading file.";
+ exit(1);
+ }
+
+ std::cerr << "Wrote " << outputimage << std::endl;
+
+ return 0;
+}
+
+
+// Parse name=value parts
+// return true on success
+
+bool ParseNameValuePair(std::string& name,
+ std::string& value,
+ const std::string& input)
+{
+ // split string into name=value
+ size_t pos = input.find('=');
+ if(pos==std::string::npos) return false;
+
+ name = input.substr(0,pos);
+ value = input.substr(pos+1);
+ return true;
+}
+
+// return true on success
+bool StringToFloat(float * fval, const char * str)
+{
+ if(!str) return false;
+
+ std::istringstream inputStringstream(str);
+ float x;
+ if(!(inputStringstream >> x))
+ {
+ return false;
+ }
+
+ if(fval) *fval = x;
+ return true;
+}
+
+bool StringToInt(int * ival, const char * str)
+{
+ if(!str) return false;
+
+ std::istringstream inputStringstream(str);
+ int x;
+ if(!(inputStringstream >> x))
+ {
+ return false;
+ }
+
+ if(ival) *ival = x;
+ return true;
+}
+
+
+
+
diff --git a/src/apps/ociodisplay/CMakeLists.txt b/src/apps/ociodisplay/CMakeLists.txt
new file mode 100644
index 0000000..e80e9f9
--- /dev/null
+++ b/src/apps/ociodisplay/CMakeLists.txt
@@ -0,0 +1,11 @@
+include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${OPENGL_INCLUDE_DIR}
+ ${OIIO_INCLUDES}
+ ${GLEW_INCLUDES}
+)
+add_executable(ociodisplay main.cpp)
+# set_target_properties(ociodisplay PROPERTIES INSTALL_RPATH ${OIIO_LIBRARIES} )
+target_link_libraries(ociodisplay ${GLEW_LIBRARIES} ${GLUT_LIBRARY} ${OPENGL_LIBRARY} ${OIIO_LIBRARIES} OpenColorIO)
+install(TARGETS ociodisplay DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/bin)
diff --git a/src/apps/ociodisplay/main.cpp b/src/apps/ociodisplay/main.cpp
new file mode 100644
index 0000000..1b7f5a6
--- /dev/null
+++ b/src/apps/ociodisplay/main.cpp
@@ -0,0 +1,734 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <cstdlib>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <vector>
+
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glext.h>
+#include <GLUT/glut.h>
+#else
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glut.h>
+#endif
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <OpenImageIO/imageio.h>
+#include <OpenImageIO/typedesc.h>
+#if (OIIO_VERSION < 10100)
+namespace OIIO = OIIO_NAMESPACE;
+#endif
+
+GLint g_win = 0;
+int g_winWidth = 0;
+int g_winHeight = 0;
+
+GLuint g_fragShader = 0;
+GLuint g_program = 0;
+
+GLuint g_imageTexID;
+float g_imageAspect;
+
+GLuint g_lut3dTexID;
+const int LUT3D_EDGE_SIZE = 32;
+std::vector<float> g_lut3d;
+std::string g_lut3dcacheid;
+std::string g_shadercacheid;
+
+std::string g_inputColorSpace;
+std::string g_display;
+std::string g_transformName;
+
+float g_exposure_fstop = 0.0f;
+float g_display_gamma = 1.0f;
+int g_channelHot[4] = { 1, 1, 1, 1 }; // show rgb
+
+
+void UpdateOCIOGLState();
+
+static void InitImageTexture(const char * filename)
+{
+ glGenTextures(1, &g_imageTexID);
+
+ std::vector<float> img;
+ int texWidth = 512;
+ int texHeight = 512;
+ int components = 4;
+
+ if(filename)
+ {
+ std::cout << "loading: " << filename << std::endl;
+ try
+ {
+ OIIO::ImageInput* f = OIIO::ImageInput::create(filename);
+ if(!f)
+ {
+ std::cerr << "Could not create image input." << std::endl;
+ exit(1);
+ }
+
+ OIIO::ImageSpec spec;
+ f->open(filename, spec);
+
+ std::string error = f->geterror();
+ if(!error.empty())
+ {
+ std::cerr << "Error loading image " << error << std::endl;
+ exit(1);
+ }
+
+ texWidth = spec.width;
+ texHeight = spec.height;
+ components = spec.nchannels;
+
+ img.resize(texWidth*texHeight*components);
+ memset(&img[0], 0, texWidth*texHeight*components*sizeof(float));
+
+ f->read_image(OIIO::TypeDesc::TypeFloat, &img[0]);
+ delete f;
+ }
+ catch(...)
+ {
+ std::cerr << "Error loading file.";
+ exit(1);
+ }
+ }
+ // If no file is provided, use a default gradient texture
+ else
+ {
+ std::cout << "No image specified, loading gradient." << std::endl;
+
+ img.resize(texWidth*texHeight*components);
+ memset(&img[0], 0, texWidth*texHeight*components*sizeof(float));
+
+ for(int y=0; y<texHeight; ++y)
+ {
+ for(int x=0; x<texWidth; ++x)
+ {
+ float c = (float)x/((float)texWidth-1.0f);
+ img[components*(texWidth*y+x) + 0] = c;
+ img[components*(texWidth*y+x) + 1] = c;
+ img[components*(texWidth*y+x) + 2] = c;
+ img[components*(texWidth*y+x) + 3] = 1.0f;
+ }
+ }
+ }
+
+
+ GLenum format = 0;
+ if(components == 4) format = GL_RGBA;
+ else if(components == 3) format = GL_RGB;
+ else
+ {
+ std::cerr << "Cannot load image with " << components << " components." << std::endl;
+ exit(1);
+ }
+
+ g_imageAspect = 1.0;
+ if(texHeight!=0)
+ {
+ g_imageAspect = (float) texWidth / (float) texHeight;
+ }
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, g_imageTexID);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, texWidth, texHeight, 0,
+ format, GL_FLOAT, &img[0]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+}
+
+void InitOCIO(const char * filename)
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ g_display = config->getDefaultDisplay();
+ g_transformName = config->getDefaultView(g_display.c_str());
+
+ g_inputColorSpace = OCIO::ROLE_SCENE_LINEAR;
+ if(filename)
+ {
+ std::string cs = config->parseColorSpaceFromString(filename);
+ if(!cs.empty())
+ {
+ g_inputColorSpace = cs;
+ std::cout << "colorspace: " << cs << std::endl;
+ }
+ else
+ {
+ std::cout << "colorspace: " << g_inputColorSpace << " \t(could not determine from filename, using default)" << std::endl;
+ }
+ }
+}
+
+static void AllocateLut3D()
+{
+ glGenTextures(1, &g_lut3dTexID);
+
+ int num3Dentries = 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE;
+ g_lut3d.resize(num3Dentries);
+ memset(&g_lut3d[0], 0, sizeof(float)*num3Dentries);
+
+ glActiveTexture(GL_TEXTURE2);
+
+ glBindTexture(GL_TEXTURE_3D, g_lut3dTexID);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
+ LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+ 0, GL_RGB,GL_FLOAT, &g_lut3d[0]);
+}
+
+/*
+static void
+Idle(void)
+{
+ // + Do Work
+ glutPostRedisplay();
+}
+*/
+
+void Redisplay(void)
+{
+ float windowAspect = 1.0;
+ if(g_winHeight != 0)
+ {
+ windowAspect = (float)g_winWidth/(float)g_winHeight;
+ }
+
+ float pts[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; // x0,y0,x1,y1
+ if(windowAspect>g_imageAspect)
+ {
+ float imgWidthScreenSpace = g_imageAspect * (float)g_winHeight;
+ pts[0] = (float)g_winWidth * 0.5f - (float)imgWidthScreenSpace * 0.5f;
+ pts[2] = (float)g_winWidth * 0.5f + (float)imgWidthScreenSpace * 0.5f;
+ pts[1] = 0.0f;
+ pts[3] = (float)g_winHeight;
+ }
+ else
+ {
+ float imgHeightScreenSpace = (float)g_winWidth / g_imageAspect;
+ pts[0] = 0.0f;
+ pts[2] = (float)g_winWidth;
+ pts[1] = (float)g_winHeight * 0.5f - imgHeightScreenSpace * 0.5f;
+ pts[3] = (float)g_winHeight * 0.5f + imgHeightScreenSpace * 0.5f;
+ }
+
+ glEnable(GL_TEXTURE_2D);
+ glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glColor3f(1, 1, 1);
+
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2f(pts[0], pts[1]);
+
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2f(pts[0], pts[3]);
+
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2f(pts[2], pts[3]);
+
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2f(pts[2], pts[1]);
+
+ glEnd();
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D);
+
+ glutSwapBuffers();
+}
+
+
+static void Reshape(int width, int height)
+{
+ g_winWidth = width;
+ g_winHeight = height;
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, g_winWidth, 0.0, g_winHeight, -100.0, 100.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+
+static void CleanUp(void)
+{
+ glDeleteShader(g_fragShader);
+ glDeleteProgram(g_program);
+ glutDestroyWindow(g_win);
+}
+
+
+static void Key(unsigned char key, int /*x*/, int /*y*/)
+{
+ if(key == 'c' || key == 'C')
+ {
+ g_channelHot[0] = 1;
+ g_channelHot[1] = 1;
+ g_channelHot[2] = 1;
+ g_channelHot[3] = 1;
+ }
+ else if(key == 'r' || key == 'R')
+ {
+ g_channelHot[0] = 1;
+ g_channelHot[1] = 0;
+ g_channelHot[2] = 0;
+ g_channelHot[3] = 0;
+ }
+ else if(key == 'g' || key == 'G')
+ {
+ g_channelHot[0] = 0;
+ g_channelHot[1] = 1;
+ g_channelHot[2] = 0;
+ g_channelHot[3] = 0;
+ }
+ else if(key == 'b' || key == 'B')
+ {
+ g_channelHot[0] = 0;
+ g_channelHot[1] = 0;
+ g_channelHot[2] = 1;
+ g_channelHot[3] = 0;
+ }
+ else if(key == 'a' || key == 'A')
+ {
+ g_channelHot[0] = 0;
+ g_channelHot[1] = 0;
+ g_channelHot[2] = 0;
+ g_channelHot[3] = 1;
+ }
+ else if(key == 'l' || key == 'L')
+ {
+ g_channelHot[0] = 1;
+ g_channelHot[1] = 1;
+ g_channelHot[2] = 1;
+ g_channelHot[3] = 0;
+ }
+ else if(key == 27)
+ {
+ CleanUp();
+ exit(0);
+ }
+
+ UpdateOCIOGLState();
+ glutPostRedisplay();
+}
+
+
+static void SpecialKey(int key, int x, int y)
+{
+ (void) x;
+ (void) y;
+
+ int mod = glutGetModifiers();
+
+ if(key == GLUT_KEY_UP && (mod & GLUT_ACTIVE_CTRL))
+ {
+ g_exposure_fstop += 0.25f;
+ }
+ else if(key == GLUT_KEY_DOWN && (mod & GLUT_ACTIVE_CTRL))
+ {
+ g_exposure_fstop -= 0.25f;
+ }
+ else if(key == GLUT_KEY_HOME && (mod & GLUT_ACTIVE_CTRL))
+ {
+ g_exposure_fstop = 0.0f;
+ g_display_gamma = 1.0f;
+ }
+
+ else if(key == GLUT_KEY_UP && (mod & GLUT_ACTIVE_ALT))
+ {
+ g_display_gamma *= 1.1f;
+ }
+ else if(key == GLUT_KEY_DOWN && (mod & GLUT_ACTIVE_ALT))
+ {
+ g_display_gamma /= 1.1f;
+ }
+ else if(key == GLUT_KEY_HOME && (mod & GLUT_ACTIVE_ALT))
+ {
+ g_exposure_fstop = 0.0f;
+ g_display_gamma = 1.0f;
+ }
+
+ UpdateOCIOGLState();
+
+ glutPostRedisplay();
+}
+
+GLuint
+CompileShaderText(GLenum shaderType, const char *text)
+{
+ GLuint shader;
+ GLint stat;
+
+ shader = glCreateShader(shaderType);
+ glShaderSource(shader, 1, (const GLchar **) &text, NULL);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
+
+ if (!stat)
+ {
+ GLchar log[1000];
+ GLsizei len;
+ glGetShaderInfoLog(shader, 1000, &len, log);
+ fprintf(stderr, "Error: problem compiling shader: %s\n", log);
+ return 0;
+ }
+
+ return shader;
+}
+
+GLuint
+LinkShaders(GLuint fragShader)
+{
+ if (!fragShader) return 0;
+
+ GLuint program = glCreateProgram();
+
+ if (fragShader)
+ glAttachShader(program, fragShader);
+
+ glLinkProgram(program);
+
+ /* check link */
+ {
+ GLint stat;
+ glGetProgramiv(program, GL_LINK_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetProgramInfoLog(program, 1000, &len, log);
+ fprintf(stderr, "Shader link error:\n%s\n", log);
+ return 0;
+ }
+ }
+
+ return program;
+}
+
+const char * g_fragShaderText = ""
+"\n"
+"uniform sampler2D tex1;\n"
+"uniform sampler3D tex2;\n"
+"\n"
+"void main()\n"
+"{\n"
+" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
+" gl_FragColor = OCIODisplay(col, tex2);\n"
+"}\n";
+
+
+void UpdateOCIOGLState()
+{
+ // Step 0: Get the processor using any of the pipelines mentioned above.
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
+ transform->setInputColorSpaceName( g_inputColorSpace.c_str() );
+ transform->setDisplay( g_display.c_str() );
+ transform->setView( g_transformName.c_str() );
+
+ // Add optional transforms to create a full-featured, "canonical" display pipeline
+ // Fstop exposure control (in SCENE_LINEAR)
+ {
+ float gain = powf(2.0f, g_exposure_fstop);
+ const float slope4f[] = { gain, gain, gain, gain };
+ float m44[16];
+ float offset4[4];
+ OCIO::MatrixTransform::Scale(m44, offset4, slope4f);
+ OCIO::MatrixTransformRcPtr mtx = OCIO::MatrixTransform::Create();
+ mtx->setValue(m44, offset4);
+ transform->setLinearCC(mtx);
+ }
+
+ // Channel swizzling
+ {
+ float lumacoef[3];
+ config->getDefaultLumaCoefs(lumacoef);
+ float m44[16];
+ float offset[4];
+ OCIO::MatrixTransform::View(m44, offset, g_channelHot, lumacoef);
+ OCIO::MatrixTransformRcPtr swizzle = OCIO::MatrixTransform::Create();
+ swizzle->setValue(m44, offset);
+ transform->setChannelView(swizzle);
+ }
+
+ // Post-display transform gamma
+ {
+ float exponent = 1.0f/std::max(1e-6f, static_cast<float>(g_display_gamma));
+ const float exponent4f[] = { exponent, exponent, exponent, exponent };
+ OCIO::ExponentTransformRcPtr expTransform = OCIO::ExponentTransform::Create();
+ expTransform->setValue(exponent4f);
+ transform->setDisplayCC(expTransform);
+ }
+
+ OCIO::ConstProcessorRcPtr processor;
+ try
+ {
+ processor = config->getProcessor(transform);
+ }
+ catch(OCIO::Exception & e)
+ {
+ std::cerr << e.what() << std::endl;
+ return;
+ }
+ catch(...)
+ {
+ return;
+ }
+
+ // Step 1: Create a GPU Shader Description
+ OCIO::GpuShaderDesc shaderDesc;
+ shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
+ shaderDesc.setFunctionName("OCIODisplay");
+ shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+
+ // Step 2: Compute the 3D LUT
+ std::string lut3dCacheID = processor->getGpuLut3DCacheID(shaderDesc);
+ if(lut3dCacheID != g_lut3dcacheid)
+ {
+ //std::cerr << "Computing 3DLut " << g_lut3dcacheid << std::endl;
+
+ g_lut3dcacheid = lut3dCacheID;
+ processor->getGpuLut3D(&g_lut3d[0], shaderDesc);
+
+ glBindTexture(GL_TEXTURE_3D, g_lut3dTexID);
+ glTexSubImage3D(GL_TEXTURE_3D, 0,
+ 0, 0, 0,
+ LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
+ GL_RGB,GL_FLOAT, &g_lut3d[0]);
+ }
+
+ // Step 3: Compute the Shader
+ std::string shaderCacheID = processor->getGpuShaderTextCacheID(shaderDesc);
+ if(g_program == 0 || shaderCacheID != g_shadercacheid)
+ {
+ //std::cerr << "Computing Shader " << g_shadercacheid << std::endl;
+
+ g_shadercacheid = shaderCacheID;
+
+ std::ostringstream os;
+ os << processor->getGpuShaderText(shaderDesc) << "\n";
+ os << g_fragShaderText;
+ //std::cerr << os.str() << std::endl;
+
+ if(g_fragShader) glDeleteShader(g_fragShader);
+ g_fragShader = CompileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+ if(g_program) glDeleteProgram(g_program);
+ g_program = LinkShaders(g_fragShader);
+ }
+
+ glUseProgram(g_program);
+ glUniform1i(glGetUniformLocation(g_program, "tex1"), 1);
+ glUniform1i(glGetUniformLocation(g_program, "tex2"), 2);
+}
+
+void menuCallback(int /*id*/)
+{
+ glutPostRedisplay();
+}
+
+void imageColorSpace_CB(int id)
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ const char * name = config->getColorSpaceNameByIndex(id);
+ if(!name) return;
+
+ g_inputColorSpace = name;
+
+ UpdateOCIOGLState();
+ glutPostRedisplay();
+}
+
+void displayDevice_CB(int id)
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ const char * display = config->getDisplay(id);
+ if(!display) return;
+
+ g_display = display;
+
+ const char * csname = config->getDisplayColorSpaceName(g_display.c_str(), g_transformName.c_str());
+ if(!csname)
+ {
+ g_transformName = config->getDefaultView(g_display.c_str());
+ }
+
+ UpdateOCIOGLState();
+ glutPostRedisplay();
+}
+
+void transform_CB(int id)
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ const char * transform = config->getView(g_display.c_str(), id);
+ if(!transform) return;
+
+ g_transformName = transform;
+
+ UpdateOCIOGLState();
+ glutPostRedisplay();
+}
+
+static void PopulateOCIOMenus()
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+
+ int csMenuID = glutCreateMenu(imageColorSpace_CB);
+ for(int i=0; i<config->getNumColorSpaces(); ++i)
+ {
+ glutAddMenuEntry(config->getColorSpaceNameByIndex(i), i);
+ }
+
+ int deviceMenuID = glutCreateMenu(displayDevice_CB);
+ for(int i=0; i<config->getNumDisplays(); ++i)
+ {
+ glutAddMenuEntry(config->getDisplay(i), i);
+ }
+
+ int transformMenuID = glutCreateMenu(transform_CB);
+ const char * defaultDisplay = config->getDefaultDisplay();
+ for(int i=0; i<config->getNumViews(defaultDisplay); ++i)
+ {
+ glutAddMenuEntry(config->getView(defaultDisplay, i), i);
+ }
+
+ glutCreateMenu(menuCallback);
+ glutAddSubMenu("Image ColorSpace", csMenuID);
+ glutAddSubMenu("Transform", transformMenuID);
+ glutAddSubMenu("Device", deviceMenuID);
+
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+const char * USAGE_TEXT = "\n"
+"Keys:\n"
+"\tCtrl+Up: Exposure +1/4 stop (in scene linear)\n"
+"\tCtrl+Down: Exposure -1/4 stop (in scene linear)\n"
+"\tCtrl+Home: Reset Exposure + Gamma\n"
+"\n"
+"\tAlt+Up: Gamma up (post display transform)\n"
+"\tAlt+Down: Gamma down (post display transform)\n"
+"\tAlt+Home: Reset Exposure + Gamma\n"
+"\n"
+"\tC: View Color\n"
+"\tR: View Red \n"
+"\tG: View Green\n"
+"\tB: View Blue\n"
+"\tA: View Alpha\n"
+"\tL: View Luma\n"
+"\n"
+"\tRight-Mouse Button: Configure Display / Transform / ColorSpace\n"
+"\n"
+"\tEsc: Quit\n";
+
+int main(int argc, char **argv)
+{
+ glutInit(&argc, argv);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+ glutInitWindowSize(512, 512);
+ glutInitWindowPosition (100, 100);
+
+ g_win = glutCreateWindow(argv[0]);
+
+#ifndef __APPLE__
+ glewInit();
+ if (!glewIsSupported("GL_VERSION_2_0"))
+ {
+ printf("OpenGL 2.0 not supported\n");
+ exit(1);
+ }
+#endif
+
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutSpecialFunc(SpecialKey);
+ glutDisplayFunc(Redisplay);
+
+ const char * filename = 0;
+ if(argc>1) filename = argv[1];
+
+ std::cout << USAGE_TEXT << std::endl;
+
+ // TODO: switch profiles based on shading language
+ // std::cout << "GL_SHADING_LANGUAGE_VERSION: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
+ AllocateLut3D();
+
+ InitImageTexture(filename);
+ try
+ {
+ InitOCIO(filename);
+ }
+ catch(OCIO::Exception & e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(1);
+ }
+
+ PopulateOCIOMenus();
+
+ Reshape(1024, 512);
+
+ UpdateOCIOGLState();
+
+ Redisplay();
+
+ /*
+ if (Anim)
+ {
+ glutIdleFunc(Idle);
+ }
+ */
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/src/apps/ociolutimage/CMakeLists.txt b/src/apps/ociolutimage/CMakeLists.txt
new file mode 100644
index 0000000..86bc0e7
--- /dev/null
+++ b/src/apps/ociolutimage/CMakeLists.txt
@@ -0,0 +1,16 @@
+if (OIIO_FOUND)
+ include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${CMAKE_SOURCE_DIR}/src/apps/share/
+ ${OIIO_INCLUDES}
+ )
+
+ file(GLOB_RECURSE share_src_files "${CMAKE_SOURCE_DIR}/src/apps/share/*.cpp")
+
+ add_executable(ociolutimage ${share_src_files} main.cpp)
+
+ target_link_libraries(ociolutimage ${OIIO_LIBRARIES} OpenColorIO dl)
+
+ install(TARGETS ociolutimage DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/bin)
+endif()
diff --git a/src/apps/ociolutimage/main.cpp b/src/apps/ociolutimage/main.cpp
new file mode 100644
index 0000000..2d5906b
--- /dev/null
+++ b/src/apps/ociolutimage/main.cpp
@@ -0,0 +1,398 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+OCIO_NAMESPACE_USING;
+
+#include <OpenImageIO/imageio.h>
+#include <OpenImageIO/typedesc.h>
+#if (OIIO_VERSION < 10100)
+namespace OIIO = OIIO_NAMESPACE;
+#endif
+
+#include "argparse.h"
+
+#include <algorithm>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <sstream>
+
+#include "pystring.h"
+
+enum Lut3DOrder
+{
+ LUT3DORDER_FAST_RED = 0,
+ LUT3DORDER_FAST_BLUE
+};
+
+void WriteLut3D(const std::string & filename, const float* lutdata, int edgeLen);
+void GenerateIdentityLut3D(float* img, int edgeLen, int numChannels, Lut3DOrder lut3DOrder);
+
+
+void GetLutImageSize(int & width, int & height,
+ int cubesize, int maxwidth)
+{
+ // Compute the image width / height
+ width = cubesize*cubesize;
+ if(maxwidth>0 && width>=maxwidth)
+ {
+ // TODO: Do something smarter here to find a better multiple,
+ // to create a more pleasing gradient rendition.
+ // Use prime divisors / lowest common denominator, if possible?
+ width = std::min(maxwidth, width);
+ }
+
+ int numpixels = cubesize*cubesize*cubesize;
+ height = (int)(ceilf((float)numpixels/(float)width));
+}
+
+
+void Generate(int cubesize, int maxwidth,
+ const std::string & outputfile,
+ const std::string & configfile,
+ const std::string & incolorspace,
+ const std::string & outcolorspace)
+{
+ int width = 0;
+ int height = 0;
+ int numchannels = 3;
+ GetLutImageSize(width, height, cubesize, maxwidth);
+
+ std::vector<float> img;
+ img.resize(width*height*numchannels, 0);
+
+ GenerateIdentityLut3D(&img[0], cubesize, numchannels, LUT3DORDER_FAST_RED);
+
+ if(!incolorspace.empty() || !outcolorspace.empty())
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::Config::Create();
+ if(!configfile.empty())
+ {
+ config = OCIO::Config::CreateFromFile(configfile.c_str());
+ }
+ else if(getenv("OCIO"))
+ {
+ config = OCIO::Config::CreateFromEnv();
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "You must specify an ocio configuration ";
+ os << "(either with --config or $OCIO).";
+ throw Exception(os.str().c_str());
+ }
+
+ OCIO::ConstProcessorRcPtr processor =
+ config->getProcessor(incolorspace.c_str(), outcolorspace.c_str());
+
+ OCIO::PackedImageDesc imgdesc(&img[0], width, height, 3);
+ processor->apply(imgdesc);
+ }
+
+ OIIO::ImageOutput* f = OIIO::ImageOutput::create(outputfile);
+ if(!f)
+ {
+ throw Exception( "Could not create output image.");
+ }
+
+ OIIO::ImageSpec spec(width, height, numchannels, OIIO::TypeDesc::TypeFloat);
+
+ // TODO: If DPX, force 16-bit output?
+ f->open(outputfile, spec);
+ f->write_image(OIIO::TypeDesc::FLOAT, &img[0]);
+ f->close();
+ delete f;
+}
+
+
+void Extract(int cubesize, int maxwidth,
+ const std::string & inputfile,
+ const std::string & outputfile)
+{
+ // Read the image
+ OIIO::ImageInput* f = OIIO::ImageInput::create(inputfile);
+ if(!f)
+ {
+ throw Exception("Could not create input image.");
+ }
+
+ OIIO::ImageSpec spec;
+ f->open(inputfile, spec);
+
+ std::string error = f->geterror();
+ if(!error.empty())
+ {
+ std::ostringstream os;
+ os << "Error loading image " << error;
+ throw Exception(os.str().c_str());
+ }
+
+ int width = 0;
+ int height = 0;
+ GetLutImageSize(width, height, cubesize, maxwidth);
+
+ if(spec.width != width || spec.height != height)
+ {
+ std::ostringstream os;
+ os << "Image does not have expected dimensions. ";
+ os << "Expected " << width << "x" << height << ", ";
+ os << "Found " << spec.width << "x" << spec.height;
+ throw Exception(os.str().c_str());
+ }
+
+ if(spec.nchannels<3)
+ {
+ throw Exception("Image must have 3 or more channels.");
+ }
+
+ int lut3DNumPixels = cubesize*cubesize*cubesize;
+
+ if(spec.width*spec.height<lut3DNumPixels)
+ {
+ throw Exception("Image is not large enough to contain expected 3dlut.");
+ }
+
+ // TODO: confirm no data window?
+ std::vector<float> img;
+ img.resize(spec.width*spec.height*spec.nchannels, 0);
+ f->read_image(OIIO::TypeDesc::TypeFloat, &img[0]);
+ delete f;
+
+ // Repack into rgb
+ // Convert the RGB[...] image to an RGB image, in place.
+ // Of course, this only works because we're doing it from left to right
+ // so old pixels are read before they're written over
+
+ if(spec.nchannels > 3)
+ {
+ for(int i=0; i<lut3DNumPixels; ++i)
+ {
+ img[3*i+0] = img[spec.nchannels*i+0];
+ img[3*i+1] = img[spec.nchannels*i+1];
+ img[3*i+2] = img[spec.nchannels*i+2];
+ }
+ }
+
+ img.resize(lut3DNumPixels*3);
+
+ // Write the output lut
+ WriteLut3D(outputfile, &img[0], cubesize);
+}
+
+
+
+int main (int argc, const char* argv[])
+{
+ bool generate = false;
+ bool extract = false;
+ int cubesize = 32;
+ int maxwidth = 2048;
+ std::string inputfile;
+ std::string outputfile;
+ std::string config;
+ std::string incolorspace;
+ std::string outcolorspace;
+
+ // TODO: Add optional allocation transform instead of colorconvert
+ ArgParse ap;
+ ap.options("ociolutimage -- Convert a 3dlut to or from an image\n\n"
+ "usage: ociolutimage [options] <OUTPUTFILE.LUT>\n\n"
+ "example: ociolutimage --generate --output lut.exr\n"
+ "example: ociolutimage --extract --input lut.exr --output output.spi3d\n",
+ "<SEPARATOR>", "",
+ "--generate", &generate, "Generate a lattice image",
+ "--extract", &extract, "Extract a 3dlut from an input image",
+ "<SEPARATOR>", "",
+ "--cubesize %d", &cubesize, "Size of the cube (default: 32)",
+ "--maxwidth %d", &maxwidth, "Specify maximum width of the image (default: 2048)",
+ "--input %s", &inputfile, "Specify the input filename",
+ "--output %s", &outputfile, "Specify the output filename",
+ "<SEPARATOR>", "",
+ "--config %s", &config, ".ocio configuration file (default: $OCIO)",
+ "--colorconvert %s %s", &incolorspace, &outcolorspace, "Apply a color space conversion to the image.",
+ NULL);
+
+ if (ap.parse(argc, argv) < 0)
+ {
+ std::cout << ap.geterror() << std::endl;
+ ap.usage();
+ std::cout << "\n";
+ return 1;
+ }
+
+ if (argc == 1 )
+ {
+ ap.usage();
+ std::cout << "\n";
+ return 1;
+ }
+
+ if(generate)
+ {
+ try
+ {
+ Generate(cubesize, maxwidth,
+ outputfile,
+ config, incolorspace, outcolorspace);
+ }
+ catch(std::exception & e)
+ {
+ std::cerr << "Error generating image: " << e.what() << std::endl;
+ exit(1);
+ }
+ catch(...)
+ {
+ std::cerr << "Error generating image. An unknown error occurred.\n";
+ exit(1);
+ }
+ }
+ else if(extract)
+ {
+ try
+ {
+ Extract(cubesize, maxwidth,
+ inputfile, outputfile);
+ }
+ catch(std::exception & e)
+ {
+ std::cerr << "Error extracting lut: " << e.what() << std::endl;
+ exit(1);
+ }
+ catch(...)
+ {
+ std::cerr << "Error extracting lut. An unknown error occurred.\n";
+ exit(1);
+ }
+ }
+ else
+ {
+ std::cerr << "Must specify either --generate or --extract.\n";
+ exit(1);
+ }
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// TODO: These should be exposed from inside OCIO, in appropriate time.
+//
+
+inline int GetLut3DIndex_B(int indexR, int indexG, int indexB,
+ int sizeR, int sizeG, int /*sizeB*/)
+{
+ return 3 * (indexR + sizeR * (indexG + sizeG * indexB));
+}
+
+inline int GetLut3DIndex_R(int indexR, int indexG, int indexB,
+ int /*sizeR*/, int sizeG, int sizeB)
+{
+ return 3 * (indexB + sizeB * (indexG + sizeG * indexR));
+}
+
+void GenerateIdentityLut3D(float* img, int edgeLen, int numChannels,
+ Lut3DOrder lut3DOrder)
+{
+ if(!img) return;
+ if(numChannels < 3)
+ {
+ throw Exception("Cannot generate idenitity 3d lut with less than 3 channels.");
+ }
+
+ float c = 1.0f / ((float)edgeLen - 1.0f);
+
+ if(lut3DOrder == LUT3DORDER_FAST_RED)
+ {
+ for(int i=0; i<edgeLen*edgeLen*edgeLen; i++)
+ {
+ img[numChannels*i+0] = (float)(i%edgeLen) * c;
+ img[numChannels*i+1] = (float)((i/edgeLen)%edgeLen) * c;
+ img[numChannels*i+2] = (float)((i/edgeLen/edgeLen)%edgeLen) * c;
+ }
+ }
+ else if(lut3DOrder == LUT3DORDER_FAST_BLUE)
+ {
+ for(int i=0; i<edgeLen*edgeLen*edgeLen; i++)
+ {
+ img[numChannels*i+0] = (float)((i/edgeLen/edgeLen)%edgeLen) * c;
+ img[numChannels*i+1] = (float)((i/edgeLen)%edgeLen) * c;
+ img[numChannels*i+2] = (float)(i%edgeLen) * c;
+ }
+ }
+ else
+ {
+ throw Exception("Unknown Lut3DOrder.");
+ }
+}
+
+void WriteLut3D(const std::string & filename, const float* lutdata, int edgeLen)
+{
+ if(!pystring::endswith(filename,".spi3d"))
+ {
+ std::ostringstream os;
+ os << "Only .spi3d writing is currently supported. ";
+ os << "As a work around, please write a .spi3d file, and then use ";
+ os << "ociobakelut for transcoding.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::ofstream output;
+ output.open(filename.c_str());
+ if(!output.is_open())
+ {
+ std::ostringstream os;
+ os << "Error opening " << filename << " for writing.";
+ throw Exception(os.str().c_str());
+ }
+
+ output << "SPILUT 1.0\n";
+ output << "3 3\n";
+ output << edgeLen << " " << edgeLen << " " << edgeLen << "\n";
+
+ int index = 0;
+ for(int rindex=0; rindex<edgeLen; ++rindex)
+ {
+ for(int gindex=0; gindex<edgeLen; ++gindex)
+ {
+ for(int bindex=0; bindex<edgeLen; ++bindex)
+ {
+ index = GetLut3DIndex_B(rindex, gindex, bindex,
+ edgeLen, edgeLen, edgeLen);
+
+ output << rindex << " " << gindex << " " << bindex << " ";
+ output << lutdata[index+0] << " ";
+ output << lutdata[index+1] << " ";
+ output << lutdata[index+2] << "\n";
+ }
+ }
+ }
+
+ output.close();
+}
diff --git a/src/apps/share/argparse.cpp b/src/apps/share/argparse.cpp
new file mode 100644
index 0000000..ea61d78
--- /dev/null
+++ b/src/apps/share/argparse.cpp
@@ -0,0 +1,528 @@
+/*
+ Copyright 2008 Larry Gritz and the other authors and contributors.
+ All Rights Reserved.
+ Based on BSD-licensed software Copyright 2004 NVIDIA Corp.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the software's owners nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ (This is the Modified BSD License)
+*/
+
+
+#include <cstring>
+#include <cctype>
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <cstdarg>
+#include <iterator>
+
+#include "strutil.h"
+#include "argparse.h"
+
+/*
+OIIO_NAMESPACE_ENTER
+{
+*/
+
+class ArgOption {
+public:
+ typedef int (*callback_t) (int, const char**);
+
+ ArgOption (const char *str);
+ ~ArgOption () { }
+
+ int initialize ();
+
+ int parameter_count () const { return m_count; }
+ const std::string & name() const { return m_flag; }
+
+ const std::string & fmt() const { return m_format; }
+
+ bool is_flag () const { return m_type == Flag; }
+ bool is_sublist () const { return m_type == Sublist; }
+ bool is_regular () const { return m_type == Regular; }
+
+ void add_parameter (int i, void *p);
+
+ void set_parameter (int i, const char *argv);
+
+ void add_argument (const char *argv);
+ int invoke_callback () const;
+
+ int invoke_callback (int argc, const char **argv) const {
+ return m_callback ? m_callback (argc, argv) : 0;
+ }
+
+ void set_callback (callback_t cb) { m_callback = cb; }
+
+ void found_on_command_line () { m_repetitions++; }
+ int parsed_count () const { return m_repetitions; }
+
+ void description (const char *d) { m_descript = d; }
+ const std::string & description() const { return m_descript; }
+
+private:
+ enum OptionType { None, Regular, Flag, Sublist };
+
+ std::string m_format; // original format string
+ std::string m_flag; // just the -flag_foo part
+ std::string m_code; // paramter types, eg "df"
+ std::string m_descript;
+ OptionType m_type;
+ int m_count; // number of parameters
+ std::vector<void *> m_param; // pointers to app data vars
+ callback_t m_callback;
+ int m_repetitions; // number of times on cmd line
+ std::vector<std::string> m_argv;
+};
+
+
+
+// Constructor. Does not do any parsing or error checking.
+// Make sure to call initialize() right after construction.
+ArgOption::ArgOption (const char *str)
+ : m_format(str), m_type(None), m_count(0),
+ m_callback(NULL), m_repetitions(0)
+{
+}
+
+
+
+// Parses the format string ("-option %s %d %f") to extract the
+// flag ("-option") and create a code string ("sdf"). After the
+// code string is created, the param list of void* pointers is
+// allocated to hold the argument variable pointers.
+int
+ArgOption::initialize()
+{
+ size_t n;
+ const char *s;
+
+ if (m_format.empty() || m_format == "%*") {
+ m_type = Sublist;
+ m_count = 1; // sublist callback function pointer
+ m_code = "*";
+ m_flag = "";
+ } else if (m_format == "<SEPARATOR>") {
+ } else {
+ // extract the flag name
+ s = &m_format[0];
+ assert(*s == '-');
+ assert(isalpha(s[1]) || (s[1] == '-' && isalpha(s[2])));
+
+ s++;
+ if (*s == '-')
+ s++;
+
+ while (isalnum(*s) || *s == '_' || *s == '-') s++;
+
+ if (! *s) {
+ m_flag = m_format;
+ m_type = Flag;
+ m_count = 1;
+ m_code = "b";
+ } else {
+ n = s - (&m_format[0]);
+ m_flag.assign (m_format.begin(), m_format.begin()+n);
+
+ // Parse the scanf-like parameters
+
+ m_type = Regular;
+
+ n = (m_format.length() - n) / 2; // conservative estimate
+ m_code.clear ();
+
+ while (*s != '\0') {
+ if (*s == '%') {
+ s++;
+ assert(*s != '\0');
+
+ m_count++; // adding another parameter
+
+ switch (*s) {
+ case 'd': // 32bit int
+ case 'g': // float
+ case 'f': // float
+ case 'F': // double
+ case 's': // string
+ case 'L': // vector<string>
+ assert (m_type == Regular);
+ m_code += *s;
+ break;
+
+ case '*':
+ assert(m_count == 1);
+ m_type = Sublist;
+ break;
+
+ default:
+ std::cerr << "Programmer error: Unknown option ";
+ std::cerr << "type string \"" << *s << "\"" << "\n";
+ abort();
+ }
+ }
+
+ s++;
+ }
+ }
+ }
+
+ // Allocate space for the parameter pointers and initialize to NULL
+ m_param.resize (m_count, NULL);
+
+ return 0;
+}
+
+
+
+// Stores the pointer to an argument in the param list and
+// initializes flag options to FALSE.
+// FIXME -- there is no such initialization. Bug?
+void
+ArgOption::add_parameter (int i, void *p)
+{
+ assert (i >= 0 && i < m_count);
+ m_param[i] = p;
+}
+
+
+
+// Given a string from argv, set the associated option parameter
+// at index i using the format conversion code in the code string.
+void
+ArgOption::set_parameter (int i, const char *argv)
+{
+ assert(i < m_count);
+
+ switch (m_code[i]) {
+ case 'd':
+ *(int *)m_param[i] = atoi(argv);
+ break;
+
+ case 'f':
+ case 'g':
+ *(float *)m_param[i] = (float)atof(argv);
+ break;
+
+ case 'F':
+ *(double *)m_param[i] = atof(argv);
+ break;
+
+ case 's':
+ *(std::string *)m_param[i] = argv;
+ break;
+
+ case 'S':
+ *(std::string *)m_param[i] = argv;
+ break;
+
+ case 'L':
+ ((std::vector<std::string> *)m_param[i])->push_back (argv);
+ break;
+
+ case 'b':
+ *(bool *)m_param[i] = true;
+ break;
+
+ case '*':
+ default:
+ abort();
+ }
+}
+
+
+
+// Call the sublist callback if any arguments have been parsed
+int
+ArgOption::invoke_callback () const
+{
+ assert (m_count == 1);
+
+ int argc = (int) m_argv.size();
+ if (argc == 0)
+ return 0;
+
+ // Convert the argv's to char*[]
+ const char **myargv = (const char **) alloca (argc * sizeof(const char *));
+ for (int i = 0; i < argc; ++i)
+ myargv[i] = m_argv[i].c_str();
+ return invoke_callback (argc, myargv);
+}
+
+
+
+// Add an argument to this sublist option
+void
+ArgOption::add_argument (const char *argv)
+{
+ m_argv.push_back (argv);
+}
+
+
+
+
+
+ArgParse::ArgParse (int argc, const char **argv)
+ : m_argc(argc), m_argv(argv), m_global(NULL)
+{
+}
+
+
+
+ArgParse::~ArgParse()
+{
+ for (unsigned int i=0; i<m_option.size(); ++i) {
+ ArgOption *opt = m_option[i];
+ delete opt;
+ }
+}
+
+
+
+// Top level command line parsing function called after all options
+// have been parsed and created from the format strings. This function
+// parses the command line (argc,argv) stored internally in the constructor.
+// Each command line argument is parsed and checked to see if it matches an
+// existing option. If there is no match, and error is reported and the
+// function returns early. If there is a match, all the arguments for
+// that option are parsed and the associated variables are set.
+int
+ArgParse::parse (int xargc, const char **xargv)
+{
+ m_argc = xargc;
+ m_argv = xargv;
+
+ for (int i = 1; i < m_argc; i++) {
+ if (m_argv[i][0] == '-' &&
+ (isalpha (m_argv[i][1]) || m_argv[i][1] == '-')) { // flag
+ ArgOption *option = find_option (m_argv[i]);
+ if (option == NULL) {
+ error ("Invalid option \"%s\"", m_argv[i]);
+ return -1;
+ }
+
+ option->found_on_command_line();
+
+ if (option->is_flag()) {
+ option->set_parameter(0, NULL);
+ } else {
+ assert (option->is_regular());
+ for (int j = 0; j < option->parameter_count(); j++) {
+ if (j+i+1 >= m_argc) {
+ error ("Missing parameter %d from option "
+ "\"%s\"", j+1, option->name().c_str());
+ return -1;
+ }
+ option->set_parameter (j, m_argv[i+j+1]);
+ }
+ i += option->parameter_count();
+ }
+ } else {
+ // not an option nor an option parameter, glob onto global list
+ if (m_global)
+ m_global->invoke_callback (1, m_argv+i);
+ else {
+ error ("Argument \"%s\" does not have an associated "
+ "option", m_argv[i]);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+// Primary entry point. This function accepts a set of format strings
+// and variable pointers. Each string contains an option name and a
+// scanf-like format string to enumerate the arguments of that option
+// (eg. "-option %d %f %s"). The format string is followed by a list
+// of pointers to the argument variables, just like scanf. All format
+// strings and arguments are parsed to create a list of ArgOption objects.
+// After all ArgOptions are created, the command line is parsed and
+// the sublist option callbacks are invoked.
+int
+ArgParse::options (const char *intro, ...)
+{
+ va_list ap;
+ va_start (ap, intro);
+
+ m_intro = intro;
+ for (const char *cur = va_arg(ap, char *); cur; cur = va_arg(ap, char *)) {
+ if (find_option (cur) &&
+ strcmp(cur, "<SEPARATOR>")) {
+ error ("Option \"%s\" is multiply defined", cur);
+ return -1;
+ }
+
+ // Build a new option and then parse the values
+ ArgOption *option = new ArgOption (cur);
+ if (option->initialize() < 0) {
+ return -1;
+ }
+
+ if (cur[0] == '\0' ||
+ (cur[0] == '%' && cur[1] == '*' && cur[2] == '\0')) {
+ // set default global option
+ m_global = option;
+ }
+
+ // Grab any parameters and store them with this option
+ for (int i = 0; i < option->parameter_count(); i++) {
+ void *p = va_arg (ap, void *);
+ if (p == NULL) {
+ error ("Missing argument parameter for \"%s\"",
+ option->name().c_str());
+ return -1;
+ }
+
+ option->add_parameter (i, p);
+
+ if (option == m_global)
+ option->set_callback ((ArgOption::callback_t)p);
+ }
+
+ // Last argument is description
+ option->description ((const char *) va_arg (ap, const char *));
+ m_option.push_back(option);
+ }
+
+ va_end (ap);
+ return 0;
+}
+
+
+
+// Find an option by name in the option vector
+ArgOption *
+ArgParse::find_option (const char *name)
+{
+ for (std::vector<ArgOption *>::const_iterator i = m_option.begin();
+ i != m_option.end(); i++) {
+ const char *opt = (*i)->name().c_str();
+ if (! strcmp(name, opt))
+ return *i;
+ // Match even if the user mixes up one dash or two
+ if (name[0] == '-' && name[1] == '-' && opt[0] == '-' && opt[1] != '-')
+ if (! strcmp (name+1, opt))
+ return *i;
+ if (name[0] == '-' && name[1] != '-' && opt[0] == '-' && opt[1] == '-')
+ if (! strcmp (name, opt+1))
+ return *i;
+ }
+
+ return NULL;
+}
+
+
+
+int
+ArgParse::found (const char *option_name)
+{
+ ArgOption *option = find_option(option_name);
+ if (option == NULL) return 0;
+ return option->parsed_count();
+}
+
+
+
+void
+ArgParse::error (const char *format, ...)
+{
+ va_list ap;
+ va_start (ap, format);
+ m_errmessage = Strutil::vformat (format, ap);
+ va_end (ap);
+}
+
+std::string
+ArgParse::geterror () const
+{
+ std::string e = m_errmessage;
+ m_errmessage.clear ();
+ return e;
+}
+
+
+void
+ArgParse::usage () const
+{
+ const size_t longline = 40;
+ std::cout << m_intro << '\n';
+ size_t maxlen = 0;
+
+ for (unsigned int i=0; i<m_option.size(); ++i) {
+ ArgOption *opt = m_option[i];
+ size_t fmtlen = opt->fmt().length();
+ // Option lists > 40 chars will be split into multiple lines
+ if (fmtlen < longline)
+ maxlen = std::max (maxlen, fmtlen);
+ }
+
+ for (unsigned int i=0; i<m_option.size(); ++i) {
+ ArgOption *opt = m_option[i];
+ if (opt->description().length()) {
+ size_t fmtlen = opt->fmt().length();
+ if (opt->fmt() == "<SEPARATOR>")
+ std::cout << opt->description() << '\n';
+ else if (fmtlen < longline)
+ std::cout << " " << opt->fmt()
+ << std::string (maxlen + 2 - fmtlen, ' ')
+ << opt->description() << '\n';
+ else
+ std::cout << " " << opt->fmt() << "\n "
+ << std::string (maxlen + 2, ' ')
+ << opt->description() << '\n';
+ }
+ }
+}
+
+
+
+std::string
+ArgParse::command_line () const
+{
+ std::string s;
+ for (int i = 0; i < m_argc; ++i) {
+ if (strchr (m_argv[i], ' ')) {
+ s += '\"';
+ s += m_argv[i];
+ s += '\"';
+ } else {
+ s += m_argv[i];
+ }
+ if (i < m_argc-1)
+ s += ' ';
+ }
+ return s;
+}
+
+
+/*
+}
+OIIO_NAMESPACE_EXIT
+*/
+
diff --git a/src/apps/share/argparse.h b/src/apps/share/argparse.h
new file mode 100644
index 0000000..fd3ec6d
--- /dev/null
+++ b/src/apps/share/argparse.h
@@ -0,0 +1,181 @@
+/*
+ Copyright 2008 Larry Gritz and the other authors and contributors.
+ All Rights Reserved.
+ Based on BSD-licensed software Copyright 2004 NVIDIA Corp.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the software's owners nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ (This is the Modified BSD License)
+*/
+
+
+/// \file
+/// \brief Simple parsing of program command-line arguments.
+
+
+#ifndef OPENCOLORIO_ARGPARSE_H
+#define OPENCOLORIO_ARGPARSE_H
+
+#include <vector>
+
+#ifndef OPENCOLORIO_PRINTF_ARGS /* See comments in strutil.h */
+# ifndef __GNUC__
+# define __attribute__(x)
+# endif
+# define OPENCOLORIO_PRINTF_ARGS(fmtarg_pos, vararg_pos) \
+ __attribute__ ((format (printf, fmtarg_pos, vararg_pos) ))
+#endif
+
+/*
+OIIO_NAMESPACE_ENTER
+{
+*/
+
+class ArgOption; // Forward declaration
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+///
+/// \class ArgParse
+///
+/// Argument Parsing
+///
+/// The parse function takes a list of options and variables or functions
+/// for storing option values and return <0 on failure:
+///
+/// \code
+/// static int
+/// parse_files (int argc, const char *argv[])
+/// {
+/// for (int i = 0; i < argc; i++)
+/// filenames.push_back (argv[i]);
+/// return 0;
+/// }
+///
+/// ...
+///
+/// ArgParse ap;
+///
+/// ap.options ("Usage: myapp [options] filename...",
+/// "%*", parse_objects, "",
+/// "-camera %f %f %f", &camera[0], &camera[1], &camera[2],
+/// "set the camera position",
+/// "-lookat %f %f %f", &lx, &ly, &lz,
+/// "set the position of interest",
+/// "-oversampling %d", &oversampling, "oversamping rate",
+/// "-passes %d", &passes, "number of passes",
+/// "-lens %f %f %f", &aperture, &focalDistance, &focalLength,
+/// "set aperture, focal distance, focal length",
+/// "-format %d %d %f", &width, &height, &aspect,
+/// "set width, height, aspect ratio",
+/// "-v", &flag, "verbose output",
+/// NULL);
+///
+/// if (ap.parse (argc, argv) < 0) {
+/// std::cerr << ap.geterror() << std::endl;
+/// ap.usage ();
+/// return EXIT_FAILURE;
+/// }
+/// \endcode
+///
+/// The available argument types are:
+/// - no \% argument - bool flag
+/// - \%d - 32bit integer
+/// - \%f - 32bit float
+/// - \%F - 64bit float (double)
+/// - \%s - std::string
+/// - \%L - std::vector<std::string> (takes 1 arg, appends to list)
+/// - \%* - catch all non-options and pass individually as an (argc,argv)
+/// sublist to a callback, each immediately after it's found
+///
+/// There are several special format tokens:
+/// - "<SEPARATOR>" - not an option at all, just a description to print
+/// in the usage output.
+///
+/// Notes:
+/// - If an option doesn't have any arguments, a flag argument is assumed.
+/// - Flags are initialized to false. No other variables are initialized.
+/// - The empty string, "", is used as a global sublist (ie. "%*").
+/// - Sublist functions are all of the form "int func(int argc, char **argv)".
+/// - If a sublist function returns -1, parse() will terminate early.
+///
+/////////////////////////////////////////////////////////////////////////////
+
+
+class ArgParse {
+public:
+ ArgParse (int argc=0, const char **argv=NULL);
+ ~ArgParse ();
+
+ /// Declare the command line options. After the introductory
+ /// message, parameters are a set of format strings and variable
+ /// pointers. Each string contains an option name and a scanf-like
+ /// format string to enumerate the arguments of that option
+ /// (eg. "-option %d %f %s"). The format string is followed by a
+ /// list of pointers to the argument variables, just like scanf. A
+ /// NULL terminates the list.
+ int options (const char *intro, ...);
+
+ /// With the options already set up, parse the command line.
+ /// Return 0 if ok, -1 if it's a malformed command line.
+ int parse (int argc, const char **argv);
+
+ /// Return any error messages generated during the course of parse()
+ /// (and clear any error flags). If no error has occurred since the
+ /// last time geterror() was called, it will return an empty string.
+ std::string geterror () const;
+
+ /// Deprecated
+ ///
+ std::string error_message () const { return geterror (); }
+
+ /// Print the usage message to stdout. The usage message is
+ /// generated and formatted automatically based on the command and
+ /// description arguments passed to parse().
+ void usage () const;
+
+ /// Return the entire command-line as one string.
+ ///
+ std::string command_line () const;
+
+private:
+ int m_argc; // a copy of the command line argc
+ const char **m_argv; // a copy of the command line argv
+ mutable std::string m_errmessage; // error message
+ ArgOption *m_global; // option for extra cmd line arguments
+ std::string m_intro;
+ std::vector<ArgOption *> m_option;
+
+ ArgOption *find_option(const char *name);
+ void error (const char *format, ...) OPENCOLORIO_PRINTF_ARGS(2,3);
+ int found (const char *option); // number of times option was parsed
+};
+
+/*
+}
+OIIO_NAMESPACE_EXIT
+*/
+
+#endif // OPENCOLORIO_ARGPARSE_H
diff --git a/src/apps/share/pystring.cpp b/src/apps/share/pystring.cpp
new file mode 100644
index 0000000..7805162
--- /dev/null
+++ b/src/apps/share/pystring.cpp
@@ -0,0 +1,1658 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// Neither the name of the organization Sony Pictures Imageworks nor the
+// names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "pystring.h"
+
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+
+namespace pystring
+{
+
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+#ifndef WINDOWS
+#define WINDOWS
+#endif
+#endif
+
+// This definition codes from configure.in in the python src.
+// Strictly speaking this limits us to str sizes of 2**31.
+// Should we wish to handle this limit, we could use an architecture
+// specific #defines and read from ssize_t (unistd.h) if the header exists.
+// But in the meantime, the use of int assures maximum arch compatibility.
+// This must also equal the size used in the end = MAX_32BIT_INT default arg.
+
+typedef int Py_ssize_t;
+
+/* helper macro to fixup start/end slice values */
+#define ADJUST_INDICES(start, end, len) \
+ if (end > len) \
+ end = len; \
+ else if (end < 0) { \
+ end += len; \
+ if (end < 0) \
+ end = 0; \
+ } \
+ if (start < 0) { \
+ start += len; \
+ if (start < 0) \
+ start = 0; \
+ }
+
+
+ namespace {
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// why doesn't the std::reverse work?
+ ///
+ void reverse_strings( std::vector< std::string > & result)
+ {
+ for (std::vector< std::string >::size_type i = 0; i < result.size() / 2; i++ )
+ {
+ std::swap(result[i], result[result.size() - 1 - i]);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void split_whitespace( const std::string & str, std::vector< std::string > & result, int maxsplit )
+ {
+ std::string::size_type i, j, len = str.size();
+ for (i = j = 0; i < len; )
+ {
+
+ while ( i < len && ::isspace( str[i] ) ) i++;
+ j = i;
+
+ while ( i < len && ! ::isspace( str[i]) ) i++;
+
+
+
+ if (j < i)
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( j, i - j ));
+
+ while ( i < len && ::isspace( str[i])) i++;
+ j = i;
+ }
+ }
+ if (j < len)
+ {
+ result.push_back( str.substr( j, len - j ));
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void rsplit_whitespace( const std::string & str, std::vector< std::string > & result, int maxsplit )
+ {
+ std::string::size_type len = str.size();
+ std::string::size_type i, j;
+ for (i = j = len; i > 0; )
+ {
+
+ while ( i > 0 && ::isspace( str[i - 1] ) ) i--;
+ j = i;
+
+ while ( i > 0 && ! ::isspace( str[i - 1]) ) i--;
+
+
+
+ if (j > i)
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( i, j - i ));
+
+ while ( i > 0 && ::isspace( str[i - 1])) i--;
+ j = i;
+ }
+ }
+ if (j > 0)
+ {
+ result.push_back( str.substr( 0, j ));
+ }
+ //std::reverse( result, result.begin(), result.end() );
+ reverse_strings( result );
+ }
+
+ } //anonymous namespace
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void split( const std::string & str, std::vector< std::string > & result, const std::string & sep, int maxsplit )
+ {
+ result.clear();
+
+ if ( maxsplit < 0 ) maxsplit = MAX_32BIT_INT;//result.max_size();
+
+
+ if ( sep.size() == 0 )
+ {
+ split_whitespace( str, result, maxsplit );
+ return;
+ }
+
+ std::string::size_type i,j, len = str.size(), n = sep.size();
+
+ i = j = 0;
+
+ while ( i+n <= len )
+ {
+ if ( str[i] == sep[0] && str.substr( i, n ) == sep )
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( j, i - j ) );
+ i = j = i + n;
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ result.push_back( str.substr( j, len-j ) );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep, int maxsplit )
+ {
+ if ( maxsplit < 0 )
+ {
+ split( str, result, sep, 0 );
+ return;
+ }
+
+ result.clear();
+
+ if ( sep.size() == 0 )
+ {
+ rsplit_whitespace( str, result, maxsplit );
+ return;
+ }
+
+ std::string::size_type i,j, len = str.size(), n = sep.size();
+
+ i = j = len;
+
+ while ( i > n )
+ {
+ if ( str[i - 1] == sep[n - 1] && str.substr( i - n, n ) == sep )
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( i, j - i ) );
+ i = j = i - n;
+ }
+ else
+ {
+ i--;
+ }
+ }
+
+ result.push_back( str.substr( 0, j ) );
+ reverse_strings( result );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ #define LEFTSTRIP 0
+ #define RIGHTSTRIP 1
+ #define BOTHSTRIP 2
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string do_strip( const std::string & str, int striptype, const std::string & chars )
+ {
+ Py_ssize_t len = (Py_ssize_t) str.size(), i, j, charslen = (Py_ssize_t) chars.size();
+
+ if ( charslen == 0 )
+ {
+ i = 0;
+ if ( striptype != RIGHTSTRIP )
+ {
+ while ( i < len && ::isspace( str[i] ) )
+ {
+ i++;
+ }
+ }
+
+ j = len;
+ if ( striptype != LEFTSTRIP )
+ {
+ do
+ {
+ j--;
+ }
+ while (j >= i && ::isspace(str[j]));
+
+ j++;
+ }
+
+
+ }
+ else
+ {
+ const char * sep = chars.c_str();
+
+ i = 0;
+ if ( striptype != RIGHTSTRIP )
+ {
+ while ( i < len && memchr(sep, str[i], charslen) )
+ {
+ i++;
+ }
+ }
+
+ j = len;
+ if (striptype != LEFTSTRIP)
+ {
+ do
+ {
+ j--;
+ }
+ while (j >= i && memchr(sep, str[j], charslen) );
+ j++;
+ }
+
+
+ }
+
+ if ( i == 0 && j == len )
+ {
+ return str;
+ }
+ else
+ {
+ return str.substr( i, j - i );
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result )
+ {
+ result.resize(3);
+ int index = find( str, sep );
+ if ( index < 0 )
+ {
+ result[0] = str;
+ result[1] = "";
+ result[2] = "";
+ }
+ else
+ {
+ result[0] = str.substr( 0, index );
+ result[1] = sep;
+ result[2] = str.substr( index + sep.size(), str.size() );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result )
+ {
+ result.resize(3);
+ int index = rfind( str, sep );
+ if ( index < 0 )
+ {
+ result[0] = "";
+ result[1] = "";
+ result[2] = str;
+ }
+ else
+ {
+ result[0] = str.substr( 0, index );
+ result[1] = sep;
+ result[2] = str.substr( index + sep.size(), str.size() );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string strip( const std::string & str, const std::string & chars )
+ {
+ return do_strip( str, BOTHSTRIP, chars );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string lstrip( const std::string & str, const std::string & chars )
+ {
+ return do_strip( str, LEFTSTRIP, chars );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string rstrip( const std::string & str, const std::string & chars )
+ {
+ return do_strip( str, RIGHTSTRIP, chars );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string join( const std::string & str, const std::vector< std::string > & seq )
+ {
+ std::vector< std::string >::size_type seqlen = seq.size(), i;
+
+ if ( seqlen == 0 ) return "";
+ if ( seqlen == 1 ) return seq[0];
+
+ std::string result( seq[0] );
+
+ for ( i = 1; i < seqlen; ++i )
+ {
+ result += str + seq[i];
+
+ }
+
+
+ return result;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ namespace
+ {
+ /* Matches the end (direction >= 0) or start (direction < 0) of self
+ * against substr, using the start and end arguments. Returns
+ * -1 on error, 0 if not found and 1 if found.
+ */
+
+ int _string_tailmatch(const std::string & self, const std::string & substr,
+ Py_ssize_t start, Py_ssize_t end,
+ int direction)
+ {
+ Py_ssize_t len = (Py_ssize_t) self.size();
+ Py_ssize_t slen = (Py_ssize_t) substr.size();
+
+ const char* sub = substr.c_str();
+ const char* str = self.c_str();
+
+ ADJUST_INDICES(start, end, len);
+
+ if (direction < 0) {
+ // startswith
+ if (start+slen > len)
+ return 0;
+ } else {
+ // endswith
+ if (end-start < slen || start > len)
+ return 0;
+ if (end-slen > start)
+ start = end - slen;
+ }
+ if (end-start >= slen)
+ return (!std::memcmp(str+start, sub, slen));
+
+ return 0;
+ }
+ }
+
+ bool endswith( const std::string & str, const std::string & suffix, int start, int end )
+ {
+ int result = _string_tailmatch(str, suffix,
+ (Py_ssize_t) start, (Py_ssize_t) end, +1);
+ //if (result == -1) // TODO: Error condition
+
+ return static_cast<bool>(result);
+ }
+
+
+ bool startswith( const std::string & str, const std::string & prefix, int start, int end )
+ {
+ int result = _string_tailmatch(str, prefix,
+ (Py_ssize_t) start, (Py_ssize_t) end, -1);
+ //if (result == -1) // TODO: Error condition
+
+ return static_cast<bool>(result);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ bool isalnum( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+
+
+ if( len == 1 )
+ {
+ return ::isalnum( str[0] );
+ }
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isalnum( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isalpha( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isalpha( (int) str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isalpha( (int) str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isdigit( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isdigit( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ! ::isdigit( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool islower( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::islower( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::islower( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isspace( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isspace( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isspace( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool istitle( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+
+ if ( len == 0 ) return false;
+ if ( len == 1 ) return ::isupper( str[0] );
+
+ bool cased = false, previous_is_cased = false;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::isupper( str[i] ) )
+ {
+ if ( previous_is_cased )
+ {
+ return false;
+ }
+
+ previous_is_cased = true;
+ cased = true;
+ }
+ else if ( ::islower( str[i] ) )
+ {
+ if (!previous_is_cased)
+ {
+ return false;
+ }
+
+ previous_is_cased = true;
+ cased = true;
+
+ }
+ else
+ {
+ previous_is_cased = false;
+ }
+ }
+
+ return cased;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isupper( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isupper( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isupper( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string capitalize( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+
+ if ( len > 0)
+ {
+ if (::islower(s[0])) s[0] = (char) ::toupper( s[0] );
+ }
+
+ for ( i = 1; i < len; ++i )
+ {
+ if (::isupper(s[i])) s[i] = (char) ::tolower( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string lower( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::isupper( s[i] ) ) s[i] = (char) ::tolower( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string upper( const std::string & str )
+ {
+ std::string s( str ) ;
+ std::string::size_type len = s.size(), i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::islower( s[i] ) ) s[i] = (char) ::toupper( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string swapcase( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::islower( s[i] ) ) s[i] = (char) ::toupper( s[i] );
+ else if (::isupper( s[i] ) ) s[i] = (char) ::tolower( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string title( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+ bool previous_is_cased = false;
+
+ for ( i = 0; i < len; ++i )
+ {
+ int c = s[i];
+ if ( ::islower(c) )
+ {
+ if ( !previous_is_cased )
+ {
+ s[i] = (char) ::toupper(c);
+ }
+ previous_is_cased = true;
+ }
+ else if ( ::isupper(c) )
+ {
+ if ( previous_is_cased )
+ {
+ s[i] = (char) ::tolower(c);
+ }
+ previous_is_cased = true;
+ }
+ else
+ {
+ previous_is_cased = false;
+ }
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string translate( const std::string & str, const std::string & table, const std::string & deletechars )
+ {
+ std::string s;
+ std::string::size_type len = str.size(), dellen = deletechars.size();
+
+ if ( table.size() != 256 )
+ {
+ // TODO : raise exception instead
+ return str;
+ }
+
+ //if nothing is deleted, use faster code
+ if ( dellen == 0 )
+ {
+ s = str;
+ for ( std::string::size_type i = 0; i < len; ++i )
+ {
+ s[i] = table[ s[i] ];
+ }
+ return s;
+ }
+
+
+ int trans_table[256];
+ for ( int i = 0; i < 256; i++)
+ {
+ trans_table[i] = table[i];
+ }
+
+ for ( std::string::size_type i = 0; i < dellen; i++)
+ {
+ trans_table[(int) deletechars[i] ] = -1;
+ }
+
+ for ( std::string::size_type i = 0; i < len; ++i )
+ {
+ if ( trans_table[ (int) str[i] ] != -1 )
+ {
+ s += table[ str[i] ];
+ }
+ }
+
+ return s;
+
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string zfill( const std::string & str, int width )
+ {
+ int len = (int)str.size();
+
+ if ( len >= width )
+ {
+ return str;
+ }
+
+ std::string s( str );
+
+ int fill = width - len;
+
+ s = std::string( fill, '0' ) + s;
+
+
+ if ( s[fill] == '+' || s[fill] == '-' )
+ {
+ s[0] = s[fill];
+ s[fill] = '0';
+ }
+
+ return s;
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string ljust( const std::string & str, int width )
+ {
+ std::string::size_type len = str.size();
+ if ( (( int ) len ) >= width ) return str;
+ return str + std::string( width - len, ' ' );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string rjust( const std::string & str, int width )
+ {
+ std::string::size_type len = str.size();
+ if ( (( int ) len ) >= width ) return str;
+ return std::string( width - len, ' ' ) + str;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string center( const std::string & str, int width )
+ {
+ int len = (int) str.size();
+ int marg, left;
+
+ if ( len >= width ) return str;
+
+ marg = width - len;
+ left = marg / 2 + (marg & width & 1);
+
+ return std::string( left, ' ' ) + str + std::string( marg - left, ' ' );
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string slice( const std::string & str, int start, int end )
+ {
+ ADJUST_INDICES(start, end, (int) str.size());
+ if ( start >= end ) return "";
+ return str.substr( start, end - start );
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int find( const std::string & str, const std::string & sub, int start, int end )
+ {
+ ADJUST_INDICES(start, end, (int) str.size());
+
+ std::string::size_type result = str.find( sub, start );
+
+ // If we cannot find the string, or if the end-point of our found substring is past
+ // the allowed end limit, return that it can't be found.
+ if( result == std::string::npos ||
+ (result + sub.size() > (std::string::size_type)end) )
+ {
+ return -1;
+ }
+
+ return (int) result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int index( const std::string & str, const std::string & sub, int start, int end )
+ {
+ return find( str, sub, start, end );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int rfind( const std::string & str, const std::string & sub, int start, int end )
+ {
+ ADJUST_INDICES(start, end, (int) str.size());
+
+ std::string::size_type result = str.rfind( sub, end );
+
+ if( result == std::string::npos ||
+ result < (std::string::size_type)start ||
+ (result + sub.size() > (std::string::size_type)end))
+ return -1;
+
+ return (int)result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int rindex( const std::string & str, const std::string & sub, int start, int end )
+ {
+ return rfind( str, sub, start, end );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string expandtabs( const std::string & str, int tabsize )
+ {
+ std::string s( str );
+
+ std::string::size_type len = str.size(), i = 0;
+ int offset = 0;
+
+ int j = 0;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( str[i] == '\t' )
+ {
+
+ if ( tabsize > 0 )
+ {
+ int fillsize = tabsize - (j % tabsize);
+ j += fillsize;
+ s.replace( i + offset, 1, std::string( fillsize, ' ' ));
+ offset += fillsize - 1;
+ }
+ else
+ {
+ s.replace( i + offset, 1, "" );
+ offset -= 1;
+ }
+
+ }
+ else
+ {
+ j++;
+
+ if (str[i] == '\n' || str[i] == '\r')
+ {
+ j = 0;
+ }
+ }
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int count( const std::string & str, const std::string & substr, int start, int end )
+ {
+ int nummatches = 0;
+ int cursor = start;
+
+ while ( 1 )
+ {
+ cursor = find( str, substr, cursor, end );
+
+ if ( cursor < 0 ) break;
+
+ cursor += (int) substr.size();
+ nummatches += 1;
+ }
+
+ return nummatches;
+
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count )
+ {
+ int sofar = 0;
+ int cursor = 0;
+ std::string s( str );
+
+ std::string::size_type oldlen = oldstr.size(), newlen = newstr.size();
+
+ while ( ( cursor = find( s, oldstr, cursor ) ) != -1 )
+ {
+ if ( count > -1 && sofar >= count )
+ {
+ break;
+ }
+
+ s.replace( cursor, oldlen, newstr );
+
+ cursor += (int) newlen;
+ ++sofar;
+ }
+
+ return s;
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends )
+ {
+ result.clear();
+ std::string::size_type len = str.size(), i, j, eol;
+
+ for (i = j = 0; i < len; )
+ {
+ while (i < len && str[i] != '\n' && str[i] != '\r') i++;
+
+ eol = i;
+ if (i < len)
+ {
+ if (str[i] == '\r' && i + 1 < len && str[i+1] == '\n')
+ {
+ i += 2;
+ }
+ else
+ {
+ i++;
+ }
+ if (keepends)
+ eol = i;
+
+ }
+
+ result.push_back( str.substr( j, eol - j ) );
+ j = i;
+
+ }
+
+ if (j < len)
+ {
+ result.push_back( str.substr( j, len - j ) );
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string mul( const std::string & str, int n )
+ {
+ // Early exits
+ if (n <= 0) return "";
+ if (n == 1) return str;
+
+ std::ostringstream os;
+ for(int i=0; i<n; ++i)
+ {
+ os << str;
+ }
+ return os.str();
+ }
+
+
+
+namespace os
+{
+namespace path
+{
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ /// These functions are C++ ports of the python2.6 versions of os.path,
+ /// and come from genericpath.py, ntpath.py, posixpath.py
+
+ /// Split a pathname into drive and path specifiers.
+ /// Returns drivespec, pathspec. Either part may be empty.
+ void splitdrive_nt(std::string & drivespec, std::string & pathspec,
+ const std::string & p)
+ {
+ if(pystring::slice(p, 1, 2) == ":")
+ {
+ std::string path = p; // In case drivespec == p
+ drivespec = pystring::slice(path, 0, 2);
+ pathspec = pystring::slice(path, 2);
+ }
+ else
+ {
+ drivespec = "";
+ pathspec = p;
+ }
+ }
+
+ // On Posix, drive is always empty
+ void splitdrive_posix(std::string & drivespec, std::string & pathspec,
+ const std::string & path)
+ {
+ drivespec = "";
+ pathspec = path;
+ }
+
+ void splitdrive(std::string & drivespec, std::string & pathspec,
+ const std::string & path)
+ {
+#ifdef WINDOWS
+ return splitdrive_nt(drivespec, pathspec, path);
+#else
+ return splitdrive_posix(drivespec, pathspec, path);
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ // Test whether a path is absolute
+ // In windows, if the character to the right of the colon
+ // is a forward or backslash it's absolute.
+ bool isabs_nt(const std::string & path)
+ {
+ std::string drivespec, pathspec;
+ splitdrive_nt(drivespec, pathspec, path);
+ if(pathspec.empty()) return false;
+ return ((pathspec[0] == '/') || (pathspec[0] == '\\'));
+ }
+
+ bool isabs_posix(const std::string & s)
+ {
+ return pystring::startswith(s, "/");
+ }
+
+ bool isabs(const std::string & path)
+ {
+#ifdef WINDOWS
+ return isabs_nt(path);
+#else
+ return isabs_posix(path);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ std::string abspath_nt(const std::string & path, const std::string & cwd)
+ {
+ std::string p = path;
+ if(!isabs_nt(p)) p = join_nt(cwd, p);
+ return normpath_nt(p);
+ }
+
+ std::string abspath_posix(const std::string & path, const std::string & cwd)
+ {
+ std::string p = path;
+ if(!isabs_posix(p)) p = join_posix(cwd, p);
+ return normpath_posix(p);
+ }
+
+ std::string abspath(const std::string & path, const std::string & cwd)
+ {
+#ifdef WINDOWS
+ return abspath_nt(path, cwd);
+#else
+ return abspath_posix(path, cwd);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ std::string join_nt(const std::vector< std::string > & paths)
+ {
+ if(paths.empty()) return "";
+ if(paths.size() == 1) return paths[0];
+
+ std::string path = paths[0];
+
+ for(unsigned int i=1; i<paths.size(); ++i)
+ {
+ std::string b = paths[i];
+
+ bool b_nts = false;
+ if(path.empty())
+ {
+ b_nts = true;
+ }
+ else if(isabs_nt(b))
+ {
+ // This probably wipes out path so far. However, it's more
+ // complicated if path begins with a drive letter:
+ // 1. join('c:', '/a') == 'c:/a'
+ // 2. join('c:/', '/a') == 'c:/a'
+ // But
+ // 3. join('c:/a', '/b') == '/b'
+ // 4. join('c:', 'd:/') = 'd:/'
+ // 5. join('c:/', 'd:/') = 'd:/'
+
+ if( (pystring::slice(path, 1, 2) != ":") ||
+ (pystring::slice(b, 1, 2) == ":") )
+ {
+ // Path doesnt start with a drive letter
+ b_nts = true;
+ }
+ // Else path has a drive letter, and b doesn't but is absolute.
+ else if((path.size()>3) ||
+ ((path.size()==3) && !pystring::endswith(path, "/") && !pystring::endswith(path, "\\")))
+ {
+ b_nts = true;
+ }
+ }
+
+ if(b_nts)
+ {
+ path = b;
+ }
+ else
+ {
+ // Join, and ensure there's a separator.
+ // assert len(path) > 0
+ if( pystring::endswith(path, "/") || pystring::endswith(path, "\\"))
+ {
+ if(pystring::startswith(b,"/") || pystring::startswith(b,"\\"))
+ {
+ path += pystring::slice(b, 1);
+ }
+ else
+ {
+ path += b;
+ }
+ }
+ else if(pystring::endswith(path, ":"))
+ {
+ path += b;
+ }
+ else if(!b.empty())
+ {
+ if(pystring::startswith(b,"/") || pystring::startswith(b,"\\"))
+ {
+ path += b;
+ }
+ else
+ {
+ path += "\\" + b;
+ }
+ }
+ else
+ {
+ // path is not empty and does not end with a backslash,
+ // but b is empty; since, e.g., split('a/') produces
+ // ('a', ''), it's best if join() adds a backslash in
+ // this case.
+ path += "\\";
+ }
+ }
+ }
+
+ return path;
+ }
+
+ // Join two or more pathname components, inserting "\\" as needed.
+ std::string join_nt(const std::string & a, const std::string & b)
+ {
+ std::vector< std::string > paths(2);
+ paths[0] = a;
+ paths[1] = b;
+ return join_nt(paths);
+ }
+
+ // Join pathnames.
+ // If any component is an absolute path, all previous path components
+ // will be discarded.
+ // Ignore the previous parts if a part is absolute.
+ // Insert a '/' unless the first part is empty or already ends in '/'.
+
+ std::string join_posix(const std::vector< std::string > & paths)
+ {
+ if(paths.empty()) return "";
+ if(paths.size() == 1) return paths[0];
+
+ std::string path = paths[0];
+
+ for(unsigned int i=1; i<paths.size(); ++i)
+ {
+ std::string b = paths[i];
+ if(pystring::startswith(b, "/"))
+ {
+ path = b;
+ }
+ else if(path.empty() || pystring::endswith(path, "/"))
+ {
+ path += b;
+ }
+ else
+ {
+ path += "/" + b;
+ }
+ }
+
+ return path;
+ }
+
+ std::string join_posix(const std::string & a, const std::string & b)
+ {
+ std::vector< std::string > paths(2);
+ paths[0] = a;
+ paths[1] = b;
+ return join_posix(paths);
+ }
+
+ std::string join(const std::string & path1, const std::string & path2)
+ {
+#ifdef WINDOWS
+ return join_nt(path1, path2);
+#else
+ return join_posix(path1, path2);
+#endif
+ }
+
+
+ std::string join(const std::vector< std::string > & paths)
+ {
+#ifdef WINDOWS
+ return join_nt(paths);
+#else
+ return join_posix(paths);
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+
+ // Split a pathname.
+ // Return (head, tail) where tail is everything after the final slash.
+ // Either part may be empty
+
+ void split_nt(std::string & head, std::string & tail, const std::string & path)
+ {
+ std::string d, p;
+ splitdrive_nt(d, p, path);
+
+ // set i to index beyond p's last slash
+ int i = (int)p.size();
+
+ while(i>0 && (p[i-1] != '\\') && (p[i-1] != '/'))
+ {
+ i = i - 1;
+ }
+
+ head = pystring::slice(p,0,i);
+ tail = pystring::slice(p,i); // now tail has no slashes
+
+ // remove trailing slashes from head, unless it's all slashes
+ std::string head2 = head;
+ while(!head2.empty() && ((pystring::slice(head2,-1) == "/") ||
+ (pystring::slice(head2,-1) == "\\")))
+ {
+ head2 = pystring::slice(head,0,-1);
+ }
+
+ if(!head2.empty()) head = head2;
+ head = d + head;
+ }
+
+
+ // Split a path in head (everything up to the last '/') and tail (the
+ // rest). If the path ends in '/', tail will be empty. If there is no
+ // '/' in the path, head will be empty.
+ // Trailing '/'es are stripped from head unless it is the root.
+
+ void split_posix(std::string & head, std::string & tail, const std::string & p)
+ {
+ int i = pystring::rfind(p, "/") + 1;
+
+ head = pystring::slice(p,0,i);
+ tail = pystring::slice(p,i);
+
+ if(!head.empty() && (head != pystring::mul("/", (int) head.size())))
+ {
+ head = pystring::rstrip(head, "/");
+ }
+ }
+
+ void split(std::string & head, std::string & tail, const std::string & path)
+ {
+#ifdef WINDOWS
+ return split_nt(head, tail, path);
+#else
+ return split_posix(head, tail, path);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ std::string basename_nt(const std::string & path)
+ {
+ std::string head, tail;
+ split_nt(head, tail, path);
+ return tail;
+ }
+
+ std::string basename_posix(const std::string & path)
+ {
+ std::string head, tail;
+ split_posix(head, tail, path);
+ return tail;
+ }
+
+ std::string basename(const std::string & path)
+ {
+#ifdef WINDOWS
+ return basename_nt(path);
+#else
+ return basename_posix(path);
+#endif
+ }
+
+ std::string dirname_nt(const std::string & path)
+ {
+ std::string head, tail;
+ split_nt(head, tail, path);
+ return head;
+ }
+
+ std::string dirname_posix(const std::string & path)
+ {
+ std::string head, tail;
+ split_posix(head, tail, path);
+ return head;
+ }
+
+ std::string dirname(const std::string & path)
+ {
+#ifdef WINDOWS
+ return dirname_nt(path);
+#else
+ return dirname_posix(path);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ // Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
+ std::string normpath_nt(const std::string & p)
+ {
+ std::string path = p;
+ path = pystring::replace(path, "/","\\");
+
+ std::string prefix;
+ splitdrive_nt(prefix, path, path);
+
+ // We need to be careful here. If the prefix is empty, and the path starts
+ // with a backslash, it could either be an absolute path on the current
+ // drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It
+ // is therefore imperative NOT to collapse multiple backslashes blindly in
+ // that case.
+ // The code below preserves multiple backslashes when there is no drive
+ // letter. This means that the invalid filename \\\a\b is preserved
+ // unchanged, where a\\\b is normalised to a\b. It's not clear that there
+ // is any better behaviour for such edge cases.
+
+ if(prefix.empty())
+ {
+ // No drive letter - preserve initial backslashes
+ while(pystring::slice(path,0,1) == "\\")
+ {
+ prefix = prefix + "\\";
+ path = pystring::slice(path,1);
+ }
+ }
+ else
+ {
+ // We have a drive letter - collapse initial backslashes
+ if(pystring::startswith(path, "\\"))
+ {
+ prefix = prefix + "\\";
+ path = pystring::lstrip(path, "\\");
+ }
+ }
+
+ std::vector<std::string> comps;
+ pystring::split(path, comps, "\\");
+
+ int i = 0;
+
+ while(i<(int)comps.size())
+ {
+ if(comps[i].empty() || comps[i] == ".")
+ {
+ comps.erase(comps.begin()+i);
+ }
+ else if(comps[i] == "..")
+ {
+ if(i>0 && comps[i-1] != "..")
+ {
+ comps.erase(comps.begin()+i-1, comps.begin()+i+1);
+ i -= 1;
+ }
+ else if(i == 0 && pystring::endswith(prefix, "\\"))
+ {
+ comps.erase(comps.begin()+i);
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ // If the path is now empty, substitute '.'
+ if(prefix.empty() && comps.empty())
+ {
+ comps.push_back(".");
+ }
+
+ return prefix + pystring::join("\\", comps);
+ }
+
+ // Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
+ // It should be understood that this may change the meaning of the path
+ // if it contains symbolic links!
+ // Normalize path, eliminating double slashes, etc.
+
+ std::string normpath_posix(const std::string & p)
+ {
+ if(p.empty()) return ".";
+
+ std::string path = p;
+
+ int initial_slashes = pystring::startswith(path,"/") ? 1 : 0;
+
+ // POSIX allows one or two initial slashes, but treats three or more
+ // as single slash.
+
+ if (initial_slashes && pystring::startswith(path,"//")
+ && !pystring::startswith(path,"///"))
+ initial_slashes = 2;
+
+ std::vector<std::string> comps, new_comps;
+ pystring::split(path, comps, "/");
+
+ for(unsigned int i=0; i<comps.size(); ++i)
+ {
+ std::string comp = comps[i];
+ if(comp.empty() || comp == ".")
+ continue;
+
+ if( (comp != "..") || ((initial_slashes == 0) && new_comps.empty()) ||
+ (!new_comps.empty() && new_comps[new_comps.size()-1] == ".."))
+ {
+ new_comps.push_back(comp);
+ }
+ else if (!new_comps.empty())
+ {
+ new_comps.pop_back();
+ }
+ }
+
+ path = pystring::join("/", new_comps);
+
+ if (initial_slashes > 0)
+ path = pystring::mul("/",initial_slashes) + path;
+
+ if(path.empty()) return ".";
+ return path;
+ }
+
+ std::string normpath(const std::string & path)
+ {
+#ifdef WINDOWS
+ return normpath_nt(path);
+#else
+ return normpath_posix(path);
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ // Split the extension from a pathname.
+ // Extension is everything from the last dot to the end, ignoring
+ // leading dots. Returns "(root, ext)"; ext may be empty.
+ // It is always true that root + ext == p
+
+ void splitext_generic(std::string & root, std::string & ext,
+ const std::string & p,
+ const std::string & sep,
+ const std::string & altsep,
+ const std::string & extsep)
+ {
+ int sepIndex = pystring::rfind(p, sep);
+ if(!altsep.empty())
+ {
+ int altsepIndex = pystring::rfind(p, altsep);
+ sepIndex = std::max(sepIndex, altsepIndex);
+ }
+
+ int dotIndex = pystring::rfind(p, extsep);
+ if(dotIndex > sepIndex)
+ {
+ // Skip all leading dots
+ int filenameIndex = sepIndex + 1;
+
+ while(filenameIndex < dotIndex)
+ {
+ if(pystring::slice(p,filenameIndex) != extsep)
+ {
+ root = pystring::slice(p, 0, dotIndex);
+ ext = pystring::slice(p, dotIndex);
+ return;
+ }
+
+ filenameIndex += 1;
+ }
+ }
+
+ root = p;
+ ext = "";
+ }
+
+ void splitext_nt(std::string & root, std::string & ext, const std::string & path)
+ {
+ return splitext_generic(root, ext, path,
+ "\\", "/", ".");
+ }
+
+ void splitext_posix(std::string & root, std::string & ext, const std::string & path)
+ {
+ return splitext_generic(root, ext, path,
+ "/", "", ".");
+ }
+
+ void splitext(std::string & root, std::string & ext, const std::string & path)
+ {
+#ifdef WINDOWS
+ return splitext_nt(root, ext, path);
+#else
+ return splitext_posix(root, ext, path);
+#endif
+ }
+
+} // namespace path
+} // namespace os
+
+
+}//namespace pystring
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/apps/share/pystring.h b/src/apps/share/pystring.h
new file mode 100644
index 0000000..f0729db
--- /dev/null
+++ b/src/apps/share/pystring.h
@@ -0,0 +1,438 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// Neither the name of the organization Sony Pictures Imageworks nor the
+// names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_OCIO_PYSTRING_H
+#define INCLUDED_OCIO_PYSTRING_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <string>
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+// Version 1.1.2
+// https://github.com/imageworks/pystring/tarball/v1.1.2
+
+namespace pystring
+{
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @mainpage pystring
+ ///
+ /// This is a set of functions matching the interface and behaviors of python string methods
+ /// (as of python 2.3) using std::string.
+ ///
+ /// Overlapping functionality ( such as index and slice/substr ) of std::string is included
+ /// to match python interfaces.
+ ///
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @defgroup functions pystring
+ /// @{
+
+
+ #define MAX_32BIT_INT 2147483647
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with only its first character capitalized.
+ ///
+ std::string capitalize( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return centered in a string of length width. Padding is done using spaces.
+ ///
+ std::string center( const std::string & str, int width );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the number of occurrences of substring sub in string S[start:end]. Optional
+ /// arguments start and end are interpreted as in slice notation.
+ ///
+ int count( const std::string & str, const std::string & substr, int start = 0, int end = MAX_32BIT_INT);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return True if the string ends with the specified suffix, otherwise return False. With
+ /// optional start, test beginning at that position. With optional end, stop comparing at that position.
+ ///
+ bool endswith( const std::string & str, const std::string & suffix, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string where all tab characters are expanded using spaces. If tabsize
+ /// is not given, a tab size of 8 characters is assumed.
+ ///
+ std::string expandtabs( const std::string & str, int tabsize = 8);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the lowest index in the string where substring sub is found, such that sub is
+ /// contained in the range [start, end). Optional arguments start and end are interpreted as
+ /// in slice notation. Return -1 if sub is not found.
+ ///
+ int find( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Synonym of find right now. Python version throws exceptions. This one currently doesn't
+ ///
+ int index( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all characters in the string are alphanumeric and there is at least one
+ /// character, false otherwise.
+ ///
+ bool isalnum( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all characters in the string are alphabetic and there is at least one
+ /// character, false otherwise
+ ///
+ bool isalpha( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all characters in the string are digits and there is at least one
+ /// character, false otherwise.
+ ///
+ bool isdigit( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all cased characters in the string are lowercase and there is at least one
+ /// cased character, false otherwise.
+ ///
+ bool islower( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if there are only whitespace characters in the string and there is at least
+ /// one character, false otherwise.
+ ///
+ bool isspace( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if the string is a titlecased string and there is at least one character,
+ /// i.e. uppercase characters may only follow uncased characters and lowercase characters only
+ /// cased ones. Return false otherwise.
+ ///
+ bool istitle( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all cased characters in the string are uppercase and there is at least one
+ /// cased character, false otherwise.
+ ///
+ bool isupper( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a string which is the concatenation of the strings in the sequence seq.
+ /// The separator between elements is the str argument
+ ///
+ std::string join( const std::string & str, const std::vector< std::string > & seq );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the string left justified in a string of length width. Padding is done using
+ /// spaces. The original string is returned if width is less than str.size().
+ ///
+ std::string ljust( const std::string & str, int width );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string converted to lowercase.
+ ///
+ std::string lower( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with leading characters removed. If chars is omitted or None,
+ /// whitespace characters are removed. If given and not "", chars must be a string; the
+ /// characters in the string will be stripped from the beginning of the string this method
+ /// is called on (argument "str" ).
+ ///
+ std::string lstrip( const std::string & str, const std::string & chars = "" );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string, concatenated N times, together.
+ /// Corresponds to the __mul__ operator.
+ ///
+ std::string mul( const std::string & str, int n);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the string around first occurance of sep.
+ /// Three strings will always placed into result. If sep is found, the strings will
+ /// be the text before sep, sep itself, and the remaining text. If sep is
+ /// not found, the original string will be returned with two empty strings.
+ ///
+ void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with all occurrences of substring old replaced by new. If
+ /// the optional argument count is given, only the first count occurrences are replaced.
+ ///
+ std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count = -1);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the highest index in the string where substring sub is found, such that sub is
+ /// contained within s[start,end]. Optional arguments start and end are interpreted as in
+ /// slice notation. Return -1 on failure.
+ ///
+ int rfind( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Currently a synonym of rfind. The python version raises exceptions. This one currently
+ /// does not
+ ///
+ int rindex( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the string right justified in a string of length width. Padding is done using
+ /// spaces. The original string is returned if width is less than str.size().
+ ///
+ std::string rjust( const std::string & str, int width);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the string around last occurance of sep.
+ /// Three strings will always placed into result. If sep is found, the strings will
+ /// be the text before sep, sep itself, and the remaining text. If sep is
+ /// not found, the original string will be returned with two empty strings.
+ ///
+ void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with trailing characters removed. If chars is "", whitespace
+ /// characters are removed. If not "", the characters in the string will be stripped from the
+ /// end of the string this method is called on.
+ ///
+ std::string rstrip( const std::string & str, const std::string & chars = "" );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
+ /// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
+ /// any whitespace string is a separator.
+ ///
+ void split( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
+ /// Does a number of splits starting at the end of the string, the result still has the
+ /// split strings in their original order.
+ /// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
+ /// any whitespace string is a separator.
+ ///
+ void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a list of the lines in the string, breaking at line boundaries. Line breaks
+ /// are not included in the resulting list unless keepends is given and true.
+ ///
+ void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends = false );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return True if string starts with the prefix, otherwise return False. With optional start,
+ /// test string beginning at that position. With optional end, stop comparing string at that
+ /// position
+ ///
+ bool startswith( const std::string & str, const std::string & prefix, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with leading and trailing characters removed. If chars is "",
+ /// whitespace characters are removed. If given not "", the characters in the string will be
+ /// stripped from the both ends of the string this method is called on.
+ ///
+ std::string strip( const std::string & str, const std::string & chars = "" );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with uppercase characters converted to lowercase and vice versa.
+ ///
+ std::string swapcase( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a titlecased version of the string: words start with uppercase characters,
+ /// all remaining cased characters are lowercase.
+ ///
+ std::string title( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string where all characters occurring in the optional argument
+ /// deletechars are removed, and the remaining characters have been mapped through the given
+ /// translation table, which must be a string of length 256.
+ ///
+ std::string translate( const std::string & str, const std::string & table, const std::string & deletechars = "");
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string converted to uppercase.
+ ///
+ std::string upper( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the numeric string left filled with zeros in a string of length width. The original
+ /// string is returned if width is less than str.size().
+ ///
+ std::string zfill( const std::string & str, int width );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief function matching python's slice functionality.
+ ///
+ std::string slice( const std::string & str, int start = 0, int end = MAX_32BIT_INT);
+
+ ///
+ /// @ }
+ ///
+
+
+namespace os
+{
+namespace path
+{
+ // All of the function below have three versions.
+ // Example:
+ // join(...)
+ // join_nt(...)
+ // join_posix(...)
+ //
+ // The regular function dispatches to the other versions - based on the OS
+ // at compile time - to match the result you'd get from the python
+ // interepreter on the same operating system
+ //
+ // Should you want to 'lock off' to a particular version of the string
+ // manipulation across *all* operating systems, use the version with the
+ // _OS you are interested in. I.e., you can use posix style path joining,
+ // even on Windows, with join_posix.
+ //
+ // The naming, (nt, posix) matches the cpython source implementation.
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @defgroup functions pystring::os::path
+ /// @{
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the base name of pathname path. This is the second half of the pair returned
+ /// by split(path). Note that the result of this function is different from the Unix basename
+ /// program; where basename for '/foo/bar/' returns 'bar', the basename() function returns an
+ /// empty string ('').
+
+ std::string basename(const std::string & path);
+ std::string basename_nt(const std::string & path);
+ std::string basename_posix(const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the directory name of pathname path. This is the first half of the pair
+ /// returned by split(path).
+
+ std::string dirname(const std::string & path);
+ std::string dirname_nt(const std::string & path);
+ std::string dirname_posix(const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return True if path is an absolute pathname. On Unix, that means it begins with a
+ /// slash, on Windows that it begins with a (back)slash after chopping off a potential drive
+ /// letter.
+
+ bool isabs(const std::string & path);
+ bool isabs_nt(const std::string & path);
+ bool isabs_posix(const std::string & s);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a normalized absolutized version of the pathname path.
+ ///
+ /// NOTE: This differs from the interface of the python equivalent in that it requires you
+ /// to pass in the current working directory as an argument.
+
+ std::string abspath(const std::string & path, const std::string & cwd);
+ std::string abspath_nt(const std::string & path, const std::string & cwd);
+ std::string abspath_posix(const std::string & path, const std::string & cwd);
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Join one or more path components intelligently. If any component is an absolute
+ /// path, all previous components (on Windows, including the previous drive letter, if there
+ /// was one) are thrown away, and joining continues. The return value is the concatenation of
+ /// path1, and optionally path2, etc., with exactly one directory separator (os.sep) inserted
+ /// between components, unless path2 is empty. Note that on Windows, since there is a current
+ /// directory for each drive, os.path.join("c:", "foo") represents a path relative to the
+ /// current directory on drive C: (c:foo), not c:\foo.
+
+ /// This dispatches based on the compilation OS
+ std::string join(const std::string & path1, const std::string & path2);
+ std::string join_nt(const std::string & path1, const std::string & path2);
+ std::string join_posix(const std::string & path1, const std::string & path2);
+
+ std::string join(const std::vector< std::string > & paths);
+ std::string join_nt(const std::vector< std::string > & paths);
+ std::string join_posix(const std::vector< std::string > & paths);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Normalize a pathname. This collapses redundant separators and up-level references
+ /// so that A//B, A/B/, A/./B and A/foo/../B all become A/B. It does not normalize the case
+ /// (use normcase() for that). On Windows, it converts forward slashes to backward slashes.
+ /// It should be understood that this may change the meaning of the path if it contains
+ /// symbolic links!
+
+ std::string normpath(const std::string & path);
+ std::string normpath_nt(const std::string & path);
+ std::string normpath_posix(const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the pathname path into a pair, (head, tail) where tail is the last pathname
+ /// component and head is everything leading up to that. The tail part will never contain a
+ /// slash; if path ends in a slash, tail will be empty. If there is no slash in path, head
+ /// will be empty. If path is empty, both head and tail are empty. Trailing slashes are
+ /// stripped from head unless it is the root (one or more slashes only). In all cases,
+ /// join(head, tail) returns a path to the same location as path (but the strings may
+ /// differ).
+
+ void split(std::string & head, std::string & tail, const std::string & path);
+ void split_nt(std::string & head, std::string & tail, const std::string & path);
+ void split_posix(std::string & head, std::string & tail, const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the pathname path into a pair (drive, tail) where drive is either a drive
+ /// specification or the empty string. On systems which do not use drive specifications,
+ /// drive will always be the empty string. In all cases, drive + tail will be the same as
+ /// path.
+
+ void splitdrive(std::string & drivespec, std::string & pathspec, const std::string & path);
+ void splitdrive_nt(std::string & drivespec, std::string & pathspec, const std::string & p);
+ void splitdrive_posix(std::string & drivespec, std::string & pathspec, const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the pathname path into a pair (root, ext) such that root + ext == path, and
+ /// ext is empty or begins with a period and contains at most one period. Leading periods on
+ /// the basename are ignored; splitext('.cshrc') returns ('.cshrc', '').
+
+ void splitext(std::string & root, std::string & ext, const std::string & path);
+ void splitext_nt(std::string & root, std::string & ext, const std::string & path);
+ void splitext_posix(std::string & root, std::string & ext, const std::string & path);
+
+ ///
+ /// @ }
+ ///
+} // namespace path
+} // namespace os
+
+} // namespace pystring
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/apps/share/strutil.cpp b/src/apps/share/strutil.cpp
new file mode 100644
index 0000000..58938bb
--- /dev/null
+++ b/src/apps/share/strutil.cpp
@@ -0,0 +1,86 @@
+/*
+ Copyright 2008 Larry Gritz and the other authors and contributors.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the software's owners nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ (This is the Modified BSD License)
+*/
+
+
+#include <string>
+#include <cstdarg>
+#include <cstdio>
+#include <vector>
+#include <iostream>
+#include <cmath>
+
+#include "strutil.h"
+
+
+
+std::string
+Strutil::vformat (const char *fmt, va_list ap)
+{
+ // Allocate a buffer on the stack that's big enough for us almost
+ // all the time. Be prepared to allocate dynamically if it doesn't fit.
+ size_t size = 1024;
+ char stackbuf[1024];
+ std::vector<char> dynamicbuf;
+ char *buf = &stackbuf[0];
+
+ while (1) {
+ // Try to vsnprintf into our buffer.
+ va_list apsave;
+#ifdef va_copy
+ va_copy (apsave, ap);
+#else
+ apsave = ap;
+#endif
+ int needed = vsnprintf (buf, size, fmt, ap);
+ va_end (ap);
+
+ // NB. C99 (which modern Linux and OS X follow) says vsnprintf
+ // failure returns the length it would have needed. But older
+ // glibc and current Windows return -1 for failure, i.e., not
+ // telling us how much was needed.
+
+ if (needed < (int)size && needed >= 0) {
+ // It fit fine so we're done.
+ return std::string (buf, (size_t) needed);
+ }
+
+ // vsnprintf reported that it wanted to write more characters
+ // than we allotted. So try again using a dynamic buffer. This
+ // doesn't happen very often if we chose our initial size well.
+ size = (needed > 0) ? (needed+1) : (size*2);
+ dynamicbuf.resize (size);
+ buf = &dynamicbuf[0];
+#ifdef va_copy
+ va_copy (ap, apsave);
+#else
+ ap = apsave;
+#endif
+ }
+}
diff --git a/src/apps/share/strutil.h b/src/apps/share/strutil.h
new file mode 100644
index 0000000..44b50da
--- /dev/null
+++ b/src/apps/share/strutil.h
@@ -0,0 +1,83 @@
+/*
+ Copyright 2008 Larry Gritz and the other authors and contributors.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the software's owners nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ (This is the Modified BSD License)
+*/
+
+
+/////////////////////////////////////////////////////////////////////////
+/// @file strutil.h
+///
+/// @brief String-related utilities, all in namespace Strutil.
+/////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef OPENCOLORIO_STRUTIL_H
+#define OPENCOLORIO_STRUTIL_H
+
+#include <cstdarg>
+#include <string>
+#include <cstring>
+#include <map>
+
+
+#ifndef OPENCOLORIO_PRINTF_ARGS
+# ifndef __GNUC__
+# define __attribute__(x)
+# endif
+ // Enable printf-like warnings with gcc by attaching
+ // OPENIMAGEIO_PRINTF_ARGS to printf-like functions. Eg:
+ //
+ // void foo (const char* fmt, ...) OPENCOLORIO_PRINTF_ARGS(1,2);
+ //
+ // The arguments specify the positions of the format string and the the
+ // beginning of the varargs parameter list respectively.
+ //
+ // For member functions with arguments like the example above, you need
+ // OPENCOLORIO_PRINTF_ARGS(2,3) instead. (gcc includes the implicit this
+ // pointer when it counts member function arguments.)
+# define OPENCOLORIO_PRINTF_ARGS(fmtarg_pos, vararg_pos) \
+ __attribute__ ((format (printf, fmtarg_pos, vararg_pos) ))
+#endif
+
+
+
+/// @namespace Strutil
+///
+/// @brief String-related utilities.
+namespace Strutil {
+
+/// Return a std::string formatted from printf-like arguments -- passed
+/// already as a va_list.
+std::string vformat (const char *fmt, va_list ap)
+ OPENCOLORIO_PRINTF_ARGS(1,0);
+
+}; // namespace Strutil
+
+
+#endif // OPENCOLORIO_STRUTIL_H
diff --git a/src/core/AllocationOp.cpp b/src/core/AllocationOp.cpp
new file mode 100644
index 0000000..ed4c9db
--- /dev/null
+++ b/src/core/AllocationOp.cpp
@@ -0,0 +1,128 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "AllocationOp.h"
+#include "LogOps.h"
+#include "MatrixOps.h"
+#include "Op.h"
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+
+ void CreateAllocationOps(OpRcPtrVec & ops,
+ const AllocationData & data,
+ TransformDirection dir)
+ {
+ if(data.allocation == ALLOCATION_UNIFORM)
+ {
+ float oldmin[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float oldmax[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ float newmin[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float newmax[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ if(data.vars.size() >= 2)
+ {
+ for(int i=0; i<3; ++i)
+ {
+ oldmin[i] = data.vars[0];
+ oldmax[i] = data.vars[1];
+ }
+ }
+
+ CreateFitOp(ops,
+ oldmin, oldmax,
+ newmin, newmax,
+ dir);
+ }
+ else if(data.allocation == ALLOCATION_LG2)
+ {
+ float oldmin[4] = { -10.0f, -10.0f, -10.0f, 0.0f };
+ float oldmax[4] = { 6.0f, 6.0f, 6.0f, 1.0f };
+ float newmin[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float newmax[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ if(data.vars.size() >= 2)
+ {
+ for(int i=0; i<3; ++i)
+ {
+ oldmin[i] = data.vars[0];
+ oldmax[i] = data.vars[1];
+ }
+ }
+
+
+ // Log Settings
+ // output = k * log(mx+b, base) + kb
+
+ float k[3] = { 1.0f, 1.0f, 1.0f };
+ float m[3] = { 1.0f, 1.0f, 1.0f };
+ float b[3] = { 0.0f, 0.0f, 0.0f };
+ float base[3] = { 2.0f, 2.0f, 2.0f };
+ float kb[3] = { 0.0f, 0.0f, 0.0f };
+
+ if(data.vars.size() >= 3)
+ {
+ for(int i=0; i<3; ++i)
+ {
+ b[i] = data.vars[2];
+ }
+ }
+
+ if(dir == TRANSFORM_DIR_FORWARD)
+ {
+ CreateLogOp(ops, k, m, b, base, kb, dir);
+
+ CreateFitOp(ops,
+ oldmin, oldmax,
+ newmin, newmax,
+ dir);
+ }
+ else if(dir == TRANSFORM_DIR_INVERSE)
+ {
+ CreateFitOp(ops,
+ oldmin, oldmax,
+ newmin, newmax,
+ dir);
+
+ CreateLogOp(ops, k, m, b, base, kb, dir);
+ }
+ else
+ {
+ throw Exception("Cannot BuildAllocationOps, unspecified transform direction.");
+ }
+ }
+ else
+ {
+ throw Exception("Unsupported Allocation Type.");
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/AllocationOp.h b/src/core/AllocationOp.h
new file mode 100644
index 0000000..8fd491f
--- /dev/null
+++ b/src/core/AllocationOp.h
@@ -0,0 +1,45 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_ALLOCATIONOP_H
+#define INCLUDED_OCIO_ALLOCATIONOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ void CreateAllocationOps(OpRcPtrVec & ops,
+ const AllocationData & data,
+ TransformDirection dir);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/AllocationTransform.cpp b/src/core/AllocationTransform.cpp
new file mode 100644
index 0000000..592b36e
--- /dev/null
+++ b/src/core/AllocationTransform.cpp
@@ -0,0 +1,182 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+#include <sstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "AllocationOp.h"
+#include "OpBuilders.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ AllocationTransformRcPtr AllocationTransform::Create()
+ {
+ return AllocationTransformRcPtr(new AllocationTransform(), &deleter);
+ }
+
+ void AllocationTransform::deleter(AllocationTransform* t)
+ {
+ delete t;
+ }
+
+
+ class AllocationTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ Allocation allocation_;
+ std::vector<float> vars_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD),
+ allocation_(ALLOCATION_UNIFORM)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ allocation_ = rhs.allocation_;
+ vars_ = rhs.vars_;
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ AllocationTransform::AllocationTransform()
+ : m_impl(new AllocationTransform::Impl)
+ {
+ }
+
+ TransformRcPtr AllocationTransform::createEditableCopy() const
+ {
+ AllocationTransformRcPtr transform = AllocationTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ AllocationTransform::~AllocationTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ AllocationTransform& AllocationTransform::operator= (const AllocationTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection AllocationTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void AllocationTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+
+ Allocation AllocationTransform::getAllocation() const
+ {
+ return getImpl()->allocation_;
+ }
+
+ void AllocationTransform::setAllocation(Allocation allocation)
+ {
+ getImpl()->allocation_ = allocation;
+ }
+
+ int AllocationTransform::getNumVars() const
+ {
+ return static_cast<int>(getImpl()->vars_.size());
+ }
+
+ void AllocationTransform::getVars(float * vars) const
+ {
+ if(!getImpl()->vars_.empty())
+ {
+ memcpy(vars,
+ &getImpl()->vars_[0],
+ getImpl()->vars_.size()*sizeof(float));
+ }
+ }
+
+ void AllocationTransform::setVars(int numvars, const float * vars)
+ {
+ getImpl()->vars_.resize(numvars);
+
+ if(!getImpl()->vars_.empty())
+ {
+ memcpy(&getImpl()->vars_[0],
+ vars,
+ numvars*sizeof(float));
+ }
+ }
+
+ std::ostream& operator<< (std::ostream& os, const AllocationTransform& t)
+ {
+ os << "<AllocationTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ void BuildAllocationOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const AllocationTransform& allocationTransform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ allocationTransform.getDirection());
+
+ AllocationData data;
+ data.allocation = allocationTransform.getAllocation();
+ data.vars.resize(allocationTransform.getNumVars());
+ if(!data.vars.empty())
+ {
+ allocationTransform.getVars(&data.vars[0]);
+ }
+
+ CreateAllocationOps(ops, data, combinedDir);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Baker.cpp b/src/core/Baker.cpp
new file mode 100644
index 0000000..581df5f
--- /dev/null
+++ b/src/core/Baker.cpp
@@ -0,0 +1,297 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <vector>
+#include <iostream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "MathUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+ BakerRcPtr Baker::Create()
+ {
+ return BakerRcPtr(new Baker(), &deleter);
+ }
+
+ void Baker::deleter(Baker* c)
+ {
+ delete c;
+ }
+
+ class Baker::Impl
+ {
+ public:
+
+ ConfigRcPtr config_;
+ std::string formatName_;
+ std::string type_;
+ std::string metadata_;
+ std::string inputSpace_;
+ std::string shaperSpace_;
+ std::string looks_;
+ std::string targetSpace_;
+ int shapersize_;
+ int cubesize_;
+
+ Impl() :
+ shapersize_(-1),
+ cubesize_(-1)
+ {
+ }
+
+ ~Impl()
+ {
+ }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ config_ = rhs.config_;
+ formatName_ = rhs.formatName_;
+ inputSpace_ = rhs.inputSpace_;
+ shaperSpace_ = rhs.shaperSpace_;
+ looks_ = rhs.looks_;
+ targetSpace_ = rhs.targetSpace_;
+ shapersize_ = rhs.shapersize_;
+ cubesize_ = rhs.cubesize_;
+ return *this;
+ }
+ };
+
+ Baker::Baker()
+ : m_impl(new Baker::Impl)
+ {
+ }
+
+ Baker::~Baker()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ BakerRcPtr Baker::createEditableCopy() const
+ {
+ BakerRcPtr oven = Baker::Create();
+ *oven->m_impl = *m_impl;
+ return oven;
+ }
+
+ void Baker::setConfig(const ConstConfigRcPtr & config)
+ {
+ getImpl()->config_ = config->createEditableCopy();
+ }
+
+ ConstConfigRcPtr Baker::getConfig() const
+ {
+ return getImpl()->config_;
+ }
+
+ int Baker::getNumFormats()
+ {
+ return FormatRegistry::GetInstance().getNumFormats(FORMAT_CAPABILITY_WRITE);
+ }
+
+ const char * Baker::getFormatNameByIndex(int index)
+ {
+ return FormatRegistry::GetInstance().getFormatNameByIndex(FORMAT_CAPABILITY_WRITE, index);
+ }
+
+ const char * Baker::getFormatExtensionByIndex(int index)
+ {
+ return FormatRegistry::GetInstance().getFormatExtensionByIndex(FORMAT_CAPABILITY_WRITE, index);
+ }
+
+ void Baker::setFormat(const char * formatName)
+ {
+ getImpl()->formatName_ = formatName;
+ }
+
+ const char * Baker::getFormat() const
+ {
+ return getImpl()->formatName_.c_str();
+ }
+
+ void Baker::setType(const char * type)
+ {
+ getImpl()->type_ = type;
+ }
+
+ const char * Baker::getType() const
+ {
+ return getImpl()->type_.c_str();
+ }
+
+ void Baker::setMetadata(const char * metadata)
+ {
+ getImpl()->metadata_ = metadata;
+ }
+
+ const char * Baker::getMetadata() const
+ {
+ return getImpl()->metadata_.c_str();
+ }
+
+ void Baker::setInputSpace(const char * inputSpace)
+ {
+ getImpl()->inputSpace_ = inputSpace;
+ }
+
+ const char * Baker::getInputSpace() const
+ {
+ return getImpl()->inputSpace_.c_str();
+ }
+
+ void Baker::setShaperSpace(const char * shaperSpace)
+ {
+ getImpl()->shaperSpace_ = shaperSpace;
+ }
+
+ const char * Baker::getShaperSpace() const
+ {
+ return getImpl()->shaperSpace_.c_str();
+ }
+
+ void Baker::setLooks(const char * looks)
+ {
+ getImpl()->looks_ = looks;
+ }
+
+ const char * Baker::getLooks() const
+ {
+ return getImpl()->looks_.c_str();
+ }
+
+ void Baker::setTargetSpace(const char * targetSpace)
+ {
+ getImpl()->targetSpace_ = targetSpace;
+ }
+
+ const char * Baker::getTargetSpace() const
+ {
+ return getImpl()->targetSpace_.c_str();
+ }
+
+ void Baker::setShaperSize(int shapersize)
+ {
+ getImpl()->shapersize_ = shapersize;
+ }
+
+ int Baker::getShaperSize() const
+ {
+ return getImpl()->shapersize_;
+ }
+
+ void Baker::setCubeSize(int cubesize)
+ {
+ getImpl()->cubesize_ = cubesize;
+ }
+
+ int Baker::getCubeSize() const
+ {
+ return getImpl()->cubesize_;
+ }
+
+ void Baker::bake(std::ostream & os) const
+ {
+ FileFormat* fmt = FormatRegistry::GetInstance().getFileFormatByName(getImpl()->formatName_);
+
+ if(!fmt)
+ {
+ std::ostringstream err;
+ err << "The format named '" << getImpl()->formatName_;
+ err << "' could not be found. ";
+ throw Exception(err.str().c_str());
+ }
+
+ try
+ {
+ fmt->Write(*this, getImpl()->formatName_, os);
+ }
+ catch(std::exception & e)
+ {
+ std::ostringstream err;
+ err << "Error baking " << getImpl()->formatName_ << ":";
+ err << e.what();
+ throw Exception(err.str().c_str());
+ }
+
+ //
+ // TODO:
+ //
+ // - throw exception when we don't have inputSpace and targetSpace
+ // at least set
+ // - check limits of shaper and target, throw exception if we can't
+ // write that much data in x format
+ // - check that the shaper is 1D transform only, throw excpetion
+ // - check the file format supports shapers, 1D and 3D
+ // - add some checks to make sure we are monotonic
+ // - deal with the case of writing out non cube formats (1D only)
+ // - do a compare between ocio transform and output lut transform
+ // throw error if we going beyond tolerance
+ //
+ }
+
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+/*
+OIIO_ADD_TEST(Baker_Unit_Tests, test_listlutwriters)
+{
+
+ std::vector<std::string> current_writers;
+ current_writers.push_back("cinespace");
+ current_writers.push_back("houdini");
+
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+
+ OIIO_CHECK_EQUAL(baker->getNumFormats(), (int)current_writers.size());
+
+ std::vector<std::string> test;
+ for(int i = 0; i < baker->getNumFormats(); ++i)
+ test.push_back(baker->getFormatNameByIndex(i));
+
+ for(unsigned int i = 0; i < current_writers.size(); ++i)
+ OIIO_CHECK_EQUAL(current_writers[i], test[i]);
+
+}
+*/
+
+#endif // OCIO_BUILD_TESTS
+
+
diff --git a/src/core/CDLTransform.cpp b/src/core/CDLTransform.cpp
new file mode 100644
index 0000000..0e321ff
--- /dev/null
+++ b/src/core/CDLTransform.cpp
@@ -0,0 +1,776 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <fstream>
+#include <tinyxml.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "CDLTransform.h"
+#include "ExponentOps.h"
+#include "MatrixOps.h"
+#include "MathUtils.h"
+#include "Mutex.h"
+#include "OpBuilders.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ /*
+ "<ColorCorrection id=''>"
+ " <SOPNode>"
+ " <Description/> "
+ " <Slope>1 1 1</Slope> "
+ " <Offset>0 0 0</Offset> "
+ " <Power>1 1 1</Power> "
+ " </SOPNode> "
+ " <SatNode>"
+ " <Saturation> 1 </Saturation> "
+ " </SatNode> "
+ " </ColorCorrection>";
+
+ */
+
+ // http://ticpp.googlecode.com/svn/docs/ticpp_8h-source.html#l01670
+
+ void SetTiXmlText( TiXmlElement* element, const char * value)
+ {
+ if ( element->NoChildren() )
+ {
+ element->LinkEndChild( new TiXmlText( value ) );
+ }
+ else
+ {
+ if ( 0 == element->GetText() )
+ {
+ element->InsertBeforeChild( element->FirstChild(), TiXmlText( value ) );
+ }
+ else
+ {
+ // There already is text, so change it
+ element->FirstChild()->SetValue( value );
+ }
+ }
+ }
+
+ std::string BuildXML(const CDLTransform & cdl)
+ {
+ TiXmlDocument doc;
+
+ // TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
+ TiXmlElement * root = new TiXmlElement( "ColorCorrection" );
+ doc.LinkEndChild( root );
+ root->SetAttribute("id", cdl.getID());
+
+ TiXmlElement * sop = new TiXmlElement( "SOPNode" );
+ root->LinkEndChild( sop );
+
+ TiXmlElement * desc = new TiXmlElement( "Description" );
+ sop->LinkEndChild( desc );
+ SetTiXmlText(desc, cdl.getDescription());
+
+ TiXmlElement * slope = new TiXmlElement( "Slope" );
+ sop->LinkEndChild( slope );
+ float slopeval[3];
+ cdl.getSlope(slopeval);
+ SetTiXmlText(slope, FloatVecToString(slopeval, 3).c_str());
+
+ TiXmlElement * offset = new TiXmlElement( "Offset" );
+ sop->LinkEndChild( offset );
+ float offsetval[3];
+ cdl.getOffset(offsetval);
+ SetTiXmlText(offset, FloatVecToString(offsetval, 3).c_str());
+
+ TiXmlElement * power = new TiXmlElement( "Power" );
+ sop->LinkEndChild( power );
+ float powerval[3];
+ cdl.getPower(powerval);
+ SetTiXmlText(power, FloatVecToString(powerval, 3).c_str());
+
+ TiXmlElement * sat = new TiXmlElement( "SatNode" );
+ root->LinkEndChild( sat );
+
+ TiXmlElement * saturation = new TiXmlElement( "Saturation" );
+ sat->LinkEndChild( saturation );
+ SetTiXmlText(saturation, FloatToString(cdl.getSat()).c_str());
+
+ TiXmlPrinter printer;
+ printer.SetStreamPrinting();
+ doc.Accept( &printer );
+ return printer.Str();
+ }
+ }
+
+ void LoadCDL(CDLTransform * cdl, TiXmlElement * root)
+ {
+ if(!cdl) return;
+
+ if(!root)
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << "Null root element.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(std::string(root->Value()) != "ColorCorrection")
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << "Root element is type '" << root->Value() << "', ";
+ os << "ColorCorrection expected.";
+ throw Exception(os.str().c_str());
+ }
+
+ TiXmlHandle handle( root );
+
+ const char * id = root->Attribute("id");
+ if(!id) id = "";
+
+ cdl->setID(id);
+
+ TiXmlElement* desc = handle.FirstChild( "SOPNode" ).FirstChild("Description").ToElement();
+ if(desc)
+ {
+ const char * text = desc->GetText();
+ if(text) cdl->setDescription(text);
+ }
+
+ std::vector<std::string> lineParts;
+ std::vector<float> floatArray;
+
+ TiXmlElement* slope = handle.FirstChild( "SOPNode" ).FirstChild("Slope").ToElement();
+ if(slope)
+ {
+ const char * text = slope->GetText();
+ if(text)
+ {
+ pystring::split(pystring::strip(text), lineParts);
+ if((lineParts.size() != 3) || (!StringVecToFloatVec(floatArray, lineParts)))
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << id << ".SOPNode.Slope text '";
+ os << text << "' is not convertible to 3 floats.";
+ throw Exception(os.str().c_str());
+ }
+ cdl->setSlope(&floatArray[0]);
+ }
+ }
+
+ TiXmlElement* offset = handle.FirstChild( "SOPNode" ).FirstChild("Offset").ToElement();
+ if(offset)
+ {
+ const char * text = offset->GetText();
+ if(text)
+ {
+ pystring::split(pystring::strip(text), lineParts);
+ if((lineParts.size() != 3) || (!StringVecToFloatVec(floatArray, lineParts)))
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << id << ".SOPNode.Offset text '";
+ os << text << "' is not convertible to 3 floats.";
+ throw Exception(os.str().c_str());
+ }
+ cdl->setOffset(&floatArray[0]);
+ }
+ }
+
+ TiXmlElement* power = handle.FirstChild( "SOPNode" ).FirstChild("Power").ToElement();
+ if(power)
+ {
+ const char * text = power->GetText();
+ if(text)
+ {
+ pystring::split(pystring::strip(text), lineParts);
+ if((lineParts.size() != 3) || (!StringVecToFloatVec(floatArray, lineParts)))
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << id << ".SOPNode.Power text '";
+ os << text << "' is not convertible to 3 floats.";
+ throw Exception(os.str().c_str());
+ }
+ cdl->setPower(&floatArray[0]);
+ }
+ }
+
+ TiXmlElement* sat = handle.FirstChild( "SatNode" ).FirstChild("Saturation").ToElement();
+ if(sat)
+ {
+ const char * text = sat->GetText();
+ if(text)
+ {
+ float satval = 1.0f;
+ if(!StringToFloat(&satval, text))
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << id << ".SatNode.Saturation text '";
+ os << text << "' is not convertible to float.";
+ throw Exception(os.str().c_str());
+ }
+ cdl->setSat(satval);
+ }
+ }
+ }
+
+
+
+ void GetCDLTransforms(CDLTransformMap & transforms,
+ TiXmlElement * cccRootElement)
+ {
+ if(std::string(cccRootElement->Value()) != "ColorCorrectionCollection")
+ {
+ std::ostringstream os;
+ os << "GetCDLTransforms Error. ";
+ os << "Root element is type '" << cccRootElement->Value() << "', ";
+ os << "ColorCorrectionCollection expected.";
+ throw Exception(os.str().c_str());
+ }
+
+ TiXmlNode * child = cccRootElement->FirstChild("ColorCorrection");
+ while(child)
+ {
+ CDLTransformRcPtr transform = CDLTransform::Create();
+ LoadCDL(transform.get(), child->ToElement());
+
+ std::string id = transform->getID();
+ if(id.empty())
+ {
+ std::ostringstream os;
+ os << "Error loading ccc xml, ";
+ os << "All ASC ColorCorrections must specify an 'id' value.";
+ throw Exception(os.str().c_str());
+ }
+
+ CDLTransformMap::iterator iter = transforms.find(id);
+ if(iter != transforms.end())
+ {
+ std::ostringstream os;
+ os << "Error loading ccc xml. ";
+ os << "All ASC ColorCorrections must specify a unique 'id' value. ";
+ os << "Duplicate elements with '" << id << "' found.";
+ throw Exception(os.str().c_str());
+ }
+
+ transforms[id] = transform;
+
+ child = child->NextSibling("ColorCorrection");
+ }
+ }
+
+ void LoadCDL(CDLTransform * cdl, const char * xml)
+ {
+ if(!xml || (strlen(xml) == 0))
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << "Null string provided.";
+ throw Exception(os.str().c_str());
+ }
+
+ TiXmlDocument doc;
+ doc.Parse(xml);
+
+ if(doc.Error())
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << doc.ErrorDesc() << " (line ";
+ os << doc.ErrorRow() << ", character ";
+ os << doc.ErrorCol() << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ if(!doc.RootElement())
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml, ";
+ os << "please confirm the xml is valid.";
+ throw Exception(os.str().c_str());
+ }
+
+ LoadCDL(cdl, doc.RootElement()->ToElement());
+ }
+
+ CDLTransformRcPtr CDLTransform::Create()
+ {
+ return CDLTransformRcPtr(new CDLTransform(), &deleter);
+ }
+
+ namespace
+ {
+ std::string GetCDLLocalCacheKey(const std::string & src,
+ const std::string & cccid)
+ {
+ return src + " : " + cccid;
+ }
+
+ CDLTransformMap g_cache;
+ Mutex g_cacheMutex;
+ }
+
+ void ClearCDLTransformFileCache()
+ {
+ AutoMutex lock(g_cacheMutex);
+ g_cache.clear();
+ }
+
+ // TODO: Expose functions for introspecting in ccc file
+ // TODO: Share caching with normal cdl pathway
+
+ CDLTransformRcPtr CDLTransform::CreateFromFile(const char * src, const char * cccid)
+ {
+ if(!src || (strlen(src) == 0) || !cccid)
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << "Source file not specified.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Check cache
+ AutoMutex lock(g_cacheMutex);
+ {
+ CDLTransformMap::iterator iter =
+ g_cache.find(GetCDLLocalCacheKey(src,cccid));
+ if(iter != g_cache.end())
+ {
+ return iter->second;
+ }
+ }
+
+ std::ifstream istream(src);
+ if(istream.fail()) {
+ std::ostringstream os;
+ os << "Error could not read CDL source file '" << src;
+ os << "'. Please verify the file exists and appropriate ";
+ os << "permissions are set.";
+ throw Exception (os.str().c_str());
+ }
+
+ // Read the file into a string.
+ std::ostringstream rawdata;
+ rawdata << istream.rdbuf();
+ std::string xml = rawdata.str();
+
+ if(xml.empty())
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml. ";
+ os << "The specified source file, '";
+ os << src << "' appears to be empty.";
+ throw Exception(os.str().c_str());
+ }
+
+ TiXmlDocument doc;
+ doc.Parse(xml.c_str());
+
+ if(doc.Error())
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml from file '";
+ os << src << "'. ";
+ os << doc.ErrorDesc() << " (line ";
+ os << doc.ErrorRow() << ", character ";
+ os << doc.ErrorCol() << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ if(!doc.RootElement())
+ {
+ std::ostringstream os;
+ os << "Error loading CDL xml from file '";
+ os << src << "'. ";
+ os << "Please confirm the xml is valid.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string rootValue = doc.RootElement()->Value();
+ if(rootValue == "ColorCorrection")
+ {
+ // Load a single ColorCorrection into the cache
+ CDLTransformRcPtr cdl = CDLTransform::Create();
+ LoadCDL(cdl.get(), doc.RootElement()->ToElement());
+ g_cache[GetCDLLocalCacheKey(src,cccid)] = cdl;
+ return cdl;
+ }
+ else if(rootValue == "ColorCorrectionCollection")
+ {
+ // Load all CCs from the ColorCorrectionCollection
+ // into the cache
+
+ CDLTransformMap transforms;
+ GetCDLTransforms(transforms, doc.RootElement());
+
+ if(transforms.empty())
+ {
+ std::ostringstream os;
+ os << "Error loading ccc xml. ";
+ os << "No ColorCorrection elements found in file '";
+ os << src << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ for(CDLTransformMap::iterator iter = transforms.begin();
+ iter != transforms.end();
+ ++iter)
+ {
+ g_cache[GetCDLLocalCacheKey(src,iter->first)] = iter->second;
+ }
+
+ CDLTransformMap::iterator cciter = g_cache.find(GetCDLLocalCacheKey(src,cccid));
+ if(cciter == g_cache.end())
+ {
+ std::ostringstream os;
+ os << "Error loading ccc xml. ";
+ os << "The specified cccid " << cccid << " ";
+ os << "could not be found in file '";
+ os << src << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ return cciter->second;
+ }
+
+ std::ostringstream os;
+ os << "Error loading CDL xml from file '";
+ os << src << "'. ";
+ os << "Root xml element is type '" << rootValue << "', ";
+ os << "ColorCorrection or ColorCorrectionCollection expected.";
+ throw Exception(os.str().c_str());
+ }
+
+ void CDLTransform::deleter(CDLTransform* t)
+ {
+ delete t;
+ }
+
+ class CDLTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+
+ float sop_[9];
+ float sat_;
+ std::string id_;
+ std::string description_;
+
+ mutable std::string xml_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD),
+ sat_(1.0f)
+ {
+ sop_[0] = 1.0f;
+ sop_[1] = 1.0f;
+ sop_[2] = 1.0f;
+ sop_[3] = 0.0f;
+ sop_[4] = 0.0f;
+ sop_[5] = 0.0f;
+ sop_[6] = 1.0f;
+ sop_[7] = 1.0f;
+ sop_[8] = 1.0f;
+ }
+
+ ~Impl()
+ {
+
+ }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+
+ memcpy(sop_, rhs.sop_, sizeof(float)*9);
+ sat_ = rhs.sat_;
+ id_ = rhs.id_;
+ description_ = rhs.description_;
+
+ return *this;
+ }
+
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ CDLTransform::CDLTransform()
+ : m_impl(new CDLTransform::Impl)
+ {
+ }
+
+ TransformRcPtr CDLTransform::createEditableCopy() const
+ {
+ CDLTransformRcPtr transform = CDLTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ CDLTransform::~CDLTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ CDLTransform& CDLTransform::operator= (const CDLTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection CDLTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void CDLTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ const char * CDLTransform::getXML() const
+ {
+ getImpl()->xml_ = BuildXML(*this);
+ return getImpl()->xml_.c_str();
+ }
+
+ void CDLTransform::setXML(const char * xml)
+ {
+ LoadCDL(this, xml);
+ }
+
+ // We use this approach, rather than comparing XML to get around the
+ // case where setXML with extra data was provided.
+
+ bool CDLTransform::equals(const ConstCDLTransformRcPtr & other) const
+ {
+ if(!other) return false;
+
+ if(getImpl()->dir_ != other->getImpl()->dir_) return false;
+
+ const float abserror = 1e-9f;
+
+ for(int i=0; i<9; ++i)
+ {
+ if(!equalWithAbsError(getImpl()->sop_[i], other->getImpl()->sop_[i], abserror))
+ {
+ return false;
+ }
+ }
+
+ if(!equalWithAbsError(getImpl()->sat_, other->getImpl()->sat_, abserror))
+ {
+ return false;
+ }
+
+ if(getImpl()->id_ != other->getImpl()->id_)
+ {
+ return false;
+ }
+
+ if(getImpl()->description_ != other->getImpl()->description_)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ void CDLTransform::setSlope(const float * rgb)
+ {
+ memcpy(&getImpl()->sop_[0], rgb, sizeof(float)*3);
+ }
+
+ void CDLTransform::getSlope(float * rgb) const
+ {
+ memcpy(rgb, &getImpl()->sop_[0], sizeof(float)*3);
+ }
+
+ void CDLTransform::setOffset(const float * rgb)
+ {
+ memcpy(&getImpl()->sop_[3], rgb, sizeof(float)*3);
+ }
+
+ void CDLTransform::getOffset(float * rgb) const
+ {
+ memcpy(rgb, &getImpl()->sop_[3], sizeof(float)*3);
+ }
+
+ void CDLTransform::setPower(const float * rgb)
+ {
+ memcpy(&getImpl()->sop_[6], rgb, sizeof(float)*3);
+ }
+
+ void CDLTransform::getPower(float * rgb) const
+ {
+ memcpy(rgb, &getImpl()->sop_[6], sizeof(float)*3);
+ }
+
+ void CDLTransform::setSOP(const float * vec9)
+ {
+ memcpy(&getImpl()->sop_, vec9, sizeof(float)*9);
+ }
+
+ void CDLTransform::getSOP(float * vec9) const
+ {
+ memcpy(vec9, &getImpl()->sop_, sizeof(float)*9);
+ }
+
+ void CDLTransform::setSat(float sat)
+ {
+ getImpl()->sat_ = sat;
+ }
+
+ float CDLTransform::getSat() const
+ {
+ return getImpl()->sat_;
+ }
+
+ void CDLTransform::getSatLumaCoefs(float * rgb) const
+ {
+ if(!rgb) return;
+ rgb[0] = 0.2126f;
+ rgb[1] = 0.7152f;
+ rgb[2] = 0.0722f;
+ }
+
+ void CDLTransform::setID(const char * id)
+ {
+ if(id)
+ {
+ getImpl()->id_ = id;
+ }
+ else
+ {
+ getImpl()->id_ = "";
+ }
+ }
+
+ const char * CDLTransform::getID() const
+ {
+ return getImpl()->id_.c_str();
+ }
+
+ void CDLTransform::setDescription(const char * desc)
+ {
+ if(desc)
+ {
+ getImpl()->description_ = desc;
+ }
+ else
+ {
+ getImpl()->description_ = "";
+ }
+ }
+
+ const char * CDLTransform::getDescription() const
+ {
+ return getImpl()->description_.c_str();
+ }
+
+ std::ostream& operator<< (std::ostream& os, const CDLTransform& t)
+ {
+ float sop[9];
+ t.getSOP(sop);
+
+ os << "<CDLTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << "sop=";
+ for (unsigned int i=0; i<9; ++i)
+ {
+ if(i!=0) os << " ";
+ os << sop[i];
+ }
+ os << ", ";
+ os << "sat=" << t.getSat() << ",";
+ os << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ void BuildCDLOps(OpRcPtrVec & ops,
+ const Config & /*config*/,
+ const CDLTransform & cdlTransform,
+ TransformDirection dir)
+ {
+ float scale4[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ cdlTransform.getSlope(scale4);
+
+ float offset4[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ cdlTransform.getOffset(offset4);
+
+ float power4[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ cdlTransform.getPower(power4);
+
+ float lumaCoef3[] = { 1.0f, 1.0f, 1.0f };
+ cdlTransform.getSatLumaCoefs(lumaCoef3);
+
+ float sat = cdlTransform.getSat();
+
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ cdlTransform.getDirection());
+
+ // TODO: Confirm ASC Sat math is correct.
+ // TODO: Handle Clamping conditions more explicitly
+
+ if(combinedDir == TRANSFORM_DIR_FORWARD)
+ {
+ // 1) Scale + Offset
+ CreateScaleOffsetOp(ops, scale4, offset4, TRANSFORM_DIR_FORWARD);
+
+ // 2) Power + Clamp
+ CreateExponentOp(ops, power4, TRANSFORM_DIR_FORWARD);
+
+ // 3) Saturation + Clamp
+ CreateSaturationOp(ops, sat, lumaCoef3, TRANSFORM_DIR_FORWARD);
+ }
+ else if(combinedDir == TRANSFORM_DIR_INVERSE)
+ {
+ // 3) Saturation + Clamp
+ CreateSaturationOp(ops, sat, lumaCoef3, TRANSFORM_DIR_INVERSE);
+
+ // 2) Power + Clamp
+ CreateExponentOp(ops, power4, TRANSFORM_DIR_INVERSE);
+
+ // 1) Scale + Offset
+ CreateScaleOffsetOp(ops, scale4, offset4, TRANSFORM_DIR_INVERSE);
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/CDLTransform.h b/src/core/CDLTransform.h
new file mode 100644
index 0000000..8b945ad
--- /dev/null
+++ b/src/core/CDLTransform.h
@@ -0,0 +1,53 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_CDLTRANSFORM_H
+#define INCLUDED_OCIO_CDLTRANSFORM_H
+
+#include <map>
+#include <tinyxml.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ typedef std::map<std::string,CDLTransformRcPtr> CDLTransformMap;
+
+ void ClearCDLTransformFileCache();
+
+ void LoadCDL(CDLTransform * cdl, const char * xml);
+ void LoadCDL(CDLTransform * cdl, TiXmlElement * root);
+
+ // Get a map of transform cccid : cdl transform
+ void GetCDLTransforms(CDLTransformMap & transforms,
+ TiXmlElement * cccroot);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
new file mode 100644
index 0000000..50194f3
--- /dev/null
+++ b/src/core/CMakeLists.txt
@@ -0,0 +1,93 @@
+###############################################################################
+### OCIO CORE ###
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${EXTERNAL_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}/ext/oiio/src/include
+)
+
+file(GLOB_RECURSE core_src_files "${CMAKE_SOURCE_DIR}/src/core/*.cpp")
+file(GLOB_RECURSE core_export_headers "${CMAKE_SOURCE_DIR}/export/OpenColorIO/*.h")
+
+message(STATUS "Create OpenColorABI.h from OpenColorABI.h.in")
+configure_file(${CMAKE_SOURCE_DIR}/export/OpenColorIO/OpenColorABI.h.in
+ ${CMAKE_BINARY_DIR}/export/OpenColorABI.h @ONLY)
+list(APPEND core_export_headers ${CMAKE_BINARY_DIR}/export/OpenColorABI.h)
+
+# SHARED
+
+if(OCIO_BUILD_SHARED)
+ add_library(OpenColorIO SHARED ${core_src_files})
+
+ if(USE_EXTERNAL_TINYXML)
+ target_link_libraries(OpenColorIO ${TINYXML_LIBRARIES})
+ else(USE_EXTERNAL_TINYXML)
+ add_dependencies(OpenColorIO tinyxml)
+ endif(USE_EXTERNAL_TINYXML)
+
+ if(USE_EXTERNAL_YAML)
+ target_link_libraries(OpenColorIO ${YAML_CPP_LIBRARIES})
+ else(USE_EXTERNAL_YAML)
+ add_dependencies(OpenColorIO YAML_CPP_LOCAL)
+ endif()
+
+ if(WIN32)
+ target_link_libraries(OpenColorIO
+ debug ${EXTERNAL_DEBUG_LIBRARIES}
+ optimized ${EXTERNAL_OPTIMIZED_LIBRARIES}
+ general ${EXTERNAL_GENERAL_LIBRARIES})
+ else()
+ target_link_libraries(OpenColorIO ${EXTERNAL_GENERAL_LIBRARIES})
+ endif()
+ set_target_properties(OpenColorIO PROPERTIES
+ OUTPUT_NAME OpenColorIO
+ COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
+ LINK_FLAGS "${EXTERNAL_LINK_FLAGS}")
+
+ message(STATUS "Setting OCIO SOVERSION to: ${SOVERSION}")
+ set_target_properties(OpenColorIO PROPERTIES
+ VERSION ${OCIO_VERSION}
+ SOVERSION ${SOVERSION})
+
+ install(TARGETS OpenColorIO DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib${LIB_SUFFIX})
+endif()
+
+# STATIC
+
+if(OCIO_BUILD_STATIC)
+ list(REMOVE_ITEM core_src_files ${CMAKE_SOURCE_DIR}/src/core/UnitTest.cpp)
+ add_library(OpenColorIO_STATIC STATIC ${core_src_files})
+ add_dependencies(OpenColorIO_STATIC tinyxml YAML_CPP_LOCAL)
+ if(WIN32)
+ target_link_libraries(OpenColorIO_STATIC
+ debug ${EXTERNAL_DEBUG_LIBRARIES}
+ optimized ${EXTERNAL_OPTIMIZED_LIBRARIES}
+ general ${EXTERNAL_GENERAL_LIBRARIES})
+ else()
+ target_link_libraries(OpenColorIO_STATIC ${EXTERNAL_GENERAL_LIBRARIES})
+ endif()
+ set_target_properties(OpenColorIO_STATIC PROPERTIES
+ OUTPUT_NAME OpenColorIO
+ COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
+ LINK_FLAGS "${EXTERNAL_LINK_FLAGS}")
+
+ message(STATUS "Setting OCIO SOVERSION to: ${SOVERSION}")
+ set_target_properties(OpenColorIO_STATIC PROPERTIES
+ VERSION ${OCIO_VERSION}
+ SOVERSION ${SOVERSION})
+
+ install(TARGETS OpenColorIO_STATIC DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib)
+endif()
+
+# public interface
+install(FILES ${core_export_headers}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/OpenColorIO/)
+
+# pkg-config
+message(STATUS "Create OpenColorIO.pc from OpenColorIO.pc.in")
+configure_file(${CMAKE_SOURCE_DIR}/export/pkgconfig/OpenColorIO.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/OpenColorIO.pc @ONLY)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/OpenColorIO.pc
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib${LIB_SUFFIX}/pkgconfig/)
diff --git a/src/core/Caching.cpp b/src/core/Caching.cpp
new file mode 100644
index 0000000..afb0e7c
--- /dev/null
+++ b/src/core/Caching.cpp
@@ -0,0 +1,47 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "CDLTransform.h"
+#include "PathUtils.h"
+#include "FileTransform.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Processors which the user hangs onto have local caches.
+ // Should these be cleared?
+
+ void ClearAllCaches()
+ {
+ ClearPathCaches();
+ ClearFileTransformCaches();
+ ClearCDLTransformFileCache();
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ColorSpace.cpp b/src/core/ColorSpace.cpp
new file mode 100644
index 0000000..ed2a473
--- /dev/null
+++ b/src/core/ColorSpace.cpp
@@ -0,0 +1,270 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+#include <sstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ ColorSpaceRcPtr ColorSpace::Create()
+ {
+ return ColorSpaceRcPtr(new ColorSpace(), &deleter);
+ }
+
+ void ColorSpace::deleter(ColorSpace* c)
+ {
+ delete c;
+ }
+
+
+ class ColorSpace::Impl
+ {
+ public:
+ std::string name_;
+ std::string family_;
+ std::string equalityGroup_;
+ std::string description_;
+
+ BitDepth bitDepth_;
+ bool isData_;
+
+ Allocation allocation_;
+ std::vector<float> allocationVars_;
+
+ TransformRcPtr toRefTransform_;
+ TransformRcPtr fromRefTransform_;
+
+ bool toRefSpecified_;
+ bool fromRefSpecified_;
+
+ Impl() :
+ bitDepth_(BIT_DEPTH_UNKNOWN),
+ isData_(false),
+ allocation_(ALLOCATION_UNIFORM),
+ toRefSpecified_(false),
+ fromRefSpecified_(false)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ name_ = rhs.name_;
+ family_ = rhs.family_;
+ equalityGroup_ = rhs.equalityGroup_;
+ description_ = rhs.description_;
+ bitDepth_ = rhs.bitDepth_;
+ isData_ = rhs.isData_;
+ allocation_ = rhs.allocation_;
+ allocationVars_ = rhs.allocationVars_;
+
+ toRefTransform_ = rhs.toRefTransform_;
+ if(toRefTransform_) toRefTransform_ = toRefTransform_->createEditableCopy();
+
+ fromRefTransform_ = rhs.fromRefTransform_;
+ if(fromRefTransform_) fromRefTransform_ = fromRefTransform_->createEditableCopy();
+
+ toRefSpecified_ = rhs.toRefSpecified_;
+ fromRefSpecified_ = rhs.fromRefSpecified_;
+ return *this;
+ }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ ColorSpace::ColorSpace()
+ : m_impl(new ColorSpace::Impl)
+ {
+ }
+
+ ColorSpace::~ColorSpace()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ ColorSpaceRcPtr ColorSpace::createEditableCopy() const
+ {
+ ColorSpaceRcPtr cs = ColorSpace::Create();
+ *cs->m_impl = *m_impl;
+ return cs;
+ }
+
+ const char * ColorSpace::getName() const
+ {
+ return getImpl()->name_.c_str();
+ }
+
+ void ColorSpace::setName(const char * name)
+ {
+ getImpl()->name_ = name;
+ }
+ const char * ColorSpace::getFamily() const
+ {
+ return getImpl()->family_.c_str();
+ }
+
+ void ColorSpace::setFamily(const char * family)
+ {
+ getImpl()->family_ = family;
+ }
+
+ const char * ColorSpace::getEqualityGroup() const
+ {
+ return getImpl()->equalityGroup_.c_str();
+ }
+
+ void ColorSpace::setEqualityGroup(const char * equalityGroup)
+ {
+ getImpl()->equalityGroup_ = equalityGroup;
+ }
+
+ const char * ColorSpace::getDescription() const
+ {
+ return getImpl()->description_.c_str();
+ }
+
+ void ColorSpace::setDescription(const char * description)
+ {
+ getImpl()->description_ = description;
+ }
+
+ BitDepth ColorSpace::getBitDepth() const
+ {
+ return getImpl()->bitDepth_;
+ }
+
+ void ColorSpace::setBitDepth(BitDepth bitDepth)
+ {
+ getImpl()->bitDepth_ = bitDepth;
+ }
+
+ bool ColorSpace::isData() const
+ {
+ return getImpl()->isData_;
+ }
+
+ void ColorSpace::setIsData(bool val)
+ {
+ getImpl()->isData_ = val;
+ }
+
+ Allocation ColorSpace::getAllocation() const
+ {
+ return getImpl()->allocation_;
+ }
+
+ void ColorSpace::setAllocation(Allocation allocation)
+ {
+ getImpl()->allocation_ = allocation;
+ }
+
+ int ColorSpace::getAllocationNumVars() const
+ {
+ return static_cast<int>(getImpl()->allocationVars_.size());
+ }
+
+ void ColorSpace::getAllocationVars(float * vars) const
+ {
+ if(!getImpl()->allocationVars_.empty())
+ {
+ memcpy(vars,
+ &getImpl()->allocationVars_[0],
+ getImpl()->allocationVars_.size()*sizeof(float));
+ }
+ }
+
+ void ColorSpace::setAllocationVars(int numvars, const float * vars)
+ {
+ getImpl()->allocationVars_.resize(numvars);
+
+ if(!getImpl()->allocationVars_.empty())
+ {
+ memcpy(&getImpl()->allocationVars_[0],
+ vars,
+ numvars*sizeof(float));
+ }
+ }
+
+ ConstTransformRcPtr ColorSpace::getTransform(ColorSpaceDirection dir) const
+ {
+ if(dir == COLORSPACE_DIR_TO_REFERENCE)
+ return getImpl()->toRefTransform_;
+ else if(dir == COLORSPACE_DIR_FROM_REFERENCE)
+ return getImpl()->fromRefTransform_;
+
+ throw Exception("Unspecified ColorSpaceDirection");
+ }
+
+ void ColorSpace::setTransform(const ConstTransformRcPtr & transform,
+ ColorSpaceDirection dir)
+ {
+ TransformRcPtr transformCopy;
+ if(transform) transformCopy = transform->createEditableCopy();
+
+ if(dir == COLORSPACE_DIR_TO_REFERENCE)
+ getImpl()->toRefTransform_ = transformCopy;
+ else if(dir == COLORSPACE_DIR_FROM_REFERENCE)
+ getImpl()->fromRefTransform_ = transformCopy;
+ else
+ throw Exception("Unspecified ColorSpaceDirection");
+ }
+
+ std::ostream& operator<< (std::ostream& os, const ColorSpace& cs)
+ {
+ os << "<ColorSpace ";
+ os << "name=" << cs.getName() << ", ";
+ os << "family=" << cs.getFamily() << ", ";
+ os << "equalityGroup=" << cs.getEqualityGroup() << ", ";
+ os << "bitDepth=" << BitDepthToString(cs.getBitDepth()) << ", ";
+ os << "isData=" << BoolToString(cs.isData()) << ", ";
+ os << "allocation=" << AllocationToString(cs.getAllocation()) << ", ";
+ os << ">\n";
+
+ if(cs.getTransform(COLORSPACE_DIR_TO_REFERENCE))
+ {
+ os << "\t" << cs.getName() << " --> Reference\n";
+ os << cs.getTransform(COLORSPACE_DIR_TO_REFERENCE);
+ }
+
+ if(cs.getTransform(COLORSPACE_DIR_FROM_REFERENCE))
+ {
+ os << "\tReference --> " << cs.getName() << "\n";
+ os << cs.getTransform(COLORSPACE_DIR_FROM_REFERENCE);
+ }
+ return os;
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ColorSpaceTransform.cpp b/src/core/ColorSpaceTransform.cpp
new file mode 100644
index 0000000..92f3878
--- /dev/null
+++ b/src/core/ColorSpaceTransform.cpp
@@ -0,0 +1,246 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "NoOps.h"
+#include "OpBuilders.h"
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ColorSpaceTransformRcPtr ColorSpaceTransform::Create()
+ {
+ return ColorSpaceTransformRcPtr(new ColorSpaceTransform(), &deleter);
+ }
+
+ void ColorSpaceTransform::deleter(ColorSpaceTransform* t)
+ {
+ delete t;
+ }
+
+
+ class ColorSpaceTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ std::string src_;
+ std::string dst_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ src_ = rhs.src_;
+ dst_ = rhs.dst_;
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ ColorSpaceTransform::ColorSpaceTransform()
+ : m_impl(new ColorSpaceTransform::Impl)
+ {
+ }
+
+ TransformRcPtr ColorSpaceTransform::createEditableCopy() const
+ {
+ ColorSpaceTransformRcPtr transform = ColorSpaceTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ ColorSpaceTransform::~ColorSpaceTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ ColorSpaceTransform& ColorSpaceTransform::operator= (const ColorSpaceTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection ColorSpaceTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void ColorSpaceTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ const char * ColorSpaceTransform::getSrc() const
+ {
+ return getImpl()->src_.c_str();
+ }
+
+ void ColorSpaceTransform::setSrc(const char * src)
+ {
+ getImpl()->src_ = src;
+ }
+
+ const char * ColorSpaceTransform::getDst() const
+ {
+ return getImpl()->dst_.c_str();
+ }
+
+ void ColorSpaceTransform::setDst(const char * dst)
+ {
+ getImpl()->dst_ = dst;
+ }
+
+ std::ostream& operator<< (std::ostream& os, const ColorSpaceTransform& t)
+ {
+ os << "<ColorSpaceTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ void BuildColorSpaceOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const ColorSpaceTransform & colorSpaceTransform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ colorSpaceTransform.getDirection());
+
+ ConstColorSpaceRcPtr src, dst;
+
+ if(combinedDir == TRANSFORM_DIR_FORWARD)
+ {
+ src = config.getColorSpace( colorSpaceTransform.getSrc() );
+ dst = config.getColorSpace( colorSpaceTransform.getDst() );
+ }
+ else if(combinedDir == TRANSFORM_DIR_INVERSE)
+ {
+ dst = config.getColorSpace( colorSpaceTransform.getSrc() );
+ src = config.getColorSpace( colorSpaceTransform.getDst() );
+ }
+
+ BuildColorSpaceOps(ops, config, context, src, dst);
+ }
+
+ namespace
+ {
+ bool AreColorSpacesInSameEqualityGroup(const ConstColorSpaceRcPtr & csa,
+ const ConstColorSpaceRcPtr & csb)
+ {
+ std::string a = csa->getEqualityGroup();
+ std::string b = csb->getEqualityGroup();
+
+ if(!a.empty()) return (a==b);
+ return false;
+ }
+ }
+
+ void BuildColorSpaceOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstColorSpaceRcPtr & srcColorSpace,
+ const ConstColorSpaceRcPtr & dstColorSpace)
+ {
+ if(!srcColorSpace)
+ throw Exception("BuildColorSpaceOps failed, null srcColorSpace.");
+ if(!dstColorSpace)
+ throw Exception("BuildColorSpaceOps failed, null dstColorSpace.");
+
+ if(AreColorSpacesInSameEqualityGroup(srcColorSpace, dstColorSpace))
+ return;
+ if(dstColorSpace->isData() || srcColorSpace->isData())
+ return;
+
+ // Consider dt8 -> vd8?
+ // One would have to explode the srcColorSpace->getTransform(COLORSPACE_DIR_TO_REFERENCE);
+ // result, and walk through it step by step. If the dstColorspace family were
+ // ever encountered in transit, we'd want to short circuit the result.
+
+ AllocationData srcAllocation;
+ srcAllocation.allocation = srcColorSpace->getAllocation();
+ srcAllocation.vars.resize( srcColorSpace->getAllocationNumVars());
+ if(srcAllocation.vars.size() > 0)
+ {
+ srcColorSpace->getAllocationVars(&srcAllocation.vars[0]);
+ }
+
+ CreateGpuAllocationNoOp(ops, srcAllocation);
+
+ // Go to the reference space, either by using
+ // * cs->ref in the forward direction
+ // * ref->cs in the inverse direction
+ if(srcColorSpace->getTransform(COLORSPACE_DIR_TO_REFERENCE))
+ {
+ BuildOps(ops, config, context, srcColorSpace->getTransform(COLORSPACE_DIR_TO_REFERENCE), TRANSFORM_DIR_FORWARD);
+ }
+ else if(srcColorSpace->getTransform(COLORSPACE_DIR_FROM_REFERENCE))
+ {
+ BuildOps(ops, config, context, srcColorSpace->getTransform(COLORSPACE_DIR_FROM_REFERENCE), TRANSFORM_DIR_INVERSE);
+ }
+ // Otherwise, both are not defined so its a no-op. This is not an error condition.
+
+ // Go from the reference space, either by using
+ // * ref->cs in the forward direction
+ // * cs->ref in the inverse direction
+ if(dstColorSpace->getTransform(COLORSPACE_DIR_FROM_REFERENCE))
+ {
+ BuildOps(ops, config, context, dstColorSpace->getTransform(COLORSPACE_DIR_FROM_REFERENCE), TRANSFORM_DIR_FORWARD);
+ }
+ else if(dstColorSpace->getTransform(COLORSPACE_DIR_TO_REFERENCE))
+ {
+ BuildOps(ops, config, context, dstColorSpace->getTransform(COLORSPACE_DIR_TO_REFERENCE), TRANSFORM_DIR_INVERSE);
+ }
+ // Otherwise, both are not defined so its a no-op. This is not an error condition.
+
+ AllocationData dstAllocation;
+ dstAllocation.allocation = dstColorSpace->getAllocation();
+ dstAllocation.vars.resize( dstColorSpace->getAllocationNumVars());
+ if(dstAllocation.vars.size() > 0)
+ {
+ dstColorSpace->getAllocationVars(&dstAllocation.vars[0]);
+ }
+
+ CreateGpuAllocationNoOp(ops, dstAllocation);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Config.cpp b/src/core/Config.cpp
new file mode 100644
index 0000000..985990f
--- /dev/null
+++ b/src/core/Config.cpp
@@ -0,0 +1,2223 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <cstdlib>
+#include <cstring>
+#include <set>
+#include <sstream>
+#include <fstream>
+#include <utility>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "HashUtils.h"
+#include "Logging.h"
+#include "LookParse.h"
+#include "MathUtils.h"
+#include "Mutex.h"
+#include "OpBuilders.h"
+#include "PathUtils.h"
+#include "ParseUtils.h"
+#include "Processor.h"
+#include "PrivateTypes.h"
+#include "pystring/pystring.h"
+#include "OCIOYaml.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const char * OCIO_CONFIG_ENVVAR = "OCIO";
+ const char * OCIO_ACTIVE_DISPLAYS_ENVVAR = "OCIO_ACTIVE_DISPLAYS";
+ const char * OCIO_ACTIVE_VIEWS_ENVVAR = "OCIO_ACTIVE_VIEWS";
+
+ enum Sanity
+ {
+ SANITY_UNKNOWN = 0,
+ SANITY_SANE,
+ SANITY_INSANE
+ };
+
+ // These are the 709 primaries specified by the ASC.
+ const float DEFAULT_LUMA_COEFF_R = 0.2126f;
+ const float DEFAULT_LUMA_COEFF_G = 0.7152f;
+ const float DEFAULT_LUMA_COEFF_B = 0.0722f;
+
+ const char * INTERNAL_RAW_PROFILE =
+ "ocio_profile_version: 1\n"
+ "strictparsing: false\n"
+ "roles:\n"
+ " default: raw\n"
+ "displays:\n"
+ " sRGB:\n"
+ " - !<View> {name: Raw, colorspace: raw}\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: raw\n"
+ " family: raw\n"
+ " equalitygroup:\n"
+ " bitdepth: 32f\n"
+ " isdata: true\n"
+ " allocation: uniform\n"
+ " description: 'A raw color space. Conversions to and from this space are no-ops.'\n";
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ const char * GetVersion()
+ {
+ return OCIO_VERSION;
+ }
+
+ int GetVersionHex()
+ {
+ return OCIO_VERSION_HEX;
+ }
+
+ namespace
+ {
+ ConstConfigRcPtr g_currentConfig;
+ Mutex g_currentConfigLock;
+ }
+
+ ConstConfigRcPtr GetCurrentConfig()
+ {
+ AutoMutex lock(g_currentConfigLock);
+
+ if(!g_currentConfig)
+ {
+ g_currentConfig = Config::CreateFromEnv();
+ }
+
+ return g_currentConfig;
+ }
+
+ void SetCurrentConfig(const ConstConfigRcPtr & config)
+ {
+ AutoMutex lock(g_currentConfigLock);
+
+ g_currentConfig = config->createEditableCopy();
+ }
+
+ namespace
+ {
+
+ // Roles
+ // (lower case role name: colorspace name)
+ std::string LookupRole(const StringMap & roles, const std::string & rolename)
+ {
+ StringMap::const_iterator iter = roles.find(pystring::lower(rolename));
+ if(iter == roles.end()) return "";
+ return iter->second;
+ }
+
+
+ void GetFileReferences(std::set<std::string> & files,
+ const ConstTransformRcPtr & transform)
+ {
+ if(!transform) return;
+
+ if(ConstGroupTransformRcPtr groupTransform = \
+ DynamicPtrCast<const GroupTransform>(transform))
+ {
+ for(int i=0; i<groupTransform->size(); ++i)
+ {
+ GetFileReferences(files, groupTransform->getTransform(i));
+ }
+ }
+ else if(ConstFileTransformRcPtr fileTransform = \
+ DynamicPtrCast<const FileTransform>(transform))
+ {
+ files.insert(fileTransform->getSrc());
+ }
+ }
+
+ void GetColorSpaceReferences(std::set<std::string> & colorSpaceNames,
+ const ConstTransformRcPtr & transform)
+ {
+ if(!transform) return;
+
+ if(ConstGroupTransformRcPtr groupTransform = \
+ DynamicPtrCast<const GroupTransform>(transform))
+ {
+ for(int i=0; i<groupTransform->size(); ++i)
+ {
+ GetColorSpaceReferences(colorSpaceNames, groupTransform->getTransform(i));
+ }
+ }
+ else if(ConstColorSpaceTransformRcPtr colorSpaceTransform = \
+ DynamicPtrCast<const ColorSpaceTransform>(transform))
+ {
+ colorSpaceNames.insert(colorSpaceTransform->getSrc());
+ colorSpaceNames.insert(colorSpaceTransform->getDst());
+ }
+ else if(ConstDisplayTransformRcPtr displayTransform = \
+ DynamicPtrCast<const DisplayTransform>(transform))
+ {
+ colorSpaceNames.insert(displayTransform->getInputColorSpaceName());
+ }
+ else if(ConstLookTransformRcPtr lookTransform = \
+ DynamicPtrCast<const LookTransform>(transform))
+ {
+ colorSpaceNames.insert(colorSpaceTransform->getSrc());
+ colorSpaceNames.insert(colorSpaceTransform->getDst());
+ }
+ }
+
+
+ bool FindColorSpaceIndex(int * index,
+ const ColorSpaceVec & colorspaces,
+ const std::string & csname)
+ {
+ if(csname.empty()) return false;
+
+ std::string csnamelower = pystring::lower(csname);
+
+ for(unsigned int i = 0; i < colorspaces.size(); ++i)
+ {
+ if(csnamelower == pystring::lower(colorspaces[i]->getName()))
+ {
+ if(index) *index = i;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ // Displays
+ struct View
+ {
+ std::string name;
+ std::string colorspace;
+ std::string looks;
+
+ View() { }
+
+ View(const std::string & name_,
+ const std::string & colorspace_,
+ const std::string & looksList_) :
+ name(name_),
+ colorspace(colorspace_),
+ looks(looksList_)
+ { }
+ };
+
+ typedef std::vector<View> ViewVec;
+ typedef std::map<std::string, ViewVec> DisplayMap; // (display name : ViewVec)
+
+ void operator >> (const YAML::Node& node, View& v)
+ {
+ if(node.Tag() != "View")
+ return;
+
+ std::string key, stringval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "name")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ v.name = stringval;
+ }
+ else if(key == "colorspace")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ v.colorspace = stringval;
+ }
+ else if(key == "looks" || key == "look")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ v.looks = stringval;
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+
+ if(v.name.empty())
+ {
+ throw Exception("View does not specify 'name'.");
+ }
+ if(v.colorspace.empty())
+ {
+ std::ostringstream os;
+ os << "View '" << v.name << "' ";
+ os << "does not specify colorspace.";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, View view)
+ {
+ out << YAML::VerbatimTag("View");
+ out << YAML::Flow;
+ out << YAML::BeginMap;
+ out << YAML::Key << "name" << YAML::Value << view.name;
+ out << YAML::Key << "colorspace" << YAML::Value << view.colorspace;
+ if(!view.looks.empty()) out << YAML::Key << "looks" << YAML::Value << view.looks;
+ out << YAML::EndMap;
+ return out;
+ }
+
+ DisplayMap::iterator find_display(DisplayMap & displays, const std::string & display)
+ {
+ for(DisplayMap::iterator iter = displays.begin();
+ iter != displays.end();
+ ++iter)
+ {
+ if(StrEqualsCaseIgnore(display, iter->first)) return iter;
+ }
+ return displays.end();
+ }
+
+ DisplayMap::const_iterator find_display_const(const DisplayMap & displays, const std::string & display)
+ {
+ for(DisplayMap::const_iterator iter = displays.begin();
+ iter != displays.end();
+ ++iter)
+ {
+ if(StrEqualsCaseIgnore(display, iter->first)) return iter;
+ }
+ return displays.end();
+ }
+
+ int find_view(const ViewVec & vec, const std::string & name)
+ {
+ for(unsigned int i=0; i<vec.size(); ++i)
+ {
+ if(StrEqualsCaseIgnore(name, vec[i].name)) return i;
+ }
+ return -1;
+ }
+
+ void AddDisplay(DisplayMap & displays,
+ const std::string & display,
+ const std::string & view,
+ const std::string & colorspace,
+ const std::string & looks)
+ {
+ DisplayMap::iterator iter = find_display(displays, display);
+ if(iter == displays.end())
+ {
+ ViewVec views;
+ views.push_back( View(view, colorspace, looks) );
+ displays[display] = views;
+ }
+ else
+ {
+ ViewVec & views = iter->second;
+ int index = find_view(views, view);
+ if(index<0)
+ {
+ views.push_back( View(view, colorspace, looks) );
+ }
+ else
+ {
+ views[index].colorspace = colorspace;
+ views[index].looks = looks;
+ }
+ }
+ }
+
+ void ComputeDisplays(StringVec & displayCache,
+ const DisplayMap & displays,
+ const StringVec & activeDisplays,
+ const StringVec & activeDisplaysEnvOverride)
+ {
+ displayCache.clear();
+
+ StringVec displayMasterList;
+ for(DisplayMap::const_iterator iter = displays.begin();
+ iter != displays.end();
+ ++iter)
+ {
+ displayMasterList.push_back(iter->first);
+ }
+
+ // Apply the env override if it's not empty.
+ if(!activeDisplaysEnvOverride.empty())
+ {
+ displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplaysEnvOverride);
+ if(!displayCache.empty()) return;
+ }
+ // Otherwise, aApply the active displays if it's not empty.
+ else if(!activeDisplays.empty())
+ {
+ displayCache = IntersectStringVecsCaseIgnore(displayMasterList, activeDisplays);
+ if(!displayCache.empty()) return;
+ }
+
+ displayCache = displayMasterList;
+ }
+
+
+
+ } // namespace
+
+ class Config::Impl
+ {
+ public:
+ ContextRcPtr context_;
+ std::string description_;
+ ColorSpaceVec colorspaces_;
+ StringMap roles_;
+ LookVec looksList_;
+
+ DisplayMap displays_;
+ StringVec activeDisplays_;
+ StringVec activeDisplaysEnvOverride_;
+ StringVec activeViews_;
+ StringVec activeViewsEnvOverride_;
+
+ mutable std::string activeDisplaysStr_;
+ mutable std::string activeViewsStr_;
+ mutable StringVec displayCache_;
+
+ // Misc
+ std::vector<float> defaultLumaCoefs_;
+ bool strictParsing_;
+
+ mutable Sanity sanity_;
+ mutable std::string sanitytext_;
+
+ mutable Mutex cacheidMutex_;
+ mutable StringMap cacheids_;
+ mutable std::string cacheidnocontext_;
+
+ Impl() :
+ context_(Context::Create()),
+ strictParsing_(true),
+ sanity_(SANITY_UNKNOWN)
+ {
+ context_->loadEnvironment();
+
+ char* activeDisplays = std::getenv(OCIO_ACTIVE_DISPLAYS_ENVVAR);
+ SplitStringEnvStyle(activeDisplaysEnvOverride_, activeDisplays);
+
+ char * activeViews = std::getenv(OCIO_ACTIVE_VIEWS_ENVVAR);
+ SplitStringEnvStyle(activeViewsEnvOverride_, activeViews);
+
+ defaultLumaCoefs_.resize(3);
+ defaultLumaCoefs_[0] = DEFAULT_LUMA_COEFF_R;
+ defaultLumaCoefs_[1] = DEFAULT_LUMA_COEFF_G;
+ defaultLumaCoefs_[2] = DEFAULT_LUMA_COEFF_B;
+ }
+
+ ~Impl()
+ {
+
+ }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ context_ = rhs.context_->createEditableCopy();
+ description_ = rhs.description_;
+
+ // Deep copy the colorspaces
+ colorspaces_.clear();
+ colorspaces_.reserve(rhs.colorspaces_.size());
+ for(unsigned int i=0; i<rhs.colorspaces_.size(); ++i)
+ {
+ colorspaces_.push_back(rhs.colorspaces_[i]->createEditableCopy());
+ }
+
+ // Deep copy the looks
+ looksList_.clear();
+ looksList_.reserve(rhs.looksList_.size());
+ for(unsigned int i=0; i<rhs.looksList_.size(); ++i)
+ {
+ looksList_.push_back(rhs.looksList_[i]->createEditableCopy());
+ }
+
+ // Assignment operator will suffice for these
+ roles_ = rhs.roles_;
+
+ displays_ = rhs.displays_;
+ activeDisplays_ = rhs.activeDisplays_;
+ activeViews_ = rhs.activeViews_;
+ activeViewsEnvOverride_ = rhs.activeViewsEnvOverride_;
+ activeDisplaysEnvOverride_ = rhs.activeDisplaysEnvOverride_;
+ activeDisplaysStr_ = rhs.activeDisplaysStr_;
+ displayCache_ = rhs.displayCache_;
+
+ defaultLumaCoefs_ = rhs.defaultLumaCoefs_;
+ strictParsing_ = rhs.strictParsing_;
+
+ sanity_ = rhs.sanity_;
+ sanitytext_ = rhs.sanitytext_;
+
+ cacheids_ = rhs.cacheids_;
+ cacheidnocontext_ = cacheidnocontext_;
+ return *this;
+ }
+
+ void load(std::istream & istream, const char * name);
+
+ // Any time you modify the state of the config, you must call this
+ // to reset internal cache states. You also should do this in a
+ // thread safe manner by acquiring the cacheidMutex_;
+ void resetCacheIDs();
+
+ // Get all internal transforms (to generate cacheIDs, validation, etc).
+ // This currently crawls colorspaces + looks
+ void getAllIntenalTransforms(ConstTransformVec & transformVec) const;
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ ConfigRcPtr Config::Create()
+ {
+ return ConfigRcPtr(new Config(), &deleter);
+ }
+
+ void Config::deleter(Config* c)
+ {
+ delete c;
+ }
+
+ ConstConfigRcPtr Config::CreateFromEnv()
+ {
+ char* file = std::getenv(OCIO_CONFIG_ENVVAR);
+ if(file) return CreateFromFile(file);
+
+ std::ostringstream os;
+ os << "Color management disabled. ";
+ os << "(Specify the $OCIO environment variable to enable.)";
+ LogInfo(os.str());
+
+ std::istringstream istream;
+ istream.str(INTERNAL_RAW_PROFILE);
+
+ ConfigRcPtr config = Config::Create();
+ config->getImpl()->load(istream, "");
+ return config;
+ }
+
+ ConstConfigRcPtr Config::CreateFromFile(const char * filename)
+ {
+ std::ifstream istream(filename);
+ if(istream.fail()) {
+ std::ostringstream os;
+ os << "Error could not read '" << filename;
+ os << "' OCIO profile.";
+ throw Exception (os.str().c_str());
+ }
+
+ ConfigRcPtr config = Config::Create();
+ config->getImpl()->load(istream, filename);
+ return config;
+ }
+
+ ConstConfigRcPtr Config::CreateFromStream(std::istream & istream)
+ {
+ ConfigRcPtr config = Config::Create();
+ config->getImpl()->load(istream, "");
+ return config;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ Config::Config()
+ : m_impl(new Config::Impl)
+ {
+ }
+
+ Config::~Config()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ ConfigRcPtr Config::createEditableCopy() const
+ {
+ ConfigRcPtr config = Config::Create();
+ *config->m_impl = *m_impl;
+ return config;
+ }
+
+ void Config::sanityCheck() const
+ {
+ if(getImpl()->sanity_ == SANITY_SANE) return;
+ if(getImpl()->sanity_ == SANITY_INSANE)
+ {
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ getImpl()->sanity_ = SANITY_INSANE;
+ getImpl()->sanitytext_ = "";
+
+
+ ///// COLORSPACES
+ StringSet existingColorSpaces;
+
+ // Confirm all ColorSpaces are valid
+ for(unsigned int i=0; i<getImpl()->colorspaces_.size(); ++i)
+ {
+ if(!getImpl()->colorspaces_[i])
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The colorspace at index " << i << " is null.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ const char * name = getImpl()->colorspaces_[i]->getName();
+ if(!name || strlen(name) == 0)
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The colorspace at index " << i << " is not named.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ std::string namelower = pystring::lower(name);
+ StringSet::const_iterator it = existingColorSpaces.find(namelower);
+ if(it != existingColorSpaces.end())
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "Two colorspaces are defined with the same name, '";
+ os << namelower << "'.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ existingColorSpaces.insert(namelower);
+ }
+
+ // Confirm all roles are valid
+ {
+ for(StringMap::const_iterator iter = getImpl()->roles_.begin(),
+ end = getImpl()->roles_.end(); iter!=end; ++iter)
+ {
+ int csindex = -1;
+ if(!FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, iter->second))
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The role '" << iter->first << "' ";
+ os << "refers to a colorspace, '" << iter->second << "', ";
+ os << "which is not defined.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ // Confirm no name conflicts between colorspaces and roles
+ if(FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, iter->first))
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The role '" << iter->first << "' ";
+ os << " is in conflict with a colorspace of the same name.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+ }
+ }
+
+ ///// DISPLAYS
+
+ int numviews = 0;
+
+ // Confirm all Displays transforms refer to colorspaces that exit
+ for(DisplayMap::const_iterator iter = getImpl()->displays_.begin();
+ iter != getImpl()->displays_.end();
+ ++iter)
+ {
+ std::string display = iter->first;
+ const ViewVec & views = iter->second;
+ if(views.empty())
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The display '" << display << "' ";
+ os << "does not define any views.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ for(unsigned int i=0; i<views.size(); ++i)
+ {
+ if(views[i].name.empty() || views[i].colorspace.empty())
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The display '" << display << "' ";
+ os << "defines a view with an empty name and/or colorspace.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ int csindex = -1;
+ if(!FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, views[i].colorspace))
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The display '" << display << "' ";
+ os << "refers to a colorspace, '" << views[i].colorspace << "', ";
+ os << "which is not defined.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ // Confirm looks references exist
+ LookParseResult looks;
+ const LookParseResult::Options & options = looks.parse(views[i].looks);
+
+ for(unsigned int optionindex=0;
+ optionindex<options.size();
+ ++optionindex)
+ {
+ for(unsigned int tokenindex=0;
+ tokenindex<options[optionindex].size();
+ ++tokenindex)
+ {
+ std::string look = options[optionindex][tokenindex].name;
+
+ if(!look.empty() && !getLook(look.c_str()))
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The display '" << display << "' ";
+ os << "refers to a look, '" << look << "', ";
+ os << "which is not defined.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+ }
+ }
+
+ ++numviews;
+ }
+ }
+
+ // Confirm at least one display entry exists.
+ if(numviews == 0)
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "No displays are specified.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ // Confirm for all Transforms that reference internal colorspaces,
+ // the named space exists
+ {
+ ConstTransformVec allTransforms;
+ getImpl()->getAllIntenalTransforms(allTransforms);
+
+ std::set<std::string> colorSpaceNames;
+ for(unsigned int i=0; i<colorSpaceNames.size(); ++i)
+ {
+ GetColorSpaceReferences(colorSpaceNames, allTransforms[i]);
+ }
+
+ for(std::set<std::string>::iterator iter = colorSpaceNames.begin();
+ iter != colorSpaceNames.end(); ++iter)
+ {
+ int csindex = -1;
+ if(!FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, *iter))
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "This config references a ColorSpace, '" << *iter << "', ";
+ os << "which is not defined.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+ }
+ }
+
+ ///// LOOKS
+
+ // For all looks, confirm the process space exists and the look is named
+ for(unsigned int i=0; i<getImpl()->looksList_.size(); ++i)
+ {
+ std::string name = getImpl()->looksList_[i]->getName();
+ if(name.empty())
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The look at index '" << i << "' ";
+ os << "does not specify a name.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ std::string processSpace = getImpl()->looksList_[i]->getProcessSpace();
+ if(processSpace.empty())
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The look '" << name << "' ";
+ os << "does not specify a process space.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+
+ int csindex=0;
+ if(!FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, processSpace))
+ {
+ std::ostringstream os;
+ os << "Config failed sanitycheck. ";
+ os << "The look '" << name << "' ";
+ os << "specifies a process color space, '";
+ os << processSpace << "', which is not defined.";
+ getImpl()->sanitytext_ = os.str();
+ throw Exception(getImpl()->sanitytext_.c_str());
+ }
+ }
+
+
+
+ // Everything is groovy.
+ getImpl()->sanity_ = SANITY_SANE;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ const char * Config::getDescription() const
+ {
+ return getImpl()->description_.c_str();
+ }
+
+ void Config::setDescription(const char * description)
+ {
+ getImpl()->description_ = description;
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+
+ // RESOURCES //////////////////////////////////////////////////////////////
+
+ ConstContextRcPtr Config::getCurrentContext() const
+ {
+ return getImpl()->context_;
+ }
+
+ const char * Config::getSearchPath() const
+ {
+ return getImpl()->context_->getSearchPath();
+ }
+
+ void Config::setSearchPath(const char * path)
+ {
+ getImpl()->context_->setSearchPath(path);
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ const char * Config::getWorkingDir() const
+ {
+ return getImpl()->context_->getWorkingDir();
+ }
+
+ void Config::setWorkingDir(const char * dirname)
+ {
+ getImpl()->context_->setWorkingDir(dirname);
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ int Config::getNumColorSpaces() const
+ {
+ return static_cast<int>(getImpl()->colorspaces_.size());
+ }
+
+ const char * Config::getColorSpaceNameByIndex(int index) const
+ {
+ if(index<0 || index >= (int)getImpl()->colorspaces_.size())
+ {
+ return "";
+ }
+
+ return getImpl()->colorspaces_[index]->getName();
+ }
+
+ ConstColorSpaceRcPtr Config::getColorSpace(const char * name) const
+ {
+ int index = getIndexForColorSpace(name);
+ if(index<0 || index >= (int)getImpl()->colorspaces_.size())
+ {
+ return ColorSpaceRcPtr();
+ }
+
+ return getImpl()->colorspaces_[index];
+ }
+
+ int Config::getIndexForColorSpace(const char * name) const
+ {
+ int csindex = -1;
+
+ // Check to see if the name is a color space
+ if( FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, name) )
+ {
+ return csindex;
+ }
+
+ // Check to see if the name is a role
+ std::string csname = LookupRole(getImpl()->roles_, name);
+ if( FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, csname) )
+ {
+ return csindex;
+ }
+
+ // Is a default role defined?
+ // (And, are we allowed to use it)
+ if(!getImpl()->strictParsing_)
+ {
+ csname = LookupRole(getImpl()->roles_, ROLE_DEFAULT);
+ if( FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, csname) )
+ {
+ return csindex;
+ }
+ }
+
+ return -1;
+ }
+
+ void Config::addColorSpace(const ConstColorSpaceRcPtr & original)
+ {
+ ColorSpaceRcPtr cs = original->createEditableCopy();
+
+ std::string name = cs->getName();
+ if(name.empty())
+ throw Exception("Cannot addColorSpace with an empty name.");
+
+ // Check to see if the colorspace already exists
+ int csindex = -1;
+ if( FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, name) )
+ {
+ getImpl()->colorspaces_[csindex] = cs;
+ }
+ else
+ {
+ // Otherwise, add it
+ getImpl()->colorspaces_.push_back( cs );
+ }
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ void Config::clearColorSpaces()
+ {
+ getImpl()->colorspaces_.clear();
+ }
+
+
+
+
+
+
+ const char * Config::parseColorSpaceFromString(const char * str) const
+ {
+ if(!str) return "";
+
+ // Search the entire filePath, including directory name (if provided)
+ // convert the filename to lowercase.
+ std::string fullstr = pystring::lower(std::string(str));
+
+ // See if it matches a lut name.
+ // This is the position of the RIGHT end of the colorspace substring, not the left
+ int rightMostColorPos=-1;
+ std::string rightMostColorspace = "";
+ int rightMostColorSpaceIndex = -1;
+
+ // Find the right-most occcurance within the string for each colorspace.
+ for (unsigned int i=0; i<getImpl()->colorspaces_.size(); ++i)
+ {
+ std::string csname = pystring::lower(getImpl()->colorspaces_[i]->getName());
+
+ // find right-most extension matched in filename
+ int colorspacePos = pystring::rfind(fullstr, csname);
+ if(colorspacePos < 0)
+ continue;
+
+ // If we have found a match, move the pointer over to the right end of the substring
+ // This will allow us to find the longest name that matches the rightmost colorspace
+ colorspacePos += (int)csname.size();
+
+ if ( (colorspacePos > rightMostColorPos) ||
+ ((colorspacePos == rightMostColorPos) && (csname.size() > rightMostColorspace.size()))
+ )
+ {
+ rightMostColorPos = colorspacePos;
+ rightMostColorspace = csname;
+ rightMostColorSpaceIndex = i;
+ }
+ }
+
+ if(rightMostColorSpaceIndex>=0)
+ {
+ return getImpl()->colorspaces_[rightMostColorSpaceIndex]->getName();
+ }
+
+ if(!getImpl()->strictParsing_)
+ {
+ // Is a default role defined?
+ std::string csname = LookupRole(getImpl()->roles_, ROLE_DEFAULT);
+ if(!csname.empty())
+ {
+ int csindex = -1;
+ if( FindColorSpaceIndex(&csindex, getImpl()->colorspaces_, csname) )
+ {
+ // This is necessary to not return a reference to
+ // a local variable.
+ return getImpl()->colorspaces_[csindex]->getName();
+ }
+ }
+ }
+
+ return "";
+ }
+
+ bool Config::isStrictParsingEnabled() const
+ {
+ return getImpl()->strictParsing_;
+ }
+
+ void Config::setStrictParsingEnabled(bool enabled)
+ {
+ getImpl()->strictParsing_ = enabled;
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ // Roles
+ void Config::setRole(const char * role, const char * colorSpaceName)
+ {
+ // Set the role
+ if(colorSpaceName)
+ {
+ getImpl()->roles_[pystring::lower(role)] = std::string(colorSpaceName);
+ }
+ // Unset the role
+ else
+ {
+ StringMap::iterator iter = getImpl()->roles_.find(pystring::lower(role));
+ if(iter != getImpl()->roles_.end())
+ {
+ getImpl()->roles_.erase(iter);
+ }
+ }
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ int Config::getNumRoles() const
+ {
+ return static_cast<int>(getImpl()->roles_.size());
+ }
+
+ bool Config::hasRole(const char * role) const
+ {
+ return LookupRole(getImpl()->roles_, role) == "" ? false : true;
+ }
+
+ const char * Config::getRoleName(int index) const
+ {
+ if(index < 0 || index >= (int)getImpl()->roles_.size()) return "";
+ StringMap::const_iterator iter = getImpl()->roles_.begin();
+ for(int i = 0; i < index; ++i) ++iter;
+ return iter->first.c_str();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // Display/View Registration
+
+
+ const char * Config::getDefaultDisplay() const
+ {
+ if(getImpl()->displayCache_.empty())
+ {
+ ComputeDisplays(getImpl()->displayCache_,
+ getImpl()->displays_,
+ getImpl()->activeDisplays_,
+ getImpl()->activeDisplaysEnvOverride_);
+ }
+
+ int index = -1;
+
+ if(!getImpl()->activeDisplaysEnvOverride_.empty())
+ {
+ StringVec orderedDisplays = IntersectStringVecsCaseIgnore(getImpl()->activeDisplaysEnvOverride_,
+ getImpl()->displayCache_);
+ if(!orderedDisplays.empty())
+ {
+ index = FindInStringVecCaseIgnore(getImpl()->displayCache_, orderedDisplays[0]);
+ }
+ }
+ else if(!getImpl()->activeDisplays_.empty())
+ {
+ StringVec orderedDisplays = IntersectStringVecsCaseIgnore(getImpl()->activeDisplays_,
+ getImpl()->displayCache_);
+ if(!orderedDisplays.empty())
+ {
+ index = FindInStringVecCaseIgnore(getImpl()->displayCache_, orderedDisplays[0]);
+ }
+ }
+
+ if(index >= 0)
+ {
+ return getImpl()->displayCache_[index].c_str();
+ }
+
+ if(!getImpl()->displayCache_.empty())
+ {
+ return getImpl()->displayCache_[0].c_str();
+ }
+
+ return "";
+ }
+
+
+ int Config::getNumDisplays() const
+ {
+ if(getImpl()->displayCache_.empty())
+ {
+ ComputeDisplays(getImpl()->displayCache_,
+ getImpl()->displays_,
+ getImpl()->activeDisplays_,
+ getImpl()->activeDisplaysEnvOverride_);
+ }
+
+ return static_cast<int>(getImpl()->displayCache_.size());
+ }
+
+ const char * Config::getDisplay(int index) const
+ {
+ if(getImpl()->displayCache_.empty())
+ {
+ ComputeDisplays(getImpl()->displayCache_,
+ getImpl()->displays_,
+ getImpl()->activeDisplays_,
+ getImpl()->activeDisplaysEnvOverride_);
+ }
+
+ if(index>=0 || index < static_cast<int>(getImpl()->displayCache_.size()))
+ {
+ return getImpl()->displayCache_[index].c_str();
+ }
+
+ return "";
+ }
+
+ const char * Config::getDefaultView(const char * display) const
+ {
+ if(getImpl()->displayCache_.empty())
+ {
+ ComputeDisplays(getImpl()->displayCache_,
+ getImpl()->displays_,
+ getImpl()->activeDisplays_,
+ getImpl()->activeDisplaysEnvOverride_);
+ }
+
+ if(!display) return "";
+
+ DisplayMap::const_iterator iter = find_display_const(getImpl()->displays_, display);
+ if(iter == getImpl()->displays_.end()) return "";
+
+ const ViewVec & views = iter->second;
+
+ StringVec masterViews;
+ for(unsigned int i=0; i<views.size(); ++i)
+ {
+ masterViews.push_back(views[i].name);
+ }
+
+ int index = -1;
+
+ if(!getImpl()->activeViewsEnvOverride_.empty())
+ {
+ StringVec orderedViews = IntersectStringVecsCaseIgnore(getImpl()->activeViewsEnvOverride_,
+ masterViews);
+ if(!orderedViews.empty())
+ {
+ index = FindInStringVecCaseIgnore(masterViews, orderedViews[0]);
+ }
+ }
+ else if(!getImpl()->activeViews_.empty())
+ {
+ StringVec orderedViews = IntersectStringVecsCaseIgnore(getImpl()->activeViews_,
+ masterViews);
+ if(!orderedViews.empty())
+ {
+ index = FindInStringVecCaseIgnore(masterViews, orderedViews[0]);
+ }
+ }
+
+ if(index >= 0)
+ {
+ return views[index].name.c_str();
+ }
+
+ if(!views.empty())
+ {
+ return views[0].name.c_str();
+ }
+
+ return "";
+ }
+
+ int Config::getNumViews(const char * display) const
+ {
+ if(getImpl()->displayCache_.empty())
+ {
+ ComputeDisplays(getImpl()->displayCache_,
+ getImpl()->displays_,
+ getImpl()->activeDisplays_,
+ getImpl()->activeDisplaysEnvOverride_);
+ }
+
+ if(!display) return 0;
+
+ DisplayMap::const_iterator iter = find_display_const(getImpl()->displays_, display);
+ if(iter == getImpl()->displays_.end()) return 0;
+
+ const ViewVec & views = iter->second;
+ return static_cast<int>(views.size());
+ }
+
+ const char * Config::getView(const char * display, int index) const
+ {
+ if(getImpl()->displayCache_.empty())
+ {
+ ComputeDisplays(getImpl()->displayCache_,
+ getImpl()->displays_,
+ getImpl()->activeDisplays_,
+ getImpl()->activeDisplaysEnvOverride_);
+ }
+
+ if(!display) return "";
+
+ DisplayMap::const_iterator iter = find_display_const(getImpl()->displays_, display);
+ if(iter == getImpl()->displays_.end()) return "";
+
+ const ViewVec & views = iter->second;
+ return views[index].name.c_str();
+ }
+
+ const char * Config::getDisplayColorSpaceName(const char * display, const char * view) const
+ {
+ if(!display || !view) return "";
+
+ DisplayMap::const_iterator iter = find_display_const(getImpl()->displays_, display);
+ if(iter == getImpl()->displays_.end()) return "";
+
+ const ViewVec & views = iter->second;
+ int index = find_view(views, view);
+ if(index<0) return "";
+
+ return views[index].colorspace.c_str();
+ }
+
+ const char * Config::getDisplayLooks(const char * display, const char * view) const
+ {
+ if(!display || !view) return "";
+
+ DisplayMap::const_iterator iter = find_display_const(getImpl()->displays_, display);
+ if(iter == getImpl()->displays_.end()) return "";
+
+ const ViewVec & views = iter->second;
+ int index = find_view(views, view);
+ if(index<0) return "";
+
+ return views[index].looks.c_str();
+ }
+
+ void Config::addDisplay(const char * display, const char * view,
+ const char * colorSpaceName, const char * lookName)
+ {
+
+ if(!display || !view || !colorSpaceName || !lookName) return;
+
+ AddDisplay(getImpl()->displays_,
+ display, view, colorSpaceName, lookName);
+ getImpl()->displayCache_.clear();
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ void Config::clearDisplays()
+ {
+ getImpl()->displays_.clear();
+ getImpl()->displayCache_.clear();
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ void Config::setActiveDisplays(const char * displays)
+ {
+ getImpl()->activeDisplays_.clear();
+ SplitStringEnvStyle(getImpl()->activeDisplays_, displays);
+
+ getImpl()->displayCache_.clear();
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ const char * Config::getActiveDisplays() const
+ {
+ getImpl()->activeDisplaysStr_ = JoinStringEnvStyle(getImpl()->activeDisplays_);
+ return getImpl()->activeDisplaysStr_.c_str();
+ }
+
+ void Config::setActiveViews(const char * views)
+ {
+ getImpl()->activeViews_.clear();
+ SplitStringEnvStyle(getImpl()->activeViews_, views);
+
+ getImpl()->displayCache_.clear();
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ const char * Config::getActiveViews() const
+ {
+ getImpl()->activeViewsStr_ = JoinStringEnvStyle(getImpl()->activeViews_);
+ return getImpl()->activeViewsStr_.c_str();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ void Config::getDefaultLumaCoefs(float * c3) const
+ {
+ memcpy(c3, &getImpl()->defaultLumaCoefs_[0], 3*sizeof(float));
+ }
+
+ void Config::setDefaultLumaCoefs(const float * c3)
+ {
+ memcpy(&getImpl()->defaultLumaCoefs_[0], c3, 3*sizeof(float));
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+
+ ConstLookRcPtr Config::getLook(const char * name) const
+ {
+ std::string namelower = pystring::lower(name);
+
+ for(unsigned int i=0; i<getImpl()->looksList_.size(); ++i)
+ {
+ if(pystring::lower(getImpl()->looksList_[i]->getName()) == namelower)
+ {
+ return getImpl()->looksList_[i];
+ }
+ }
+
+ return ConstLookRcPtr();
+ }
+
+ int Config::getNumLooks() const
+ {
+ return static_cast<int>(getImpl()->looksList_.size());
+ }
+
+ const char * Config::getLookNameByIndex(int index) const
+ {
+ if(index<0 || index>=static_cast<int>(getImpl()->looksList_.size()))
+ {
+ return "";
+ }
+
+ return getImpl()->looksList_[index]->getName();
+ }
+
+ void Config::addLook(const ConstLookRcPtr & look)
+ {
+ std::string name = look->getName();
+ if(name.empty())
+ throw Exception("Cannot addLook with an empty name.");
+
+ std::string namelower = pystring::lower(name);
+
+ // If the look exists, replace it
+ for(unsigned int i=0; i<getImpl()->looksList_.size(); ++i)
+ {
+ if(pystring::lower(getImpl()->looksList_[i]->getName()) == namelower)
+ {
+ getImpl()->looksList_[i] = look->createEditableCopy();
+ return;
+ }
+ }
+
+ // Otherwise, add it
+ getImpl()->looksList_.push_back(look->createEditableCopy());
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ void Config::clearLooks()
+ {
+ getImpl()->looksList_.clear();
+
+ AutoMutex lock(getImpl()->cacheidMutex_);
+ getImpl()->resetCacheIDs();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ ConstProcessorRcPtr Config::getProcessor(const ConstColorSpaceRcPtr & src,
+ const ConstColorSpaceRcPtr & dst) const
+ {
+ ConstContextRcPtr context = getCurrentContext();
+ return getProcessor(context, src, dst);
+ }
+
+ ConstProcessorRcPtr Config::getProcessor(const ConstContextRcPtr & context,
+ const ConstColorSpaceRcPtr & src,
+ const ConstColorSpaceRcPtr & dst) const
+ {
+ if(!src)
+ {
+ throw Exception("Config::GetProcessor failed. Source colorspace is null.");
+ }
+ if(!dst)
+ {
+ throw Exception("Config::GetProcessor failed. Destination colorspace is null.");
+ }
+
+ ProcessorRcPtr processor = Processor::Create();
+ processor->getImpl()->addColorSpaceConversion(*this, context, src, dst);
+ processor->getImpl()->finalize();
+ return processor;
+ }
+
+ ConstProcessorRcPtr Config::getProcessor(const char * srcName,
+ const char * dstName) const
+ {
+ ConstContextRcPtr context = getCurrentContext();
+ return getProcessor(context, srcName, dstName);
+ }
+
+ //! Names can be colorspace name or role name
+ ConstProcessorRcPtr Config::getProcessor(const ConstContextRcPtr & context,
+ const char * srcName,
+ const char * dstName) const
+ {
+ ConstColorSpaceRcPtr src = getColorSpace(srcName);
+ if(!src)
+ {
+ std::ostringstream os;
+ os << "Could not find colorspace '" << srcName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ ConstColorSpaceRcPtr dst = getColorSpace(dstName);
+ if(!dst)
+ {
+ std::ostringstream os;
+ os << "Could not find colorspace '" << dstName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ return getProcessor(context, src, dst);
+ }
+
+
+ ConstProcessorRcPtr Config::getProcessor(const ConstTransformRcPtr& transform) const
+ {
+ return getProcessor(transform, TRANSFORM_DIR_FORWARD);
+ }
+
+
+ ConstProcessorRcPtr Config::getProcessor(const ConstTransformRcPtr& transform,
+ TransformDirection direction) const
+ {
+ ConstContextRcPtr context = getCurrentContext();
+ return getProcessor(context, transform, direction);
+ }
+
+ ConstProcessorRcPtr Config::getProcessor(const ConstContextRcPtr & context,
+ const ConstTransformRcPtr& transform,
+ TransformDirection direction) const
+ {
+ ProcessorRcPtr processor = Processor::Create();
+ processor->getImpl()->addTransform(*this, context, transform, direction);
+ processor->getImpl()->finalize();
+ return processor;
+ }
+
+ std::ostream& operator<< (std::ostream& os, const Config& config)
+ {
+ config.serialize(os);
+ return os;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // CacheID
+
+ const char * Config::getCacheID() const
+ {
+ return getCacheID(getCurrentContext());
+ }
+
+ const char * Config::getCacheID(const ConstContextRcPtr & context) const
+ {
+ AutoMutex lock(getImpl()->cacheidMutex_);
+
+ // A null context will use the empty cacheid
+ std::string contextcacheid = "";
+ if(context) contextcacheid = context->getCacheID();
+
+ StringMap::const_iterator cacheiditer = getImpl()->cacheids_.find(contextcacheid);
+ if(cacheiditer != getImpl()->cacheids_.end())
+ {
+ return cacheiditer->second.c_str();
+ }
+
+ // Include the hash of the yaml config serialization
+ if(getImpl()->cacheidnocontext_.empty())
+ {
+ std::stringstream cacheid;
+ serialize(cacheid);
+ std::string fullstr = cacheid.str();
+ getImpl()->cacheidnocontext_ = CacheIDHash(fullstr.c_str(), (int)fullstr.size());
+ }
+
+ // Also include all file references, using the context (if specified)
+ std::string fileReferencesFashHash = "";
+ if(context)
+ {
+ std::ostringstream filehash;
+
+ ConstTransformVec allTransforms;
+ getImpl()->getAllIntenalTransforms(allTransforms);
+
+ std::set<std::string> files;
+ for(unsigned int i=0; i<allTransforms.size(); ++i)
+ {
+ GetFileReferences(files, allTransforms[i]);
+ }
+
+ for(std::set<std::string>::iterator iter = files.begin();
+ iter != files.end(); ++iter)
+ {
+ if(iter->empty()) continue;
+ filehash << *iter << "=";
+
+ try
+ {
+ std::string resolvedLocation = context->resolveFileLocation(iter->c_str());
+ filehash << GetFastFileHash(resolvedLocation) << " ";
+ }
+ catch(...)
+ {
+ filehash << "? ";
+ continue;
+ }
+ }
+
+ std::string fullstr = filehash.str();
+ fileReferencesFashHash = CacheIDHash(fullstr.c_str(), (int)fullstr.size());
+ }
+
+ getImpl()->cacheids_[contextcacheid] = getImpl()->cacheidnocontext_ + ":" + fileReferencesFashHash;
+ return getImpl()->cacheids_[contextcacheid].c_str();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Serialization
+
+ void Config::serialize(std::ostream& os) const
+ {
+ try
+ {
+ YAML::Emitter out;
+ out << YAML::Block;
+ out << YAML::BeginMap;
+ out << YAML::Key << "ocio_profile_version" << YAML::Value << 1;
+ out << YAML::Newline;
+
+ out << YAML::Key << "search_path" << YAML::Value << getImpl()->context_->getSearchPath();
+ out << YAML::Key << "strictparsing" << YAML::Value << getImpl()->strictParsing_;
+ out << YAML::Key << "luma" << YAML::Value << YAML::Flow << getImpl()->defaultLumaCoefs_;
+
+ if(getImpl()->description_ != "")
+ {
+ out << YAML::Newline;
+ out << YAML::Key << "description";
+ out << YAML::Value << getImpl()->description_;
+ }
+
+ // Roles
+ out << YAML::Newline;
+ out << YAML::Key << "roles";
+ out << YAML::Value << getImpl()->roles_;
+
+ // Displays
+ out << YAML::Newline;
+ out << YAML::Key << "displays";
+ out << YAML::Value << getImpl()->displays_;
+ out << YAML::Newline;
+ out << YAML::Key << "active_displays";
+ out << YAML::Value << YAML::Flow << getImpl()->activeDisplays_;
+ out << YAML::Key << "active_views";
+ out << YAML::Value << YAML::Flow << getImpl()->activeViews_;
+
+ // Looks
+ if(!getImpl()->looksList_.empty())
+ {
+ out << YAML::Newline;
+ out << YAML::Key << "looks";
+ out << YAML::Value << getImpl()->looksList_;
+ }
+
+ // ColorSpaces
+ {
+ out << YAML::Newline;
+ out << YAML::Key << "colorspaces";
+ out << YAML::Value << getImpl()->colorspaces_;
+ }
+
+ out << YAML::EndMap;
+
+ os << out.c_str();
+ }
+ catch( const std::exception & e)
+ {
+ std::ostringstream error;
+ error << "Error building YAML: " << e.what();
+ throw Exception(error.str().c_str());
+ }
+ }
+
+ void Config::Impl::load(std::istream & istream, const char * filename)
+ {
+ try
+ {
+ YAML::Parser parser(istream);
+ YAML::Node node;
+ parser.GetNextDocument(node);
+
+ // check profile version
+ int profile_version = 0;
+ if(node.FindValue("ocio_profile_version") == NULL)
+ {
+ std::ostringstream os;
+ os << "The specified file ";
+ os << "does not appear to be an OCIO configuration.";
+ throw Exception (os.str().c_str());
+ }
+
+ node["ocio_profile_version"] >> profile_version;
+ if(profile_version > 1)
+ {
+ std::ostringstream os;
+ os << "This .ocio config ";
+ if(filename && *filename)
+ {
+ os << " '" << filename << "' ";
+ }
+ os << "is version " << profile_version << ". ";
+ os << "This version of the OpenColorIO library (" << OCIO_VERSION ") ";
+ os << "is not known to be able to load this profile. ";
+ os << "An attempt will be made, but there are no guarantees that the ";
+ os << "results will be accurate. Continue at your own risk.";
+ LogWarning(os.str());
+ }
+
+
+ std::string key, stringval;
+ bool boolval = false;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "ocio_profile_version") { } // Already handled above.
+ else if(key == "search_path" || key == "resource_path")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ context_->setSearchPath(stringval.c_str());
+ }
+ else if(key == "strictparsing")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<bool>(boolval))
+ strictParsing_ = boolval;
+ }
+ else if(key == "description")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ description_ = stringval;
+ }
+ else if(key == "luma")
+ {
+ std::vector<float> val;
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> val;
+ if(val.size() != 3)
+ {
+ std::ostringstream os;
+ os << "'luma' field must be 3 ";
+ os << "floats. Found '" << val.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ defaultLumaCoefs_ = val;
+ }
+ }
+ else if(key == "roles")
+ {
+ const YAML::Node& roles = iter.second();
+ if(roles.Type() != YAML::NodeType::Map)
+ {
+ std::ostringstream os;
+ os << "'roles' field needs to be a (name: key) map.";
+ throw Exception(os.str().c_str());
+ }
+ for (YAML::Iterator it = roles.begin();
+ it != roles.end(); ++it)
+ {
+ std::string k, v;
+ it.first() >> k;
+ it.second() >> v;
+ roles_[pystring::lower(k)] = v;
+ }
+ }
+ else if(key == "displays")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> displays_;
+ }
+ }
+ else if(key == "active_displays")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> activeDisplays_;
+ }
+ }
+ else if(key == "active_views")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> activeViews_;
+ }
+ }
+ else if(key == "colorspaces")
+ {
+ const YAML::Node& colorspaces = iter.second();
+
+ if(colorspaces.Type() != YAML::NodeType::Sequence)
+ {
+ std::ostringstream os;
+ os << "'colorspaces' field needs to be a (- !<ColorSpace>) list.";
+ throw Exception(os.str().c_str());
+ }
+
+ for(unsigned i = 0; i < colorspaces.size(); ++i)
+ {
+ if(colorspaces[i].Tag() == "ColorSpace")
+ {
+ ColorSpaceRcPtr cs = ColorSpace::Create();
+ colorspaces[i] >> cs;
+ colorspaces_.push_back( cs );
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Unknown element found in colorspaces:";
+ os << colorspaces[i].Tag() << ". Only ColorSpace(s)";
+ os << " currently handled.";
+ LogWarning(os.str());
+ }
+ }
+ }
+ else if(key == "looks")
+ {
+ const YAML::Node& looks = iter.second();
+
+ if(looks.Type() != YAML::NodeType::Sequence)
+ {
+ std::ostringstream os;
+ os << "'looks' field needs to be a (- !<Look>) list.";
+ throw Exception(os.str().c_str());
+ }
+
+ for(unsigned i = 0; i < looks.size(); ++i)
+ {
+ if(looks[i].Tag() == "Look")
+ {
+ LookRcPtr look = Look::Create();
+ looks[i] >> look;
+ looksList_.push_back( look );
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Unknown element found in looks:";
+ os << looks[i].Tag() << ". Only Look(s)";
+ os << " currently handled.";
+ LogWarning(os.str());
+ }
+ }
+ }
+ else
+ {
+ LogUnknownKeyWarning("profile", iter.first());
+ }
+ }
+
+ if(filename)
+ {
+ std::string realfilename = pystring::os::path::abspath(filename);
+ std::string configrootdir = pystring::os::path::dirname(realfilename);
+ context_->setWorkingDir(configrootdir.c_str());
+ }
+ }
+ catch( const std::exception & e)
+ {
+ std::ostringstream os;
+ os << "Error: Loading the OCIO profile ";
+ if(filename) os << "'" << filename << "' ";
+ os << "failed. " << e.what();
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ void Config::Impl::resetCacheIDs()
+ {
+ cacheids_.clear();
+ cacheidnocontext_ = "";
+ sanity_ = SANITY_UNKNOWN;
+ sanitytext_ = "";
+ }
+
+ void Config::Impl::getAllIntenalTransforms(ConstTransformVec & transformVec) const
+ {
+ // Grab all transforms from the ColorSpaces
+ for(unsigned int i=0; i<colorspaces_.size(); ++i)
+ {
+ if(colorspaces_[i]->getTransform(COLORSPACE_DIR_TO_REFERENCE))
+ transformVec.push_back(colorspaces_[i]->getTransform(COLORSPACE_DIR_TO_REFERENCE));
+ if(colorspaces_[i]->getTransform(COLORSPACE_DIR_FROM_REFERENCE))
+ transformVec.push_back(colorspaces_[i]->getTransform(COLORSPACE_DIR_FROM_REFERENCE));
+ }
+
+ // Grab all transforms from the Looks
+ for(unsigned int i=0; i<looksList_.size(); ++i)
+ {
+ if(looksList_[i]->getTransform())
+ transformVec.push_back(looksList_[i]->getTransform());
+ if(looksList_[i]->getInverseTransform())
+ transformVec.push_back(looksList_[i]->getInverseTransform());
+ }
+
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+#include <sys/stat.h>
+#include "pystring/pystring.h"
+
+#if 0
+OIIO_ADD_TEST(Config, test_searchpath_filesystem)
+{
+
+ OCIO::EnvMap env = OCIO::GetEnvMap();
+ std::string OCIO_TEST_AREA("$OCIO_TEST_AREA");
+ EnvExpand(&OCIO_TEST_AREA, &env);
+
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+
+ // basic get/set/expand
+ config->setSearchPath("."
+ ":$OCIO_TEST1"
+ ":/$OCIO_JOB/${OCIO_SEQ}/$OCIO_SHOT/ocio");
+
+ OIIO_CHECK_ASSERT(strcmp(config->getSearchPath(),
+ ".:$OCIO_TEST1:/$OCIO_JOB/${OCIO_SEQ}/$OCIO_SHOT/ocio") == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->getSearchPath(true),
+ ".:foobar:/meatballs/cheesecake/mb-cc-001/ocio") == 0);
+
+ // find some files
+ config->setSearchPath(".."
+ ":$OCIO_TEST1"
+ ":${OCIO_TEST_AREA}/test_search/one"
+ ":$OCIO_TEST_AREA/test_search/two");
+
+ // setup for search test
+ std::string base_dir("$OCIO_TEST_AREA/test_search/");
+ EnvExpand(&base_dir, &env);
+ mkdir(base_dir.c_str(), 0777);
+
+ std::string one_dir("$OCIO_TEST_AREA/test_search/one/");
+ EnvExpand(&one_dir, &env);
+ mkdir(one_dir.c_str(), 0777);
+
+ std::string two_dir("$OCIO_TEST_AREA/test_search/two/");
+ EnvExpand(&two_dir, &env);
+ mkdir(two_dir.c_str(), 0777);
+
+ std::string lut1(one_dir+"somelut1.lut");
+ std::ofstream somelut1(lut1.c_str());
+ somelut1.close();
+
+ std::string lut2(two_dir+"somelut2.lut");
+ std::ofstream somelut2(lut2.c_str());
+ somelut2.close();
+
+ std::string lut3(two_dir+"somelut3.lut");
+ std::ofstream somelut3(lut3.c_str());
+ somelut3.close();
+
+ std::string lutdotdot(OCIO_TEST_AREA+"/lutdotdot.lut");
+ std::ofstream somelutdotdot(lutdotdot.c_str());
+ somelutdotdot.close();
+
+ // basic search test
+ OIIO_CHECK_ASSERT(strcmp(config->findFile("somelut1.lut"),
+ lut1.c_str()) == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->findFile("somelut2.lut"),
+ lut2.c_str()) == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->findFile("somelut3.lut"),
+ lut3.c_str()) == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->findFile("lutdotdot.lut"),
+ lutdotdot.c_str()) == 0);
+
+}
+#endif
+
+OIIO_ADD_TEST(Config, InternalRawProfile)
+{
+ std::istringstream is;
+ is.str(OCIO::INTERNAL_RAW_PROFILE);
+ OIIO_CHECK_NO_THOW(OCIO::ConstConfigRcPtr config = OCIO::Config::CreateFromStream(is));
+}
+
+OIIO_ADD_TEST(Config, SimpleConfig)
+{
+
+ std::string SIMPLE_PROFILE =
+ "ocio_profile_version: 1\n"
+ "resource_path: luts\n"
+ "strictparsing: false\n"
+ "luma: [0.2126, 0.7152, 0.0722]\n"
+ "roles:\n"
+ " compositing_log: lgh\n"
+ " default: raw\n"
+ " scene_linear: lnh\n"
+ "displays:\n"
+ " sRGB:\n"
+ " - !<View> {name: Film1D, colorspace: vd8}\n"
+ " - !<View> {name: Log, colorspace: lg10}\n"
+ " - !<View> {name: Raw, colorspace: raw}\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: raw\n"
+ " family: raw\n"
+ " equalitygroup: \n"
+ " bitdepth: 32f\n"
+ " description: |\n"
+ " A raw color space. Conversions to and from this space are no-ops.\n"
+ " isdata: true\n"
+ " allocation: uniform\n"
+ " - !<ColorSpace>\n"
+ " name: lnh\n"
+ " family: ln\n"
+ " equalitygroup: \n"
+ " bitdepth: 16f\n"
+ " description: |\n"
+ " The show reference space. This is a sensor referred linear\n"
+ " representation of the scene with primaries that correspond to\n"
+ " scanned film. 0.18 in this space corresponds to a properly\n"
+ " exposed 18% grey card.\n"
+ " isdata: false\n"
+ " allocation: lg2\n"
+ " - !<ColorSpace>\n"
+ " name: loads_of_transforms\n"
+ " family: vd8\n"
+ " equalitygroup: \n"
+ " bitdepth: 8ui\n"
+ " description: 'how many transforms can we use?'\n"
+ " isdata: false\n"
+ " allocation: uniform\n"
+ " to_reference: !<GroupTransform>\n"
+ " direction: forward\n"
+ " children:\n"
+ " - !<FileTransform>\n"
+ " src: diffusemult.spimtx\n"
+ " interpolation: unknown\n"
+ " - !<ColorSpaceTransform>\n"
+ " src: vd8\n"
+ " dst: lnh\n"
+ " - !<ExponentTransform>\n"
+ " value: [2.2, 2.2, 2.2, 1]\n"
+ " - !<MatrixTransform>\n"
+ " matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]\n"
+ " offset: [0, 0, 0, 0]\n"
+ " - !<CDLTransform>\n"
+ " slope: [1, 1, 1]\n"
+ " offset: [0, 0, 0]\n"
+ " power: [1, 1, 1]\n"
+ " saturation: 1\n"
+ "\n";
+
+ std::istringstream is;
+ is.str(SIMPLE_PROFILE);
+ OCIO::ConstConfigRcPtr config;
+ OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
+}
+
+OIIO_ADD_TEST(Config, Roles)
+{
+
+ std::string SIMPLE_PROFILE =
+ "ocio_profile_version: 1\n"
+ "strictparsing: false\n"
+ "roles:\n"
+ " compositing_log: lgh\n"
+ " default: raw\n"
+ " scene_linear: lnh\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: raw\n"
+ " - !<ColorSpace>\n"
+ " name: lnh\n"
+ " - !<ColorSpace>\n"
+ " name: lgh\n"
+ "\n";
+
+ std::istringstream is;
+ is.str(SIMPLE_PROFILE);
+ OCIO::ConstConfigRcPtr config;
+ OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
+
+ OIIO_CHECK_EQUAL(config->getNumRoles(), 3);
+
+ OIIO_CHECK_ASSERT(config->hasRole("compositing_log") == true);
+ OIIO_CHECK_ASSERT(config->hasRole("cheese") == false);
+ OIIO_CHECK_ASSERT(config->hasRole("") == false);
+
+ OIIO_CHECK_ASSERT(strcmp(config->getRoleName(2), "scene_linear") == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->getRoleName(0), "compositing_log") == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->getRoleName(1), "default") == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->getRoleName(10), "") == 0);
+ OIIO_CHECK_ASSERT(strcmp(config->getRoleName(-4), "") == 0);
+
+}
+
+OIIO_ADD_TEST(Config, Serialize)
+{
+
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("testing");
+ cs->setFamily("test");
+ OCIO::FileTransformRcPtr transform1 = \
+ OCIO::FileTransform::Create();
+ OCIO::GroupTransformRcPtr groupTransform = OCIO::GroupTransform::Create();
+ groupTransform->push_back(transform1);
+ cs->setTransform(groupTransform, OCIO::COLORSPACE_DIR_TO_REFERENCE);
+ config->addColorSpace(cs);
+ config->setRole( OCIO::ROLE_COMPOSITING_LOG, cs->getName() );
+ }
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("testing2");
+ cs->setFamily("test");
+ OCIO::ExponentTransformRcPtr transform1 = \
+ OCIO::ExponentTransform::Create();
+ OCIO::GroupTransformRcPtr groupTransform = OCIO::GroupTransform::Create();
+ groupTransform->push_back(transform1);
+ cs->setTransform(groupTransform, OCIO::COLORSPACE_DIR_TO_REFERENCE);
+ config->addColorSpace(cs);
+ config->setRole( OCIO::ROLE_COMPOSITING_LOG, cs->getName() );
+ }
+
+ // for testing
+ //std::ofstream outfile("/tmp/test.ocio");
+ //config->serialize(outfile);
+ //outfile.close();
+
+ std::ostringstream os;
+ config->serialize(os);
+
+ std::string PROFILE_OUT =
+ "ocio_profile_version: 1\n"
+ "\n"
+ "search_path: \"\"\n"
+ "strictparsing: true\n"
+ "luma: [0.2126, 0.7152, 0.0722]\n"
+ "\n"
+ "roles:\n"
+ " compositing_log: testing2\n"
+ "\n"
+ "displays:\n"
+ " {}\n"
+ "\n"
+ "active_displays: []\n"
+ "active_views: []\n"
+ "\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: testing\n"
+ " family: test\n"
+ " equalitygroup: \"\"\n"
+ " bitdepth: unknown\n"
+ " isdata: false\n"
+ " allocation: uniform\n"
+ " to_reference: !<GroupTransform>\n"
+ " children:\n"
+ " - !<FileTransform> {src: \"\", interpolation: unknown}\n"
+ "\n"
+ " - !<ColorSpace>\n"
+ " name: testing2\n"
+ " family: test\n"
+ " equalitygroup: \"\"\n"
+ " bitdepth: unknown\n"
+ " isdata: false\n"
+ " allocation: uniform\n"
+ " to_reference: !<GroupTransform>\n"
+ " children:\n"
+ " - !<ExponentTransform> {value: [1, 1, 1, 1]}\n";
+
+ std::vector<std::string> osvec;
+ OCIO::pystring::splitlines(os.str(), osvec);
+ std::vector<std::string> PROFILE_OUTvec;
+ OCIO::pystring::splitlines(PROFILE_OUT, PROFILE_OUTvec);
+
+ OIIO_CHECK_EQUAL(osvec.size(), PROFILE_OUTvec.size());
+ for(unsigned int i = 0; i < PROFILE_OUTvec.size(); ++i)
+ OIIO_CHECK_EQUAL(osvec[i], PROFILE_OUTvec[i]);
+}
+
+
+OIIO_ADD_TEST(Config, SanityCheck)
+{
+ {
+ std::string SIMPLE_PROFILE =
+ "ocio_profile_version: 1\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: raw\n"
+ " - !<ColorSpace>\n"
+ " name: raw\n"
+ "strictparsing: false\n"
+ "roles:\n"
+ " default: raw\n"
+ "displays:\n"
+ " sRGB:\n"
+ " - !<View> {name: Raw, colorspace: raw}\n"
+ "\n";
+
+ std::istringstream is;
+ is.str(SIMPLE_PROFILE);
+ OCIO::ConstConfigRcPtr config;
+ OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
+
+ OIIO_CHECK_THOW(config->sanityCheck(), OCIO::Exception);
+ }
+
+ {
+ std::string SIMPLE_PROFILE =
+ "ocio_profile_version: 1\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: raw\n"
+ "strictparsing: false\n"
+ "roles:\n"
+ " default: raw\n"
+ "displays:\n"
+ " sRGB:\n"
+ " - !<View> {name: Raw, colorspace: raw}\n"
+ "\n";
+
+ std::istringstream is;
+ is.str(SIMPLE_PROFILE);
+ OCIO::ConstConfigRcPtr config;
+ OIIO_CHECK_NO_THOW(config = OCIO::Config::CreateFromStream(is));
+
+ OIIO_CHECK_NO_THOW(config->sanityCheck());
+ }
+}
+
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/Context.cpp b/src/core/Context.cpp
new file mode 100644
index 0000000..25d4ea7
--- /dev/null
+++ b/src/core/Context.cpp
@@ -0,0 +1,364 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <map>
+#include <string>
+#include <iostream>
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "HashUtils.h"
+#include "Mutex.h"
+#include "PathUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+namespace
+{
+ typedef std::map< std::string, std::string> StringMap;
+
+ void GetAbsoluteSearchPaths(std::vector<std::string> & searchpaths,
+ const std::string & pathString,
+ const std::string & configRootDir);
+}
+
+ class Context::Impl
+ {
+ public:
+ std::string searchPath_;
+ std::string workingDir_;
+ EnvMap envMap_;
+
+ mutable std::string cacheID_;
+ mutable StringMap resultsCache_;
+ mutable Mutex resultsCacheMutex_;
+
+ Impl()
+ {
+ }
+
+ ~Impl()
+ {
+
+ }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ AutoMutex lock1(resultsCacheMutex_);
+ AutoMutex lock2(rhs.resultsCacheMutex_);
+
+ searchPath_ = rhs.searchPath_;
+ workingDir_ = rhs.workingDir_;
+ envMap_ = rhs.envMap_;
+
+ resultsCache_ = rhs.resultsCache_;
+ cacheID_ = rhs.cacheID_;
+
+ return *this;
+ }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ ContextRcPtr Context::Create()
+ {
+ return ContextRcPtr(new Context(), &deleter);
+ }
+
+ void Context::deleter(Context* c)
+ {
+ delete c;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ Context::Context()
+ : m_impl(new Context::Impl)
+ {
+ }
+
+ Context::~Context()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ ContextRcPtr Context::createEditableCopy() const
+ {
+ ContextRcPtr context = Context::Create();
+ *context->m_impl = *getImpl();
+ return context;
+ }
+
+ const char * Context::getCacheID() const
+ {
+ AutoMutex lock(getImpl()->resultsCacheMutex_);
+
+ if(getImpl()->cacheID_.empty())
+ {
+ std::ostringstream cacheid;
+ cacheid << "Search Path " << getImpl()->searchPath_ << " ";
+ cacheid << "Working Dir " << getImpl()->workingDir_ << " ";
+
+ for (EnvMap::const_iterator iter = getImpl()->envMap_.begin(),
+ end = getImpl()->envMap_.end();
+ iter != end; ++iter)
+ {
+ cacheid << iter->first << "=" << iter->second << " ";
+ }
+
+ std::string fullstr = cacheid.str();
+ getImpl()->cacheID_ = CacheIDHash(fullstr.c_str(), (int)fullstr.size());
+ }
+
+ return getImpl()->cacheID_.c_str();
+ }
+
+ void Context::setSearchPath(const char * path)
+ {
+ AutoMutex lock(getImpl()->resultsCacheMutex_);
+
+ getImpl()->searchPath_ = path;
+ getImpl()->resultsCache_.clear();
+ getImpl()->cacheID_ = "";
+ }
+
+ const char * Context::getSearchPath() const
+ {
+ return getImpl()->searchPath_.c_str();
+ }
+
+ void Context::setWorkingDir(const char * dirname)
+ {
+ AutoMutex lock(getImpl()->resultsCacheMutex_);
+
+ getImpl()->workingDir_ = dirname;
+ getImpl()->resultsCache_.clear();
+ getImpl()->cacheID_ = "";
+ }
+
+ const char * Context::getWorkingDir() const
+ {
+ return getImpl()->workingDir_.c_str();
+ }
+
+ void Context::loadEnvironment()
+ {
+ LoadEnvironment(getImpl()->envMap_);
+ }
+
+ void Context::setStringVar(const char * name, const char * value)
+ {
+ if(!name) return;
+
+ AutoMutex lock(getImpl()->resultsCacheMutex_);
+ getImpl()->resultsCache_.clear();
+ getImpl()->cacheID_ = "";
+
+ // Set the value if specified
+ if(value)
+ {
+ getImpl()->envMap_[name] = value;
+ }
+ // If a null value is specified, erase it
+ else
+ {
+ EnvMap::iterator iter = getImpl()->envMap_.find(name);
+ if(iter != getImpl()->envMap_.end())
+ {
+ getImpl()->envMap_.erase(iter);
+ }
+ }
+ }
+
+ const char * Context::getStringVar(const char * name) const
+ {
+ if(!name) return "";
+
+ EnvMap::const_iterator iter = getImpl()->envMap_.find(name);
+ if(iter != getImpl()->envMap_.end())
+ {
+ return iter->second.c_str();
+ }
+
+ return "";
+ }
+
+ int Context::getNumStringVars() const
+ {
+ return static_cast<int>(getImpl()->envMap_.size());
+ }
+
+ const char * Context::getStringVarNameByIndex(int index) const
+ {
+ if(index < 0 || index >= static_cast<int>(getImpl()->envMap_.size()))
+ return "";
+
+ EnvMap::const_iterator iter = getImpl()->envMap_.begin();
+ for(int count = 0; count<index; ++count) ++iter;
+
+ return iter->first.c_str();
+ }
+
+ const char * Context::resolveStringVar(const char * val) const
+ {
+ AutoMutex lock(getImpl()->resultsCacheMutex_);
+
+ if(!val || !*val)
+ {
+ return "";
+ }
+
+ StringMap::const_iterator iter = getImpl()->resultsCache_.find(val);
+ if(iter != getImpl()->resultsCache_.end())
+ {
+ return iter->second.c_str();
+ }
+
+
+ std::string resolvedval = EnvExpand(val, getImpl()->envMap_);
+
+ getImpl()->resultsCache_[val] = resolvedval;
+ return getImpl()->resultsCache_[val].c_str();
+ }
+
+
+
+ const char * Context::resolveFileLocation(const char * filename) const
+ {
+ AutoMutex lock(getImpl()->resultsCacheMutex_);
+
+ if(!filename || !*filename)
+ {
+ return "";
+ }
+
+ StringMap::const_iterator iter = getImpl()->resultsCache_.find(filename);
+ if(iter != getImpl()->resultsCache_.end())
+ {
+ return iter->second.c_str();
+ }
+
+ // Load an absolute file reference
+ if(pystring::os::path::isabs(filename))
+ {
+ std::string expandedfullpath = EnvExpand(filename, getImpl()->envMap_);
+ if(FileExists(expandedfullpath))
+ {
+ getImpl()->resultsCache_[filename] = expandedfullpath;
+ return getImpl()->resultsCache_[filename].c_str();
+ }
+
+ std::ostringstream errortext;
+ errortext << "The specified absolute file reference ";
+ errortext << "'" << expandedfullpath << "' could not be located. ";
+ throw Exception(errortext.str().c_str());
+ }
+
+ // Load a relative file reference
+ // Prep the search path vector
+ // TODO: Cache this prepped vector?
+ std::vector<std::string> searchpaths;
+ GetAbsoluteSearchPaths(searchpaths,
+ getImpl()->searchPath_,
+ getImpl()->workingDir_);
+
+ // Loop over each path, and try to find the file
+ std::ostringstream errortext;
+ errortext << "The specified file reference ";
+ errortext << " '" << filename << "' could not be located. ";
+ errortext << "The following attempts were made: ";
+
+ for (unsigned int i = 0; i < searchpaths.size(); ++i)
+ {
+ // Make an attempt to find the lut in one of the search paths
+ std::string fullpath = pystring::os::path::join(searchpaths[i], filename);
+ std::string expandedfullpath = EnvExpand(fullpath, getImpl()->envMap_);
+ if(FileExists(expandedfullpath))
+ {
+ getImpl()->resultsCache_[filename] = expandedfullpath;
+ return getImpl()->resultsCache_[filename].c_str();
+ }
+ if(i!=0) errortext << " : ";
+ errortext << expandedfullpath;
+ }
+
+ throw ExceptionMissingFile(errortext.str().c_str());
+ }
+
+ std::ostream& operator<< (std::ostream& os, const Context& context)
+ {
+ os << "Context:\n";
+ for(int i=0; i<context.getNumStringVars(); ++i)
+ {
+ const char * key = context.getStringVarNameByIndex(i);
+ os << key << "=" << context.getStringVar(key) << "\n";
+ }
+ return os;
+ }
+
+
+namespace
+{
+ void GetAbsoluteSearchPaths(std::vector<std::string> & searchpaths,
+ const std::string & pathString,
+ const std::string & workingDir)
+ {
+ if(pathString.empty())
+ {
+ searchpaths.push_back(workingDir);
+ return;
+ }
+
+ std::vector<std::string> parts;
+ pystring::split(pathString, parts, ":");
+
+ for (unsigned int i = 0; i < parts.size(); ++i)
+ {
+ // Remove trailing "/", and spaces
+ std::string dirname = pystring::rstrip(pystring::strip(parts[i]), "/");
+
+ if(!pystring::os::path::isabs(dirname))
+ {
+ dirname = pystring::os::path::join(workingDir, dirname);
+ }
+
+ searchpaths.push_back(pystring::os::path::normpath(dirname));
+ }
+ }
+}
+
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/DisplayTransform.cpp b/src/core/DisplayTransform.cpp
new file mode 100644
index 0000000..35216db
--- /dev/null
+++ b/src/core/DisplayTransform.cpp
@@ -0,0 +1,410 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "OpBuilders.h"
+
+#include <cmath>
+#include <cstring>
+#include <iterator>
+
+OCIO_NAMESPACE_ENTER
+{
+ DisplayTransformRcPtr DisplayTransform::Create()
+ {
+ return DisplayTransformRcPtr(new DisplayTransform(), &deleter);
+ }
+
+ void DisplayTransform::deleter(DisplayTransform* t)
+ {
+ delete t;
+ }
+
+ class DisplayTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ std::string inputColorSpaceName_;
+ TransformRcPtr linearCC_;
+ TransformRcPtr colorTimingCC_;
+ TransformRcPtr channelView_;
+ std::string display_;
+ std::string view_;
+ TransformRcPtr displayCC_;
+
+ std::string looksOverride_;
+ bool looksOverrideEnabled_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD),
+ looksOverrideEnabled_(false)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ inputColorSpaceName_ = rhs.inputColorSpaceName_;
+
+ linearCC_ = rhs.linearCC_;
+ if(linearCC_) linearCC_ = linearCC_->createEditableCopy();
+
+ colorTimingCC_ = rhs.colorTimingCC_;
+ if(colorTimingCC_) colorTimingCC_ = colorTimingCC_->createEditableCopy();
+
+ channelView_ = rhs.channelView_;
+ if(channelView_) channelView_ = channelView_->createEditableCopy();
+
+ display_ = rhs.display_;
+ view_ = rhs.view_;
+
+ displayCC_ = rhs.displayCC_;
+ if(displayCC_) displayCC_ = displayCC_->createEditableCopy();
+
+ looksOverride_ = rhs.looksOverride_;
+ looksOverrideEnabled_ = rhs.looksOverrideEnabled_;
+
+ return *this;
+ }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ DisplayTransform::DisplayTransform()
+ : m_impl(new DisplayTransform::Impl)
+ {
+ }
+
+ TransformRcPtr DisplayTransform::createEditableCopy() const
+ {
+ DisplayTransformRcPtr transform = DisplayTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ DisplayTransform::~DisplayTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ DisplayTransform& DisplayTransform::operator= (const DisplayTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection DisplayTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void DisplayTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ void DisplayTransform::setInputColorSpaceName(const char * name)
+ {
+ getImpl()->inputColorSpaceName_ = name;
+ }
+
+ const char * DisplayTransform::getInputColorSpaceName() const
+ {
+ return getImpl()->inputColorSpaceName_.c_str();
+ }
+
+ void DisplayTransform::setLinearCC(const ConstTransformRcPtr & cc)
+ {
+ getImpl()->linearCC_ = cc->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getLinearCC() const
+ {
+ return getImpl()->linearCC_;
+ }
+
+ void DisplayTransform::setColorTimingCC(const ConstTransformRcPtr & cc)
+ {
+ getImpl()->colorTimingCC_ = cc->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getColorTimingCC() const
+ {
+ return getImpl()->colorTimingCC_;
+ }
+
+ void DisplayTransform::setChannelView(const ConstTransformRcPtr & transform)
+ {
+ getImpl()->channelView_ = transform->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getChannelView() const
+ {
+ return getImpl()->channelView_;
+ }
+
+ void DisplayTransform::setDisplay(const char * display)
+ {
+ getImpl()->display_ = display;
+ }
+
+ const char * DisplayTransform::getDisplay() const
+ {
+ return getImpl()->display_.c_str();
+ }
+
+ void DisplayTransform::setView(const char * view)
+ {
+ getImpl()->view_ = view;
+ }
+
+ const char * DisplayTransform::getView() const
+ {
+ return getImpl()->view_.c_str();
+ }
+
+ void DisplayTransform::setDisplayCC(const ConstTransformRcPtr & cc)
+ {
+ getImpl()->displayCC_ = cc->createEditableCopy();
+ }
+
+ ConstTransformRcPtr DisplayTransform::getDisplayCC() const
+ {
+ return getImpl()->displayCC_;
+ }
+
+ void DisplayTransform::setLooksOverride(const char * looks)
+ {
+ getImpl()->looksOverride_ = looks;
+ }
+
+ const char * DisplayTransform::getLooksOverride() const
+ {
+ return getImpl()->looksOverride_.c_str();
+ }
+
+ void DisplayTransform::setLooksOverrideEnabled(bool enabled)
+ {
+ getImpl()->looksOverrideEnabled_ = enabled;
+ }
+
+ bool DisplayTransform::getLooksOverrideEnabled() const
+ {
+ return getImpl()->looksOverrideEnabled_;
+ }
+
+ std::ostream& operator<< (std::ostream& os, const DisplayTransform& t)
+ {
+ os << "<DisplayTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << "inputColorSpace=" << t.getInputColorSpaceName() << ", ";
+ os << "display=" << t.getDisplay() << ", ";
+ os << "view=" << t.getView() << ", ";
+ os << ">\n";
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ void BuildDisplayOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const DisplayTransform & displayTransform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ displayTransform.getDirection());
+ if(combinedDir != TRANSFORM_DIR_FORWARD)
+ {
+ std::ostringstream os;
+ os << "DisplayTransform can only be applied in the forward direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string inputColorSpaceName = displayTransform.getInputColorSpaceName();
+ ConstColorSpaceRcPtr inputColorSpace = config.getColorSpace(inputColorSpaceName.c_str());
+ if(!inputColorSpace)
+ {
+ std::ostringstream os;
+ os << "DisplayTransform error.";
+ if(inputColorSpaceName.empty()) os << " InputColorSpaceName is unspecified.";
+ else os << " Cannot find inputColorSpace, named '" << inputColorSpaceName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string display = displayTransform.getDisplay();
+ std::string view = displayTransform.getView();
+
+ std::string displayColorSpaceName = config.getDisplayColorSpaceName(display.c_str(), view.c_str());
+ ConstColorSpaceRcPtr displayColorspace = config.getColorSpace(displayColorSpaceName.c_str());
+ if(!displayColorspace)
+ {
+ std::ostringstream os;
+ os << "DisplayTransform error.";
+ os << " Cannot find display colorspace, '" << displayColorSpaceName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ bool skipColorSpaceConversions = (inputColorSpace->isData() || displayColorspace->isData());
+
+ // If we're viewing alpha, also skip all color space conversions.
+ // If the user does uses a different transform for the channel view,
+ // in place of a simple matrix, they run the risk that when viewing alpha
+ // the colorspace transforms will not be skipped. (I.e., filmlook will be applied
+ // to alpha.) If this ever becomes an issue, additional engineering will be
+ // added at that time.
+
+ ConstMatrixTransformRcPtr typedChannelView = DynamicPtrCast<const MatrixTransform>(
+ displayTransform.getChannelView());
+ if(typedChannelView)
+ {
+ float matrix44[16];
+ typedChannelView->getValue(matrix44, 0x0);
+
+ if((matrix44[3]>0.0f) || (matrix44[7]>0.0f) || (matrix44[11]>0.0f))
+ {
+ skipColorSpaceConversions = true;
+ }
+ }
+
+
+
+ ConstColorSpaceRcPtr currentColorSpace = inputColorSpace;
+
+
+
+ // Apply a transform in ROLE_SCENE_LINEAR
+ ConstTransformRcPtr linearCC = displayTransform.getLinearCC();
+ if(linearCC)
+ {
+ // Put the new ops into a temp array, to see if it's a no-op
+ // If it is a no-op, dont bother doing the colorspace conversion.
+ OpRcPtrVec tmpOps;
+ BuildOps(tmpOps, config, context, linearCC, TRANSFORM_DIR_FORWARD);
+
+ if(!IsOpVecNoOp(tmpOps))
+ {
+ ConstColorSpaceRcPtr targetColorSpace = config.getColorSpace(ROLE_SCENE_LINEAR);
+
+ if(!skipColorSpaceConversions)
+ {
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ targetColorSpace);
+ currentColorSpace = targetColorSpace;
+ }
+
+ std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops));
+ }
+ }
+
+
+ // Apply a color correction, in ROLE_COLOR_TIMING
+ ConstTransformRcPtr colorTimingCC = displayTransform.getColorTimingCC();
+ if(colorTimingCC)
+ {
+ // Put the new ops into a temp array, to see if it's a no-op
+ // If it is a no-op, dont bother doing the colorspace conversion.
+ OpRcPtrVec tmpOps;
+ BuildOps(tmpOps, config, context, colorTimingCC, TRANSFORM_DIR_FORWARD);
+
+ if(!IsOpVecNoOp(tmpOps))
+ {
+ ConstColorSpaceRcPtr targetColorSpace = config.getColorSpace(ROLE_COLOR_TIMING);
+
+ if(!skipColorSpaceConversions)
+ {
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ targetColorSpace);
+ currentColorSpace = targetColorSpace;
+ }
+
+ std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops));
+ }
+ }
+
+ // Apply a look, if specified
+ LookParseResult looks;
+ if(displayTransform.getLooksOverrideEnabled())
+ {
+ looks.parse(displayTransform.getLooksOverride());
+ }
+ else if(!skipColorSpaceConversions)
+ {
+ looks.parse(config.getDisplayLooks(display.c_str(), view.c_str()));
+ }
+
+ if(!looks.empty())
+ {
+ BuildLookOps(ops,
+ currentColorSpace,
+ skipColorSpaceConversions,
+ config,
+ context,
+ looks);
+ }
+
+ // Apply a channel view
+ ConstTransformRcPtr channelView = displayTransform.getChannelView();
+ if(channelView)
+ {
+ BuildOps(ops, config, context, channelView, TRANSFORM_DIR_FORWARD);
+ }
+
+
+ // Apply the conversion to the display color space
+ if(!skipColorSpaceConversions)
+ {
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ displayColorspace);
+ currentColorSpace = displayColorspace;
+ }
+
+
+ // Apply a display cc
+ ConstTransformRcPtr displayCC = displayTransform.getDisplayCC();
+ if(displayCC)
+ {
+ BuildOps(ops, config, context, displayCC, TRANSFORM_DIR_FORWARD);
+ }
+
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Exception.cpp b/src/core/Exception.cpp
new file mode 100644
index 0000000..b3d514c
--- /dev/null
+++ b/src/core/Exception.cpp
@@ -0,0 +1,74 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+
+ Exception::Exception(const char * msg) throw()
+ : std::exception(),
+ msg_(msg)
+ {}
+
+ Exception::Exception(const Exception& e) throw()
+ : std::exception(),
+ msg_(e.msg_)
+ {}
+
+ //*** operator=
+ Exception& Exception::operator=(const Exception& e) throw()
+ {
+ msg_ = e.msg_;
+ return *this;
+ }
+
+ //*** ~Exception
+ Exception::~Exception() throw()
+ {
+ }
+
+ //*** what
+ const char* Exception::what() const throw()
+ {
+ return msg_.c_str();
+ }
+
+
+
+
+ ExceptionMissingFile::ExceptionMissingFile(const char * msg) throw()
+ : Exception(msg)
+ {}
+
+ ExceptionMissingFile::ExceptionMissingFile(const ExceptionMissingFile& e) throw()
+ : Exception(e)
+ {}
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ExponentOps.cpp b/src/core/ExponentOps.cpp
new file mode 100644
index 0000000..56e34d4
--- /dev/null
+++ b/src/core/ExponentOps.cpp
@@ -0,0 +1,372 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cmath>
+#include <cstring>
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "ExponentOps.h"
+#include "GpuShaderUtils.h"
+#include "MathUtils.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ void ApplyClampExponent(float* rgbaBuffer, long numPixels,
+ const float* exp4)
+ {
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ rgbaBuffer[0] = powf( std::max(0.0f, rgbaBuffer[0]), exp4[0]);
+ rgbaBuffer[1] = powf( std::max(0.0f, rgbaBuffer[1]), exp4[1]);
+ rgbaBuffer[2] = powf( std::max(0.0f, rgbaBuffer[2]), exp4[2]);
+ rgbaBuffer[3] = powf( std::max(0.0f, rgbaBuffer[3]), exp4[3]);
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ const int FLOAT_DECIMALS = 7;
+ }
+
+
+ namespace
+ {
+ class ExponentOp : public Op
+ {
+ public:
+ ExponentOp(const float * exp4,
+ TransformDirection direction);
+ virtual ~ExponentOp();
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const;
+ virtual std::string getCacheID() const;
+
+ virtual bool isNoOp() const;
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+
+ virtual bool canCombineWith(const OpRcPtr & op) const;
+ virtual void combineWith(OpRcPtrVec & ops, const OpRcPtr & secondOp) const;
+
+ virtual bool hasChannelCrosstalk() const;
+ virtual void finalize();
+ virtual void apply(float* rgbaBuffer, long numPixels) const;
+
+ virtual bool supportsGpuShader() const;
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const;
+ private:
+ float m_exp4[4];
+
+ // Set in finalize
+ std::string m_cacheID;
+ };
+
+ typedef OCIO_SHARED_PTR<ExponentOp> ExponentOpRcPtr;
+
+
+ ExponentOp::ExponentOp(const float * exp4,
+ TransformDirection direction):
+ Op()
+ {
+ if(direction == TRANSFORM_DIR_UNKNOWN)
+ {
+ throw Exception("Cannot create ExponentOp with unspecified transform direction.");
+ }
+
+ if(direction == TRANSFORM_DIR_INVERSE)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ if(!IsScalarEqualToZero(exp4[i]))
+ {
+ m_exp4[i] = 1.0f / exp4[i];
+ }
+ else
+ {
+ throw Exception("Cannot apply ExponentOp op, Cannot apply 0.0 exponent in the inverse.");
+ }
+ }
+ }
+ else
+ {
+ memcpy(m_exp4, exp4, 4*sizeof(float));
+ }
+ }
+
+ OpRcPtr ExponentOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new ExponentOp(m_exp4, TRANSFORM_DIR_FORWARD));
+ return op;
+ }
+
+ ExponentOp::~ExponentOp()
+ { }
+
+ std::string ExponentOp::getInfo() const
+ {
+ return "<ExponentOp>";
+ }
+
+ std::string ExponentOp::getCacheID() const
+ {
+ return m_cacheID;
+ }
+
+ bool ExponentOp::isNoOp() const
+ {
+ return IsVecEqualToOne(m_exp4, 4);
+ }
+
+ bool ExponentOp::isSameType(const OpRcPtr & op) const
+ {
+ ExponentOpRcPtr typedRcPtr = DynamicPtrCast<ExponentOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool ExponentOp::isInverse(const OpRcPtr & op) const
+ {
+ ExponentOpRcPtr typedRcPtr = DynamicPtrCast<ExponentOp>(op);
+ if(!typedRcPtr) return false;
+
+ float combined[4] = { m_exp4[0]*typedRcPtr->m_exp4[0],
+ m_exp4[1]*typedRcPtr->m_exp4[1],
+ m_exp4[2]*typedRcPtr->m_exp4[2],
+ m_exp4[3]*typedRcPtr->m_exp4[3] };
+
+ return IsVecEqualToOne(combined, 4);
+ }
+
+ bool ExponentOp::canCombineWith(const OpRcPtr & op) const
+ {
+ return isSameType(op);
+ }
+
+
+ void ExponentOp::combineWith(OpRcPtrVec & ops, const OpRcPtr & secondOp) const
+ {
+ ExponentOpRcPtr typedRcPtr = DynamicPtrCast<ExponentOp>(secondOp);
+ if(!typedRcPtr)
+ {
+ std::ostringstream os;
+ os << "ExponentOp can only be combined with other ";
+ os << "ExponentOps. secondOp:" << secondOp->getInfo();
+ throw Exception(os.str().c_str());
+ }
+
+ float combined[4] = { m_exp4[0]*typedRcPtr->m_exp4[0],
+ m_exp4[1]*typedRcPtr->m_exp4[1],
+ m_exp4[2]*typedRcPtr->m_exp4[2],
+ m_exp4[3]*typedRcPtr->m_exp4[3] };
+
+ CreateExponentOp(ops, combined, TRANSFORM_DIR_FORWARD);
+ }
+
+ bool ExponentOp::hasChannelCrosstalk() const
+ {
+ return false;
+ }
+
+ void ExponentOp::finalize()
+ {
+ // Create the cacheID
+ std::ostringstream cacheIDStream;
+ cacheIDStream << "<ExponentOp ";
+ cacheIDStream.precision(FLOAT_DECIMALS);
+ for(int i=0; i<4; ++i)
+ {
+ cacheIDStream << m_exp4[i] << " ";
+ }
+ cacheIDStream << ">";
+ m_cacheID = cacheIDStream.str();
+ }
+
+ void ExponentOp::apply(float* rgbaBuffer, long numPixels) const
+ {
+ if(!rgbaBuffer) return;
+
+ ApplyClampExponent(rgbaBuffer, numPixels, m_exp4);
+ }
+
+ bool ExponentOp::supportsGpuShader() const
+ {
+ return true;
+ }
+
+ void ExponentOp::writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const
+ {
+ GpuLanguage lang = shaderDesc.getLanguage();
+ float zerovec[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ shader << pixelName << " = pow(";
+ shader << "max(" << pixelName << ", " << GpuTextHalf4(zerovec, lang) << ")";
+ shader << ", " << GpuTextHalf4(m_exp4, lang) << ");\n";
+ }
+
+ } // Anon namespace
+
+
+
+ void CreateExponentOp(OpRcPtrVec & ops,
+ const float * exp4,
+ TransformDirection direction)
+ {
+ bool expIsIdentity = IsVecEqualToOne(exp4, 4);
+ if(expIsIdentity) return;
+
+ ops.push_back( ExponentOpRcPtr(new ExponentOp(exp4, direction)) );
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+#include "UnitTest.h"
+
+OCIO_NAMESPACE_USING
+
+OIIO_ADD_TEST(ExponentOps, Value)
+{
+ float exp1[4] = { 1.2f, 1.3f, 1.4f, 1.5f };
+
+ OpRcPtrVec ops;
+ CreateExponentOp(ops, exp1, TRANSFORM_DIR_FORWARD);
+ CreateExponentOp(ops, exp1, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+
+ for(unsigned int i=0; i<ops.size(); ++i)
+ {
+ ops[i]->finalize();
+ }
+
+ float error = 1e-6f;
+
+ const float source[] = { 0.5f, 0.5f, 0.5f, 0.5f, };
+
+ const float result1[] = { 0.43527528164806206f, 0.40612619817811774f,
+ 0.37892914162759955f, 0.35355339059327379f };
+
+ float tmp[4];
+ memcpy(tmp, source, 4*sizeof(float));
+ ops[0]->apply(tmp, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp[i], result1[i], error);
+ }
+
+ ops[1]->apply(tmp, 1);
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp[i], source[i], error);
+ }
+}
+
+OIIO_ADD_TEST(ExponentOps, Inverse)
+{
+ float exp1[4] = { 2.0f, 1.02345f, 5.651321f, 0.12345678910f };
+ float exp2[4] = { 2.0f, 2.0f, 2.0f, 2.0f };
+
+ OpRcPtrVec ops;
+
+ CreateExponentOp(ops, exp1, TRANSFORM_DIR_FORWARD);
+ CreateExponentOp(ops, exp1, TRANSFORM_DIR_INVERSE);
+ CreateExponentOp(ops, exp2, TRANSFORM_DIR_FORWARD);
+ CreateExponentOp(ops, exp2, TRANSFORM_DIR_INVERSE);
+
+ OIIO_CHECK_EQUAL(ops.size(), 4);
+
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[1]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[2]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[3]->clone()));
+
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[0]), false);
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[1]), true);
+ OIIO_CHECK_EQUAL(ops[1]->isInverse(ops[0]), true);
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[3]), false);
+ OIIO_CHECK_EQUAL(ops[3]->isInverse(ops[0]), false);
+ OIIO_CHECK_EQUAL(ops[2]->isInverse(ops[3]), true);
+ OIIO_CHECK_EQUAL(ops[3]->isInverse(ops[2]), true);
+ OIIO_CHECK_EQUAL(ops[3]->isInverse(ops[3]), false);
+}
+
+OIIO_ADD_TEST(ExponentOps, Combining)
+{
+ float exp1[4] = { 2.0f, 2.0f, 2.0f, 1.0f };
+ float exp2[4] = { 1.2f, 1.2f, 1.2f, 1.0f };
+
+ OpRcPtrVec ops;
+ CreateExponentOp(ops, exp1, TRANSFORM_DIR_FORWARD);
+ CreateExponentOp(ops, exp2, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+
+ float error = 1e-6f;
+ const float source[] = { 0.5f, 0.5f, 0.5f, 0.5f, };
+ const float result[] = { 0.18946457081379978f, 0.18946457081379978f,
+ 0.18946457081379978f, 0.5f };
+
+ float tmp[4];
+ memcpy(tmp, source, 4*sizeof(float));
+ ops[0]->apply(tmp, 1);
+ ops[1]->apply(tmp, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp[i], result[i], error);
+ }
+
+
+ OpRcPtrVec combined;
+ ops[0]->combineWith(combined, ops[1]);
+ OIIO_CHECK_EQUAL(combined.size(), 1);
+
+ float tmp2[4];
+ memcpy(tmp2, source, 4*sizeof(float));
+ combined[0]->apply(tmp2, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp2[i], result[i], error);
+ }
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/ExponentOps.h b/src/core/ExponentOps.h
new file mode 100644
index 0000000..95dd1f6
--- /dev/null
+++ b/src/core/ExponentOps.h
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_EXPONENTOP_H
+#define INCLUDED_OCIO_EXPONENTOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // If the exponent is 1.0, this will return without clamping
+ // Otherwise, will be clamped between [0.0, inf]
+
+ void CreateExponentOp(OpRcPtrVec & ops,
+ const float * exponent4,
+ TransformDirection direction);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/ExponentTransform.cpp b/src/core/ExponentTransform.cpp
new file mode 100644
index 0000000..7bc180f
--- /dev/null
+++ b/src/core/ExponentTransform.cpp
@@ -0,0 +1,151 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "ExponentOps.h"
+#include "OpBuilders.h"
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ExponentTransformRcPtr ExponentTransform::Create()
+ {
+ return ExponentTransformRcPtr(new ExponentTransform(), &deleter);
+ }
+
+ void ExponentTransform::deleter(ExponentTransform* t)
+ {
+ delete t;
+ }
+
+
+ class ExponentTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ float value_[4];
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ value_[i] = 1.0f;
+ }
+ }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ memcpy(value_, rhs.value_, 4*sizeof(float));
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ ExponentTransform::ExponentTransform()
+ : m_impl(new ExponentTransform::Impl)
+ {
+ }
+
+ TransformRcPtr ExponentTransform::createEditableCopy() const
+ {
+ ExponentTransformRcPtr transform = ExponentTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ ExponentTransform::~ExponentTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ ExponentTransform& ExponentTransform::operator= (const ExponentTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection ExponentTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void ExponentTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ void ExponentTransform::setValue(const float * vec4)
+ {
+ if(vec4) memcpy(getImpl()->value_, vec4, 4*sizeof(float));
+ }
+
+ void ExponentTransform::getValue(float * vec4) const
+ {
+ if(vec4) memcpy(vec4, getImpl()->value_, 4*sizeof(float));
+ }
+
+ std::ostream& operator<< (std::ostream& os, const ExponentTransform& t)
+ {
+ os << "<ExponentTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ void BuildExponentOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ExponentTransform & transform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ transform.getDirection());
+
+ float vec4[4];
+ transform.getValue(vec4);
+
+ CreateExponentOp(ops,
+ vec4,
+ combinedDir);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/FileFormat3DL.cpp b/src/core/FileFormat3DL.cpp
new file mode 100644
index 0000000..9d7e131
--- /dev/null
+++ b/src/core/FileFormat3DL.cpp
@@ -0,0 +1,638 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "MathUtils.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <sstream>
+
+/*
+// Discreet's Flame Lut Format
+// Use a loose interpretation of the format to allow other 3d luts that look
+// similar, but dont strictly adhere to the real definition.
+
+// If line starts with text or # skip it
+// If line is a bunch of ints (more than 3) , it's the 1d shaper lut
+
+// All remaining lines of size 3 int are data
+// cube size is determined from num entries
+// The bit depth of the shaper lut and the 3d lut need not be the same.
+
+Example 1, FLAME
+# Comment here
+0 64 128 192 256 320 384 448 512 576 640 704 768 832 896 960 1023
+
+0 0 0
+0 0 100
+0 0 200
+
+
+Example 2, LUSTRE
+#Tokens required by applications - do not edit
+3DMESH
+Mesh 4 12
+0 64 128 192 256 320 384 448 512 576 640 704 768 832 896 960 1023
+
+
+
+0 17 17
+0 0 88
+0 0 157
+9 101 197
+0 118 308
+...
+
+4092 4094 4094
+
+#Tokens required by applications - do not edit
+
+LUT8
+gamma 1.0
+
+In this example, the 3D LUT has an input bit depth of 4 bits and an output
+bit depth of 12 bits. You use the input value to calculate the RGB triplet
+to be 17*17*17 (where 17=(2 to the power of 4)+1, and 4 is the input bit
+depth). The first triplet is the output value at (0,0,0);(0,0,1);...;
+(0,0,16) r,g,b coordinates; the second triplet is the output value at
+(0,1,0);(0,1,1);...;(0,1,16) r,g,b coordinates; and so on. You use the output
+bit depth to set the output bit depth range (12 bits or 0-4095).
+NoteLustre supports an input and output depth of 16 bits for 3D LUTs; however,
+in the processing pipeline, the BLACK_LEVEL to WHITE_LEVEL range is only 14
+bits. This means that even if the 3D LUT is 16 bits, it is normalized to
+fit the BLACK_LEVEL to WHITE_LEVEL range of Lustre.
+In Lustre, 3D LUT files can contain grids of 17 cubed, 33 cubed, and 65 cubed;
+however, Lustre converts 17 cubed and 65 cubed grids to 33 cubed for internal
+processing on the output (for rendering and calibration), but not on the input
+3D LUT.
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile () :
+ has1D(false),
+ has3D(false)
+ {
+ lut1D = Lut1D::Create();
+ lut3D = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ bool has1D;
+ bool has3D;
+ Lut1DRcPtr lut1D;
+ Lut3DRcPtr lut3D;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+
+
+
+
+
+ // We use the maximum value found in the lut to infer
+ // the bit depth. While this is fugly. We dont believe
+ // there is a better way, looking at the file, to
+ // determine this.
+ //
+ // Note: We allow for 2x overshoot in the luts.
+ // As we dont allow for odd bit depths, this isnt a big deal.
+ // So sizes from 1/2 max - 2x max are valid
+ //
+ // FILE EXPECTED MAX CORRECTLY DECODED IF MAX IN THIS RANGE
+ // 8-bit 255 [0, 511]
+ // 10-bit 1023 [512, 2047]
+ // 12-bit 4095 [2048, 8191]
+ // 14-bit 16383 [8192, 32767]
+ // 16-bit 65535 [32768, 131071+]
+
+ int GetLikelyLutBitDepth(int testval)
+ {
+ const int MIN_BIT_DEPTH = 8;
+ const int MAX_BIT_DEPTH = 16;
+
+ if(testval < 0) return -1;
+
+ // Only test even bit depths
+ for(int bitDepth = MIN_BIT_DEPTH;
+ bitDepth <= MAX_BIT_DEPTH; bitDepth+=2)
+ {
+ int maxcode = static_cast<int>(pow(2.0,bitDepth));
+ int adjustedMax = maxcode * 2 - 1;
+ if(testval<=adjustedMax) return bitDepth;
+ }
+
+ return MAX_BIT_DEPTH;
+ }
+
+ int GetMaxValueFromIntegerBitDepth(int bitDepth)
+ {
+ return static_cast<int>( pow(2.0, bitDepth) ) - 1;
+ }
+
+ int GetClampedIntFromNormFloat(float val, float scale)
+ {
+ val = std::min(std::max(0.0f, val), 1.0f) * scale;
+ return static_cast<int>(roundf(val));
+ }
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "flame";
+ info.extension = "3dl";
+ info.capabilities = (FORMAT_CAPABILITY_READ | FORMAT_CAPABILITY_WRITE);
+ formatInfoVec.push_back(info);
+
+ FormatInfo info2 = info;
+ info2.name = "lustre";
+ formatInfoVec.push_back(info2);
+ }
+
+ // Try and load the format
+ // Raise an exception if it can't be loaded.
+
+ CachedFileRcPtr LocalFileFormat::Read(std::istream & istream) const
+ {
+ std::vector<int> rawshaper;
+ std::vector<int> raw3d;
+
+ // Parse the file 3d lut data to an int array
+ {
+ const int MAX_LINE_SIZE = 4096;
+ char lineBuffer[MAX_LINE_SIZE];
+
+ std::vector<std::string> lineParts;
+ std::vector<int> tmpData;
+
+ while(istream.good())
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+
+ // Strip and split the line
+ pystring::split(pystring::strip(lineBuffer), lineParts);
+
+ if(lineParts.empty()) continue;
+ if((lineParts.size() > 0) && pystring::startswith(lineParts[0],"#")) continue;
+
+ // If we havent found a list of ints, continue
+ if(!StringVecToIntVec(tmpData, lineParts)) continue;
+
+ // If we've found more than 3 ints, and dont have
+ // a shaper lut yet, we've got it!
+ if(tmpData.size()>3 && rawshaper.empty())
+ {
+ for(unsigned int i=0; i<tmpData.size(); ++i)
+ {
+ rawshaper.push_back(tmpData[i]);
+ }
+ }
+
+ // If we've found 3 ints, add it to our 3dlut.
+ if(tmpData.size() == 3)
+ {
+ raw3d.push_back(tmpData[0]);
+ raw3d.push_back(tmpData[1]);
+ raw3d.push_back(tmpData[2]);
+ }
+ }
+ }
+
+ if(raw3d.empty() && rawshaper.empty())
+ {
+ std::ostringstream os;
+ os << "Error parsing .3dl file.";
+ os << "Does not appear to contain a valid shaper lut or a 3D lut.";
+ throw Exception(os.str().c_str());
+ }
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ // If all we're doing to parse the format is to read in sets of 3 numbers,
+ // it's possible that other formats will accidentally be able to be read
+ // mistakenly as .3dl files. We can exclude a huge segement of these mis-reads
+ // by screening for files that use float represenations. I.e., if the MAX
+ // value of the lut is a small number (such as <128.0) it's likely not an integer
+ // format, and thus not a likely 3DL file.
+
+ const int FORMAT3DL_CODEVALUE_LOWEST_PLAUSIBLE_MAXINT = 128;
+
+ // Interpret the shaper lut
+ if(!rawshaper.empty())
+ {
+ cachedFile->has1D = true;
+
+ // Find the maximum shaper lut value to infer bit-depth
+ int shapermax = 0;
+ for(unsigned int i=0; i<rawshaper.size(); ++i)
+ {
+ shapermax = std::max(shapermax, rawshaper[i]);
+ }
+
+ if(shapermax<FORMAT3DL_CODEVALUE_LOWEST_PLAUSIBLE_MAXINT)
+ {
+ std::ostringstream os;
+ os << "Error parsing .3dl file.";
+ os << "The maximum shaper lut value, " << shapermax;
+ os << ", is unreasonably low. This lut is probably not a .3dl ";
+ os << "file, but instead a related format that shares a similar ";
+ os << "structure.";
+
+ throw Exception(os.str().c_str());
+ }
+
+ int shaperbitdepth = GetLikelyLutBitDepth(shapermax);
+ if(shaperbitdepth<0)
+ {
+ std::ostringstream os;
+ os << "Error parsing .3dl file.";
+ os << "The maximum shaper lut value, " << shapermax;
+ os << ", does not correspond to any likely bit depth. ";
+ os << "Please confirm source file is valid.";
+ throw Exception(os.str().c_str());
+ }
+
+ int bitdepthmax = GetMaxValueFromIntegerBitDepth(shaperbitdepth);
+ float scale = 1.0f / static_cast<float>(bitdepthmax);
+
+ for(int channel=0; channel<3; ++channel)
+ {
+ cachedFile->lut1D->luts[channel].resize(rawshaper.size());
+
+ for(unsigned int i=0; i<rawshaper.size(); ++i)
+ {
+ cachedFile->lut1D->luts[channel][i] = static_cast<float>(rawshaper[i])*scale;
+ }
+ }
+
+ // The error threshold will be 2 code values. This will allow
+ // shaper luts which use different int conversions (round vs. floor)
+ // to both be optimized.
+ // Required: Abs Tolerance
+
+ const int FORMAT3DL_SHAPER_CODEVALUE_TOLERANCE = 2;
+ cachedFile->lut1D->maxerror = FORMAT3DL_SHAPER_CODEVALUE_TOLERANCE*scale;
+ cachedFile->lut1D->errortype = ERROR_ABSOLUTE;
+ }
+
+
+
+ // Interpret the parsed data.
+ if(!raw3d.empty())
+ {
+ cachedFile->has3D = true;
+
+ // Find the maximum shaper lut value to infer bit-depth
+ int lut3dmax = 0;
+ for(unsigned int i=0; i<raw3d.size(); ++i)
+ {
+ lut3dmax = std::max(lut3dmax, raw3d[i]);
+ }
+
+ if(lut3dmax<FORMAT3DL_CODEVALUE_LOWEST_PLAUSIBLE_MAXINT)
+ {
+ std::ostringstream os;
+ os << "Error parsing .3dl file.";
+ os << "The maximum 3d lut value, " << lut3dmax;
+ os << ", is unreasonably low. This lut is probably not a .3dl ";
+ os << "file, but instead a related format that shares a similar ";
+ os << "structure.";
+
+ throw Exception(os.str().c_str());
+ }
+
+ int lut3dbitdepth = GetLikelyLutBitDepth(lut3dmax);
+ if(lut3dbitdepth<0)
+ {
+ std::ostringstream os;
+ os << "Error parsing .3dl file.";
+ os << "The maximum 3d lut value, " << lut3dmax;
+ os << ", does not correspond to any likely bit depth. ";
+ os << "Please confirm source file is valid.";
+ throw Exception(os.str().c_str());
+ }
+
+ int bitdepthmax = GetMaxValueFromIntegerBitDepth(lut3dbitdepth);
+ float scale = 1.0f / static_cast<float>(bitdepthmax);
+
+ // Interpret the int array as a 3dlut
+ int lutEdgeLen = Get3DLutEdgeLenFromNumPixels((int)raw3d.size()/3);
+
+ // Reformat 3D data
+ cachedFile->lut3D->size[0] = lutEdgeLen;
+ cachedFile->lut3D->size[1] = lutEdgeLen;
+ cachedFile->lut3D->size[2] = lutEdgeLen;
+ cachedFile->lut3D->lut.reserve(lutEdgeLen * lutEdgeLen * lutEdgeLen * 3);
+
+ for(int rIndex=0; rIndex<lutEdgeLen; ++rIndex)
+ {
+ for(int gIndex=0; gIndex<lutEdgeLen; ++gIndex)
+ {
+ for(int bIndex=0; bIndex<lutEdgeLen; ++bIndex)
+ {
+ int i = GetLut3DIndex_B(rIndex, gIndex, bIndex,
+ lutEdgeLen, lutEdgeLen, lutEdgeLen);
+
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+0]) * scale);
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+1]) * scale);
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+2]) * scale);
+ }
+ }
+ }
+ }
+
+ return cachedFile;
+ }
+
+ // 65 -> 6
+ // 33 -> 5
+ // 17 -> 4
+
+ int CubeDimensionLenToLustreBitDepth(int size)
+ {
+ float logval = logf(static_cast<float>(size-1)) / logf(2.0);
+ return static_cast<int>(logval);
+ }
+
+ void LocalFileFormat::Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const
+ {
+ int DEFAULT_CUBE_SIZE = 0;
+ int SHAPER_BIT_DEPTH = 10;
+ int CUBE_BIT_DEPTH = 12;
+
+ if(formatName == "lustre")
+ {
+ DEFAULT_CUBE_SIZE = 33;
+ }
+ else if(formatName == "flame")
+ {
+ DEFAULT_CUBE_SIZE = 17;
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Unknown 3dl format name, '";
+ os << formatName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ ConstConfigRcPtr config = baker.getConfig();
+
+ int cubeSize = baker.getCubeSize();
+ if(cubeSize==-1) cubeSize = DEFAULT_CUBE_SIZE;
+ cubeSize = std::max(2, cubeSize); // smallest cube is 2x2x2
+
+ int shaperSize = baker.getShaperSize();
+ if(shaperSize==-1) shaperSize = cubeSize;
+
+ std::vector<float> cubeData;
+ cubeData.resize(cubeSize*cubeSize*cubeSize*3);
+ GenerateIdentityLut3D(&cubeData[0], cubeSize, 3, LUT3DORDER_FAST_BLUE);
+ PackedImageDesc cubeImg(&cubeData[0], cubeSize*cubeSize*cubeSize, 1, 3);
+
+ // Apply our conversion from the input space to the output space.
+ ConstProcessorRcPtr inputToTarget;
+ std::string looks = baker.getLooks();
+ if (!looks.empty())
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(baker.getInputSpace());
+ transform->setDst(baker.getTargetSpace());
+ inputToTarget = config->getProcessor(transform,
+ TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ inputToTarget = config->getProcessor(baker.getInputSpace(),
+ baker.getTargetSpace());
+ }
+ inputToTarget->apply(cubeImg);
+
+ // Write out the file.
+ // For for maximum compatibility with other apps, we will
+ // not utilize the shaper or output any metadata
+
+ if(formatName == "lustre")
+ {
+ int meshInputBitDepth = CubeDimensionLenToLustreBitDepth(cubeSize);
+ ostream << "3DMESH\n";
+ ostream << "Mesh " << meshInputBitDepth << " " << CUBE_BIT_DEPTH << "\n";
+ }
+
+ std::vector<float> shaperData(shaperSize);
+ GenerateIdentityLut1D(&shaperData[0], shaperSize, 1);
+
+ float shaperScale = static_cast<float>(
+ GetMaxValueFromIntegerBitDepth(SHAPER_BIT_DEPTH));
+
+ for(unsigned int i=0; i<shaperData.size(); ++i)
+ {
+ if(i != 0) ostream << " ";
+ int val = GetClampedIntFromNormFloat(shaperData[i], shaperScale);
+ ostream << val;
+ }
+ ostream << "\n";
+
+ // Write out the 3D Cube
+ float cubeScale = static_cast<float>(
+ GetMaxValueFromIntegerBitDepth(CUBE_BIT_DEPTH));
+ if(cubeSize < 2)
+ {
+ throw Exception("Internal cube size exception.");
+ }
+ for(int i=0; i<cubeSize*cubeSize*cubeSize; ++i)
+ {
+ int r = GetClampedIntFromNormFloat(cubeData[3*i+0], cubeScale);
+ int g = GetClampedIntFromNormFloat(cubeData[3*i+1], cubeScale);
+ int b = GetClampedIntFromNormFloat(cubeData[3*i+2], cubeScale);
+ ostream << r << " " << g << " " << b << "\n";
+ }
+ ostream << "\n";
+
+ if(formatName == "lustre")
+ {
+ ostream << "LUT8\n";
+ ostream << "gamma 1.0\n";
+ }
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build .3dl Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ // TODO: INTERP_LINEAR should not be hard-coded.
+ // Instead query 'highest' interpolation?
+ // (right now, it's linear). If cubic is added, consider
+ // using it
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ if(cachedFile->has1D)
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ INTERP_LINEAR, newDir);
+ }
+ if(cachedFile->has3D)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ if(cachedFile->has3D)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ if(cachedFile->has1D)
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ INTERP_LINEAR, newDir);
+ }
+ }
+ }
+ }
+
+ FileFormat * CreateFileFormat3DL()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+// FILE EXPECTED MAX CORRECTLY DECODED IF MAX IN THIS RANGE
+// 8-bit 255 [0, 511]
+// 10-bit 1023 [512, 2047]
+// 12-bit 4095 [2048, 8191]
+// 14-bit 16383 [8192, 32767]
+// 16-bit 65535 [32768, 131071]
+
+OIIO_ADD_TEST(FileFormat3DL, GetLikelyLutBitDepth)
+{
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(-1), -1);
+
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(0), 8);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(1), 8);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(255), 8);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(256), 8);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(511), 8);
+
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(512), 10);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(1023), 10);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(1024), 10);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(2047), 10);
+
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(2048), 12);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(4095), 12);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(4096), 12);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(8191), 12);
+
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(16383), 14);
+
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(65535), 16);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(65536), 16);
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(131071), 16);
+
+ OIIO_CHECK_EQUAL(OCIO::GetLikelyLutBitDepth(131072), 16);
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/FileFormatCC.cpp b/src/core/FileFormatCC.cpp
new file mode 100644
index 0000000..ade09a6
--- /dev/null
+++ b/src/core/FileFormatCC.cpp
@@ -0,0 +1,151 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "OpBuilders.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile ()
+ {
+ transform = CDLTransform::Create();
+ };
+
+ ~LocalCachedFile() {};
+
+ CDLTransformRcPtr transform;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "ColorCorrection";
+ info.extension = "cc";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ // Try and load the format
+ // Raise an exception if it can't be loaded.
+
+ CachedFileRcPtr LocalFileFormat::Read(std::istream & istream) const
+ {
+ std::ostringstream rawdata;
+ rawdata << istream.rdbuf();
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ try
+ {
+ cachedFile->transform->setXML(rawdata.str().c_str());
+ }
+ catch(Exception & e)
+ {
+ std::ostringstream os;
+ os << "Error parsing .cc file. ";
+ os << "Does not appear to contain a valid ASC CDL XML:";
+ os << e.what();
+ throw Exception(os.str().c_str());
+ }
+
+ return cachedFile;
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build .cc Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ BuildCDLOps(ops,
+ config,
+ *cachedFile->transform,
+ newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatCC()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
diff --git a/src/core/FileFormatCCC.cpp b/src/core/FileFormatCCC.cpp
new file mode 100644
index 0000000..ec43803
--- /dev/null
+++ b/src/core/FileFormatCCC.cpp
@@ -0,0 +1,195 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <map>
+#include <tinyxml.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "CDLTransform.h"
+#include "FileTransform.h"
+#include "OpBuilders.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ typedef std::map<std::string,CDLTransformRcPtr> CDLMap;
+
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile () {};
+
+ ~LocalCachedFile() {};
+
+ CDLMap transforms;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+ typedef OCIO_SHARED_PTR<TiXmlDocument> TiXmlDocumentRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "ColorCorrectionCollection";
+ info.extension = "ccc";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ // Try and load the format
+ // Raise an exception if it can't be loaded.
+
+ CachedFileRcPtr LocalFileFormat::Read(std::istream & istream) const
+ {
+ std::ostringstream rawdata;
+ rawdata << istream.rdbuf();
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ TiXmlDocumentRcPtr doc = TiXmlDocumentRcPtr(new TiXmlDocument());
+ doc->Parse(rawdata.str().c_str());
+
+ if(doc->Error())
+ {
+ std::ostringstream os;
+ os << "XML Parse Error. ";
+ os << doc->ErrorDesc() << " (line ";
+ os << doc->ErrorRow() << ", character ";
+ os << doc->ErrorCol() << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ TiXmlElement* rootElement = doc->RootElement();
+ if(!rootElement)
+ {
+ std::ostringstream os;
+ os << "Error loading xml. Null root element.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(std::string(rootElement->Value()) != "ColorCorrectionCollection")
+ {
+ std::ostringstream os;
+ os << "Error loading ccc xml. ";
+ os << "Root element is type '" << rootElement->Value() << "', ";
+ os << "ColorCorrectionCollection expected.";
+ throw Exception(os.str().c_str());
+ }
+
+ GetCDLTransforms(cachedFile->transforms, rootElement);
+
+ if(cachedFile->transforms.empty())
+ {
+ std::ostringstream os;
+ os << "Error loading ccc xml. ";
+ os << "No ColorCorrection elements found.";
+ throw Exception(os.str().c_str());
+ }
+
+ return cachedFile;
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build .ccc Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build ASC FileTransform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string cccid = fileTransform.getCCCId();
+ cccid = context->resolveStringVar(cccid.c_str());
+
+ CDLMap::const_iterator iter = cachedFile->transforms.find(cccid);
+ if(iter == cachedFile->transforms.end())
+ {
+ std::ostringstream os;
+ os << "Cannot build ASC FileTransform, specified cccid '";
+ os << cccid << "' not found in " << fileTransform.getSrc();
+ throw Exception(os.str().c_str());
+ }
+
+ BuildCDLOps(ops,
+ config,
+ *(iter->second),
+ newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatCCC()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
diff --git a/src/core/FileFormatCSP.cpp b/src/core/FileFormatCSP.cpp
new file mode 100644
index 0000000..eae4d9d
--- /dev/null
+++ b/src/core/FileFormatCSP.cpp
@@ -0,0 +1,1112 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cassert>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "MathUtils.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const int NUM_PRELUT_SAMPLES = 65536; // 2**16 samples
+ // Always use linear interpolation for preluts to get the
+ // best precision
+ const Interpolation PRELUT_INTERPOLATION = INTERP_LINEAR;
+
+ typedef struct rsr_Interpolator1D_Raw_
+ {
+ float * stims;
+ float * values;
+ unsigned int length;
+ } rsr_Interpolator1D_Raw;
+
+ rsr_Interpolator1D_Raw * rsr_Interpolator1D_Raw_create( unsigned int prelutLength );
+ void rsr_Interpolator1D_Raw_destroy( rsr_Interpolator1D_Raw * prelut );
+
+
+ /* An opaque handle to the cineSpace 1D Interpolator object */
+ typedef struct rsr_Interpolator1D_ rsr_Interpolator1D;
+
+ rsr_Interpolator1D * rsr_Interpolator1D_createFromRaw( rsr_Interpolator1D_Raw * data );
+ void rsr_Interpolator1D_destroy( rsr_Interpolator1D * rawdata );
+ float rsr_Interpolator1D_interpolate( float x, rsr_Interpolator1D * data );
+
+
+ /*
+ * =========== INTERNAL HELPER FUNCTIONS ============
+ */
+ struct rsr_Interpolator1D_
+ {
+ int nSamplePoints;
+ float * stims;
+
+ /* 5 * (nSamplePoints-1) long, holding a sequence of
+ * 1.0/delta, a, b, c, d
+ * such that the curve in interval i is given by
+ * z = (stims[i] - x)* (1.0/delta)
+ * y = a + b*z + c*z^2 + d*z^3
+ */
+ float * parameters;
+
+ float minValue; /* = f( stims[0] ) */
+ float maxValue; /* = f(stims[nSamplePoints-1] ) */
+ };
+
+ static int rsr_internal_I1D_refineSegment( float x, float * data, int low, int high )
+ {
+ int midPoint;
+
+ // TODO: Change assert to an exception?
+ assert( x>= data[low] );
+ assert( x<= data[high] );
+ assert( (high-low) > 0);
+ if( high-low==1 ) return low;
+
+ midPoint = (low+high)/2;
+ if( x<data[midPoint] ) return rsr_internal_I1D_refineSegment(x, data, low, midPoint );
+ return rsr_internal_I1D_refineSegment(x, data, midPoint, high );
+ }
+
+ static int rsr_internal_I1D_findSegmentContaining( float x, float * data, int n )
+ {
+ return rsr_internal_I1D_refineSegment(x, data, 0, n-1);
+ }
+
+ /*
+ * =========== USER FUNCTIONS ============
+ */
+
+
+ void rsr_Interpolator1D_destroy( rsr_Interpolator1D * data )
+ {
+ if(data==NULL) return;
+ free(data->stims);
+ free(data->parameters);
+ free(data);
+ }
+
+
+
+ float rsr_Interpolator1D_interpolate( float x, rsr_Interpolator1D * data )
+ {
+ int segId;
+ float * segdata;
+ float invDelta;
+ float a,b,c,d,z;
+
+ assert(data!=NULL);
+
+ /* Is x in range? */
+ if( isnan(x) ) return x;
+
+ if( x<data->stims[0] ) return data->minValue;
+ if (x>data->stims[ data->nSamplePoints -1] ) return data->maxValue;
+
+ /* Ok so its between the begining and end .. lets find out where... */
+ segId = rsr_internal_I1D_findSegmentContaining( x, data->stims, data->nSamplePoints );
+
+ assert(data->parameters !=NULL );
+
+ segdata = data->parameters + 5 * segId;
+
+ invDelta = segdata[0];
+ a = segdata[1];
+ b = segdata[2];
+ c = segdata[3];
+ d = segdata[4];
+
+ z = ( x - data->stims[segId] ) * invDelta;
+
+ return a + z * ( b + z * ( c + d * z ) ) ;
+
+ }
+
+ rsr_Interpolator1D * rsr_Interpolator1D_createFromRaw( rsr_Interpolator1D_Raw * data )
+ {
+ rsr_Interpolator1D * retval = NULL;
+ /* Check the sanity of the data */
+ assert(data!=NULL);
+ assert(data->length>=2);
+ assert(data->stims!=NULL);
+ assert(data->values!=NULL);
+
+ /* Create the real data. */
+ retval = (rsr_Interpolator1D*)malloc( sizeof(rsr_Interpolator1D) ); // OCIO change: explicit cast
+ if(retval==NULL)
+ {
+ return NULL;
+ }
+
+ retval->stims = (float*)malloc( sizeof(float) * data->length ); // OCIO change: explicit cast
+ if(retval->stims==NULL)
+ {
+ free(retval);
+ return NULL;
+ }
+ memcpy( retval->stims, data->stims, sizeof(float) * data->length );
+
+ retval->parameters = (float*)malloc( 5*sizeof(float) * ( data->length - 1 ) ); // OCIO change: explicit cast
+ if(retval->parameters==NULL)
+ {
+ free(retval->stims);
+ free(retval);
+ return NULL;
+ }
+ retval->nSamplePoints = data->length;
+ retval->minValue = data->values[0];
+ retval->maxValue = data->values[ data->length -1];
+
+ /* Now the fun part .. filling in the coeficients. */
+ if(data->length==2)
+ {
+ retval->parameters[0] = 1.0f/(data->stims[1]-data->stims[0]);
+ retval->parameters[1] = data->values[0];
+ retval->parameters[2] = ( data->values[1] - data->values[0] );
+ retval->parameters[3] = 0;
+ retval->parameters[4] = 0;
+ }
+ else
+ {
+ unsigned int i;
+ float * params = retval->parameters;
+ for(i=0; i< data->length-1; ++i)
+ {
+ float f0 = data->values[i+0];
+ float f1 = data->values[i+1];
+
+ params[0] = 1.0f/(retval->stims[i+1]-retval->stims[i+0]);
+
+ if(i==0)
+ {
+ float delta = data->stims[i+1] - data->stims[i];
+ float delta2 = (data->stims[i+2] - data->stims[i+1])/delta;
+ float f2 = data->values[i+2];
+
+ float dfdx1 = (f2-f0)/(1+delta2);
+ params[1] = 1.0f * f0 + 0.0f * f1 + 0.0f * dfdx1;
+ params[2] = -2.0f * f0 + 2.0f * f1 - 1.0f * dfdx1;
+ params[3] = 1.0f * f0 - 1.0f * f1 + 1.0f * dfdx1;
+ params[4] = 0.0;
+ }
+ else if (i==data->length-2)
+ {
+ float delta = data->stims[i+1] - data->stims[i];
+ float delta1 = (data->stims[i]-data->stims[i-1])/delta;
+ float fn1 = data->values[i-1];
+ float dfdx0 = (f1-fn1)/(1+delta1);
+ params[1] = 1.0f * f0 + 0.0f * f1 + 0.0f * dfdx0;
+ params[2] = 0.0f * f0 + 0.0f * f1 + 1.0f * dfdx0;
+ params[3] = -1.0f * f0 + 1.0f * f1 - 1.0f * dfdx0;
+ params[4] = 0.0;
+ }
+ else
+ {
+ float delta = data->stims[i+1] - data->stims[i];
+ float fn1=data->values[i-1];
+ float delta1 = (data->stims[i] - data->stims[i-1])/delta;
+
+ float f2=data->values[i+2];
+ float delta2 = (data->stims[i+2] - data->stims[i+1])/delta;
+
+ float dfdx0 = (f1-fn1)/(1.0f+delta1);
+ float dfdx1 = (f2-f0)/(1.0f+delta2);
+
+ params[1] = 1.0f * f0 + 0.0f * dfdx0 + 0.0f * f1 + 0.0f * dfdx1;
+ params[2] = 0.0f * f0 + 1.0f * dfdx0 + 0.0f * f1 + 0.0f * dfdx1;
+ params[3] =-3.0f * f0 - 2.0f * dfdx0 + 3.0f * f1 - 1.0f * dfdx1;
+ params[4] = 2.0f * f0 + 1.0f * dfdx0 - 2.0f * f1 + 1.0f * dfdx1;
+ }
+
+ params+=5;
+ }
+ }
+ return retval;
+ }
+
+ rsr_Interpolator1D_Raw * rsr_Interpolator1D_Raw_create( unsigned int prelutLength)
+ {
+ unsigned int i;
+ rsr_Interpolator1D_Raw * prelut = (rsr_Interpolator1D_Raw*)malloc( sizeof(rsr_Interpolator1D_Raw) ); // OCIO change: explicit cast
+ if(prelut==NULL) return NULL;
+
+ prelut->stims = (float*)malloc( sizeof(float) * prelutLength ); // OCIO change: explicit cast
+ if(prelut->stims==NULL)
+ {
+ free(prelut);
+ return NULL;
+ }
+
+ prelut->values = (float*)malloc( sizeof(float) * prelutLength ); // OCIO change: explicit cast
+ if(prelut->values == NULL)
+ {
+ free(prelut->stims);
+ free(prelut);
+ return NULL;
+ }
+
+ prelut->length = prelutLength;
+
+ for( i=0; i<prelutLength; ++i )
+ {
+ prelut->stims[i] = 0.0;
+ prelut->values[i] = 0.0;
+ }
+
+ return prelut;
+ }
+
+ void rsr_Interpolator1D_Raw_destroy( rsr_Interpolator1D_Raw * prelut )
+ {
+ if(prelut==NULL) return;
+ free( prelut->stims );
+ free( prelut->values );
+ free( prelut );
+ }
+
+ } // End unnamed namespace for Interpolators.c
+
+ namespace
+ {
+ class CachedFileCSP : public CachedFile
+ {
+ public:
+ CachedFileCSP () :
+ hasprelut(false),
+ csptype("unknown"),
+ metadata("none")
+ {
+ prelut = Lut1D::Create();
+ lut1D = Lut1D::Create();
+ lut3D = Lut3D::Create();
+ };
+ ~CachedFileCSP() {};
+
+ bool hasprelut;
+ std::string csptype;
+ std::string metadata;
+ Lut1DRcPtr prelut;
+ Lut1DRcPtr lut1D;
+ Lut3DRcPtr lut3D;
+ };
+ typedef OCIO_SHARED_PTR<CachedFileCSP> CachedFileCSPRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+
+ // TODO: remove this when we don't need to debug
+ /*
+ template<class T>
+ std::ostream& operator<< (std::ostream& os, const std::vector<T>& v)
+ {
+ copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, " "));
+ return os;
+ }
+ */
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "cinespace";
+ info.extension = "csp";
+ info.capabilities = (FORMAT_CAPABILITY_READ | FORMAT_CAPABILITY_WRITE);
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+
+ // this shouldn't happen
+ if (!istream)
+ {
+ throw Exception ("file stream empty when trying to read csp lut");
+ }
+
+ Lut1DRcPtr prelut_ptr = Lut1D::Create();
+ Lut1DRcPtr lut1d_ptr = Lut1D::Create();
+ Lut3DRcPtr lut3d_ptr = Lut3D::Create();
+
+ // try and read the lut header
+ std::string line;
+ nextline (istream, line);
+ if (line != "CSPLUTV100")
+ {
+ std::ostringstream os;
+ os << "Lut doesn't seem to be a csp file, expected 'CSPLUTV100'.";
+ os << "First line: '" << line << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ // next line tells us if we are reading a 1D or 3D lut
+ nextline (istream, line);
+ if (line != "1D" && line != "3D")
+ {
+ std::ostringstream os;
+ os << "Unsupported CSP lut type. Require 1D or 3D. ";
+ os << "Found, '" << line << "'.";
+ throw Exception(os.str().c_str());
+ }
+ std::string csptype = line;
+
+ // read meta data block
+ std::string metadata;
+ std::streampos curr_pos = istream.tellg ();
+ nextline (istream, line);
+ if (line == "BEGIN METADATA")
+ {
+ while (line != "END METADATA" || !istream)
+ {
+ nextline (istream, line);
+ if (line != "END METADATA")
+ metadata += line + "\n";
+ }
+ }
+ else
+ {
+ istream.seekg (curr_pos);
+ }
+
+ // Make 3 vectors of prelut inputs + output values
+ std::vector<float> prelut_in[3];
+ std::vector<float> prelut_out[3];
+ bool useprelut[3] = { false, false, false };
+
+ // Parse the prelut block
+ for (int c = 0; c < 3; ++c)
+ {
+ // how many points do we have for this channel
+ nextline (istream, line);
+ int cpoints = 0;
+
+ if(!StringToInt(&cpoints, line.c_str()) || cpoints<0)
+ {
+ std::ostringstream os;
+ os << "Prelut does not specify valid dimension size on channel '";
+ os << c << ": " << line;
+ throw Exception(os.str().c_str());
+ }
+
+ if(cpoints>=2)
+ {
+ std::vector<std::string> inputparts, outputparts;
+
+ nextline (istream, line);
+ pystring::split(pystring::strip(line), inputparts);
+
+ nextline (istream, line);
+ pystring::split(pystring::strip(line), outputparts);
+
+ if(static_cast<int>(inputparts.size()) != cpoints ||
+ static_cast<int>(outputparts.size()) != cpoints)
+ {
+ std::ostringstream os;
+ os << "Prelut does not specify the expected number of data points. ";
+ os << "Expected: " << cpoints << ".";
+ os << "Found: " << inputparts.size() << ", " << outputparts.size() << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ if(!StringVecToFloatVec(prelut_in[c], inputparts) ||
+ !StringVecToFloatVec(prelut_out[c], outputparts))
+ {
+ std::ostringstream os;
+ os << "Prelut data is malformed, cannot to float array.";
+ throw Exception(os.str().c_str());
+ }
+
+
+ useprelut[c] = (!VecsEqualWithRelError(&(prelut_in[c][0]), static_cast<int>(prelut_in[c].size()),
+ &(prelut_out[c][0]), static_cast<int>(prelut_out[c].size()),
+ 1e-6f));
+ }
+ else
+ {
+ // Even though it's probably not part of the spec, why not allow for a size 0
+ // in a channel to be specified? It should be synonymous with identity,
+ // and allows the code lower down to assume all 3 channels exist
+
+ prelut_in[c].push_back(0.0f);
+ prelut_in[c].push_back(1.0f);
+ prelut_out[c].push_back(0.0f);
+ prelut_out[c].push_back(1.0f);
+ useprelut[c] = false;
+ }
+ }
+
+ if (csptype == "1D")
+ {
+
+ // how many 1D lut points do we have
+ nextline (istream, line);
+ int points1D = atoi (line.c_str());
+
+ //
+ float from_min = 0.0;
+ float from_max = 1.0;
+ for(int i=0; i<3; ++i)
+ {
+ lut1d_ptr->from_min[i] = from_min;
+ lut1d_ptr->from_max[i] = from_max;
+ lut1d_ptr->luts[i].clear();
+ lut1d_ptr->luts[i].reserve(points1D);
+ }
+
+ for(int i = 0; i < points1D; ++i)
+ {
+
+ // scan for the three floats
+ float lp[3];
+ nextline (istream, line);
+ if (sscanf (line.c_str(), "%f %f %f",
+ &lp[0], &lp[1], &lp[2]) != 3) {
+ throw Exception ("malformed 1D csp lut");
+ }
+
+ // store each channel
+ lut1d_ptr->luts[0].push_back(lp[0]);
+ lut1d_ptr->luts[1].push_back(lp[1]);
+ lut1d_ptr->luts[2].push_back(lp[2]);
+
+ }
+
+ }
+ else if (csptype == "3D")
+ {
+ // read the cube size
+ nextline (istream, line);
+ if (sscanf (line.c_str(), "%d %d %d",
+ &lut3d_ptr->size[0],
+ &lut3d_ptr->size[1],
+ &lut3d_ptr->size[2]) != 3 ) {
+ throw Exception("malformed 3D csp lut, couldn't read cube size");
+ }
+
+
+ // resize cube
+ int num3dentries = lut3d_ptr->size[0] * lut3d_ptr->size[1] * lut3d_ptr->size[2];
+ lut3d_ptr->lut.resize(num3dentries * 3);
+
+ for(int i=0; i<num3dentries; ++i)
+ {
+ // load the cube
+ nextline (istream, line);
+
+ if(sscanf (line.c_str(), "%f %f %f",
+ &lut3d_ptr->lut[3*i+0],
+ &lut3d_ptr->lut[3*i+1],
+ &lut3d_ptr->lut[3*i+2]) != 3 )
+ {
+ std::ostringstream os;
+ os << "Malformed 3D csp lut, couldn't read cube row (";
+ os << i << "): " << line << " .";
+ throw Exception(os.str().c_str());
+ }
+ }
+ }
+
+ CachedFileCSPRcPtr cachedFile = CachedFileCSPRcPtr (new CachedFileCSP ());
+ cachedFile->csptype = csptype;
+ cachedFile->metadata = metadata;
+
+ if(useprelut[0] || useprelut[1] || useprelut[2])
+ {
+ cachedFile->hasprelut = true;
+
+ for (int c = 0; c < 3; ++c)
+ {
+ size_t prelut_numpts = prelut_in[c].size();
+ float from_min = prelut_in[c][0];
+ float from_max = prelut_in[c][prelut_numpts-1];
+
+ // Allocate the interpolator
+ rsr_Interpolator1D_Raw * cprelut_raw =
+ rsr_Interpolator1D_Raw_create(static_cast<unsigned int>(prelut_numpts));
+
+ // Copy our prelut data into the interpolator
+ for(size_t i=0; i<prelut_numpts; ++i)
+ {
+ cprelut_raw->stims[i] = prelut_in[c][i];
+ cprelut_raw->values[i] = prelut_out[c][i];
+ }
+
+ // Create interpolater, to resample to simple 1D lut
+ rsr_Interpolator1D * interpolater =
+ rsr_Interpolator1D_createFromRaw(cprelut_raw);
+
+ // Resample into 1D lut
+ // TODO: Fancy spline analysis to determine required number of samples
+ prelut_ptr->from_min[c] = from_min;
+ prelut_ptr->from_max[c] = from_max;
+ prelut_ptr->luts[c].clear();
+ prelut_ptr->luts[c].reserve(NUM_PRELUT_SAMPLES);
+
+ for (int i = 0; i < NUM_PRELUT_SAMPLES; ++i)
+ {
+ float interpo = float(i) / float(NUM_PRELUT_SAMPLES-1);
+ float srcval = lerpf(from_min, from_max, interpo);
+ float newval = rsr_Interpolator1D_interpolate(srcval, interpolater);
+ prelut_ptr->luts[c].push_back(newval);
+ }
+
+ rsr_Interpolator1D_Raw_destroy(cprelut_raw);
+ rsr_Interpolator1D_destroy(interpolater);
+ }
+
+ prelut_ptr->maxerror = 1e-6f;
+ prelut_ptr->errortype = ERROR_RELATIVE;
+
+ cachedFile->prelut = prelut_ptr;
+ }
+
+ if(csptype == "1D")
+ {
+ lut1d_ptr->maxerror = 0.0f;
+ lut1d_ptr->errortype = ERROR_RELATIVE;
+ cachedFile->lut1D = lut1d_ptr;
+ }
+ else if (csptype == "3D")
+ {
+ cachedFile->lut3D = lut3d_ptr;
+ }
+
+ return cachedFile;
+ }
+
+
+ void LocalFileFormat::Write(const Baker & baker,
+ const std::string & /*formatName*/,
+ std::ostream & ostream) const
+ {
+ const int DEFAULT_CUBE_SIZE = 32;
+ const int DEFAULT_SHAPER_SIZE = 1024;
+
+ ConstConfigRcPtr config = baker.getConfig();
+
+ // TODO: Add 1d/3d lut writing switch, using hasChannelCrosstalk
+ int cubeSize = baker.getCubeSize();
+ if(cubeSize==-1) cubeSize = DEFAULT_CUBE_SIZE;
+ cubeSize = std::max(2, cubeSize); // smallest cube is 2x2x2
+ std::vector<float> cubeData;
+ cubeData.resize(cubeSize*cubeSize*cubeSize*3);
+ GenerateIdentityLut3D(&cubeData[0], cubeSize, 3, LUT3DORDER_FAST_RED);
+ PackedImageDesc cubeImg(&cubeData[0], cubeSize*cubeSize*cubeSize, 1, 3);
+
+ std::string looks = baker.getLooks();
+
+ std::vector<float> shaperInData;
+ std::vector<float> shaperOutData;
+
+ // Use an explicitly shaper space
+ // TODO: Use the optional allocation for the shaper space,
+ // instead of the implied 0-1 uniform allocation
+ std::string shaperSpace = baker.getShaperSpace();
+ if(!shaperSpace.empty())
+ {
+ int shaperSize = baker.getShaperSize();
+ if(shaperSize<0) shaperSize = DEFAULT_SHAPER_SIZE;
+ if(shaperSize<2)
+ {
+ std::ostringstream os;
+ os << "When a shaper space has been specified, '";
+ os << baker.getShaperSpace() << "', a shaper size less than 2 is not allowed.";
+ throw Exception(os.str().c_str());
+ }
+
+ shaperOutData.resize(shaperSize*3);
+ shaperInData.resize(shaperSize*3);
+ GenerateIdentityLut1D(&shaperOutData[0], shaperSize, 3);
+ GenerateIdentityLut1D(&shaperInData[0], shaperSize, 3);
+
+ ConstProcessorRcPtr shaperToInput = config->getProcessor(baker.getShaperSpace(), baker.getInputSpace());
+ if(shaperToInput->hasChannelCrosstalk())
+ {
+ // TODO: Automatically turn shaper into non-crosstalked version?
+ std::ostringstream os;
+ os << "The specified shaperSpace, '";
+ os << baker.getShaperSpace() << "' has channel crosstalk, which is not appropriate for shapers. ";
+ os << "Please select an alternate shaper space or omit this option.";
+ throw Exception(os.str().c_str());
+ }
+ PackedImageDesc shaperInImg(&shaperInData[0], shaperSize, 1, 3);
+ shaperToInput->apply(shaperInImg);
+
+ ConstProcessorRcPtr shaperToTarget;
+ if (!looks.empty())
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(baker.getShaperSpace());
+ transform->setDst(baker.getTargetSpace());
+ shaperToTarget = config->getProcessor(transform,
+ TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ shaperToTarget = config->getProcessor(baker.getShaperSpace(),
+ baker.getTargetSpace());
+ }
+ shaperToTarget->apply(cubeImg);
+ }
+ else
+ {
+ // A shaper is not specified, let's fake one, using the input space allocation as
+ // our guide
+
+ ConstColorSpaceRcPtr inputColorSpace = config->getColorSpace(baker.getInputSpace());
+
+ if(!inputColorSpace)
+ {
+ std::ostringstream os;
+ os << "Could not find colorspace '" << baker.getInputSpace() << "'";
+ throw Exception(os.str().c_str());
+ }
+
+ // Let's make an allocation transform for this colorspace
+ AllocationTransformRcPtr allocationTransform = AllocationTransform::Create();
+ allocationTransform->setAllocation(inputColorSpace->getAllocation());
+
+ // numVars may be '0'
+ int numVars = inputColorSpace->getAllocationNumVars();
+ if(numVars>0)
+ {
+ std::vector<float> vars(numVars);
+ inputColorSpace->getAllocationVars(&vars[0]);
+ allocationTransform->setVars(numVars, &vars[0]);
+ }
+ else
+ {
+ allocationTransform->setVars(0, NULL);
+ }
+
+ // What size shaper should we make?
+ int shaperSize = baker.getShaperSize();
+ if(shaperSize<0) shaperSize = DEFAULT_SHAPER_SIZE;
+ shaperSize = std::max(2, shaperSize);
+ if(inputColorSpace->getAllocation() == ALLOCATION_UNIFORM)
+ {
+ // This is an awesome optimization.
+ // If we know it's a uniform scaling, only 2 points will suffice!
+ shaperSize = 2;
+ }
+ shaperOutData.resize(shaperSize*3);
+ shaperInData.resize(shaperSize*3);
+ GenerateIdentityLut1D(&shaperOutData[0], shaperSize, 3);
+ GenerateIdentityLut1D(&shaperInData[0], shaperSize, 3);
+
+ // Apply the forward to the allocation to the output shaper y axis, and the cube
+ ConstProcessorRcPtr shaperToInput = config->getProcessor(allocationTransform, TRANSFORM_DIR_INVERSE);
+ PackedImageDesc shaperInImg(&shaperInData[0], shaperSize, 1, 3);
+ shaperToInput->apply(shaperInImg);
+ shaperToInput->apply(cubeImg);
+
+ // Apply the 3d lut to the remainder (from the input to the output)
+ ConstProcessorRcPtr inputToTarget;
+ if (!looks.empty())
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(baker.getInputSpace());
+ transform->setDst(baker.getTargetSpace());
+ inputToTarget = config->getProcessor(transform,
+ TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ inputToTarget = config->getProcessor(baker.getInputSpace(), baker.getTargetSpace());
+ }
+ inputToTarget->apply(cubeImg);
+ }
+
+ // Write out the file
+ ostream << "CSPLUTV100\n";
+ ostream << "3D\n";
+ ostream << "BEGIN METADATA\n";
+ std::string metadata = baker.getMetadata();
+ if(!metadata.empty())
+ {
+ ostream << metadata << "\n";
+ }
+ ostream << "END METADATA\n";
+ ostream << "\n";
+
+ // Write out the 1D Prelut
+ ostream.setf(std::ios::fixed, std::ios::floatfield);
+ ostream.precision(6);
+
+ if(shaperInData.size()<2 || shaperOutData.size() != shaperInData.size())
+ {
+ throw Exception("Internal shaper size exception.");
+ }
+
+ if(!shaperInData.empty())
+ {
+ for(int c=0; c<3; ++c)
+ {
+ ostream << shaperInData.size()/3 << "\n";
+ for(unsigned int i = 0; i<shaperInData.size()/3; ++i)
+ {
+ if(i != 0) ostream << " ";
+ ostream << shaperInData[3*i+c];
+ }
+ ostream << "\n";
+
+ for(unsigned int i = 0; i<shaperInData.size()/3; ++i)
+ {
+ if(i != 0) ostream << " ";
+ ostream << shaperOutData[3*i+c];
+ }
+ ostream << "\n";
+ }
+ }
+ ostream << "\n";
+
+ // Write out the 3D Cube
+ if(cubeSize < 2)
+ {
+ throw Exception("Internal cube size exception.");
+ }
+ ostream << cubeSize << " " << cubeSize << " " << cubeSize << "\n";
+ for(int i=0; i<cubeSize*cubeSize*cubeSize; ++i)
+ {
+ ostream << cubeData[3*i+0] << " " << cubeData[3*i+1] << " " << cubeData[3*i+2] << "\n";
+ }
+ ostream << "\n";
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+
+ CachedFileCSPRcPtr cachedFile = DynamicPtrCast<CachedFileCSP>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build CSP Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ if(cachedFile->hasprelut)
+ {
+ CreateLut1DOp(ops, cachedFile->prelut,
+ PRELUT_INTERPOLATION, newDir);
+ }
+ if(cachedFile->csptype == "1D")
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), newDir);
+ else if(cachedFile->csptype == "3D")
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ if(cachedFile->csptype == "1D")
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), newDir);
+ else if(cachedFile->csptype == "3D")
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ if(cachedFile->hasprelut)
+ {
+ CreateLut1DOp(ops, cachedFile->prelut,
+ PRELUT_INTERPOLATION, newDir);
+ }
+ }
+
+ return;
+
+ }
+ }
+
+ FileFormat * CreateFileFormatCSP()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(FileFormatCSP, simple1D)
+{
+ std::ostringstream strebuf;
+ strebuf << "CSPLUTV100" << "\n";
+ strebuf << "1D" << "\n";
+ strebuf << "" << "\n";
+ strebuf << "BEGIN METADATA" << "\n";
+ strebuf << "foobar" << "\n";
+ strebuf << "END METADATA" << "\n";
+ strebuf << "" << "\n";
+ strebuf << "2" << "\n";
+ strebuf << "0.0 1.0" << "\n";
+ strebuf << "0.0 2.0" << "\n";
+ strebuf << "6" << "\n";
+ strebuf << "0.0 0.2 0.4 0.6 0.8 1.0" << "\n";
+ strebuf << "0.0 0.4 0.8 1.2 1.6 2.0" << "\n";
+ strebuf << "3" << "\n";
+ strebuf << "0.0 0.1 1.0" << "\n";
+ strebuf << "0.0 0.2 2.0" << "\n";
+ strebuf << "" << "\n";
+ strebuf << "6" << "\n";
+ strebuf << "0.0 0.0 0.0" << "\n";
+ strebuf << "0.2 0.3 0.1" << "\n";
+ strebuf << "0.4 0.5 0.2" << "\n";
+ strebuf << "0.5 0.6 0.3" << "\n";
+ strebuf << "0.6 0.8 0.4" << "\n";
+ strebuf << "1.0 0.9 0.5" << "\n";
+
+ float red[6] = { 0.0f, 0.2f, 0.4f, 0.5f, 0.6f, 1.0f };
+ float green[6] = { 0.0f, 0.3f, 0.5f, 0.6f, 0.8f, 0.9f };
+ float blue[6] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
+
+ std::istringstream simple1D;
+ simple1D.str(strebuf.str());
+
+ // Read file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile = tester.Read(simple1D);
+ OCIO::CachedFileCSPRcPtr csplut = OCIO::DynamicPtrCast<OCIO::CachedFileCSP>(cachedFile);
+
+ // check prelut data (note: the spline is resampled into a 1D LUT)
+ for(int c=0; c<3; ++c)
+ {
+ for (unsigned int i = 0; i < csplut->prelut->luts[c].size(); i += 128)
+ {
+ float input = float(i) / float(csplut->prelut->luts[c].size()-1);
+ float output = csplut->prelut->luts[c][i];
+ OIIO_CHECK_CLOSE(input*2.0f, output, 1e-4);
+ }
+ }
+ // check 1D data
+ // red
+ unsigned int i;
+ for(i = 0; i < csplut->lut1D->luts[0].size(); ++i)
+ OIIO_CHECK_EQUAL(red[i], csplut->lut1D->luts[0][i]);
+ // green
+ for(i = 0; i < csplut->lut1D->luts[1].size(); ++i)
+ OIIO_CHECK_EQUAL(green[i], csplut->lut1D->luts[1][i]);
+ // blue
+ for(i = 0; i < csplut->lut1D->luts[2].size(); ++i)
+ OIIO_CHECK_EQUAL(blue[i], csplut->lut1D->luts[2][i]);
+
+}
+
+OIIO_ADD_TEST(FileFormatCSP, simple3D)
+{
+ std::ostringstream strebuf;
+ strebuf << "CSPLUTV100" << "\n";
+ strebuf << "3D" << "\n";
+ strebuf << "" << "\n";
+ strebuf << "BEGIN METADATA" << "\n";
+ strebuf << "foobar" << "\n";
+ strebuf << "END METADATA" << "\n";
+ strebuf << "" << "\n";
+ strebuf << "11" << "\n";
+ strebuf << "0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0" << "\n";
+ strebuf << "0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0" << "\n";
+ strebuf << "6" << "\n";
+ strebuf << "0.0 0.2 0.4 0.6 0.8 1.0" << "\n";
+ strebuf << "0.0 0.2000000 0.4 0.6 0.8 1.0" << "\n";
+ strebuf << "5" << "\n";
+ strebuf << "0.0 0.25 0.5 0.6 0.7" << "\n";
+ strebuf << "0.0 0.25000001 0.5 0.6 0.7" << "\n";
+ strebuf << "" << "\n";
+ strebuf << "1 2 3" << "\n";
+ strebuf << "0.0 0.0 0.0" << "\n";
+ strebuf << "1.0 0.0 0.0" << "\n";
+ strebuf << "0.0 0.5 0.0" << "\n";
+ strebuf << "1.0 0.5 0.0" << "\n";
+ strebuf << "0.0 1.0 0.0" << "\n";
+ strebuf << "1.0 1.0 0.0" << "\n";
+
+ float cube[1 * 2 * 3 * 3] = { 0.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0,
+ 1.0, 0.5, 0.0,
+ 0.0, 1.0, 0.0,
+ 1.0, 1.0, 0.0 };
+
+ std::istringstream simple3D;
+ simple3D.str(strebuf.str());
+
+ // Load file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile = tester.Read(simple3D);
+ OCIO::CachedFileCSPRcPtr csplut = OCIO::DynamicPtrCast<OCIO::CachedFileCSP>(cachedFile);
+
+ // check prelut data
+ OIIO_CHECK_ASSERT(csplut->hasprelut == false);
+
+ // check cube data
+ for(unsigned int i = 0; i < csplut->lut3D->lut.size(); ++i) {
+ OIIO_CHECK_EQUAL(cube[i], csplut->lut3D->lut[i]);
+ }
+
+ // check baker output
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("lnf");
+ cs->setFamily("lnf");
+ config->addColorSpace(cs);
+ config->setRole(OCIO::ROLE_REFERENCE, cs->getName());
+ }
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("shaper");
+ cs->setFamily("shaper");
+ OCIO::ExponentTransformRcPtr transform1 = OCIO::ExponentTransform::Create();
+ float test[4] = {2.6f, 2.6f, 2.6f, 1.0f};
+ transform1->setValue(test);
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_TO_REFERENCE);
+ config->addColorSpace(cs);
+ }
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("target");
+ cs->setFamily("target");
+ OCIO::CDLTransformRcPtr transform1 = OCIO::CDLTransform::Create();
+ float rgb[3] = {0.1f, 0.1f, 0.1f};
+ transform1->setOffset(rgb);
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+ config->addColorSpace(cs);
+ }
+
+ /*
+ std::string bout =
+ "CSPLUTV100\n"
+ "3D\n"
+ "\n"
+ "BEGIN METADATA\n"
+ "date: 2011:02:21 15:22:55\n"
+ "END METADATA\n"
+ "\n"
+ "10\n"
+ "0.000000 0.111111 0.222222 0.333333 0.444444 0.555556 0.666667 0.777778 0.888889 1.000000\n"
+ "0.000000 0.429520 0.560744 0.655378 0.732058 0.797661 0.855604 0.907865 0.955710 1.000000\n"
+ "10\n"
+ "0.000000 0.111111 0.222222 0.333333 0.444444 0.555556 0.666667 0.777778 0.888889 1.000000\n"
+ "0.000000 0.429520 0.560744 0.655378 0.732058 0.797661 0.855604 0.907865 0.955710 1.000000\n"
+ "10\n"
+ "0.000000 0.111111 0.222222 0.333333 0.444444 0.555556 0.666667 0.777778 0.888889 1.000000\n"
+ "0.000000 0.429520 0.560744 0.655378 0.732058 0.797661 0.855604 0.907865 0.955710 1.000000\n"
+ "\n"
+ "2 2 2\n"
+ "0.100000 0.100000 0.100000\n"
+ "1.000000 0.100000 0.100000\n"
+ "0.100000 1.000000 0.100000\n"
+ "1.000000 1.000000 0.100000\n"
+ "0.100000 0.100000 1.000000\n"
+ "1.000000 0.100000 1.000000\n"
+ "0.100000 1.000000 1.000000\n"
+ "1.000000 1.000000 1.000000\n"
+ "\n";
+
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+ baker->setConfig(config);
+ baker->setFormat("cinespace");
+ baker->setInputSpace("lnf");
+ baker->setShaperSpace("shaper");
+ baker->setTargetSpace("target");
+ baker->setShaperSize(10);
+ baker->setCubeSize(2);
+ std::ostringstream output;
+ baker->bake(output);
+
+ //
+ std::vector<std::string> osvec;
+ OCIO::pystring::splitlines(output.str(), osvec);
+ std::vector<std::string> resvec;
+ OCIO::pystring::splitlines(bout, resvec);
+ OIIO_CHECK_EQUAL(osvec.size(), resvec.size());
+ for(unsigned int i = 0; i < resvec.size(); ++i)
+ {
+ // skip timestamp line
+ if(i != 4) OIIO_CHECK_EQUAL(osvec[i], resvec[i]);
+ }
+ */
+
+}
+
+// TODO: More strenuous tests of prelut resampling (non-noop preluts)
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/FileFormatHDL.cpp b/src/core/FileFormatHDL.cpp
new file mode 100644
index 0000000..995ef9f
--- /dev/null
+++ b/src/core/FileFormatHDL.cpp
@@ -0,0 +1,1481 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+
+ Houdini LUTs
+ http://www.sidefx.com/docs/hdk11.0/hdk_io_lut.html
+
+ Types:
+ - 1D Lut (partial support)
+ - 3D Lut
+ - 3D Lut with 1D Prelut
+
+ TODO:
+ - Add support for other 1D types (R, G, B, A, RGB, RGBA, All)
+ we only support type 'C' atm.
+ - Add support for 'Sampling' tag
+
+*/
+
+#include <cstdio>
+#include <iostream>
+#include <iterator>
+#include <cmath>
+#include <vector>
+#include <string>
+#include <algorithm>
+#include <map>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "ParseUtils.h"
+#include "MathUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ // HDL parser helpers
+
+ // HDL headers/LUT's are shoved into these datatypes
+ typedef std::map<std::string, std::vector<std::string> > StringToStringVecMap;
+ typedef std::map<std::string, std::vector<float> > StringToFloatVecMap;
+
+ void
+ readHeaders(StringToStringVecMap& headers,
+ std::istream& istream)
+ {
+ std::string line;
+ while(nextline(istream, line))
+ {
+ std::vector<std::string> chunks;
+
+ // Remove trailing/leading whitespace, lower-case and
+ // split into words
+ pystring::split(pystring::lower(pystring::strip(line)), chunks);
+
+ // Skip empty lines
+ if(chunks.empty()) continue;
+
+ // Stop looking for headers at the "LUT:" line
+ if(chunks[0] == "lut:") break;
+
+ // Use first index as key, and remove it from the value
+ std::string key = chunks[0];
+ chunks.erase(chunks.begin());
+
+ headers[key] = chunks;
+ }
+ }
+
+ // Try to grab key (e.g "version") from headers. Throws
+ // exception if not found, or if number of chunks in value is
+ // not between min_vals and max_vals (e.g the "length" key
+ // must exist, and must have either 1 or 2 values)
+ std::vector<std::string>
+ findHeaderItem(StringToStringVecMap& headers,
+ const std::string key,
+ const unsigned int min_vals,
+ const unsigned int max_vals)
+ {
+ StringToStringVecMap::iterator iter;
+ iter = headers.find(key);
+
+ // Error if key is not found
+ if(iter == headers.end())
+ {
+ std::ostringstream os;
+ os << "'" << key << "' line not found";
+ throw Exception(os.str().c_str());
+ }
+
+ // Error if incorrect number of values is found
+ if(iter->second.size() < min_vals ||
+ iter->second.size() > max_vals)
+ {
+ std::ostringstream os;
+ os << "Incorrect number of chunks (" << iter->second.size() << ")";
+ os << " after '" << key << "' line, expected ";
+
+ if(min_vals == max_vals)
+ {
+ os << min_vals;
+ }
+ else
+ {
+ os << "between " << min_vals << " and " << max_vals;
+ }
+
+ throw Exception(os.str().c_str());
+ }
+
+ return iter->second;
+ }
+
+ // Simple wrapper to call findHeaderItem with a fixed number
+ // of values (e.g "version" should have a single value)
+ std::vector<std::string>
+ findHeaderItem(StringToStringVecMap& chunks,
+ const std::string key,
+ const unsigned int numvals)
+ {
+ return findHeaderItem(chunks, key, numvals, numvals);
+ }
+
+ // Crudely parse LUT's - doesn't do any length checking etc,
+ // just grabs a series of floats for Pre{...}, 3d{...} etc
+ // Does some basic error checking, but there are situations
+ // were it could incorrectly accept broken data (like
+ // "Pre{0.0\n1.0}blah"), but hopefully none where it misses
+ // data
+ void
+ readLuts(std::istream& istream,
+ StringToFloatVecMap& lutValues)
+ {
+ // State variables
+ bool inlut = false;
+ std::string lutname;
+
+ std::string word;
+
+ while(istream >> word)
+ {
+ if(!inlut)
+ {
+ if(word == "{")
+ {
+ // Lone "{" is for a 3D
+ inlut = true;
+ lutname = "3d";
+ }
+ else
+ {
+ // Named lut, e.g "Pre {"
+ inlut = true;
+ lutname = pystring::lower(word);
+
+ // Ensure next word is "{"
+ std::string nextword;
+ istream >> nextword;
+ if(nextword != "{")
+ {
+ std::ostringstream os;
+ os << "Malformed LUT - Unknown word '";
+ os << word << "' after LUT name '";
+ os << nextword << "'";
+ throw Exception(os.str().c_str());
+ }
+ }
+ }
+ else if(word == "}")
+ {
+ // end of LUT
+ inlut = false;
+ lutname = "";
+ }
+ else if(inlut)
+ {
+ // StringToFloat was far slower, for 787456 values:
+ // - StringToFloat took 3879 (avg nanoseconds per value)
+ // - stdtod took 169 nanoseconds
+ char* endptr = 0;
+ float v = static_cast<float>(strtod(word.c_str(), &endptr));
+
+ if(!*endptr)
+ {
+ // Since each word should contain a single
+ // float value, the pointer should be null
+ lutValues[lutname].push_back(v);
+ }
+ else
+ {
+ // stdtod endptr still contained stuff,
+ // meaning an invalid float value
+ std::ostringstream os;
+ os << "Invalid float value in " << lutname;
+ os << " LUT, '" << word << "'";
+ throw Exception(os.str().c_str());
+ }
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Unexpected word, possibly a value outside";
+ os <<" a LUT {} block. Word was '" << word << "'";
+ throw Exception(os.str().c_str());
+
+ }
+ }
+ }
+
+ } // end anonymous "HDL parser helpers" namespace
+
+ namespace
+ {
+ class CachedFileHDL : public CachedFile
+ {
+ public:
+ CachedFileHDL ()
+ {
+ hdlversion = "unknown";
+ hdlformat = "unknown";
+ hdltype = "unknown";
+ hdlblack = 0.0;
+ hdlwhite = 1.0;
+ lut1D = Lut1D::Create();
+ lut3D = Lut3D::Create();
+ };
+ ~CachedFileHDL() {};
+ std::string hdlversion;
+ std::string hdlformat;
+ std::string hdltype;
+ float to_min; // TODO: maybe add this to Lut1DOp?
+ float to_max; // TODO: maybe add this to Lut1DOp?
+ float hdlblack;
+ float hdlwhite;
+ Lut1DRcPtr lut1D;
+ Lut3DRcPtr lut3D;
+ };
+ typedef OCIO_SHARED_PTR<CachedFileHDL> CachedFileHDLRcPtr;
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "houdini";
+ info.extension = "lut";
+ info.capabilities = FORMAT_CAPABILITY_READ | FORMAT_CAPABILITY_WRITE;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+
+ // this shouldn't happen
+ if (!istream)
+ throw Exception ("file stream empty when trying to read Houdini lut");
+
+ //
+ CachedFileHDLRcPtr cachedFile = CachedFileHDLRcPtr (new CachedFileHDL ());
+ Lut1DRcPtr lut1d_ptr = Lut1D::Create();
+ Lut3DRcPtr lut3d_ptr = Lut3D::Create();
+
+ // Parse headers into key-value pairs
+ StringToStringVecMap header_chunks;
+ StringToStringVecMap::iterator iter;
+
+ // Read headers, ending after the "LUT:" line
+ readHeaders(header_chunks, istream);
+
+ // Grab useful values from headers
+ std::vector<std::string> value;
+
+ // "Version 3" - format version (currently one version
+ // number per LUT type)
+ value = findHeaderItem(header_chunks, "version", 1);
+ cachedFile->hdlversion = value[0];
+
+ // "Format any" - bit depth of image the LUT should be
+ // applied to (this is basically ignored)
+ value = findHeaderItem(header_chunks, "format", 1);
+ cachedFile->hdlformat = value[0];
+
+ // "Type 3d" - type of LUT
+ {
+ value = findHeaderItem(header_chunks, "type", 1);
+
+ cachedFile->hdltype = value[0];
+ }
+
+ // "From 0.0 1.0" - range of input values
+ {
+ float from_min, from_max;
+
+ value = findHeaderItem(header_chunks, "from", 2);
+
+ if(!StringToFloat(&from_min, value[0].c_str()) ||
+ !StringToFloat(&from_max, value[1].c_str()))
+ {
+ std::ostringstream os;
+ os << "Invalid float value(s) on 'From' line, '";
+ os << value[0] << "' and '" << value[1] << "'";
+ throw Exception(os.str().c_str());
+ }
+
+ for(int i = 0; i < 3; ++i)
+ {
+ lut1d_ptr->from_min[i] = from_min;
+ lut1d_ptr->from_max[i] = from_max;
+ }
+ }
+
+
+ // "To 0.0 1.0" - range of values in LUT (e.g "0 255"
+ // to specify values as 8-bit numbers, usually "0 1")
+ {
+ float to_min, to_max;
+
+ value = findHeaderItem(header_chunks, "to", 2);
+
+ if(!StringToFloat(&to_min, value[0].c_str()) ||
+ !StringToFloat(&to_max, value[1].c_str()))
+ {
+ std::ostringstream os;
+ os << "Invalid float value(s) on 'To' line, '";
+ os << value[0] << "' and '" << value[1] << "'";
+ throw Exception(os.str().c_str());
+ }
+ cachedFile->to_min = to_min;
+ cachedFile->to_max = to_max;
+ }
+
+ // "Black 0" and "White 1" - obsolete options, should be 0
+ // and 1
+
+ {
+ value = findHeaderItem(header_chunks, "black", 1);
+
+ float black;
+
+ if(!StringToFloat(&black, value[0].c_str()))
+ {
+ std::ostringstream os;
+ os << "Invalid float value on 'Black' line, '";
+ os << value[0] << "'";
+ throw Exception(os.str().c_str());
+ }
+ cachedFile->hdlblack = black;
+ }
+
+ {
+ value = findHeaderItem(header_chunks, "white", 1);
+
+ float white;
+
+ if(!StringToFloat(&white, value[0].c_str()))
+ {
+ std::ostringstream os;
+ os << "Invalid float value on 'White' line, '";
+ os << value[0] << "'";
+ throw Exception(os.str().c_str());
+ }
+ cachedFile->hdlwhite = white;
+ }
+
+
+ // Verify type is valid and supported - used to handle
+ // length sensibly, and checking the LUT later
+ {
+ std::string ltype = cachedFile->hdltype;
+ if(ltype != "3d" && ltype != "3d+1d" && ltype != "c")
+ {
+ std::ostringstream os;
+ os << "Unsupported Houdini LUT type: '" << ltype << "'";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+
+ // "Length 2" or "Length 2 5" - either "[cube size]", or "[cube
+ // size] [prelut size]"
+ int size_3d = -1;
+ int size_prelut = -1;
+ int size_1d = -1;
+
+ {
+ std::vector<int> lut_sizes;
+
+ value = findHeaderItem(header_chunks, "length", 1, 2);
+ for(unsigned int i = 0; i < value.size(); ++i)
+ {
+ int tmpsize = -1;
+ if(!StringToInt(&tmpsize, value[i].c_str()))
+ {
+ std::ostringstream os;
+ os << "Invalid integer on 'Length' line: ";
+ os << "'" << value[0] << "'";
+ throw Exception(os.str().c_str());
+ }
+ lut_sizes.push_back(tmpsize);
+ }
+
+ if(cachedFile->hdltype == "3d" || cachedFile->hdltype == "3d+1d")
+ {
+ // Set cube size
+ size_3d = lut_sizes[0];
+
+ lut3d_ptr->size[0] = lut_sizes[0];
+ lut3d_ptr->size[1] = lut_sizes[0];
+ lut3d_ptr->size[2] = lut_sizes[0];
+ }
+
+ if(cachedFile->hdltype == "c")
+ {
+ size_1d = lut_sizes[0];
+ }
+
+ if(cachedFile->hdltype == "3d+1d")
+ {
+ size_prelut = lut_sizes[1];
+ }
+ }
+
+ // Read stuff after "LUT:"
+ StringToFloatVecMap lut_data;
+ readLuts(istream, lut_data);
+
+ //
+ StringToFloatVecMap::iterator lut_iter;
+
+ if(cachedFile->hdltype == "3d+1d")
+ {
+ // Read prelut, and bind onto cachedFile
+ lut_iter = lut_data.find("pre");
+ if(lut_iter == lut_data.end())
+ {
+ std::ostringstream os;
+ os << "3D+1D LUT should contain Pre{} LUT section";
+ throw Exception(os.str().c_str());
+ }
+
+ if(size_prelut != static_cast<int>(lut_iter->second.size()))
+ {
+ std::ostringstream os;
+ os << "Pre{} LUT was " << lut_iter->second.size();
+ os << " values long, expected " << size_prelut << " values";
+ throw Exception(os.str().c_str());
+ }
+
+ lut1d_ptr->luts[0] = lut_iter->second;
+ lut1d_ptr->luts[1] = lut_iter->second;
+ lut1d_ptr->luts[2] = lut_iter->second;
+ lut1d_ptr->maxerror = 0.0f;
+ lut1d_ptr->errortype = ERROR_RELATIVE;
+ cachedFile->lut1D = lut1d_ptr;
+ }
+
+ if(cachedFile->hdltype == "3d" ||
+ cachedFile->hdltype == "3d+1d")
+ {
+ // Bind 3D LUT to lut3d_ptr, along with some
+ // slightly-elabourate error messages
+
+ lut_iter = lut_data.find("3d");
+ if(lut_iter == lut_data.end())
+ {
+ std::ostringstream os;
+ os << "3D LUT section not found";
+ throw Exception(os.str().c_str());
+ }
+
+ int size_3d_cubed = size_3d * size_3d * size_3d;
+
+ if(size_3d_cubed * 3 != static_cast<int>(lut_iter->second.size()))
+ {
+ int foundsize = static_cast<int>(lut_iter->second.size());
+ int foundlines = foundsize / 3;
+
+ std::ostringstream os;
+ os << "3D LUT contains incorrect number of values. ";
+ os << "Contained " << foundsize << " values ";
+ os << "(" << foundlines << " lines), ";
+ os << "expected " << (size_3d_cubed*3) << " values ";
+ os << "(" << size_3d_cubed << " lines)";
+ throw Exception(os.str().c_str());
+ }
+
+ lut3d_ptr->lut = lut_iter->second;
+
+ // Bind to cachedFile
+ cachedFile->lut3D = lut3d_ptr;
+ }
+
+ if(cachedFile->hdltype == "c")
+ {
+ // Bind simple 1D RGB LUT
+ lut_iter = lut_data.find("rgb");
+ if(lut_iter == lut_data.end())
+ {
+ std::ostringstream os;
+ os << "3D+1D LUT should contain Pre{} LUT section";
+ throw Exception(os.str().c_str());
+ }
+
+ if(size_1d != static_cast<int>(lut_iter->second.size()))
+ {
+ std::ostringstream os;
+ os << "RGB{} LUT was " << lut_iter->second.size();
+ os << " values long, expected " << size_1d << " values";
+ throw Exception(os.str().c_str());
+ }
+
+ lut1d_ptr->luts[0] = lut_iter->second;
+ lut1d_ptr->luts[1] = lut_iter->second;
+ lut1d_ptr->luts[2] = lut_iter->second;
+ lut1d_ptr->maxerror = 0.0f;
+ lut1d_ptr->errortype = ERROR_RELATIVE;
+ cachedFile->lut1D = lut1d_ptr;
+ }
+
+ return cachedFile;
+ }
+
+ void LocalFileFormat::Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const
+ {
+
+ if(formatName != "houdini")
+ {
+ std::ostringstream os;
+ os << "Unknown hdl format name, '";
+ os << formatName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Get config
+ ConstConfigRcPtr config = baker.getConfig();
+
+ // setup the floating point precision
+ ostream.setf(std::ios::fixed, std::ios::floatfield);
+ ostream.precision(6);
+
+ // Default sizes
+ const int DEFAULT_SHAPER_SIZE = 1024;
+ // MPlay produces bad results with 32^3 cube (in a way
+ // that looks more quantised than even "nearest"
+ // interpolation in OCIOFileTransform)
+ const int DEFAULT_CUBE_SIZE = 64;
+ const int DEFAULT_1D_SIZE = 1024;
+
+ // Get configured sizes
+ int cubeSize = baker.getCubeSize();
+ int shaperSize = baker.getShaperSize();
+ // FIXME: Misusing cube size to set 1D LUT size, as it seemed
+ // slightly less confusing than using the shaper LUT size
+ int onedSize = baker.getCubeSize();
+
+ // Defaults and sanity check on cube size
+ if(cubeSize == -1) cubeSize = DEFAULT_CUBE_SIZE;
+ if(cubeSize < 0) cubeSize = DEFAULT_CUBE_SIZE;
+ if(cubeSize<2)
+ {
+ std::ostringstream os;
+ os << "Cube size must be 2 or larger (was " << cubeSize << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ // ..and same for shaper size
+ if(shaperSize<0) shaperSize = DEFAULT_SHAPER_SIZE;
+ if(shaperSize<2)
+ {
+ std::ostringstream os;
+ os << "A shaper space ('" << baker.getShaperSpace() << "') has";
+ os << " been specified, so the shaper size must be 2 or larger";
+ throw Exception(os.str().c_str());
+ }
+
+ // ..and finally, for the 1D LUT size
+ if(onedSize == -1) onedSize = DEFAULT_1D_SIZE;
+ if(onedSize < 2)
+ {
+ std::ostringstream os;
+ os << "1D LUT size must be higher than 2 (was " << onedSize << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ // Version numbers
+ const int HDL_1D = 1; // 1D LUT version number
+ const int HDL_3D = 2; // 3D LUT version number
+ const int HDL_3D1D = 3; // 3D LUT with 1D prelut
+
+ // Get spaces from baker
+ const std::string shaperSpace = baker.getShaperSpace();
+ const std::string inputSpace = baker.getInputSpace();
+ const std::string targetSpace = baker.getTargetSpace();
+ const std::string looks = baker.getLooks();
+
+ // Determine required LUT type
+ ConstProcessorRcPtr inputToTargetProc;
+ if (!looks.empty())
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(inputSpace.c_str());
+ transform->setDst(targetSpace.c_str());
+ inputToTargetProc = config->getProcessor(transform,
+ TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ inputToTargetProc = config->getProcessor(
+ inputSpace.c_str(),
+ targetSpace.c_str());
+ }
+
+ int required_lut = -1;
+
+ if(inputToTargetProc->hasChannelCrosstalk())
+ {
+ if(shaperSpace.empty())
+ {
+ // Has crosstalk, but no prelut, so need 3D LUT
+ required_lut = HDL_3D;
+ }
+ else
+ {
+ // Crosstalk with shaper-space
+ required_lut = HDL_3D1D;
+ }
+ }
+ else
+ {
+ // No crosstalk
+ required_lut = HDL_1D;
+ }
+
+ if(required_lut == -1)
+ {
+ // Unnecessary paranoia
+ throw Exception(
+ "Internal logic error, LUT type was not determined");
+ }
+
+ // Make prelut
+ std::vector<float> prelutData;
+
+ float fromInStart = 0; // for "From:" part of header
+ float fromInEnd = 1;
+
+ if(required_lut == HDL_3D1D)
+ {
+ // TODO: Later we only grab the green channel for the prelut,
+ // should ensure the prelut is monochromatic somehow?
+
+ ConstProcessorRcPtr inputToShaperProc = config->getProcessor(
+ inputSpace.c_str(),
+ shaperSpace.c_str());
+
+ if(inputToShaperProc->hasChannelCrosstalk())
+ {
+ // TODO: Automatically turn shaper into
+ // non-crosstalked version?
+ std::ostringstream os;
+ os << "The specified shaperSpace, '" << baker.getShaperSpace();
+ os << "' has channel crosstalk, which is not appropriate for";
+ os << " shapers. Please select an alternate shaper space or";
+ os << " omit this option.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Calculate min/max value
+ {
+ // Get input value of 1.0 in shaper space, as this
+ // is the higest value that is transformed by the
+ // cube (e.g for a generic lin-to-log trasnform,
+ // what the log value 1.0 is in linear).
+ ConstProcessorRcPtr shaperToInputProc = config->getProcessor(
+ shaperSpace.c_str(),
+ inputSpace.c_str());
+
+ float minval[3] = {0.0f, 0.0f, 0.0f};
+ float maxval[3] = {1.0f, 1.0f, 1.0f};
+
+ shaperToInputProc->applyRGB(minval);
+ shaperToInputProc->applyRGB(maxval);
+
+ // Grab green channel, as this is the one used later
+ fromInStart = minval[1];
+ fromInEnd = maxval[1];
+ }
+
+ // Generate the identity prelut values, then apply the transform.
+ // Prelut is linearly sampled from fromInStart to fromInEnd
+ prelutData.resize(shaperSize*3);
+
+ for (int i = 0; i < shaperSize; ++i)
+ {
+ const float x = (float)(double(i) / double(shaperSize - 1));
+ float cur_value = lerpf(fromInStart, fromInEnd, x);
+
+ prelutData[3*i+0] = cur_value;
+ prelutData[3*i+1] = cur_value;
+ prelutData[3*i+2] = cur_value;
+ }
+
+ PackedImageDesc prelutImg(&prelutData[0], shaperSize, 1, 3);
+ inputToShaperProc->apply(prelutImg);
+ }
+
+ // TODO: Do same "auto prelut" input-space allocation as FileFormatCSP?
+
+ // Make 3D LUT
+ std::vector<float> cubeData;
+ if(required_lut == HDL_3D || required_lut == HDL_3D1D)
+ {
+ cubeData.resize(cubeSize*cubeSize*cubeSize*3);
+
+ GenerateIdentityLut3D(&cubeData[0], cubeSize, 3, LUT3DORDER_FAST_RED);
+ PackedImageDesc cubeImg(&cubeData[0], cubeSize*cubeSize*cubeSize, 1, 3);
+
+ ConstProcessorRcPtr cubeProc;
+ if(required_lut == HDL_3D1D)
+ {
+ // Prelut goes from input-to-shaper, so cube goes from shaper-to-target
+ if (!looks.empty())
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(inputSpace.c_str());
+ transform->setDst(targetSpace.c_str());
+ cubeProc = config->getProcessor(transform,
+ TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ cubeProc = config->getProcessor(shaperSpace.c_str(),
+ targetSpace.c_str());
+ }
+ }
+ else
+ {
+ // No prelut, so cube goes from input-to-target
+ cubeProc = inputToTargetProc;
+ }
+
+
+ cubeProc->apply(cubeImg);
+ }
+
+
+ // Make 1D LUT
+ std::vector<float> onedData;
+ if(required_lut == HDL_1D)
+ {
+ onedData.resize(onedSize * 3);
+
+ GenerateIdentityLut1D(&onedData[0], onedSize, 3);
+ PackedImageDesc onedImg(&onedData[0], onedSize, 1, 3);
+
+ inputToTargetProc->apply(onedImg);
+ }
+
+
+ // Write the file contents
+ ostream << "Version\t\t" << required_lut << "\n";
+ ostream << "Format\t\t" << "any" << "\n";
+
+ ostream << "Type\t\t";
+ if(required_lut == HDL_1D)
+ ostream << "RGB";
+ if(required_lut == HDL_3D)
+ ostream << "3D";
+ if(required_lut == HDL_3D1D)
+ ostream << "3D+1D";
+ ostream << "\n";
+
+ ostream << "From\t\t" << fromInStart << " " << fromInEnd << "\n";
+ ostream << "To\t\t" << 0.0f << " " << 1.0f << "\n";
+ ostream << "Black\t\t" << 0.0f << "\n";
+ ostream << "White\t\t" << 1.0f << "\n";
+
+ if(required_lut == HDL_3D1D)
+ ostream << "Length\t\t" << cubeSize << " " << shaperSize << "\n";
+ if(required_lut == HDL_3D)
+ ostream << "Length\t\t" << cubeSize << "\n";
+ if(required_lut == HDL_1D)
+ ostream << "Length\t\t" << onedSize << "\n";
+
+ ostream << "LUT:\n";
+
+ // Write prelut
+ if(required_lut == HDL_3D1D)
+ {
+ ostream << "Pre {\n";
+ for(int i=0; i < shaperSize; ++i)
+ {
+ // Grab green channel from RGB prelut
+ ostream << "\t" << prelutData[i*3+1] << "\n";
+ }
+ ostream << "}\n";
+ }
+
+ // Write "3D {" part of output of 3D+1D LUT
+ if(required_lut == HDL_3D1D)
+ {
+ ostream << "3D {\n";
+ }
+
+ // Write the slightly-different "{" without line for the 3D-only LUT
+ if(required_lut == HDL_3D)
+ {
+ ostream << " {\n";
+ }
+
+ // Write the cube data after the "{"
+ if(required_lut == HDL_3D || required_lut == HDL_3D1D)
+ {
+ for(int i=0; i < cubeSize*cubeSize*cubeSize; ++i)
+ {
+ // TODO: Original baker code clamped values to
+ // 1.0, was this necessary/desirable?
+
+ ostream << "\t" << cubeData[3*i+0];
+ ostream << " " << cubeData[3*i+1];
+ ostream << " " << cubeData[3*i+2] << "\n";
+ }
+
+ // Write closing "}"
+ ostream << " }\n";
+ }
+
+ // Write out channels for 1D LUT
+ if(required_lut == HDL_1D)
+ {
+ ostream << "R {\n";
+ for(int i=0; i < onedSize; ++i)
+ ostream << "\t" << onedData[i*3+0] << "\n";
+ ostream << "}\n";
+
+ ostream << "G {\n";
+ for(int i=0; i < onedSize; ++i)
+ ostream << "\t" << onedData[i*3+1] << "\n";
+ ostream << "}\n";
+
+ ostream << "B {\n";
+ for(int i=0; i < onedSize; ++i)
+ ostream << "\t" << onedData[i*3+2] << "\n";
+ ostream << "}\n";
+ }
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+
+ CachedFileHDLRcPtr cachedFile = DynamicPtrCast<CachedFileHDL>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build Houdini Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+
+ if(newDir == TRANSFORM_DIR_FORWARD) {
+ if(cachedFile->hdltype == "c")
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(cachedFile->hdltype == "3d")
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(cachedFile->hdltype == "3d+1d")
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), newDir);
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else
+ {
+ throw Exception("Unhandled hdltype while creating forward ops");
+ }
+ } else if(newDir == TRANSFORM_DIR_INVERSE) {
+ if(cachedFile->hdltype == "c")
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(cachedFile->hdltype == "3d")
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(cachedFile->hdltype == "3d+1d")
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else
+ {
+ throw Exception("Unhandled hdltype while creating reverse ops");
+ }
+ }
+ return;
+ }
+ }
+
+ FileFormat * CreateFileFormatHDL()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(FileFormatHDL, Read1D)
+{
+ std::ostringstream strebuf;
+ strebuf << "Version\t\t1" << "\n";
+ strebuf << "Format\t\tany" << "\n";
+ strebuf << "Type\t\tC" << "\n";
+ strebuf << "From\t\t0.1 3.2" << "\n";
+ strebuf << "To\t\t0 1" << "\n";
+ strebuf << "Black\t\t0" << "\n";
+ strebuf << "White\t\t0.99" << "\n";
+ strebuf << "Length\t\t9" << "\n";
+ strebuf << "LUT:" << "\n";
+ strebuf << "RGB {" << "\n";
+ strebuf << "\t0" << "\n";
+ strebuf << "\t0.000977517" << "\n";
+ strebuf << "\t0.00195503" << "\n";
+ strebuf << "\t0.00293255" << "\n";
+ strebuf << "\t0.00391007" << "\n";
+ strebuf << "\t0.00488759" << "\n";
+ strebuf << "\t0.0058651" << "\n";
+ strebuf << "\t0.999022" << "\n";
+ strebuf << "\t1.67 }" << "\n";
+
+ //
+ float from_min = 0.1f;
+ float from_max = 3.2f;
+ float to_min = 0.0f;
+ float to_max = 1.0f;
+ float black = 0.0f;
+ float white = 0.99f;
+ float lut1d[9] = { 0.0f, 0.000977517f, 0.00195503f, 0.00293255f,
+ 0.00391007f, 0.00488759f, 0.0058651f, 0.999022f, 1.67f };
+
+ std::istringstream simple3D1D;
+ simple3D1D.str(strebuf.str());
+
+ // Load file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile = tester.Read(simple3D1D);
+ OCIO::CachedFileHDLRcPtr lut = OCIO::DynamicPtrCast<OCIO::CachedFileHDL>(cachedFile);
+
+ //
+ OIIO_CHECK_EQUAL(to_min, lut->to_min);
+ OIIO_CHECK_EQUAL(to_max, lut->to_max);
+ OIIO_CHECK_EQUAL(black, lut->hdlblack);
+ OIIO_CHECK_EQUAL(white, lut->hdlwhite);
+
+ // check 1D data (each channel has the same data)
+ for(int c = 0; c < 3; ++c) {
+ OIIO_CHECK_EQUAL(from_min, lut->lut1D->from_min[c]);
+ OIIO_CHECK_EQUAL(from_max, lut->lut1D->from_max[c]);
+
+ OIIO_CHECK_EQUAL(9, lut->lut1D->luts[c].size());
+
+ for(unsigned int i = 0; i < lut->lut1D->luts[c].size(); ++i) {
+ OIIO_CHECK_EQUAL(lut1d[i], lut->lut1D->luts[c][i]);
+ }
+ }
+}
+
+OIIO_ADD_TEST(FileFormatHDL, Bake1D)
+{
+
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+
+ // Add lnf space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("lnf");
+ cs->setFamily("lnf");
+ config->addColorSpace(cs);
+ config->setRole(OCIO::ROLE_REFERENCE, cs->getName());
+ }
+
+ // Add target space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("target");
+ cs->setFamily("target");
+ OCIO::CDLTransformRcPtr transform1 = OCIO::CDLTransform::Create();
+
+ float rgb[3] = {0.1f, 0.1f, 0.1f};
+ transform1->setOffset(rgb);
+
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+ config->addColorSpace(cs);
+ }
+
+ std::string bout =
+ "Version\t\t1\n"
+ "Format\t\tany\n"
+ "Type\t\tRGB\n"
+ "From\t\t0.000000 1.000000\n"
+ "To\t\t0.000000 1.000000\n"
+ "Black\t\t0.000000\n"
+ "White\t\t1.000000\n"
+ "Length\t\t10\n"
+ "LUT:\n"
+ "R {\n"
+ "\t0.100000\n"
+ "\t0.211111\n"
+ "\t0.322222\n"
+ "\t0.433333\n"
+ "\t0.544444\n"
+ "\t0.655556\n"
+ "\t0.766667\n"
+ "\t0.877778\n"
+ "\t0.988889\n"
+ "\t1.100000\n"
+ " }\n"
+ "G {\n"
+ "\t0.100000\n"
+ "\t0.211111\n"
+ "\t0.322222\n"
+ "\t0.433333\n"
+ "\t0.544444\n"
+ "\t0.655556\n"
+ "\t0.766667\n"
+ "\t0.877778\n"
+ "\t0.988889\n"
+ "\t1.100000\n"
+ " }\n"
+ "B {\n"
+ "\t0.100000\n"
+ "\t0.211111\n"
+ "\t0.322222\n"
+ "\t0.433333\n"
+ "\t0.544444\n"
+ "\t0.655556\n"
+ "\t0.766667\n"
+ "\t0.877778\n"
+ "\t0.988889\n"
+ "\t1.100000\n"
+ " }\n";
+
+ //
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+ baker->setConfig(config);
+ baker->setFormat("houdini");
+ baker->setInputSpace("lnf");
+ baker->setTargetSpace("target");
+ baker->setCubeSize(10); // FIXME: Misusing the cube size to set the 1D LUT size
+ std::ostringstream output;
+ baker->bake(output);
+
+ //std::cerr << "The LUT: " << std::endl << output.str() << std::endl;
+ //std::cerr << "Expected:" << std::endl << bout << std::endl;
+
+ //
+ std::vector<std::string> osvec;
+ OCIO::pystring::splitlines(output.str(), osvec);
+ std::vector<std::string> resvec;
+ OCIO::pystring::splitlines(bout, resvec);
+ OIIO_CHECK_EQUAL(osvec.size(), resvec.size());
+ for(unsigned int i = 0; i < std::min(osvec.size(), resvec.size()); ++i)
+ OIIO_CHECK_EQUAL(OCIO::pystring::strip(osvec[i]), OCIO::pystring::strip(resvec[i]));
+
+}
+
+OIIO_ADD_TEST(FileFormatHDL, Read3D)
+{
+ std::ostringstream strebuf;
+ strebuf << "Version 2" << "\n";
+ strebuf << "Format any" << "\n";
+ strebuf << "Type 3D" << "\n";
+ strebuf << "From 0.2 0.9" << "\n";
+ strebuf << "To 0.001 0.999" << "\n";
+ strebuf << "Black 0.002" << "\n";
+ strebuf << "White 0.98" << "\n";
+ strebuf << "Length 2" << "\n";
+ strebuf << "LUT:" << "\n";
+ strebuf << " {" << "\n";
+ strebuf << " 0 0 0" << "\n";
+ strebuf << " 0 0 0" << "\n";
+ strebuf << " 0 0.390735 2.68116e-28" << "\n";
+ strebuf << " 0 0.390735 0" << "\n";
+ strebuf << " 0 0 0" << "\n";
+ strebuf << " 0 0 0.599397" << "\n";
+ strebuf << " 0 0.601016 0" << "\n";
+ strebuf << " 0 0.601016 0.917034" << "\n";
+ strebuf << " }" << "\n";
+
+ std::istringstream simple3D1D;
+ simple3D1D.str(strebuf.str());
+ // Load file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile = tester.Read(simple3D1D);
+ OCIO::CachedFileHDLRcPtr lut = OCIO::DynamicPtrCast<OCIO::CachedFileHDL>(cachedFile);
+
+ //
+ //float from_min = 0.2;
+ //float from_max = 0.9;
+ float to_min = 0.001f;
+ float to_max = 0.999f;
+ float black = 0.002f;
+ float white = 0.98f;
+ float cube[2 * 2 * 2 * 3 ] = {
+ 0.f, 0.f, 0.f,
+ 0.f, 0.f, 0.f,
+ 0.f, 0.390735f, 2.68116e-28f,
+ 0.f, 0.390735f, 0.f,
+ 0.f, 0.f, 0.f,
+ 0.f, 0.f, 0.599397f,
+ 0.f, 0.601016f, 0.f,
+ 0.f, 0.601016f, 0.917034f };
+
+ //
+ OIIO_CHECK_EQUAL(to_min, lut->to_min);
+ OIIO_CHECK_EQUAL(to_max, lut->to_max);
+ OIIO_CHECK_EQUAL(black, lut->hdlblack);
+ OIIO_CHECK_EQUAL(white, lut->hdlwhite);
+
+ // check cube data
+ OIIO_CHECK_EQUAL(2*2*2*3, lut->lut3D->lut.size());
+
+ for(unsigned int i = 0; i < lut->lut3D->lut.size(); ++i) {
+ OIIO_CHECK_EQUAL(cube[i], lut->lut3D->lut[i]);
+ }
+}
+
+OIIO_ADD_TEST(FileFormatHDL, Bake3D)
+{
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+
+ // Set luma coef's to simple values
+ {
+ float lumaCoef[3] = {0.333f, 0.333f, 0.333f};
+ config->setDefaultLumaCoefs(lumaCoef);
+ }
+
+ // Add lnf space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("lnf");
+ cs->setFamily("lnf");
+ config->addColorSpace(cs);
+ config->setRole(OCIO::ROLE_REFERENCE, cs->getName());
+ }
+
+ // Add target space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("target");
+ cs->setFamily("target");
+ OCIO::CDLTransformRcPtr transform1 = OCIO::CDLTransform::Create();
+
+ // Set saturation to cause channel crosstalk, making a 3D LUT
+ transform1->setSat(0.5f);
+
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+ config->addColorSpace(cs);
+ }
+
+ std::string bout =
+ "Version\t\t2\n"
+ "Format\t\tany\n"
+ "Type\t\t3D\n"
+ "From\t\t0.000000 1.000000\n"
+ "To\t\t0.000000 1.000000\n"
+ "Black\t\t0.000000\n"
+ "White\t\t1.000000\n"
+ "Length\t\t2\n"
+ "LUT:\n"
+ " {\n"
+ "\t0.000000 0.000000 0.000000\n"
+ "\t0.606300 0.106300 0.106300\n"
+ "\t0.357600 0.857600 0.357600\n"
+ "\t0.963900 0.963900 0.463900\n"
+ "\t0.036100 0.036100 0.536100\n"
+ "\t0.642400 0.142400 0.642400\n"
+ "\t0.393700 0.893700 0.893700\n"
+ "\t1.000000 1.000000 1.000000\n"
+ " }\n";
+
+ //
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+ baker->setConfig(config);
+ baker->setFormat("houdini");
+ baker->setInputSpace("lnf");
+ baker->setTargetSpace("target");
+ baker->setCubeSize(2);
+ std::ostringstream output;
+ baker->bake(output);
+
+ //std::cerr << "The LUT: " << std::endl << output.str() << std::endl;
+ //std::cerr << "Expected:" << std::endl << bout << std::endl;
+
+ //
+ std::vector<std::string> osvec;
+ OCIO::pystring::splitlines(output.str(), osvec);
+ std::vector<std::string> resvec;
+ OCIO::pystring::splitlines(bout, resvec);
+ OIIO_CHECK_EQUAL(osvec.size(), resvec.size());
+ for(unsigned int i = 0; i < std::min(osvec.size(), resvec.size()); ++i)
+ OIIO_CHECK_EQUAL(OCIO::pystring::strip(osvec[i]), OCIO::pystring::strip(resvec[i]));
+}
+
+OIIO_ADD_TEST(FileFormatHDL, Read3D1D)
+{
+ std::ostringstream strebuf;
+ strebuf << "Version 3" << "\n";
+ strebuf << "Format any" << "\n";
+ strebuf << "Type 3D+1D" << "\n";
+ strebuf << "From 0.005478 14.080103" << "\n";
+ strebuf << "To 0 1" << "\n";
+ strebuf << "Black 0" << "\n";
+ strebuf << "White 1" << "\n";
+ strebuf << "Length 2 10" << "\n";
+ strebuf << "LUT:" << "\n";
+ strebuf << "Pre {" << "\n";
+ strebuf << " 0.994922" << "\n";
+ strebuf << " 0.995052" << "\n";
+ strebuf << " 0.995181" << "\n";
+ strebuf << " 0.995310" << "\n";
+ strebuf << " 0.995439" << "\n";
+ strebuf << " 0.995568" << "\n";
+ strebuf << " 0.995697" << "\n";
+ strebuf << " 0.995826" << "\n";
+ strebuf << " 0.995954" << "\n";
+ strebuf << " 0.996082" << "\n";
+ strebuf << "}" << "\n";
+ strebuf << "3D {" << "\n";
+ strebuf << " 0.093776 0.093776 0.093776" << "\n";
+ strebuf << " 0.105219 0.093776 0.093776" << "\n";
+ strebuf << " 0.118058 0.093776 0.093776" << "\n";
+ strebuf << " 0.132463 0.093776 0.093776" << "\n";
+ strebuf << " 0.148626 0.093776 0.093776" << "\n";
+ strebuf << " 0.166761 0.093776 0.093776" << "\n";
+ strebuf << " 0.187109 0.093776 0.093776" << "\n";
+ strebuf << " 0.209939 0.093776 0.093776" << "\n";
+ strebuf << "}" << "\n";
+
+ //
+ float from_min = 0.005478f;
+ float from_max = 14.080103f;
+ float to_min = 0.0f;
+ float to_max = 1.0f;
+ float black = 0.0f;
+ float white = 1.0f;
+ float prelut[10] = { 0.994922f, 0.995052f, 0.995181f, 0.995310f, 0.995439f,
+ 0.995568f, 0.995697f, 0.995826f, 0.995954f, 0.996082f };
+ float cube[2 * 2 * 2 * 3 ] = {
+ 0.093776f, 0.093776f, 0.093776f,
+ 0.105219f, 0.093776f, 0.093776f,
+ 0.118058f, 0.093776f, 0.093776f,
+ 0.132463f, 0.093776f, 0.093776f,
+ 0.148626f, 0.093776f, 0.093776f,
+ 0.166761f, 0.093776f, 0.093776f,
+ 0.187109f, 0.093776f, 0.093776f,
+ 0.209939f, 0.093776f, 0.093776f };
+
+ std::istringstream simple3D1D;
+ simple3D1D.str(strebuf.str());
+
+ // Load file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile = tester.Read(simple3D1D);
+ OCIO::CachedFileHDLRcPtr lut = OCIO::DynamicPtrCast<OCIO::CachedFileHDL>(cachedFile);
+
+ //
+ OIIO_CHECK_EQUAL(to_min, lut->to_min);
+ OIIO_CHECK_EQUAL(to_max, lut->to_max);
+ OIIO_CHECK_EQUAL(black, lut->hdlblack);
+ OIIO_CHECK_EQUAL(white, lut->hdlwhite);
+
+ // check prelut data (each channel has the same data)
+ for(int c = 0; c < 3; ++c) {
+ OIIO_CHECK_EQUAL(from_min, lut->lut1D->from_min[c]);
+ OIIO_CHECK_EQUAL(from_max, lut->lut1D->from_max[c]);
+ OIIO_CHECK_EQUAL(10, lut->lut1D->luts[c].size());
+
+ for(unsigned int i = 0; i < lut->lut1D->luts[c].size(); ++i) {
+ OIIO_CHECK_EQUAL(prelut[i], lut->lut1D->luts[c][i]);
+ }
+ }
+
+ OIIO_CHECK_EQUAL(2*2*2*3, lut->lut3D->lut.size());
+
+ // check cube data
+ for(unsigned int i = 0; i < lut->lut3D->lut.size(); ++i) {
+ OIIO_CHECK_EQUAL(cube[i], lut->lut3D->lut[i]);
+ }
+}
+
+OIIO_ADD_TEST(FileFormatHDL, Bake3D1D)
+{
+ // check baker output
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+
+ // Set luma coef's to simple values
+ {
+ float lumaCoef[3] = {0.333f, 0.333f, 0.333f};
+ config->setDefaultLumaCoefs(lumaCoef);
+ }
+
+ // Add lnf space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("lnf");
+ cs->setFamily("lnf");
+ config->addColorSpace(cs);
+ config->setRole(OCIO::ROLE_REFERENCE, cs->getName());
+ }
+
+ // Add shaper space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("shaper");
+ cs->setFamily("shaper");
+ OCIO::ExponentTransformRcPtr transform1 = OCIO::ExponentTransform::Create();
+ float test[4] = {2.6f, 2.6f, 2.6f, 1.0f};
+ transform1->setValue(test);
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_TO_REFERENCE);
+ config->addColorSpace(cs);
+ }
+
+ // Add target space
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("target");
+ cs->setFamily("target");
+ OCIO::CDLTransformRcPtr transform1 = OCIO::CDLTransform::Create();
+
+ // Set saturation to cause channel crosstalk, making a 3D LUT
+ transform1->setSat(0.5f);
+
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+ config->addColorSpace(cs);
+ }
+
+ std::string bout =
+ "Version\t\t3\n"
+ "Format\t\tany\n"
+ "Type\t\t3D+1D\n"
+ "From\t\t0.000000 1.000000\n"
+ "To\t\t0.000000 1.000000\n"
+ "Black\t\t0.000000\n"
+ "White\t\t1.000000\n"
+ "Length\t\t2 10\n"
+ "LUT:\n"
+ "Pre {\n"
+ "\t0.000000\n"
+ "\t0.429520\n"
+ "\t0.560744\n"
+ "\t0.655378\n"
+ "\t0.732057\n"
+ "\t0.797661\n"
+ "\t0.855604\n"
+ "\t0.907865\n"
+ "\t0.955710\n"
+ "\t1.000000\n"
+ "}\n"
+ "3D {\n"
+ "\t0.000000 0.000000 0.000000\n"
+ "\t0.606300 0.106300 0.106300\n"
+ "\t0.357600 0.857600 0.357600\n"
+ "\t0.963900 0.963900 0.463900\n"
+ "\t0.036100 0.036100 0.536100\n"
+ "\t0.642400 0.142400 0.642400\n"
+ "\t0.393700 0.893700 0.893700\n"
+ "\t1.000000 1.000000 1.000000\n"
+ "}\n";
+
+ //
+ OCIO::BakerRcPtr baker = OCIO::Baker::Create();
+ baker->setConfig(config);
+ baker->setFormat("houdini");
+ baker->setInputSpace("lnf");
+ baker->setShaperSpace("shaper");
+ baker->setTargetSpace("target");
+ baker->setShaperSize(10);
+ baker->setCubeSize(2);
+ std::ostringstream output;
+ baker->bake(output);
+
+ //std::cerr << "The LUT: " << std::endl << output.str() << std::endl;
+ //std::cerr << "Expected:" << std::endl << bout << std::endl;
+
+ //
+ std::vector<std::string> osvec;
+ OCIO::pystring::splitlines(output.str(), osvec);
+ std::vector<std::string> resvec;
+ OCIO::pystring::splitlines(bout, resvec);
+ OIIO_CHECK_EQUAL(osvec.size(), resvec.size());
+
+ // TODO: Get this working on osx
+ /*
+ for(unsigned int i = 0; i < std::min(osvec.size(), resvec.size()); ++i)
+ OIIO_CHECK_EQUAL(OCIO::pystring::strip(osvec[i]), OCIO::pystring::strip(resvec[i]));
+ */
+}
+
+#endif // OCIO_BUILD_TESTS
diff --git a/src/core/FileFormatIridasCube.cpp b/src/core/FileFormatIridasCube.cpp
new file mode 100644
index 0000000..6b2a496
--- /dev/null
+++ b/src/core/FileFormatIridasCube.cpp
@@ -0,0 +1,398 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <iterator>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+/*
+
+http://doc.iridas.com/index.php/LUT_Formats
+
+#comments start with '#'
+#title is currently ignored, but it's not an error to enter one
+TITLE "title"
+
+#LUT_1D_SIZE M or
+#LUT_3D_SIZE M
+#where M is the size of the texture
+#a 3D texture has the size M x M x M
+#e.g. LUT_3D_SIZE 16 creates a 16 x 16 x 16 3D texture
+LUT_3D_SIZE 2
+
+#Default input value range (domain) is 0.0 (black) to 1.0 (white)
+#Specify other min/max values to map the cube to any custom input
+#range you wish to use, for example if you're working with HDR data
+DOMAIN_MIN 0.0 0.0 0.0
+DOMAIN_MAX 1.0 1.0 1.0
+
+#for 1D textures, the data is simply a list of floating point values,
+#three per line, in RGB order
+#for 3D textures, the data is also RGB, and ordered in such a way
+#that the red coordinate changes fastest, then the green coordinate,
+#and finally, the blue coordinate changes slowest:
+0.0 0.0 0.0
+1.0 0.0 0.0
+0.0 1.0 0.0
+1.0 1.0 0.0
+0.0 0.0 1.0
+1.0 0.0 1.0
+0.0 1.0 1.0
+1.0 1.0 1.0
+
+#Note that the LUT data is not limited to any particular range
+#and can contain values under 0.0 and over 1.0
+#The processing application might however still clip the
+#output values to the 0.0 - 1.0 range, depending on the internal
+#precision of that application's pipeline
+#IRIDAS applications generally use a floating point pipeline
+#with little or no clipping
+
+
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile () :
+ has1D(false),
+ has3D(false)
+ {
+ lut1D = Lut1D::Create();
+ lut3D = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ bool has1D;
+ bool has3D;
+ Lut1DRcPtr lut1D;
+ Lut3DRcPtr lut3D;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "iridas_cube";
+ info.extension = "cube";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+ // this shouldn't happen
+ if(!istream)
+ {
+ throw Exception ("File stream empty when trying to read Iridas .cube lut");
+ }
+
+ // Parse the file
+ std::vector<float> raw;
+
+ int size3d[] = { 0, 0, 0 };
+ int size1d = 0;
+
+ bool in1d = false;
+ bool in3d = false;
+
+ float domain_min[] = { 0.0f, 0.0f, 0.0f };
+ float domain_max[] = { 1.0f, 1.0f, 1.0f };
+
+ {
+ std::string line;
+ std::vector<std::string> parts;
+ std::vector<float> tmpfloats;
+
+ while(nextline(istream, line))
+ {
+ // All lines starting with '#' are comments
+ if(pystring::startswith(line,"#")) continue;
+
+ // Strip, lowercase, and split the line
+ pystring::split(pystring::lower(pystring::strip(line)), parts);
+ if(parts.empty()) continue;
+
+ if(pystring::lower(parts[0]) == "title")
+ {
+ // Optional, and currently unhandled
+ }
+ else if(pystring::lower(parts[0]) == "lut_1d_size")
+ {
+ if(parts.size() != 2 || !StringToInt( &size1d, parts[1].c_str()))
+ {
+ throw Exception("Malformed LUT_1D_SIZE tag in Iridas .cube lut.");
+ }
+
+ raw.reserve(3*size1d);
+ in1d = true;
+ }
+ else if(pystring::lower(parts[0]) == "lut_2d_size")
+ {
+ throw Exception("Unsupported Iridas .cube lut tag: 'LUT_2D_SIZE'.");
+ }
+ else if(pystring::lower(parts[0]) == "lut_3d_size")
+ {
+ int size = 0;
+
+ if(parts.size() != 2 || !StringToInt( &size, parts[1].c_str()))
+ {
+ throw Exception("Malformed LUT_3D_SIZE tag in Iridas .cube lut.");
+ }
+ size3d[0] = size;
+ size3d[1] = size;
+ size3d[2] = size;
+
+ raw.reserve(3*size3d[0]*size3d[1]*size3d[2]);
+ in3d = true;
+ }
+ else if(pystring::lower(parts[0]) == "domain_min")
+ {
+ if(parts.size() != 4 ||
+ !StringToFloat( &domain_min[0], parts[1].c_str()) ||
+ !StringToFloat( &domain_min[1], parts[2].c_str()) ||
+ !StringToFloat( &domain_min[2], parts[3].c_str()))
+ {
+ throw Exception("Malformed DOMAIN_MIN tag in Iridas .cube lut.");
+ }
+ }
+ else if(pystring::lower(parts[0]) == "domain_max")
+ {
+ if(parts.size() != 4 ||
+ !StringToFloat( &domain_max[0], parts[1].c_str()) ||
+ !StringToFloat( &domain_max[1], parts[2].c_str()) ||
+ !StringToFloat( &domain_max[2], parts[3].c_str()))
+ {
+ throw Exception("Malformed DOMAIN_MAX tag in Iridas .cube lut.");
+ }
+ }
+ else
+ {
+ // It must be a float triple!
+
+ if(!StringVecToFloatVec(tmpfloats, parts) || tmpfloats.size() != 3)
+ {
+ std::ostringstream os;
+ os << "Malformed color triples specified in Iridas .cube lut:";
+ os << "'" << line << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ for(int i=0; i<3; ++i)
+ {
+ raw.push_back(tmpfloats[i]);
+ }
+ }
+ }
+ }
+
+ // Interpret the parsed data, validate lut sizes
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ if(in1d)
+ {
+ if(size1d != static_cast<int>(raw.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in Iridas .cube lut. ";
+ os << "Incorrect number of lut1d entries. ";
+ os << "Found " << raw.size()/3 << ", expected " << size1d << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ // Reformat 1D data
+ if(size1d>0)
+ {
+ cachedFile->has1D = true;
+ memcpy(cachedFile->lut1D->from_min, domain_min, 3*sizeof(float));
+ memcpy(cachedFile->lut1D->from_max, domain_max, 3*sizeof(float));
+
+ for(int channel=0; channel<3; ++channel)
+ {
+ cachedFile->lut1D->luts[channel].resize(size1d);
+ for(int i=0; i<size1d; ++i)
+ {
+ cachedFile->lut1D->luts[channel][i] = raw[3*i+channel];
+ }
+ }
+
+ // 1e-5 rel error is a good threshold when float numbers near 0
+ // are written out with 6 decimal places of precision. This is
+ // a bit aggressive, I.e., changes in the 6th decimal place will
+ // be considered roundoff error, but changes in the 5th decimal
+ // will be considered lut 'intent'.
+ // 1.0
+ // 1.000005 equal to 1.0
+ // 1.000007 equal to 1.0
+ // 1.000010 not equal
+ // 0.0
+ // 0.000001 not equal
+
+ cachedFile->lut1D->maxerror = 1e-5f;
+ cachedFile->lut1D->errortype = ERROR_RELATIVE;
+ }
+ }
+ else if(in3d)
+ {
+ cachedFile->has3D = true;
+
+ if(size3d[0]*size3d[1]*size3d[2] != static_cast<int>(raw.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in Iridas .cube lut. ";
+ os << "Incorrect number of lut3d entries. ";
+ os << "Found " << raw.size()/3 << ", expected " << size3d[0]*size3d[1]*size3d[2] << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ // Reformat 3D data
+ memcpy(cachedFile->lut3D->from_min, domain_min, 3*sizeof(float));
+ memcpy(cachedFile->lut3D->from_max, domain_max, 3*sizeof(float));
+ cachedFile->lut3D->size[0] = size3d[0];
+ cachedFile->lut3D->size[1] = size3d[1];
+ cachedFile->lut3D->size[2] = size3d[2];
+ cachedFile->lut3D->lut = raw;
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Parse error in Iridas .cube lut. ";
+ os << "Lut type (1D/3D) unspecified.";
+ throw Exception(os.str().c_str());
+ }
+
+ return cachedFile;
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build Iridas .cube Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ // TODO: INTERP_LINEAR should not be hard-coded.
+ // Instead query 'highest' interpolation?
+ // (right now, it's linear). If cubic is added, consider
+ // using it
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ if(cachedFile->has1D)
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ INTERP_LINEAR, newDir);
+ }
+ if(cachedFile->has3D)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ if(cachedFile->has3D)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ if(cachedFile->has1D)
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ INTERP_LINEAR, newDir);
+ }
+ }
+ }
+ }
+
+ FileFormat * CreateFileFormatIridasCube()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/FileFormatIridasItx.cpp b/src/core/FileFormatIridasItx.cpp
new file mode 100644
index 0000000..43af60e
--- /dev/null
+++ b/src/core/FileFormatIridasItx.cpp
@@ -0,0 +1,336 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <iterator>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+/*
+
+Iridas itx format
+LUT_3D_SIZE M
+
+#LUT_3D_SIZE M
+#where M is the size of the texture
+#a 3D texture has the size M x M x M
+#e.g. LUT_3D_SIZE 16 creates a 16 x 16 x 16 3D texture
+
+#for 1D textures, the data is simply a list of floating point values,
+#three per line, in RGB order
+#for 3D textures, the data is also RGB, and ordered in such a way
+#that the red coordinate changes fastest, then the green coordinate,
+#and finally, the blue coordinate changes slowest:
+0.0 0.0 0.0
+1.0 0.0 0.0
+0.0 1.0 0.0
+1.0 1.0 0.0
+0.0 0.0 1.0
+1.0 0.0 1.0
+0.0 1.0 1.0
+1.0 1.0 1.0
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile ()
+ {
+ lut3D = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ Lut3DRcPtr lut3D;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "iridas_itx";
+ info.extension = "itx";
+ info.capabilities = (FORMAT_CAPABILITY_READ | FORMAT_CAPABILITY_WRITE);
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+ // this shouldn't happen
+ if(!istream)
+ {
+ throw Exception ("File stream empty when trying to read Iridas .itx lut");
+ }
+
+ // Parse the file
+ std::vector<float> raw;
+
+ int size3d[] = { 0, 0, 0 };
+ bool in3d = false;
+
+ {
+ std::string line;
+ std::vector<std::string> parts;
+ std::vector<float> tmpfloats;
+
+ while(nextline(istream, line))
+ {
+ // All lines starting with '#' are comments
+ if(pystring::startswith(line,"#")) continue;
+
+ // Strip, lowercase, and split the line
+ pystring::split(pystring::lower(pystring::strip(line)), parts);
+ if(parts.empty()) continue;
+
+ if(pystring::lower(parts[0]) == "lut_3d_size")
+ {
+ int size = 0;
+
+ if(parts.size() != 2 || !StringToInt( &size, parts[1].c_str()))
+ {
+ throw Exception("Malformed LUT_3D_SIZE tag in Iridas .itx lut.");
+ }
+ size3d[0] = size;
+ size3d[1] = size;
+ size3d[2] = size;
+
+ raw.reserve(3*size3d[0]*size3d[1]*size3d[2]);
+ in3d = true;
+ }
+ else if(in3d)
+ {
+ // It must be a float triple!
+
+ if(!StringVecToFloatVec(tmpfloats, parts) || tmpfloats.size() != 3)
+ {
+ std::ostringstream os;
+ os << "Malformed color triples specified in Iridas .itx lut:";
+ os << "'" << line << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ for(int i=0; i<3; ++i)
+ {
+ raw.push_back(tmpfloats[i]);
+ }
+ }
+ }
+ }
+
+ // Interpret the parsed data, validate lut sizes
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ if(in3d)
+ {
+ if(size3d[0]*size3d[1]*size3d[2] != static_cast<int>(raw.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in Iridas .itx lut. ";
+ os << "Incorrect number of lut3d entries. ";
+ os << "Found " << raw.size()/3 << ", expected " << size3d[0]*size3d[1]*size3d[2] << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ // Reformat 3D data
+ cachedFile->lut3D->size[0] = size3d[0];
+ cachedFile->lut3D->size[1] = size3d[1];
+ cachedFile->lut3D->size[2] = size3d[2];
+ cachedFile->lut3D->lut = raw;
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Parse error in Iridas .itx lut. ";
+ os << "Lut type (1D/3D) unspecified.";
+ throw Exception(os.str().c_str());
+ }
+
+ return cachedFile;
+ }
+
+ void LocalFileFormat::Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const
+ {
+ int DEFAULT_CUBE_SIZE = 64;
+
+ if(formatName != "iridas_itx")
+ {
+ std::ostringstream os;
+ os << "Unknown 3dl format name, '";
+ os << formatName << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ ConstConfigRcPtr config = baker.getConfig();
+
+ int cubeSize = baker.getCubeSize();
+ if(cubeSize==-1) cubeSize = DEFAULT_CUBE_SIZE;
+ cubeSize = std::max(2, cubeSize); // smallest cube is 2x2x2
+
+ std::vector<float> cubeData;
+ cubeData.resize(cubeSize*cubeSize*cubeSize*3);
+ GenerateIdentityLut3D(&cubeData[0], cubeSize, 3, LUT3DORDER_FAST_RED);
+ PackedImageDesc cubeImg(&cubeData[0], cubeSize*cubeSize*cubeSize, 1, 3);
+
+ // Apply our conversion from the input space to the output space.
+ ConstProcessorRcPtr inputToTarget;
+ std::string looks = baker.getLooks();
+ if (!looks.empty())
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ transform->setLooks(looks.c_str());
+ transform->setSrc(baker.getInputSpace());
+ transform->setDst(baker.getTargetSpace());
+ inputToTarget = config->getProcessor(transform,
+ TRANSFORM_DIR_FORWARD);
+ }
+ else
+ {
+ inputToTarget = config->getProcessor(baker.getInputSpace(),
+ baker.getTargetSpace());
+ }
+ inputToTarget->apply(cubeImg);
+
+ // Write out the file.
+ // For for maximum compatibility with other apps, we will
+ // not utilize the shaper or output any metadata
+
+ ostream << "LUT_3D_SIZE " << cubeSize << "\n";
+ if(cubeSize < 2)
+ {
+ throw Exception("Internal cube size exception.");
+ }
+
+ // Set to a fixed 6 decimal precision
+ ostream.setf(std::ios::fixed, std::ios::floatfield);
+ ostream.precision(6);
+ for(int i=0; i<cubeSize*cubeSize*cubeSize; ++i)
+ {
+ float r = cubeData[3*i+0];
+ float g = cubeData[3*i+1];
+ float b = cubeData[3*i+2];
+ ostream << r << " " << g << " " << b << "\n";
+ }
+ ostream << "\n";
+ }
+
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build Iridas .itx Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ // TODO: INTERP_LINEAR should not be hard-coded.
+ // Instead query 'highest' interpolation?
+ // (right now, it's linear). If cubic is added, consider
+ // using it
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ }
+ }
+
+ FileFormat * CreateFileFormatIridasItx()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/FileFormatIridasLook.cpp b/src/core/FileFormatIridasLook.cpp
new file mode 100644
index 0000000..d53c641
--- /dev/null
+++ b/src/core/FileFormatIridasLook.cpp
@@ -0,0 +1,1356 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <iterator>
+
+#include <tinyxml.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+/*
+
+Iridas .look format
+
+An XML format containing <shaders>, a series of layers describing the
+operations and their parameters (irrelevant to us in this context).
+
+This series of shaders is baked into the <LUT> section.
+
+<?xml version="1.0" ?>
+<look>
+ <shaders>
+ # anything in here is useless to us
+ </shaders>
+ <LUT>
+ <size>"8"</size> # Size of 3D LUT
+ <data>"
+ 0000008000000080000000802CF52E3D2DF52E3D2DF52E3D2CF5AE3D2DF5AE3D
+ # ...cut...
+ 5A216A3F5A216A3FAD10753FAD10753FAD10753F0000803F0000803F0000803F"
+ </data>
+ </LUT>
+</look>
+
+The LUT data contains a 3D LUT, as a hex-encoded series of 32-bit
+floats, with little-endian bit-ordering. LUT value ordering is
+LUT3DORDER_FAST_RED (red index incrementing fastest, then green, then
+blue)
+
+The LUT data is parsed by removing all whitespace and quotes. Taking 8
+characters at a time and intepreting as little-endian float, as follows:
+
+Given the string "0000003F0000803FAD10753F":
+
+ >>> import binascii, struct
+ >>> struct.unpack("<f", binascii.unhexlify("0000003F"))[0]
+ 0.5
+ >>> struct.unpack("<f", binascii.unhexlify("0000803F"))[0]
+ 1.0
+ >>> struct.unpack("<f", binascii.unhexlify("AD10753F"))[0]
+ 0.9572857022285461
+
+ */
+
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ // convert hex ascii to int
+ // return true on success, false on failure
+ bool hexasciitoint(char& ival, char character)
+ {
+ if(character>=48 && character<=57) // [0-9]
+ {
+ ival = static_cast<char>(character-48);
+ return true;
+ }
+ else if(character>=65 && character<=70) // [A-F]
+ {
+ ival = static_cast<char>(10+character-65);
+ return true;
+ }
+ else if(character>=97 && character<=102) // [a-f]
+ {
+ ival = static_cast<char>(10+character-97);
+ return true;
+ }
+
+ ival = 0;
+ return false;
+ }
+
+ // convert array of 8 hex ascii to f32
+ // The input hexascii is required to be a little-endian representation
+ // as used in the iridas file format
+ // "AD10753F" -> 0.9572857022285461f on ALL architectures
+
+ bool hexasciitofloat(float& fval, const char * ascii)
+ {
+ // Convert all ASCII numbers to their numerical representations
+ char asciinums[8];
+ for(unsigned int i=0; i<8; ++i)
+ {
+ if(!hexasciitoint(asciinums[i], ascii[i]))
+ {
+ return false;
+ }
+ }
+
+ unsigned char * fvalbytes = reinterpret_cast<unsigned char *>(&fval);
+
+#if OCIO_LITTLE_ENDIAN
+ // Since incoming values are little endian, and we're on little endian
+ // preserve the byte order
+ fvalbytes[0] = (unsigned char) (asciinums[1] | (asciinums[0] << 4));
+ fvalbytes[1] = (unsigned char) (asciinums[3] | (asciinums[2] << 4));
+ fvalbytes[2] = (unsigned char) (asciinums[5] | (asciinums[4] << 4));
+ fvalbytes[3] = (unsigned char) (asciinums[7] | (asciinums[6] << 4));
+#else
+ // Since incoming values are little endian, and we're on big endian
+ // flip the byte order
+ fvalbytes[3] = (unsigned char) (asciinums[1] | (asciinums[0] << 4));
+ fvalbytes[2] = (unsigned char) (asciinums[3] | (asciinums[2] << 4));
+ fvalbytes[1] = (unsigned char) (asciinums[5] | (asciinums[4] << 4));
+ fvalbytes[0] = (unsigned char) (asciinums[7] | (asciinums[6] << 4));
+#endif
+ return true;
+ }
+ }
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile ()
+ {
+ lut3D = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ Lut3DRcPtr lut3D;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+ typedef OCIO_SHARED_PTR<TiXmlDocument> TiXmlDocumentRcPtr;
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "iridas_look";
+ info.extension = "look";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+
+ // Get root element from XML file
+ TiXmlDocumentRcPtr doc;
+ TiXmlElement* rootElement;
+
+ {
+ std::ostringstream rawdata;
+ rawdata << istream.rdbuf();
+
+ doc = TiXmlDocumentRcPtr(new TiXmlDocument());
+ doc->Parse(rawdata.str().c_str());
+
+ if(doc->Error())
+ {
+ std::ostringstream os;
+ os << "XML Parse Error. ";
+ os << doc->ErrorDesc() << " (line ";
+ os << doc->ErrorRow() << ", character ";
+ os << doc->ErrorCol() << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ // Check for blank file
+ rootElement = doc->RootElement();
+ if(!rootElement)
+ {
+ std::ostringstream os;
+ os << "Error loading xml. Null root element.";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ // Check root element is <look>
+ if(std::string(rootElement->Value()) != "look")
+ {
+ std::ostringstream os;
+ os << "Error loading .look LUT. ";
+ os << "Root element is type '" << rootElement->Value() << "', ";
+ os << "expected 'look'.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Fail to load file if it contains a <mask> section
+ if(rootElement->FirstChild("mask") && rootElement->FirstChild("mask")->FirstChild())
+ {
+ // If root element contains "mask" child, and it is
+ // not empty, throw exception
+ std::ostringstream os;
+ os << "Cannot load .look LUT containing mask";
+ throw Exception(os.str().c_str());
+ }
+
+ // Get <LUT> section
+
+ // TODO: There is a LUT1D section in some .look files,
+ // which we could use if available. Need to check
+ // assumption that it is only written for 1D transforms,
+ // and it matches the desired output
+ TiXmlNode* lutsection = rootElement->FirstChild("LUT");
+
+ if(!lutsection)
+ {
+ std::ostringstream os;
+ os << "Error loading .look LUT. ";
+ os << "Could not find required 'LUT' section.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Get 3D LUT size
+ int size_3d = -1;
+
+ {
+ // Get size from <look><LUT><size>'123'</size></LUT></look>
+ TiXmlNode* elemsize = lutsection->FirstChild("size");
+ if(!elemsize)
+ {
+ std::ostringstream os;
+ os << "Error loading .look LUT. ";
+ os << "LUT section did not contain 'size'.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string size_raw = std::string(elemsize->ToElement()->GetText());
+ std::string size_clean = pystring::strip(size_raw, "'\" "); // strip quotes and space
+
+ char* endptr = 0;
+ size_3d = static_cast<int>(strtol(size_clean.c_str(), &endptr, 10));
+
+ if(*endptr)
+ {
+ // strtol didn't consume entire string, there was
+ // remaining data, thus did not contain a single interger
+ std::ostringstream os;
+ os << "Invalid LUT size value: '" << size_raw;
+ os << "'. Expected quoted integer.";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ // Grab raw 3D data
+ std::vector<float> raw;
+ {
+ TiXmlNode* dataelem = lutsection->FirstChild("data");
+ if(!dataelem)
+ {
+ std::ostringstream os;
+ os << "Error loading .look LUT. ";
+ os << "LUT section did not contain 'data'.";
+ throw Exception(os.str().c_str());
+ }
+
+ raw.reserve(3*(size_3d*size_3d*size_3d));
+
+ std::string what = dataelem->ToElement()->GetText();
+
+ // Remove spaces, quotes and newlines
+ what = pystring::replace(what, " ", "");
+ what = pystring::replace(what, "\"", "");
+ what = pystring::replace(what, "'", "");
+ what = pystring::replace(what, "\n", "");
+
+ if(what.size() % 8 != 0)
+ {
+ std::ostringstream os;
+ os << "Error loading .look LUT. ";
+ os << "Number of characters in 'data' must be multiple of 8. ";
+ os << what.size() << " elements found.";
+ throw Exception(os.str().c_str());
+ }
+
+ const char * ascii = what.c_str();
+ float fval = 0.0f;
+ for(unsigned int i=0; i<what.size()/8; ++i)
+ {
+ if(!hexasciitofloat(fval, &ascii[8*i]))
+ {
+ std::ostringstream os;
+ os << "Error loading .look LUT. ";
+ os << "Non-hex characters found in 'data' block ";
+ os << "at index '" << (8*i) << "'.";
+ throw Exception(os.str().c_str());
+ }
+ raw.push_back(fval);
+ }
+ }
+
+
+ // Validate LUT sizes, and create cached file object
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ if((size_3d*size_3d*size_3d)*3 != static_cast<int>(raw.size()))
+ {
+ std::ostringstream os;
+ os << "Parse error in Iridas .look lut. ";
+ os << "Incorrect number of lut3d entries. ";
+ os << "Found " << raw.size() << " values, expected " << (size_3d*size_3d*size_3d)*3 << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ // Reformat 3D data
+ cachedFile->lut3D->size[0] = size_3d;
+ cachedFile->lut3D->size[1] = size_3d;
+ cachedFile->lut3D->size[2] = size_3d;
+ cachedFile->lut3D->lut = raw;
+
+ return cachedFile;
+ }
+
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build Iridas .look Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatIridasLook()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+#include "UnitTest.h"
+
+OCIO_NAMESPACE_USING
+
+
+
+OIIO_ADD_TEST(FileFormatIridasLook, hexasciitoint)
+{
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, 'a');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 10);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, 'A');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 10);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, 'f');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 15);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, 'F');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 15);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, '0');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 0);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, '0');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 0);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, '9');
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(ival, 9);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, '\n');
+ OIIO_CHECK_EQUAL(success, false);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, 'j');
+ OIIO_CHECK_EQUAL(success, false);
+ }
+
+ {
+ char ival = 0;
+ bool success = hexasciitoint(ival, 'x');
+ OIIO_CHECK_EQUAL(success, false);
+ }
+}
+
+
+OIIO_ADD_TEST(FileFormatIridasLook, hexasciitofloat)
+{
+ //>>> import binascii, struct
+ //>> struct.unpack("<f", binascii.unhexlify("AD10753F"))[0]
+ //0.9572857022285461
+
+ {
+ float fval = 0.0f;
+ bool success = hexasciitofloat(fval, "0000003F");
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(fval, 0.5f);
+ }
+
+ {
+ float fval = 0.0f;
+ bool success = hexasciitofloat(fval, "0000803F");
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(fval, 1.0f);
+ }
+
+ {
+ float fval = 0.0f;
+ bool success = hexasciitofloat(fval, "AD10753F");
+ OIIO_CHECK_EQUAL(success, true); OIIO_CHECK_EQUAL(fval, 0.9572857022285461f);
+ }
+
+ {
+ float fval = 0.0f;
+ bool success = hexasciitofloat(fval, "AD10X53F");
+ OIIO_CHECK_EQUAL(success, false);
+ }
+}
+
+
+OIIO_ADD_TEST(FileFormatIridasLook, simple3d)
+{
+ std::ostringstream strebuf;
+ strebuf << "<?xml version=\"1.0\" ?>" << "\n";
+ strebuf << "<look>" << "\n";
+ strebuf << " <shaders>" << "\n";
+ strebuf << " <base>" << "\n";
+ strebuf << " <visible>\"1\"</visible>" << "\n";
+ strebuf << " <sublayer0>" << "\n";
+ strebuf << " <opacity>\"1\"</opacity>" << "\n";
+ strebuf << " <parameters>" << "\n";
+ strebuf << " <Secondary1>\"1\"</Secondary1>" << "\n";
+ strebuf << " <Secondary5>\"0\"</Secondary5>" << "\n";
+ strebuf << " <Secondary4>\"0\"</Secondary4>" << "\n";
+ strebuf << " <Secondary2>\"0\"</Secondary2>" << "\n";
+ strebuf << " <Secondary6>\"0\"</Secondary6>" << "\n";
+ strebuf << " <Secondary3>\"0\"</Secondary3>" << "\n";
+ strebuf << " <Blur>\"0\"</Blur>" << "\n";
+ strebuf << " <saturation>\"0\"</saturation>" << "\n";
+ strebuf << " </parameters>" << "\n";
+ strebuf << " </sublayer0>" << "\n";
+ strebuf << " </base>" << "\n";
+ strebuf << " </shaders>" << "\n";
+ strebuf << " <LUT>" << "\n";
+ strebuf << " <size>\"8\"</size>" << "\n";
+ strebuf << " <data>\"" << "\n";
+ strebuf << " 0000008000000080000000802CF52E3D2DF52E3D2DF52E3D2CF5AE3D2DF5AE3D" << "\n";
+ strebuf << " 2DF5AE3DE237033EE237033EE237033E2CF52E3E2DF52E3E2DF52E3E78B25A3E" << "\n";
+ strebuf << " 78B25A3E78B25A3EE037833EE137833EE137833E8616993E8716993E8716993E" << "\n";
+ strebuf << " 4BBDAB3D4BBDAB3D4BBDAB3DF09B013EF09B013EF09B013E3C592D3E3C592D3E" << "\n";
+ strebuf << " 3C592D3E8716593E8716593E8716593EE969823EE969823EE969823E8E48983E" << "\n";
+ strebuf << " 8E48983E8E48983E3227AE3E3327AE3E3327AE3ED805C43ED905C43ED905C43E" << "\n";
+ strebuf << " 4BBD2B3E4BBD2B3E4BBD2B3E967A573E967A573E967A573EF09B813EF09B813E" << "\n";
+ strebuf << " F09B813E967A973E967A973E967A973E3C59AD3E3C59AD3E3C59AD3EE137C33E" << "\n";
+ strebuf << " E137C33EE137C33E8616D93E8616D93E8616D93E2CF5EE3E2CF5EE3E2CF5EE3E" << "\n";
+ strebuf << " F9CD803EF9CD803EF9CD803E9EAC963E9EAC963E9EAC963E448BAC3E448BAC3E" << "\n";
+ strebuf << " 448BAC3EEA69C23EEA69C23EEA69C23E8F48D83E8F48D83E8F48D83E3527EE3E" << "\n";
+ strebuf << " 3527EE3E3527EE3EED02023FED02023FED02023F40F20C3F40F20C3F40F20C3F" << "\n";
+ strebuf << " 4BBDAB3E4BBDAB3E4BBDAB3EF09BC13EF09BC13EF09BC13E967AD73E967AD73E" << "\n";
+ strebuf << " 967AD73E3C59ED3E3C59ED3E3C59ED3EF09B013FF09B013FF09B013F438B0C3F" << "\n";
+ strebuf << " 438B0C3F438B0C3F967A173F967A173F967A173FE969223FE969223FE969223F" << "\n";
+ strebuf << " 9EACD63E9EACD63E9EACD63E428BEC3E438BEC3E438BEC3EF434013FF434013F" << "\n";
+ strebuf << " F434013F47240C3F47240C3F47240C3F9A13173F9A13173F9A13173FED02223F" << "\n";
+ strebuf << " ED02223FED02223F3FF22C3F3FF22C3F3FF22C3F92E1373F92E1373F92E1373F" << "\n";
+ strebuf << " F8CD003FF8CD003FF8CD003F49BD0B3F4ABD0B3F4ABD0B3F9DAC163F9DAC163F" << "\n";
+ strebuf << " 9DAC163FF09B213FF09B213FF09B213F438B2C3F438B2C3F438B2C3F967A373F" << "\n";
+ strebuf << " 967A373F967A373FE869423FE869423FE869423F3B594D3F3B594D3F3B594D3F" << "\n";
+ strebuf << " A245163FA245163FA245163FF334213FF434213FF434213F47242C3F47242C3F" << "\n";
+ strebuf << " 47242C3F9A13373F9A13373F9A13373FED02423FED02423FED02423F40F24C3F" << "\n";
+ strebuf << " 40F24C3F40F24C3F92E1573F92E1573F92E1573FE5D0623FE5D0623FE5D0623F" << "\n";
+ strebuf << " 9E69853C9E69853C9869853CFCA9713DFCA9713DFCA9713D944FD03D944FD03D" << "\n";
+ strebuf << " 944FD03D14E5133E15E5133E15E5133E60A23F3E60A23F3E60A23F3EAA5F6B3E" << "\n";
+ strebuf << " AB5F6B3EAB5F6B3E7A8E8B3E7A8E8B3E7A8E8B3E206DA13E206DA13E206DA13E" << "\n";
+ strebuf << " B217CD3DB217CD3DB217CD3D2449123E2449123E2449123E6F063E3E6F063E3E" << "\n";
+ strebuf << " 6F063E3EBAC3693EBAC3693EBAC3693E82C08A3E82C08A3E82C08A3E289FA03E" << "\n";
+ strebuf << " 289FA03E289FA03ECC7DB63ECC7DB63ECC7DB63E725CCC3E715CCC3E715CCC3E" << "\n";
+ strebuf << " 7E6A3C3E7E6A3C3E7E6A3C3ECA27683ECA27683ECA27683E8AF2893E8AF2893E" << "\n";
+ strebuf << " 8AF2893E30D19F3E30D19F3E30D19F3ED5AFB53ED5AFB53ED5AFB53E7B8ECB3E" << "\n";
+ strebuf << " 7B8ECB3E7A8ECB3E1F6DE13E1F6DE13E1E6DE13EC44BF73EC54BF73EC44BF73E" << "\n";
+ strebuf << " 9224893E9224893E9224893E38039F3E38039F3E38039F3EDEE1B43EDEE1B43E" << "\n";
+ strebuf << " DEE1B43E83C0CA3E83C0CA3E82C0CA3E299FE03E299FE03E289FE03ECE7DF63E" << "\n";
+ strebuf << " CE7DF63ECD7DF63E392E063F392E063F382E063F8C1D113F8C1D113F8B1D113F" << "\n";
+ strebuf << " E413B43EE413B43EE413B43E89F2C93E8AF2C93E89F2C93E30D1DF3E30D1DF3E" << "\n";
+ strebuf << " 2FD1DF3ED5AFF53ED5AFF53ED4AFF53E3DC7053F3DC7053F3CC7053F90B6103F" << "\n";
+ strebuf << " 90B6103F8FB6103FE2A51B3FE2A51B3FE1A51B3F3595263F3595263F3495263F" << "\n";
+ strebuf << " 3703DF3E3703DF3E3603DF3EDCE1F43EDDE1F43EDCE1F43E4160053F4160053F" << "\n";
+ strebuf << " 4060053F944F103F944F103F934F103FE73E1B3FE73E1B3FE63E1B3F392E263F" << "\n";
+ strebuf << " 392E263F382E263F8C1D313F8C1D313F8B1D313FDF0C3C3FDF0C3C3FDE0C3C3F" << "\n";
+ strebuf << " 44F9043F44F9043F43F9043F96E80F3F97E80F3F96E80F3FEAD71A3FEAD71A3F" << "\n";
+ strebuf << " E9D71A3F3DC7253F3DC7253F3CC7253F90B6303F90B6303F8FB6303FE2A53B3F" << "\n";
+ strebuf << " E2A53B3FE1A53B3F3595463F3595463F3495463F8884513F8884513F8784513F" << "\n";
+ strebuf << " EE701A3FEE701A3FED701A3F4060253F4160253F4060253F944F303F944F303F" << "\n";
+ strebuf << " 934F303FE73E3B3FE73E3B3FE63E3B3F3A2E463F3A2E463F392E463F8C1D513F" << "\n";
+ strebuf << " 8C1D513F8B1D513FDF0C5C3FDF0C5C3FDE0C5C3F32FC663F32FC663F31FC663F" << "\n";
+ strebuf << " 9E69053D9E69053D9869053D652F9A3D652F9A3D642F9A3DFCA9F13DFCA9F13D" << "\n";
+ strebuf << " FCA9F13D4892243E4992243E4992243E944F503E944F503E944F503EDE0C7C3E" << "\n";
+ strebuf << " DF0C7C3EDF0C7C3E14E5933E14E5933E14E5933EBAC3A93EBAC3A93EBAC3A93E" << "\n";
+ strebuf << " 1A72EE3D1A72EE3D1A72EE3D58F6223E58F6223E58F6223EA3B34E3EA3B34E3E" << "\n";
+ strebuf << " A3B34E3EEE707A3EEE707A3EEE707A3E1C17933E1C17933E1C17933EC2F5A83E" << "\n";
+ strebuf << " C2F5A83EC2F5A83E66D4BE3E66D4BE3E66D4BE3E0CB3D43E0BB3D43E0CB3D43E" << "\n";
+ strebuf << " B2174D3EB2174D3EB2174D3EFDD4783EFDD4783EFDD4783E2449923E2449923E" << "\n";
+ strebuf << " 2449923ECA27A83ECA27A83ECA27A83E6F06BE3E6F06BE3E6F06BE3E15E5D33E" << "\n";
+ strebuf << " 15E5D33E15E5D33EB9C3E93EB9C3E93EB9C3E93E5EA2FF3E5FA2FF3E5FA2FF3E" << "\n";
+ strebuf << " 2C7B913E2C7B913E2C7B913ED259A73ED259A73ED259A73E7838BD3E7838BD3E" << "\n";
+ strebuf << " 7838BD3E1D17D33E1D17D33E1D17D33EC3F5E83EC3F5E83EC3F5E83E68D4FE3E" << "\n";
+ strebuf << " 68D4FE3E68D4FE3E86590A3F86590A3F86590A3FD948153FD948153FD948153F" << "\n";
+ strebuf << " 7E6ABC3E7E6ABC3E7E6ABC3E2349D23E2449D23E2449D23ECA27E83ECA27E83E" << "\n";
+ strebuf << " CA27E83E6F06FE3E6F06FE3E6F06FE3E8AF2093F8AF2093F8AF2093FDDE1143F" << "\n";
+ strebuf << " DDE1143FDDE1143F2FD11F3F2FD11F3F2FD11F3F82C02A3F82C02A3F82C02A3F" << "\n";
+ strebuf << " D159E73ED159E73ED159E73E7638FD3E7738FD3E7738FD3E8E8B093F8E8B093F" << "\n";
+ strebuf << " 8E8B093FE17A143FE17A143FE17A143F346A1F3F346A1F3F346A1F3F86592A3F" << "\n";
+ strebuf << " 86592A3F86592A3FD948353FD948353FD948353F2C38403F2C38403F2C38403F" << "\n";
+ strebuf << " 9124093F9124093F9124093FE313143FE413143FE413143F37031F3F37031F3F" << "\n";
+ strebuf << " 37031F3F8AF2293F8AF2293F8AF2293FDDE1343FDDE1343FDDE1343F2FD13F3F" << "\n";
+ strebuf << " 2FD13F3F2FD13F3F82C04A3F82C04A3F81C04A3FD5AF553FD5AF553FD4AF553F" << "\n";
+ strebuf << " 3B9C1E3F3B9C1E3F3B9C1E3F8D8B293F8E8B293F8E8B293FE17A343FE17A343F" << "\n";
+ strebuf << " E17A343F346A3F3F346A3F3F346A3F3F87594A3F87594A3F86594A3FD948553F" << "\n";
+ strebuf << " D948553FD848553F2C38603F2C38603F2B38603F7F276B3F7F276B3F7E276B3F" << "\n";
+ strebuf << " 6E1E483D6E1E483D681E483DCD89BB3DCD89BB3DCC89BB3D3282093E3282093E" << "\n";
+ strebuf << " 3282093E7C3F353E7D3F353E7C3F353EC8FC603EC8FC603EC8FC603E095D863E" << "\n";
+ strebuf << " 095D863E095D863EAE3B9C3EAE3B9C3EAE3B9C3E541AB23E541AB23E541AB23E" << "\n";
+ strebuf << " 41E6073E41E6073E40E6073E8CA3333E8CA3333E8CA3333ED7605F3ED7605F3E" << "\n";
+ strebuf << " D7605F3E118F853E118F853E118F853EB66D9B3EB66D9B3EB66D9B3E5B4CB13E" << "\n";
+ strebuf << " 5B4CB13E5B4CB13E002BC73E002BC73E002BC73EA609DD3EA509DD3EA609DD3E" << "\n";
+ strebuf << " E6C45D3EE6C45D3EE6C45D3E18C1843E18C1843E18C1843EBE9F9A3EBE9F9A3E" << "\n";
+ strebuf << " BE9F9A3E647EB03E647EB03E647EB03E095DC63E095DC63E095DC63EAE3BDC3E" << "\n";
+ strebuf << " AE3BDC3EAE3BDC3E531AF23E531AF23E531AF23E7CFC033F7CFC033F7CFC033F" << "\n";
+ strebuf << " C6D1993EC6D1993EC6D1993E6CB0AF3E6CB0AF3E6CB0AF3E128FC53E128FC53E" << "\n";
+ strebuf << " 128FC53EB76DDB3EB76DDB3EB76DDB3E5D4CF13E5D4CF13E5D4CF13E8195033F" << "\n";
+ strebuf << " 8195033F8195033FD3840E3FD3840E3FD3840E3F2674193F2674193F2674193F" << "\n";
+ strebuf << " 18C1C43E18C1C43E18C1C43EBD9FDA3EBE9FDA3EBE9FDA3E647EF03E647EF03E" << "\n";
+ strebuf << " 647EF03E842E033F842E033F842E033FD71D0E3FD71D0E3FD71D0E3F2A0D193F" << "\n";
+ strebuf << " 2A0D193F2A0D193F7CFC233F7CFC233F7CFC233FCFEB2E3FCFEB2E3FCFEB2E3F" << "\n";
+ strebuf << " 6BB0EF3E6BB0EF3E6BB0EF3E87C7023F88C7023F88C7023FDBB60D3FDBB60D3F" << "\n";
+ strebuf << " DBB60D3F2EA6183F2EA6183F2EA6183F8195233F8195233F8195233FD3842E3F" << "\n";
+ strebuf << " D3842E3FD3842E3F2674393F2674393F2674393F7963443F7963443F7963443F" << "\n";
+ strebuf << " DE4F0D3FDE4F0D3FDE4F0D3F303F183F313F183F313F183F842E233F842E233F" << "\n";
+ strebuf << " 842E233FD71D2E3FD71D2E3FD71D2E3F2A0D393F2A0D393F2A0D393F7CFC433F" << "\n";
+ strebuf << " 7CFC433F7CFC433FCFEB4E3FCFEB4E3FCFEB4E3F22DB593F22DB593F22DB593F" << "\n";
+ strebuf << " 88C7223F88C7223F88C7223FDAB62D3FDBB62D3FDBB62D3F2EA6383F2EA6383F" << "\n";
+ strebuf << " 2EA6383F8195433F8195433F8195433FD4844E3FD4844E3FD4844E3F2674593F" << "\n";
+ strebuf << " 2674593F2674593F7963643F7963643F7963643FCC526F3FCC526F3FCC526F3F" << "\n";
+ strebuf << " 9E69853D9E69853D9869853D34E4DC3D34E4DC3D34E4DC3D652F1A3E652F1A3E" << "\n";
+ strebuf << " 642F1A3EB1EC453EB1EC453EB0EC453EFCA9713EFCA9713EFCA9713EA3B38E3E" << "\n";
+ strebuf << " A3B38E3EA3B38E3E4892A43E4892A43E4892A43EEE70BA3EEE70BA3EEE70BA3E" << "\n";
+ strebuf << " 7493183E7493183E7493183EBF50443EBF50443EBE50443E0A0E703E0A0E703E" << "\n";
+ strebuf << " 0A0E703EABE58D3EABE58D3EABE58D3E50C4A33E50C4A33E50C4A33EF5A2B93E" << "\n";
+ strebuf << " F5A2B93EF5A2B93E9A81CF3E9981CF3E9A81CF3E4060E53E3F60E53E4060E53E" << "\n";
+ strebuf << " 1A726E3E1A726E3E1A726E3EB2178D3EB2178D3EB2178D3E58F6A23E58F6A23E" << "\n";
+ strebuf << " 58F6A23EFED4B83EFED4B83EFED4B83EA3B3CE3EA3B3CE3EA3B3CE3E4892E43E" << "\n";
+ strebuf << " 4892E43E4892E43EED70FA3EED70FA3EED70FA3EC927083FC927083FC927083F" << "\n";
+ strebuf << " 6028A23E6028A23E6028A23E0607B83E0607B83E0607B83EABE5CD3EABE5CD3E" << "\n";
+ strebuf << " ABE5CD3E51C4E33E51C4E33E51C4E33EF7A2F93EF7A2F93EF7A2F93ECEC0073F" << "\n";
+ strebuf << " CEC0073FCEC0073F20B0123F20B0123F20B0123F739F1D3F739F1D3F739F1D3F" << "\n";
+ strebuf << " B217CD3EB217CD3EB217CD3E57F6E23E58F6E23E58F6E23EFDD4F83EFDD4F83E" << "\n";
+ strebuf << " FDD4F83ED159073FD159073FD159073F2449123F2449123F2449123F77381D3F" << "\n";
+ strebuf << " 77381D3F77381D3FC927283FC927283FC927283F1C17333F1C17333F1C17333F" << "\n";
+ strebuf << " 0507F83E0507F83E0507F83ED4F2063FD5F2063FD5F2063F28E2113F28E2113F" << "\n";
+ strebuf << " 28E2113F7BD11C3F7BD11C3F7BD11C3FCEC0273FCEC0273FCEC0273F20B0323F" << "\n";
+ strebuf << " 20B0323F20B0323F739F3D3F739F3D3F739F3D3FC68E483FC68E483FC68E483F" << "\n";
+ strebuf << " 2B7B113F2B7B113F2B7B113F7D6A1C3F7E6A1C3F7E6A1C3FD159273FD159273F" << "\n";
+ strebuf << " D159273F2449323F2449323F2449323F77383D3F77383D3F77383D3FC927483F" << "\n";
+ strebuf << " C927483FC927483F1C17533F1C17533F1C17533F6F065E3F6F065E3F6F065E3F" << "\n";
+ strebuf << " D5F2263FD5F2263FD5F2263F27E2313F28E2313F28E2313F7BD13C3F7BD13C3F" << "\n";
+ strebuf << " 7BD13C3FCEC0473FCEC0473FCEC0473F21B0523F21B0523F21B0523F739F5D3F" << "\n";
+ strebuf << " 739F5D3F739F5D3FC68E683FC68E683FC68E683F197E733F197E733F197E733F" << "\n";
+ strebuf << " 06C4A63D06C4A63D00C4A63D9C3EFE3D9C3EFE3D983EFE3D99DC2A3E99DC2A3E" << "\n";
+ strebuf << " 98DC2A3EE599563EE599563EE499563E982B813E982B813E982B813E3D0A973E" << "\n";
+ strebuf << " 3D0A973E3D0A973EE2E8AC3EE2E8AC3EE2E8AC3E88C7C23E88C7C23E88C7C23E" << "\n";
+ strebuf << " A840293EA840293EA840293EF3FD543EF3FD543EF0FD543E9F5D803E9F5D803E" << "\n";
+ strebuf << " 9F5D803E453C963E453C963E453C963EEA1AAC3EEA1AAC3EEA1AAC3E8FF9C13E" << "\n";
+ strebuf << " 8FF9C13E8FF9C13E34D8D73E33D8D73E34D8D73EDAB6ED3ED9B6ED3EDAB6ED3E" << "\n";
+ strebuf << " 4E1F7F3E4E1F7F3E4E1F7F3E4C6E953E4C6E953E4C6E953EF24CAB3EF24CAB3E" << "\n";
+ strebuf << " F24CAB3E982BC13E982BC13E982BC13E3D0AD73E3D0AD73E3D0AD73EE2E8EC3E" << "\n";
+ strebuf << " E2E8EC3EE2E8EC3EC363013FC363013FC363013F16530C3F16530C3F16530C3F" << "\n";
+ strebuf << " FA7EAA3EFA7EAA3EFA7EAA3EA05DC03EA05DC03EA05DC03E453CD63E453CD63E" << "\n";
+ strebuf << " 453CD63EEB1AEC3EEB1AEC3EEB1AEC3EC8FC003FC8FC003FC8FC003F1BEC0B3F" << "\n";
+ strebuf << " 1BEC0B3F1BEC0B3F6DDB163F6DDB163F6DDB163FC0CA213FC0CA213FC0CA213F" << "\n";
+ strebuf << " 4C6ED53E4C6ED53E4C6ED53EF14CEB3EF24CEB3EF24CEB3ECB95003FCB95003F" << "\n";
+ strebuf << " CB95003F1E850B3F1E850B3F1E850B3F7174163F7174163F7174163FC463213F" << "\n";
+ strebuf << " C463213FC463213F16532C3F16532C3F16532C3F6942373F6942373F6942373F" << "\n";
+ strebuf << " CF2E003FCF2E003FCF2E003F211E0B3F221E0B3F221E0B3F750D163F750D163F" << "\n";
+ strebuf << " 750D163FC8FC203FC8FC203FC8FC203F1BEC2B3F1BEC2B3F1BEC2B3F6DDB363F" << "\n";
+ strebuf << " 6DDB363F6DDB363FC0CA413FC0CA413FC0CA413F13BA4C3F13BA4C3F13BA4C3F" << "\n";
+ strebuf << " 78A6153F78A6153F78A6153FCA95203FCB95203FCB95203F1E852B3F1E852B3F" << "\n";
+ strebuf << " 1E852B3F7174363F7174363F7174363FC463413FC463413FC463413F16534C3F" << "\n";
+ strebuf << " 16534C3F16534C3F6942573F6942573F6942573FBC31623FBC31623FBC31623F" << "\n";
+ strebuf << " 221E2B3F221E2B3F221E2B3F740D363F750D363F750D363FC8FC403FC8FC403F" << "\n";
+ strebuf << " C8FC403F1BEC4B3F1BEC4B3F1BEC4B3F6EDB563F6EDB563F6EDB563FC0CA613F" << "\n";
+ strebuf << " C0CA613FC0CA613F13BA6C3F13BA6C3F13BA6C3F66A9773F66A9773F66A9773F" << "\n";
+ strebuf << " 6D1EC83D6D1EC83D681EC83D81CC0F3E81CC0F3E80CC0F3ECD893B3ECD893B3E" << "\n";
+ strebuf << " CC893B3E1847673E1847673E1847673E3182893E3182893E3082893ED7609F3E" << "\n";
+ strebuf << " D7609F3ED6609F3E7C3FB53E7C3FB53E7C3FB53E221ECB3E221ECB3E221ECB3E" << "\n";
+ strebuf << " DCED393EDCED393EDCED393E26AB653E26AB653E24AB653E39B4883E39B4883E" << "\n";
+ strebuf << " 38B4883EDE929E3EDE929E3EDE929E3E8371B43E8371B43E8271B43E2950CA3E" << "\n";
+ strebuf << " 2850CA3E2950CA3ECE2EE03ECD2EE03ECE2EE03E740DF63E730DF63E740DF63E" << "\n";
+ strebuf << " 40E6873E40E6873E40E6873EE6C49D3EE6C49D3EE6C49D3E8CA3B33E8CA3B33E" << "\n";
+ strebuf << " 8CA3B33E3182C93E3182C93E3182C93ED660DF3ED660DF3ED660DF3E7C3FF53E" << "\n";
+ strebuf << " 7C3FF53E7C3FF53E108F053F108F053F108F053F637E103F637E103F637E103F" << "\n";
+ strebuf << " 94D5B23E94D5B23E94D5B23E39B4C83E39B4C83E39B4C83EDF92DE3EDF92DE3E" << "\n";
+ strebuf << " DF92DE3E8571F43E8571F43E8571F43E1528053F1528053F1528053F6817103F" << "\n";
+ strebuf << " 6817103F6817103FBA061B3FBA061B3FBA061B3F0DF6253F0DF6253F0DF6253F" << "\n";
+ strebuf << " E6C4DD3EE6C4DD3EE6C4DD3E8AA3F33E8BA3F33E8BA3F33E18C1043F18C1043F" << "\n";
+ strebuf << " 18C1043F6BB00F3F6BB00F3F6BB00F3FBE9F1A3FBE9F1A3FBE9F1A3F118F253F" << "\n";
+ strebuf << " 118F253F118F253F637E303F637E303F637E303FB66D3B3FB66D3B3FB66D3B3F" << "\n";
+ strebuf << " 1C5A043F1C5A043F1C5A043F6E490F3F6F490F3F6F490F3FC2381A3FC2381A3F" << "\n";
+ strebuf << " C2381A3F1528253F1528253F1528253F6717303F6717303F6717303FBA063B3F" << "\n";
+ strebuf << " BA063B3FBA063B3F0DF6453F0DF6453F0DF6453F60E5503F60E5503F60E5503F" << "\n";
+ strebuf << " C5D1193FC5D1193FC5D1193F17C1243F18C1243F18C1243F6BB02F3F6BB02F3F" << "\n";
+ strebuf << " 6BB02F3FBE9F3A3FBE9F3A3FBE9F3A3F108F453F108F453F108F453F637E503F" << "\n";
+ strebuf << " 637E503F637E503FB66D5B3FB66D5B3FB66D5B3F095D663F095D663F095D663F" << "\n";
+ strebuf << " 6F492F3F6F492F3F6F492F3FC1383A3FC2383A3FC2383A3F1528453F1528453F" << "\n";
+ strebuf << " 1528453F6817503F6817503F6817503FBA065B3FBA065B3FBA065B3F0DF6653F" << "\n";
+ strebuf << " 0DF6653F0DF6653F60E5703F60E5703F60E5703FB3D47B3FB3D47B3FB3D47B3F" << "\n";
+ strebuf << " D578E93DD578E93DD078E93DB579203EB579203EB479203E01374C3E01374C3E" << "\n";
+ strebuf << " 00374C3E4CF4773E4CF4773E4CF4773ECBD8913ECBD8913ECAD8913E71B7A73E" << "\n";
+ strebuf << " 71B7A73E70B7A73E1696BD3E1696BD3E1696BD3EBC74D33EBC74D33EBC74D33E" << "\n";
+ strebuf << " 109B4A3E109B4A3E109B4A3E5A58763E5A58763E5858763ED30A913ED30A913E" << "\n";
+ strebuf << " D20A913E78E9A63E78E9A63E78E9A63E1DC8BC3E1DC8BC3E1CC8BC3EC3A6D23E" << "\n";
+ strebuf << " C2A6D23EC2A6D23E6885E83E6785E83E6885E83E0E64FE3E0D64FE3E0E64FE3E" << "\n";
+ strebuf << " DA3C903EDA3C903EDA3C903E801BA63E801BA63E801BA63E26FABB3E26FABB3E" << "\n";
+ strebuf << " 26FABB3ECBD8D13ECBD8D13ECAD8D13E70B7E73E70B7E73E70B7E73E1696FD3E" << "\n";
+ strebuf << " 1696FD3E1696FD3E5DBA093F5DBA093F5DBA093FB0A9143FB0A9143FB0A9143F" << "\n";
+ strebuf << " 2E2CBB3E2E2CBB3E2E2CBB3ED20AD13ED30AD13ED20AD13E79E9E63E79E9E63E" << "\n";
+ strebuf << " 78E9E63E1FC8FC3E1FC8FC3E1EC8FC3E6253093F6253093F6253093FB542143F" << "\n";
+ strebuf << " B542143FB542143F07321F3F07321F3F07321F3F5A212A3F5A212A3F5A212A3F" << "\n";
+ strebuf << " 801BE63E801BE63E801BE63E24FAFB3E25FAFB3E24FAFB3E65EC083F65EC083F" << "\n";
+ strebuf << " 65EC083FB8DB133FB8DB133FB8DB133F0BCB1E3F0BCB1E3F0BCB1E3F5EBA293F" << "\n";
+ strebuf << " 5EBA293F5EBA293FB0A9343FB0A9343FB0A9343F03993F3F03993F3F03993F3F" << "\n";
+ strebuf << " 6985083F6985083F6985083FBB74133FBC74133FBC74133F0F641E3F0F641E3F" << "\n";
+ strebuf << " 0F641E3F6253293F6253293F6253293FB442343FB442343FB442343F07323F3F" << "\n";
+ strebuf << " 07323F3F07323F3F5A214A3F5A214A3F5A214A3FAD10553FAD10553FAD10553F" << "\n";
+ strebuf << " 12FD1D3F12FD1D3F12FD1D3F64EC283F65EC283F65EC283FB8DB333FB8DB333F" << "\n";
+ strebuf << " B8DB333F0BCB3E3F0BCB3E3F0BCB3E3F5DBA493F5DBA493F5DBA493FB0A9543F" << "\n";
+ strebuf << " B0A9543FB0A9543F03995F3F03995F3F03995F3F56886A3F56886A3F56886A3F" << "\n";
+ strebuf << " BC74333FBC74333FBC74333F0E643E3F0F643E3F0F643E3F6153493F6253493F" << "\n";
+ strebuf << " 6253493FB542543FB542543FB542543F07325F3F07325F3F07325F3F5A216A3F" << "\n";
+ strebuf << " 5A216A3F5A216A3FAD10753FAD10753FAD10753F0000803F0000803F0000803F\"" << "\n";
+ strebuf << " </data>" << "\n";
+ strebuf << " </LUT>" << "\n";
+ strebuf << "</look>" << "\n";
+
+ std::istringstream simple1D;
+ simple1D.str(strebuf.str());
+
+ // Read file
+ LocalFileFormat tester;
+ CachedFileRcPtr cachedFile = tester.Read(simple1D);
+ LocalCachedFileRcPtr looklut = DynamicPtrCast<LocalCachedFile>(cachedFile);
+
+ // Check LUT size is correct
+ OIIO_CHECK_EQUAL(looklut->lut3D->size[0], 8);
+ OIIO_CHECK_EQUAL(looklut->lut3D->size[1], 8);
+ OIIO_CHECK_EQUAL(looklut->lut3D->size[2], 8);
+
+ // Check LUT values
+ OIIO_CHECK_EQUAL(looklut->lut3D->lut.size(), 8*8*8*3);
+
+ double cube[8 * 8 * 8 * 3] = {
+ -0.00000, -0.00000, -0.00000,
+ 0.04271, 0.04271, 0.04271,
+ 0.08543, 0.08543, 0.08543,
+ 0.12814, 0.12814, 0.12814,
+ 0.17086, 0.17086, 0.17086,
+ 0.21357, 0.21357, 0.21357,
+ 0.25629, 0.25629, 0.25629,
+ 0.29900, 0.29900, 0.29900,
+ 0.08386, 0.08386, 0.08386,
+ 0.12657, 0.12657, 0.12657,
+ 0.16929, 0.16929, 0.16929,
+ 0.21200, 0.21200, 0.21200,
+ 0.25471, 0.25471, 0.25471,
+ 0.29743, 0.29743, 0.29743,
+ 0.34014, 0.34014, 0.34014,
+ 0.38286, 0.38286, 0.38286,
+ 0.16771, 0.16771, 0.16771,
+ 0.21043, 0.21043, 0.21043,
+ 0.25314, 0.25314, 0.25314,
+ 0.29586, 0.29586, 0.29586,
+ 0.33857, 0.33857, 0.33857,
+ 0.38129, 0.38129, 0.38129,
+ 0.42400, 0.42400, 0.42400,
+ 0.46671, 0.46671, 0.46671,
+ 0.25157, 0.25157, 0.25157,
+ 0.29429, 0.29429, 0.29429,
+ 0.33700, 0.33700, 0.33700,
+ 0.37971, 0.37971, 0.37971,
+ 0.42243, 0.42243, 0.42243,
+ 0.46514, 0.46514, 0.46514,
+ 0.50786, 0.50786, 0.50786,
+ 0.55057, 0.55057, 0.55057,
+ 0.33543, 0.33543, 0.33543,
+ 0.37814, 0.37814, 0.37814,
+ 0.42086, 0.42086, 0.42086,
+ 0.46357, 0.46357, 0.46357,
+ 0.50629, 0.50629, 0.50629,
+ 0.54900, 0.54900, 0.54900,
+ 0.59171, 0.59171, 0.59171,
+ 0.63443, 0.63443, 0.63443,
+ 0.41929, 0.41929, 0.41929,
+ 0.46200, 0.46200, 0.46200,
+ 0.50471, 0.50471, 0.50471,
+ 0.54743, 0.54743, 0.54743,
+ 0.59014, 0.59014, 0.59014,
+ 0.63286, 0.63286, 0.63286,
+ 0.67557, 0.67557, 0.67557,
+ 0.71829, 0.71829, 0.71829,
+ 0.50314, 0.50314, 0.50314,
+ 0.54586, 0.54586, 0.54586,
+ 0.58857, 0.58857, 0.58857,
+ 0.63129, 0.63129, 0.63129,
+ 0.67400, 0.67400, 0.67400,
+ 0.71671, 0.71671, 0.71671,
+ 0.75943, 0.75943, 0.75943,
+ 0.80214, 0.80214, 0.80214,
+ 0.58700, 0.58700, 0.58700,
+ 0.62971, 0.62971, 0.62971,
+ 0.67243, 0.67243, 0.67243,
+ 0.71514, 0.71514, 0.71514,
+ 0.75786, 0.75786, 0.75786,
+ 0.80057, 0.80057, 0.80057,
+ 0.84329, 0.84329, 0.84329,
+ 0.88600, 0.88600, 0.88600,
+ 0.01629, 0.01629, 0.01629,
+ 0.05900, 0.05900, 0.05900,
+ 0.10171, 0.10171, 0.10171,
+ 0.14443, 0.14443, 0.14443,
+ 0.18714, 0.18714, 0.18714,
+ 0.22986, 0.22986, 0.22986,
+ 0.27257, 0.27257, 0.27257,
+ 0.31529, 0.31529, 0.31529,
+ 0.10014, 0.10014, 0.10014,
+ 0.14286, 0.14286, 0.14286,
+ 0.18557, 0.18557, 0.18557,
+ 0.22829, 0.22829, 0.22829,
+ 0.27100, 0.27100, 0.27100,
+ 0.31371, 0.31371, 0.31371,
+ 0.35643, 0.35643, 0.35643,
+ 0.39914, 0.39914, 0.39914,
+ 0.18400, 0.18400, 0.18400,
+ 0.22671, 0.22671, 0.22671,
+ 0.26943, 0.26943, 0.26943,
+ 0.31214, 0.31214, 0.31214,
+ 0.35486, 0.35486, 0.35486,
+ 0.39757, 0.39757, 0.39757,
+ 0.44029, 0.44029, 0.44029,
+ 0.48300, 0.48300, 0.48300,
+ 0.26786, 0.26786, 0.26786,
+ 0.31057, 0.31057, 0.31057,
+ 0.35329, 0.35329, 0.35329,
+ 0.39600, 0.39600, 0.39600,
+ 0.43871, 0.43871, 0.43871,
+ 0.48143, 0.48143, 0.48143,
+ 0.52414, 0.52414, 0.52414,
+ 0.56686, 0.56686, 0.56686,
+ 0.35171, 0.35171, 0.35171,
+ 0.39443, 0.39443, 0.39443,
+ 0.43714, 0.43714, 0.43714,
+ 0.47986, 0.47986, 0.47986,
+ 0.52257, 0.52257, 0.52257,
+ 0.56529, 0.56529, 0.56529,
+ 0.60800, 0.60800, 0.60800,
+ 0.65071, 0.65071, 0.65071,
+ 0.43557, 0.43557, 0.43557,
+ 0.47829, 0.47829, 0.47829,
+ 0.52100, 0.52100, 0.52100,
+ 0.56371, 0.56371, 0.56371,
+ 0.60643, 0.60643, 0.60643,
+ 0.64914, 0.64914, 0.64914,
+ 0.69186, 0.69186, 0.69186,
+ 0.73457, 0.73457, 0.73457,
+ 0.51943, 0.51943, 0.51943,
+ 0.56214, 0.56214, 0.56214,
+ 0.60486, 0.60486, 0.60486,
+ 0.64757, 0.64757, 0.64757,
+ 0.69029, 0.69029, 0.69029,
+ 0.73300, 0.73300, 0.73300,
+ 0.77571, 0.77571, 0.77571,
+ 0.81843, 0.81843, 0.81843,
+ 0.60329, 0.60329, 0.60329,
+ 0.64600, 0.64600, 0.64600,
+ 0.68871, 0.68871, 0.68871,
+ 0.73143, 0.73143, 0.73143,
+ 0.77414, 0.77414, 0.77414,
+ 0.81686, 0.81686, 0.81686,
+ 0.85957, 0.85957, 0.85957,
+ 0.90229, 0.90229, 0.90229,
+ 0.03257, 0.03257, 0.03257,
+ 0.07529, 0.07529, 0.07529,
+ 0.11800, 0.11800, 0.11800,
+ 0.16071, 0.16071, 0.16071,
+ 0.20343, 0.20343, 0.20343,
+ 0.24614, 0.24614, 0.24614,
+ 0.28886, 0.28886, 0.28886,
+ 0.33157, 0.33157, 0.33157,
+ 0.11643, 0.11643, 0.11643,
+ 0.15914, 0.15914, 0.15914,
+ 0.20186, 0.20186, 0.20186,
+ 0.24457, 0.24457, 0.24457,
+ 0.28729, 0.28729, 0.28729,
+ 0.33000, 0.33000, 0.33000,
+ 0.37271, 0.37271, 0.37271,
+ 0.41543, 0.41543, 0.41543,
+ 0.20029, 0.20029, 0.20029,
+ 0.24300, 0.24300, 0.24300,
+ 0.28571, 0.28571, 0.28571,
+ 0.32843, 0.32843, 0.32843,
+ 0.37114, 0.37114, 0.37114,
+ 0.41386, 0.41386, 0.41386,
+ 0.45657, 0.45657, 0.45657,
+ 0.49929, 0.49929, 0.49929,
+ 0.28414, 0.28414, 0.28414,
+ 0.32686, 0.32686, 0.32686,
+ 0.36957, 0.36957, 0.36957,
+ 0.41229, 0.41229, 0.41229,
+ 0.45500, 0.45500, 0.45500,
+ 0.49771, 0.49771, 0.49771,
+ 0.54043, 0.54043, 0.54043,
+ 0.58314, 0.58314, 0.58314,
+ 0.36800, 0.36800, 0.36800,
+ 0.41071, 0.41071, 0.41071,
+ 0.45343, 0.45343, 0.45343,
+ 0.49614, 0.49614, 0.49614,
+ 0.53886, 0.53886, 0.53886,
+ 0.58157, 0.58157, 0.58157,
+ 0.62429, 0.62429, 0.62429,
+ 0.66700, 0.66700, 0.66700,
+ 0.45186, 0.45186, 0.45186,
+ 0.49457, 0.49457, 0.49457,
+ 0.53729, 0.53729, 0.53729,
+ 0.58000, 0.58000, 0.58000,
+ 0.62271, 0.62271, 0.62271,
+ 0.66543, 0.66543, 0.66543,
+ 0.70814, 0.70814, 0.70814,
+ 0.75086, 0.75086, 0.75086,
+ 0.53571, 0.53571, 0.53571,
+ 0.57843, 0.57843, 0.57843,
+ 0.62114, 0.62114, 0.62114,
+ 0.66386, 0.66386, 0.66386,
+ 0.70657, 0.70657, 0.70657,
+ 0.74929, 0.74929, 0.74929,
+ 0.79200, 0.79200, 0.79200,
+ 0.83471, 0.83471, 0.83471,
+ 0.61957, 0.61957, 0.61957,
+ 0.66229, 0.66229, 0.66229,
+ 0.70500, 0.70500, 0.70500,
+ 0.74771, 0.74771, 0.74771,
+ 0.79043, 0.79043, 0.79043,
+ 0.83314, 0.83314, 0.83314,
+ 0.87586, 0.87586, 0.87586,
+ 0.91857, 0.91857, 0.91857,
+ 0.04886, 0.04886, 0.04886,
+ 0.09157, 0.09157, 0.09157,
+ 0.13429, 0.13429, 0.13429,
+ 0.17700, 0.17700, 0.17700,
+ 0.21971, 0.21971, 0.21971,
+ 0.26243, 0.26243, 0.26243,
+ 0.30514, 0.30514, 0.30514,
+ 0.34786, 0.34786, 0.34786,
+ 0.13271, 0.13271, 0.13271,
+ 0.17543, 0.17543, 0.17543,
+ 0.21814, 0.21814, 0.21814,
+ 0.26086, 0.26086, 0.26086,
+ 0.30357, 0.30357, 0.30357,
+ 0.34629, 0.34629, 0.34629,
+ 0.38900, 0.38900, 0.38900,
+ 0.43171, 0.43171, 0.43171,
+ 0.21657, 0.21657, 0.21657,
+ 0.25929, 0.25929, 0.25929,
+ 0.30200, 0.30200, 0.30200,
+ 0.34471, 0.34471, 0.34471,
+ 0.38743, 0.38743, 0.38743,
+ 0.43014, 0.43014, 0.43014,
+ 0.47286, 0.47286, 0.47286,
+ 0.51557, 0.51557, 0.51557,
+ 0.30043, 0.30043, 0.30043,
+ 0.34314, 0.34314, 0.34314,
+ 0.38586, 0.38586, 0.38586,
+ 0.42857, 0.42857, 0.42857,
+ 0.47129, 0.47129, 0.47129,
+ 0.51400, 0.51400, 0.51400,
+ 0.55671, 0.55671, 0.55671,
+ 0.59943, 0.59943, 0.59943,
+ 0.38429, 0.38429, 0.38429,
+ 0.42700, 0.42700, 0.42700,
+ 0.46971, 0.46971, 0.46971,
+ 0.51243, 0.51243, 0.51243,
+ 0.55514, 0.55514, 0.55514,
+ 0.59786, 0.59786, 0.59786,
+ 0.64057, 0.64057, 0.64057,
+ 0.68329, 0.68329, 0.68329,
+ 0.46814, 0.46814, 0.46814,
+ 0.51086, 0.51086, 0.51086,
+ 0.55357, 0.55357, 0.55357,
+ 0.59629, 0.59629, 0.59629,
+ 0.63900, 0.63900, 0.63900,
+ 0.68171, 0.68171, 0.68171,
+ 0.72443, 0.72443, 0.72443,
+ 0.76714, 0.76714, 0.76714,
+ 0.55200, 0.55200, 0.55200,
+ 0.59471, 0.59471, 0.59471,
+ 0.63743, 0.63743, 0.63743,
+ 0.68014, 0.68014, 0.68014,
+ 0.72286, 0.72286, 0.72286,
+ 0.76557, 0.76557, 0.76557,
+ 0.80829, 0.80829, 0.80829,
+ 0.85100, 0.85100, 0.85100,
+ 0.63586, 0.63586, 0.63586,
+ 0.67857, 0.67857, 0.67857,
+ 0.72129, 0.72129, 0.72129,
+ 0.76400, 0.76400, 0.76400,
+ 0.80671, 0.80671, 0.80671,
+ 0.84943, 0.84943, 0.84943,
+ 0.89214, 0.89214, 0.89214,
+ 0.93486, 0.93486, 0.93486,
+ 0.06514, 0.06514, 0.06514,
+ 0.10786, 0.10786, 0.10786,
+ 0.15057, 0.15057, 0.15057,
+ 0.19329, 0.19329, 0.19329,
+ 0.23600, 0.23600, 0.23600,
+ 0.27871, 0.27871, 0.27871,
+ 0.32143, 0.32143, 0.32143,
+ 0.36414, 0.36414, 0.36414,
+ 0.14900, 0.14900, 0.14900,
+ 0.19171, 0.19171, 0.19171,
+ 0.23443, 0.23443, 0.23443,
+ 0.27714, 0.27714, 0.27714,
+ 0.31986, 0.31986, 0.31986,
+ 0.36257, 0.36257, 0.36257,
+ 0.40529, 0.40529, 0.40529,
+ 0.44800, 0.44800, 0.44800,
+ 0.23286, 0.23286, 0.23286,
+ 0.27557, 0.27557, 0.27557,
+ 0.31829, 0.31829, 0.31829,
+ 0.36100, 0.36100, 0.36100,
+ 0.40371, 0.40371, 0.40371,
+ 0.44643, 0.44643, 0.44643,
+ 0.48914, 0.48914, 0.48914,
+ 0.53186, 0.53186, 0.53186,
+ 0.31671, 0.31671, 0.31671,
+ 0.35943, 0.35943, 0.35943,
+ 0.40214, 0.40214, 0.40214,
+ 0.44486, 0.44486, 0.44486,
+ 0.48757, 0.48757, 0.48757,
+ 0.53029, 0.53029, 0.53029,
+ 0.57300, 0.57300, 0.57300,
+ 0.61571, 0.61571, 0.61571,
+ 0.40057, 0.40057, 0.40057,
+ 0.44329, 0.44329, 0.44329,
+ 0.48600, 0.48600, 0.48600,
+ 0.52871, 0.52871, 0.52871,
+ 0.57143, 0.57143, 0.57143,
+ 0.61414, 0.61414, 0.61414,
+ 0.65686, 0.65686, 0.65686,
+ 0.69957, 0.69957, 0.69957,
+ 0.48443, 0.48443, 0.48443,
+ 0.52714, 0.52714, 0.52714,
+ 0.56986, 0.56986, 0.56986,
+ 0.61257, 0.61257, 0.61257,
+ 0.65529, 0.65529, 0.65529,
+ 0.69800, 0.69800, 0.69800,
+ 0.74071, 0.74071, 0.74071,
+ 0.78343, 0.78343, 0.78343,
+ 0.56829, 0.56829, 0.56829,
+ 0.61100, 0.61100, 0.61100,
+ 0.65371, 0.65371, 0.65371,
+ 0.69643, 0.69643, 0.69643,
+ 0.73914, 0.73914, 0.73914,
+ 0.78186, 0.78186, 0.78186,
+ 0.82457, 0.82457, 0.82457,
+ 0.86729, 0.86729, 0.86729,
+ 0.65214, 0.65214, 0.65214,
+ 0.69486, 0.69486, 0.69486,
+ 0.73757, 0.73757, 0.73757,
+ 0.78029, 0.78029, 0.78029,
+ 0.82300, 0.82300, 0.82300,
+ 0.86571, 0.86571, 0.86571,
+ 0.90843, 0.90843, 0.90843,
+ 0.95114, 0.95114, 0.95114,
+ 0.08143, 0.08143, 0.08143,
+ 0.12414, 0.12414, 0.12414,
+ 0.16686, 0.16686, 0.16686,
+ 0.20957, 0.20957, 0.20957,
+ 0.25229, 0.25229, 0.25229,
+ 0.29500, 0.29500, 0.29500,
+ 0.33771, 0.33771, 0.33771,
+ 0.38043, 0.38043, 0.38043,
+ 0.16529, 0.16529, 0.16529,
+ 0.20800, 0.20800, 0.20800,
+ 0.25071, 0.25071, 0.25071,
+ 0.29343, 0.29343, 0.29343,
+ 0.33614, 0.33614, 0.33614,
+ 0.37886, 0.37886, 0.37886,
+ 0.42157, 0.42157, 0.42157,
+ 0.46429, 0.46429, 0.46429,
+ 0.24914, 0.24914, 0.24914,
+ 0.29186, 0.29186, 0.29186,
+ 0.33457, 0.33457, 0.33457,
+ 0.37729, 0.37729, 0.37729,
+ 0.42000, 0.42000, 0.42000,
+ 0.46271, 0.46271, 0.46271,
+ 0.50543, 0.50543, 0.50543,
+ 0.54814, 0.54814, 0.54814,
+ 0.33300, 0.33300, 0.33300,
+ 0.37571, 0.37571, 0.37571,
+ 0.41843, 0.41843, 0.41843,
+ 0.46114, 0.46114, 0.46114,
+ 0.50386, 0.50386, 0.50386,
+ 0.54657, 0.54657, 0.54657,
+ 0.58929, 0.58929, 0.58929,
+ 0.63200, 0.63200, 0.63200,
+ 0.41686, 0.41686, 0.41686,
+ 0.45957, 0.45957, 0.45957,
+ 0.50229, 0.50229, 0.50229,
+ 0.54500, 0.54500, 0.54500,
+ 0.58771, 0.58771, 0.58771,
+ 0.63043, 0.63043, 0.63043,
+ 0.67314, 0.67314, 0.67314,
+ 0.71586, 0.71586, 0.71586,
+ 0.50071, 0.50071, 0.50071,
+ 0.54343, 0.54343, 0.54343,
+ 0.58614, 0.58614, 0.58614,
+ 0.62886, 0.62886, 0.62886,
+ 0.67157, 0.67157, 0.67157,
+ 0.71429, 0.71429, 0.71429,
+ 0.75700, 0.75700, 0.75700,
+ 0.79971, 0.79971, 0.79971,
+ 0.58457, 0.58457, 0.58457,
+ 0.62729, 0.62729, 0.62729,
+ 0.67000, 0.67000, 0.67000,
+ 0.71271, 0.71271, 0.71271,
+ 0.75543, 0.75543, 0.75543,
+ 0.79814, 0.79814, 0.79814,
+ 0.84086, 0.84086, 0.84086,
+ 0.88357, 0.88357, 0.88357,
+ 0.66843, 0.66843, 0.66843,
+ 0.71114, 0.71114, 0.71114,
+ 0.75386, 0.75386, 0.75386,
+ 0.79657, 0.79657, 0.79657,
+ 0.83929, 0.83929, 0.83929,
+ 0.88200, 0.88200, 0.88200,
+ 0.92471, 0.92471, 0.92471,
+ 0.96743, 0.96743, 0.96743,
+ 0.09771, 0.09771, 0.09771,
+ 0.14043, 0.14043, 0.14043,
+ 0.18314, 0.18314, 0.18314,
+ 0.22586, 0.22586, 0.22586,
+ 0.26857, 0.26857, 0.26857,
+ 0.31129, 0.31129, 0.31129,
+ 0.35400, 0.35400, 0.35400,
+ 0.39671, 0.39671, 0.39671,
+ 0.18157, 0.18157, 0.18157,
+ 0.22429, 0.22429, 0.22429,
+ 0.26700, 0.26700, 0.26700,
+ 0.30971, 0.30971, 0.30971,
+ 0.35243, 0.35243, 0.35243,
+ 0.39514, 0.39514, 0.39514,
+ 0.43786, 0.43786, 0.43786,
+ 0.48057, 0.48057, 0.48057,
+ 0.26543, 0.26543, 0.26543,
+ 0.30814, 0.30814, 0.30814,
+ 0.35086, 0.35086, 0.35086,
+ 0.39357, 0.39357, 0.39357,
+ 0.43629, 0.43629, 0.43629,
+ 0.47900, 0.47900, 0.47900,
+ 0.52171, 0.52171, 0.52171,
+ 0.56443, 0.56443, 0.56443,
+ 0.34929, 0.34929, 0.34929,
+ 0.39200, 0.39200, 0.39200,
+ 0.43471, 0.43471, 0.43471,
+ 0.47743, 0.47743, 0.47743,
+ 0.52014, 0.52014, 0.52014,
+ 0.56286, 0.56286, 0.56286,
+ 0.60557, 0.60557, 0.60557,
+ 0.64829, 0.64829, 0.64829,
+ 0.43314, 0.43314, 0.43314,
+ 0.47586, 0.47586, 0.47586,
+ 0.51857, 0.51857, 0.51857,
+ 0.56129, 0.56129, 0.56129,
+ 0.60400, 0.60400, 0.60400,
+ 0.64671, 0.64671, 0.64671,
+ 0.68943, 0.68943, 0.68943,
+ 0.73214, 0.73214, 0.73214,
+ 0.51700, 0.51700, 0.51700,
+ 0.55971, 0.55971, 0.55971,
+ 0.60243, 0.60243, 0.60243,
+ 0.64514, 0.64514, 0.64514,
+ 0.68786, 0.68786, 0.68786,
+ 0.73057, 0.73057, 0.73057,
+ 0.77329, 0.77329, 0.77329,
+ 0.81600, 0.81600, 0.81600,
+ 0.60086, 0.60086, 0.60086,
+ 0.64357, 0.64357, 0.64357,
+ 0.68629, 0.68629, 0.68629,
+ 0.72900, 0.72900, 0.72900,
+ 0.77171, 0.77171, 0.77171,
+ 0.81443, 0.81443, 0.81443,
+ 0.85714, 0.85714, 0.85714,
+ 0.89986, 0.89986, 0.89986,
+ 0.68471, 0.68471, 0.68471,
+ 0.72743, 0.72743, 0.72743,
+ 0.77014, 0.77014, 0.77014,
+ 0.81286, 0.81286, 0.81286,
+ 0.85557, 0.85557, 0.85557,
+ 0.89829, 0.89829, 0.89829,
+ 0.94100, 0.94100, 0.94100,
+ 0.98371, 0.98371, 0.98371,
+ 0.11400, 0.11400, 0.11400,
+ 0.15671, 0.15671, 0.15671,
+ 0.19943, 0.19943, 0.19943,
+ 0.24214, 0.24214, 0.24214,
+ 0.28486, 0.28486, 0.28486,
+ 0.32757, 0.32757, 0.32757,
+ 0.37029, 0.37029, 0.37029,
+ 0.41300, 0.41300, 0.41300,
+ 0.19786, 0.19786, 0.19786,
+ 0.24057, 0.24057, 0.24057,
+ 0.28329, 0.28329, 0.28329,
+ 0.32600, 0.32600, 0.32600,
+ 0.36871, 0.36871, 0.36871,
+ 0.41143, 0.41143, 0.41143,
+ 0.45414, 0.45414, 0.45414,
+ 0.49686, 0.49686, 0.49686,
+ 0.28171, 0.28171, 0.28171,
+ 0.32443, 0.32443, 0.32443,
+ 0.36714, 0.36714, 0.36714,
+ 0.40986, 0.40986, 0.40986,
+ 0.45257, 0.45257, 0.45257,
+ 0.49529, 0.49529, 0.49529,
+ 0.53800, 0.53800, 0.53800,
+ 0.58071, 0.58071, 0.58071,
+ 0.36557, 0.36557, 0.36557,
+ 0.40829, 0.40829, 0.40829,
+ 0.45100, 0.45100, 0.45100,
+ 0.49371, 0.49371, 0.49371,
+ 0.53643, 0.53643, 0.53643,
+ 0.57914, 0.57914, 0.57914,
+ 0.62186, 0.62186, 0.62186,
+ 0.66457, 0.66457, 0.66457,
+ 0.44943, 0.44943, 0.44943,
+ 0.49214, 0.49214, 0.49214,
+ 0.53486, 0.53486, 0.53486,
+ 0.57757, 0.57757, 0.57757,
+ 0.62029, 0.62029, 0.62029,
+ 0.66300, 0.66300, 0.66300,
+ 0.70571, 0.70571, 0.70571,
+ 0.74843, 0.74843, 0.74843,
+ 0.53329, 0.53329, 0.53329,
+ 0.57600, 0.57600, 0.57600,
+ 0.61871, 0.61871, 0.61871,
+ 0.66143, 0.66143, 0.66143,
+ 0.70414, 0.70414, 0.70414,
+ 0.74686, 0.74686, 0.74686,
+ 0.78957, 0.78957, 0.78957,
+ 0.83229, 0.83229, 0.83229,
+ 0.61714, 0.61714, 0.61714,
+ 0.65986, 0.65986, 0.65986,
+ 0.70257, 0.70257, 0.70257,
+ 0.74529, 0.74529, 0.74529,
+ 0.78800, 0.78800, 0.78800,
+ 0.83071, 0.83071, 0.83071,
+ 0.87343, 0.87343, 0.87343,
+ 0.91614, 0.91614, 0.91614,
+ 0.70100, 0.70100, 0.70100,
+ 0.74371, 0.74371, 0.74371,
+ 0.78643, 0.78643, 0.78643,
+ 0.82914, 0.82914, 0.82914,
+ 0.87186, 0.87186, 0.87186,
+ 0.91457, 0.91457, 0.91457,
+ 0.95729, 0.95729, 0.95729,
+ 1.00000, 1.00000, 1.00000
+ };
+
+ // check cube data
+ for(unsigned int i = 0; i < looklut->lut3D->lut.size(); ++i) {
+ OIIO_CHECK_CLOSE(cube[i], looklut->lut3D->lut[i], 1e-4);
+ }
+}
+
+
+OIIO_ADD_TEST(FileFormatIridasLook, fail_on_mask)
+{
+ std::ostringstream strebuf;
+ strebuf << "<?xml version=\"1.0\" ?>" << "\n";
+ strebuf << "<look>" << "\n";
+ strebuf << " <shaders>" << "\n";
+ strebuf << " <base>" << "\n";
+ strebuf << " <rangeversion>\"2\"</rangeversion>" << "\n";
+ strebuf << " <visible>\"1\"</visible>" << "\n";
+ strebuf << " <sublayer0>" << "\n";
+ strebuf << " <opacity>\"1\"</opacity>" << "\n";
+ strebuf << " <parameters>" << "\n";
+ strebuf << " <LogPrinterLights>\"N1\"</LogPrinterLights>" << "\n";
+ strebuf << " </parameters>" << "\n";
+ strebuf << " </sublayer0>" << "\n";
+ strebuf << " <sublayer3>" << "\n";
+ strebuf << " <opacity>\"1\"</opacity>" << "\n";
+ strebuf << " <parameters>" << "\n";
+ strebuf << " <gamma.Z>\"0.49967\"</gamma.Z>" << "\n";
+ strebuf << " <gain.Z>\"0.28739\"</gain.Z>" << "\n";
+ strebuf << " <gamma.Y>\"0.49179\"</gamma.Y>" << "\n";
+ strebuf << " <gain.Y>\"0.22243\"</gain.Y>" << "\n";
+ strebuf << " <gain.X>\"0.34531\"</gain.X>" << "\n";
+ strebuf << " <gamma.X>\"0.39388\"</gamma.X>" << "\n";
+ strebuf << " </parameters>" << "\n";
+ strebuf << " </sublayer3>" << "\n";
+ strebuf << " </base>" << "\n";
+ strebuf << " </shaders>" << "\n";
+ strebuf << " <mask>" << "\n";
+ strebuf << " <name>\"Untitled00_00_00_00\"</name>" << "\n";
+ strebuf << " <activecontour>\"0\"</activecontour>" << "\n";
+ strebuf << " <width>\"1024\"</width>" << "\n";
+ strebuf << " <height>\"778\"</height>" << "\n";
+ strebuf << " <contour>" << "\n";
+ strebuf << " <positive>\"1\"</positive>" << "\n";
+ strebuf << " <point>" << "\n";
+ strebuf << " <inner>\"catmull-rom,value:317.5,583.5@0\"</inner>" << "\n";
+ strebuf << " <innerprevtangent>\"catmull-rom,value:0,0@0\"</innerprevtangent>" << "\n";
+ strebuf << " <innernexttangent>\"catmull-rom,value:0,0@0\"</innernexttangent>" << "\n";
+ strebuf << " <falloffexponent>\"catmull-rom,value:1@0\"</falloffexponent>" << "\n";
+ strebuf << " <falloffweight>\"catmull-rom,value:0.5@0\"</falloffweight>" << "\n";
+ strebuf << " <detached>linear,value:0@0</detached>" << "\n";
+ strebuf << " <outer>\"catmull-rom,value:317.5,583.5@0\"</outer>" << "\n";
+ strebuf << " <outerprevtangent>\"catmull-rom,value:0,0@0\"</outerprevtangent>" << "\n";
+ strebuf << " <outernexttangent>\"catmull-rom,value:0,0@0\"</outernexttangent>" << "\n";
+ strebuf << " <spline>\"linear,value:0@0\"</spline>" << "\n";
+ strebuf << " <smooth>\"linear,value:0@0\"</smooth>" << "\n";
+ strebuf << " </point>" << "\n";
+ strebuf << " </contour>" << "\n";
+ strebuf << " </mask>" << "\n";
+ strebuf << " <LUT>" << "\n";
+ strebuf << " <size>\"8\"</size>" << "\n";
+ strebuf << " <data>\"" << "\n";
+ strebuf << " 000000000000000000000000878B933D000000000000000057BC563E00000000" << "\n";
+ strebuf << " ...truncated, should never be parsed due to mask section\"" << "\n";
+ strebuf << " </data>" << "\n";
+ strebuf << " </LUT>" << "\n";
+ strebuf << "</look>" << "\n";
+
+ std::istringstream infile;
+ infile.str(strebuf.str());
+
+ // Read file
+ LocalFileFormat tester;
+ try
+ {
+ CachedFileRcPtr cachedFile = tester.Read(infile);
+ OIIO_CHECK_ASSERT(false); // Fail test if previous line doesn't throw Exception
+ }
+ catch(Exception& e)
+ {
+ // Check exception message is correct error (not something
+ // like "cannot parse LUT data")
+ std::string expected_error = "Cannot load .look LUT containing mask";
+ OIIO_CHECK_EQUAL(e.what(), expected_error);
+ }
+
+}
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/FileFormatPandora.cpp b/src/core/FileFormatPandora.cpp
new file mode 100644
index 0000000..eef68d2
--- /dev/null
+++ b/src/core/FileFormatPandora.cpp
@@ -0,0 +1,286 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <iostream>
+#include <iterator>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile ()
+ {
+ lut3D = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ Lut3DRcPtr lut3D;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "pandora_mga";
+ info.extension = "mga";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+
+ FormatInfo info2;
+ info2.name = "pandora_m3d";
+ info2.extension = "m3d";
+ info2.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info2);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+ // this shouldn't happen
+ if(!istream)
+ {
+ throw Exception ("File stream empty when trying to read Pandora lut");
+ }
+
+ // Validate the file type
+ std::string line;
+
+ // Parse the file
+ std::string format;
+ int lutEdgeLen = 0;
+ int outputBitDepthMaxValue = 0;
+ std::vector<int> raw3d;
+
+ {
+ std::vector<std::string> parts;
+ std::vector<int> tmpints;
+ bool inLut3d = false;
+
+ while(nextline(istream, line))
+ {
+ // Strip, lowercase, and split the line
+ pystring::split(pystring::lower(pystring::strip(line)), parts);
+ if(parts.empty()) continue;
+
+ // Skip all lines starting with '#'
+ if(pystring::startswith(parts[0],"#")) continue;
+
+ if(parts[0] == "channel")
+ {
+ if(parts.size() != 2 || pystring::lower(parts[1]) != "3d")
+ {
+ throw Exception("Parse error in Pandora lut. Only 3d luts are currently supported. (channel: 3d).");
+ }
+ }
+ else if(parts[0] == "in")
+ {
+ int inval = 0;
+ if(parts.size() != 2 || !StringToInt( &inval, parts[1].c_str()))
+ {
+ throw Exception("Malformed 'in' tag in Pandora lut.");
+ }
+ raw3d.reserve(inval*3);
+ lutEdgeLen = Get3DLutEdgeLenFromNumPixels(inval);
+ }
+ else if(parts[0] == "out")
+ {
+ if(parts.size() != 2 || !StringToInt( &outputBitDepthMaxValue, parts[1].c_str()))
+ {
+ throw Exception("Malformed 'out' tag in Pandora lut.");
+ }
+ }
+ else if(parts[0] == "format")
+ {
+ if(parts.size() != 2 || pystring::lower(parts[1]) != "lut")
+ {
+ throw Exception("Parse error in Pandora lut. Only luts are currently supported. (format: lut).");
+ }
+ }
+ else if(parts[0] == "values")
+ {
+ if(parts.size() != 4 ||
+ pystring::lower(parts[1]) != "red" ||
+ pystring::lower(parts[2]) != "green" ||
+ pystring::lower(parts[3]) != "blue")
+ {
+ throw Exception("Parse error in Pandora lut. Only rgb luts are currently supported. (values: red green blue).");
+ }
+
+ inLut3d = true;
+ }
+ else if(inLut3d)
+ {
+ if(!StringVecToIntVec(tmpints, parts) || tmpints.size() != 4)
+ {
+ std::ostringstream os;
+ os << "Parse error in Pandora lut. Expected to find 4 integers. Instead found '"
+ << line << "'";
+ throw Exception(os.str().c_str());
+ }
+
+ raw3d.push_back(tmpints[1]);
+ raw3d.push_back(tmpints[2]);
+ raw3d.push_back(tmpints[3]);
+ }
+ }
+ }
+
+ // Interpret the parsed data, validate lut sizes
+ if(lutEdgeLen*lutEdgeLen*lutEdgeLen != static_cast<int>(raw3d.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in Pandora lut. ";
+ os << "Incorrect number of lut3d entries. ";
+ os << "Found " << raw3d.size()/3 << ", expected " << lutEdgeLen*lutEdgeLen*lutEdgeLen << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ if(lutEdgeLen*lutEdgeLen*lutEdgeLen == 0)
+ {
+ std::ostringstream os;
+ os << "Parse error in Pandora lut. ";
+ os << "No 3D Lut entries found.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(outputBitDepthMaxValue <= 0)
+ {
+ std::ostringstream os;
+ os << "Parse error in Pandora lut. ";
+ os << "A valid 'out' tag was not found.";
+ throw Exception(os.str().c_str());
+ }
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ // Reformat 3D data
+ cachedFile->lut3D->size[0] = lutEdgeLen;
+ cachedFile->lut3D->size[1] = lutEdgeLen;
+ cachedFile->lut3D->size[2] = lutEdgeLen;
+ cachedFile->lut3D->lut.reserve(raw3d.size());
+
+ float scale = 1.0f / ((float)outputBitDepthMaxValue - 1.0f);
+
+ for(int rIndex=0; rIndex<lutEdgeLen; ++rIndex)
+ {
+ for(int gIndex=0; gIndex<lutEdgeLen; ++gIndex)
+ {
+ for(int bIndex=0; bIndex<lutEdgeLen; ++bIndex)
+ {
+ int i = GetLut3DIndex_B(rIndex, gIndex, bIndex,
+ lutEdgeLen, lutEdgeLen, lutEdgeLen);
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+0]) * scale);
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+1]) * scale);
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+2]) * scale);
+ }
+ }
+ }
+
+ return cachedFile;
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build Truelight .cub Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ }
+ }
+
+ FileFormat * CreateFileFormatPandora()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/FileFormatSpi1D.cpp b/src/core/FileFormatSpi1D.cpp
new file mode 100644
index 0000000..2835c50
--- /dev/null
+++ b/src/core/FileFormatSpi1D.cpp
@@ -0,0 +1,261 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "pystring/pystring.h"
+
+#include <cstdio>
+#include <sstream>
+
+/*
+Version 1
+From -7.5 3.7555555555555555
+Components 1
+Length 4096
+{
+ 0.031525943963232252
+ 0.045645604561056156
+ ...
+}
+
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile()
+ {
+ lut = Lut1D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ Lut1DRcPtr lut;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "spi1d";
+ info.extension = "spi1d";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ // Try and load the format
+ // Raise an exception if it can't be loaded.
+
+ CachedFileRcPtr LocalFileFormat::Read(std::istream & istream) const
+ {
+ Lut1DRcPtr lut1d = Lut1D::Create();
+
+ // Parse Header Info
+ int lut_size = -1;
+ float from_min = 0.0;
+ float from_max = 1.0;
+ int version = -1;
+ int components = -1;
+
+ const int MAX_LINE_SIZE = 4096;
+ char lineBuffer[MAX_LINE_SIZE];
+
+ // PARSE HEADER INFO
+ {
+ std::string headerLine("");
+ do
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ headerLine = std::string(lineBuffer);
+ if(pystring::startswith(headerLine, "Version"))
+ {
+ if(sscanf(lineBuffer, "Version %d", &version)!=1)
+ throw Exception("Invalid 'Version' Tag");
+ }
+ else if(pystring::startswith(headerLine, "From"))
+ {
+ if(sscanf(lineBuffer, "From %f %f", &from_min, &from_max)!=2)
+ throw Exception("Invalid 'From' Tag");
+ }
+ else if(pystring::startswith(headerLine, "Components"))
+ {
+ if(sscanf(lineBuffer, "Components %d", &components)!=1)
+ throw Exception("Invalid 'Components' Tag");
+ }
+ else if(pystring::startswith(headerLine, "Length"))
+ {
+ if(sscanf(lineBuffer, "Length %d", &lut_size)!=1)
+ throw Exception("Invalid 'Length' Tag");
+ }
+ }
+ while (istream.good() && !pystring::startswith(headerLine,"{"));
+ }
+
+ if(version == -1)
+ throw Exception("Could not find 'Version' Tag");
+ if(version != 1)
+ throw Exception("Only format version 1 supported.");
+ if (lut_size == -1)
+ throw Exception("Could not find 'Length' Tag");
+ if (components == -1)
+ throw Exception("Could not find 'Components' Tag");
+ if (components<0 || components>3)
+ throw Exception("Components must be [1,2,3]");
+
+
+
+ for(int i=0; i<3; ++i)
+ {
+ lut1d->from_min[i] = from_min;
+ lut1d->from_max[i] = from_max;
+ lut1d->luts[i].clear();
+ lut1d->luts[i].reserve(lut_size);
+ }
+
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+
+ int lineCount=0;
+ float values[4];
+
+ while (istream.good())
+ {
+ // If 1 component is specificed, use x1 x1 x1 defaultA
+ if(components==1 && sscanf(lineBuffer,"%f",&values[0])==1)
+ {
+ lut1d->luts[0].push_back(values[0]);
+ lut1d->luts[1].push_back(values[0]);
+ lut1d->luts[2].push_back(values[0]);
+ ++lineCount;
+ }
+ // If 2 components are specificed, use x1 x2 0.0
+ else if(components==2 && sscanf(lineBuffer,"%f %f",&values[0],&values[1])==2)
+ {
+ lut1d->luts[0].push_back(values[0]);
+ lut1d->luts[1].push_back(values[1]);
+ lut1d->luts[2].push_back(0.0);
+ ++lineCount;
+ }
+ // If 3 component is specificed, use x1 x2 x3 defaultA
+ else if(components==3 && sscanf(lineBuffer,"%f %f %f",&values[0],&values[1],&values[2])==3)
+ {
+ lut1d->luts[0].push_back(values[0]);
+ lut1d->luts[1].push_back(values[1]);
+ lut1d->luts[2].push_back(values[2]);
+ ++lineCount;
+ }
+
+ if(lineCount == lut_size) break;
+
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ }
+
+ if(lineCount!=lut_size)
+ throw Exception("Not enough entries found.");
+ }
+
+ // 1e-5 rel error is a good threshold when float numbers near 0
+ // are written out with 6 decimal places of precision. This is
+ // a bit aggressive, I.e., changes in the 6th decimal place will
+ // be considered roundoff error, but changes in the 5th decimal
+ // will be considered lut 'intent'.
+ // 1.0
+ // 1.000005 equal to 1.0
+ // 1.000007 equal to 1.0
+ // 1.000010 not equal
+ // 0.0
+ // 0.000001 not equal
+ lut1d->maxerror = 1e-5f;
+ lut1d->errortype = ERROR_RELATIVE;
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+ cachedFile->lut = lut1d;
+ return cachedFile;
+ }
+
+ void LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ if(!cachedFile) // This should never happen.
+ {
+ std::ostringstream os;
+ os << "Cannot build Spi1D Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+
+ CreateLut1DOp(ops,
+ cachedFile->lut,
+ fileTransform.getInterpolation(),
+ newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatSpi1D()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/FileFormatSpi3D.cpp b/src/core/FileFormatSpi3D.cpp
new file mode 100644
index 0000000..b1d8c69
--- /dev/null
+++ b/src/core/FileFormatSpi3D.cpp
@@ -0,0 +1,209 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut3DOp.h"
+#include "pystring/pystring.h"
+
+#include <cstdio>
+#include <sstream>
+
+/*
+SPILUT 1.0
+3 3
+32 32 32
+0 0 0 0.0132509 0.0158522 0.0156622
+0 0 1 0.0136178 0.018843 0.033921
+0 0 2 0.0136487 0.0240918 0.0563014
+0 0 3 0.015706 0.0303061 0.0774135
+
+... entries can be in any order
+... after the expected number of entries is found, file can contain anything
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile()
+ {
+ lut = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ Lut3DRcPtr lut;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "spi3d";
+ info.extension = "spi3d";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+ const int MAX_LINE_SIZE = 4096;
+ char lineBuffer[MAX_LINE_SIZE];
+
+ Lut3DRcPtr lut3d = Lut3D::Create();
+
+ // Read header information
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ if(!pystring::startswith(pystring::lower(lineBuffer), "spilut"))
+ {
+ std::ostringstream os;
+ os << "Lut does not appear to be valid spilut format. ";
+ os << "Expected 'SPILUT'. Found, '" << lineBuffer << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ // TODO: Assert 2nd line is 3 3
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+
+ // Get LUT Size
+ // TODO: Error handling
+ int rSize, gSize, bSize;
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ sscanf(lineBuffer, "%d %d %d", &rSize, &gSize, &bSize);
+
+ lut3d->size[0] = rSize;
+ lut3d->size[1] = gSize;
+ lut3d->size[2] = bSize;
+ lut3d->lut.resize(rSize * gSize * bSize * 3);
+
+ // Parse table
+ int index = 0;
+ int rIndex, gIndex, bIndex;
+ float redValue, greenValue, blueValue;
+
+ int entriesRemaining = rSize * gSize * bSize;
+
+ while (istream.good() && entriesRemaining > 0)
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+
+ if (sscanf(lineBuffer, "%d %d %d %f %f %f",
+ &rIndex, &gIndex, &bIndex,
+ &redValue, &greenValue, &blueValue) == 6)
+ {
+ index = GetLut3DIndex_B(rIndex, gIndex, bIndex,
+ rSize, gSize, bSize);
+ if(index < 0 || index >= (int) lut3d->lut.size())
+ {
+ std::ostringstream os;
+ os << "Cannot load .spi3d lut, data is invalid. ";
+ os << "A lut entry is specified (";
+ os << rIndex << " " << gIndex << " " << bIndex;
+ os << " that falls outside of the cube.";
+ throw Exception(os.str().c_str());
+ }
+
+ lut3d->lut[index+0] = redValue;
+ lut3d->lut[index+1] = greenValue;
+ lut3d->lut[index+2] = blueValue;
+
+ entriesRemaining--;
+ }
+ }
+
+ // Have we fully populated the table?
+ if (entriesRemaining>0)
+ throw Exception("Not enough entries found.");
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+ cachedFile->lut = lut3d;
+ return cachedFile;
+ }
+
+ void LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ if(!cachedFile) // This should never happen.
+ {
+ std::ostringstream os;
+ os << "Cannot build Spi3D Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+
+ CreateLut3DOp(ops,
+ cachedFile->lut,
+ fileTransform.getInterpolation(),
+ newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatSpi3D()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/FileFormatSpiMtx.cpp b/src/core/FileFormatSpiMtx.cpp
new file mode 100644
index 0000000..e14f557
--- /dev/null
+++ b/src/core/FileFormatSpiMtx.cpp
@@ -0,0 +1,195 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "MatrixOps.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile()
+ {
+ memset(m44, 0, 16*sizeof(float));
+ memset(offset4, 0, 4*sizeof(float));
+ };
+ ~LocalCachedFile() {};
+
+ float m44[16];
+ float offset4[4];
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "spimtx";
+ info.extension = "spimtx";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+
+ // Read the entire file.
+ std::ostringstream fileStream;
+
+ {
+ const int MAX_LINE_SIZE = 4096;
+ char lineBuffer[MAX_LINE_SIZE];
+
+ while (istream.good())
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ fileStream << std::string(lineBuffer) << " ";
+ }
+ }
+
+ // Turn it into parts
+ std::vector<std::string> lineParts;
+ pystring::split(pystring::strip(fileStream.str()), lineParts);
+ if(lineParts.size() != 12)
+ {
+ std::ostringstream os;
+ os << "Error parsing .spimtx file. ";
+ os << "File must contain 12 float entries. ";
+ os << lineParts.size() << " found.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Turn the parts into floats
+ std::vector<float> floatArray;
+ if(!StringVecToFloatVec(floatArray, lineParts))
+ {
+ std::ostringstream os;
+ os << "Error parsing .spimtx file. ";
+ os << "File must contain all float entries. ";
+ throw Exception(os.str().c_str());
+ }
+
+
+ // Put the bits in the right place
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ cachedFile->m44[0] = floatArray[0];
+ cachedFile->m44[1] = floatArray[1];
+ cachedFile->m44[2] = floatArray[2];
+ cachedFile->m44[3] = 0.0f;
+
+ cachedFile->m44[4] = floatArray[4];
+ cachedFile->m44[5] = floatArray[5];
+ cachedFile->m44[6] = floatArray[6];
+ cachedFile->m44[7] = 0.0f;
+
+ cachedFile->m44[8] = floatArray[8];
+ cachedFile->m44[9] = floatArray[9];
+ cachedFile->m44[10] = floatArray[10];
+ cachedFile->m44[11] = 0.0f;
+
+ cachedFile->m44[12] = 0.0f;
+ cachedFile->m44[13] = 0.0f;
+ cachedFile->m44[14] = 0.0f;
+ cachedFile->m44[15] = 1.0f;
+
+ cachedFile->offset4[0] = floatArray[3] / 65535.0f;
+ cachedFile->offset4[1] = floatArray[7] / 65535.0f;
+ cachedFile->offset4[2] = floatArray[11] / 65535.0f;
+ cachedFile->offset4[3] = 0.0f;
+
+ return cachedFile;
+ }
+
+ void LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ if(!cachedFile) // This should never happen.
+ {
+ std::ostringstream os;
+ os << "Cannot build SpiMtx Ops. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+
+ CreateMatrixOffsetOp(ops,
+ cachedFile->m44,
+ cachedFile->offset4,
+ newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatSpiMtx()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/FileFormatTruelight.cpp b/src/core/FileFormatTruelight.cpp
new file mode 100644
index 0000000..a7ccc48
--- /dev/null
+++ b/src/core/FileFormatTruelight.cpp
@@ -0,0 +1,620 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <iostream>
+#include <iterator>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+// This implements the spec for:
+// Per http://www.filmlight.ltd.uk/resources/documents/truelight/white-papers_tl.php
+// FL-TL-TN-0388-TLCubeFormat2.0.pdf
+//
+// Known deficiency in implementation:
+// 1D shaper luts (InputLUT) using integer encodings (vs float) are not supported.
+// How to we determine if the input is integer? MaxVal? Or do we look for a decimal-point?
+// How about scientific notation? (which is explicitly allowed?)
+
+/*
+The input LUT is used to interpolate a higher precision LUT matched to the particular image
+format. For integer formats, the range 0-1 is mapped onto the integer range. Floating point
+values outside the 0-1 range are allowed but may be truncated for integer formats.
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile () :
+ has1D(false),
+ has3D(false)
+ {
+ lut1D = Lut1D::Create();
+ lut3D = Lut3D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ bool has1D;
+ bool has3D;
+ Lut1DRcPtr lut1D;
+ Lut3DRcPtr lut3D;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "truelight";
+ info.extension = "cub";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+ // this shouldn't happen
+ if(!istream)
+ {
+ throw Exception ("File stream empty when trying to read Truelight .cub lut");
+ }
+
+ // Validate the file type
+ std::string line;
+ if(!nextline(istream, line) ||
+ !pystring::startswith(pystring::lower(line), "# truelight cube"))
+ {
+ throw Exception("Lut doesn't seem to be a Truelight .cub lut.");
+ }
+
+ // Parse the file
+ std::vector<float> raw1d;
+ std::vector<float> raw3d;
+ int size3d[] = { 0, 0, 0 };
+ int size1d = 0;
+ {
+ std::vector<std::string> parts;
+ std::vector<float> tmpfloats;
+
+ bool in1d = false;
+ bool in3d = false;
+
+ while(nextline(istream, line))
+ {
+ // Strip, lowercase, and split the line
+ pystring::split(pystring::lower(pystring::strip(line)), parts);
+
+ if(parts.empty()) continue;
+
+ // Parse header metadata (which starts with #)
+ if(pystring::startswith(parts[0],"#"))
+ {
+ if(parts.size() < 2) continue;
+
+ if(parts[1] == "width")
+ {
+ if(parts.size() != 5 ||
+ !StringToInt( &size3d[0], parts[2].c_str()) ||
+ !StringToInt( &size3d[1], parts[3].c_str()) ||
+ !StringToInt( &size3d[2], parts[4].c_str()))
+ {
+ throw Exception("Malformed width tag in Truelight .cub lut.");
+ }
+
+ raw3d.reserve(3*size3d[0]*size3d[1]*size3d[2]);
+ }
+ else if(parts[1] == "lutlength")
+ {
+ if(parts.size() != 3 ||
+ !StringToInt( &size1d, parts[2].c_str()))
+ {
+ throw Exception("Malformed lutlength tag in Truelight .cub lut.");
+ }
+ raw1d.reserve(3*size1d);
+ }
+ else if(parts[1] == "inputlut")
+ {
+ in1d = true;
+ in3d = false;
+ }
+ else if(parts[1] == "cube")
+ {
+ in3d = true;
+ in1d = false;
+ }
+ else if(parts[1] == "end")
+ {
+ in3d = false;
+ in1d = false;
+
+ // If we hit the end tag, don't bother searching further in the file.
+ break;
+ }
+ }
+
+
+ if(in1d || in3d)
+ {
+ if(StringVecToFloatVec(tmpfloats, parts) && (tmpfloats.size() == 3))
+ {
+ if(in1d)
+ {
+ raw1d.push_back(tmpfloats[0]);
+ raw1d.push_back(tmpfloats[1]);
+ raw1d.push_back(tmpfloats[2]);
+ }
+ else if(in3d)
+ {
+ raw3d.push_back(tmpfloats[0]);
+ raw3d.push_back(tmpfloats[1]);
+ raw3d.push_back(tmpfloats[2]);
+ }
+ }
+ }
+ }
+ }
+
+ // Interpret the parsed data, validate lut sizes
+
+ if(size1d != static_cast<int>(raw1d.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in Truelight .cub lut. ";
+ os << "Incorrect number of lut1d entries. ";
+ os << "Found " << raw1d.size()/3 << ", expected " << size1d << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ if(size3d[0]*size3d[1]*size3d[2] != static_cast<int>(raw3d.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in Truelight .cub lut. ";
+ os << "Incorrect number of lut3d entries. ";
+ os << "Found " << raw3d.size()/3 << ", expected " << size3d[0]*size3d[1]*size3d[2] << ".";
+ throw Exception(os.str().c_str());
+ }
+
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ cachedFile->has1D = (size1d>0);
+ cachedFile->has3D = (size3d[0]*size3d[1]*size3d[2]>0);
+
+ // Reformat 1D data
+ if(cachedFile->has1D)
+ {
+ for(int channel=0; channel<3; ++channel)
+ {
+ // Determine the scale factor for the 1d lut. Example:
+ // The inputlut feeding a 6x6x6 3dlut should be scaled from 0.0-5.0.
+ // Beware: Nuke Truelight Writer (at least 6.3 and before) is busted
+ // and does this scaling incorrectly.
+
+ float descale = 1.0f;
+ if(cachedFile->has3D)
+ {
+ descale = 1.0f / static_cast<float>(size3d[channel]-1);
+ }
+
+ cachedFile->lut1D->luts[channel].resize(size1d);
+ for(int i=0; i<size1d; ++i)
+ {
+ cachedFile->lut1D->luts[channel][i] = raw1d[3*i+channel] * descale;
+ }
+ }
+
+ // 1e-5 rel error is a good threshold when float numbers near 0
+ // are written out with 6 decimal places of precision. This is
+ // a bit aggressive, I.e., changes in the 6th decimal place will
+ // be considered roundoff error, but changes in the 5th decimal
+ // will be considered lut 'intent'.
+ // 1.0
+ // 1.000005 equal to 1.0
+ // 1.000007 equal to 1.0
+ // 1.000010 not equal
+ // 0.0
+ // 0.000001 not equal
+
+ cachedFile->lut1D->maxerror = 1e-5f;
+ cachedFile->lut1D->errortype = ERROR_RELATIVE;
+ }
+
+ // Reformat 3D data
+ if(cachedFile->has3D)
+ {
+ cachedFile->lut3D->size[0] = size3d[0];
+ cachedFile->lut3D->size[1] = size3d[1];
+ cachedFile->lut3D->size[2] = size3d[2];
+ cachedFile->lut3D->lut = raw3d;
+ }
+
+ return cachedFile;
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build Truelight .cub Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ // TODO: INTERP_LINEAR should not be hard-coded.
+ // Instead query 'highest' interpolation?
+ // (right now, it's linear). If cubic is added, consider
+ // using it
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ if(cachedFile->has1D)
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ INTERP_LINEAR, newDir);
+ }
+
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+
+ if(cachedFile->has1D)
+ {
+ CreateLut1DOp(ops, cachedFile->lut1D,
+ INTERP_LINEAR, newDir);
+ }
+ }
+ }
+ }
+
+ FileFormat * CreateFileFormatTruelight()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(FileFormatTruelight, ShaperAndLut3D)
+{
+ // This lowers the red channel by 0.5, other channels are unaffected.
+ const char * luttext = "# Truelight Cube v2.0\n"
+ "# iDims 3\n"
+ "# oDims 3\n"
+ "# width 3 3 3\n"
+ "# lutLength 5\n"
+ "# InputLUT\n"
+ " 0.000000 0.000000 0.000000\n"
+ " 0.500000 0.500000 0.500000\n"
+ " 1.000000 1.000000 1.000000\n"
+ " 1.500000 1.500000 1.500000\n"
+ " 2.000000 2.000000 2.000000\n"
+ "\n"
+ "# Cube\n"
+ " 0.000000 0.000000 0.000000\n"
+ " 0.250000 0.000000 0.000000\n"
+ " 0.500000 0.000000 0.000000\n"
+ " 0.000000 0.500000 0.000000\n"
+ " 0.250000 0.500000 0.000000\n"
+ " 0.500000 0.500000 0.000000\n"
+ " 0.000000 1.000000 0.000000\n"
+ " 0.250000 1.000000 0.000000\n"
+ " 0.500000 1.000000 0.000000\n"
+ " 0.000000 0.000000 0.500000\n"
+ " 0.250000 0.000000 0.500000\n"
+ " 0.500000 0.000000 0.500000\n"
+ " 0.000000 0.500000 0.500000\n"
+ " 0.250000 0.500000 0.500000\n"
+ " 0.500000 0.500000 0.500000\n"
+ " 0.000000 1.000000 0.500000\n"
+ " 0.250000 1.000000 0.500000\n"
+ " 0.500000 1.000000 0.500000\n"
+ " 0.000000 0.000000 1.000000\n"
+ " 0.250000 0.000000 1.000000\n"
+ " 0.500000 0.000000 1.000000\n"
+ " 0.000000 0.500000 1.000000\n"
+ " 0.250000 0.500000 1.000000\n"
+ " 0.500000 0.500000 1.000000\n"
+ " 0.000000 1.000000 1.000000\n"
+ " 0.250000 1.000000 1.000000\n"
+ " 0.500000 1.000000 1.000000\n"
+ "\n"
+ "# end\n"
+ "\n"
+ "# Truelight profile\n"
+ "title{madeup on some display}\n"
+ "print{someprint}\n"
+ "display{some}\n"
+ "cubeFile{madeup.cube}\n"
+ "\n"
+ " # This last line confirms 'end' tag is obeyed\n"
+ " 1.23456 1.23456 1.23456\n";
+
+ std::istringstream lutIStream;
+ lutIStream.str(luttext);
+
+ // Read file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile;
+ OIIO_CHECK_NO_THOW(cachedFile = tester.Read(lutIStream));
+ OCIO::LocalCachedFileRcPtr lut = OCIO::DynamicPtrCast<OCIO::LocalCachedFile>(cachedFile);
+
+ OIIO_CHECK_ASSERT(lut->has1D);
+ OIIO_CHECK_ASSERT(lut->has3D);
+
+ float data[4*3] = { 0.1f, 0.2f, 0.3f, 0.0f,
+ 1.0f, 0.5f, 0.123456f, 0.0f,
+ -1.0f, 1.5f, 0.5f, 0.0f };
+
+ float result[4*3] = { 0.05f, 0.2f, 0.3f, 0.0f,
+ 0.50f, 0.5f, 0.123456f, 0.0f,
+ 0.0f, 1.5f, 0.5f, 0.0f };
+
+ OCIO::OpRcPtrVec ops;
+ if(lut->has1D)
+ {
+ CreateLut1DOp(ops, lut->lut1D,
+ OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ if(lut->has3D)
+ {
+ CreateLut3DOp(ops, lut->lut3D,
+ OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ FinalizeOpVec(ops);
+
+
+ // Apply the result
+ for(OCIO::OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ ops[i]->apply(data, 3);
+ }
+
+ for(int i=0; i<3; ++i)
+ {
+ OIIO_CHECK_CLOSE( data[i], result[i], 1.0e-6 );
+ }
+}
+
+OIIO_ADD_TEST(FileFormatTruelight, Shaper)
+{
+ const char * luttext = "# Truelight Cube v2.0\n"
+ "# lutLength 11\n"
+ "# iDims 3\n"
+ "\n"
+ "\n"
+ "# InputLUT\n"
+ " 0.000 0.000 -0.000\n"
+ " 0.200 0.010 -0.100\n"
+ " 0.400 0.040 -0.200\n"
+ " 0.600 0.090 -0.300\n"
+ " 0.800 0.160 -0.400\n"
+ " 1.000 0.250 -0.500\n"
+ " 1.200 0.360 -0.600\n"
+ " 1.400 0.490 -0.700\n"
+ " 1.600 0.640 -0.800\n"
+ " 1.800 0.820 -0.900\n"
+ " 2.000 1.000 -1.000\n"
+ "\n\n\n"
+ "# end\n";
+
+ std::istringstream lutIStream;
+ lutIStream.str(luttext);
+
+ // Read file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile;
+ OIIO_CHECK_NO_THOW(cachedFile = tester.Read(lutIStream));
+
+ OCIO::LocalCachedFileRcPtr lut = OCIO::DynamicPtrCast<OCIO::LocalCachedFile>(cachedFile);
+
+ OIIO_CHECK_ASSERT(lut->has1D);
+ OIIO_CHECK_ASSERT(!lut->has3D);
+
+ float data[4*3] = { 0.1f, 0.2f, 0.3f, 0.0f,
+ 1.0f, 0.5f, 0.123456f, 0.0f,
+ -1.0f, 1.5f, 0.5f, 0.0f };
+
+ float result[4*3] = { 0.2f, 0.04f, -0.3f, 0.0f,
+ 2.0f, 0.25f, -0.123456f, 0.0f,
+ 0.0f, 1.0f, -0.5f, 0.0f };
+
+ OCIO::OpRcPtrVec ops;
+ if(lut->has1D)
+ {
+ CreateLut1DOp(ops, lut->lut1D,
+ OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ if(lut->has3D)
+ {
+ CreateLut3DOp(ops, lut->lut3D,
+ OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ FinalizeOpVec(ops);
+
+
+ // Apply the result
+ for(OCIO::OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ ops[i]->apply(data, 3);
+ }
+
+ for(int i=0; i<3; ++i)
+ {
+ OIIO_CHECK_CLOSE( data[i], result[i], 1.0e-6 );
+ }
+}
+
+
+OIIO_ADD_TEST(FileFormatTruelight, Lut3D)
+{
+ // This lowers the red channel by 0.5, other channels are unaffected.
+ const char * luttext = "# Truelight Cube v2.0\n"
+ "# iDims 3\n"
+ "# oDims 3\n"
+ "# width 3 3 3\n"
+ "\n\n\n"
+ "# Cube\n"
+ " 0.000000 0.000000 0.000000\n"
+ " 0.250000 0.000000 0.000000\n"
+ " 0.500000 0.000000 0.000000\n"
+ " 0.000000 0.500000 0.000000\n"
+ " 0.250000 0.500000 0.000000\n"
+ " 0.500000 0.500000 0.000000\n"
+ " 0.000000 1.000000 0.000000\n"
+ " 0.250000 1.000000 0.000000\n"
+ " 0.500000 1.000000 0.000000\n"
+ " 0.000000 0.000000 0.500000\n"
+ " 0.250000 0.000000 0.500000\n"
+ " 0.500000 0.000000 0.500000\n"
+ " 0.000000 0.500000 0.500000\n"
+ " 0.250000 0.500000 0.500000\n"
+ " 0.500000 0.500000 0.500000\n"
+ " 0.000000 1.000000 0.500000\n"
+ " 0.250000 1.000000 0.500000\n"
+ " 0.500000 1.000000 0.500000\n"
+ " 0.000000 0.000000 1.000000\n"
+ " 0.250000 0.000000 1.000000\n"
+ " 0.500000 0.000000 1.000000\n"
+ " 0.000000 0.500000 1.000000\n"
+ " 0.250000 0.500000 1.000000\n"
+ " 0.500000 0.500000 1.000000\n"
+ " 0.000000 1.000000 1.000000\n"
+ " 0.250000 1.000000 1.000000\n"
+ " 0.500000 1.000000 1.000000\n"
+ "\n"
+ "# end\n";
+
+ std::istringstream lutIStream;
+ lutIStream.str(luttext);
+
+ // Read file
+ OCIO::LocalFileFormat tester;
+ OCIO::CachedFileRcPtr cachedFile;
+ OIIO_CHECK_NO_THOW(cachedFile = tester.Read(lutIStream));
+ OCIO::LocalCachedFileRcPtr lut = OCIO::DynamicPtrCast<OCIO::LocalCachedFile>(cachedFile);
+
+ OIIO_CHECK_ASSERT(!lut->has1D);
+ OIIO_CHECK_ASSERT(lut->has3D);
+
+ float data[4*3] = { 0.1f, 0.2f, 0.3f, 0.0f,
+ 1.0f, 0.5f, 0.123456f, 0.0f,
+ -1.0f, 1.5f, 0.5f, 0.0f };
+
+ float result[4*3] = { 0.05f, 0.2f, 0.3f, 0.0f,
+ 0.50f, 0.5f, 0.123456f, 0.0f,
+ 0.0f, 1.5f, 0.5f, 0.0f };
+
+ OCIO::OpRcPtrVec ops;
+ if(lut->has1D)
+ {
+ CreateLut1DOp(ops, lut->lut1D,
+ OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ if(lut->has3D)
+ {
+ CreateLut3DOp(ops, lut->lut3D,
+ OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ FinalizeOpVec(ops);
+
+
+ // Apply the result
+ for(OCIO::OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ ops[i]->apply(data, 3);
+ }
+
+ for(int i=0; i<3; ++i)
+ {
+ OIIO_CHECK_CLOSE( data[i], result[i], 1.0e-6 );
+ }
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/FileFormatVF.cpp b/src/core/FileFormatVF.cpp
new file mode 100644
index 0000000..cb46ef0
--- /dev/null
+++ b/src/core/FileFormatVF.cpp
@@ -0,0 +1,297 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut3DOp.h"
+#include "MatrixOps.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile () :
+ useMatrix(false)
+ {
+ lut3D = Lut3D::Create();
+ memset(m44, 0, 16*sizeof(float));
+ };
+ ~LocalCachedFile() {};
+
+ Lut3DRcPtr lut3D;
+ float m44[16];
+ bool useMatrix;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "nukevf";
+ info.extension = "vf";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ CachedFileRcPtr
+ LocalFileFormat::Read(std::istream & istream) const
+ {
+ // this shouldn't happen
+ if(!istream)
+ {
+ throw Exception ("File stream empty when trying to read .vf lut");
+ }
+
+ // Validate the file type
+ std::string line;
+ if(!nextline(istream, line) ||
+ !pystring::startswith(pystring::lower(line), "#inventor"))
+ {
+ throw Exception("Lut doesn't seem to be a .vf lut. Expecting '#Inventor V2.1 ascii'.");
+ }
+
+ // Parse the file
+ std::vector<float> raw3d;
+ int size3d[] = { 0, 0, 0 };
+ std::vector<float> global_transform;
+
+ {
+ std::vector<std::string> parts;
+ std::vector<float> tmpfloats;
+
+ bool in3d = false;
+
+ while(nextline(istream, line))
+ {
+ // Strip, lowercase, and split the line
+ pystring::split(pystring::lower(pystring::strip(line)), parts);
+
+ if(parts.empty()) continue;
+
+ if(pystring::startswith(parts[0],"#")) continue;
+
+ if(!in3d)
+ {
+ if(parts[0] == "grid_size")
+ {
+ if(parts.size() != 4 ||
+ !StringToInt( &size3d[0], parts[1].c_str()) ||
+ !StringToInt( &size3d[1], parts[2].c_str()) ||
+ !StringToInt( &size3d[2], parts[3].c_str()))
+ {
+ throw Exception("Malformed grid_size tag in .vf lut.");
+ }
+
+ raw3d.reserve(3*size3d[0]*size3d[1]*size3d[2]);
+ }
+ else if(parts[0] == "global_transform")
+ {
+ if(parts.size() != 17)
+ {
+ throw Exception("Malformed global_transform tag. 16 floats expected.");
+ }
+
+ parts.erase(parts.begin()); // Drop the 1st entry. (the tag)
+ if(!StringVecToFloatVec(global_transform, parts) || global_transform.size() != 16)
+ {
+ throw Exception("Malformed global_transform tag. Could not convert to float array.");
+ }
+ }
+ // TODO: element_size (aka scale3)
+ // TODO: world_origin (aka translate3)
+ else if(parts[0] == "data")
+ {
+ in3d = true;
+ }
+ }
+ else // (in3d)
+ {
+ if(StringVecToFloatVec(tmpfloats, parts) && (tmpfloats.size() == 3))
+ {
+ raw3d.push_back(tmpfloats[0]);
+ raw3d.push_back(tmpfloats[1]);
+ raw3d.push_back(tmpfloats[2]);
+ }
+ }
+ }
+ }
+
+ // Interpret the parsed data, validate lut sizes
+ if(size3d[0]*size3d[1]*size3d[2] != static_cast<int>(raw3d.size()/3))
+ {
+ std::ostringstream os;
+ os << "Parse error in .vf lut. ";
+ os << "Incorrect number of lut3d entries. ";
+ os << "Found " << raw3d.size()/3 << ", expected " << size3d[0]*size3d[1]*size3d[2] << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ if(size3d[0]*size3d[1]*size3d[2] == 0)
+ {
+ std::ostringstream os;
+ os << "Parse error in .vf lut. ";
+ os << "No 3D Lut entries found.";
+ throw Exception(os.str().c_str());
+ }
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+
+ // Setup the global matrix.
+ // (Nuke pre-scales this by the 3dlut size, so we must undo that here)
+ if(global_transform.size() == 16)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ global_transform[4*i+0] *= static_cast<float>(size3d[0]);
+ global_transform[4*i+1] *= static_cast<float>(size3d[1]);
+ global_transform[4*i+2] *= static_cast<float>(size3d[2]);
+ }
+
+ memcpy(cachedFile->m44, &global_transform[0], 16*sizeof(float));
+ cachedFile->useMatrix = true;
+ }
+
+ // Reformat 3D data
+ cachedFile->lut3D->size[0] = size3d[0];
+ cachedFile->lut3D->size[1] = size3d[1];
+ cachedFile->lut3D->size[2] = size3d[2];
+ cachedFile->lut3D->lut.reserve(raw3d.size());
+
+ for(int rIndex=0; rIndex<size3d[0]; ++rIndex)
+ {
+ for(int gIndex=0; gIndex<size3d[1]; ++gIndex)
+ {
+ for(int bIndex=0; bIndex<size3d[2]; ++bIndex)
+ {
+ int i = GetLut3DIndex_B(rIndex, gIndex, bIndex,
+ size3d[0], size3d[1], size3d[2]);
+
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+0]));
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+1]));
+ cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+2]));
+ }
+ }
+ }
+
+ return cachedFile;
+ }
+
+ void
+ LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ // This should never happen.
+ if(!cachedFile)
+ {
+ std::ostringstream os;
+ os << "Cannot build .vf Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+ if(newDir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "Cannot build file format transform,";
+ os << " unspecified transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(newDir == TRANSFORM_DIR_FORWARD)
+ {
+ if(cachedFile->useMatrix)
+ {
+ CreateMatrixOp(ops, cachedFile->m44, newDir);
+ }
+
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+ }
+ else if(newDir == TRANSFORM_DIR_INVERSE)
+ {
+ CreateLut3DOp(ops, cachedFile->lut3D,
+ fileTransform.getInterpolation(), newDir);
+
+ if(cachedFile->useMatrix)
+ {
+ CreateMatrixOp(ops, cachedFile->m44, newDir);
+ }
+ }
+ }
+ }
+
+ FileFormat * CreateFileFormatVF()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+// TODO: Unit test
diff --git a/src/core/FileTransform.cpp b/src/core/FileTransform.cpp
new file mode 100644
index 0000000..45b5a3e
--- /dev/null
+++ b/src/core/FileTransform.cpp
@@ -0,0 +1,579 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Logging.h"
+#include "Mutex.h"
+#include "NoOps.h"
+#include "PathUtils.h"
+#include "pystring/pystring.h"
+
+#include <fstream>
+#include <map>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ FileTransformRcPtr FileTransform::Create()
+ {
+ return FileTransformRcPtr(new FileTransform(), &deleter);
+ }
+
+ void FileTransform::deleter(FileTransform* t)
+ {
+ delete t;
+ }
+
+
+ class FileTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ std::string src_;
+ std::string cccid_;
+ Interpolation interp_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD),
+ interp_(INTERP_UNKNOWN)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ src_ = rhs.src_;
+ cccid_ = rhs.cccid_;
+ interp_ = rhs.interp_;
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ FileTransform::FileTransform()
+ : m_impl(new FileTransform::Impl)
+ {
+ }
+
+ TransformRcPtr FileTransform::createEditableCopy() const
+ {
+ FileTransformRcPtr transform = FileTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ FileTransform::~FileTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ FileTransform& FileTransform::operator= (const FileTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection FileTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void FileTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ const char * FileTransform::getSrc() const
+ {
+ return getImpl()->src_.c_str();
+ }
+
+ void FileTransform::setSrc(const char * src)
+ {
+ getImpl()->src_ = src;
+ }
+
+ const char * FileTransform::getCCCId() const
+ {
+ return getImpl()->cccid_.c_str();
+ }
+
+ void FileTransform::setCCCId(const char * cccid)
+ {
+ getImpl()->cccid_ = cccid;
+ }
+
+ Interpolation FileTransform::getInterpolation() const
+ {
+ return getImpl()->interp_;
+ }
+
+ void FileTransform::setInterpolation(Interpolation interp)
+ {
+ getImpl()->interp_ = interp;
+ }
+
+ int FileTransform::getNumFormats()
+ {
+ return FormatRegistry::GetInstance().getNumFormats(FORMAT_CAPABILITY_READ);
+ }
+
+ const char * FileTransform::getFormatNameByIndex(int index)
+ {
+ return FormatRegistry::GetInstance().getFormatNameByIndex(FORMAT_CAPABILITY_READ, index);
+ }
+
+ const char * FileTransform::getFormatExtensionByIndex(int index)
+ {
+ return FormatRegistry::GetInstance().getFormatExtensionByIndex(FORMAT_CAPABILITY_READ, index);
+ }
+
+ std::ostream& operator<< (std::ostream& os, const FileTransform& t)
+ {
+ os << "<FileTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << "interpolation=" << InterpolationToString(t.getInterpolation()) << ", ";
+ os << "src='" << t.getSrc() << "', ";
+ os << "cccid='" << t.getCCCId() << "'";
+ os << ">";
+
+ return os;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // NOTE: You must be mindful when editing this function.
+ // to be resiliant to the static initialization order 'fiasco'
+ //
+ // See
+ // http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
+ // http://stackoverflow.com/questions/335369/finding-c-static-initialization-order-problems
+ // for more info.
+
+ namespace
+ {
+ FormatRegistry* g_formatRegistry = NULL;
+ Mutex g_formatRegistryLock;
+ }
+
+ FormatRegistry & FormatRegistry::GetInstance()
+ {
+ AutoMutex lock(g_formatRegistryLock);
+
+ if(!g_formatRegistry)
+ {
+ g_formatRegistry = new FormatRegistry();
+ }
+
+ return *g_formatRegistry;
+ }
+
+ FormatRegistry::FormatRegistry()
+ {
+ registerFileFormat(CreateFileFormat3DL());
+ registerFileFormat(CreateFileFormatCCC());
+ registerFileFormat(CreateFileFormatCC());
+ registerFileFormat(CreateFileFormatCSP());
+ registerFileFormat(CreateFileFormatHDL());
+ registerFileFormat(CreateFileFormatIridasItx());
+ registerFileFormat(CreateFileFormatIridasCube());
+ registerFileFormat(CreateFileFormatIridasLook());
+ registerFileFormat(CreateFileFormatPandora());
+ registerFileFormat(CreateFileFormatSpi1D());
+ registerFileFormat(CreateFileFormatSpi3D());
+ registerFileFormat(CreateFileFormatSpiMtx());
+ registerFileFormat(CreateFileFormatTruelight());
+ registerFileFormat(CreateFileFormatVF());
+ }
+
+ FormatRegistry::~FormatRegistry()
+ {
+ }
+
+ FileFormat* FormatRegistry::getFileFormatByName(const std::string & name) const
+ {
+ FileFormatMap::const_iterator iter = m_formatsByName.find(
+ pystring::lower(name));
+ if(iter != m_formatsByName.end())
+ return iter->second;
+ return NULL;
+ }
+
+ FileFormat* FormatRegistry::getFileFormatForExtension(const std::string & extension) const
+ {
+ FileFormatMap::const_iterator iter = m_formatsByExtension.find(
+ pystring::lower(extension));
+ if(iter != m_formatsByExtension.end())
+ return iter->second;
+ return NULL;
+ }
+
+ void FormatRegistry::registerFileFormat(FileFormat* format)
+ {
+ FormatInfoVec formatInfoVec;
+ format->GetFormatInfo(formatInfoVec);
+
+ if(formatInfoVec.empty())
+ {
+ std::ostringstream os;
+ os << "FileFormat Registry error. ";
+ os << "A file format did not provide the required format info.";
+ throw Exception(os.str().c_str());
+ }
+
+ for(unsigned int i=0; i<formatInfoVec.size(); ++i)
+ {
+ if(formatInfoVec[i].capabilities == FORMAT_CAPABILITY_NONE)
+ {
+ std::ostringstream os;
+ os << "FileFormat Registry error. ";
+ os << "A file format does not define either reading or writing.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(getFileFormatByName(formatInfoVec[i].name))
+ {
+ std::ostringstream os;
+ os << "Cannot register multiple file formats named, '";
+ os << formatInfoVec[i].name << "'.";
+ throw Exception(os.str().c_str());
+ }
+
+ m_formatsByName[formatInfoVec[i].name] = format;
+
+ // For now, dont worry if multiple formats register the same extension
+ // TODO: keep track of all of em! (make the value a vector)
+ m_formatsByExtension[formatInfoVec[i].extension] = format;
+
+ if(formatInfoVec[i].capabilities & FORMAT_CAPABILITY_READ)
+ {
+ m_readFormatNames.push_back(formatInfoVec[i].name);
+ m_readFormatExtensions.push_back(formatInfoVec[i].extension);
+ }
+
+ if(formatInfoVec[i].capabilities & FORMAT_CAPABILITY_WRITE)
+ {
+ m_writeFormatNames.push_back(formatInfoVec[i].name);
+ m_writeFormatExtensions.push_back(formatInfoVec[i].extension);
+ }
+ }
+
+ m_rawFormats.push_back(format);
+ }
+
+ int FormatRegistry::getNumRawFormats() const
+ {
+ return static_cast<int>(m_rawFormats.size());
+ }
+
+ FileFormat* FormatRegistry::getRawFormatByIndex(int index) const
+ {
+ if(index<0 || index>=getNumRawFormats())
+ {
+ return NULL;
+ }
+
+ return m_rawFormats[index];
+ }
+
+ int FormatRegistry::getNumFormats(int capability) const
+ {
+ if(capability == FORMAT_CAPABILITY_READ)
+ {
+ return static_cast<int>(m_readFormatNames.size());
+ }
+ else if(capability == FORMAT_CAPABILITY_WRITE)
+ {
+ return static_cast<int>(m_writeFormatNames.size());
+ }
+ return 0;
+ }
+
+ const char * FormatRegistry::getFormatNameByIndex(int capability, int index) const
+ {
+ if(capability == FORMAT_CAPABILITY_READ)
+ {
+ if(index<0 || index>=static_cast<int>(m_readFormatNames.size()))
+ {
+ return "";
+ }
+ return m_readFormatNames[index].c_str();
+ }
+ else if(capability == FORMAT_CAPABILITY_WRITE)
+ {
+ if(index<0 || index>=static_cast<int>(m_readFormatNames.size()))
+ {
+ return "";
+ }
+ return m_writeFormatNames[index].c_str();
+ }
+ return "";
+ }
+
+ const char * FormatRegistry::getFormatExtensionByIndex(int capability, int index) const
+ {
+ if(capability == FORMAT_CAPABILITY_READ)
+ {
+ if(index<0 || index>=static_cast<int>(m_readFormatExtensions.size()))
+ {
+ return "";
+ }
+ return m_readFormatExtensions[index].c_str();
+ }
+ else if(capability == FORMAT_CAPABILITY_WRITE)
+ {
+ if(index<0 || index>=static_cast<int>(m_writeFormatExtensions.size()))
+ {
+ return "";
+ }
+ return m_writeFormatExtensions[index].c_str();
+ }
+ return "";
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ FileFormat::~FileFormat()
+ {
+
+ }
+
+ std::string FileFormat::getName() const
+ {
+ FormatInfoVec infoVec;
+ GetFormatInfo(infoVec);
+ if(infoVec.size()>0)
+ {
+ return infoVec[0].name;
+ }
+ return "Unknown Format";
+ }
+
+
+
+ void FileFormat::Write(const Baker & /*baker*/,
+ const std::string & formatName,
+ std::ostream & /*ostream*/) const
+ {
+ std::ostringstream os;
+ os << "Format " << formatName << " does not support writing.";
+ throw Exception(os.str().c_str());
+ }
+
+ namespace
+ {
+ typedef std::pair<FileFormat*, CachedFileRcPtr> FileCachePair;
+ typedef std::map<std::string, FileCachePair> FileCacheMap;
+
+ FileCacheMap g_fileCache;
+ Mutex g_fileCacheLock;
+
+ // Get the FileFormat, CachedFilePtr
+ // or throw an exception.
+
+ FileCachePair GetFile(const std::string & filepath)
+ {
+ // Acquire fileCache mutex
+ AutoMutex lock(g_fileCacheLock);
+
+ FileCacheMap::iterator iter = g_fileCache.find(filepath);
+ if(iter != g_fileCache.end())
+ {
+ return iter->second;
+ }
+
+ // We did not find the file in the cache; let's read it.
+ {
+ std::ostringstream os;
+ os << "Opening " << filepath;
+ LogDebug(os.str());
+ }
+
+ // Open the filePath
+ std::ifstream filestream;
+ filestream.open(filepath.c_str(), std::ios_base::in);
+ if (!filestream.good())
+ {
+ std::ostringstream os;
+ os << "The specified FileTransform srcfile, '";
+ os << filepath <<"', could not be opened. ";
+ os << "Please confirm the file exists with appropriate read";
+ os << " permissions.";
+ throw Exception(os.str().c_str());
+ }
+
+
+ // Try the initial format.
+ std::string primaryErrorText;
+ std::string root, extension;
+ pystring::os::path::splitext(root, extension, filepath);
+ extension = pystring::replace(extension,".","",1); // remove the leading '.'
+
+ FileFormat * primaryFormat = FormatRegistry::GetInstance().getFileFormatForExtension(extension);
+
+ if(primaryFormat)
+ {
+ try
+ {
+ CachedFileRcPtr cachedFile = primaryFormat->Read(filestream);
+
+ // Add the result to our cache, return it.
+ FileCachePair pair = std::make_pair(primaryFormat, cachedFile);
+ g_fileCache[filepath] = pair;
+
+ if(IsDebugLoggingEnabled())
+ {
+ std::ostringstream os;
+ os << " Loaded primary format ";
+ os << primaryFormat->getName();
+ LogDebug(os.str());
+ }
+
+ return pair;
+ }
+ catch(std::exception & e)
+ {
+ primaryErrorText = e.what();
+ filestream.clear();
+ filestream.seekg( std::ifstream::beg );
+
+ if(IsDebugLoggingEnabled())
+ {
+ std::ostringstream os;
+ os << " Failed primary format ";
+ os << primaryFormat->getName();
+ os << ": " << e.what();
+ LogDebug(os.str());
+ }
+ }
+ }
+
+ // If this fails, try all other formats
+ FormatRegistry & formats = FormatRegistry::GetInstance();
+ for(int findex = 0; findex<formats.getNumRawFormats(); ++findex)
+ {
+ FileFormat * altFormat = formats.getRawFormatByIndex(findex);
+
+ // Dont bother trying the primaryFormat twice.
+ if(altFormat == primaryFormat) continue;
+
+ try
+ {
+ CachedFileRcPtr cachedFile = altFormat->Read(filestream);
+
+ // Add the result to our cache, return it.
+ FileCachePair pair = std::make_pair(altFormat, cachedFile);
+ g_fileCache[filepath] = pair;
+
+ if(IsDebugLoggingEnabled())
+ {
+ std::ostringstream os;
+ os << " Loaded alt format ";
+ os << altFormat->getName();
+ LogDebug(os.str());
+ }
+
+ return pair;
+ }
+ catch(std::exception & e)
+ {
+ filestream.clear();
+ filestream.seekg( std::ifstream::beg );
+
+ if(IsDebugLoggingEnabled())
+ {
+ std::ostringstream os;
+ os << " Failed alt format ";
+ os << altFormat->getName();
+ os << ": " << e.what();
+ LogDebug(os.str());
+ }
+ }
+ }
+
+ // No formats succeeded. Error out with a sensible message.
+ if(primaryFormat)
+ {
+ std::ostringstream os;
+ os << "The specified transform file '";
+ os << filepath <<"' could not be loaded. ";
+ os << primaryErrorText;
+
+ throw Exception(os.str().c_str());
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "The specified transform file '";
+ os << filepath <<"' does not appear to be a valid, known LUT file format.";
+ throw Exception(os.str().c_str());
+ }
+ }
+ }
+
+ void ClearFileTransformCaches()
+ {
+ AutoMutex lock(g_fileCacheLock);
+ g_fileCache.clear();
+ }
+
+ void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const FileTransform& fileTransform,
+ TransformDirection dir)
+ {
+ std::string src = fileTransform.getSrc();
+ if(src.empty())
+ {
+ std::ostringstream os;
+ os << "The transform file has not been specified.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string filepath = context->resolveFileLocation(src.c_str());
+ CreateFileNoOp(ops, filepath);
+
+ FileCachePair cachePair = GetFile(filepath);
+ FileFormat* format = cachePair.first;
+ CachedFileRcPtr cachedFile = cachePair.second;
+
+ format->BuildFileOps(ops,
+ config, context,
+ cachedFile, fileTransform,
+ dir);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/FileTransform.h b/src/core/FileTransform.h
new file mode 100644
index 0000000..3c8f070
--- /dev/null
+++ b/src/core/FileTransform.h
@@ -0,0 +1,156 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_FILETRANSFORM_H
+#define INCLUDED_OCIO_FILETRANSFORM_H
+
+#include <map>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+#include "Processor.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ void ClearFileTransformCaches();
+
+ class CachedFile
+ {
+ public:
+ CachedFile() {};
+ virtual ~CachedFile() {};
+ };
+
+ typedef OCIO_SHARED_PTR<CachedFile> CachedFileRcPtr;
+
+ const int FORMAT_CAPABILITY_NONE = 0;
+ const int FORMAT_CAPABILITY_READ = 1;
+ const int FORMAT_CAPABILITY_WRITE = 2;
+ const int FORMAT_CAPABILITY_ALL = (FORMAT_CAPABILITY_READ | FORMAT_CAPABILITY_WRITE);
+
+ struct FormatInfo
+ {
+ std::string name; // name must be globally unique
+ std::string extension; // extension does not need to be unique
+ int capabilities;
+
+ FormatInfo():
+ capabilities(FORMAT_CAPABILITY_NONE)
+ { }
+ };
+
+ typedef std::vector<FormatInfo> FormatInfoVec;
+
+ class FileFormat
+ {
+ public:
+ virtual ~FileFormat();
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const = 0;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const = 0;
+
+ virtual void Write(const Baker & baker,
+ const std::string & formatName,
+ std::ostream & ostream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr cachedFile,
+ const FileTransform & fileTransform,
+ TransformDirection dir) const = 0;
+
+ // For logging purposes
+ std::string getName() const;
+ private:
+ FileFormat& operator= (const FileFormat &);
+ };
+
+ typedef std::map<std::string, FileFormat*> FileFormatMap;
+ typedef std::vector<FileFormat*> FileFormatVector;
+
+ // TODO: This interface is ugly. What private API is actually appropriate?
+ // Maybe, instead of exposing the raw formats, we wrap it?
+ // FileCachePair GetFile(const std::string & filepath) and all
+ // lookups will move internal
+
+ class FormatRegistry
+ {
+ public:
+ static FormatRegistry & GetInstance();
+
+ // TODO: Make these return a vector of possible formats
+ FileFormat* getFileFormatByName(const std::string & name) const;
+ FileFormat* getFileFormatForExtension(const std::string & extension) const;
+
+ int getNumRawFormats() const;
+ FileFormat* getRawFormatByIndex(int index) const;
+
+ int getNumFormats(int capability) const;
+ const char * getFormatNameByIndex(int capability, int index) const;
+ const char * getFormatExtensionByIndex(int capability, int index) const;
+ private:
+ FormatRegistry();
+ ~FormatRegistry();
+
+ void registerFileFormat(FileFormat* format);
+
+ FileFormatMap m_formatsByName;
+ FileFormatMap m_formatsByExtension;
+ FileFormatVector m_rawFormats;
+
+ typedef std::vector<std::string> StringVec;
+ StringVec m_readFormatNames;
+ StringVec m_readFormatExtensions;
+ StringVec m_writeFormatNames;
+ StringVec m_writeFormatExtensions;
+ };
+
+ // Registry Builders
+ FileFormat * CreateFileFormat3DL();
+ FileFormat * CreateFileFormatCCC();
+ FileFormat * CreateFileFormatCC();
+ FileFormat * CreateFileFormatCSP();
+ FileFormat * CreateFileFormatHDL();
+ FileFormat * CreateFileFormatIridasItx();
+ FileFormat * CreateFileFormatIridasCube();
+ FileFormat * CreateFileFormatIridasLook();
+ FileFormat * CreateFileFormatPandora();
+ FileFormat * CreateFileFormatSpi1D();
+ FileFormat * CreateFileFormatSpi3D();
+ FileFormat * CreateFileFormatSpiMtx();
+ FileFormat * CreateFileFormatTruelight();
+ FileFormat * CreateFileFormatVF();
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/GpuShaderDesc.cpp b/src/core/GpuShaderDesc.cpp
new file mode 100644
index 0000000..3b20845
--- /dev/null
+++ b/src/core/GpuShaderDesc.cpp
@@ -0,0 +1,131 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Mutex.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ class GpuShaderDesc::Impl
+ {
+ public:
+ GpuLanguage language_;
+ std::string functionName_;
+ int lut3DEdgeLen_;
+
+ mutable std::string cacheID_;
+ mutable Mutex cacheIDMutex_;
+
+ Impl() :
+ language_(GPU_LANGUAGE_UNKNOWN),
+ lut3DEdgeLen_(0)
+ {
+ }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ language_ = rhs.language_;
+ functionName_ = rhs.functionName_;
+ lut3DEdgeLen_ = rhs.lut3DEdgeLen_;
+ cacheID_ = rhs.cacheID_;
+ return *this;
+ }
+ };
+
+
+ GpuShaderDesc::GpuShaderDesc()
+ : m_impl(new GpuShaderDesc::Impl)
+ {
+ }
+
+ GpuShaderDesc::~GpuShaderDesc()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+
+ void GpuShaderDesc::setLanguage(GpuLanguage lang)
+ {
+ AutoMutex lock(getImpl()->cacheIDMutex_);
+ getImpl()->language_ = lang;
+ getImpl()->cacheID_ = "";
+ }
+
+ GpuLanguage GpuShaderDesc::getLanguage() const
+ {
+ return getImpl()->language_;
+ }
+
+ void GpuShaderDesc::setFunctionName(const char * name)
+ {
+ AutoMutex lock(getImpl()->cacheIDMutex_);
+ getImpl()->functionName_ = name;
+ getImpl()->cacheID_ = "";
+ }
+
+ const char * GpuShaderDesc::getFunctionName() const
+ {
+ return getImpl()->functionName_.c_str();
+ }
+
+ void GpuShaderDesc::setLut3DEdgeLen(int len)
+ {
+ AutoMutex lock(getImpl()->cacheIDMutex_);
+ getImpl()->lut3DEdgeLen_ = len;
+ getImpl()->cacheID_ = "";
+ }
+
+ int GpuShaderDesc::getLut3DEdgeLen() const
+ {
+ return getImpl()->lut3DEdgeLen_;
+ }
+
+ const char * GpuShaderDesc::getCacheID() const
+ {
+ AutoMutex lock(getImpl()->cacheIDMutex_);
+
+ if(getImpl()->cacheID_.empty())
+ {
+ std::ostringstream os;
+ os << GpuLanguageToString(getImpl()->language_) << " ";
+ os << getImpl()->functionName_ << " ";
+ os << getImpl()->lut3DEdgeLen_;
+ getImpl()->cacheID_ = os.str();
+ }
+
+ return getImpl()->cacheID_.c_str();
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/GpuShaderUtils.cpp b/src/core/GpuShaderUtils.cpp
new file mode 100644
index 0000000..cb8d67b
--- /dev/null
+++ b/src/core/GpuShaderUtils.cpp
@@ -0,0 +1,193 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "GpuShaderUtils.h"
+#include "MathUtils.h"
+
+#include <cmath>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ void Write_half4x4(std::ostream & os, const float * m44, GpuLanguage lang)
+ {
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ os << "half4x4(";
+ for(int i=0; i<16; i++)
+ {
+ if(i!=0) os << ", ";
+ os << ClampToNormHalf(m44[i]);
+ }
+ os << ")";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0 || lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ os << "mat4(";
+ for(int i=0; i<16; i++)
+ {
+ if(i!=0) os << ", ";
+ os << m44[i]; // Clamping to half is not necessary
+ }
+ os << ")";
+ }
+ else
+ {
+ throw Exception("Unsupported shader language.");
+ }
+ }
+
+ void Write_half4(std::ostream & os, const float * v4, GpuLanguage lang)
+ {
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ os << "half4(";
+ for(int i=0; i<4; i++)
+ {
+ if(i!=0) os << ", ";
+ os << ClampToNormHalf(v4[i]);
+ }
+ os << ")";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0 || lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ os << "vec4(";
+ for(int i=0; i<4; i++)
+ {
+ if(i!=0) os << ", ";
+ os << v4[i]; // Clamping to half is not necessary
+ }
+ os << ")";
+ }
+ else
+ {
+ throw Exception("Unsupported shader language.");
+ }
+ }
+
+ void Write_half3(std::ostream & os, const float * v3, GpuLanguage lang)
+ {
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ os << "half3(";
+ for(int i=0; i<3; i++)
+ {
+ if(i!=0) os << ", ";
+ os << ClampToNormHalf(v3[i]);
+ }
+ os << ")";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0 || lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ os << "vec3(";
+ for(int i=0; i<3; i++)
+ {
+ if(i!=0) os << ", ";
+ os << v3[i]; // Clamping to half is not necessary
+ }
+ os << ")";
+ }
+ else
+ {
+ throw Exception("Unsupported shader language.");
+ }
+ }
+
+
+
+
+ std::string GpuTextHalf4x4(const float * m44, GpuLanguage lang)
+ {
+ std::ostringstream os;
+ Write_half4x4(os, m44, lang);
+ return os.str();
+ }
+
+ std::string GpuTextHalf4(const float * v4, GpuLanguage lang)
+ {
+ std::ostringstream os;
+ Write_half4(os, v4, lang);
+ return os.str();
+ }
+
+ std::string GpuTextHalf3(const float * v3, GpuLanguage lang)
+ {
+ std::ostringstream os;
+ Write_half3(os, v3, lang);
+ return os.str();
+ }
+
+ // Note that Cg and GLSL have opposite ordering for vec/mtx multiplication
+ void Write_mtx_x_vec(std::ostream & os,
+ const std::string & mtx, const std::string & vec,
+ GpuLanguage lang)
+ {
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ os << "mul( " << mtx << ", " << vec << ")";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0 || lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ os << vec << " * " << mtx;
+ }
+ else
+ {
+ throw Exception("Unsupported shader language.");
+ }
+ }
+
+
+ void Write_sampleLut3D_rgb(std::ostream & os, const std::string& variableName,
+ const std::string& lutName, int lut3DEdgeLen,
+ GpuLanguage lang)
+ {
+ float m = ((float) lut3DEdgeLen-1.0f) / (float) lut3DEdgeLen;
+ float b = 1.0f / (2.0f * (float) lut3DEdgeLen);
+
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ os << "tex3D(";
+ os << lutName << ", ";
+ os << m << " * " << variableName << ".rgb + " << b << ").rgb;" << std::endl;
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0 || lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ os << "texture3D(";
+ os << lutName << ", ";
+ os << m << " * " << variableName << ".rgb + " << b << ").rgb;" << std::endl;
+ }
+ else
+ {
+ throw Exception("Unsupported shader language.");
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/GpuShaderUtils.h b/src/core/GpuShaderUtils.h
new file mode 100644
index 0000000..43d16a4
--- /dev/null
+++ b/src/core/GpuShaderUtils.h
@@ -0,0 +1,58 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_GPUSHADERUTILS_H
+#define INCLUDED_OCIO_GPUSHADERUTILS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ std::string GpuTextHalf4x4(const float * m44, GpuLanguage lang);
+ std::string GpuTextHalf4(const float * v4, GpuLanguage lang);
+ std::string GpuTextHalf3(const float * v3, GpuLanguage lang);
+
+ void Write_mtx_x_vec(std::ostream & os,
+ const std::string & mtx, const std::string & vec,
+ GpuLanguage lang);
+
+ void Write_half4x4(std::ostream & os, const float * m44, GpuLanguage lang);
+ void Write_half4(std::ostream & os, const float * v4, GpuLanguage lang);
+ void Write_half3(std::ostream & os, const float * v3, GpuLanguage lang);
+
+ // returns vec3
+ void Write_sampleLut3D_rgb(std::ostream & os, const std::string & variableName,
+ const std::string & lutName, int lut3DEdgeLen,
+ GpuLanguage lang);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/GroupTransform.cpp b/src/core/GroupTransform.cpp
new file mode 100644
index 0000000..344714a
--- /dev/null
+++ b/src/core/GroupTransform.cpp
@@ -0,0 +1,196 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+#include "OpBuilders.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ GroupTransformRcPtr GroupTransform::Create()
+ {
+ return GroupTransformRcPtr(new GroupTransform(), &deleter);
+ }
+
+ void GroupTransform::deleter(GroupTransform* t)
+ {
+ delete t;
+ }
+
+ namespace
+ {
+ typedef std::vector<TransformRcPtr> TransformRcPtrVec;
+ }
+
+ class GroupTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ TransformRcPtrVec vec_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD)
+ { }
+
+ ~Impl()
+ {
+ vec_.clear();
+ }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+
+ vec_.clear();
+
+ for(unsigned int i=0; i<rhs.vec_.size(); ++i)
+ {
+ vec_.push_back(rhs.vec_[i]->createEditableCopy());
+ }
+
+ return *this;
+ }
+ };
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ GroupTransform::GroupTransform()
+ : m_impl(new GroupTransform::Impl)
+ {
+ }
+
+ TransformRcPtr GroupTransform::createEditableCopy() const
+ {
+ GroupTransformRcPtr transform = GroupTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ GroupTransform::~GroupTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ GroupTransform& GroupTransform::operator= (const GroupTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection GroupTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void GroupTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ int GroupTransform::size() const
+ {
+ return static_cast<int>(getImpl()->vec_.size());
+ }
+
+ ConstTransformRcPtr GroupTransform::getTransform(int index) const
+ {
+ if(index < 0 || index >= (int)getImpl()->vec_.size())
+ {
+ std::ostringstream os;
+ os << "Invalid transform index " << index << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ return getImpl()->vec_[index];
+ }
+
+ void GroupTransform::push_back(const ConstTransformRcPtr& transform)
+ {
+ getImpl()->vec_.push_back(transform->createEditableCopy());
+ }
+
+ void GroupTransform::clear()
+ {
+ getImpl()->vec_.clear();
+ }
+
+ bool GroupTransform::empty() const
+ {
+ return getImpl()->vec_.empty();
+ }
+
+ std::ostream& operator<< (std::ostream& os, const GroupTransform& groupTransform)
+ {
+ for(int i=0; i<groupTransform.size(); ++i)
+ {
+ if(i!=groupTransform.size()-1) os << "\n";
+ ConstTransformRcPtr transform = groupTransform.getTransform(i);
+ os << "\t" << *transform;
+ }
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ void BuildGroupOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const GroupTransform& groupTransform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ groupTransform.getDirection());
+
+ if(combinedDir == TRANSFORM_DIR_FORWARD)
+ {
+ for(int i=0; i<groupTransform.size(); ++i)
+ {
+ ConstTransformRcPtr childTransform = groupTransform.getTransform(i);
+ BuildOps(ops, config, context, childTransform, TRANSFORM_DIR_FORWARD);
+ }
+ }
+ else if(combinedDir == TRANSFORM_DIR_INVERSE)
+ {
+ for(int i=groupTransform.size()-1; i>=0; --i)
+ {
+ ConstTransformRcPtr childTransform = groupTransform.getTransform(i);
+ BuildOps(ops, config, context, childTransform, TRANSFORM_DIR_INVERSE);
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/HashUtils.cpp b/src/core/HashUtils.cpp
new file mode 100644
index 0000000..5b9acd1
--- /dev/null
+++ b/src/core/HashUtils.cpp
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "HashUtils.h"
+#include "md5/md5.h"
+
+#include <sstream>
+#include <iostream>
+
+OCIO_NAMESPACE_ENTER
+{
+ std::string CacheIDHash(const char * array, int size)
+ {
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)array, size);
+ md5_finish(&state, digest);
+
+ return GetPrintableHash(digest);
+ }
+
+ std::string GetPrintableHash(const md5_byte_t * digest)
+ {
+ static char charmap[] = "0123456789abcdef";
+
+ char printableResult[34];
+ char *ptr = printableResult;
+
+ // build a printable string from unprintable chars. first character
+ // of hashed cache IDs is '$', to later check if it's already been hashed
+ *ptr++ = '$';
+ for (int i=0;i<16;++i)
+ {
+ *ptr++ = charmap[(digest[i] & 0x0F)];
+ *ptr++ = charmap[(digest[i] >> 4)];
+ }
+ *ptr++ = 0;
+
+ return std::string(printableResult);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/HashUtils.h b/src/core/HashUtils.h
new file mode 100644
index 0000000..58481db
--- /dev/null
+++ b/src/core/HashUtils.h
@@ -0,0 +1,48 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_HASHUTILS_H
+#define INCLUDED_OCIO_HASHUTILS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "md5/md5.h"
+#include <string>
+
+OCIO_NAMESPACE_ENTER
+{
+ std::string CacheIDHash(const char * array, int size);
+
+ // TODO: get rid of md5.h include, make this a generic byte array
+ std::string GetPrintableHash(const md5_byte_t * digest);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
+
diff --git a/src/core/ImageDesc.cpp b/src/core/ImageDesc.cpp
new file mode 100644
index 0000000..63156c8
--- /dev/null
+++ b/src/core/ImageDesc.cpp
@@ -0,0 +1,392 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <cstdlib>
+#include <sstream>
+
+#include "ImagePacking.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+ std::ostream& operator<< (std::ostream& os, const ImageDesc& img)
+ {
+ if(const PackedImageDesc * packedImg = dynamic_cast<const PackedImageDesc*>(&img))
+ {
+ os << "<PackedImageDesc ";
+ os << "data=" << packedImg->getData() << ", ";
+ os << "width=" << packedImg->getWidth() << ", ";
+ os << "height=" << packedImg->getHeight() << ", ";
+ os << "numChannels=" << packedImg->getNumChannels() << ", ";
+ os << "chanStrideBytes=" << packedImg->getChanStrideBytes() << ", ";
+ os << "xStrideBytes=" << packedImg->getXStrideBytes() << ", ";
+ os << "yStrideBytes=" << packedImg->getYStrideBytes() << "";
+ os << ">";
+ }
+ else if(const PlanarImageDesc * planarImg = dynamic_cast<const PlanarImageDesc*>(&img))
+ {
+ os << "<PlanarImageDesc ";
+ os << "rData=" << planarImg->getRData() << ", ";
+ os << "gData=" << planarImg->getGData() << ", ";
+ os << "bData=" << planarImg->getBData() << ", ";
+ os << "aData=" << planarImg->getAData() << ", ";
+ os << "width=" << packedImg->getWidth() << ", ";
+ os << "height=" << packedImg->getHeight() << ", ";
+ os << "yStrideBytes=" << planarImg->getYStrideBytes() << "";
+ os << ">";
+ }
+ else
+ {
+ os << "<UnknownImageDesc>";
+ }
+
+ return os;
+ }
+
+ ImageDesc::~ImageDesc()
+ {
+
+ }
+
+
+
+ GenericImageDesc::GenericImageDesc():
+ width(0),
+ height(0),
+ xStrideBytes(0),
+ yStrideBytes(0),
+ rData(NULL),
+ gData(NULL),
+ bData(NULL),
+ aData(NULL)
+ { };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ GenericImageDesc::~GenericImageDesc()
+ { };
+
+ void GenericImageDesc::init(const ImageDesc& img)
+ {
+ if(const PackedImageDesc * packedImg = dynamic_cast<const PackedImageDesc*>(&img))
+ {
+ width = packedImg->getWidth();
+ height = packedImg->getHeight();
+ long numChannels = packedImg->getNumChannels();
+
+ ptrdiff_t chanStrideBytes = packedImg->getChanStrideBytes();
+ xStrideBytes = packedImg->getXStrideBytes();
+ yStrideBytes = packedImg->getYStrideBytes();
+
+ // AutoStrides will already be resolved by here, in the constructor of the ImageDesc
+ if(chanStrideBytes == AutoStride ||
+ xStrideBytes == AutoStride ||
+ yStrideBytes == AutoStride)
+ {
+ throw Exception("Malformed PackedImageDesc: Unresolved AutoStride.");
+ }
+
+ rData = packedImg->getData();
+ gData = reinterpret_cast<float*>( reinterpret_cast<char*>(rData)
+ + chanStrideBytes );
+ bData = reinterpret_cast<float*>( reinterpret_cast<char*>(rData)
+ + 2*chanStrideBytes );
+ if(numChannels >= 4)
+ {
+ aData = reinterpret_cast<float*>( reinterpret_cast<char*>(rData)
+ + 3*chanStrideBytes );
+ }
+
+ if(rData == NULL)
+ {
+ std::ostringstream os;
+ os << "PackedImageDesc Error: A null image ptr was specified.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(width <= 0 || height <= 0)
+ {
+ std::ostringstream os;
+ os << "PackedImageDesc Error: Image dimensions must be positive for both x,y. '";
+ os << width << "x" << height << "' is not allowed.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(numChannels < 3)
+ {
+ std::ostringstream os;
+ os << "PackedImageDesc Error: Image numChannels must be three (or more) (rgb+). '";
+ os << numChannels << "' is not allowed.";
+ throw Exception(os.str().c_str());
+ }
+ }
+ else if(const PlanarImageDesc * planarImg = dynamic_cast<const PlanarImageDesc*>(&img))
+ {
+ width = planarImg->getWidth();
+ height = planarImg->getHeight();
+ xStrideBytes = sizeof(float);
+ yStrideBytes = planarImg->getYStrideBytes();
+
+ // AutoStrides will already be resolved by here, in the constructor of the ImageDesc
+ if(yStrideBytes == AutoStride)
+ {
+ throw Exception("Malformed PlanarImageDesc: Unresolved AutoStride.");
+ }
+
+ rData = planarImg->getRData();
+ gData = planarImg->getGData();
+ bData = planarImg->getBData();
+ aData = planarImg->getAData();
+
+ if(width <= 0 || height <= 0)
+ {
+ std::ostringstream os;
+ os << "PlanarImageDesc Error: Image dimensions must be positive for both x,y. '";
+ os << width << "x" << height << "' is not allowed.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(rData == NULL || gData == NULL || bData == NULL)
+ {
+ std::ostringstream os;
+ os << "PlanarImageDesc Error: Valid ptrs must be passed for all 3 image rgb color channels.";
+ throw Exception(os.str().c_str());
+ }
+ }
+ else
+ {
+ throw Exception("Unknown ImageDesc type.");
+ }
+ }
+
+ bool GenericImageDesc::isPackedRGBA() const
+ {
+ char* rPtr = reinterpret_cast<char*>(rData);
+ char* gPtr = reinterpret_cast<char*>(gData);
+ char* bPtr = reinterpret_cast<char*>(bData);
+ char* aPtr = reinterpret_cast<char*>(aData);
+
+ if(gPtr-rPtr != sizeof(float)) return false;
+ if(bPtr-gPtr != sizeof(float)) return false;
+ if(aPtr && (aPtr-bPtr != sizeof(float))) return false;
+
+ // Confirm xStrideBytes is a pure float-sized packing
+ // (I.e., it will divide evenly)
+ if(xStrideBytes <= 0) return false;
+ div_t result = div((int) xStrideBytes, (int)sizeof(float));
+ if(result.rem != 0) return false;
+
+ int implicitChannels = result.quot;
+ if(implicitChannels != 4) return false;
+
+ return true;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ class PackedImageDesc::Impl
+ {
+ public:
+ float * data_;
+ long width_;
+ long height_;
+ long numChannels_;
+ ptrdiff_t chanStrideBytes_;
+ ptrdiff_t xStrideBytes_;
+ ptrdiff_t yStrideBytes_;
+
+ Impl() :
+ data_(NULL),
+ width_(0),
+ height_(0),
+ numChannels_(0),
+ chanStrideBytes_(0),
+ xStrideBytes_(0),
+ yStrideBytes_(0)
+ {
+ }
+
+ ~Impl()
+ { }
+ };
+
+ PackedImageDesc::PackedImageDesc(float * data,
+ long width, long height,
+ long numChannels,
+ ptrdiff_t chanStrideBytes,
+ ptrdiff_t xStrideBytes,
+ ptrdiff_t yStrideBytes)
+ : m_impl(new PackedImageDesc::Impl)
+ {
+ getImpl()->data_ = data;
+ getImpl()->width_ = width;
+ getImpl()->height_ = height;
+ getImpl()->numChannels_ = numChannels;
+ getImpl()->chanStrideBytes_ = (chanStrideBytes == AutoStride)
+ ? sizeof(float) : chanStrideBytes;
+ getImpl()->xStrideBytes_ = (xStrideBytes == AutoStride)
+ ? sizeof(float)*numChannels : xStrideBytes;
+ getImpl()->yStrideBytes_ = (yStrideBytes == AutoStride)
+ ? sizeof(float)*width*numChannels : yStrideBytes;
+ }
+
+ PackedImageDesc::~PackedImageDesc()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ float * PackedImageDesc::getData() const
+ {
+ return getImpl()->data_;
+ }
+
+ long PackedImageDesc::getWidth() const
+ {
+ return getImpl()->width_;
+ }
+
+ long PackedImageDesc::getHeight() const
+ {
+ return getImpl()->height_;
+ }
+
+ long PackedImageDesc::getNumChannels() const
+ {
+ return getImpl()->numChannels_;
+ }
+
+ ptrdiff_t PackedImageDesc::getChanStrideBytes() const
+ {
+ return getImpl()->chanStrideBytes_;
+ }
+
+ ptrdiff_t PackedImageDesc::getXStrideBytes() const
+ {
+ return getImpl()->xStrideBytes_;
+ }
+
+ ptrdiff_t PackedImageDesc::getYStrideBytes() const
+ {
+ return getImpl()->yStrideBytes_;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ class PlanarImageDesc::Impl
+ {
+ public:
+ float * rData_;
+ float * gData_;
+ float * bData_;
+ float * aData_;
+ long width_;
+ long height_;
+ ptrdiff_t yStrideBytes_;
+
+ Impl() :
+ rData_(NULL),
+ gData_(NULL),
+ bData_(NULL),
+ aData_(NULL),
+ width_(0),
+ height_(0),
+ yStrideBytes_(0)
+ { }
+
+ ~Impl()
+ { }
+ };
+
+
+ PlanarImageDesc::PlanarImageDesc(float * rData, float * gData, float * bData, float * aData,
+ long width, long height,
+ ptrdiff_t yStrideBytes)
+ : m_impl(new PlanarImageDesc::Impl())
+ {
+ getImpl()->rData_ = rData;
+ getImpl()->gData_ = gData;
+ getImpl()->bData_ = bData;
+ getImpl()->aData_ = aData;
+ getImpl()->width_ = width;
+ getImpl()->height_ = height;
+ getImpl()->yStrideBytes_ = (yStrideBytes == AutoStride)
+ ? sizeof(float)*width : yStrideBytes;
+ }
+
+ PlanarImageDesc::~PlanarImageDesc()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ float* PlanarImageDesc::getRData() const
+ {
+ return getImpl()->rData_;
+ }
+
+ float* PlanarImageDesc::getGData() const
+ {
+ return getImpl()->gData_;
+ }
+
+ float* PlanarImageDesc::getBData() const
+ {
+ return getImpl()->bData_;
+ }
+
+ float* PlanarImageDesc::getAData() const
+ {
+ return getImpl()->aData_;
+ }
+
+ long PlanarImageDesc::getWidth() const
+ {
+ return getImpl()->width_;
+ }
+
+ long PlanarImageDesc::getHeight() const
+ {
+ return getImpl()->height_;
+ }
+
+ ptrdiff_t PlanarImageDesc::getYStrideBytes() const
+ {
+ return getImpl()->yStrideBytes_;
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ImagePacking.cpp b/src/core/ImagePacking.cpp
new file mode 100644
index 0000000..256d25c
--- /dev/null
+++ b/src/core/ImagePacking.cpp
@@ -0,0 +1,407 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <sstream>
+#include <iostream>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+
+#include "ImagePacking.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+ namespace
+ {
+ // GENERIC CASE, SLOW BUT ALWAYS WORKS
+
+ void PackRGBAFromImageDesc_Generic(const GenericImageDesc& srcImg,
+ float* outputBuffer,
+ int* numPixelsCopied,
+ int outputBufferSize,
+ long imagePixelStartIndex)
+ {
+ assert(outputBuffer);
+ assert(numPixelsCopied);
+
+ long imgWidth = srcImg.width;
+ long imgHeight = srcImg.height;
+ long imgPixels = imgWidth * imgHeight;
+
+ if(imagePixelStartIndex<0 || imagePixelStartIndex>=imgPixels)
+ {
+ *numPixelsCopied = 0;
+ return;
+ }
+
+ ptrdiff_t xStrideBytes = srcImg.xStrideBytes;
+ ptrdiff_t yStrideBytes = srcImg.yStrideBytes;
+ long yIndex = imagePixelStartIndex / imgWidth;
+ long xIndex = imagePixelStartIndex % imgWidth;
+
+ // Figure out our initial ptr positions
+ char* rRow = reinterpret_cast<char*>(srcImg.rData) +
+ yStrideBytes * yIndex;
+ char* gRow = reinterpret_cast<char*>(srcImg.gData) +
+ yStrideBytes * yIndex;
+ char* bRow = reinterpret_cast<char*>(srcImg.bData) +
+ yStrideBytes * yIndex;
+ char* aRow = NULL;
+
+ float* rPtr = reinterpret_cast<float*>(rRow + xStrideBytes*xIndex);
+ float* gPtr = reinterpret_cast<float*>(gRow + xStrideBytes*xIndex);
+ float* bPtr = reinterpret_cast<float*>(bRow + xStrideBytes*xIndex);
+ float* aPtr = NULL;
+
+ if(srcImg.aData)
+ {
+ aRow = reinterpret_cast<char*>(srcImg.aData) + yStrideBytes * yIndex;
+ aPtr = reinterpret_cast<float*>(aRow + xStrideBytes*xIndex);
+ }
+
+ if(aPtr)
+ {
+ int pixelsCopied = 0;
+ while(pixelsCopied < outputBufferSize)
+ {
+ outputBuffer[4*pixelsCopied] = *rPtr;
+ outputBuffer[4*pixelsCopied+1] = *gPtr;
+ outputBuffer[4*pixelsCopied+2] = *bPtr;
+ outputBuffer[4*pixelsCopied+3] = *aPtr;
+ pixelsCopied++;
+ xIndex++;
+
+ // Jump to the next scanline
+ if(xIndex == imgWidth)
+ {
+ yIndex += 1;
+ if(yIndex == imgHeight)
+ {
+ *numPixelsCopied = pixelsCopied;
+ return;
+ }
+
+ xIndex = 0;
+ rRow += yStrideBytes;
+ gRow += yStrideBytes;
+ bRow += yStrideBytes;
+ aRow += yStrideBytes;
+
+ rPtr = reinterpret_cast<float*>(rRow);
+ gPtr = reinterpret_cast<float*>(gRow);
+ bPtr = reinterpret_cast<float*>(bRow);
+ aPtr = reinterpret_cast<float*>(aRow);
+ }
+ // Jump to the next pixel
+ else
+ {
+ rPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(rPtr) + xStrideBytes);
+ gPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(gPtr) + xStrideBytes);
+ bPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(bPtr) + xStrideBytes);
+ aPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(aPtr) + xStrideBytes);
+ }
+ }
+
+ *numPixelsCopied = pixelsCopied;
+ }
+ else
+ {
+ int pixelsCopied = 0;
+ while(pixelsCopied < outputBufferSize)
+ {
+ outputBuffer[4*pixelsCopied] = *rPtr;
+ outputBuffer[4*pixelsCopied+1] = *gPtr;
+ outputBuffer[4*pixelsCopied+2] = *bPtr;
+ outputBuffer[4*pixelsCopied+3] = 0.0;
+ pixelsCopied++;
+ xIndex++;
+
+ // Jump to the next scanline
+ if(xIndex == imgWidth)
+ {
+ yIndex += 1;
+ if(yIndex == imgHeight)
+ {
+ *numPixelsCopied = pixelsCopied;
+ return;
+ }
+
+ xIndex = 0;
+ rRow += yStrideBytes;
+ gRow += yStrideBytes;
+ bRow += yStrideBytes;
+
+ rPtr = reinterpret_cast<float*>(rRow);
+ gPtr = reinterpret_cast<float*>(gRow);
+ bPtr = reinterpret_cast<float*>(bRow);
+ }
+ // Jump to the next pixel
+ else
+ {
+ rPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(rPtr) + xStrideBytes);
+ gPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(gPtr) + xStrideBytes);
+ bPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(bPtr) + xStrideBytes);
+ }
+ }
+
+ *numPixelsCopied = pixelsCopied;
+ }
+ }
+
+ void UnpackRGBAToImageDesc_Generic(GenericImageDesc& dstImg,
+ float* inputBuffer,
+ int numPixelsToUnpack,
+ long imagePixelStartIndex)
+ {
+ assert(inputBuffer);
+
+ long imgWidth = dstImg.width;
+ long imgHeight = dstImg.height;
+ long imgPixels = imgWidth * imgHeight;
+
+ if(imagePixelStartIndex<0 || imagePixelStartIndex>=imgPixels)
+ {
+ return;
+ }
+
+ ptrdiff_t xStrideBytes = dstImg.xStrideBytes;
+ ptrdiff_t yStrideBytes = dstImg.yStrideBytes;
+ long yIndex = imagePixelStartIndex / imgWidth;
+ long xIndex = imagePixelStartIndex % imgWidth;
+
+ // Figure out our initial ptr positions
+ char* rRow = reinterpret_cast<char*>(dstImg.rData) +
+ yStrideBytes * yIndex;
+ char* gRow = reinterpret_cast<char*>(dstImg.gData) +
+ yStrideBytes * yIndex;
+ char* bRow = reinterpret_cast<char*>(dstImg.bData) +
+ yStrideBytes * yIndex;
+ char* aRow = NULL;
+
+ float* rPtr = reinterpret_cast<float*>(rRow + xStrideBytes*xIndex);
+ float* gPtr = reinterpret_cast<float*>(gRow + xStrideBytes*xIndex);
+ float* bPtr = reinterpret_cast<float*>(bRow + xStrideBytes*xIndex);
+ float* aPtr = NULL;
+
+ if(dstImg.aData)
+ {
+ aRow = reinterpret_cast<char*>(dstImg.aData) + yStrideBytes * yIndex;
+ aPtr = reinterpret_cast<float*>(aRow + xStrideBytes*xIndex);
+ }
+
+ if(aPtr)
+ {
+ int pixelsCopied = 0;
+ while(pixelsCopied < numPixelsToUnpack)
+ {
+ *rPtr = inputBuffer[4*pixelsCopied];
+ *gPtr = inputBuffer[4*pixelsCopied+1];
+ *bPtr = inputBuffer[4*pixelsCopied+2];
+ *aPtr = inputBuffer[4*pixelsCopied+3];
+
+ pixelsCopied++;
+ xIndex++;
+
+ // Jump to the next scanline
+ if(xIndex == imgWidth)
+ {
+ yIndex += 1;
+ if(yIndex == imgHeight)
+ {
+ return;
+ }
+
+ xIndex = 0;
+ rRow += yStrideBytes;
+ gRow += yStrideBytes;
+ bRow += yStrideBytes;
+ aRow += yStrideBytes;
+
+ rPtr = reinterpret_cast<float*>(rRow);
+ gPtr = reinterpret_cast<float*>(gRow);
+ bPtr = reinterpret_cast<float*>(bRow);
+ aPtr = reinterpret_cast<float*>(aRow);
+ }
+ // Jump to the next pixel
+ else
+ {
+ rPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(rPtr) + xStrideBytes);
+ gPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(gPtr) + xStrideBytes);
+ bPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(bPtr) + xStrideBytes);
+ aPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(aPtr) + xStrideBytes);
+ }
+ }
+ }
+ else
+ {
+ int pixelsCopied = 0;
+ while(pixelsCopied < numPixelsToUnpack)
+ {
+ *rPtr = inputBuffer[4*pixelsCopied];
+ *gPtr = inputBuffer[4*pixelsCopied+1];
+ *bPtr = inputBuffer[4*pixelsCopied+2];
+
+ pixelsCopied++;
+ xIndex++;
+
+ // Jump to the next scanline
+ if(xIndex == imgWidth)
+ {
+ yIndex += 1;
+ if(yIndex == imgHeight)
+ {
+ return;
+ }
+
+ xIndex = 0;
+ rRow += yStrideBytes;
+ gRow += yStrideBytes;
+ bRow += yStrideBytes;
+
+ rPtr = reinterpret_cast<float*>(rRow);
+ gPtr = reinterpret_cast<float*>(gRow);
+ bPtr = reinterpret_cast<float*>(bRow);
+ }
+ // Jump to the next pixel
+ else
+ {
+ rPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(rPtr) + xStrideBytes);
+ gPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(gPtr) + xStrideBytes);
+ bPtr = reinterpret_cast<float*>(
+ reinterpret_cast<char*>(bPtr) + xStrideBytes);
+ }
+ }
+ }
+ }
+
+ }
+
+
+ /*
+ namespace
+ {
+
+ void PackRGBAFromImageDesc_RGBAMemcpy(const GenericImageDesc& srcImg,
+ float* outputBuffer,
+ int* numPixelsCopied,
+ int outputBufferSize,
+ int imagePixelStartIndex)
+ {
+ assert(outputBuffer);
+ assert(numPixelsCopied);
+
+ long imgWidth = srcImg.getWidth();
+ long imgHeight = srcImg.getHeight();
+ long imgPixels = srcImg.getNumPixels();
+
+ if(imagePixelStartIndex<0 || imagePixelStartIndex>=imgPixels)
+ {
+ *numPixelsCopied = 0;
+ return;
+ }
+
+ ptrdiff_t xStrideBytes = srcImg.getXStrideBytes();
+ ptrdiff_t yStrideBytes = srcImg.getYStrideBytes();
+ int yIndex = imagePixelStartIndex / imgWidth;
+ int xIndex = imagePixelStartIndex % imgWidth;
+
+ // Figure out our initial ptr positions
+ char* imgRow = reinterpret_cast<char*>(srcImg.getRData()) +
+ yStrideBytes * yIndex;
+
+ char* imgPtr = imgRow + xStrideBytes*xIndex;
+
+ int totalPixelsCopied = 0;
+ int pixelsRemainingToCopy = outputBufferSize;
+
+ while(pixelsRemainingToCopy>0 && yIndex < imgHeight)
+ {
+ int imgScanlinePixels = imgWidth - xIndex;
+ int numPixels = std::min(imgScanlinePixels,
+ pixelsRemainingToCopy);
+ memcpy(outputBuffer+totalPixelsCopied,
+ imgPtr, numPixels);
+
+ yIndex += 1;
+ xIndex = 0;
+
+ imgRow += yStrideBytes;
+ imgPtr = imgRow;
+ totalPixelsCopied += numPixels;
+ pixelsRemainingToCopy -= numPixels;
+ }
+
+ if(numPixelsCopied) *numPixelsCopied = totalPixelsCopied;
+ }
+ }
+ */
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // TODO: Add optimized codepaths to image packing / unpacking
+
+ void PackRGBAFromImageDesc(const GenericImageDesc& srcImg,
+ float* outputBuffer,
+ int* numPixelsCopied,
+ int outputBufferSize,
+ long imagePixelStartIndex)
+ {
+ PackRGBAFromImageDesc_Generic(srcImg, outputBuffer,
+ numPixelsCopied,
+ outputBufferSize,
+ imagePixelStartIndex);
+ }
+
+
+ void UnpackRGBAToImageDesc(GenericImageDesc& dstImg,
+ float* inputBuffer,
+ int numPixelsToUnpack,
+ long imagePixelStartIndex)
+ {
+ UnpackRGBAToImageDesc_Generic(dstImg, inputBuffer,
+ numPixelsToUnpack,
+ imagePixelStartIndex);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ImagePacking.h b/src/core/ImagePacking.h
new file mode 100644
index 0000000..a03d1ea
--- /dev/null
+++ b/src/core/ImagePacking.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_IMAGEPACKING_H
+#define INCLUDED_OCIO_IMAGEPACKING_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ struct GenericImageDesc
+ {
+ long width;
+ long height;
+ ptrdiff_t xStrideBytes;
+ ptrdiff_t yStrideBytes;
+
+ float* rData;
+ float* gData;
+ float* bData;
+ float* aData;
+
+ GenericImageDesc();
+ ~GenericImageDesc();
+
+ // Resolves all AutoStride
+ void init(const ImageDesc& img);
+
+ bool isPackedRGBA() const;
+ };
+
+ void PackRGBAFromImageDesc(const GenericImageDesc& srcImg,
+ float* outputBuffer,
+ int* numPixelsCopied,
+ int outputBufferSize,
+ long imagePixelStartIndex);
+
+ void UnpackRGBAToImageDesc(GenericImageDesc& dstImg,
+ float* inputBuffer,
+ int numPixelsToUnpack,
+ long imagePixelStartIndex);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/LogOps.cpp b/src/core/LogOps.cpp
new file mode 100644
index 0000000..bc3174e
--- /dev/null
+++ b/src/core/LogOps.cpp
@@ -0,0 +1,499 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cmath>
+#include <cstring>
+#include <iostream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "GpuShaderUtils.h"
+#include "LogOps.h"
+#include "MathUtils.h"
+
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const float FLTMIN = std::numeric_limits<float>::min();
+
+ const int FLOAT_DECIMALS = 7;
+
+ // k * log(mx+b, base) + kb
+ // the caller is responsible for base != 1.0
+ // TODO: pull the precomputation into the caller?
+
+ void ApplyLinToLog(float* rgbaBuffer, long numPixels,
+ const float * k,
+ const float * m,
+ const float * b,
+ const float * base,
+ const float * kb)
+ {
+ // We account for the change of base by rolling the multiplier
+ // in with 'k'
+
+ float knew[3] = { k[0] / logf(base[0]),
+ k[1] / logf(base[1]),
+ k[2] / logf(base[0]) };
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ rgbaBuffer[0] = knew[0] * logf(std::max(m[0]*rgbaBuffer[0] + b[0], FLTMIN)) + kb[0];
+ rgbaBuffer[1] = knew[1] * logf(std::max(m[1]*rgbaBuffer[1] + b[1], FLTMIN)) + kb[1];
+ rgbaBuffer[2] = knew[2] * logf(std::max(m[2]*rgbaBuffer[2] + b[2], FLTMIN)) + kb[2];
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ // the caller is responsible for m != 0
+ // the caller is responsible for k != 0
+ // TODO: pull the precomputation into the caller?
+
+ void ApplyLogToLin(float* rgbaBuffer, long numPixels,
+ const float * k,
+ const float * m,
+ const float * b,
+ const float * base,
+ const float * kb)
+ {
+ float kinv[3] = { 1.0f / k[0],
+ 1.0f / k[1],
+ 1.0f / k[2] };
+
+ float minv[3] = { 1.0f / m[0],
+ 1.0f / m[1],
+ 1.0f / m[2] };
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ rgbaBuffer[0] = minv[0] * (powf(base[0], kinv[0]*(rgbaBuffer[0]-kb[0])) - b[0]);
+ rgbaBuffer[1] = minv[1] * (powf(base[1], kinv[1]*(rgbaBuffer[1]-kb[1])) - b[1]);
+ rgbaBuffer[2] = minv[2] * (powf(base[2], kinv[2]*(rgbaBuffer[2]-kb[2])) - b[2]);
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ namespace
+ {
+ class LogOp : public Op
+ {
+ public:
+ LogOp(const float * k,
+ const float * m,
+ const float * b,
+ const float * base,
+ const float * kb,
+ TransformDirection direction);
+ virtual ~LogOp();
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const;
+ virtual std::string getCacheID() const;
+
+ virtual bool isNoOp() const;
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const;
+ virtual void finalize();
+ virtual void apply(float* rgbaBuffer, long numPixels) const;
+
+ virtual bool supportsGpuShader() const;
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const;
+
+ private:
+ float m_k[3];
+ float m_m[3];
+ float m_b[3];
+ float m_base[3];
+ float m_kb[3];
+ TransformDirection m_direction;
+
+ std::string m_cacheID;
+ };
+
+ typedef OCIO_SHARED_PTR<LogOp> LogOpRcPtr;
+
+ LogOp::LogOp(const float * k,
+ const float * m,
+ const float * b,
+ const float * base,
+ const float * kb,
+ TransformDirection direction):
+ Op(),
+ m_direction(direction)
+ {
+ if(m_direction == TRANSFORM_DIR_UNKNOWN)
+ {
+ throw Exception("Cannot apply LogOp op, unspecified transform direction.");
+ }
+
+ memcpy(m_k, k, sizeof(float)*3);
+ memcpy(m_m, m, sizeof(float)*3);
+ memcpy(m_b, b, sizeof(float)*3);
+ memcpy(m_base, base, sizeof(float)*3);
+ memcpy(m_kb, kb, sizeof(float)*3);
+ }
+
+ OpRcPtr LogOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new LogOp(m_k, m_m, m_b, m_base, m_kb, m_direction));
+ return op;
+ }
+
+ LogOp::~LogOp()
+ { }
+
+ std::string LogOp::getInfo() const
+ {
+ return "<LogOp>";
+ }
+
+ std::string LogOp::getCacheID() const
+ {
+ return m_cacheID;
+ }
+
+ bool LogOp::isNoOp() const
+ {
+ return false;
+ }
+
+ bool LogOp::isSameType(const OpRcPtr & op) const
+ {
+ LogOpRcPtr typedRcPtr = DynamicPtrCast<LogOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool LogOp::isInverse(const OpRcPtr & op) const
+ {
+ LogOpRcPtr typedRcPtr = DynamicPtrCast<LogOp>(op);
+ if(!typedRcPtr) return false;
+
+ if(GetInverseTransformDirection(m_direction) != typedRcPtr->m_direction)
+ return false;
+
+ float error = std::numeric_limits<float>::min();
+ if(!VecsEqualWithRelError(m_k, 3, typedRcPtr->m_k, 3, error))
+ return false;
+ if(!VecsEqualWithRelError(m_m, 3, typedRcPtr->m_m, 3, error))
+ return false;
+ if(!VecsEqualWithRelError(m_b, 3, typedRcPtr->m_b, 3, error))
+ return false;
+ if(!VecsEqualWithRelError(m_base, 3, typedRcPtr->m_base, 3, error))
+ return false;
+ if(!VecsEqualWithRelError(m_kb, 3, typedRcPtr->m_kb, 3, error))
+ return false;
+
+ return true;
+ }
+
+ bool LogOp::hasChannelCrosstalk() const
+ {
+ return false;
+ }
+
+ void LogOp::finalize()
+ {
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ if(VecContainsOne(m_base, 3))
+ throw Exception("LogOp Exception, base cannot be 1.");
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ if(VecContainsZero(m_m, 3))
+ throw Exception("LogOp Exception, m (slope) cannot be 0.");
+ if(VecContainsZero(m_k, 3))
+ throw Exception("LogOp Exception, k (multiplier) cannot be 0.");
+ }
+
+ std::ostringstream cacheIDStream;
+ cacheIDStream << "<LogOp ";
+ cacheIDStream.precision(FLOAT_DECIMALS);
+ for(int i=0; i<3; ++i)
+ {
+ cacheIDStream << m_k[i] << " ";
+ cacheIDStream << m_m[i] << " ";
+ cacheIDStream << m_b[i] << " ";
+ cacheIDStream << m_base[i] << " ";
+ cacheIDStream << m_kb[i] << " ";
+ }
+
+ cacheIDStream << TransformDirectionToString(m_direction) << " ";
+ cacheIDStream << ">";
+
+ m_cacheID = cacheIDStream.str();
+ }
+
+ void LogOp::apply(float* rgbaBuffer, long numPixels) const
+ {
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ ApplyLinToLog(rgbaBuffer, numPixels,
+ m_k, m_m, m_b, m_base, m_kb);
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ ApplyLogToLin(rgbaBuffer, numPixels,
+ m_k, m_m, m_b, m_base, m_kb);
+ }
+ } // Op::process
+
+ bool LogOp::supportsGpuShader() const
+ {
+ return true;
+ }
+
+ void LogOp::writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const
+ {
+ GpuLanguage lang = shaderDesc.getLanguage();
+
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ // Lin To Log
+ // k * log(mx+b, base) + kb
+
+ // We account for the change of base by rolling the multiplier
+ // in with 'k'
+
+ float knew[3] = { m_k[0] / logf(m_base[0]),
+ m_k[1] / logf(m_base[1]),
+ m_k[2] / logf(m_base[0]) };
+
+ float clampMin[3] = { FLTMIN, FLTMIN, FLTMIN };
+
+ // TODO: Switch to f32 for internal Cg processing?
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ clampMin[0] = static_cast<float>(GetHalfNormMin());
+ clampMin[1] = static_cast<float>(GetHalfNormMin());
+ clampMin[2] = static_cast<float>(GetHalfNormMin());
+ }
+
+ // Decompose into 2 steps
+ // 1) clamp(mx+b)
+ // 2) knew * log(x) + kb
+
+ shader << pixelName << ".rgb = ";
+ shader << "max(" << GpuTextHalf3(clampMin,lang) << ", ";
+ shader << GpuTextHalf3(m_m,lang) << " * ";
+ shader << pixelName << ".rgb + ";
+ shader << GpuTextHalf3(m_b,lang) << ");\n";
+
+ shader << pixelName << ".rgb = ";
+ shader << GpuTextHalf3(knew,lang) << " * ";
+ shader << "log(" << pixelName << ".rgb) + ";
+ shader << GpuTextHalf3(m_kb,lang) << ";\n";
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ float kinv[3] = { 1.0f / m_k[0],
+ 1.0f / m_k[1],
+ 1.0f / m_k[2] };
+
+ float minv[3] = { 1.0f / m_m[0],
+ 1.0f / m_m[1],
+ 1.0f / m_m[2] };
+
+ // Decompose into 3 steps
+ // 1) kinv * ( x - kb)
+ // 2) pow(base, x)
+ // 3) minv * (x - b)
+
+ shader << pixelName << ".rgb = ";
+ shader << GpuTextHalf3(kinv,lang) << " * (";
+ shader << pixelName << ".rgb - ";
+ shader << GpuTextHalf3(m_kb,lang) << ");\n";
+
+ shader << pixelName << ".rgb = pow(";
+ shader << GpuTextHalf3(m_base,lang) << ", ";
+ shader << pixelName << ".rgb);\n";
+
+ shader << pixelName << ".rgb = ";
+ shader << GpuTextHalf3(minv,lang) << " * (";
+ shader << pixelName << ".rgb - ";
+ shader << GpuTextHalf3(m_b,lang) << ");\n";
+ }
+ }
+
+ } // Anon namespace
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ void CreateLogOp(OpRcPtrVec & ops,
+ const float * k,
+ const float * m,
+ const float * b,
+ const float * base,
+ const float * kb,
+ TransformDirection direction)
+ {
+ ops.push_back( LogOpRcPtr(new LogOp(k, m, b, base, kb, direction)) );
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(LogOps, LinToLog)
+{
+ float k[3] = { 0.18f, 0.18f, 0.18f };
+ float m[3] = { 2.0f, 2.0f, 2.0f };
+ float b[3] = { 0.1f, 0.1f, 0.1f };
+ float base[3] = { 10.0f, 10.0f, 10.0f };
+ float kb[3] = { 1.0f, 1.0f, 1.0f };
+
+
+ float data[8] = { 0.01f, 0.1f, 1.0f, 1.0f,
+ 10.0f, 100.0f, 1000.0f, 1.0f, };
+
+ float result[8] = { 0.8342526242885725f,
+ 0.90588182584953925f,
+ 1.057999473052105462f,
+ 1.0f,
+ 1.23457529033568797f,
+ 1.41422447595451795f,
+ 1.59418930777214063f,
+ 1.0f };
+
+ OCIO::OpRcPtrVec ops;
+ CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_FORWARD);
+
+ FinalizeOpVec(ops);
+
+ // Apply the result
+ for(OCIO::OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ ops[i]->apply(data, 2);
+ }
+
+ for(int i=0; i<8; ++i)
+ {
+ OIIO_CHECK_CLOSE( data[i], result[i], 1.0e-3 );
+ }
+}
+
+OIIO_ADD_TEST(LogOps, LogToLin)
+{
+ float k[3] = { 0.18f, 0.18f, 0.18f };
+ float m[3] = { 2.0f, 2.0f, 2.0f };
+ float b[3] = { 0.1f, 0.1f, 0.1f };
+ float base[3] = { 10.0f, 10.0f, 10.0f };
+ float kb[3] = { 1.0f, 1.0f, 1.0f };
+
+ float data[8] = { 0.8342526242885725f,
+ 0.90588182584953925f,
+ 1.057999473052105462f,
+ 1.0f,
+ 1.23457529033568797f,
+ 1.41422447595451795f,
+ 1.59418930777214063f,
+ 1.0f };
+
+ float result[8] = { 0.01f, 0.1f, 1.0f, 1.0f,
+ 10.0f, 100.0f, 1000.0f, 1.0f, };
+
+ OCIO::OpRcPtrVec ops;
+ CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_INVERSE);
+
+ FinalizeOpVec(ops);
+
+ // Apply the result
+ for(OCIO::OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ ops[i]->apply(data, 2);
+ }
+
+ for(int i=0; i<8; ++i)
+ {
+ OIIO_CHECK_CLOSE( data[i], result[i], 1.0e-3 );
+ }
+}
+
+OIIO_ADD_TEST(LogOps, Inverse)
+{
+ float k[3] = { 0.18f, 0.18f, 0.18f };
+ float m[3] = { 2.0f, 2.0f, 2.0f };
+ float b[3] = { 0.1f, 0.1f, 0.1f };
+ float base[3] = { 10.0f, 10.0f, 10.0f };
+ float kb[3] = { 1.0f, 1.0f, 1.0f };
+
+ OCIO::OpRcPtrVec ops;
+ CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_FORWARD);
+
+ CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_INVERSE);
+
+ base[0] += 1e-5f;
+ CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_INVERSE);
+ CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 4);
+
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[1]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[2]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[3]->clone()));
+
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[0]), false);
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[1]), true);
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL(ops[0]->isInverse(ops[3]), false);
+
+ OIIO_CHECK_EQUAL(ops[1]->isInverse(ops[0]), true);
+ OIIO_CHECK_EQUAL(ops[1]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL(ops[1]->isInverse(ops[3]), false);
+
+ OIIO_CHECK_EQUAL(ops[2]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL(ops[2]->isInverse(ops[3]), true);
+
+ OIIO_CHECK_EQUAL(ops[3]->isInverse(ops[3]), false);
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/LogOps.h b/src/core/LogOps.h
new file mode 100644
index 0000000..0356fd8
--- /dev/null
+++ b/src/core/LogOps.h
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_LOGOPS_H
+#define INCLUDED_OCIO_LOGOPS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // output = k * log(mx+b, base) + kb
+ // This does not affect alpha
+ // In the forward direction this is lin->log
+ // All input vectors are size 3 (including base)
+
+ void CreateLogOp(OpRcPtrVec & ops,
+ const float * k,
+ const float * m,
+ const float * b,
+ const float * base,
+ const float * kb,
+ TransformDirection direction);
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/LogTransform.cpp b/src/core/LogTransform.cpp
new file mode 100644
index 0000000..8ed7bb0
--- /dev/null
+++ b/src/core/LogTransform.cpp
@@ -0,0 +1,157 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+#include <sstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "LogOps.h"
+#include "OpBuilders.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ LogTransformRcPtr LogTransform::Create()
+ {
+ return LogTransformRcPtr(new LogTransform(), &deleter);
+ }
+
+ void LogTransform::deleter(LogTransform* t)
+ {
+ delete t;
+ }
+
+
+ class LogTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ float base_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD),
+ base_(2.0)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ base_ = rhs.base_;
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ LogTransform::LogTransform()
+ : m_impl(new LogTransform::Impl)
+ {
+ }
+
+ TransformRcPtr LogTransform::createEditableCopy() const
+ {
+ LogTransformRcPtr transform = LogTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ LogTransform::~LogTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ LogTransform& LogTransform::operator= (const LogTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection LogTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void LogTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+
+ float LogTransform::getBase() const
+ {
+ return getImpl()->base_;
+ }
+
+ void LogTransform::setBase(float val)
+ {
+ getImpl()->base_ = val;
+ }
+
+ std::ostream& operator<< (std::ostream& os, const LogTransform& t)
+ {
+ os << "<LogTransform ";
+ os << "base=" << t.getBase() << ", ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ void BuildLogOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const LogTransform& transform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ transform.getDirection());
+
+ float basescalar = transform.getBase();
+ float base[3] = { basescalar, basescalar, basescalar };
+
+ float k[3] = { 1.0f, 1.0f, 1.0f };
+ float m[3] = { 1.0f, 1.0f, 1.0f };
+ float b[3] = { 0.0f, 0.0f, 0.0f };
+ float kb[3] = { 0.0f, 0.0f, 0.0f };
+
+ // output = k * log(mx+b, base) + kb
+ CreateLogOp(ops,
+ k, m, b, base, kb,
+ combinedDir);
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Logging.cpp b/src/core/Logging.cpp
new file mode 100644
index 0000000..7846ac2
--- /dev/null
+++ b/src/core/Logging.cpp
@@ -0,0 +1,156 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Logging.h"
+#include "Mutex.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const char * OCIO_LOGGING_LEVEL_ENVVAR = "OCIO_LOGGING_LEVEL";
+ const LoggingLevel OCIO_DEFAULT_LOGGING_LEVEL = LOGGING_LEVEL_INFO;
+
+ Mutex g_logmutex;
+ LoggingLevel g_logginglevel = LOGGING_LEVEL_UNKNOWN;
+ bool g_initialized = false;
+ bool g_loggingOverride = false;
+
+ // You must manually acquire the logging mutex before calling this.
+ // This will set g_logginglevel, g_initialized, g_loggingOverride
+ void InitLogging()
+ {
+ if(g_initialized) return;
+
+ g_initialized = true;
+
+ char* levelstr = std::getenv(OCIO_LOGGING_LEVEL_ENVVAR);
+ if(levelstr)
+ {
+ g_loggingOverride = true;
+ g_logginglevel = LoggingLevelFromString(levelstr);
+
+ if(g_logginglevel == LOGGING_LEVEL_UNKNOWN)
+ {
+ std::cerr << "[OpenColorIO Warning]: Invalid $OCIO_LOGGING_LEVEL specified. ";
+ std::cerr << "Options: none (0), warning (1), info (2), debug (3)" << std::endl;
+ g_logginglevel = OCIO_DEFAULT_LOGGING_LEVEL;
+ }
+ }
+ else
+ {
+ g_logginglevel = OCIO_DEFAULT_LOGGING_LEVEL;
+ }
+ }
+ }
+
+ LoggingLevel GetLoggingLevel()
+ {
+ AutoMutex lock(g_logmutex);
+ InitLogging();
+
+ return g_logginglevel;
+ }
+
+ void SetLoggingLevel(LoggingLevel level)
+ {
+ AutoMutex lock(g_logmutex);
+ InitLogging();
+
+ // Calls to SetLoggingLevel are ignored if OCIO_LOGGING_LEVEL_ENVVAR
+ // is specified. This is to allow users to optionally debug OCIO at
+ // runtime even in applications that disable logging.
+
+ if(!g_loggingOverride)
+ {
+ g_logginglevel = level;
+ }
+ }
+
+ void LogWarning(const std::string & text)
+ {
+ AutoMutex lock(g_logmutex);
+ InitLogging();
+
+ if(g_logginglevel<LOGGING_LEVEL_WARNING) return;
+
+ std::vector<std::string> parts;
+ pystring::split( pystring::rstrip(text), parts, "\n");
+
+ for(unsigned int i=0; i<parts.size(); ++i)
+ {
+ std::cerr << "[OpenColorIO Warning]: " << parts[i] << std::endl;
+ }
+ }
+
+ void LogInfo(const std::string & text)
+ {
+ AutoMutex lock(g_logmutex);
+ InitLogging();
+
+ if(g_logginglevel<LOGGING_LEVEL_INFO) return;
+
+ std::vector<std::string> parts;
+ pystring::split( pystring::rstrip(text), parts, "\n");
+
+ for(unsigned int i=0; i<parts.size(); ++i)
+ {
+ std::cerr << "[OpenColorIO Info]: " << parts[i] << std::endl;
+ }
+ }
+
+ void LogDebug(const std::string & text)
+ {
+ AutoMutex lock(g_logmutex);
+ InitLogging();
+
+ if(g_logginglevel<LOGGING_LEVEL_DEBUG) return;
+
+ std::vector<std::string> parts;
+ pystring::split( pystring::rstrip(text), parts, "\n");
+
+ for(unsigned int i=0; i<parts.size(); ++i)
+ {
+ std::cerr << "[OpenColorIO Debug]: " << parts[i] << std::endl;
+ }
+ }
+
+ bool IsDebugLoggingEnabled()
+ {
+ return (GetLoggingLevel()>=LOGGING_LEVEL_DEBUG);
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Logging.h b/src/core/Logging.h
new file mode 100644
index 0000000..173e642
--- /dev/null
+++ b/src/core/Logging.h
@@ -0,0 +1,47 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_LOGGING_H
+#define INCLUDED_OCIO_LOGGING_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <string>
+
+OCIO_NAMESPACE_ENTER
+{
+ void LogWarning(const std::string & text);
+ void LogInfo(const std::string & text);
+ void LogDebug(const std::string & text);
+
+ bool IsDebugLoggingEnabled();
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/Look.cpp b/src/core/Look.cpp
new file mode 100644
index 0000000..fd1bfe7
--- /dev/null
+++ b/src/core/Look.cpp
@@ -0,0 +1,163 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+#include <sstream>
+#include <vector>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ LookRcPtr Look::Create()
+ {
+ return LookRcPtr(new Look(), &deleter);
+ }
+
+ void Look::deleter(Look* c)
+ {
+ delete c;
+ }
+
+ class Look::Impl
+ {
+ public:
+ std::string name_;
+ std::string processSpace_;
+ TransformRcPtr transform_;
+ TransformRcPtr inverseTransform_;
+
+ Impl()
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ name_ = rhs.name_;
+ processSpace_ = rhs.processSpace_;
+
+ transform_ = rhs.transform_;
+ if(transform_) transform_ = transform_->createEditableCopy();
+
+ inverseTransform_ = rhs.inverseTransform_;
+ if(inverseTransform_) inverseTransform_ = inverseTransform_->createEditableCopy();
+
+ return *this;
+ }
+ };
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ Look::Look()
+ : m_impl(new Look::Impl)
+ {
+ }
+
+ Look::~Look()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ LookRcPtr Look::createEditableCopy() const
+ {
+ LookRcPtr cs = Look::Create();
+ *cs->m_impl = *m_impl;
+ return cs;
+ }
+
+ const char * Look::getName() const
+ {
+ return getImpl()->name_.c_str();
+ }
+
+ void Look::setName(const char * name)
+ {
+ getImpl()->name_ = name;
+ }
+
+ const char * Look::getProcessSpace() const
+ {
+ return getImpl()->processSpace_.c_str();
+ }
+
+ void Look::setProcessSpace(const char * processSpace)
+ {
+ getImpl()->processSpace_ = processSpace;
+ }
+
+ ConstTransformRcPtr Look::getTransform() const
+ {
+ return getImpl()->transform_;
+ }
+
+ void Look::setTransform(const ConstTransformRcPtr & transform)
+ {
+ getImpl()->transform_ = transform->createEditableCopy();
+ }
+
+ ConstTransformRcPtr Look::getInverseTransform() const
+ {
+ return getImpl()->inverseTransform_;
+ }
+
+ void Look::setInverseTransform(const ConstTransformRcPtr & transform)
+ {
+ getImpl()->inverseTransform_ = transform->createEditableCopy();
+ }
+
+
+ std::ostream& operator<< (std::ostream& os, const Look& look)
+ {
+ os << "<Look ";
+ os << "name=" << look.getName() << ", ";
+ os << "processSpace=" << look.getProcessSpace() << ", ";
+
+ if(look.getTransform())
+ {
+ os << "\tTransform: ";
+ os << *look.getTransform();
+ }
+
+ if(look.getInverseTransform())
+ {
+ os << "\tInverseTransform: ";
+ os << *look.getInverseTransform();
+ }
+
+ os << ">";
+
+ return os;
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/LookParse.cpp b/src/core/LookParse.cpp
new file mode 100644
index 0000000..3c6db03
--- /dev/null
+++ b/src/core/LookParse.cpp
@@ -0,0 +1,309 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <algorithm>
+
+#include "LookParse.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+#include <iostream>
+
+OCIO_NAMESPACE_ENTER
+{
+ void LookParseResult::Token::parse(const std::string & str)
+ {
+ // Assert no commas, colons, or | in str.
+
+ if(pystring::startswith(str, "+"))
+ {
+ name = pystring::lstrip(str, "+");
+ dir = TRANSFORM_DIR_FORWARD;
+ }
+ // TODO: Handle --
+ else if(pystring::startswith(str, "-"))
+ {
+ name = pystring::lstrip(str, "-");
+ dir = TRANSFORM_DIR_INVERSE;
+ }
+ else
+ {
+ name = str;
+ dir = TRANSFORM_DIR_FORWARD;
+ }
+ }
+
+ void LookParseResult::Token::serialize(std::ostream & os) const
+ {
+ if(dir==TRANSFORM_DIR_FORWARD)
+ {
+ os << name;
+ }
+ else if(dir==TRANSFORM_DIR_INVERSE)
+ {
+ os << "-" << name;
+ }
+ else
+ {
+ os << "?" << name;
+ }
+ }
+
+ void LookParseResult::serialize(std::ostream & os, const Tokens & tokens)
+ {
+ for(unsigned int i=0; i<tokens.size(); ++i)
+ {
+ if(i!=0) os << ", ";
+ tokens[i].serialize(os);
+ }
+ }
+
+ const LookParseResult::Options & LookParseResult::parse(const std::string & looksstr)
+ {
+ m_options.clear();
+
+ std::string strippedlooks = pystring::strip(looksstr);
+ if(strippedlooks.empty())
+ {
+ return m_options;
+ }
+
+ std::vector<std::string> options;
+ pystring::split(strippedlooks, options, "|");
+
+ std::vector<std::string> vec;
+
+ for(unsigned int optionsindex=0;
+ optionsindex<options.size();
+ ++optionsindex)
+ {
+ LookParseResult::Tokens tokens;
+
+ vec.clear();
+ SplitStringEnvStyle(vec, options[optionsindex].c_str());
+ for(unsigned int i=0; i<vec.size(); ++i)
+ {
+ LookParseResult::Token t;
+ t.parse(vec[i]);
+ tokens.push_back(t);
+ }
+
+ m_options.push_back(tokens);
+ }
+
+ return m_options;
+ }
+
+ const LookParseResult::Options & LookParseResult::getOptions() const
+ {
+ return m_options;
+ }
+
+ bool LookParseResult::empty() const
+ {
+ return m_options.empty();
+ }
+
+ void LookParseResult::reverse()
+ {
+ // m_options itself should NOT be reversed.
+ // The individual looks
+ // need to be applied in the inverse direction. But, the precedence
+ // for which option to apply is to be maintained!
+
+ for(unsigned int optionindex=0;
+ optionindex<m_options.size();
+ ++optionindex)
+ {
+ std::reverse(m_options[optionindex].begin(), m_options[optionindex].end());
+
+ for(unsigned int tokenindex=0;
+ tokenindex<m_options[optionindex].size();
+ ++tokenindex)
+ {
+ m_options[optionindex][tokenindex].dir =
+ GetInverseTransformDirection(
+ m_options[optionindex][tokenindex].dir);
+ }
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+OCIO_NAMESPACE_USING
+
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(LookParse, Parse)
+{
+ LookParseResult r;
+
+ {
+ const LookParseResult::Options & options = r.parse("");
+ OIIO_CHECK_EQUAL(options.size(), 0);
+ OIIO_CHECK_EQUAL(options.empty(), true);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse(" ");
+ OIIO_CHECK_EQUAL(options.size(), 0);
+ OIIO_CHECK_EQUAL(options.empty(), true);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse("cc");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse("+cc");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse(" +cc");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse(" +cc ");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse("+cc,-di");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0].size(), 2);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[0][1].name, "di");
+ OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse(" +cc , -di");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0].size(), 2);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[0][1].name, "di");
+ OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse(" +cc : -di");
+ OIIO_CHECK_EQUAL(options.size(), 1);
+ OIIO_CHECK_EQUAL(options[0].size(), 2);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[0][1].name, "di");
+ OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse("+cc, -di |-cc");
+ OIIO_CHECK_EQUAL(options.size(), 2);
+ OIIO_CHECK_EQUAL(options[0].size(), 2);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[0][1].name, "di");
+ OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options[1].size(), 1);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ OIIO_CHECK_EQUAL(options[1][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[1][0].dir, TRANSFORM_DIR_INVERSE);
+ }
+
+ {
+ const LookParseResult::Options & options = r.parse("+cc, -di |-cc| ");
+ OIIO_CHECK_EQUAL(options.size(), 3);
+ OIIO_CHECK_EQUAL(options[0].size(), 2);
+ OIIO_CHECK_EQUAL(options[0][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[0][1].name, "di");
+ OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options[1].size(), 1);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ OIIO_CHECK_EQUAL(options[1][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[1][0].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options[2].size(), 1);
+ OIIO_CHECK_EQUAL(options[2][0].name, "");
+ OIIO_CHECK_EQUAL(options[2][0].dir, TRANSFORM_DIR_FORWARD);
+ }
+}
+
+OIIO_ADD_TEST(LookParse, Reverse)
+{
+ LookParseResult r;
+
+ {
+ r.parse("+cc, -di |-cc| ");
+ r.reverse();
+ const LookParseResult::Options & options = r.getOptions();
+
+ OIIO_CHECK_EQUAL(options.size(), 3);
+ OIIO_CHECK_EQUAL(options[0].size(), 2);
+ OIIO_CHECK_EQUAL(options[0][1].name, "cc");
+ OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(options[0][0].name, "di");
+ OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[1].size(), 1);
+ OIIO_CHECK_EQUAL(options.empty(), false);
+ OIIO_CHECK_EQUAL(options[1][0].name, "cc");
+ OIIO_CHECK_EQUAL(options[1][0].dir, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(options[2].size(), 1);
+ OIIO_CHECK_EQUAL(options[2][0].name, "");
+ OIIO_CHECK_EQUAL(options[2][0].dir, TRANSFORM_DIR_INVERSE);
+ }
+
+
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/LookParse.h b/src/core/LookParse.h
new file mode 100644
index 0000000..e867ce7
--- /dev/null
+++ b/src/core/LookParse.h
@@ -0,0 +1,79 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_PARSED_LOOK_H
+#define INCLUDED_OCIO_PARSED_LOOK_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // Looks parse structures
+ // This is contains a list, where each option entry corresponds to
+ // an "or" separated looks token list.
+ // I.e, " +cc,-onset | +cc " parses to TWO options: (+cc,-onset), (+cc)
+
+ class LookParseResult
+ {
+ public:
+ struct Token
+ {
+ std::string name;
+ TransformDirection dir;
+
+ Token():
+ dir(TRANSFORM_DIR_FORWARD) {}
+
+ void parse(const std::string & str);
+ void serialize(std::ostream & os) const;
+ };
+
+ typedef std::vector<Token> Tokens;
+
+ static void serialize(std::ostream & os, const Tokens & tokens);
+
+ typedef std::vector<Tokens> Options;
+
+ const Options & parse(const std::string & looksstr);
+
+ const Options & getOptions() const;
+ bool empty() const;
+
+ void reverse();
+
+ private:
+ Options m_options;
+ };
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/LookTransform.cpp b/src/core/LookTransform.cpp
new file mode 100644
index 0000000..0092d16
--- /dev/null
+++ b/src/core/LookTransform.cpp
@@ -0,0 +1,405 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <algorithm>
+#include <iterator>
+
+#include "LookParse.h"
+#include "NoOps.h"
+#include "OpBuilders.h"
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+
+OCIO_NAMESPACE_ENTER
+{
+ LookTransformRcPtr LookTransform::Create()
+ {
+ return LookTransformRcPtr(new LookTransform(), &deleter);
+ }
+
+ void LookTransform::deleter(LookTransform* t)
+ {
+ delete t;
+ }
+
+
+ class LookTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ std::string src_;
+ std::string dst_;
+ std::string looks_;
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ src_ = rhs.src_;
+ dst_ = rhs.dst_;
+ looks_ = rhs.looks_;
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ LookTransform::LookTransform()
+ : m_impl(new LookTransform::Impl)
+ {
+ }
+
+ TransformRcPtr LookTransform::createEditableCopy() const
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ LookTransform::~LookTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ LookTransform& LookTransform::operator= (const LookTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection LookTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void LookTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ const char * LookTransform::getSrc() const
+ {
+ return getImpl()->src_.c_str();
+ }
+
+ void LookTransform::setSrc(const char * src)
+ {
+ getImpl()->src_ = src;
+ }
+
+ const char * LookTransform::getDst() const
+ {
+ return getImpl()->dst_.c_str();
+ }
+
+ void LookTransform::setDst(const char * dst)
+ {
+ getImpl()->dst_ = dst;
+ }
+
+ void LookTransform::setLooks(const char * looks)
+ {
+ getImpl()->looks_ = looks;
+ }
+
+ const char * LookTransform::getLooks() const
+ {
+ return getImpl()->looks_.c_str();
+ }
+
+ std::ostream& operator<< (std::ostream& os, const LookTransform& t)
+ {
+ os << "<LookTransform ";
+ os << "src=" << t.getSrc() << ", ";
+ os << "dst=" << t.getDst() << ", ";
+ os << "looks=" << t.getLooks() << ", ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+ return os;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ namespace
+ {
+
+ void RunLookTokens(OpRcPtrVec & ops,
+ ConstColorSpaceRcPtr & currentColorSpace,
+ bool skipColorSpaceConversions,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const LookParseResult::Tokens & lookTokens)
+ {
+ if(lookTokens.empty()) return;
+
+ for(unsigned int i=0; i<lookTokens.size(); ++i)
+ {
+ const std::string & lookName = lookTokens[i].name;
+
+ if(lookName.empty()) continue;
+
+ ConstLookRcPtr look = config.getLook(lookName.c_str());
+ if(!look)
+ {
+ std::ostringstream os;
+ os << "RunLookTokens error. ";
+ os << "The specified look, '" << lookName;
+ os << "', cannot be found. ";
+ if(config.getNumLooks() == 0)
+ {
+ os << " (No looks defined in config)";
+ }
+ else
+ {
+ os << " (looks: ";
+ for(int ii=0; ii<config.getNumLooks(); ++ii)
+ {
+ if(ii != 0) os << ", ";
+ os << config.getLookNameByIndex(ii);
+ }
+ os << ")";
+ }
+
+ throw Exception(os.str().c_str());
+ }
+
+ // Put the new ops into a temp array, to see if it's a no-op
+ // If it is a no-op, dont bother doing the colorspace conversion.
+ OpRcPtrVec tmpOps;
+
+ if(lookTokens[i].dir == TRANSFORM_DIR_FORWARD)
+ {
+ CreateLookNoOp(tmpOps, lookName);
+ if(look->getTransform())
+ {
+ BuildOps(tmpOps, config, context, look->getTransform(), TRANSFORM_DIR_FORWARD);
+ }
+ else if(look->getInverseTransform())
+ {
+ BuildOps(tmpOps, config, context, look->getInverseTransform(), TRANSFORM_DIR_INVERSE);
+ }
+ }
+ else if(lookTokens[i].dir == TRANSFORM_DIR_INVERSE)
+ {
+ CreateLookNoOp(tmpOps, std::string("-") + lookName);
+ if(look->getInverseTransform())
+ {
+ BuildOps(tmpOps, config, context, look->getInverseTransform(), TRANSFORM_DIR_FORWARD);
+ }
+ else if(look->getTransform())
+ {
+ BuildOps(tmpOps, config, context, look->getTransform(), TRANSFORM_DIR_INVERSE);
+ }
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "BuildLookOps error. ";
+ os << "The specified look, '" << lookTokens[i].name;
+ os << "' has an ill-defined transform direction.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(!IsOpVecNoOp(tmpOps))
+ {
+ if(!skipColorSpaceConversions)
+ {
+ ConstColorSpaceRcPtr processColorSpace = config.getColorSpace(look->getProcessSpace());
+ if(!processColorSpace)
+ {
+ std::ostringstream os;
+ os << "RunLookTokens error. ";
+ os << "The specified look, '" << lookTokens[i].name;
+ os << "', requires processing in the ColorSpace, '";
+ os << look->getProcessSpace() << "' which is not defined.";
+ throw Exception(os.str().c_str());
+ }
+
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ processColorSpace);
+ currentColorSpace = processColorSpace;
+ }
+
+ std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops));
+ }
+ }
+ }
+
+ } // anon namespace
+
+ ////////////////////////////////////////////////////////////////////////////
+
+
+ void BuildLookOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const LookTransform & lookTransform,
+ TransformDirection dir)
+ {
+ ConstColorSpaceRcPtr src, dst;
+ src = config.getColorSpace( lookTransform.getSrc() );
+ dst = config.getColorSpace( lookTransform.getDst() );
+
+ if(!src)
+ {
+ std::ostringstream os;
+ os << "BuildLookOps error.";
+ os << "The specified lookTransform specifies a src colorspace, '";
+ os << lookTransform.getSrc() << "', which is not defined.";
+ throw Exception(os.str().c_str());
+ }
+
+ if(!dst)
+ {
+ std::ostringstream os;
+ os << "BuildLookOps error.";
+ os << "The specified lookTransform specifies a dst colorspace, '";
+ os << lookTransform.getDst() << "', which is not defined.";
+ throw Exception(os.str().c_str());
+ }
+
+ LookParseResult looks;
+ looks.parse(lookTransform.getLooks());
+
+ // We must handle the inverse src/dst colorspace transformation explicitly.
+ if(dir == TRANSFORM_DIR_INVERSE)
+ {
+ std::swap(src, dst);
+ looks.reverse();
+ }
+ else if(dir == TRANSFORM_DIR_UNKNOWN)
+ {
+ std::ostringstream os;
+ os << "BuildLookOps error. A valid transform direction must be specified.";
+ throw Exception(os.str().c_str());
+ }
+
+ ConstColorSpaceRcPtr currentColorSpace = src;
+ BuildLookOps(ops,
+ currentColorSpace,
+ false,
+ config,
+ context,
+ looks);
+
+ BuildColorSpaceOps(ops, config, context,
+ currentColorSpace,
+ dst);
+ }
+
+ void BuildLookOps(OpRcPtrVec & ops,
+ ConstColorSpaceRcPtr & currentColorSpace,
+ bool skipColorSpaceConversions,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const LookParseResult & looks)
+ {
+ const LookParseResult::Options & options = looks.getOptions();
+
+ if(options.empty())
+ {
+ // Do nothing
+ }
+ else if(options.size() == 1)
+ {
+ // As an optimization, if we only have a single look option,
+ // just push back onto the final location
+ RunLookTokens(ops,
+ currentColorSpace,
+ skipColorSpaceConversions,
+ config,
+ context,
+ options[0]);
+ }
+ else
+ {
+ // If we have multiple look options, try each one in order,
+ // and if we can create the ops without a missing file exception,
+ // push back it's results and return
+
+ bool success = false;
+ std::ostringstream os;
+
+ OpRcPtrVec tmpOps;
+ ConstColorSpaceRcPtr cs;
+
+ for(unsigned int i=0; i<options.size(); ++i)
+ {
+ cs = currentColorSpace;
+ tmpOps.clear();
+
+ try
+ {
+ RunLookTokens(tmpOps,
+ cs,
+ skipColorSpaceConversions,
+ config,
+ context,
+ options[i]);
+ success = true;
+ break;
+ }
+ catch(ExceptionMissingFile & e)
+ {
+ if(i != 0) os << " ... ";
+
+ os << "(";
+ LookParseResult::serialize(os, options[i]);
+ os << ") " << e.what();
+ }
+ }
+
+ if(success)
+ {
+ currentColorSpace = cs;
+ std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops));
+ }
+ else
+ {
+ throw ExceptionMissingFile(os.str().c_str());
+ }
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Lut1DOp.cpp b/src/core/Lut1DOp.cpp
new file mode 100644
index 0000000..8363536
--- /dev/null
+++ b/src/core/Lut1DOp.cpp
@@ -0,0 +1,1038 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "HashUtils.h"
+#include "Lut1DOp.h"
+#include "MathUtils.h"
+#include "SSE.h"
+
+#include <algorithm>
+#include <cmath>
+#include <sstream>
+#include <iostream>
+
+OCIO_NAMESPACE_ENTER
+{
+ Lut1D::Lut1D() :
+ maxerror(std::numeric_limits<float>::min()),
+ errortype(ERROR_RELATIVE)
+ {
+ for(int i=0; i<3; ++i)
+ {
+ from_min[i] = 0.0f;
+ from_max[i] = 1.0f;
+ }
+ }
+
+ Lut1DRcPtr Lut1D::Create()
+ {
+ return Lut1DRcPtr(new Lut1D());
+ }
+
+
+ namespace
+ {
+ bool IsLut1DNoOp(const Lut1D & lut,
+ float maxerror,
+ ErrorType errortype)
+ {
+ // If tolerance not positive, skip the check.
+ if(!(maxerror > 0.0)) return false;
+
+ for(int channel = 0; channel<3; ++channel)
+ {
+ if(lut.luts[channel].size() == 0) continue;
+
+ float inorm = 1.0f / (static_cast<float>(lut.luts[channel].size()) - 1.0f);
+
+ float m = lut.from_max[channel] - lut.from_min[channel];
+ float b = lut.from_min[channel];
+
+ for(unsigned int i=0; i<lut.luts[channel].size(); ++i)
+ {
+ float x = static_cast<float>(i) * inorm;
+ float identval = m*x+b;
+ float lutval = lut.luts[channel][i];
+
+ if(errortype == ERROR_ABSOLUTE)
+ {
+ if(!equalWithAbsError(identval, lutval, maxerror))
+ {
+ return false;
+ }
+ }
+ else if(errortype == ERROR_RELATIVE)
+ {
+ if(!equalWithRelError(identval, lutval, maxerror))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ throw Exception("Unknown error type.");
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ std::string Lut1D::getCacheID() const
+ {
+ AutoMutex lock(m_mutex);
+
+ if(luts[0].empty() || luts[1].empty() || luts[2].empty())
+ throw Exception("Cannot compute cacheID of invalid Lut1D");
+
+ if(!m_cacheID.empty())
+ return m_cacheID;
+
+ finalize();
+ return m_cacheID;
+ }
+
+ bool Lut1D::isNoOp() const
+ {
+ AutoMutex lock(m_mutex);
+
+ if(luts[0].empty() || luts[1].empty() || luts[2].empty())
+ throw Exception("Cannot compute noOp of invalid Lut1D");
+
+ if(!m_cacheID.empty())
+ return m_isNoOp;
+
+ finalize();
+
+ return m_isNoOp;
+ }
+
+ void Lut1D::unfinalize()
+ {
+ AutoMutex lock(m_mutex);
+ m_cacheID = "";
+ m_isNoOp = false;
+ }
+
+ void Lut1D::finalize() const
+ {
+ m_isNoOp = IsLut1DNoOp(*this, maxerror, errortype);
+
+ if(m_isNoOp)
+ {
+ m_cacheID = "<NULL 1D>";
+ }
+ else
+ {
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)from_min, 3*sizeof(float));
+ md5_append(&state, (const md5_byte_t *)from_max, 3*sizeof(float));
+
+ for(int i=0; i<3; ++i)
+ {
+ md5_append( &state, (const md5_byte_t *)&(luts[i][0]),
+ (int) (luts[i].size()*sizeof(float)) );
+ }
+
+ md5_finish(&state, digest);
+
+ m_cacheID = GetPrintableHash(digest);
+ }
+ }
+
+
+ namespace
+ {
+ // Note: This function assumes that minVal is less than maxVal
+ inline int clamp(float k, float minVal, float maxVal)
+ {
+ return static_cast<int>(roundf(std::max(std::min(k, maxVal), minVal)));
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // Nearest Forward
+
+ inline float lookupNearest_1D(float index, float maxIndex, const float * simple_lut)
+ {
+ return simple_lut[clamp(index, 0.0f, maxIndex)];
+ }
+
+ void Lut1D_Nearest(float* rgbaBuffer, long numPixels, const Lut1D & lut)
+ {
+ float maxIndex[3];
+ float mInv[3];
+ float b[3];
+ float mInv_x_maxIndex[3];
+ const float* startPos[3];
+
+ for(int i=0; i<3; ++i)
+ {
+ maxIndex[i] = (float) (lut.luts[i].size() - 1);
+ mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+ mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);
+ startPos[i] = &(lut.luts[i][0]);
+ }
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ if(!isnan(rgbaBuffer[0]))
+ rgbaBuffer[0] = lookupNearest_1D(mInv_x_maxIndex[0] * (rgbaBuffer[0] - b[0]), maxIndex[0], startPos[0]);
+ if(!isnan(rgbaBuffer[1]))
+ rgbaBuffer[1] = lookupNearest_1D(mInv_x_maxIndex[1] * (rgbaBuffer[1] - b[1]), maxIndex[1], startPos[1]);
+ if(!isnan(rgbaBuffer[2]))
+ rgbaBuffer[2] = lookupNearest_1D(mInv_x_maxIndex[2] * (rgbaBuffer[2] - b[2]), maxIndex[2], startPos[2]);
+
+ rgbaBuffer += 4;
+ }
+ }
+#ifdef USE_SSE
+ void Lut1D_Nearest_SSE(float* rgbaBuffer, long numPixels, const Lut1D & lut)
+ {
+ // orig: 546 ms
+ // curr: 91 ms
+
+ // These are all sized 4, to allow simpler sse loading
+ float maxIndex[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float mInv[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float b[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float mInv_x_maxIndex[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float* startPos[3];
+
+ for(int i=0; i<3; ++i)
+ {
+ maxIndex[i] = (float) (lut.luts[i].size() - 1);
+ mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+ mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);
+ startPos[i] = &(lut.luts[i][0]);
+ }
+
+ const __m128 _zero = _mm_setzero_ps();
+ const __m128 _mInv_x_maxIndex = _mm_loadu_ps(mInv_x_maxIndex);
+ const __m128 _b = _mm_loadu_ps(b);
+ const __m128 _maxIndex = _mm_loadu_ps(maxIndex);
+ const __m128 _half = _mm_set1_ps(0.5f);
+
+ float result[4];
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ // TODO: SSE Optimized nancheck
+
+ __m128 p = _mm_loadu_ps(rgbaBuffer);
+
+ // mInv_x_maxIndex * (p - b)
+ p = _mm_sub_ps(p, _b);
+ p = _mm_mul_ps(p, _mInv_x_maxIndex);
+
+ // clamp _zero <= b <= _maxIndex
+ p = _mm_max_ps(p, _zero);
+ p = _mm_min_ps(p, _maxIndex);
+
+ // add 0.5f for rounding
+ p = _mm_add_ps(p, _half);
+
+ _mm_storeu_ps(result, p);
+
+
+ // TODO: use native SSE to convert to an int?
+ // _mm_cvttss_si32
+ // Converts the lower single-precision, floating-point value of
+ // a to a 32-bit integer with truncation
+ //
+ // _mm_cvttps_pi32 converts 2 floats to 2 32-bit packed ints,
+ // with truncation
+
+ if(!isnan(result[0]))
+ rgbaBuffer[0] = startPos[0][(int)(result[0])];
+ if(!isnan(result[1]))
+ rgbaBuffer[1] = startPos[1][(int)(result[1])];
+ if(!isnan(result[2]))
+ rgbaBuffer[2] = startPos[2][(int)(result[2])];
+
+ rgbaBuffer += 4;
+ }
+ }
+#endif
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // Linear Forward
+
+ inline float lookupLinear_1D(float index, float maxIndex, const float * simple_lut)
+ {
+ int indexLow = clamp(std::floor(index), 0.0f, maxIndex);
+ int indexHigh = clamp(std::ceil(index), 0.0f, maxIndex);
+ float delta = index - (float)indexLow;
+ return (1.0f-delta) * simple_lut[indexLow] + delta * simple_lut[indexHigh];
+ }
+
+ void Lut1D_Linear(float* rgbaBuffer, long numPixels, const Lut1D & lut)
+ {
+ float maxIndex[3];
+ float mInv[3];
+ float b[3];
+ float mInv_x_maxIndex[3];
+ const float* startPos[3];
+
+ for(int i=0; i<3; ++i)
+ {
+ maxIndex[i] = (float) (lut.luts[i].size() - 1);
+ mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+ mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);
+ startPos[i] = &(lut.luts[i][0]);
+ }
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ if(!isnan(rgbaBuffer[0]))
+ rgbaBuffer[0] = lookupLinear_1D(mInv_x_maxIndex[0] * (rgbaBuffer[0] - b[0]), maxIndex[0], startPos[0]);
+ if(!isnan(rgbaBuffer[1]))
+ rgbaBuffer[1] = lookupLinear_1D(mInv_x_maxIndex[1] * (rgbaBuffer[1] - b[1]), maxIndex[1], startPos[1]);
+ if(!isnan(rgbaBuffer[2]))
+ rgbaBuffer[2] = lookupLinear_1D(mInv_x_maxIndex[2] * (rgbaBuffer[2] - b[2]), maxIndex[2], startPos[2]);
+
+ rgbaBuffer += 4;
+ }
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // Nearest Inverse
+
+ inline float reverseLookupNearest_1D(const float v, const float *start, const float *end)
+ {
+ const float *lowbound = std::lower_bound(start, end, v);
+ if (lowbound != start) --lowbound;
+
+ const float *highbound = lowbound;
+ if (highbound < end - 1) ++highbound;
+
+ // NOTE: Not dividing result by /(size-1) anymore
+ if (fabsf(v - *lowbound) < fabsf(v - *highbound))
+ {
+ return (float)(lowbound-start);
+ }
+ else
+ {
+ return (float)(highbound-start);
+ }
+ }
+
+ void Lut1D_NearestInverse(float* rgbaBuffer, long numPixels, const Lut1D & lut)
+ {
+ float m[3];
+ float b[3];
+ const float* startPos[3];
+ const float* endPos[3];
+
+ for(int i=0; i<3; ++i)
+ {
+ m[i] = (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+
+ startPos[i] = &(lut.luts[i][0]);
+ endPos[i] = startPos[i] + lut.luts[i].size();
+
+ // Roll the size division into m as an optimization
+ m[i] /= (float) (lut.luts[i].size() - 1);
+ }
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ if(!isnan(rgbaBuffer[0]))
+ rgbaBuffer[0] = m[0] * reverseLookupNearest_1D(rgbaBuffer[0], startPos[0], endPos[0]) + b[0];
+ if(!isnan(rgbaBuffer[1]))
+ rgbaBuffer[1] = m[1] * reverseLookupNearest_1D(rgbaBuffer[1], startPos[1], endPos[1]) + b[1];
+ if(!isnan(rgbaBuffer[2]))
+ rgbaBuffer[2] = m[2] * reverseLookupNearest_1D(rgbaBuffer[2], startPos[2], endPos[2]) + b[2];
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Linear Inverse
+
+ inline float reverseLookupLinear_1D(const float v, const float *start, const float *end, float invMaxIndex)
+ {
+ const float *lowbound = std::lower_bound(start, end, v);
+ if (lowbound != start) --lowbound;
+
+ const float *highbound = lowbound;
+ if (highbound < end - 1) ++highbound;
+
+ // lowbound is the lower bound, highbound is the upper bound.
+ float delta = 0.0;
+ if (*highbound > *lowbound)
+ {
+ delta = (v - *lowbound) / (*highbound - *lowbound);
+ }
+
+ return ((float)(lowbound - start) + delta) * invMaxIndex;
+ }
+
+ void Lut1D_LinearInverse(float* rgbaBuffer, long numPixels, const Lut1D & lut)
+ {
+ float m[3];
+ float b[3];
+ const float* startPos[3];
+ const float* endPos[3];
+ float invMaxIndex[3];
+
+ for(int i=0; i<3; ++i)
+ {
+ m[i] = (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+
+ startPos[i] = &(lut.luts[i][0]);
+ endPos[i] = startPos[i] + lut.luts[i].size();
+
+ invMaxIndex[i] = 1.0f / (float) (lut.luts[i].size() - 1);
+ }
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ if(!isnan(rgbaBuffer[0]))
+ rgbaBuffer[0] = m[0] * reverseLookupLinear_1D(rgbaBuffer[0], startPos[0], endPos[0], invMaxIndex[0]) + b[0];
+ if(!isnan(rgbaBuffer[1]))
+ rgbaBuffer[1] = m[1] * reverseLookupLinear_1D(rgbaBuffer[1], startPos[1], endPos[1], invMaxIndex[0]) + b[1];
+ if(!isnan(rgbaBuffer[2]))
+ rgbaBuffer[2] = m[2] * reverseLookupLinear_1D(rgbaBuffer[2], startPos[2], endPos[2], invMaxIndex[0]) + b[2];
+
+ rgbaBuffer += 4;
+ }
+ }
+
+
+ }
+
+ namespace
+ {
+ class Lut1DOp : public Op
+ {
+ public:
+ Lut1DOp(const Lut1DRcPtr & lut,
+ Interpolation interpolation,
+ TransformDirection direction);
+ virtual ~Lut1DOp();
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const;
+ virtual std::string getCacheID() const;
+
+ virtual bool isNoOp() const;
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const;
+ virtual void finalize();
+ virtual void apply(float* rgbaBuffer, long numPixels) const;
+
+ virtual bool supportsGpuShader() const;
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const;
+
+ private:
+ const Lut1DRcPtr m_lut;
+ Interpolation m_interpolation;
+ TransformDirection m_direction;
+
+ std::string m_cacheID;
+ };
+
+ typedef OCIO_SHARED_PTR<Lut1DOp> Lut1DOpRcPtr;
+
+
+ Lut1DOp::Lut1DOp(const Lut1DRcPtr & lut,
+ Interpolation interpolation,
+ TransformDirection direction):
+ Op(),
+ m_lut(lut),
+ m_interpolation(interpolation),
+ m_direction(direction)
+ {
+ }
+
+ OpRcPtr Lut1DOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new Lut1DOp(m_lut, m_interpolation, m_direction));
+ return op;
+ }
+
+ Lut1DOp::~Lut1DOp()
+ { }
+
+ std::string Lut1DOp::getInfo() const
+ {
+ return "<Lut1DOp>";
+ }
+
+ std::string Lut1DOp::getCacheID() const
+ {
+ return m_cacheID;
+ }
+
+ // TODO: compute real value for isNoOp
+ bool Lut1DOp::isNoOp() const
+ {
+ return false;
+ }
+
+ bool Lut1DOp::isSameType(const OpRcPtr & op) const
+ {
+ Lut1DOpRcPtr typedRcPtr = DynamicPtrCast<Lut1DOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool Lut1DOp::isInverse(const OpRcPtr & op) const
+ {
+ Lut1DOpRcPtr typedRcPtr = DynamicPtrCast<Lut1DOp>(op);
+ if(!typedRcPtr) return false;
+
+ if(GetInverseTransformDirection(m_direction) != typedRcPtr->m_direction)
+ return false;
+
+ return (m_lut->getCacheID() == typedRcPtr->m_lut->getCacheID());
+ }
+
+ bool Lut1DOp::hasChannelCrosstalk() const
+ {
+ return false;
+ }
+
+ void Lut1DOp::finalize()
+ {
+ if(m_direction == TRANSFORM_DIR_UNKNOWN)
+ {
+ throw Exception("Cannot apply lut1d op, unspecified transform direction.");
+ }
+
+ // Validate the requested interpolation type
+ switch(m_interpolation)
+ {
+ // These are the allowed values.
+ case INTERP_NEAREST:
+ case INTERP_LINEAR:
+ break;
+ case INTERP_BEST:
+ m_interpolation = INTERP_LINEAR;
+ break;
+ case INTERP_UNKNOWN:
+ throw Exception("Cannot apply Lut1DOp, unspecified interpolation.");
+ break;
+ case INTERP_TETRAHEDRAL:
+ throw Exception("Cannot apply Lut1DOp, tetrahedral interpolation is not allowed for 1d luts.");
+ break;
+ default:
+ throw Exception("Cannot apply Lut1DOp, invalid interpolation specified.");
+ }
+
+ if(m_lut->luts[0].empty() || m_lut->luts[1].empty() || m_lut->luts[2].empty())
+ {
+ throw Exception("Cannot apply lut1d op, no lut data provided.");
+ }
+
+ // Create the cacheID
+ std::ostringstream cacheIDStream;
+ cacheIDStream << "<Lut1DOp ";
+ cacheIDStream << m_lut->getCacheID() << " ";
+ cacheIDStream << InterpolationToString(m_interpolation) << " ";
+ cacheIDStream << TransformDirectionToString(m_direction) << " ";
+ cacheIDStream << ">";
+ m_cacheID = cacheIDStream.str();
+ }
+
+ void Lut1DOp::apply(float* rgbaBuffer, long numPixels) const
+ {
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ if(m_interpolation == INTERP_NEAREST)
+ {
+#ifdef USE_SSE
+ Lut1D_Nearest_SSE(rgbaBuffer, numPixels, *m_lut);
+#else
+ Lut1D_Nearest(rgbaBuffer, numPixels, *m_lut);
+#endif
+ }
+ else if(m_interpolation == INTERP_LINEAR)
+ {
+ Lut1D_Linear(rgbaBuffer, numPixels, *m_lut);
+ }
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ if(m_interpolation == INTERP_NEAREST)
+ {
+ Lut1D_NearestInverse(rgbaBuffer, numPixels, *m_lut);
+ }
+ else if(m_interpolation == INTERP_LINEAR)
+ {
+ Lut1D_LinearInverse(rgbaBuffer, numPixels, *m_lut);
+ }
+ }
+ }
+
+ bool Lut1DOp::supportsGpuShader() const
+ {
+ return false;
+ }
+
+ void Lut1DOp::writeGpuShader(std::ostream & /*shader*/,
+ const std::string & /*pixelName*/,
+ const GpuShaderDesc & /*shaderDesc*/) const
+ {
+ throw Exception("Lut1DOp does not support analytical shader generation.");
+ }
+ }
+
+ void CreateLut1DOp(OpRcPtrVec & ops,
+ const Lut1DRcPtr & lut,
+ Interpolation interpolation,
+ TransformDirection direction)
+ {
+ if(lut->isNoOp()) return;
+
+ // TODO: Detect if lut1d can be exactly approximated as y = mx + b
+ // If so, return a mtx instead.
+
+ ops.push_back( OpRcPtr(new Lut1DOp(lut, interpolation, direction)) );
+ }
+
+
+ void GenerateIdentityLut1D(float* img, int numElements, int numChannels)
+ {
+ if(!img) return;
+ int numChannelsToFill = std::min(3, numChannels);
+
+ float scale = 1.0f / ((float) numElements - 1.0f);
+ for(int i=0; i<numElements; i++)
+ {
+ for(int c=0; c<numChannelsToFill; ++c)
+ {
+ img[numChannels*i+c] = scale * (float)(i);
+ }
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+#include <cstring>
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(Lut1DOp, NoOp)
+{
+ // Make an identity lut
+ OCIO::Lut1DRcPtr lut = OCIO::Lut1D::Create();
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ for(int c=0; c<3; ++c)
+ {
+ lut->luts[c].push_back(x);
+ }
+ }
+
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_RELATIVE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), true);
+
+ lut->unfinalize();
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_ABSOLUTE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), true);
+
+ // Edit the lut
+ // These should NOT be identity
+ lut->unfinalize();
+ lut->luts[0][125] += 1e-3f;
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_RELATIVE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), false);
+
+ lut->unfinalize();
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_ABSOLUTE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), false);
+}
+
+
+OIIO_ADD_TEST(Lut1DOp, FiniteValue)
+{
+ // Make a lut that squares the input
+ OCIO::Lut1DRcPtr lut = OCIO::Lut1D::Create();
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ float x2 = x*x;
+
+ for(int c=0; c<3; ++c)
+ {
+ lut->luts[c].push_back(x2);
+ }
+ }
+
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_RELATIVE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), false);
+
+ float inputBuffer_linearforward[4] = { 0.5f, 0.6f, 0.7f, 0.5f };
+ float outputBuffer_linearforward[4] = { 0.25f, 0.36f, 0.49f, 0.5f };
+ OCIO::Lut1D_Linear(inputBuffer_linearforward, 1, *lut);
+ for(int i=0; i <4; ++i)
+ {
+ OIIO_CHECK_CLOSE(inputBuffer_linearforward[i], outputBuffer_linearforward[i], 1e-5f);
+ }
+
+ float inputBuffer_nearestforward[4] = { 0.5f, 0.6f, 0.7f, 0.5f };
+ float outputBuffer_nearestforward[4] = { 0.25f, 0.36f, 0.49f, 0.5f };
+ OCIO::Lut1D_Nearest(inputBuffer_nearestforward, 1, *lut);
+ for(int i=0; i <4; ++i)
+ {
+ OIIO_CHECK_CLOSE(inputBuffer_nearestforward[i], outputBuffer_nearestforward[i], 1e-2f);
+ }
+
+ float inputBuffer_linearinverse[4] = { 0.5f, 0.6f, 0.7f, 0.5f };
+ float outputBuffer_linearinverse[4] = { 0.25f, 0.36f, 0.49f, 0.5f };
+ OCIO::Lut1D_LinearInverse(outputBuffer_linearinverse, 1, *lut);
+ for(int i=0; i <4; ++i)
+ {
+ OIIO_CHECK_CLOSE(inputBuffer_linearinverse[i], outputBuffer_linearinverse[i], 1e-5f);
+ }
+
+ float inputBuffer_nearestinverse[4] = { 0.5f, 0.6f, 0.7f, 0.5f };
+ float outputBuffer_nearestinverse[4] = { 0.25f, 0.36f, 0.49f, 0.5f };
+ OCIO::Lut1D_NearestInverse(outputBuffer_nearestinverse, 1, *lut);
+ for(int i=0; i <4; ++i)
+ {
+ OIIO_CHECK_CLOSE(inputBuffer_nearestinverse[i], outputBuffer_nearestinverse[i], 1e-2f);
+ }
+}
+
+
+OIIO_ADD_TEST(Lut1DOp, Inverse)
+{
+ // Make a lut that squares the input
+ OCIO::Lut1DRcPtr lut_a = OCIO::Lut1D::Create();
+ {
+ lut_a->from_min[0] = 0.0f;
+ lut_a->from_min[1] = 0.0f;
+ lut_a->from_min[2] = 0.0f;
+ lut_a->from_max[0] = 1.0f;
+ lut_a->from_max[1] = 1.0f;
+ lut_a->from_max[2] = 1.0f;
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ float x2 = x*x;
+
+ for(int c=0; c<3; ++c)
+ {
+ lut_a->luts[c].push_back(x2);
+ }
+ }
+ lut_a->maxerror = 1e-5f;
+ lut_a->errortype = OCIO::ERROR_RELATIVE;
+ }
+
+ // Make another lut
+ OCIO::Lut1DRcPtr lut_b = OCIO::Lut1D::Create();
+ {
+ lut_b->from_min[0] = 0.5f;
+ lut_b->from_min[1] = 0.6f;
+ lut_b->from_min[2] = 0.7f;
+ lut_b->from_max[0] = 1.0f;
+ lut_b->from_max[1] = 1.0f;
+ lut_b->from_max[2] = 1.0f;
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ float x2 = x*x;
+
+ for(int c=0; c<3; ++c)
+ {
+ lut_b->luts[c].push_back(x2);
+ }
+ }
+ lut_b->maxerror = 1e-5f;
+ lut_b->errortype = OCIO::ERROR_RELATIVE;
+ }
+
+ OCIO::OpRcPtrVec ops;
+ CreateLut1DOp(ops, lut_a, OCIO::INTERP_NEAREST, OCIO::TRANSFORM_DIR_FORWARD);
+ CreateLut1DOp(ops, lut_a, OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_INVERSE);
+ CreateLut1DOp(ops, lut_b, OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ CreateLut1DOp(ops, lut_b, OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_INVERSE);
+
+ OIIO_CHECK_EQUAL(ops.size(), 4);
+
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[1]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[2]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[3]->clone()));
+
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[1]), true);
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[3]), false);
+ OIIO_CHECK_EQUAL( ops[2]->isInverse(ops[3]), true);
+}
+
+
+#ifdef USE_SSE
+OIIO_ADD_TEST(Lut1DOp, SSE)
+{
+ // Make a lut that squares the input
+ OCIO::Lut1DRcPtr lut = OCIO::Lut1D::Create();
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ float x2 = x*x;
+
+ for(int c=0; c<3; ++c)
+ {
+ lut->luts[c].push_back(x2);
+ }
+ }
+
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_RELATIVE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), false);
+
+ int NUM_TEST_PIXELS = 1024;
+ std::vector<float> testValues(NUM_TEST_PIXELS*4);
+ std::vector<float> outputBuffer_cpu(NUM_TEST_PIXELS*4);
+ std::vector<float> outputBuffer_sse(NUM_TEST_PIXELS*4);
+
+ float val = -1.0f;
+ float delta = 0.00123456789f;
+
+ for(int i=0; i<NUM_TEST_PIXELS*4; ++i)
+ {
+ testValues[i] = val;
+ val += delta;
+ }
+
+ memcpy(&outputBuffer_cpu[0], &testValues[0], testValues.size()*sizeof(float));
+ memcpy(&outputBuffer_sse[0], &testValues[0], testValues.size()*sizeof(float));
+
+ OCIO::Lut1D_Nearest(&outputBuffer_cpu[0], NUM_TEST_PIXELS, *lut);
+ OCIO::Lut1D_Nearest_SSE(&outputBuffer_sse[0], NUM_TEST_PIXELS, *lut);
+
+ for(int i=0; i<NUM_TEST_PIXELS*4; ++i)
+ {
+ OIIO_CHECK_CLOSE(outputBuffer_cpu[i], outputBuffer_sse[i], 1e-7f);
+ //OIIO_CHECK_EQUAL(outputBuffer_cpu[i], outputBuffer_sse[i]);
+ }
+
+
+ // Test special values
+ /*
+ NUM_TEST_PIXELS = 2;
+ testValues.resize(NUM_TEST_PIXELS*4);
+ outputBuffer_cpu.resize(NUM_TEST_PIXELS*4);
+ outputBuffer_sse.resize(NUM_TEST_PIXELS*4);
+
+ testValues[0] = std::numeric_limits<float>::signaling_NaN();
+ testValues[1] = std::numeric_limits<float>::quiet_NaN();
+ testValues[2] = -std::numeric_limits<float>::signaling_NaN();
+ testValues[3] = -std::numeric_limits<float>::signaling_NaN();
+
+ testValues[4] = std::numeric_limits<float>::infinity();
+ testValues[5] = -std::numeric_limits<float>::infinity();
+ testValues[6] = 0.0f;
+
+
+ memcpy(&outputBuffer_cpu[0], &testValues[0], testValues.size()*sizeof(float));
+ memcpy(&outputBuffer_sse[0], &testValues[0], testValues.size()*sizeof(float));
+
+ OCIO::Lut1D_Nearest(&outputBuffer_cpu[0], NUM_TEST_PIXELS, lut);
+ OCIO::Lut1D_Nearest_SSE(&outputBuffer_sse[0], NUM_TEST_PIXELS, lut);
+
+ for(int i=0; i<NUM_TEST_PIXELS*4; ++i)
+ {
+ //OIIO_CHECK_CLOSE(outputBuffer_cpu[i], outputBuffer_sse[i], 1e-7f);
+ OIIO_CHECK_EQUAL(outputBuffer_cpu[i], outputBuffer_sse[i]);
+ }
+
+ */
+}
+#endif
+
+
+OIIO_ADD_TEST(Lut1DOp, NanInf)
+{
+ // Make a lut that squares the input
+ OCIO::Lut1DRcPtr lut = OCIO::Lut1D::Create();
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ float x2 = x*x;
+
+ for(int c=0; c<3; ++c)
+ {
+ lut->luts[c].push_back(x2);
+ }
+ }
+
+ lut->maxerror = 1e-5f;
+ lut->errortype = OCIO::ERROR_RELATIVE;
+ OIIO_CHECK_EQUAL(lut->isNoOp(), false);
+
+ const float reference[4] = { std::numeric_limits<float>::signaling_NaN(),
+ std::numeric_limits<float>::quiet_NaN(),
+ std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity() };
+ /*
+ float output[4] = { std::numeric_limits<float>::signaling_NaN(),
+ std::numeric_limits<float>::quiet_NaN(),
+ 1.0f,
+ -std::numeric_limits<float>::infinity() };
+ */
+ float color[4];
+
+ memcpy(color, reference, 4*sizeof(float));
+ OCIO::Lut1D_Linear(color, 1, *lut);
+ /*
+ for(int i=0; i<4; ++i)
+ {
+ if(isnan(color[i]))
+ {
+ std::cerr << color[i] << " " << output[i] << std::endl;
+ OIIO_CHECK_EQUAL(isnan(color[i]), isnan(output[i]));
+ }
+ else
+ {
+ OIIO_CHECK_EQUAL(color[i], output[i]);
+ }
+ }
+ */
+ memcpy(color, reference, 4*sizeof(float));
+ OCIO::Lut1D_Nearest(color, 1, *lut);
+ /*
+ for(int i=0; i <4; ++i)
+ {
+ if(isnan(color[i]))
+ {
+ OIIO_CHECK_EQUAL(isnan(color[i]), isnan(output[i]));
+ }
+ else
+ {
+ OIIO_CHECK_EQUAL(color[i], output[i]);
+ }
+ }
+ */
+ memcpy(color, reference, 4*sizeof(float));
+ OCIO::Lut1D_LinearInverse(color, 1, *lut);
+ /*
+ for(int i=0; i <4; ++i)
+ {
+ if(isnan(color[i]))
+ {
+ OIIO_CHECK_EQUAL(isnan(color[i]), isnan(output[i]));
+ }
+ else
+ {
+ OIIO_CHECK_EQUAL(color[i], output[i]);
+ }
+ }
+ */
+ memcpy(color, reference, 4*sizeof(float));
+ OCIO::Lut1D_NearestInverse(color, 1, *lut);
+ /*
+ for(int i=0; i <4; ++i)
+ {
+ if(isnan(color[i]))
+ {
+ OIIO_CHECK_EQUAL(isnan(color[i]), isnan(output[i]));
+ }
+ else
+ {
+ OIIO_CHECK_EQUAL(color[i], output[i]);
+ }
+ }
+ */
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/Lut1DOp.h b/src/core/Lut1DOp.h
new file mode 100644
index 0000000..d4d96c1
--- /dev/null
+++ b/src/core/Lut1DOp.h
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_LUT1DOP_H
+#define INCLUDED_OCIO_LUT1DOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Mutex.h"
+#include "Op.h"
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: turn into a class instead of a struct?
+
+ enum ErrorType
+ {
+ ERROR_ABSOLUTE = 1,
+ ERROR_RELATIVE
+ };
+
+
+ struct Lut1D;
+ typedef OCIO_SHARED_PTR<Lut1D> Lut1DRcPtr;
+
+ struct Lut1D
+ {
+ static Lut1DRcPtr Create();
+
+ // This will compute the cacheid, and also
+ // determine if the lut is a no-op.
+ // If this lut is being read in from float ASCII text
+ // a value of 1e-5 is preferable.
+ // If this lut is being read in from integer ASCII
+ // representation, the value will depend on the LSB
+ // at the specified integer precision.
+ // Example: reading 10-bit ints? Use 2/1023.0
+ // If you dont want to do the noop computation,
+ // specify a 0.0 tolerance.
+ //
+ // TODO: Instead of having each user compute the error
+ // individually, maybe they should specify the original file bitdepth?
+ // (with appropriate precision tokens?)
+ float maxerror;
+ ErrorType errortype;
+
+ float from_min[3];
+ float from_max[3];
+
+ typedef std::vector<float> fv_t;
+ fv_t luts[3];
+
+ std::string getCacheID() const;
+ bool isNoOp() const;
+
+ void unfinalize();
+ private:
+ Lut1D();
+
+ mutable std::string m_cacheID;
+ mutable bool m_isNoOp;
+ mutable Mutex m_mutex;
+
+ void finalize() const;
+ };
+
+ typedef OCIO_SHARED_PTR<Lut1D> Lut1DRcPtr;
+
+ // This generates an identity 1d lut, from 0.0 to 1.0
+ void GenerateIdentityLut1D(float* img, int numElements, int numChannels);
+
+ void CreateLut1DOp(OpRcPtrVec & ops,
+ const Lut1DRcPtr & lut,
+ Interpolation interpolation,
+ TransformDirection direction);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/Lut3DOp.cpp b/src/core/Lut3DOp.cpp
new file mode 100644
index 0000000..d64d451
--- /dev/null
+++ b/src/core/Lut3DOp.cpp
@@ -0,0 +1,982 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "HashUtils.h"
+#include "Lut3DOp.h"
+#include "MathUtils.h"
+
+#include <cmath>
+#include <limits>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ Lut3D::Lut3D()
+ {
+ for(int i=0; i<3; ++i)
+ {
+ from_min[i] = 0.0f;
+ from_max[i] = 1.0f;
+ size[i] = 0;
+ }
+ }
+
+ Lut3DRcPtr Lut3D::Create()
+ {
+ return Lut3DRcPtr(new Lut3D());
+ }
+
+ std::string Lut3D::getCacheID() const
+ {
+ AutoMutex lock(m_cacheidMutex);
+
+ if(lut.empty())
+ throw Exception("Cannot compute cacheID of invalid Lut3D");
+
+ if(!m_cacheID.empty())
+ return m_cacheID;
+
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ md5_init(&state);
+
+ md5_append(&state, (const md5_byte_t *)from_min, 3*sizeof(float));
+ md5_append(&state, (const md5_byte_t *)from_max, 3*sizeof(float));
+ md5_append(&state, (const md5_byte_t *)size, 3*sizeof(int));
+ md5_append(&state, (const md5_byte_t *)&lut[0], (int) (lut.size()*sizeof(float)));
+
+ md5_finish(&state, digest);
+
+ m_cacheID = GetPrintableHash(digest);
+
+ return m_cacheID;
+ }
+
+
+ namespace
+ {
+ // Linear
+ inline float lerp(float a, float b, float z)
+ { return (b - a) * z + a; }
+
+ inline void lerp_rgb(float* out, float* a, float* b, float* z)
+ {
+ out[0] = (b[0] - a[0]) * z[0] + a[0];
+ out[1] = (b[1] - a[1]) * z[1] + a[1];
+ out[2] = (b[2] - a[2]) * z[2] + a[2];
+ }
+
+ // Bilinear
+ inline float lerp(float a, float b, float c, float d, float y, float z)
+ { return lerp(lerp(a, b, z), lerp(c, d, z), y); }
+
+ inline void lerp_rgb(float* out, float* a, float* b, float* c,
+ float* d, float* y, float* z)
+ {
+ float v1[3];
+ float v2[3];
+
+ lerp_rgb(v1, a, b, z);
+ lerp_rgb(v2, c, d, z);
+ lerp_rgb(out, v1, v2, y);
+ }
+
+ // Trilinear
+ inline float lerp(float a, float b, float c, float d,
+ float e, float f, float g, float h,
+ float x, float y, float z)
+ { return lerp(lerp(a,b,c,d,y,z), lerp(e,f,g,h,y,z), x); }
+
+ inline void lerp_rgb(float* out, float* a, float* b, float* c, float* d,
+ float* e, float* f, float* g, float* h,
+ float* x, float* y, float* z)
+ {
+ float v1[3];
+ float v2[3];
+
+ lerp_rgb(v1, a,b,c,d,y,z);
+ lerp_rgb(v2, e,f,g,h,y,z);
+ lerp_rgb(out, v1, v2, x);
+ }
+
+ inline float lookupNearest_3D(int rIndex, int gIndex, int bIndex,
+ int size_red, int size_green, int size_blue,
+ const float* simple_rgb_lut, int channelIndex)
+ {
+ return simple_rgb_lut[ GetLut3DIndex_B(rIndex, gIndex, bIndex,
+ size_red, size_green, size_blue) + channelIndex];
+ }
+
+ inline void lookupNearest_3D_rgb(float* rgb,
+ int rIndex, int gIndex, int bIndex,
+ int size_red, int size_green, int size_blue,
+ const float* simple_rgb_lut)
+ {
+ int offset = GetLut3DIndex_B(rIndex, gIndex, bIndex, size_red, size_green, size_blue);
+ rgb[0] = simple_rgb_lut[offset];
+ rgb[1] = simple_rgb_lut[offset+1];
+ rgb[2] = simple_rgb_lut[offset+2];
+ }
+
+ // Note: This function assumes that minVal is less than maxVal
+ inline int clamp(float k, float minVal, float maxVal)
+ {
+ return static_cast<int>(roundf(std::max(std::min(k, maxVal), minVal)));
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Nearest Forward
+
+ void Lut3D_Nearest(float* rgbaBuffer, long numPixels, const Lut3D & lut)
+ {
+ float maxIndex[3];
+ float mInv[3];
+ float b[3];
+ float mInv_x_maxIndex[3];
+ int lutSize[3];
+ const float* startPos = &(lut.lut[0]);
+
+ for(int i=0; i<3; ++i)
+ {
+ maxIndex[i] = (float) (lut.size[i] - 1);
+ mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+ mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);
+
+ lutSize[i] = lut.size[i];
+ }
+
+ int localIndex[3];
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ if(isnan(rgbaBuffer[0]) || isnan(rgbaBuffer[1]) || isnan(rgbaBuffer[2]))
+ {
+ rgbaBuffer[0] = std::numeric_limits<float>::quiet_NaN();
+ rgbaBuffer[1] = std::numeric_limits<float>::quiet_NaN();
+ rgbaBuffer[2] = std::numeric_limits<float>::quiet_NaN();
+ }
+ else
+ {
+ localIndex[0] = clamp(mInv_x_maxIndex[0] * (rgbaBuffer[0] - b[0]), 0.0f, maxIndex[0]);
+ localIndex[1] = clamp(mInv_x_maxIndex[1] * (rgbaBuffer[1] - b[1]), 0.0f, maxIndex[1]);
+ localIndex[2] = clamp(mInv_x_maxIndex[2] * (rgbaBuffer[2] - b[2]), 0.0f, maxIndex[2]);
+
+ lookupNearest_3D_rgb(rgbaBuffer, localIndex[0], localIndex[1], localIndex[2],
+ lutSize[0], lutSize[1], lutSize[2], startPos);
+ }
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Linear Forward
+
+ void Lut3D_Linear(float* rgbaBuffer, long numPixels, const Lut3D & lut)
+ {
+ float maxIndex[3];
+ float mInv[3];
+ float b[3];
+ float mInv_x_maxIndex[3];
+ int lutSize[3];
+ const float* startPos = &(lut.lut[0]);
+
+ for(int i=0; i<3; ++i)
+ {
+ maxIndex[i] = (float) (lut.size[i] - 1);
+ mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+ mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);
+
+ lutSize[i] = lut.size[i];
+ }
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+
+ if(isnan(rgbaBuffer[0]) || isnan(rgbaBuffer[1]) || isnan(rgbaBuffer[2]))
+ {
+ rgbaBuffer[0] = std::numeric_limits<float>::quiet_NaN();
+ rgbaBuffer[1] = std::numeric_limits<float>::quiet_NaN();
+ rgbaBuffer[2] = std::numeric_limits<float>::quiet_NaN();
+ }
+ else
+ {
+ float localIndex[3];
+ int indexLow[3];
+ int indexHigh[3];
+ float delta[3];
+ float a[3];
+ float b_[3];
+ float c[3];
+ float d[3];
+ float e[3];
+ float f[3];
+ float g[3];
+ float h[4];
+ float x[4];
+ float y[4];
+ float z[4];
+
+ localIndex[0] = std::max(std::min(mInv_x_maxIndex[0] * (rgbaBuffer[0] - b[0]), maxIndex[0]), 0.0f);
+ localIndex[1] = std::max(std::min(mInv_x_maxIndex[1] * (rgbaBuffer[1] - b[1]), maxIndex[1]), 0.0f);
+ localIndex[2] = std::max(std::min(mInv_x_maxIndex[2] * (rgbaBuffer[2] - b[2]), maxIndex[2]), 0.0f);
+
+ indexLow[0] = static_cast<int>(std::floor(localIndex[0]));
+ indexLow[1] = static_cast<int>(std::floor(localIndex[1]));
+ indexLow[2] = static_cast<int>(std::floor(localIndex[2]));
+
+ indexHigh[0] = static_cast<int>(std::ceil(localIndex[0]));
+ indexHigh[1] = static_cast<int>(std::ceil(localIndex[1]));
+ indexHigh[2] = static_cast<int>(std::ceil(localIndex[2]));
+
+ delta[0] = localIndex[0] - static_cast<float>(indexLow[0]);
+ delta[1] = localIndex[1] - static_cast<float>(indexLow[1]);
+ delta[2] = localIndex[2] - static_cast<float>(indexLow[2]);
+
+ // Lookup 8 corners of cube
+ lookupNearest_3D_rgb(a, indexLow[0], indexLow[1], indexLow[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(b_, indexLow[0], indexLow[1], indexHigh[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(c, indexLow[0], indexHigh[1], indexLow[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(d, indexLow[0], indexHigh[1], indexHigh[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(e, indexHigh[0], indexLow[1], indexLow[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(f, indexHigh[0], indexLow[1], indexHigh[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(g, indexHigh[0], indexHigh[1], indexLow[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+ lookupNearest_3D_rgb(h, indexHigh[0], indexHigh[1], indexHigh[2], lutSize[0], lutSize[1], lutSize[2], startPos);
+
+ // Also store the 3d interpolation coordinates
+ x[0] = delta[0]; x[1] = delta[0]; x[2] = delta[0];
+ y[0] = delta[1]; y[1] = delta[1]; y[2] = delta[1];
+ z[0] = delta[2]; z[1] = delta[2]; z[2] = delta[2];
+
+ // Do a trilinear interpolation of the 8 corners
+ // 4726.8 scanlines/sec
+
+ lerp_rgb(rgbaBuffer, a, b_, c, d, e, f, g, h,
+ x, y, z);
+ }
+
+ rgbaBuffer += 4;
+ }
+ }
+ }
+
+
+ void Lut3D_Tetrahedral(float* rgbaBuffer, long numPixels, const Lut3D & lut)
+ {
+ // Tetrahedral interoplation, as described by:
+ // http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf
+ // http://blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/
+ // http://www.hpl.hp.com/techreports/98/HPL-98-95.html
+
+ float maxIndex[3];
+ float mInv[3];
+ float b[3];
+ float mInv_x_maxIndex[3];
+ int lutSize[3];
+ const float* startPos = &(lut.lut[0]);
+
+ for(int i=0; i<3; ++i)
+ {
+ maxIndex[i] = (float) (lut.size[i] - 1);
+ mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
+ b[i] = lut.from_min[i];
+ mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);
+
+ lutSize[i] = lut.size[i];
+ }
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+
+ if(isnan(rgbaBuffer[0]) || isnan(rgbaBuffer[1]) || isnan(rgbaBuffer[2]))
+ {
+ rgbaBuffer[0] = std::numeric_limits<float>::quiet_NaN();
+ rgbaBuffer[1] = std::numeric_limits<float>::quiet_NaN();
+ rgbaBuffer[2] = std::numeric_limits<float>::quiet_NaN();
+ }
+ else
+ {
+ float localIndex[3];
+ int indexLow[3];
+ int indexHigh[3];
+ float delta[3];
+
+ // Same index/delta calculation as linear interpolation
+ localIndex[0] = std::max(std::min(mInv_x_maxIndex[0] * (rgbaBuffer[0] - b[0]), maxIndex[0]), 0.0f);
+ localIndex[1] = std::max(std::min(mInv_x_maxIndex[1] * (rgbaBuffer[1] - b[1]), maxIndex[1]), 0.0f);
+ localIndex[2] = std::max(std::min(mInv_x_maxIndex[2] * (rgbaBuffer[2] - b[2]), maxIndex[2]), 0.0f);
+
+ indexLow[0] = static_cast<int>(std::floor(localIndex[0]));
+ indexLow[1] = static_cast<int>(std::floor(localIndex[1]));
+ indexLow[2] = static_cast<int>(std::floor(localIndex[2]));
+
+ indexHigh[0] = static_cast<int>(std::ceil(localIndex[0]));
+ indexHigh[1] = static_cast<int>(std::ceil(localIndex[1]));
+ indexHigh[2] = static_cast<int>(std::ceil(localIndex[2]));
+
+ delta[0] = localIndex[0] - static_cast<float>(indexLow[0]);
+ delta[1] = localIndex[1] - static_cast<float>(indexLow[1]);
+ delta[2] = localIndex[2] - static_cast<float>(indexLow[2]);
+
+ // Rebind for consistency with Truelight paper
+ float fx = delta[0];
+ float fy = delta[1];
+ float fz = delta[2];
+
+ // Compute index into LUT for surrounding corners
+ const int n000 = GetLut3DIndex_B(indexLow[0], indexLow[1], indexLow[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n100 = GetLut3DIndex_B(indexHigh[0], indexLow[1], indexLow[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n010 = GetLut3DIndex_B(indexLow[0], indexHigh[1], indexLow[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n001 = GetLut3DIndex_B(indexLow[0], indexLow[1], indexHigh[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n110 = GetLut3DIndex_B(indexHigh[0], indexHigh[1], indexLow[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n101 = GetLut3DIndex_B(indexHigh[0], indexLow[1], indexHigh[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n011 = GetLut3DIndex_B(indexLow[0], indexHigh[1], indexHigh[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+ const int n111 = GetLut3DIndex_B(indexHigh[0], indexHigh[1], indexHigh[2],
+ lutSize[0], lutSize[1], lutSize[2]);
+
+ if (fx > fy) {
+ if (fy > fz) {
+ rgbaBuffer[0] =
+ (1-fx) * startPos[n000] +
+ (fx-fy) * startPos[n100] +
+ (fy-fz) * startPos[n110] +
+ (fz) * startPos[n111];
+
+ rgbaBuffer[1] =
+ (1-fx) * startPos[n000+1] +
+ (fx-fy) * startPos[n100+1] +
+ (fy-fz) * startPos[n110+1] +
+ (fz) * startPos[n111+1];
+
+ rgbaBuffer[2] =
+ (1-fx) * startPos[n000+2] +
+ (fx-fy) * startPos[n100+2] +
+ (fy-fz) * startPos[n110+2] +
+ (fz) * startPos[n111+2];
+ }
+ else if (fx > fz)
+ {
+ rgbaBuffer[0] =
+ (1-fx) * startPos[n000] +
+ (fx-fz) * startPos[n100] +
+ (fz-fy) * startPos[n101] +
+ (fy) * startPos[n111];
+
+ rgbaBuffer[1] =
+ (1-fx) * startPos[n000+1] +
+ (fx-fz) * startPos[n100+1] +
+ (fz-fy) * startPos[n101+1] +
+ (fy) * startPos[n111+1];
+
+ rgbaBuffer[2] =
+ (1-fx) * startPos[n000+2] +
+ (fx-fz) * startPos[n100+2] +
+ (fz-fy) * startPos[n101+2] +
+ (fy) * startPos[n111+2];
+ }
+ else
+ {
+ rgbaBuffer[0] =
+ (1-fz) * startPos[n000] +
+ (fz-fx) * startPos[n001] +
+ (fx-fy) * startPos[n101] +
+ (fy) * startPos[n111];
+
+ rgbaBuffer[1] =
+ (1-fz) * startPos[n000+1] +
+ (fz-fx) * startPos[n001+1] +
+ (fx-fy) * startPos[n101+1] +
+ (fy) * startPos[n111+1];
+
+ rgbaBuffer[2] =
+ (1-fz) * startPos[n000+2] +
+ (fz-fx) * startPos[n001+2] +
+ (fx-fy) * startPos[n101+2] +
+ (fy) * startPos[n111+2];
+ }
+ }
+ else
+ {
+ if (fz > fy)
+ {
+ rgbaBuffer[0] =
+ (1-fz) * startPos[n000] +
+ (fz-fy) * startPos[n001] +
+ (fy-fx) * startPos[n011] +
+ (fx) * startPos[n111];
+
+ rgbaBuffer[1] =
+ (1-fz) * startPos[n000+1] +
+ (fz-fy) * startPos[n001+1] +
+ (fy-fx) * startPos[n011+1] +
+ (fx) * startPos[n111+1];
+
+ rgbaBuffer[2] =
+ (1-fz) * startPos[n000+2] +
+ (fz-fy) * startPos[n001+2] +
+ (fy-fx) * startPos[n011+2] +
+ (fx) * startPos[n111+2];
+ }
+ else if (fz > fx)
+ {
+ rgbaBuffer[0] =
+ (1-fy) * startPos[n000] +
+ (fy-fz) * startPos[n010] +
+ (fz-fx) * startPos[n011] +
+ (fx) * startPos[n111];
+
+ rgbaBuffer[1] =
+ (1-fy) * startPos[n000+1] +
+ (fy-fz) * startPos[n010+1] +
+ (fz-fx) * startPos[n011+1] +
+ (fx) * startPos[n111+1];
+
+ rgbaBuffer[2] =
+ (1-fy) * startPos[n000+2] +
+ (fy-fz) * startPos[n010+2] +
+ (fz-fx) * startPos[n011+2] +
+ (fx) * startPos[n111+2];
+ }
+ else
+ {
+ rgbaBuffer[0] =
+ (1-fy) * startPos[n000] +
+ (fy-fx) * startPos[n010] +
+ (fx-fz) * startPos[n110] +
+ (fz) * startPos[n111];
+
+ rgbaBuffer[1] =
+ (1-fy) * startPos[n000+1] +
+ (fy-fx) * startPos[n010+1] +
+ (fx-fz) * startPos[n110+1] +
+ (fz) * startPos[n111+1];
+
+ rgbaBuffer[2] =
+ (1-fy) * startPos[n000+2] +
+ (fy-fx) * startPos[n010+2] +
+ (fx-fz) * startPos[n110+2] +
+ (fz) * startPos[n111+2];
+ }
+ }
+ } // !isnan
+
+ rgbaBuffer += 4;
+ }
+ }
+
+
+ void GenerateIdentityLut3D(float* img, int edgeLen, int numChannels, Lut3DOrder lut3DOrder)
+ {
+ if(!img) return;
+ if(numChannels < 3)
+ {
+ throw Exception("Cannot generate idenitity 3d lut with less than 3 channels.");
+ }
+
+ float c = 1.0f / ((float)edgeLen - 1.0f);
+
+ if(lut3DOrder == LUT3DORDER_FAST_RED)
+ {
+ for(int i=0; i<edgeLen*edgeLen*edgeLen; i++)
+ {
+ img[numChannels*i+0] = (float)(i%edgeLen) * c;
+ img[numChannels*i+1] = (float)((i/edgeLen)%edgeLen) * c;
+ img[numChannels*i+2] = (float)((i/edgeLen/edgeLen)%edgeLen) * c;
+ }
+ }
+ else if(lut3DOrder == LUT3DORDER_FAST_BLUE)
+ {
+ for(int i=0; i<edgeLen*edgeLen*edgeLen; i++)
+ {
+ img[numChannels*i+0] = (float)((i/edgeLen/edgeLen)%edgeLen) * c;
+ img[numChannels*i+1] = (float)((i/edgeLen)%edgeLen) * c;
+ img[numChannels*i+2] = (float)(i%edgeLen) * c;
+ }
+ }
+ else
+ {
+ throw Exception("Unknown Lut3DOrder.");
+ }
+ }
+
+
+ int Get3DLutEdgeLenFromNumPixels(int numPixels)
+ {
+ int dim = static_cast<int>(roundf(powf((float) numPixels, 1.0f/3.0f)));
+
+ if(dim*dim*dim != numPixels)
+ {
+ std::ostringstream os;
+ os << "Cannot infer 3D Lut size. ";
+ os << numPixels << " element(s) does not correspond to a ";
+ os << "unform cube edge length. (nearest edge length is ";
+ os << dim << ").";
+ throw Exception(os.str().c_str());
+ }
+
+ return dim;
+ }
+
+ namespace
+ {
+ class Lut3DOp : public Op
+ {
+ public:
+ Lut3DOp(Lut3DRcPtr lut,
+ Interpolation interpolation,
+ TransformDirection direction);
+ virtual ~Lut3DOp();
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const;
+ virtual std::string getCacheID() const;
+
+ virtual bool isNoOp() const;
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const;
+ virtual void finalize();
+ virtual void apply(float* rgbaBuffer, long numPixels) const;
+
+ virtual bool supportsGpuShader() const;
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const;
+
+ private:
+ Lut3DRcPtr m_lut;
+ Interpolation m_interpolation;
+ TransformDirection m_direction;
+
+ // Set in finalize
+ std::string m_cacheID;
+ };
+
+ typedef OCIO_SHARED_PTR<Lut3DOp> Lut3DOpRcPtr;
+
+
+ Lut3DOp::Lut3DOp(Lut3DRcPtr lut,
+ Interpolation interpolation,
+ TransformDirection direction):
+ Op(),
+ m_lut(lut),
+ m_interpolation(interpolation),
+ m_direction(direction)
+ {
+ }
+
+ OpRcPtr Lut3DOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new Lut3DOp(m_lut, m_interpolation, m_direction));
+ return op;
+ }
+
+ Lut3DOp::~Lut3DOp()
+ { }
+
+ std::string Lut3DOp::getInfo() const
+ {
+ return "<Lut3DOp>";
+ }
+
+ std::string Lut3DOp::getCacheID() const
+ {
+ return m_cacheID;
+ }
+
+ // TODO: compute real value for isNoOp
+ bool Lut3DOp::isNoOp() const
+ {
+ return false;
+ }
+
+ bool Lut3DOp::isSameType(const OpRcPtr & op) const
+ {
+ Lut3DOpRcPtr typedRcPtr = DynamicPtrCast<Lut3DOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool Lut3DOp::isInverse(const OpRcPtr & op) const
+ {
+ Lut3DOpRcPtr typedRcPtr = DynamicPtrCast<Lut3DOp>(op);
+ if(!typedRcPtr) return false;
+
+ if(GetInverseTransformDirection(m_direction) != typedRcPtr->m_direction)
+ return false;
+
+ return (m_lut->getCacheID() == typedRcPtr->m_lut->getCacheID());
+ }
+
+ // TODO: compute real value for hasChannelCrosstalk
+ bool Lut3DOp::hasChannelCrosstalk() const
+ {
+ return true;
+ }
+
+ void Lut3DOp::finalize()
+ {
+ if(m_direction != TRANSFORM_DIR_FORWARD)
+ {
+ std::ostringstream os;
+ os << "3D Luts can only be applied in the forward direction. ";
+ os << "(" << TransformDirectionToString(m_direction) << ")";
+ os << " specified.";
+ throw Exception(os.str().c_str());
+ }
+
+ // Validate the requested interpolation type
+ switch(m_interpolation)
+ {
+ // These are the allowed values.
+ case INTERP_NEAREST:
+ case INTERP_LINEAR:
+ case INTERP_TETRAHEDRAL:
+ break;
+ case INTERP_BEST:
+ m_interpolation = INTERP_LINEAR;
+ break;
+ case INTERP_UNKNOWN:
+ throw Exception("Cannot apply Lut3DOp, unspecified interpolation.");
+ break;
+ default:
+ throw Exception("Cannot apply Lut3DOp, invalid interpolation specified.");
+ }
+
+ for(int i=0; i<3; ++i)
+ {
+ if(m_lut->size[i] == 0)
+ {
+ throw Exception("Cannot apply Lut3DOp, lut object is empty.");
+ }
+ // TODO if from_min[i] == from_max[i]
+ }
+
+ if(m_lut->size[0]*m_lut->size[1]*m_lut->size[2] * 3 != (int)m_lut->lut.size())
+ {
+ throw Exception("Cannot apply Lut3DOp, specified size does not match data.");
+ }
+
+ // Create the cacheID
+ std::ostringstream cacheIDStream;
+ cacheIDStream << "<Lut3DOp ";
+ cacheIDStream << m_lut->getCacheID() << " ";
+ cacheIDStream << InterpolationToString(m_interpolation) << " ";
+ cacheIDStream << TransformDirectionToString(m_direction) << " ";
+ cacheIDStream << ">";
+ m_cacheID = cacheIDStream.str();
+ }
+
+ void Lut3DOp::apply(float* rgbaBuffer, long numPixels) const
+ {
+ if(m_interpolation == INTERP_NEAREST)
+ {
+ Lut3D_Nearest(rgbaBuffer, numPixels, *m_lut);
+ }
+ else if(m_interpolation == INTERP_LINEAR)
+ {
+ Lut3D_Linear(rgbaBuffer, numPixels, *m_lut);
+ }
+ else if(m_interpolation == INTERP_TETRAHEDRAL)
+ {
+ Lut3D_Tetrahedral(rgbaBuffer, numPixels, *m_lut);
+ }
+ }
+
+ bool Lut3DOp::supportsGpuShader() const
+ {
+ return false;
+ }
+
+ void Lut3DOp::writeGpuShader(std::ostream & /*shader*/,
+ const std::string & /*pixelName*/,
+ const GpuShaderDesc & /*shaderDesc*/) const
+ {
+ throw Exception("Lut3DOp does not support analytical shader generation.");
+ }
+ }
+
+ void CreateLut3DOp(OpRcPtrVec & ops,
+ Lut3DRcPtr lut,
+ Interpolation interpolation,
+ TransformDirection direction)
+ {
+ ops.push_back( Lut3DOpRcPtr(new Lut3DOp(lut, interpolation, direction)) );
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+#include <cstring>
+#include <cstdlib>
+#include <sys/time.h>
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(Lut3DOp, NanInfValueCheck)
+{
+ OCIO::Lut3DRcPtr lut = OCIO::Lut3D::Create();
+
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+
+ lut->size[0] = 3;
+ lut->size[1] = 3;
+ lut->size[2] = 3;
+
+ lut->lut.resize(lut->size[0]*lut->size[1]*lut->size[2]*3);
+
+ GenerateIdentityLut3D(&lut->lut[0], lut->size[0], 3, OCIO::LUT3DORDER_FAST_RED);
+ for(unsigned int i=0; i<lut->lut.size(); ++i)
+ {
+ lut->lut[i] = powf(lut->lut[i], 2.0f);
+ }
+
+ const float reference[4] = { std::numeric_limits<float>::signaling_NaN(),
+ std::numeric_limits<float>::quiet_NaN(),
+ std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity() };
+ float color[4];
+
+ memcpy(color, reference, 4*sizeof(float));
+ OCIO::Lut3D_Nearest(color, 1, *lut);
+
+ memcpy(color, reference, 4*sizeof(float));
+ OCIO::Lut3D_Linear(color, 1, *lut);
+}
+
+
+OIIO_ADD_TEST(Lut3DOp, ValueCheck)
+{
+ OCIO::Lut3DRcPtr lut = OCIO::Lut3D::Create();
+
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+
+ lut->size[0] = 32;
+ lut->size[1] = 32;
+ lut->size[2] = 32;
+
+ lut->lut.resize(lut->size[0]*lut->size[1]*lut->size[2]*3);
+ GenerateIdentityLut3D(&lut->lut[0], lut->size[0], 3, OCIO::LUT3DORDER_FAST_RED);
+ for(unsigned int i=0; i<lut->lut.size(); ++i)
+ {
+ lut->lut[i] = powf(lut->lut[i], 2.0f);
+ }
+
+ const float reference[] = { 0.0f, 0.2f, 0.3f, 1.0f,
+ 0.1234f, 0.4567f, 0.9876f, 1.0f,
+ 11.0f, -0.5f, 0.5010f, 1.0f
+ };
+ const float nearest[] = { 0.0f, 0.03746097535f, 0.0842871964f, 1.0f,
+ 0.01664932258f, 0.2039542049f, 1.0f, 1.0f,
+ 1.0f, 0.0f, 0.2663891613f, 1.0f
+ };
+ const float linear[] = { 0.0f, 0.04016649351f, 0.09021852165f, 1.0f,
+ 0.01537752338f, 0.2087130845f, 0.9756000042f, 1.0f,
+ 1.0f, 0.0f, 0.2512601018f, 1.0f
+ };
+ float color[12];
+
+ // Check nearest
+ memcpy(color, reference, 12*sizeof(float));
+ OCIO::Lut3D_Nearest(color, 3, *lut);
+ for(unsigned int i=0; i<12; ++i)
+ {
+ OIIO_CHECK_CLOSE(color[i], nearest[i], 1e-8);
+ }
+
+ // Check linear
+ memcpy(color, reference, 12*sizeof(float));
+ OCIO::Lut3D_Linear(color, 3, *lut);
+ for(unsigned int i=0; i<12; ++i)
+ {
+ OIIO_CHECK_CLOSE(color[i], linear[i], 1e-8);
+ }
+
+ // Check tetrahedral
+ memcpy(color, reference, 12*sizeof(float));
+ OCIO::Lut3D_Tetrahedral(color, 3, *lut);
+ for(unsigned int i=0; i<12; ++i)
+ {
+ OIIO_CHECK_CLOSE(color[i], linear[i], 1e-7); // Note, max delta lowered from 1e-8
+ }
+}
+
+
+
+OIIO_ADD_TEST(Lut3DOp, InverseComparisonCheck)
+{
+ OCIO::Lut3DRcPtr lut_a = OCIO::Lut3D::Create();
+ lut_a->from_min[0] = 0.0f;
+ lut_a->from_min[1] = 0.0f;
+ lut_a->from_min[2] = 0.0f;
+ lut_a->from_max[0] = 1.0f;
+ lut_a->from_max[1] = 1.0f;
+ lut_a->from_max[2] = 1.0f;
+ lut_a->size[0] = 32;
+ lut_a->size[1] = 32;
+ lut_a->size[2] = 32;
+ lut_a->lut.resize(lut_a->size[0]*lut_a->size[1]*lut_a->size[2]*3);
+ GenerateIdentityLut3D(&lut_a->lut[0], lut_a->size[0], 3, OCIO::LUT3DORDER_FAST_RED);
+
+ OCIO::Lut3DRcPtr lut_b = OCIO::Lut3D::Create();
+ lut_b->from_min[0] = 0.5f;
+ lut_b->from_min[1] = 0.5f;
+ lut_b->from_min[2] = 0.5f;
+ lut_b->from_max[0] = 1.0f;
+ lut_b->from_max[1] = 1.0f;
+ lut_b->from_max[2] = 1.0f;
+ lut_b->size[0] = 32;
+ lut_b->size[1] = 32;
+ lut_b->size[2] = 32;
+ lut_b->lut.resize(lut_b->size[0]*lut_b->size[1]*lut_b->size[2]*3);
+ GenerateIdentityLut3D(&lut_b->lut[0], lut_b->size[0], 3, OCIO::LUT3DORDER_FAST_RED);
+
+ OCIO::OpRcPtrVec ops;
+ CreateLut3DOp(ops, lut_a, OCIO::INTERP_NEAREST, OCIO::TRANSFORM_DIR_FORWARD);
+ CreateLut3DOp(ops, lut_a, OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_INVERSE);
+ CreateLut3DOp(ops, lut_b, OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_FORWARD);
+ CreateLut3DOp(ops, lut_b, OCIO::INTERP_LINEAR, OCIO::TRANSFORM_DIR_INVERSE);
+
+ OIIO_CHECK_EQUAL(ops.size(), 4);
+
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[1]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[2]));
+ OIIO_CHECK_ASSERT(ops[0]->isSameType(ops[3]->clone()));
+
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[1]), true);
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[2]), false);
+ OIIO_CHECK_EQUAL( ops[0]->isInverse(ops[3]), false);
+ OIIO_CHECK_EQUAL( ops[2]->isInverse(ops[3]), true);
+}
+
+
+OIIO_ADD_TEST(Lut3DOp, PerformanceCheck)
+{
+ /*
+ OCIO::Lut3D lut;
+
+ lut.from_min[0] = 0.0f;
+ lut.from_min[1] = 0.0f;
+ lut.from_min[2] = 0.0f;
+
+ lut.from_max[0] = 1.0f;
+ lut.from_max[1] = 1.0f;
+ lut.from_max[2] = 1.0f;
+
+ lut.size[0] = 32;
+ lut.size[1] = 32;
+ lut.size[2] = 32;
+
+ lut.lut.resize(lut.size[0]*lut.size[1]*lut.size[2]*3);
+ GenerateIdentityLut3D(&lut.lut[0], lut.size[0], 3, OCIO::LUT3DORDER_FAST_RED);
+
+ std::vector<float> img;
+ int xres = 2048;
+ int yres = 1;
+ int channels = 4;
+ img.resize(xres*yres*channels);
+
+ srand48(0);
+
+ // create random values from -0.05 to 1.05
+ // (To simulate clipping performance)
+
+ for(unsigned int i=0; i<img.size(); ++i)
+ {
+ float uniform = (float)drand48();
+ img[i] = uniform*1.1f - 0.05f;
+ }
+
+ timeval t;
+ gettimeofday(&t, 0);
+ double starttime = (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
+
+ int numloops = 1024;
+ for(int i=0; i<numloops; ++i)
+ {
+ //OCIO::Lut3D_Nearest(&img[0], xres*yres, lut);
+ OCIO::Lut3D_Linear(&img[0], xres*yres, lut);
+ }
+
+ gettimeofday(&t, 0);
+ double endtime = (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
+ double totaltime_a = (endtime-starttime)/numloops;
+
+ printf("Linear: %0.1f ms - %0.1f fps\n", totaltime_a*1000.0, 1.0/totaltime_a);
+
+
+ // Tetrahedral
+ gettimeofday(&t, 0);
+ starttime = (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
+
+ for(int i=0; i<numloops; ++i)
+ {
+ OCIO::Lut3D_Tetrahedral(&img[0], xres*yres, lut);
+ }
+
+ gettimeofday(&t, 0);
+ endtime = (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
+ double totaltime_b = (endtime-starttime)/numloops;
+
+ printf("Tetra: %0.1f ms - %0.1f fps\n", totaltime_b*1000.0, 1.0/totaltime_b);
+
+ double speed_diff = totaltime_a/totaltime_b;
+ printf("Tetra is %.04f speed of Linear\n", speed_diff);
+ */
+}
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/Lut3DOp.h b/src/core/Lut3DOp.h
new file mode 100644
index 0000000..bba532b
--- /dev/null
+++ b/src/core/Lut3DOp.h
@@ -0,0 +1,114 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_LUT3DOP_H
+#define INCLUDED_OCIO_LUT3DOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Mutex.h"
+#include "Op.h"
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: turn into a class instead of a struct?
+
+ struct Lut3D;
+ typedef OCIO_SHARED_PTR<Lut3D> Lut3DRcPtr;
+
+ struct Lut3D
+ {
+ static Lut3DRcPtr Create();
+
+ float from_min[3];
+ float from_max[3];
+ int size[3];
+
+ typedef std::vector<float> fv_t;
+ fv_t lut;
+
+ std::string getCacheID() const;
+
+ private:
+ Lut3D();
+ mutable std::string m_cacheID;
+ mutable Mutex m_cacheidMutex;
+ };
+
+ // RGB channel ordering.
+ // Pixels ordered in such a way that the blue coordinate changes fastest,
+ // then the green coordinate, and finally, the red coordinate changes slowest
+
+ inline int GetLut3DIndex_B(int indexR, int indexG, int indexB,
+ int sizeR, int sizeG, int /*sizeB*/)
+ {
+ return 3 * (indexR + sizeR * (indexG + sizeG * indexB));
+ }
+
+
+ // RGB channel ordering.
+ // Pixels ordered in such a way that the red coordinate changes fastest,
+ // then the green coordinate, and finally, the blue coordinate changes slowest
+
+ inline int GetLut3DIndex_R(int indexR, int indexG, int indexB,
+ int /*sizeR*/, int sizeG, int sizeB)
+ {
+ return 3 * (indexB + sizeB * (indexG + sizeG * indexR));
+ }
+
+ // What is the preferred order for the lut3d?
+ // I.e., are the first two entries change along
+ // the blue direction, or the red direction?
+ // OpenGL expects 'red'
+
+ enum Lut3DOrder
+ {
+ LUT3DORDER_FAST_RED = 0,
+ LUT3DORDER_FAST_BLUE
+ };
+
+ void GenerateIdentityLut3D(float* img, int edgeLen, int numChannels,
+ Lut3DOrder lut3DOrder);
+
+ // Essentially the cube root, but will throw an exception if the
+ // cuberoot is not exact.
+ int Get3DLutEdgeLenFromNumPixels(int numPixels);
+
+
+
+ void CreateLut3DOp(OpRcPtrVec & ops,
+ Lut3DRcPtr lut,
+ Interpolation interpolation,
+ TransformDirection direction);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/MathUtils.cpp b/src/core/MathUtils.cpp
new file mode 100644
index 0000000..19691d7
--- /dev/null
+++ b/src/core/MathUtils.cpp
@@ -0,0 +1,603 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <cstring>
+
+#include "MathUtils.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const float FLTMIN = std::numeric_limits<float>::min();
+ }
+
+ bool IsScalarEqualToZero(float v)
+ {
+ return equalWithAbsError(v, 0.0f, FLTMIN);
+ }
+
+ bool IsScalarEqualToOne(float v)
+ {
+ return equalWithAbsError(v, 1.0f, FLTMIN);
+ }
+
+ float GetSafeScalarInverse(float v, float defaultValue)
+ {
+ if(IsScalarEqualToZero(v)) return defaultValue;
+ return 1.0f / v;
+ }
+
+ bool IsVecEqualToZero(const float* v, int size)
+ {
+ for(int i=0; i<size; ++i)
+ {
+ if(!IsScalarEqualToZero(v[i])) return false;
+ }
+ return true;
+ }
+
+ bool IsVecEqualToOne(const float* v, int size)
+ {
+ for(int i=0; i<size; ++i)
+ {
+ if(!IsScalarEqualToOne(v[i])) return false;
+ }
+ return true;
+ }
+
+ bool VecContainsZero(const float* v, int size)
+ {
+ for(int i=0; i<size; ++i)
+ {
+ if(IsScalarEqualToZero(v[i])) return true;
+ }
+ return false;
+ }
+
+ bool VecContainsOne(const float* v, int size)
+ {
+ for(int i=0; i<size; ++i)
+ {
+ if(IsScalarEqualToOne(v[i])) return true;
+ }
+ return false;
+ }
+
+ bool VecsEqualWithRelError(const float* v1, int size1,
+ const float* v2, int size2,
+ float e)
+ {
+ if(size1 != size2) return false;
+ for(int i=0; i<size1; ++i)
+ {
+ if(!equalWithRelError(v1[i], v2[i], e)) return false;
+ }
+
+ return true;
+ }
+
+ double ClampToNormHalf(double val)
+ {
+ if(val < -GetHalfMax())
+ {
+ return -GetHalfMax();
+ }
+
+ if(val > -GetHalfNormMin() && val<GetHalfNormMin())
+ {
+ return 0.0;
+ }
+
+ if(val > GetHalfMax())
+ {
+ return GetHalfMax();
+ }
+
+ return val;
+ }
+
+ bool IsM44Identity(const float* m44)
+ {
+ int index=0;
+
+ for(unsigned int j=0; j<4; ++j)
+ {
+ for(unsigned int i=0; i<4; ++i)
+ {
+ index = 4*j+i;
+
+ if(i==j)
+ {
+ if(!IsScalarEqualToOne(m44[index])) return false;
+ }
+ else
+ {
+ if(!IsScalarEqualToZero(m44[index])) return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool IsM44Diagonal(const float* m44)
+ {
+ for(int i=0; i<16; ++i)
+ {
+ if((i%5)==0) continue; // If we're on the diagonal, skip it
+ if(!IsScalarEqualToZero(m44[i])) return false;
+ }
+
+ return true;
+ }
+
+ void GetM44Diagonal(float* out4, const float* m44)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ out4[i] = m44[i*5];
+ }
+ }
+
+ // We use an intermediate double representation to make sure
+ // there is minimal float precision error on the determinant's computation
+ // (We have seen IsScalarEqualToZero sensitivities here on 32-bit
+ // virtual machines)
+
+ bool GetM44Inverse(float* inverse_out, const float* m_)
+ {
+ double m[16];
+ for(unsigned int i=0; i<16; ++i) m[i] = (double)m_[i];
+
+ double d10_21 = m[4]*m[9] - m[5]*m[8];
+ double d10_22 = m[4]*m[10] - m[6]*m[8];
+ double d10_23 = m[4]*m[11] - m[7]*m[8];
+ double d11_22 = m[5]*m[10] - m[6]*m[9];
+ double d11_23 = m[5]*m[11] - m[7]*m[9];
+ double d12_23 = m[6]*m[11] - m[7]*m[10];
+
+ double a00 = m[13]*d12_23 - m[14]*d11_23 + m[15]*d11_22;
+ double a10 = m[14]*d10_23 - m[15]*d10_22 - m[12]*d12_23;
+ double a20 = m[12]*d11_23 - m[13]*d10_23 + m[15]*d10_21;
+ double a30 = m[13]*d10_22 - m[14]*d10_21 - m[12]*d11_22;
+
+ double det = a00*m[0] + a10*m[1] + a20*m[2] + a30*m[3];
+
+ if(IsScalarEqualToZero((float)det)) return false;
+
+ det = 1.0/det;
+
+ double d00_31 = m[0]*m[13] - m[1]*m[12];
+ double d00_32 = m[0]*m[14] - m[2]*m[12];
+ double d00_33 = m[0]*m[15] - m[3]*m[12];
+ double d01_32 = m[1]*m[14] - m[2]*m[13];
+ double d01_33 = m[1]*m[15] - m[3]*m[13];
+ double d02_33 = m[2]*m[15] - m[3]*m[14];
+
+ double a01 = m[9]*d02_33 - m[10]*d01_33 + m[11]*d01_32;
+ double a11 = m[10]*d00_33 - m[11]*d00_32 - m[8]*d02_33;
+ double a21 = m[8]*d01_33 - m[9]*d00_33 + m[11]*d00_31;
+ double a31 = m[9]*d00_32 - m[10]*d00_31 - m[8]*d01_32;
+
+ double a02 = m[6]*d01_33 - m[7]*d01_32 - m[5]*d02_33;
+ double a12 = m[4]*d02_33 - m[6]*d00_33 + m[7]*d00_32;
+ double a22 = m[5]*d00_33 - m[7]*d00_31 - m[4]*d01_33;
+ double a32 = m[4]*d01_32 - m[5]*d00_32 + m[6]*d00_31;
+
+ double a03 = m[2]*d11_23 - m[3]*d11_22 - m[1]*d12_23;
+ double a13 = m[0]*d12_23 - m[2]*d10_23 + m[3]*d10_22;
+ double a23 = m[1]*d10_23 - m[3]*d10_21 - m[0]*d11_23;
+ double a33 = m[0]*d11_22 - m[1]*d10_22 + m[2]*d10_21;
+
+ inverse_out[0] = (float) (a00*det);
+ inverse_out[1] = (float) (a01*det);
+ inverse_out[2] = (float) (a02*det);
+ inverse_out[3] = (float) (a03*det);
+ inverse_out[4] = (float) (a10*det);
+ inverse_out[5] = (float) (a11*det);
+ inverse_out[6] = (float) (a12*det);
+ inverse_out[7] = (float) (a13*det);
+ inverse_out[8] = (float) (a20*det);
+ inverse_out[9] = (float) (a21*det);
+ inverse_out[10] = (float) (a22*det);
+ inverse_out[11] = (float) (a23*det);
+ inverse_out[12] = (float) (a30*det);
+ inverse_out[13] = (float) (a31*det);
+ inverse_out[14] = (float) (a32*det);
+ inverse_out[15] = (float) (a33*det);
+
+ return true;
+ }
+
+ void GetM44M44Product(float* mout, const float* m1_, const float* m2_)
+ {
+ float m1[16];
+ float m2[16];
+ memcpy(m1, m1_, 16*sizeof(float));
+ memcpy(m2, m2_, 16*sizeof(float));
+
+ mout[ 0] = m1[ 0]*m2[0] + m1[ 1]*m2[4] + m1[ 2]*m2[ 8] + m1[ 3]*m2[12];
+ mout[ 1] = m1[ 0]*m2[1] + m1[ 1]*m2[5] + m1[ 2]*m2[ 9] + m1[ 3]*m2[13];
+ mout[ 2] = m1[ 0]*m2[2] + m1[ 1]*m2[6] + m1[ 2]*m2[10] + m1[ 3]*m2[14];
+ mout[ 3] = m1[ 0]*m2[3] + m1[ 1]*m2[7] + m1[ 2]*m2[11] + m1[ 3]*m2[15];
+ mout[ 4] = m1[ 4]*m2[0] + m1[ 5]*m2[4] + m1[ 6]*m2[ 8] + m1[ 7]*m2[12];
+ mout[ 5] = m1[ 4]*m2[1] + m1[ 5]*m2[5] + m1[ 6]*m2[ 9] + m1[ 7]*m2[13];
+ mout[ 6] = m1[ 4]*m2[2] + m1[ 5]*m2[6] + m1[ 6]*m2[10] + m1[ 7]*m2[14];
+ mout[ 7] = m1[ 4]*m2[3] + m1[ 5]*m2[7] + m1[ 6]*m2[11] + m1[ 7]*m2[15];
+ mout[ 8] = m1[ 8]*m2[0] + m1[ 9]*m2[4] + m1[10]*m2[ 8] + m1[11]*m2[12];
+ mout[ 9] = m1[ 8]*m2[1] + m1[ 9]*m2[5] + m1[10]*m2[ 9] + m1[11]*m2[13];
+ mout[10] = m1[ 8]*m2[2] + m1[ 9]*m2[6] + m1[10]*m2[10] + m1[11]*m2[14];
+ mout[11] = m1[ 8]*m2[3] + m1[ 9]*m2[7] + m1[10]*m2[11] + m1[11]*m2[15];
+ mout[12] = m1[12]*m2[0] + m1[13]*m2[4] + m1[14]*m2[ 8] + m1[15]*m2[12];
+ mout[13] = m1[12]*m2[1] + m1[13]*m2[5] + m1[14]*m2[ 9] + m1[15]*m2[13];
+ mout[14] = m1[12]*m2[2] + m1[13]*m2[6] + m1[14]*m2[10] + m1[15]*m2[14];
+ mout[15] = m1[12]*m2[3] + m1[13]*m2[7] + m1[14]*m2[11] + m1[15]*m2[15];
+ }
+
+ namespace
+ {
+
+ void GetM44V4Product(float* vout, const float* m, const float* v_)
+ {
+ float v[4];
+ memcpy(v, v_, 4*sizeof(float));
+
+ vout[0] = m[ 0]*v[0] + m[ 1]*v[1] + m[ 2]*v[2] + m[ 3]*v[3];
+ vout[1] = m[ 4]*v[0] + m[ 5]*v[1] + m[ 6]*v[2] + m[ 7]*v[3];
+ vout[2] = m[ 8]*v[0] + m[ 9]*v[1] + m[10]*v[2] + m[11]*v[3];
+ vout[3] = m[12]*v[0] + m[13]*v[1] + m[14]*v[2] + m[15]*v[3];
+ }
+
+ void GetV4Sum(float* vout, const float* v1, const float* v2)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ vout[i] = v1[i] + v2[i];
+ }
+ }
+
+ } // anon namespace
+
+ // All m(s) are 4x4. All v(s) are size 4 vectors.
+ // Return mout, vout, where mout*x+vout == m2*(m1*x+v1)+v2
+ // mout = m2*m1
+ // vout = m2*v1 + v2
+ void GetMxbCombine(float* mout, float* vout,
+ const float* m1_, const float* v1_,
+ const float* m2_, const float* v2_)
+ {
+ float m1[16];
+ float v1[4];
+ float m2[16];
+ float v2[4];
+ memcpy(m1, m1_, 16*sizeof(float));
+ memcpy(v1, v1_, 4*sizeof(float));
+ memcpy(m2, m2_, 16*sizeof(float));
+ memcpy(v2, v2_, 4*sizeof(float));
+
+ GetM44M44Product(mout, m2, m1);
+ GetM44V4Product(vout, m2, v1);
+ GetV4Sum(vout, vout, v2);
+ }
+
+ namespace
+ {
+
+ void GetMxbResult(float* vout, float* m, float* x, float* v)
+ {
+ GetM44V4Product(vout, m, x);
+ GetV4Sum(vout, vout, v);
+ }
+
+ } // anon namespace
+
+ bool GetMxbInverse(float* mout, float* vout,
+ const float* m_, const float* v_)
+ {
+ float m[16];
+ float v[4];
+ memcpy(m, m_, 16*sizeof(float));
+ memcpy(v, v_, 4*sizeof(float));
+
+ if(!GetM44Inverse(mout, m)) return false;
+
+ for(int i=0; i<4; ++i)
+ {
+ v[i] = -v[i];
+ }
+ GetM44V4Product(vout, mout, v);
+
+ return true;
+ }
+
+}
+
+OCIO_NAMESPACE_EXIT
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+OCIO_NAMESPACE_USING
+
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(MathUtils, M44_is_diagonal)
+{
+ {
+ float m44[] = { 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f };
+ bool isdiag = IsM44Diagonal(m44);
+ OIIO_CHECK_EQUAL(isdiag, true);
+
+ m44[1] += 1e-8f;
+ isdiag = IsM44Diagonal(m44);
+ OIIO_CHECK_EQUAL(isdiag, false);
+ }
+}
+
+
+OIIO_ADD_TEST(MathUtils, IsScalarEqualToZero)
+{
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(0.0f), true);
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(-0.0f), true);
+
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(-1.072883670794056e-09f), false);
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(1.072883670794056e-09f), false);
+
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(-1.072883670794056e-03f), false);
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(1.072883670794056e-03f), false);
+
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(-1.072883670794056e-01f), false);
+ OIIO_CHECK_EQUAL(IsScalarEqualToZero(1.072883670794056e-01f), false);
+}
+
+OIIO_ADD_TEST(MathUtils, GetM44Inverse)
+{
+ // This is a degenerate matrix, and shouldnt be invertible.
+ float m[] = { 0.3f, 0.3f, 0.3f, 0.0f,
+ 0.3f, 0.3f, 0.3f, 0.0f,
+ 0.3f, 0.3f, 0.3f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f };
+
+ float mout[16];
+ bool invertsuccess = GetM44Inverse(mout, m);
+ OIIO_CHECK_EQUAL(invertsuccess, false);
+}
+
+
+OIIO_ADD_TEST(MathUtils, M44_M44_product)
+{
+ {
+ float mout[16];
+ float m1[] = { 1.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 3.0f, 1.0f };
+ float m2[] = { 1.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 2.0f, 0.0f, 0.0f, 1.0f };
+ GetM44M44Product(mout, m1, m2);
+
+ float mcorrect[] = { 1.0f, 3.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, 1.0f, 0.0f,
+ 2.0f, 1.0f, 3.0f, 1.0f };
+
+ for(int i=0; i<16; ++i)
+ {
+ OIIO_CHECK_EQUAL(mout[i], mcorrect[i]);
+ }
+ }
+}
+
+OIIO_ADD_TEST(MathUtils, M44_V4_product)
+{
+ {
+ float vout[4];
+ float m[] = { 1.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 3.0f, 1.0f };
+ float v[] = { 1.0f, 2.0f, 3.0f, 4.0f };
+ GetM44V4Product(vout, m, v);
+
+ float vcorrect[] = { 5.0f, 5.0f, 4.0f, 15.0f };
+
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_EQUAL(vout[i], vcorrect[i]);
+ }
+ }
+}
+
+OIIO_ADD_TEST(MathUtils, V4_add)
+{
+ {
+ float vout[4];
+ float v1[] = { 1.0f, 2.0f, 3.0f, 4.0f };
+ float v2[] = { 3.0f, 1.0f, 4.0f, 1.0f };
+ GetV4Sum(vout, v1, v2);
+
+ float vcorrect[] = { 4.0f, 3.0f, 7.0f, 5.0f };
+
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_EQUAL(vout[i], vcorrect[i]);
+ }
+ }
+}
+
+OIIO_ADD_TEST(MathUtils, mxb_eval)
+{
+ {
+ float vout[4];
+ float m[] = { 1.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 3.0f, 1.0f };
+ float x[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ float v[] = { 1.0f, 2.0f, 3.0f, 4.0f };
+ GetMxbResult(vout, m, x, v);
+
+ float vcorrect[] = { 4.0f, 4.0f, 5.0f, 9.0f };
+
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_EQUAL(vout[i], vcorrect[i]);
+ }
+ }
+}
+
+OIIO_ADD_TEST(MathUtils, Combine_two_mxb)
+{
+ float m1[] = { 1.0f, 0.0f, 2.0f, 0.0f,
+ 2.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 2.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 1.0f };
+ float v1[] = { 1.0f, 2.0f, 3.0f, 4.0f };
+ float m2[] = { 2.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 3.0f, 0.0f,
+ 1.0f,1.0f, 1.0f, 1.0f };
+ float v2[] = { 0.0f, 2.0f, 1.0f, 0.0f };
+ float tolerance = 1e-9f;
+
+ {
+ float x[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ float vout[4];
+
+ // Combine two mx+b operations, and apply to test point
+ float mout[16];
+ float vcombined[4];
+ GetMxbCombine(mout, vout, m1, v1, m2, v2);
+ GetMxbResult(vcombined, mout, x, vout);
+
+ // Sequentially apply the two mx+b operations.
+ GetMxbResult(vout, m1, x, v1);
+ GetMxbResult(vout, m2, vout, v2);
+
+ // Compare outputs
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(vcombined[i], vout[i], tolerance);
+ }
+ }
+
+ {
+ float x[] = { 6.0f, 0.5f, -2.0f, -0.1f };
+ float vout[4];
+
+ float mout[16];
+ float vcombined[4];
+ GetMxbCombine(mout, vout, m1, v1, m2, v2);
+ GetMxbResult(vcombined, mout, x, vout);
+
+ GetMxbResult(vout, m1, x, v1);
+ GetMxbResult(vout, m2, vout, v2);
+
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(vcombined[i], vout[i], tolerance);
+ }
+ }
+
+ {
+ float x[] = { 26.0f, -0.5f, 0.005f, 12.1f };
+ float vout[4];
+
+ float mout[16];
+ float vcombined[4];
+ GetMxbCombine(mout, vout, m1, v1, m2, v2);
+ GetMxbResult(vcombined, mout, x, vout);
+
+ GetMxbResult(vout, m1, x, v1);
+ GetMxbResult(vout, m2, vout, v2);
+
+ // We pick a not so small tolerance, as we're dealing with
+ // large numbers, and the error for CHECK_CLOSE is absolute.
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(vcombined[i], vout[i], 1e-3);
+ }
+ }
+}
+
+OIIO_ADD_TEST(MathUtils, mxb_invert)
+{
+ {
+ float m[] = { 1.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 3.0f, 1.0f };
+ float x[] = { 1.0f, 0.5f, -1.0f, 60.0f };
+ float v[] = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+ float vresult[4];
+ float mout[16];
+ float vout[4];
+
+ GetMxbResult(vresult, m, x, v);
+ bool invertsuccess = GetMxbInverse(mout, vout, m, v);
+ OIIO_CHECK_EQUAL(invertsuccess, true);
+
+ GetMxbResult(vresult, mout, vresult, vout);
+
+ float tolerance = 1e-9f;
+ for(int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(vresult[i], x[i], tolerance);
+ }
+ }
+
+ {
+ float m[] = { 0.3f, 0.3f, 0.3f, 0.0f,
+ 0.3f, 0.3f, 0.3f, 0.0f,
+ 0.3f, 0.3f, 0.3f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f };
+ float v[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ float mout[16];
+ float vout[4];
+
+ bool invertsuccess = GetMxbInverse(mout, vout, m, v);
+ OIIO_CHECK_EQUAL(invertsuccess, false);
+ }
+}
+
+#endif
+
diff --git a/src/core/MathUtils.h b/src/core/MathUtils.h
new file mode 100644
index 0000000..ffe66f3
--- /dev/null
+++ b/src/core/MathUtils.h
@@ -0,0 +1,186 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_MATHUTILS_H
+#define INCLUDED_OCIO_MATHUTILS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <cmath>
+#include <vector>
+
+#include "Op.h"
+#include "Platform.h"
+
+#ifdef WINDOWS
+#include <float.h>
+#endif
+
+OCIO_NAMESPACE_ENTER
+{
+ // From Imath
+ //--------------------------------------------------------------------------
+ // Compare two numbers and test if they are "approximately equal":
+ //
+ // equalWithAbsError (x1, x2, e)
+ //
+ // Returns true if x1 is the same as x2 with an absolute error of
+ // no more than e,
+ //
+ // abs (x1 - x2) <= e
+ //
+ // equalWithRelError (x1, x2, e)
+ //
+ // Returns true if x1 is the same as x2 with an relative error of
+ // no more than e,
+ //
+ // abs (x1 - x2) <= e * x1
+ //
+ //--------------------------------------------------------------------------
+
+ inline bool equalWithAbsError (float x1, float x2, float e)
+ {
+ return ((x1 > x2)? x1 - x2: x2 - x1) <= e;
+ }
+
+ inline bool equalWithRelError (float x1, float x2, float e)
+ {
+ return ((x1 > x2)? x1 - x2: x2 - x1) <= e * ((x1 > 0)? x1: -x1);
+ }
+
+ inline float lerpf(float a, float b, float z)
+ {
+ return (b - a) * z + a;
+ }
+
+#ifdef WINDOWS
+ inline double
+ round (float val) {
+ return floor (val + 0.5);
+ }
+
+ inline float
+ roundf (float val) {
+ return static_cast<float>(round (val));
+ }
+
+ inline int
+ isnan (float val) {
+ // Windows uses a non-standard version of 'isnan'
+ return _isnan (val);
+ }
+#else
+
+#ifdef ANDROID
+// support std::isnan - needs to be tested as it might not be part of the NDK
+#define _GLIBCXX_USE_C99_MATH 1
+#endif
+
+ // This lets all platforms just use isnan, within the OCIO namespace,
+ // across all platforms. (Windows defines the function above).
+ using std::isnan;
+#endif
+
+ // Checks within fltmin tolerance
+ bool IsScalarEqualToZero(float v);
+ bool IsScalarEqualToOne(float v);
+
+ // Are all the vector components the specified value?
+ bool IsVecEqualToZero(const float* v, int size);
+ bool IsVecEqualToOne(const float* v, int size);
+
+ // Is at least one of the specified components equal to 0?
+ bool VecContainsZero(const float* v, int size);
+ bool VecContainsOne(const float* v, int size);
+
+ // Are two vectors equal? (Same size, same values?)
+ bool VecsEqualWithRelError(const float* v1, int size1,
+ const float* v2, int size2,
+ float e);
+
+ inline double GetHalfMax()
+ {
+ return 65504.0; // Largest positive half
+ }
+
+ inline double GetHalfMin()
+ {
+ return 5.96046448e-08; // Smallest positive half;
+ }
+
+ inline double GetHalfNormMin()
+ {
+ return 6.10351562e-05; // Smallest positive normalized half
+ }
+
+ //! Clamp the specified value to the valid range of normalized half.
+ // (can be either positive or negative though
+
+ double ClampToNormHalf(double val);
+
+ float GetSafeScalarInverse(float v, float defaultValue = 1.0);
+
+
+ // All matrix / vector operations use the following sizing...
+ //
+ // m : 4x4 matrix
+ // v : 4 column vector
+
+ // Return the 4x4 inverse, and whether the inverse has succeeded.
+ // Supports in-place operations
+ bool GetM44Inverse(float* mout, const float* m);
+
+ // Is an identity matrix? (with fltmin tolerance)
+ bool IsM44Identity(const float* m);
+
+ // Is this a purely diagonal matrix?
+ bool IsM44Diagonal(const float* m);
+
+ // Extract the diagonal
+ void GetM44Diagonal(float* vout, const float* m);
+
+ // Get the product, out = m1*m2
+ // Supports in-place operations
+ void GetM44Product(float* mout, const float* m1, const float* m2);
+
+ // Combine two transforms in the mx+b form, into a single transform
+ // mout*x+vout == m2*(m1*x+v1)+v2
+ // Supports in-place operations
+ void GetMxbCombine(float* mout, float* vout,
+ const float* m1, const float* v1,
+ const float* m2, const float* v2);
+
+ // Supports in-place operations
+ bool GetMxbInverse(float* mout, float* vout,
+ const float* m, const float* v);
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/MatrixOps.cpp b/src/core/MatrixOps.cpp
new file mode 100644
index 0000000..a0d4ef3
--- /dev/null
+++ b/src/core/MatrixOps.cpp
@@ -0,0 +1,788 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "GpuShaderUtils.h"
+#include "HashUtils.h"
+#include "MatrixOps.h"
+#include "MathUtils.h"
+
+#include <cstring>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ void ApplyScale(float* rgbaBuffer, long numPixels,
+ const float* scale4)
+ {
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ rgbaBuffer[0] *= scale4[0];
+ rgbaBuffer[1] *= scale4[1];
+ rgbaBuffer[2] *= scale4[2];
+ rgbaBuffer[3] *= scale4[3];
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ void ApplyOffset(float* rgbaBuffer, long numPixels,
+ const float* offset4)
+ {
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ rgbaBuffer[0] += offset4[0];
+ rgbaBuffer[1] += offset4[1];
+ rgbaBuffer[2] += offset4[2];
+ rgbaBuffer[3] += offset4[3];
+
+ rgbaBuffer += 4;
+ }
+ }
+
+ void ApplyMatrix(float* rgbaBuffer, long numPixels,
+ const float* mat44)
+ {
+ float r,g,b,a;
+
+ for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
+ {
+ r = rgbaBuffer[0];
+ g = rgbaBuffer[1];
+ b = rgbaBuffer[2];
+ a = rgbaBuffer[3];
+
+ rgbaBuffer[0] = r*mat44[0] + g*mat44[1] + b*mat44[2] + a*mat44[3];
+ rgbaBuffer[1] = r*mat44[4] + g*mat44[5] + b*mat44[6] + a*mat44[7];
+ rgbaBuffer[2] = r*mat44[8] + g*mat44[9] + b*mat44[10] + a*mat44[11];
+ rgbaBuffer[3] = r*mat44[12] + g*mat44[13] + b*mat44[14] + a*mat44[15];
+
+ rgbaBuffer += 4;
+ }
+ }
+ }
+
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+
+ namespace
+ {
+ class MatrixOffsetOp : public Op
+ {
+ public:
+ MatrixOffsetOp(const float * m44,
+ const float * offset4,
+ TransformDirection direction);
+ virtual ~MatrixOffsetOp();
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const;
+ virtual std::string getCacheID() const;
+
+ virtual bool isNoOp() const;
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool canCombineWith(const OpRcPtr & op) const;
+ virtual void combineWith(OpRcPtrVec & ops, const OpRcPtr & secondOp) const;
+
+ virtual bool hasChannelCrosstalk() const;
+ virtual void finalize();
+ virtual void apply(float* rgbaBuffer, long numPixels) const;
+
+ virtual bool supportsGpuShader() const;
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const;
+
+ private:
+ bool m_isNoOp;
+ float m_m44[16];
+ float m_offset4[4];
+ TransformDirection m_direction;
+
+ // Set in finalize
+ bool m_m44IsIdentity;
+ bool m_m44IsDiagonal;
+ bool m_offset4IsIdentity;
+ float m_m44_inv[16];
+ std::string m_cacheID;
+ };
+
+
+ typedef OCIO_SHARED_PTR<MatrixOffsetOp> MatrixOffsetOpRcPtr;
+
+
+ MatrixOffsetOp::MatrixOffsetOp(const float * m44,
+ const float * offset4,
+ TransformDirection direction):
+ Op(),
+ m_isNoOp(false),
+ m_direction(direction),
+ m_m44IsIdentity(false),
+ m_offset4IsIdentity(false)
+ {
+ if(m_direction == TRANSFORM_DIR_UNKNOWN)
+ {
+ throw Exception("Cannot apply MatrixOffsetOp op, unspecified transform direction.");
+ }
+
+ memcpy(m_m44, m44, 16*sizeof(float));
+ memcpy(m_offset4, offset4, 4*sizeof(float));
+
+ memset(m_m44_inv, 0, 16*sizeof(float));
+
+ // This Op will be a NoOp if and old if both the offset and matrix
+ // are identity. This hold true no matter what the direction is,
+ // so we can compute this ahead of time.
+ m_isNoOp = (IsVecEqualToZero(m_offset4, 4) && IsM44Identity(m_m44));
+ }
+
+ OpRcPtr MatrixOffsetOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new MatrixOffsetOp(m_m44, m_offset4, m_direction));
+ return op;
+ }
+
+ MatrixOffsetOp::~MatrixOffsetOp()
+ { }
+
+ std::string MatrixOffsetOp::getInfo() const
+ {
+ return "<MatrixOffsetOp>";
+ }
+
+ std::string MatrixOffsetOp::getCacheID() const
+ {
+ return m_cacheID;
+ }
+
+ bool MatrixOffsetOp::isNoOp() const
+ {
+ return m_isNoOp;
+ }
+
+ bool MatrixOffsetOp::isSameType(const OpRcPtr & op) const
+ {
+ MatrixOffsetOpRcPtr typedRcPtr = DynamicPtrCast<MatrixOffsetOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool MatrixOffsetOp::isInverse(const OpRcPtr & op) const
+ {
+ MatrixOffsetOpRcPtr typedRcPtr = DynamicPtrCast<MatrixOffsetOp>(op);
+ if(!typedRcPtr) return false;
+
+ if(GetInverseTransformDirection(m_direction) != typedRcPtr->m_direction)
+ return false;
+
+ float error = std::numeric_limits<float>::min();
+ if(!VecsEqualWithRelError(m_m44, 16, typedRcPtr->m_m44, 16, error))
+ return false;
+ if(!VecsEqualWithRelError(m_offset4, 4,typedRcPtr->m_offset4, 4, error))
+ return false;
+
+ return true;
+ }
+
+ bool MatrixOffsetOp::canCombineWith(const OpRcPtr & op) const
+ {
+ return isSameType(op);
+ }
+
+ void MatrixOffsetOp::combineWith(OpRcPtrVec & ops, const OpRcPtr & secondOp) const
+ {
+ MatrixOffsetOpRcPtr typedRcPtr = DynamicPtrCast<MatrixOffsetOp>(secondOp);
+ if(!typedRcPtr)
+ {
+ std::ostringstream os;
+ os << "MatrixOffsetOp can only be combined with other ";
+ os << "MatrixOffsetOps. secondOp:" << secondOp->getInfo();
+ throw Exception(os.str().c_str());
+ }
+
+ float mout[16];
+ float vout[4];
+
+ if(m_direction == TRANSFORM_DIR_FORWARD &&
+ typedRcPtr->m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ GetMxbCombine(mout, vout,
+ m_m44, m_offset4,
+ typedRcPtr->m_m44, typedRcPtr->m_offset4);
+ }
+ else if(m_direction == TRANSFORM_DIR_FORWARD &&
+ typedRcPtr->m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ float minv2[16];
+ float vinv2[4];
+
+ if(!GetMxbInverse(minv2, vinv2, typedRcPtr->m_m44, typedRcPtr->m_offset4))
+ {
+ std::ostringstream os;
+ os << "Cannot invert second MatrixOffsetOp op. ";
+ os << "Matrix inverse does not exist for (";
+ for(int i=0; i<16; ++i)
+ {
+ os << typedRcPtr->m_m44[i] << " ";
+ }
+ os << ").";
+ throw Exception(os.str().c_str());
+ }
+
+ GetMxbCombine(mout, vout,
+ m_m44, m_offset4,
+ minv2, vinv2);
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE &&
+ typedRcPtr->m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ float minv1[16];
+ float vinv1[4];
+
+ if(!GetMxbInverse(minv1, vinv1, m_m44, m_offset4))
+ {
+ std::ostringstream os;
+ os << "Cannot invert primary MatrixOffsetOp op. ";
+ os << "Matrix inverse does not exist for (";
+ for(int i=0; i<16; ++i)
+ {
+ os << m_m44[i] << " ";
+ }
+ os << ").";
+ throw Exception(os.str().c_str());
+ }
+
+ GetMxbCombine(mout, vout,
+ minv1, vinv1,
+ typedRcPtr->m_m44, typedRcPtr->m_offset4);
+
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE &&
+ typedRcPtr->m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ float minv1[16];
+ float vinv1[4];
+ float minv2[16];
+ float vinv2[4];
+
+ if(!GetMxbInverse(minv1, vinv1, m_m44, m_offset4))
+ {
+ std::ostringstream os;
+ os << "Cannot invert primary MatrixOffsetOp op. ";
+ os << "Matrix inverse does not exist for (";
+ for(int i=0; i<16; ++i)
+ {
+ os << m_m44[i] << " ";
+ }
+ os << ").";
+ throw Exception(os.str().c_str());
+ }
+
+ if(!GetMxbInverse(minv2, vinv2, typedRcPtr->m_m44, typedRcPtr->m_offset4))
+ {
+ std::ostringstream os;
+ os << "Cannot invert second MatrixOffsetOp op. ";
+ os << "Matrix inverse does not exist for (";
+ for(int i=0; i<16; ++i)
+ {
+ os << typedRcPtr->m_m44[i] << " ";
+ }
+ os << ").";
+ throw Exception(os.str().c_str());
+ }
+
+ GetMxbCombine(mout, vout,
+ minv1, vinv1,
+ minv2, vinv2);
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "MatrixOffsetOp cannot combine ops with unspecified ";
+ os << "directions. First op: " << m_direction << " ";
+ os << "secondOp:" << typedRcPtr->m_direction;
+ throw Exception(os.str().c_str());
+ }
+
+ CreateMatrixOffsetOp(ops,
+ mout, vout,
+ TRANSFORM_DIR_FORWARD);
+ }
+
+ bool MatrixOffsetOp::hasChannelCrosstalk() const
+ {
+ return (!m_m44IsDiagonal);
+ }
+
+ void MatrixOffsetOp::finalize()
+ {
+ m_offset4IsIdentity = IsVecEqualToZero(m_offset4, 4);
+ m_m44IsIdentity = IsM44Identity(m_m44);
+ m_m44IsDiagonal = IsM44Diagonal(m_m44);
+
+ if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ if(!GetM44Inverse(m_m44_inv, m_m44))
+ {
+ std::ostringstream os;
+ os << "Cannot apply MatrixOffsetOp op. ";
+ os << "Matrix inverse does not exist for m44 (";
+ for(int i=0; i<16; ++i) os << m_m44[i] << " ";
+ os << ").";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ // Create the cacheID
+ md5_state_t state;
+ md5_byte_t digest[16];
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)m_m44, 16*sizeof(float));
+ md5_append(&state, (const md5_byte_t *)m_offset4, 4*sizeof(float));
+ md5_finish(&state, digest);
+
+ std::ostringstream cacheIDStream;
+ cacheIDStream << "<MatrixOffsetOp ";
+ cacheIDStream << GetPrintableHash(digest) << " ";
+ cacheIDStream << TransformDirectionToString(m_direction) << " ";
+ cacheIDStream << ">";
+
+ m_cacheID = cacheIDStream.str();
+ }
+
+ void MatrixOffsetOp::apply(float* rgbaBuffer, long numPixels) const
+ {
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ if(!m_m44IsIdentity)
+ {
+ if(m_m44IsDiagonal)
+ {
+ float scale[4];
+ GetM44Diagonal(scale, m_m44);
+ ApplyScale(rgbaBuffer, numPixels, scale);
+ }
+ else
+ {
+ ApplyMatrix(rgbaBuffer, numPixels, m_m44);
+ }
+ }
+
+ if(!m_offset4IsIdentity)
+ {
+ ApplyOffset(rgbaBuffer, numPixels, m_offset4);
+ }
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ if(!m_offset4IsIdentity)
+ {
+ float offset_inv[] = { -m_offset4[0],
+ -m_offset4[1],
+ -m_offset4[2],
+ -m_offset4[3] };
+
+ ApplyOffset(rgbaBuffer, numPixels, offset_inv);
+ }
+
+ if(!m_m44IsIdentity)
+ {
+ if(m_m44IsDiagonal)
+ {
+ float scale[4];
+ GetM44Diagonal(scale, m_m44_inv);
+ ApplyScale(rgbaBuffer, numPixels, scale);
+ }
+ else
+ {
+ ApplyMatrix(rgbaBuffer, numPixels, m_m44_inv);
+ }
+ }
+ }
+ } // Op::process
+
+ bool MatrixOffsetOp::supportsGpuShader() const
+ {
+ return true;
+ }
+
+ void MatrixOffsetOp::writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const
+ {
+ GpuLanguage lang = shaderDesc.getLanguage();
+
+ // TODO: This should not act upon alpha,
+ // since we dont apply it on the CPU?
+
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ if(!m_m44IsIdentity)
+ {
+ if(m_m44IsDiagonal)
+ {
+ shader << pixelName << " = ";
+ float scale[4];
+ GetM44Diagonal(scale, m_m44);
+ Write_half4(shader, scale, lang);
+ shader << " * " << pixelName << ";\n";
+ }
+ else
+ {
+ shader << pixelName << " = ";
+ Write_mtx_x_vec(shader,
+ GpuTextHalf4x4(m_m44, lang), pixelName,
+ lang);
+ shader << ";\n";
+ }
+ }
+
+ if(!m_offset4IsIdentity)
+ {
+ shader << pixelName << " = ";
+ Write_half4(shader, m_offset4, lang);
+ shader << " + " << pixelName << ";\n";
+ }
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ if(!m_offset4IsIdentity)
+ {
+ float offset_inv[] = { -m_offset4[0],
+ -m_offset4[1],
+ -m_offset4[2],
+ -m_offset4[3] };
+
+ shader << pixelName << " = ";
+ Write_half4(shader, offset_inv, lang);
+ shader << " + " << pixelName << ";\n";
+ }
+
+ if(!m_m44IsIdentity)
+ {
+ if(m_m44IsDiagonal)
+ {
+ shader << pixelName << " = ";
+ float scale[4];
+ GetM44Diagonal(scale, m_m44_inv);
+ Write_half4(shader, scale, lang);
+ shader << " * " << pixelName << ";\n";
+ }
+ else
+ {
+ shader << pixelName << " = ";
+ Write_mtx_x_vec(shader,
+ GpuTextHalf4x4(m_m44_inv, lang), pixelName,
+ lang);
+ shader << ";\n";
+ }
+ }
+ }
+ }
+
+ } // Anon namespace
+
+
+
+
+
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+
+
+ void CreateScaleOp(OpRcPtrVec & ops,
+ const float * scale4,
+ TransformDirection direction)
+ {
+ float offset4[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ CreateScaleOffsetOp(ops, scale4, offset4, direction);
+ }
+
+ void CreateMatrixOp(OpRcPtrVec & ops,
+ const float * m44,
+ TransformDirection direction)
+ {
+ float offset4[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ CreateMatrixOffsetOp(ops, m44, offset4, direction);
+ }
+
+ void CreateOffsetOp(OpRcPtrVec & ops,
+ const float * offset4,
+ TransformDirection direction)
+ {
+ float scale4[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ CreateScaleOffsetOp(ops, scale4, offset4, direction);
+ }
+
+ void CreateScaleOffsetOp(OpRcPtrVec & ops,
+ const float * scale4, const float * offset4,
+ TransformDirection direction)
+ {
+ float m44[16];
+ memset(m44, 0, 16*sizeof(float));
+
+ m44[0] = scale4[0];
+ m44[5] = scale4[1];
+ m44[10] = scale4[2];
+ m44[15] = scale4[3];
+
+ CreateMatrixOffsetOp(ops,
+ m44, offset4,
+ direction);
+ }
+
+ void CreateSaturationOp(OpRcPtrVec & ops,
+ float sat,
+ const float * lumaCoef3,
+ TransformDirection direction)
+ {
+ float matrix[16];
+ float offset[4];
+ MatrixTransform::Sat(matrix, offset,
+ sat, lumaCoef3);
+
+ CreateMatrixOffsetOp(ops, matrix, offset, direction);
+ }
+
+ void CreateMatrixOffsetOp(OpRcPtrVec & ops,
+ const float * m44, const float * offset4,
+ TransformDirection direction)
+ {
+ bool mtxIsIdentity = IsM44Identity(m44);
+ bool offsetIsIdentity = IsVecEqualToZero(offset4, 4);
+ if(mtxIsIdentity && offsetIsIdentity) return;
+
+ ops.push_back( MatrixOffsetOpRcPtr(new MatrixOffsetOp(m44,
+ offset4, direction)) );
+ }
+
+ void CreateFitOp(OpRcPtrVec & ops,
+ const float * oldmin4, const float * oldmax4,
+ const float * newmin4, const float * newmax4,
+ TransformDirection direction)
+ {
+ float matrix[16];
+ float offset[4];
+ MatrixTransform::Fit(matrix, offset,
+ oldmin4, oldmax4,
+ newmin4, newmax4);
+
+ CreateMatrixOffsetOp(ops, matrix, offset, direction);
+ }
+
+}
+OCIO_NAMESPACE_EXIT
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OCIO_NAMESPACE_USING
+
+OIIO_ADD_TEST(MatrixOps, Combining)
+{
+ float m1[16] = { 1.1f, 0.2f, 0.3f, 0.4f,
+ 0.5f, 1.6f, 0.7f, 0.8f,
+ 0.2f, 0.1f, 1.1f, 0.2f,
+ 0.3f, 0.4f, 0.5f, 1.6f };
+
+ float v1[4] = { -0.5f, -0.25f, 0.25f, 0.0f };
+
+ float m2[16] = { 1.1f, -0.1f, -0.1f, 0.0f,
+ 0.1f, 0.9f, -0.2f, 0.0f,
+ 0.05f, 0.0f, 1.1f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f };
+ float v2[4] = { -0.2f, -0.1f, -0.1f, -0.2f };
+
+ const float source[] = { 0.1f, 0.2f, 0.3f, 0.4f,
+ -0.1f, -0.2f, 50.0f, 123.4f,
+ 1.0f, 1.0f, 1.0f, 1.0f };
+ float error = 1e-4f;
+
+ {
+ OpRcPtrVec ops;
+ CreateMatrixOffsetOp(ops, m1, v1, TRANSFORM_DIR_FORWARD);
+ CreateMatrixOffsetOp(ops, m2, v2, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ ops[0]->finalize();
+ ops[1]->finalize();
+
+ OpRcPtrVec combined;
+ ops[0]->combineWith(combined, ops[1]);
+ OIIO_CHECK_EQUAL(combined.size(), 1);
+ combined[0]->finalize();
+
+ for(int test=0; test<3; ++test)
+ {
+ float tmp[4];
+ memcpy(tmp, &source[4*test], 4*sizeof(float));
+ ops[0]->apply(tmp, 1);
+ ops[1]->apply(tmp, 1);
+
+ float tmp2[4];
+ memcpy(tmp2, &source[4*test], 4*sizeof(float));
+ combined[0]->apply(tmp2, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp2[i], tmp[i], error);
+ }
+ }
+ }
+
+
+ {
+ OpRcPtrVec ops;
+ CreateMatrixOffsetOp(ops, m1, v1, TRANSFORM_DIR_FORWARD);
+ CreateMatrixOffsetOp(ops, m2, v2, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ ops[0]->finalize();
+ ops[1]->finalize();
+
+ OpRcPtrVec combined;
+ ops[0]->combineWith(combined, ops[1]);
+ OIIO_CHECK_EQUAL(combined.size(), 1);
+ combined[0]->finalize();
+
+
+ for(int test=0; test<3; ++test)
+ {
+ float tmp[4];
+ memcpy(tmp, &source[4*test], 4*sizeof(float));
+ ops[0]->apply(tmp, 1);
+ ops[1]->apply(tmp, 1);
+
+ float tmp2[4];
+ memcpy(tmp2, &source[4*test], 4*sizeof(float));
+ combined[0]->apply(tmp2, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp2[i], tmp[i], error);
+ }
+ }
+ }
+
+ {
+ OpRcPtrVec ops;
+ CreateMatrixOffsetOp(ops, m1, v1, TRANSFORM_DIR_INVERSE);
+ CreateMatrixOffsetOp(ops, m2, v2, TRANSFORM_DIR_FORWARD);
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ ops[0]->finalize();
+ ops[1]->finalize();
+
+ OpRcPtrVec combined;
+ ops[0]->combineWith(combined, ops[1]);
+ OIIO_CHECK_EQUAL(combined.size(), 1);
+ combined[0]->finalize();
+
+ for(int test=0; test<3; ++test)
+ {
+ float tmp[4];
+ memcpy(tmp, &source[4*test], 4*sizeof(float));
+ ops[0]->apply(tmp, 1);
+ ops[1]->apply(tmp, 1);
+
+ float tmp2[4];
+ memcpy(tmp2, &source[4*test], 4*sizeof(float));
+ combined[0]->apply(tmp2, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp2[i], tmp[i], error);
+ }
+ }
+ }
+
+ {
+ OpRcPtrVec ops;
+ CreateMatrixOffsetOp(ops, m1, v1, TRANSFORM_DIR_INVERSE);
+ CreateMatrixOffsetOp(ops, m2, v2, TRANSFORM_DIR_INVERSE);
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ ops[0]->finalize();
+ ops[1]->finalize();
+
+ OpRcPtrVec combined;
+ ops[0]->combineWith(combined, ops[1]);
+ OIIO_CHECK_EQUAL(combined.size(), 1);
+ combined[0]->finalize();
+
+ for(int test=0; test<3; ++test)
+ {
+ float tmp[4];
+ memcpy(tmp, &source[4*test], 4*sizeof(float));
+ ops[0]->apply(tmp, 1);
+ ops[1]->apply(tmp, 1);
+
+ float tmp2[4];
+ memcpy(tmp2, &source[4*test], 4*sizeof(float));
+ combined[0]->apply(tmp2, 1);
+
+ for(unsigned int i=0; i<4; ++i)
+ {
+ OIIO_CHECK_CLOSE(tmp2[i], tmp[i], error);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/src/core/MatrixOps.h b/src/core/MatrixOps.h
new file mode 100644
index 0000000..e462706
--- /dev/null
+++ b/src/core/MatrixOps.h
@@ -0,0 +1,75 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_MATRIXOFFSETOP_H
+#define INCLUDED_OCIO_MATRIXOFFSETOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // Use whichever is most convenient; they are equally efficient
+
+ void CreateScaleOp(OpRcPtrVec & ops,
+ const float * scale4,
+ TransformDirection direction);
+
+ void CreateMatrixOp(OpRcPtrVec & ops,
+ const float * m44,
+ TransformDirection direction);
+
+ void CreateOffsetOp(OpRcPtrVec & ops,
+ const float * offset4,
+ TransformDirection direction);
+
+ void CreateMatrixOffsetOp(OpRcPtrVec & ops,
+ const float * m44, const float * offset4,
+ TransformDirection direction);
+
+ void CreateScaleOffsetOp(OpRcPtrVec & ops,
+ const float * scale4, const float * offset4,
+ TransformDirection direction);
+
+ void CreateFitOp(OpRcPtrVec & ops,
+ const float * oldmin4, const float * oldmax4,
+ const float * newmin4, const float * newmax4,
+ TransformDirection direction);
+
+ void CreateSaturationOp(OpRcPtrVec & ops,
+ float sat,
+ const float * lumaCoef3,
+ TransformDirection direction);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/MatrixTransform.cpp b/src/core/MatrixTransform.cpp
new file mode 100644
index 0000000..cb88327
--- /dev/null
+++ b/src/core/MatrixTransform.cpp
@@ -0,0 +1,386 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "OpBuilders.h"
+#include "MatrixOps.h"
+#include "MathUtils.h"
+
+
+OCIO_NAMESPACE_ENTER
+{
+ MatrixTransformRcPtr MatrixTransform::Create()
+ {
+ return MatrixTransformRcPtr(new MatrixTransform(), &deleter);
+ }
+
+ void MatrixTransform::deleter(MatrixTransform* t)
+ {
+ delete t;
+ }
+
+ class MatrixTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ float matrix_[16];
+ float offset_[4];
+
+ Impl() :
+ dir_(TRANSFORM_DIR_FORWARD)
+ {
+ Identity(matrix_, offset_);
+ }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ memcpy(matrix_, rhs.matrix_, 16*sizeof(float));
+ memcpy(offset_, rhs.offset_, 4*sizeof(float));
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ MatrixTransform::MatrixTransform()
+ : m_impl(new MatrixTransform::Impl)
+ {
+ }
+
+ TransformRcPtr MatrixTransform::createEditableCopy() const
+ {
+ MatrixTransformRcPtr transform = MatrixTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ MatrixTransform::~MatrixTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ MatrixTransform& MatrixTransform::operator= (const MatrixTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection MatrixTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void MatrixTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ bool MatrixTransform::equals(const MatrixTransform & other) const
+ {
+ const float abserror = 1e-9f;
+
+ for(int i=0; i<16; ++i)
+ {
+ if(!equalWithAbsError(getImpl()->matrix_[i],
+ other.getImpl()->matrix_[i], abserror))
+ {
+ return false;
+ }
+ }
+
+ for(int i=0; i<4; ++i)
+ {
+ if(!equalWithAbsError(getImpl()->offset_[i],
+ other.getImpl()->offset_[i], abserror))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ void MatrixTransform::getValue(float * m44, float * offset4) const
+ {
+ if(m44) memcpy(m44, getImpl()->matrix_, 16*sizeof(float));
+ if(offset4) memcpy(offset4, getImpl()->offset_, 4*sizeof(float));
+ }
+
+ void MatrixTransform::setValue(const float * m44, const float * offset4)
+ {
+ if(m44) memcpy(getImpl()->matrix_, m44, 16*sizeof(float));
+ if(offset4) memcpy(getImpl()->offset_, offset4, 4*sizeof(float));
+ }
+
+ void MatrixTransform::setMatrix(const float * m44)
+ {
+ if(m44) memcpy(getImpl()->matrix_, m44, 16*sizeof(float));
+ }
+
+ void MatrixTransform::getMatrix(float * m44) const
+ {
+ if(m44) memcpy(m44, getImpl()->matrix_, 16*sizeof(float));
+ }
+
+ void MatrixTransform::setOffset(const float * offset4)
+ {
+ if(offset4) memcpy(getImpl()->offset_, offset4, 4*sizeof(float));
+ }
+
+ void MatrixTransform::getOffset(float * offset4) const
+ {
+ if(offset4) memcpy(offset4, getImpl()->offset_, 4*sizeof(float));
+ }
+
+ /*
+ Fit is canonically formulated as:
+ out = newmin + ((value-oldmin)/(oldmax-oldmin)*(newmax-newmin))
+ I.e., subtract the old offset, descale into the [0,1] range,
+ scale into the new range, and add the new offset
+
+ We algebraiclly manipulate the terms into y = mx + b form as:
+ m = (newmax-newmin)/(oldmax-oldmin)
+ b = (newmin*oldmax - newmax*oldmin) / (oldmax-oldmin)
+ */
+
+ void MatrixTransform::Fit(float * m44, float * offset4,
+ const float * oldmin4, const float * oldmax4,
+ const float * newmin4, const float * newmax4)
+ {
+ if(!oldmin4 || !oldmax4) return;
+ if(!newmin4 || !newmax4) return;
+
+ if(m44) memset(m44, 0, 16*sizeof(float));
+ if(offset4) memset(offset4, 0, 4*sizeof(float));
+
+ for(int i=0; i<4; ++i)
+ {
+ float denom = oldmax4[i] - oldmin4[i];
+ if(IsScalarEqualToZero(denom))
+ {
+ std::ostringstream os;
+ os << "Cannot create Fit operator. ";
+ os << "Max value equals min value '";
+ os << oldmax4[i] << "' in channel index ";
+ os << i << ".";
+ throw Exception(os.str().c_str());
+ }
+
+ if(m44) m44[5*i] = (newmax4[i]-newmin4[i]) / denom;
+ if(offset4) offset4[i] = (newmin4[i]*oldmax4[i] - newmax4[i]*oldmin4[i]) / denom;
+ }
+ }
+
+
+ void MatrixTransform::Identity(float * m44, float * offset4)
+ {
+ if(m44)
+ {
+ memset(m44, 0, 16*sizeof(float));
+ m44[0] = 1.0f;
+ m44[5] = 1.0f;
+ m44[10] = 1.0f;
+ m44[15] = 1.0f;
+ }
+
+ if(offset4)
+ {
+ offset4[0] = 0.0f;
+ offset4[1] = 0.0f;
+ offset4[2] = 0.0f;
+ offset4[3] = 0.0f;
+ }
+ }
+
+ void MatrixTransform::Sat(float * m44, float * offset4,
+ float sat, const float * lumaCoef3)
+ {
+ if(!lumaCoef3) return;
+
+ if(m44)
+ {
+ m44[0] = (1 - sat) * lumaCoef3[0] + sat;
+ m44[1] = (1 - sat) * lumaCoef3[1];
+ m44[2] = (1 - sat) * lumaCoef3[2];
+ m44[3] = 0.0f;
+
+ m44[4] = (1 - sat) * lumaCoef3[0];
+ m44[5] = (1 - sat) * lumaCoef3[1] + sat;
+ m44[6] = (1 - sat) * lumaCoef3[2];
+ m44[7] = 0.0f;
+
+ m44[8] = (1 - sat) * lumaCoef3[0];
+ m44[9] = (1 - sat) * lumaCoef3[1];
+ m44[10] = (1 - sat) * lumaCoef3[2] + sat;
+ m44[11] = 0.0f;
+
+ m44[12] = 0.0f;
+ m44[13] = 0.0f;
+ m44[14] = 0.0f;
+ m44[15] = 1.0f;
+ }
+
+ if(offset4)
+ {
+ offset4[0] = 0.0f;
+ offset4[1] = 0.0f;
+ offset4[2] = 0.0f;
+ offset4[3] = 0.0f;
+ }
+ }
+
+ void MatrixTransform::Scale(float * m44, float * offset4,
+ const float * scale4)
+ {
+ if(!scale4) return;
+
+ if(m44)
+ {
+ memset(m44, 0, 16*sizeof(float));
+ m44[0] = scale4[0];
+ m44[5] = scale4[1];
+ m44[10] = scale4[2];
+ m44[15] = scale4[3];
+ }
+
+ if(offset4)
+ {
+ offset4[0] = 0.0f;
+ offset4[1] = 0.0f;
+ offset4[2] = 0.0f;
+ offset4[3] = 0.0f;
+ }
+ }
+
+ void MatrixTransform::View(float * m44, float * offset4,
+ int * channelHot4,
+ const float * lumaCoef3)
+ {
+ if(!channelHot4 || !lumaCoef3) return;
+
+ if(offset4)
+ {
+ offset4[0] = 0.0f;
+ offset4[1] = 0.0f;
+ offset4[2] = 0.0f;
+ offset4[3] = 0.0f;
+ }
+
+ if(m44)
+ {
+ memset(m44, 0, 16*sizeof(float));
+
+ // All channels are hot, return identity
+ if(channelHot4[0] && channelHot4[1] &&
+ channelHot4[2] && channelHot4[3])
+ {
+ Identity(m44, 0x0);
+ }
+ // If not all the channels are hot, but alpha is,
+ // just show it.
+ else if(channelHot4[3])
+ {
+ for(int i=0; i<4; ++i)
+ {
+ m44[4*i+3] = 1.0f;
+ }
+ }
+ // Blend rgb as specified, place it in all 3 output
+ // channels (to make a grayscale final image)
+ else
+ {
+ float values[3] = { 0.0f, 0.0f, 0.0f };
+
+ for(int i = 0; i < 3; ++i)
+ {
+ values[i] += lumaCoef3[i] * (channelHot4[i] ? 1.0f : 0.0f);
+ }
+
+ float sum = values[0] + values[1] + values[2];
+ if(!IsScalarEqualToZero(sum))
+ {
+ values[0] /= sum;
+ values[1] /= sum;
+ values[2] /= sum;
+ }
+
+ // Copy rgb into rgb rows
+ for(int row=0; row<3; ++row)
+ {
+ for(int i=0; i<3; i++)
+ {
+ m44[4*row+i] = values[i];
+ }
+ }
+
+ // Preserve alpha
+ m44[15] = 1.0f;
+ }
+ }
+ }
+
+ std::ostream& operator<< (std::ostream& os, const MatrixTransform& t)
+ {
+ os << "<MatrixTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+ return os;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ void BuildMatrixOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const MatrixTransform & transform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ transform.getDirection());
+
+ float matrix[16];
+ float offset[4];
+ transform.getValue(matrix, offset);
+
+ CreateMatrixOffsetOp(ops,
+ matrix, offset,
+ combinedDir);
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Mutex.h b/src/core/Mutex.h
new file mode 100644
index 0000000..421ad29
--- /dev/null
+++ b/src/core/Mutex.h
@@ -0,0 +1,115 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_MUTEX_H
+#define INCLUDED_OCIO_MUTEX_H
+
+/*
+PTEX SOFTWARE
+Copyright 2009 Disney Enterprises, Inc. All rights reserved
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
+ Studios" or the names of its contributors may NOT be used to
+ endorse or promote products derived from this software without
+ specific prior written permission from Walt Disney Pictures.
+
+Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
+IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+*/
+
+#include "Platform.h"
+
+// #define DEBUG_THREADING
+
+/** For internal use only */
+
+OCIO_NAMESPACE_ENTER
+{
+
+#ifndef NDEBUG
+ template <class T>
+ class DebugLock : public T {
+ public:
+ DebugLock() : _locked(0) {}
+ void lock() { T::lock(); _locked = 1; }
+ void unlock() { assert(_locked); _locked = 0; T::unlock(); }
+ bool locked() { return _locked != 0; }
+ private:
+ int _locked;
+ };
+#endif
+
+ /** Automatically acquire and release lock within enclosing scope. */
+ template <class T>
+ class AutoLock {
+ public:
+ AutoLock(T& m) : _m(m) { _m.lock(); }
+ ~AutoLock() { _m.unlock(); }
+ private:
+ T& _m;
+ };
+
+#ifndef NDEBUG
+ // add debug wrappers to mutex and spinlock
+ typedef DebugLock<_Mutex> Mutex;
+ typedef DebugLock<_SpinLock> SpinLock;
+#else
+ typedef _Mutex Mutex;
+ typedef _SpinLock SpinLock;
+#endif
+
+ typedef AutoLock<Mutex> AutoMutex;
+ typedef AutoLock<SpinLock> AutoSpin;
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/NoOps.cpp b/src/core/NoOps.cpp
new file mode 100644
index 0000000..101324e
--- /dev/null
+++ b/src/core/NoOps.cpp
@@ -0,0 +1,641 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "AllocationOp.h"
+#include "NoOps.h"
+#include "OpBuilders.h"
+#include "Op.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class AllocationNoOp : public Op
+ {
+ public:
+ AllocationNoOp(const AllocationData & allocationData):
+ m_allocationData(allocationData) {}
+ virtual ~AllocationNoOp() {}
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const { return "<AllocationNoOp>"; }
+ virtual std::string getCacheID() const { return ""; }
+
+ virtual bool isNoOp() const { return true; }
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const { return false; }
+ virtual void finalize() { }
+ virtual void apply(float* /*rgbaBuffer*/, long /*numPixels*/) const { }
+
+ virtual bool supportsGpuShader() const { return true; }
+ virtual void writeGpuShader(std::ostream & /*shader*/,
+ const std::string & /*pixelName*/,
+ const GpuShaderDesc & /*shaderDesc*/) const
+ { }
+
+ void getGpuAllocation(AllocationData & allocation) const;
+
+ private:
+ AllocationData m_allocationData;
+ };
+
+ typedef OCIO_SHARED_PTR<AllocationNoOp> AllocationNoOpRcPtr;
+
+ OpRcPtr AllocationNoOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new AllocationNoOp(m_allocationData));
+ return op;
+ }
+
+ bool AllocationNoOp::isSameType(const OpRcPtr & op) const
+ {
+ AllocationNoOpRcPtr typedRcPtr = DynamicPtrCast<AllocationNoOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool AllocationNoOp::isInverse(const OpRcPtr & op) const
+ {
+ if(!isSameType(op)) return false;
+ return true;
+ }
+
+ void AllocationNoOp::getGpuAllocation(AllocationData & allocation) const
+ {
+ allocation = m_allocationData;
+ }
+
+ // Return whether the op defines an Allocation
+ bool DefinesGpuAllocation(const OpRcPtr & op)
+ {
+ AllocationNoOpRcPtr allocationNoOpRcPtr =
+ DynamicPtrCast<AllocationNoOp>(op);
+
+ if(allocationNoOpRcPtr) return true;
+ return false;
+ }
+ }
+
+ void CreateGpuAllocationNoOp(OpRcPtrVec & ops,
+ const AllocationData & allocationData)
+ {
+ ops.push_back( AllocationNoOpRcPtr(new AllocationNoOp(allocationData)) );
+ }
+
+
+ namespace
+ {
+ // Find the minimal index range in the opVec that does not support
+ // shader text generation. The endIndex *is* inclusive.
+ //
+ // I.e., if the entire opVec does not support GPUShaders, the
+ // result will be startIndex = 0, endIndex = opVec.size() - 1
+ //
+ // If the entire opVec supports GPU generation, both the
+ // startIndex and endIndex will equal -1
+
+ void GetGpuUnsupportedIndexRange(int * startIndex, int * endIndex,
+ const OpRcPtrVec & opVec)
+ {
+ int start = -1;
+ int end = -1;
+
+ for(unsigned int i=0; i<opVec.size(); ++i)
+ {
+ // We've found a gpu unsupported op.
+ // If it's the first, save it as our start.
+ // Otherwise, update the end.
+
+ if(!opVec[i]->supportsGpuShader())
+ {
+ if(start<0)
+ {
+ start = i;
+ end = i;
+ }
+ else end = i;
+ }
+ }
+
+ // Now that we've found a startIndex, walk back until we find
+ // one that defines a GpuAllocation. (we can only upload to
+ // the gpu at a location are tagged with an allocation)
+
+ while(start>0)
+ {
+ if(DefinesGpuAllocation(opVec[start])) break;
+ --start;
+ }
+
+ if(startIndex) *startIndex = start;
+ if(endIndex) *endIndex = end;
+ }
+
+
+ bool GetGpuAllocation(AllocationData & allocation,
+ const OpRcPtr & op)
+ {
+ AllocationNoOpRcPtr allocationNoOpRcPtr =
+ DynamicPtrCast<AllocationNoOp>(op);
+
+ if(!allocationNoOpRcPtr)
+ {
+ return false;
+ }
+
+ allocationNoOpRcPtr->getGpuAllocation(allocation);
+ return true;
+ }
+ }
+
+
+ void PartitionGPUOps(OpRcPtrVec & gpuPreOps,
+ OpRcPtrVec & gpuLatticeOps,
+ OpRcPtrVec & gpuPostOps,
+ const OpRcPtrVec & ops)
+ {
+ //
+ // Partition the original, raw opvec into 3 segments for GPU Processing
+ //
+ // gpuLatticeOps need not support analytical gpu shader generation
+ // the pre and post ops must support analytical generation.
+ // Additional ops will be inserted to take into account allocations
+ // transformations.
+
+
+ // This is used to bound our analytical shader text generation
+ // start index and end index are inclusive.
+
+ int gpuLut3DOpStartIndex = 0;
+ int gpuLut3DOpEndIndex = 0;
+ GetGpuUnsupportedIndexRange(&gpuLut3DOpStartIndex,
+ &gpuLut3DOpEndIndex,
+ ops);
+
+ // Write the entire shader using only shader text (3d lut is unused)
+ if(gpuLut3DOpStartIndex == -1 && gpuLut3DOpEndIndex == -1)
+ {
+ for(unsigned int i=0; i<ops.size(); ++i)
+ {
+ gpuPreOps.push_back( ops[i]->clone() );
+ }
+ }
+ // Analytical -> 3dlut -> analytical
+ else
+ {
+ // Handle analytical shader block before start index.
+ for(int i=0; i<gpuLut3DOpStartIndex; ++i)
+ {
+ gpuPreOps.push_back( ops[i]->clone() );
+ }
+
+ // Get the GPU Allocation at the cross-over point
+ // Create 2 symmetrically canceling allocation ops,
+ // where the shader text moves to a nicely allocated LDR
+ // (low dynamic range color space), and the lattice processing
+ // does the inverse (making the overall operation a no-op
+ // color-wise
+
+ AllocationData allocation;
+ if(gpuLut3DOpStartIndex<0 || gpuLut3DOpStartIndex>=(int)ops.size())
+ {
+ std::ostringstream error;
+ error << "Invalid GpuUnsupportedIndexRange: ";
+ error << "gpuLut3DOpStartIndex: " << gpuLut3DOpStartIndex << " ";
+ error << "gpuLut3DOpEndIndex: " << gpuLut3DOpEndIndex << " ";
+ error << "cpuOps.size: " << ops.size();
+ throw Exception(error.str().c_str());
+ }
+
+ // If the specified location defines an allocation, use it.
+ // It's possible that this index wont define an allocation.
+ // (For example in the case of getProcessor(FileTransform)
+ if(GetGpuAllocation(allocation, ops[gpuLut3DOpStartIndex]))
+ {
+ CreateAllocationOps(gpuPreOps, allocation,
+ TRANSFORM_DIR_FORWARD);
+ CreateAllocationOps(gpuLatticeOps, allocation,
+ TRANSFORM_DIR_INVERSE);
+ }
+
+ // Handle cpu lattice processing
+ for(int i=gpuLut3DOpStartIndex; i<=gpuLut3DOpEndIndex; ++i)
+ {
+ gpuLatticeOps.push_back( ops[i]->clone() );
+ }
+
+ // And then handle the gpu post processing
+ for(int i=gpuLut3DOpEndIndex+1; i<(int)ops.size(); ++i)
+ {
+ gpuPostOps.push_back( ops[i]->clone() );
+ }
+ }
+ }
+
+ void AssertPartitionIntegrity(OpRcPtrVec & gpuPreOps,
+ OpRcPtrVec & gpuLatticeOps,
+ OpRcPtrVec & gpuPostOps)
+ {
+ // All gpu pre ops must support analytical gpu shader generation
+ for(unsigned int i=0; i<gpuPreOps.size(); ++i)
+ {
+ if(!gpuPreOps[i]->supportsGpuShader())
+ {
+ throw Exception("Patition failed check. gpuPreOps");
+ }
+ }
+
+ // If there are any lattice ops, at lease one must NOT support GPU
+ // shaders (otherwise this block isnt necessary!)
+ if(gpuLatticeOps.size()>0)
+ {
+ bool requireslattice = false;
+ for(unsigned int i=0; i<gpuLatticeOps.size(); ++i)
+ {
+ if(!gpuLatticeOps[i]->supportsGpuShader()) requireslattice = true;
+ }
+
+ if(!requireslattice)
+ {
+ throw Exception("Patition failed check. gpuLatticeOps");
+ }
+ }
+
+ // All gpu post ops must support analytical gpu shader generation
+ for(unsigned int i=0; i<gpuPostOps.size(); ++i)
+ {
+ if(!gpuPostOps[i]->supportsGpuShader())
+ {
+ throw Exception("Patition failed check. gpuPostOps");
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class FileNoOp : public Op
+ {
+ public:
+ FileNoOp(const std::string & fileReference):
+ m_fileReference(fileReference) {}
+ virtual ~FileNoOp() {}
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const { return "<FileNoOp>"; }
+ virtual std::string getCacheID() const { return ""; }
+
+ virtual bool isNoOp() const { return true; }
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const { return false; }
+ virtual void dumpMetadata(ProcessorMetadataRcPtr & metadata) const;
+
+ virtual void finalize() {}
+ virtual void apply(float* /*rgbaBuffer*/, long /*numPixels*/) const {}
+
+ virtual bool supportsGpuShader() const { return true; }
+ virtual void writeGpuShader(std::ostream & /*shader*/,
+ const std::string & /*pixelName*/,
+ const GpuShaderDesc & /*shaderDesc*/) const
+ { }
+
+ private:
+ std::string m_fileReference;
+ };
+
+ typedef OCIO_SHARED_PTR<FileNoOp> FileNoOpRcPtr;
+
+ OpRcPtr FileNoOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new FileNoOp(m_fileReference));
+ return op;
+ }
+
+ bool FileNoOp::isSameType(const OpRcPtr & op) const
+ {
+ FileNoOpRcPtr typedRcPtr = DynamicPtrCast<FileNoOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool FileNoOp::isInverse(const OpRcPtr & op) const
+ {
+ return isSameType(op);
+ }
+
+ void FileNoOp::dumpMetadata(ProcessorMetadataRcPtr & metadata) const
+ {
+ metadata->addFile(m_fileReference.c_str());
+ }
+ }
+
+ void CreateFileNoOp(OpRcPtrVec & ops,
+ const std::string & fileReference)
+ {
+ ops.push_back( FileNoOpRcPtr(new FileNoOp(fileReference)) );
+ }
+
+
+
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LookNoOp : public Op
+ {
+ public:
+ LookNoOp(const std::string & look):
+ m_look(look) {}
+ virtual ~LookNoOp() {}
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const { return "<LookNoOp>"; }
+ virtual std::string getCacheID() const { return ""; }
+
+ virtual bool isNoOp() const { return true; }
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const { return false; }
+ virtual void dumpMetadata(ProcessorMetadataRcPtr & metadata) const;
+
+ virtual void finalize() {}
+ virtual void apply(float* /*rgbaBuffer*/, long /*numPixels*/) const {}
+
+ virtual bool supportsGpuShader() const { return true; }
+ virtual void writeGpuShader(std::ostream & /*shader*/,
+ const std::string & /*pixelName*/,
+ const GpuShaderDesc & /*shaderDesc*/) const
+ { }
+
+ private:
+ std::string m_look;
+ };
+
+ typedef OCIO_SHARED_PTR<LookNoOp> LookNoOpRcPtr;
+
+ OpRcPtr LookNoOp::clone() const
+ {
+ OpRcPtr op = OpRcPtr(new FileNoOp(m_look));
+ return op;
+ }
+
+ bool LookNoOp::isSameType(const OpRcPtr & op) const
+ {
+ FileNoOpRcPtr typedRcPtr = DynamicPtrCast<FileNoOp>(op);
+ if(!typedRcPtr) return false;
+ return true;
+ }
+
+ bool LookNoOp::isInverse(const OpRcPtr & op) const
+ {
+ return isSameType(op);
+ }
+
+ void LookNoOp::dumpMetadata(ProcessorMetadataRcPtr & metadata) const
+ {
+ metadata->addLook(m_look.c_str());
+ }
+ }
+
+ void CreateLookNoOp(OpRcPtrVec & ops,
+ const std::string & look)
+ {
+ ops.push_back( LookNoOpRcPtr(new LookNoOp(look)) );
+ }
+
+}
+OCIO_NAMESPACE_EXIT
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+OCIO_NAMESPACE_USING
+
+#include "UnitTest.h"
+#include "Lut1DOp.h"
+#include "MatrixOps.h"
+
+void CreateGenericAllocationOp(OpRcPtrVec & ops)
+{
+ AllocationData srcAllocation;
+ srcAllocation.allocation = ALLOCATION_LG2;
+ srcAllocation.vars.push_back(-8.0f);
+ srcAllocation.vars.push_back(8.0f);
+ CreateGpuAllocationNoOp(ops, srcAllocation);
+}
+
+void CreateGenericScaleOp(OpRcPtrVec & ops)
+{
+ float scale4[4] = { 1.04f, 1.05f, 1.06f, 1.0f };
+ CreateScaleOp(ops, scale4, TRANSFORM_DIR_FORWARD);
+}
+
+void CreateGenericLutOp(OpRcPtrVec & ops)
+{
+ // Make a lut that squares the input
+ Lut1DRcPtr lut = Lut1D::Create();
+ {
+ lut->from_min[0] = 0.0f;
+ lut->from_min[1] = 0.0f;
+ lut->from_min[2] = 0.0f;
+ lut->from_max[0] = 1.0f;
+ lut->from_max[1] = 1.0f;
+ lut->from_max[2] = 1.0f;
+ int size = 256;
+ for(int i=0; i<size; ++i)
+ {
+ float x = (float)i / (float)(size-1);
+ float x2 = x*x;
+
+ for(int c=0; c<3; ++c)
+ {
+ lut->luts[c].push_back(x2);
+ }
+ }
+ }
+
+ CreateLut1DOp(ops, lut, INTERP_LINEAR, TRANSFORM_DIR_FORWARD);
+}
+
+OIIO_ADD_TEST(NoOps, PartitionGPUOps)
+{
+ {
+ OpRcPtrVec ops;
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 0);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 0);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 0);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ }
+
+ {
+ OpRcPtrVec ops;
+ CreateGenericAllocationOp(ops);
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 1);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 0);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 0);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ }
+
+ {
+ OpRcPtrVec ops;
+
+ CreateGenericAllocationOp(ops);
+ CreateGenericScaleOp(ops);
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 2);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 0);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 0);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ }
+
+ {
+ OpRcPtrVec ops;
+
+ CreateGenericAllocationOp(ops);
+ CreateGenericLutOp(ops);
+ CreateGenericScaleOp(ops);
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 2);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 4);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 1);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ }
+
+ {
+ OpRcPtrVec ops;
+
+ CreateGenericLutOp(ops);
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 0);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 1);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 0);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ }
+
+ {
+ OpRcPtrVec ops;
+
+ CreateGenericLutOp(ops);
+ CreateGenericScaleOp(ops);
+ CreateGenericAllocationOp(ops);
+ CreateGenericLutOp(ops);
+ CreateGenericScaleOp(ops);
+ CreateGenericAllocationOp(ops);
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 0);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 4);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 2);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ }
+
+ {
+ OpRcPtrVec ops;
+
+ CreateGenericAllocationOp(ops);
+ CreateGenericScaleOp(ops);
+ CreateGenericLutOp(ops);
+ CreateGenericScaleOp(ops);
+ CreateGenericAllocationOp(ops);
+ CreateGenericLutOp(ops);
+ CreateGenericScaleOp(ops);
+ CreateGenericAllocationOp(ops);
+
+ OpRcPtrVec gpuPreOps, gpuLatticeOps, gpuPostOps;
+ PartitionGPUOps(gpuPreOps, gpuLatticeOps, gpuPostOps, ops);
+
+ OIIO_CHECK_EQUAL(gpuPreOps.size(), 2);
+ OIIO_CHECK_EQUAL(gpuLatticeOps.size(), 8);
+ OIIO_CHECK_EQUAL(gpuPostOps.size(), 2);
+
+ OIIO_CHECK_NO_THOW( AssertPartitionIntegrity(gpuPreOps,
+ gpuLatticeOps,
+ gpuPostOps) );
+ /*
+ std::cerr << "gpuPreOps" << std::endl;
+ std::cerr << SerializeOpVec(gpuPreOps, 4) << std::endl;
+ std::cerr << "gpuLatticeOps" << std::endl;
+ std::cerr << SerializeOpVec(gpuLatticeOps, 4) << std::endl;
+ std::cerr << "gpuPostOps" << std::endl;
+ std::cerr << SerializeOpVec(gpuPostOps, 4) << std::endl;
+ */
+ }
+} // PartitionGPUOps
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/NoOps.h b/src/core/NoOps.h
new file mode 100644
index 0000000..dcc93e8
--- /dev/null
+++ b/src/core/NoOps.h
@@ -0,0 +1,67 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_GPUALLOCATIONNOOP_H
+#define INCLUDED_OCIO_GPUALLOCATIONNOOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ void CreateGpuAllocationNoOp(OpRcPtrVec & ops,
+ const AllocationData & allocationData);
+
+
+ // Partition an opvec into 3 segments for GPU Processing
+ //
+ // gpuLatticeOps need not support analytical gpu shader generation
+ // the pre and post ops must support analytical generation.
+ //
+ // Additional ops will optinally be inserted to take into account
+ // allocation transformations
+
+ void PartitionGPUOps(OpRcPtrVec & gpuPreOps,
+ OpRcPtrVec & gpuLatticeOps,
+ OpRcPtrVec & gpuPostOps,
+ const OpRcPtrVec & ops);
+
+ void CreateFileNoOp(OpRcPtrVec & ops,
+ const std::string & fname);
+
+ void CreateLookNoOp(OpRcPtrVec & ops,
+ const std::string & lookName);
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/OCIOYaml.cpp b/src/core/OCIOYaml.cpp
new file mode 100644
index 0000000..7089318
--- /dev/null
+++ b/src/core/OCIOYaml.cpp
@@ -0,0 +1,1218 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstring>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Logging.h"
+#include "MathUtils.h"
+#include "OCIOYaml.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Core
+
+ void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag)
+ {
+ std::string key;
+ tag >> key;
+
+ std::ostringstream os;
+ os << "Unknown key in " << name << ": ";
+ os << "'" << key << "'. (line ";
+ os << (tag.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
+ os << tag.GetMark().column << ")";
+ LogWarning(os.str());
+ }
+
+ void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs)
+ {
+ if(node.Tag() != "ColorSpace")
+ return; // not a !<ColorSpace> tag
+
+ std::string key, stringval;
+ bool boolval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "name")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ cs->setName(stringval.c_str());
+ }
+ else if(key == "description")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ cs->setDescription(stringval.c_str());
+ }
+ else if(key == "family")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ cs->setFamily(stringval.c_str());
+ }
+ else if(key == "equalitygroup")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ cs->setEqualityGroup(stringval.c_str());
+ }
+ else if(key == "bitdepth")
+ {
+ BitDepth ret;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<BitDepth>(ret))
+ cs->setBitDepth(ret);
+ }
+ else if(key == "isdata")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<bool>(boolval))
+ cs->setIsData(boolval);
+ }
+ else if(key == "allocation")
+ {
+ Allocation val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<Allocation>(val))
+ cs->setAllocation(val);
+ }
+ else if(key == "allocationvars")
+ {
+ std::vector<float> val;
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> val;
+ if(!val.empty())
+ {
+ cs->setAllocationVars(static_cast<int>(val.size()), &val[0]);
+ }
+ }
+ }
+ else if(key == "to_reference")
+ {
+ TransformRcPtr val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformRcPtr>(val))
+ cs->setTransform(val, COLORSPACE_DIR_TO_REFERENCE);
+ }
+ else if(key == "from_reference")
+ {
+ TransformRcPtr val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformRcPtr>(val))
+ cs->setTransform(val, COLORSPACE_DIR_FROM_REFERENCE);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs)
+ {
+ out << YAML::VerbatimTag("ColorSpace");
+ out << YAML::BeginMap;
+
+ out << YAML::Key << "name" << YAML::Value << cs->getName();
+ out << YAML::Key << "family" << YAML::Value << cs->getFamily();
+ out << YAML::Key << "equalitygroup" << YAML::Value << cs->getEqualityGroup();
+ out << YAML::Key << "bitdepth" << YAML::Value << cs->getBitDepth();
+ if(strlen(cs->getDescription()) > 0)
+ {
+ out << YAML::Key << "description";
+ out << YAML::Value << YAML::Literal << cs->getDescription();
+ }
+ out << YAML::Key << "isdata" << YAML::Value << cs->isData();
+
+ out << YAML::Key << "allocation" << YAML::Value << cs->getAllocation();
+ if(cs->getAllocationNumVars() > 0)
+ {
+ std::vector<float> allocationvars(cs->getAllocationNumVars());
+ cs->getAllocationVars(&allocationvars[0]);
+ out << YAML::Key << "allocationvars";
+ out << YAML::Flow << YAML::Value << allocationvars;
+ }
+
+ ConstTransformRcPtr toref = \
+ cs->getTransform(COLORSPACE_DIR_TO_REFERENCE);
+ if(toref)
+ out << YAML::Key << "to_reference" << YAML::Value << toref;
+
+ ConstTransformRcPtr fromref = \
+ cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE);
+ if(fromref)
+ out << YAML::Key << "from_reference" << YAML::Value << fromref;
+
+ out << YAML::EndMap;
+ out << YAML::Newline;
+
+ return out;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // Look. (not the transform, the top-level class)
+
+ void operator >> (const YAML::Node& node, LookRcPtr& look)
+ {
+ if(node.Tag() != "Look")
+ return;
+
+ std::string key, stringval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "name")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ look->setName(stringval.c_str());
+ }
+ else if(key == "process_space")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ look->setProcessSpace(stringval.c_str());
+ }
+ else if(key == "transform")
+ {
+ TransformRcPtr val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformRcPtr>(val))
+ look->setTransform(val);
+ }
+ else if(key == "inverse_transform")
+ {
+ TransformRcPtr val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformRcPtr>(val))
+ look->setInverseTransform(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr look)
+ {
+ out << YAML::VerbatimTag("Look");
+ out << YAML::BeginMap;
+ out << YAML::Key << "name" << YAML::Value << look->getName();
+ out << YAML::Key << "process_space" << YAML::Value << look->getProcessSpace();
+
+ if(look->getTransform())
+ {
+ out << YAML::Key << "transform";
+ out << YAML::Value << look->getTransform();
+ }
+
+ if(look->getInverseTransform())
+ {
+ out << YAML::Key << "inverse_transform";
+ out << YAML::Value << look->getInverseTransform();
+ }
+
+ out << YAML::EndMap;
+ out << YAML::Newline;
+
+ return out;
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ namespace
+ {
+ void EmitBaseTransformKeyValues(YAML::Emitter & out,
+ const ConstTransformRcPtr & t)
+ {
+ if(t->getDirection() != TRANSFORM_DIR_FORWARD)
+ {
+ out << YAML::Key << "direction";
+ out << YAML::Value << YAML::Flow << t->getDirection();
+ }
+ }
+ }
+
+ void operator >> (const YAML::Node& node, TransformRcPtr& t)
+ {
+ if(node.Type() != YAML::NodeType::Map)
+ {
+ std::ostringstream os;
+ os << "Unsupported Transform type encountered: (" << node.Type() << ") in OCIO profile. ";
+ os << "Only Mapping types supported. (line ";
+ os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
+ os << node.GetMark().column << ")";
+ throw Exception(os.str().c_str());
+ }
+
+ std::string type = node.Tag();
+
+ if(type == "AllocationTransform") {
+ AllocationTransformRcPtr temp;
+ node.Read<AllocationTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "CDLTransform") {
+ CDLTransformRcPtr temp;
+ node.Read<CDLTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "ColorSpaceTransform") {
+ ColorSpaceTransformRcPtr temp;
+ node.Read<ColorSpaceTransformRcPtr>(temp);
+ t = temp;
+ }
+ // TODO: DisplayTransform
+ else if(type == "ExponentTransform") {
+ ExponentTransformRcPtr temp;
+ node.Read<ExponentTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "FileTransform") {
+ FileTransformRcPtr temp;
+ node.Read<FileTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "GroupTransform") {
+ GroupTransformRcPtr temp;
+ node.Read<GroupTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "LogTransform") {
+ LogTransformRcPtr temp;
+ node.Read<LogTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "LookTransform") {
+ LookTransformRcPtr temp;
+ node.Read<LookTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "MatrixTransform") {
+ MatrixTransformRcPtr temp;
+ node.Read<MatrixTransformRcPtr>(temp);
+ t = temp;
+ }
+ else if(type == "TruelightTransform") {
+ TruelightTransformRcPtr temp;
+ node.Read<TruelightTransformRcPtr>(temp);
+ t = temp;
+ }
+ else
+ {
+ // TODO: add a new empty (better name?) aka passthru Transform()
+ // which does nothing. This is so upsupported !<tag> types don't
+ // throw an exception. Alternativly this could be caught in the
+ // GroupTransformRcPtr >> operator with some type of
+ // supported_tag() method
+
+ // TODO: consider the forwards-compatibility implication of
+ // throwing an exception. Should this be a warning, instead?
+
+ // t = EmptyTransformRcPtr(new EmptyTransform(), &deleter);
+ std::ostringstream os;
+ os << "Unsupported transform type !<" << type << "> in OCIO profile. ";
+ os << " (line ";
+ os << (node.GetMark().line+1) << ", column "; // (yaml line numbers start at 0)
+ os << node.GetMark().column << ")";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t)
+ {
+ if(ConstAllocationTransformRcPtr Allocation_tran = \
+ DynamicPtrCast<const AllocationTransform>(t))
+ out << Allocation_tran;
+ else if(ConstCDLTransformRcPtr CDL_tran = \
+ DynamicPtrCast<const CDLTransform>(t))
+ out << CDL_tran;
+ else if(ConstColorSpaceTransformRcPtr ColorSpace_tran = \
+ DynamicPtrCast<const ColorSpaceTransform>(t))
+ out << ColorSpace_tran;
+ else if(ConstExponentTransformRcPtr Exponent_tran = \
+ DynamicPtrCast<const ExponentTransform>(t))
+ out << Exponent_tran;
+ else if(ConstFileTransformRcPtr File_tran = \
+ DynamicPtrCast<const FileTransform>(t))
+ out << File_tran;
+ else if(ConstGroupTransformRcPtr Group_tran = \
+ DynamicPtrCast<const GroupTransform>(t))
+ out << Group_tran;
+ else if(ConstLogTransformRcPtr Log_tran = \
+ DynamicPtrCast<const LogTransform>(t))
+ out << Log_tran;
+ else if(ConstLookTransformRcPtr Look_tran = \
+ DynamicPtrCast<const LookTransform>(t))
+ out << Look_tran;
+ else if(ConstMatrixTransformRcPtr Matrix_tran = \
+ DynamicPtrCast<const MatrixTransform>(t))
+ out << Matrix_tran;
+ else if(ConstTruelightTransformRcPtr Truelight_tran = \
+ DynamicPtrCast<const TruelightTransform>(t))
+ out << Truelight_tran;
+ else
+ throw Exception("Unsupported Transform() type for serialization.");
+
+ return out;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Transforms
+
+ void operator >> (const YAML::Node& node, GroupTransformRcPtr& t)
+ {
+ t = GroupTransform::Create();
+
+ std::string key;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "children")
+ {
+ const YAML::Node & children = iter.second();
+ for(unsigned i = 0; i <children.size(); ++i)
+ {
+ TransformRcPtr childTransform;
+ children[i].Read<TransformRcPtr>(childTransform);
+
+ // TODO: consider the forwards-compatibility implication of
+ // throwing an exception. Should this be a warning, instead?
+ if(!childTransform)
+ {
+ throw Exception("Child transform could not be parsed.");
+ }
+
+ t->push_back(childTransform);
+ }
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("GroupTransform");
+ out << YAML::BeginMap;
+ EmitBaseTransformKeyValues(out, t);
+
+ out << YAML::Key << "children";
+ out << YAML::Value;
+
+ out << YAML::BeginSeq;
+ for(int i = 0; i < t->size(); ++i)
+ {
+ out << t->getTransform(i);
+ }
+ out << YAML::EndSeq;
+
+ out << YAML::EndMap;
+
+ return out;
+ }
+
+
+
+ void operator >> (const YAML::Node& node, FileTransformRcPtr& t)
+ {
+ t = FileTransform::Create();
+
+ std::string key, stringval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "src")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setSrc(stringval.c_str());
+ }
+ else if(key == "cccid")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setCCCId(stringval.c_str());
+ }
+ else if(key == "interpolation")
+ {
+ Interpolation val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<Interpolation>(val))
+ t->setInterpolation(val);
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("FileTransform");
+ out << YAML::Flow << YAML::BeginMap;
+ out << YAML::Key << "src" << YAML::Value << t->getSrc();
+ const char * cccid = t->getCCCId();
+ if(cccid && *cccid)
+ {
+ out << YAML::Key << "cccid" << YAML::Value << t->getCCCId();
+ }
+ out << YAML::Key << "interpolation";
+ out << YAML::Value << t->getInterpolation();
+
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t)
+ {
+ t = ColorSpaceTransform::Create();
+
+ std::string key, stringval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "src")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setSrc(stringval.c_str());
+ }
+ else if(key == "dst")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setDst(stringval.c_str());
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("ColorSpaceTransform");
+ out << YAML::Flow << YAML::BeginMap;
+ out << YAML::Key << "src" << YAML::Value << t->getSrc();
+ out << YAML::Key << "dst" << YAML::Value << t->getDst();
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, LookTransformRcPtr& t)
+ {
+ t = LookTransform::Create();
+
+ std::string key, stringval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "src")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setSrc(stringval.c_str());
+ }
+ else if(key == "dst")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setDst(stringval.c_str());
+ }
+ else if(key == "looks")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setLooks(stringval.c_str());
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("LookTransform");
+ out << YAML::Flow << YAML::BeginMap;
+ out << YAML::Key << "src" << YAML::Value << t->getSrc();
+ out << YAML::Key << "dst" << YAML::Value << t->getDst();
+ out << YAML::Key << "looks" << YAML::Value << t->getLooks();
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t)
+ {
+ t = ExponentTransform::Create();
+
+ std::string key;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "value")
+ {
+ std::vector<float> val;
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> val;
+ if(val.size() != 4)
+ {
+ std::ostringstream os;
+ os << "ExponentTransform parse error, value field must be 4 ";
+ os << "floats. Found '" << val.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ t->setValue(&val[0]);
+ }
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("ExponentTransform");
+ out << YAML::Flow << YAML::BeginMap;
+
+ std::vector<float> value(4, 0.0);
+ t->getValue(&value[0]);
+ out << YAML::Key << "value";
+ out << YAML::Value << YAML::Flow << value;
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, LogTransformRcPtr& t)
+ {
+ t = LogTransform::Create();
+
+ std::string key;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "base")
+ {
+ float val = 0.0f;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<float>(val))
+ t->setBase(val);
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("LogTransform");
+ out << YAML::Flow << YAML::BeginMap;
+ out << YAML::Key << "base" << YAML::Value << t->getBase();
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t)
+ {
+ t = MatrixTransform::Create();
+
+ std::string key;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "matrix")
+ {
+ std::vector<float> val;
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> val;
+ if(val.size() != 16)
+ {
+ std::ostringstream os;
+ os << "MatrixTransform parse error, matrix field must be 16 ";
+ os << "floats. Found '" << val.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ t->setMatrix(&val[0]);
+ }
+ }
+ else if(key == "offset")
+ {
+ std::vector<float> val;
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> val;
+ if(val.size() != 4)
+ {
+ std::ostringstream os;
+ os << "MatrixTransform parse error, offset field must be 4 ";
+ os << "floats. Found '" << val.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ t->setOffset(&val[0]);
+ }
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("MatrixTransform");
+ out << YAML::Flow << YAML::BeginMap;
+
+ std::vector<float> matrix(16, 0.0);
+ t->getMatrix(&matrix[0]);
+ if(!IsM44Identity(&matrix[0]))
+ {
+ out << YAML::Key << "matrix";
+ out << YAML::Value << YAML::Flow << matrix;
+ }
+
+ std::vector<float> offset(4, 0.0);
+ t->getOffset(&offset[0]);
+ if(!IsVecEqualToZero(&offset[0],4))
+ {
+ out << YAML::Key << "offset";
+ out << YAML::Value << YAML::Flow << offset;
+ }
+
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, CDLTransformRcPtr& t)
+ {
+ t = CDLTransform::Create();
+
+ std::string key;
+ std::vector<float> floatvecval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "slope")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> floatvecval;
+ if(floatvecval.size() != 3)
+ {
+ std::ostringstream os;
+ os << "CDLTransform parse error, 'slope' field must be 3 ";
+ os << "floats. Found '" << floatvecval.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ t->setSlope(&floatvecval[0]);
+ }
+ }
+ else if(key == "offset")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> floatvecval;
+ if(floatvecval.size() != 3)
+ {
+ std::ostringstream os;
+ os << "CDLTransform parse error, 'offset' field must be 3 ";
+ os << "floats. Found '" << floatvecval.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ t->setOffset(&floatvecval[0]);
+ }
+ }
+ else if(key == "power")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> floatvecval;
+ if(floatvecval.size() != 3)
+ {
+ std::ostringstream os;
+ os << "CDLTransform parse error, 'power' field must be 3 ";
+ os << "floats. Found '" << floatvecval.size() << "'.";
+ throw Exception(os.str().c_str());
+ }
+ t->setPower(&floatvecval[0]);
+ }
+ }
+ else if(key == "saturation" || key == "sat")
+ {
+ float val = 0.0f;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<float>(val))
+ t->setSat(val);
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("CDLTransform");
+ out << YAML::Flow << YAML::BeginMap;
+
+ std::vector<float> slope(3);
+ t->getSlope(&slope[0]);
+ if(!IsVecEqualToOne(&slope[0], 3))
+ {
+ out << YAML::Key << "slope";
+ out << YAML::Value << YAML::Flow << slope;
+ }
+
+ std::vector<float> offset(3);
+ t->getOffset(&offset[0]);
+ if(!IsVecEqualToZero(&offset[0], 3))
+ {
+ out << YAML::Key << "offset";
+ out << YAML::Value << YAML::Flow << offset;
+ }
+
+ std::vector<float> power(3);
+ t->getPower(&power[0]);
+ if(!IsVecEqualToOne(&power[0], 3))
+ {
+ out << YAML::Key << "power";
+ out << YAML::Value << YAML::Flow << power;
+ }
+
+ if(!IsScalarEqualToOne(t->getSat()))
+ {
+ out << YAML::Key << "sat" << YAML::Value << t->getSat();
+ }
+
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t)
+ {
+ t = AllocationTransform::Create();
+
+ std::string key;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "allocation")
+ {
+ Allocation val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<Allocation>(val))
+ t->setAllocation(val);
+ }
+ else if(key == "vars")
+ {
+ std::vector<float> val;
+ if (iter.second().Type() != YAML::NodeType::Null)
+ {
+ iter.second() >> val;
+ if(!val.empty())
+ {
+ t->setVars(static_cast<int>(val.size()), &val[0]);
+ }
+ }
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t)
+ {
+ out << YAML::VerbatimTag("AllocationTransform");
+ out << YAML::Flow << YAML::BeginMap;
+
+ out << YAML::Key << "allocation";
+ out << YAML::Value << YAML::Flow << t->getAllocation();
+
+ if(t->getNumVars() > 0)
+ {
+ std::vector<float> vars(t->getNumVars());
+ t->getVars(&vars[0]);
+ out << YAML::Key << "vars";
+ out << YAML::Flow << YAML::Value << vars;
+ }
+
+ EmitBaseTransformKeyValues(out, t);
+ out << YAML::EndMap;
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t)
+ {
+ t = TruelightTransform::Create();
+
+ std::string key, stringval;
+
+ for (YAML::Iterator iter = node.begin();
+ iter != node.end();
+ ++iter)
+ {
+ iter.first() >> key;
+
+ if(key == "config_root")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setConfigRoot(stringval.c_str());
+ }
+ else if(key == "profile")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setProfile(stringval.c_str());
+ }
+ else if(key == "camera")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setCamera(stringval.c_str());
+ }
+ else if(key == "input_display")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setInputDisplay(stringval.c_str());
+ }
+ else if(key == "recorder")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setRecorder(stringval.c_str());
+ }
+ else if(key == "print")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setPrint(stringval.c_str());
+ }
+ else if(key == "lamp")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setLamp(stringval.c_str());
+ }
+ else if(key == "output_camera")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setOutputCamera(stringval.c_str());
+ }
+ else if(key == "display")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setDisplay(stringval.c_str());
+ }
+ else if(key == "cube_input")
+ {
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<std::string>(stringval))
+ t->setCubeInput(stringval.c_str());
+ }
+ else if(key == "direction")
+ {
+ TransformDirection val;
+ if (iter.second().Type() != YAML::NodeType::Null &&
+ iter.second().Read<TransformDirection>(val))
+ t->setDirection(val);
+ }
+ else
+ {
+ LogUnknownKeyWarning(node.Tag(), iter.first());
+ }
+ }
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t)
+ {
+
+ out << YAML::VerbatimTag("TruelightTransform");
+ out << YAML::Flow << YAML::BeginMap;
+ if(strcmp(t->getConfigRoot(), "") != 0)
+ {
+ out << YAML::Key << "config_root";
+ out << YAML::Value << YAML::Flow << t->getConfigRoot();
+ }
+ if(strcmp(t->getProfile(), "") != 0)
+ {
+ out << YAML::Key << "profile";
+ out << YAML::Value << YAML::Flow << t->getProfile();
+ }
+ if(strcmp(t->getCamera(), "") != 0)
+ {
+ out << YAML::Key << "camera";
+ out << YAML::Value << YAML::Flow << t->getCamera();
+ }
+ if(strcmp(t->getInputDisplay(), "") != 0)
+ {
+ out << YAML::Key << "input_display";
+ out << YAML::Value << YAML::Flow << t->getInputDisplay();
+ }
+ if(strcmp(t->getRecorder(), "") != 0)
+ {
+ out << YAML::Key << "recorder";
+ out << YAML::Value << YAML::Flow << t->getRecorder();
+ }
+ if(strcmp(t->getPrint(), "") != 0)
+ {
+ out << YAML::Key << "print";
+ out << YAML::Value << YAML::Flow << t->getPrint();
+ }
+ if(strcmp(t->getLamp(), "") != 0)
+ {
+ out << YAML::Key << "lamp";
+ out << YAML::Value << YAML::Flow << t->getLamp();
+ }
+ if(strcmp(t->getOutputCamera(), "") != 0)
+ {
+ out << YAML::Key << "output_camera";
+ out << YAML::Value << YAML::Flow << t->getOutputCamera();
+ }
+ if(strcmp(t->getDisplay(), "") != 0)
+ {
+ out << YAML::Key << "display";
+ out << YAML::Value << YAML::Flow << t->getDisplay();
+ }
+ if(strcmp(t->getCubeInput(), "") != 0)
+ {
+ out << YAML::Key << "cube_input";
+ out << YAML::Value << YAML::Flow << t->getCubeInput();
+ }
+
+ EmitBaseTransformKeyValues(out, t);
+
+ out << YAML::EndMap;
+ return out;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Enums
+
+ YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth) {
+ out << BitDepthToString(depth);
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, BitDepth& depth) {
+ std::string str;
+ node.Read<std::string>(str);
+ depth = BitDepthFromString(str.c_str());
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc) {
+ out << AllocationToString(alloc);
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, Allocation& alloc) {
+ std::string str;
+ node.Read<std::string>(str);
+ alloc = AllocationFromString(str.c_str());
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir) {
+ out << ColorSpaceDirectionToString(dir);
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, ColorSpaceDirection& dir) {
+ std::string str;
+ node.Read<std::string>(str);
+ dir = ColorSpaceDirectionFromString(str.c_str());
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir) {
+ out << TransformDirectionToString(dir);
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, TransformDirection& dir) {
+ std::string str;
+ node.Read<std::string>(str);
+ dir = TransformDirectionFromString(str.c_str());
+ }
+
+ YAML::Emitter& operator << (YAML::Emitter& out, Interpolation interp) {
+ out << InterpolationToString(interp);
+ return out;
+ }
+
+ void operator >> (const YAML::Node& node, Interpolation& interp) {
+ std::string str;
+ node.Read<std::string>(str);
+ interp = InterpolationFromString(str.c_str());
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/OCIOYaml.h b/src/core/OCIOYaml.h
new file mode 100644
index 0000000..7104123
--- /dev/null
+++ b/src/core/OCIOYaml.h
@@ -0,0 +1,125 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Platform.h"
+
+#ifndef WINDOWS
+
+// fwd declare yaml-cpp visibility
+#pragma GCC visibility push(hidden)
+namespace YAML {
+ class Exception;
+ class BadDereference;
+ class RepresentationException;
+ class EmitterException;
+ class ParserException;
+ class InvalidScalar;
+ class KeyNotFound;
+ template <typename T> class TypedKeyNotFound;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpace>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::Config>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::Exception>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::GpuShaderDesc>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::ImageDesc>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::Look>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::Processor>;
+
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::Transform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::AllocationTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::CDLTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::ColorSpaceTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::DisplayTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::ExponentTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::FileTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::GroupTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::LogTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::LookTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::MatrixTransform>;
+ template <> class TypedKeyNotFound<OCIO_NAMESPACE::TruelightTransform>;
+}
+#pragma GCC visibility pop
+
+#endif
+
+#include <yaml-cpp/yaml.h>
+
+#ifndef INCLUDED_OCIO_YAML_H
+#define INCLUDED_OCIO_YAML_H
+
+OCIO_NAMESPACE_ENTER
+{
+
+ // Core
+ OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceRcPtr& cs);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceRcPtr cs);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, GroupTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstGroupTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, TransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, LookRcPtr& cs);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, LookRcPtr cs);
+
+ // Transforms
+ OCIOHIDDEN void operator >> (const YAML::Node& node, AllocationTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstAllocationTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, CDLTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstCDLTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstColorSpaceTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, ExponentTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstExponentTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, FileTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstFileTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, LogTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstLogTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, LookTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstLookTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, MatrixTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstMatrixTransformRcPtr t);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, TruelightTransformRcPtr& t);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ConstTruelightTransformRcPtr t);
+
+ // Enums
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, BitDepth depth);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, BitDepth& depth);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, Allocation alloc);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, Allocation& alloc);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, ColorSpaceDirection dir);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, ColorSpaceDirection& dir);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, TransformDirection dir);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, TransformDirection& dir);
+ OCIOHIDDEN YAML::Emitter& operator << (YAML::Emitter& out, Interpolation iterp);
+ OCIOHIDDEN void operator >> (const YAML::Node& node, Interpolation& iterp);
+
+ void LogUnknownKeyWarning(const std::string & name, const YAML::Node& tag);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif // INCLUDED_OCIO_YAML_H
diff --git a/src/core/Op.cpp b/src/core/Op.cpp
new file mode 100644
index 0000000..e4e9da2
--- /dev/null
+++ b/src/core/Op.cpp
@@ -0,0 +1,126 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+#include "pystring/pystring.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ Op::~Op()
+ { }
+
+ bool Op::canCombineWith(const OpRcPtr & /*op*/) const
+ {
+ return false;
+ }
+
+ void Op::combineWith(OpRcPtrVec & /*ops*/,
+ const OpRcPtr & /*secondOp*/) const
+ {
+ std::ostringstream os;
+ os << "Op: " << getInfo() << " cannot be combined. ";
+ os << "A type-specific combining function is not defined.";
+ throw Exception(os.str().c_str());
+ }
+
+ std::ostream& operator<< (std::ostream & os, const Op & op)
+ {
+ os << op.getInfo();
+ return os;
+ }
+
+ namespace
+ {
+ const int FLOAT_DECIMALS = 7;
+ }
+
+ std::string AllocationData::getCacheID() const
+ {
+ std::ostringstream os;
+ os.precision(FLOAT_DECIMALS);
+ os << AllocationToString(allocation) << " ";
+
+ for(unsigned int i=0; i<vars.size(); ++i)
+ {
+ os << vars[i] << " ";
+ }
+
+ return os.str();
+ }
+
+ std::ostream& operator<< (std::ostream & os, const AllocationData & allocation)
+ {
+ os << allocation.getCacheID();
+ return os;
+ }
+
+ std::string SerializeOpVec(const OpRcPtrVec & ops, int indent)
+ {
+ std::ostringstream os;
+
+ for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ os << pystring::mul(" ", indent);
+ os << "Op " << i << ": " << *ops[i] << " ";
+ os << ops[i]->getCacheID() << " supports_gpu:" << ops[i]->supportsGpuShader();
+ os << "\n";
+ }
+
+ return os.str();
+ }
+
+ bool IsOpVecNoOp(const OpRcPtrVec & ops)
+ {
+ for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ if(!ops[i]->isNoOp()) return false;
+ }
+
+ return true;
+ }
+
+ void FinalizeOpVec(OpRcPtrVec & ops, bool optimize)
+ {
+ // TODO: Add envvar to force disable optimizations
+
+ if(optimize)
+ {
+ OptimizeOpVec(ops);
+ }
+
+ for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i)
+ {
+ ops[i]->finalize();
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Op.h b/src/core/Op.h
new file mode 100644
index 0000000..831c072
--- /dev/null
+++ b/src/core/Op.h
@@ -0,0 +1,136 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_OP_H
+#define INCLUDED_OCIO_OP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <sstream>
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ struct AllocationData
+ {
+ Allocation allocation;
+ std::vector<float> vars;
+
+ AllocationData():
+ allocation(ALLOCATION_UNIFORM)
+ {};
+
+ std::string getCacheID() const;
+ };
+
+ std::ostream& operator<< (std::ostream&, const AllocationData&);
+
+ class Op;
+ typedef OCIO_SHARED_PTR<Op> OpRcPtr;
+ typedef std::vector<OpRcPtr> OpRcPtrVec;
+
+ std::string SerializeOpVec(const OpRcPtrVec & ops, int indent=0);
+ bool IsOpVecNoOp(const OpRcPtrVec & ops);
+
+ void FinalizeOpVec(OpRcPtrVec & opVec, bool optimize=true);
+
+ void OptimizeOpVec(OpRcPtrVec & result);
+
+ class Op
+ {
+ public:
+ virtual ~Op();
+
+ virtual OpRcPtr clone() const = 0;
+
+ //! Something short, and printable.
+ // The type of stuff you'd want to see in debugging.
+ virtual std::string getInfo() const = 0;
+
+ //! This should yield a string of not unreasonable length.
+ //! It can only be called after finalize()
+ virtual std::string getCacheID() const = 0;
+
+ //! Is the processing a noop? I.e, does apply do nothing.
+ //! (Even no-ops may define Allocation though.)
+ //! This must be implmented in a manner where its valid to call
+ //! *prior* to finalize. (Optimizers may make use of it)
+ virtual bool isNoOp() const = 0;
+
+ virtual bool isSameType(const OpRcPtr & op) const = 0;
+
+ virtual bool isInverse(const OpRcPtr & op) const = 0;
+
+ virtual bool canCombineWith(const OpRcPtr & op) const;
+
+ // Return a vector of result ops, which correspond to
+ // THIS combinedWith secondOp.
+ //
+ // If the result is a noOp, it is valid for the resulting opsVec
+ // to be empty.
+
+ virtual void combineWith(OpRcPtrVec & ops, const OpRcPtr & secondOp) const;
+
+ virtual bool hasChannelCrosstalk() const = 0;
+
+ virtual void dumpMetadata(ProcessorMetadataRcPtr & /*metadata*/) const
+ { }
+
+ // This is called a single time after construction.
+ // Final pre-processing and safety checks should happen here,
+ // rather than in the constructor.
+
+ virtual void finalize() = 0;
+
+ // Render the specified pixels.
+ //
+ // This must be safe to call in a multi-threaded context.
+ // Ops that have mutable data internally, or rely on external
+ // caching, must thus be appropriately mutexed.
+
+ virtual void apply(float* rgbaBuffer, long numPixels) const = 0;
+
+
+ //! Does this op support gpu shader text generation
+ virtual bool supportsGpuShader() const = 0;
+
+ // TODO: If temp variables are ever needed, also pass tempvar prefix.
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const = 0;
+
+ private:
+ Op& operator= (const Op &);
+ };
+
+ std::ostream& operator<< (std::ostream&, const Op&);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/OpBuilders.h b/src/core/OpBuilders.h
new file mode 100644
index 0000000..f981478
--- /dev/null
+++ b/src/core/OpBuilders.h
@@ -0,0 +1,125 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_OPBUILDERS_H
+#define INCLUDED_OCIO_OPBUILDERS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+#include "LookParse.h"
+#include "PrivateTypes.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ void BuildOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstTransformRcPtr & transform,
+ TransformDirection dir);
+
+
+ ////////////////////////////////////////////////////////////////////////
+
+ void BuildAllocationOps(OpRcPtrVec & ops,
+ const Config & config,
+ const AllocationTransform & transform,
+ TransformDirection dir);
+
+ void BuildCDLOps(OpRcPtrVec & ops,
+ const Config & config,
+ const CDLTransform & transform,
+ TransformDirection dir);
+
+ void BuildColorSpaceOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const ColorSpaceTransform & transform,
+ TransformDirection dir);
+
+ void BuildColorSpaceOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstColorSpaceRcPtr & srcColorSpace,
+ const ConstColorSpaceRcPtr & dstColorSpace);
+
+ void BuildDisplayOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const DisplayTransform & transform,
+ TransformDirection dir);
+
+ void BuildExponentOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ExponentTransform & transform,
+ TransformDirection dir);
+
+ void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const FileTransform & transform,
+ TransformDirection dir);
+
+ void BuildGroupOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const GroupTransform & transform,
+ TransformDirection dir);
+
+ void BuildLogOps(OpRcPtrVec & ops,
+ const Config& config,
+ const LogTransform& transform,
+ TransformDirection dir);
+
+ void BuildLookOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const LookTransform & lookTransform,
+ TransformDirection dir);
+
+ void BuildLookOps(OpRcPtrVec & ops,
+ ConstColorSpaceRcPtr & currentColorSpace,
+ bool skipColorSpaceConversions,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ const LookParseResult & looks);
+
+ void BuildMatrixOps(OpRcPtrVec & ops,
+ const Config& config,
+ const MatrixTransform & transform,
+ TransformDirection dir);
+
+ void BuildTruelightOps(OpRcPtrVec & ops,
+ const Config & config,
+ const TruelightTransform & transform,
+ TransformDirection dir);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/OpOptimizers.cpp b/src/core/OpOptimizers.cpp
new file mode 100644
index 0000000..6e975eb
--- /dev/null
+++ b/src/core/OpOptimizers.cpp
@@ -0,0 +1,364 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Logging.h"
+#include "Op.h"
+
+#include <iterator>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const int MAX_OPTIMIZATION_PASSES = 8;
+
+ int RemoveNoOps(OpRcPtrVec & opVec)
+ {
+ int count = 0;
+
+ OpRcPtrVec::iterator iter = opVec.begin();
+ while(iter != opVec.end())
+ {
+ if((*iter)->isNoOp())
+ {
+ iter = opVec.erase(iter);
+ ++count;
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ return count;
+ }
+
+ int RemoveInverseOps(OpRcPtrVec & opVec)
+ {
+ int count = 0;
+ int firstindex = 0; // this must be a signed int
+
+ while(firstindex < static_cast<int>(opVec.size()-1))
+ {
+ const OpRcPtr & first = opVec[firstindex];
+ const OpRcPtr & second = opVec[firstindex+1];
+
+ // The common case of inverse ops is to have a deep nesting:
+ // ..., A, B, B', A', ...
+ //
+ // Consider the above, when firstindex reaches B:
+ //
+ // |
+ // ..., A, B, B', A', ...
+ //
+ // We will remove B and B'.
+ // Firstindex remains pointing at the original location:
+ //
+ // |
+ // ..., A, A', ...
+ //
+ // We then decrement firstindex by 1,
+ // to backstep and reconsider the A, A' case:
+ //
+ // | <-- firstindex decremented
+ // ..., A, A', ...
+ //
+
+ if(first->isSameType(second) && first->isInverse(second))
+ {
+ opVec.erase(opVec.begin() + firstindex,
+ opVec.begin() + firstindex + 2);
+ ++count;
+
+ firstindex = std::max(0, firstindex-1);
+ }
+ else
+ {
+ ++firstindex;
+ }
+ }
+
+ return count;
+ }
+
+ int CombineOps(OpRcPtrVec & opVec)
+ {
+ int count = 0;
+ int firstindex = 0; // this must be a signed int
+
+ OpRcPtrVec tmpops;
+
+ while(firstindex < static_cast<int>(opVec.size()-1))
+ {
+ const OpRcPtr & first = opVec[firstindex];
+ const OpRcPtr & second = opVec[firstindex+1];
+
+ if(first->canCombineWith(second))
+ {
+ tmpops.clear();
+ first->combineWith(tmpops, second);
+
+ // tmpops may have any number of ops in it. (0, 1, 2, ...)
+ // (size 0 would occur potentially iff the combination
+ // results in a no-op)
+ //
+ // No matter the number, we need to swap them in for the
+ // original ops
+
+ // Erase the initial two ops we've combined
+ opVec.erase(opVec.begin() + firstindex,
+ opVec.begin() + firstindex + 2);
+
+ // Insert the new ops (which may be empty) at
+ // this location
+ std::copy(tmpops.begin(), tmpops.end(),
+ std::inserter(opVec, opVec.begin() + firstindex));
+
+ // Decrement firstindex by 1,
+ // to backstep and reconsider the A, A' case.
+ // See RemoveInverseOps for the full discussion of
+ // why this is appropriate
+ firstindex = std::max(0, firstindex-1);
+
+ // We've done something so increment the count!
+ ++count;
+ }
+ else
+ {
+ ++firstindex;
+ }
+ }
+
+ return count;
+ }
+ }
+
+ void OptimizeOpVec(OpRcPtrVec & ops)
+ {
+ if(ops.empty()) return;
+
+
+ if(IsDebugLoggingEnabled())
+ {
+ LogDebug("Optimizing Op Vec...");
+ LogDebug(SerializeOpVec(ops, 4));
+ }
+
+ OpRcPtrVec::size_type originalSize = ops.size();
+ int total_noops = 0;
+ int total_inverseops = 0;
+ int total_combines = 0;
+ int passes = 0;
+
+ while(passes<=MAX_OPTIMIZATION_PASSES)
+ {
+ int noops = RemoveNoOps(ops);
+ int inverseops = RemoveInverseOps(ops);
+ int combines = CombineOps(ops);
+
+ if(noops == 0 && inverseops==0 && combines==0)
+ {
+ // No optimization progress was made, so stop trying.
+ break;
+ }
+
+ total_noops += noops;
+ total_inverseops += inverseops;
+ total_combines += combines;
+
+ ++passes;
+ }
+
+ OpRcPtrVec::size_type finalSize = ops.size();
+
+ if(passes == MAX_OPTIMIZATION_PASSES)
+ {
+ std::ostringstream os;
+ os << "The max number of passes, " << passes << ", ";
+ os << "was reached during optimization. This is likely a sign ";
+ os << "that either the complexity of the color transform is ";
+ os << "very high, or that some internal optimizers are in conflict ";
+ os << "(undo-ing / redo-ing the other's results).";
+ LogDebug(os.str().c_str());
+ }
+
+ if(IsDebugLoggingEnabled())
+ {
+ std::ostringstream os;
+ os << "Optimized ";
+ os << originalSize << "->" << finalSize << ", ";
+ os << passes << " passes, ";
+ os << total_noops << " noops removed, ";
+ os << total_inverseops << " inverse ops removed\n";
+ os << total_combines << " ops combines\n";
+ os << SerializeOpVec(ops, 4);
+ LogDebug(os.str());
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+#include "ExponentOps.h"
+#include "LogOps.h"
+#include "Lut1DOp.h"
+#include "Lut3DOp.h"
+#include "MatrixOps.h"
+
+OIIO_ADD_TEST(OpOptimizers, RemoveInverseOps)
+{
+ OCIO::OpRcPtrVec ops;
+
+ float exp[4] = { 1.2f, 1.3f, 1.4f, 1.5f };
+
+
+ float k[3] = { 0.18f, 0.18f, 0.18f };
+ float m[3] = { 2.0f, 2.0f, 2.0f };
+ float b[3] = { 0.1f, 0.1f, 0.1f };
+ float base[3] = { 10.0f, 10.0f, 10.0f };
+ float kb[3] = { 1.0f, 1.0f, 1.0f };
+
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_INVERSE);
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_INVERSE);
+
+ OIIO_CHECK_EQUAL(ops.size(), 4);
+ OCIO::RemoveInverseOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 0);
+
+
+ ops.clear();
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_INVERSE);
+ OCIO::CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_INVERSE);
+ OCIO::CreateLogOp(ops, k, m, b, base, kb, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 5);
+ OCIO::RemoveInverseOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 1);
+}
+
+
+OIIO_ADD_TEST(OpOptimizers, CombineOps)
+{
+ float m1[4] = { 2.0f, 2.0f, 2.0f, 1.0f };
+ float m2[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
+ float m3[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
+ float m4[4] = { 0.7f, 0.7f, 0.7f, 1.0f };
+
+ float exp[4] = { 1.2f, 1.3f, 1.4f, 1.5f };
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 1);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 1);
+ }
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m3, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 1);
+ }
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m3, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m4, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 3);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 1);
+ }
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m2, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 0);
+ }
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_INVERSE);
+
+ OIIO_CHECK_EQUAL(ops.size(), 2);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 0);
+ }
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+
+ OIIO_CHECK_EQUAL(ops.size(), 5);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 1);
+ }
+
+ {
+ OCIO::OpRcPtrVec ops;
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m1, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateScaleOp(ops, m2, OCIO::TRANSFORM_DIR_FORWARD);
+ OCIO::CreateExponentOp(ops, exp, OCIO::TRANSFORM_DIR_INVERSE);
+
+ OIIO_CHECK_EQUAL(ops.size(), 4);
+ OCIO::CombineOps(ops);
+ OIIO_CHECK_EQUAL(ops.size(), 0);
+ }
+}
+
+#endif // OCIO_UNIT_TEST
diff --git a/src/core/ParseUtils.cpp b/src/core/ParseUtils.cpp
new file mode 100644
index 0000000..9110161
--- /dev/null
+++ b/src/core/ParseUtils.cpp
@@ -0,0 +1,438 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <iostream>
+#include <set>
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "ParseUtils.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ const char * BoolToString(bool val)
+ {
+ if(val) return "true";
+ return "false";
+ }
+
+ bool BoolFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if((str == "true") || (str=="yes")) return true;
+ return false;
+ }
+
+ const char * LoggingLevelToString(LoggingLevel level)
+ {
+ if(level == LOGGING_LEVEL_NONE) return "none";
+ else if(level == LOGGING_LEVEL_WARNING) return "warning";
+ else if(level == LOGGING_LEVEL_INFO) return "info";
+ else if(level == LOGGING_LEVEL_DEBUG) return "debug";
+ return "unknown";
+ }
+
+ LoggingLevel LoggingLevelFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "0" || str == "none") return LOGGING_LEVEL_NONE;
+ else if(str == "1" || str == "warning") return LOGGING_LEVEL_WARNING;
+ else if(str == "2" || str == "info") return LOGGING_LEVEL_INFO;
+ else if(str == "3" || str == "debug") return LOGGING_LEVEL_DEBUG;
+ return LOGGING_LEVEL_UNKNOWN;
+ }
+
+ const char * TransformDirectionToString(TransformDirection dir)
+ {
+ if(dir == TRANSFORM_DIR_FORWARD) return "forward";
+ else if(dir == TRANSFORM_DIR_INVERSE) return "inverse";
+ return "unknown";
+ }
+
+ TransformDirection TransformDirectionFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "forward") return TRANSFORM_DIR_FORWARD;
+ else if(str == "inverse") return TRANSFORM_DIR_INVERSE;
+ return TRANSFORM_DIR_UNKNOWN;
+ }
+
+ TransformDirection CombineTransformDirections(TransformDirection d1,
+ TransformDirection d2)
+ {
+ // Any unknowns always combine to be unknown.
+ if(d1 == TRANSFORM_DIR_UNKNOWN || d2 == TRANSFORM_DIR_UNKNOWN)
+ return TRANSFORM_DIR_UNKNOWN;
+
+ if(d1 == TRANSFORM_DIR_FORWARD && d2 == TRANSFORM_DIR_FORWARD)
+ return TRANSFORM_DIR_FORWARD;
+
+ if(d1 == TRANSFORM_DIR_INVERSE && d2 == TRANSFORM_DIR_INVERSE)
+ return TRANSFORM_DIR_FORWARD;
+
+ return TRANSFORM_DIR_INVERSE;
+ }
+
+ TransformDirection GetInverseTransformDirection(TransformDirection dir)
+ {
+ if(dir == TRANSFORM_DIR_FORWARD) return TRANSFORM_DIR_INVERSE;
+ else if(dir == TRANSFORM_DIR_INVERSE) return TRANSFORM_DIR_FORWARD;
+ return TRANSFORM_DIR_UNKNOWN;
+ }
+
+ const char * ColorSpaceDirectionToString(ColorSpaceDirection dir)
+ {
+ if(dir == COLORSPACE_DIR_TO_REFERENCE) return "to_reference";
+ else if(dir == COLORSPACE_DIR_FROM_REFERENCE) return "from_reference";
+ return "unknown";
+ }
+
+ ColorSpaceDirection ColorSpaceDirectionFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "to_reference") return COLORSPACE_DIR_TO_REFERENCE;
+ else if(str == "from_reference") return COLORSPACE_DIR_FROM_REFERENCE;
+ return COLORSPACE_DIR_UNKNOWN;
+ }
+
+ const char * BitDepthToString(BitDepth bitDepth)
+ {
+ if(bitDepth == BIT_DEPTH_UINT8) return "8ui";
+ else if(bitDepth == BIT_DEPTH_UINT10) return "10ui";
+ else if(bitDepth == BIT_DEPTH_UINT12) return "12ui";
+ else if(bitDepth == BIT_DEPTH_UINT14) return "14ui";
+ else if(bitDepth == BIT_DEPTH_UINT16) return "16ui";
+ else if(bitDepth == BIT_DEPTH_UINT32) return "32ui";
+ else if(bitDepth == BIT_DEPTH_F16) return "16f";
+ else if(bitDepth == BIT_DEPTH_F32) return "32f";
+ return "unknown";
+ }
+
+ BitDepth BitDepthFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "8ui") return BIT_DEPTH_UINT8;
+ else if(str == "10ui") return BIT_DEPTH_UINT10;
+ else if(str == "12ui") return BIT_DEPTH_UINT12;
+ else if(str == "14ui") return BIT_DEPTH_UINT14;
+ else if(str == "16ui") return BIT_DEPTH_UINT16;
+ else if(str == "32ui") return BIT_DEPTH_UINT32;
+ else if(str == "16f") return BIT_DEPTH_F16;
+ else if(str == "32f") return BIT_DEPTH_F32;
+ return BIT_DEPTH_UNKNOWN;
+ }
+
+ bool BitDepthIsFloat(BitDepth bitDepth)
+ {
+ if(bitDepth == BIT_DEPTH_F16) return true;
+ else if(bitDepth == BIT_DEPTH_F32) return true;
+ return false;
+ }
+
+ int BitDepthToInt(BitDepth bitDepth)
+ {
+ if(bitDepth == BIT_DEPTH_UINT8) return 8;
+ else if(bitDepth == BIT_DEPTH_UINT10) return 10;
+ else if(bitDepth == BIT_DEPTH_UINT12) return 12;
+ else if(bitDepth == BIT_DEPTH_UINT14) return 14;
+ else if(bitDepth == BIT_DEPTH_UINT16) return 16;
+ else if(bitDepth == BIT_DEPTH_UINT32) return 32;
+
+ return 0;
+ }
+
+ const char * AllocationToString(Allocation alloc)
+ {
+ if(alloc == ALLOCATION_UNIFORM) return "uniform";
+ else if(alloc == ALLOCATION_LG2) return "lg2";
+ return "unknown";
+ }
+
+ Allocation AllocationFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "uniform") return ALLOCATION_UNIFORM;
+ else if(str == "lg2") return ALLOCATION_LG2;
+ return ALLOCATION_UNKNOWN;
+ }
+
+ const char * InterpolationToString(Interpolation interp)
+ {
+ if(interp == INTERP_NEAREST) return "nearest";
+ else if(interp == INTERP_LINEAR) return "linear";
+ else if(interp == INTERP_TETRAHEDRAL) return "tetrahedral";
+ else if(interp == INTERP_BEST) return "best";
+ return "unknown";
+ }
+
+ Interpolation InterpolationFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "nearest") return INTERP_NEAREST;
+ else if(str == "linear") return INTERP_LINEAR;
+ else if(str == "tetrahedral") return INTERP_TETRAHEDRAL;
+ else if(str == "best") return INTERP_BEST;
+ return INTERP_UNKNOWN;
+ }
+
+ const char * GpuLanguageToString(GpuLanguage language)
+ {
+ if(language == GPU_LANGUAGE_CG) return "cg";
+ else if(language == GPU_LANGUAGE_GLSL_1_0) return "glsl_1.0";
+ else if(language == GPU_LANGUAGE_GLSL_1_3) return "glsl_1.3";
+ return "unknown";
+ }
+
+ GpuLanguage GpuLanguageFromString(const char * s)
+ {
+ std::string str = pystring::lower(s);
+ if(str == "cg") return GPU_LANGUAGE_CG;
+ else if(str == "glsl_1.0") return GPU_LANGUAGE_GLSL_1_0;
+ else if(str == "glsl_1.3") return GPU_LANGUAGE_GLSL_1_3;
+ return GPU_LANGUAGE_UNKNOWN;
+ }
+
+
+ const char * ROLE_DEFAULT = "default";
+ const char * ROLE_REFERENCE = "reference";
+ const char * ROLE_DATA = "data";
+ const char * ROLE_COLOR_PICKING = "color_picking";
+ const char * ROLE_SCENE_LINEAR = "scene_linear";
+ const char * ROLE_COMPOSITING_LOG = "compositing_log";
+ const char * ROLE_COLOR_TIMING = "color_timing";
+ const char * ROLE_TEXTURE_PAINT = "texture_paint";
+ const char * ROLE_MATTE_PAINT = "matte_paint";
+
+ namespace
+ {
+ const int FLOAT_DECIMALS = 7;
+ const int DOUBLE_DECIMALS = 16;
+ }
+
+ std::string FloatToString(float value)
+ {
+ std::ostringstream pretty;
+ pretty.precision(FLOAT_DECIMALS);
+ pretty << value;
+ return pretty.str();
+ }
+
+ std::string FloatVecToString(const float * fval, unsigned int size)
+ {
+ if(size<=0) return "";
+
+ std::ostringstream pretty;
+ pretty.precision(FLOAT_DECIMALS);
+ for(unsigned int i=0; i<size; ++i)
+ {
+ if(i!=0) pretty << " ";
+ pretty << fval[i];
+ }
+
+ return pretty.str();
+ }
+
+ bool StringToFloat(float * fval, const char * str)
+ {
+ if(!str) return false;
+
+ std::istringstream inputStringstream(str);
+ float x;
+ if(!(inputStringstream >> x))
+ {
+ return false;
+ }
+
+ if(fval) *fval = x;
+ return true;
+ }
+
+ bool StringToInt(int * ival, const char * str)
+ {
+ if(!str) return false;
+
+ std::istringstream inputStringstream(str);
+ int x;
+ if(!(inputStringstream >> x))
+ {
+ return false;
+ }
+
+ if(ival) *ival = x;
+ return true;
+ }
+
+
+ std::string DoubleToString(double value)
+ {
+ std::ostringstream pretty;
+ pretty.precision(DOUBLE_DECIMALS);
+ pretty << value;
+ return pretty.str();
+ }
+
+
+ bool StringVecToFloatVec(std::vector<float> &floatArray,
+ const std::vector<std::string> &lineParts)
+ {
+ floatArray.resize(lineParts.size());
+
+ for(unsigned int i=0; i<lineParts.size(); i++)
+ {
+ std::istringstream inputStringstream(lineParts[i]);
+ float x;
+ if(!(inputStringstream >> x))
+ {
+ return false;
+ }
+ floatArray[i] = x;
+ }
+
+ return true;
+ }
+
+
+ bool StringVecToIntVec(std::vector<int> &intArray,
+ const std::vector<std::string> &lineParts)
+ {
+ intArray.resize(lineParts.size());
+
+ for(unsigned int i=0; i<lineParts.size(); i++)
+ {
+ std::istringstream inputStringstream(lineParts[i]);
+ int x;
+ if(!(inputStringstream >> x))
+ {
+ return false;
+ }
+ intArray[i] = x;
+ }
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // read the next non empty line, and store it in 'line'
+ // return 'true' on success
+
+ bool nextline(std::istream &istream, std::string &line)
+ {
+ while ( istream.good() )
+ {
+ std::getline(istream, line);
+ if(!pystring::strip(line).empty())
+ {
+ return true;
+ }
+ }
+
+ line = "";
+ return false;
+ }
+
+
+ bool StrEqualsCaseIgnore(const std::string & a, const std::string & b)
+ {
+ return (pystring::lower(a) == pystring::lower(b));
+ }
+
+ // If a ',' is in the string, split on it
+ // If a ':' is in the string, split on it
+ // Otherwise, assume a single string.
+ // Also, strip whitespace from all parts.
+
+ void SplitStringEnvStyle(std::vector<std::string> & outputvec, const char * str)
+ {
+ if(!str) return;
+
+ std::string s = pystring::strip(str);
+ if(pystring::find(s, ",") > -1)
+ {
+ pystring::split(s, outputvec, ",");
+ }
+ else if(pystring::find(s, ":") > -1)
+ {
+ pystring::split(s, outputvec, ":");
+ }
+ else
+ {
+ outputvec.push_back(s);
+ }
+
+ for(unsigned int i=0; i<outputvec.size(); ++i)
+ {
+ outputvec[i] = pystring::strip(outputvec[i]);
+ }
+ }
+
+ std::string JoinStringEnvStyle(const std::vector<std::string> & outputvec)
+ {
+ return pystring::join(", ", outputvec);
+ }
+
+ // Ordering and capitalization from vec1 is preserved
+ std::vector<std::string> IntersectStringVecsCaseIgnore(const std::vector<std::string> & vec1,
+ const std::vector<std::string> & vec2)
+ {
+ std::vector<std::string> newvec;
+ std::set<std::string> allvalues;
+
+ // Seed the set with all values from vec2
+ for(unsigned int i=0; i<vec2.size(); ++i)
+ {
+ allvalues.insert(pystring::lower(vec2[i]));
+ }
+
+ for(unsigned int i=0; i<vec1.size(); ++i)
+ {
+ std::string key = pystring::lower(vec1[i]);
+ if(allvalues.find(key) != allvalues.end())
+ {
+ newvec.push_back(vec1[i]);
+ }
+ }
+
+ return newvec;
+ }
+
+
+ int FindInStringVecCaseIgnore(const std::vector<std::string> & vec, const std::string & str)
+ {
+ std::string teststr = pystring::lower(str);
+ for(unsigned int i=0; i<vec.size(); ++i)
+ {
+ if(pystring::lower(vec[i]) == teststr) return static_cast<int>(i);
+ }
+
+ return -1;
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ParseUtils.h b/src/core/ParseUtils.h
new file mode 100644
index 0000000..efc07d4
--- /dev/null
+++ b/src/core/ParseUtils.h
@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_PARSEUTILS_H
+#define INCLUDED_OCIO_PARSEUTILS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PrivateTypes.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+
+ std::string FloatToString(float fval);
+ std::string FloatVecToString(const float * fval, unsigned int size);
+
+ std::string DoubleToString(double value);
+
+ bool StringToFloat(float * fval, const char * str);
+ bool StringToInt(int * ival, const char * str);
+
+ bool StringVecToFloatVec(std::vector<float> & floatArray,
+ const std::vector<std::string> & lineParts);
+
+ bool StringVecToIntVec(std::vector<int> & intArray,
+ const std::vector<std::string> & lineParts);
+
+ //////////////////////////////////////////////////////////////////////////
+
+ // read the next non empty line, and store it in 'line'
+ // return 'true' on success
+
+ bool nextline(std::istream &istream, std::string &line);
+
+ bool StrEqualsCaseIgnore(const std::string & a, const std::string & b);
+
+ // If a ',' is in the string, split on it
+ // If a ':' is in the string, split on it
+ // Otherwise, assume a single string.
+ // Also, strip whitespace from all parts.
+
+ void SplitStringEnvStyle(std::vector<std::string> & outputvec, const char * str);
+
+ // Join on ','
+ std::string JoinStringEnvStyle(const std::vector<std::string> & outputvec);
+
+ // Ordering and capitalization from vec1 is preserved
+ std::vector<std::string> IntersectStringVecsCaseIgnore(const std::vector<std::string> & vec1,
+ const std::vector<std::string> & vec2);
+
+ // Find the index of the specified string, ignoring case.
+ // return -1 if not found.
+
+ int FindInStringVecCaseIgnore(const std::vector<std::string> & vec, const std::string & str);
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/PathUtils.cpp b/src/core/PathUtils.cpp
new file mode 100644
index 0000000..a04ecee
--- /dev/null
+++ b/src/core/PathUtils.cpp
@@ -0,0 +1,229 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <limits>
+#include <sstream>
+#include <sys/stat.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Mutex.h"
+#include "PathUtils.h"
+#include "Platform.h"
+#include "pystring/pystring.h"
+
+#if !defined(WINDOWS)
+#include <sys/param.h>
+#else
+#include <direct.h>
+#define MAXPATHLEN 4096
+#endif
+
+#if defined(__APPLE__) && !defined(__IPHONE__)
+#include <crt_externs.h> // _NSGetEnviron()
+#elif !defined(WINDOWS)
+#include <unistd.h>
+extern char **environ;
+#endif
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ typedef std::map<std::string, std::string> StringMap;
+
+ StringMap g_fastFileHashCache;
+ Mutex g_fastFileHashCache_mutex;
+
+ std::string ComputeHash(const std::string & filename)
+ {
+ struct stat results;
+ if (stat(filename.c_str(), &results) == 0)
+ {
+ // Treat the mtime + inode as a proxy for the contents
+ std::ostringstream fasthash;
+ fasthash << results.st_ino << ":";
+ fasthash << results.st_mtime;
+ return fasthash.str();
+ }
+
+ return "";
+ }
+ }
+
+ std::string GetFastFileHash(const std::string & filename)
+ {
+ AutoMutex lock(g_fastFileHashCache_mutex);
+
+ StringMap::iterator iter = g_fastFileHashCache.find(filename);
+ if(iter != g_fastFileHashCache.end())
+ {
+ return iter->second;
+ }
+
+ std::string hash = ComputeHash(filename);
+ g_fastFileHashCache[filename] = hash;
+
+ return hash;
+ }
+
+ bool FileExists(const std::string & filename)
+ {
+ std::string hash = GetFastFileHash(filename);
+ return (!hash.empty());
+ }
+
+ void ClearPathCaches()
+ {
+ AutoMutex lock(g_fastFileHashCache_mutex);
+ g_fastFileHashCache.clear();
+ }
+
+ namespace pystring
+ {
+ namespace os
+ {
+ std::string getcwd()
+ {
+#ifdef WINDOWS
+ char path[MAXPATHLEN];
+ _getcwd(path, MAXPATHLEN);
+ return path;
+#else
+ char path[MAXPATHLEN];
+ ::getcwd(path, MAXPATHLEN);
+ return path;
+#endif
+ }
+
+ namespace path
+ {
+ std::string abspath(const std::string & path)
+ {
+ std::string p = path;
+ if(!isabs(p)) p = join(getcwd(), p);
+ return normpath(p);
+ }
+ } // namespace path
+ } // namespace os
+ }
+
+ namespace
+ {
+ inline char** GetEnviron()
+ {
+#if __IPHONE__
+ // TODO: fix this
+ return NULL;
+#elif __APPLE__
+ return (*_NSGetEnviron());
+#else
+ return environ;
+#endif
+ }
+
+ const int MAX_PATH_LENGTH = 4096;
+ }
+
+ void LoadEnvironment(EnvMap & map)
+ {
+ for (char **env = GetEnviron(); *env != NULL; ++env)
+ {
+ // split environment up into std::map[name] = value
+ std::string env_str = (char*)*env;
+ int pos = static_cast<int>(env_str.find_first_of('='));
+ map.insert(
+ EnvMap::value_type(env_str.substr(0, pos),
+ env_str.substr(pos+1, env_str.length()))
+ );
+ }
+ }
+
+ std::string EnvExpand(const std::string & str, const EnvMap & map)
+ {
+ // Early exit if no magic characters are found.
+ if(pystring::find(str, "$") == -1 &&
+ pystring::find(str, "%") == -1) return str;
+
+ std::string orig = str;
+ std::string newstr = str;
+
+ // This walks through the envmap in key order,
+ // from longest to shortest to handle envvars which are
+ // substrings.
+ // ie. '$TEST_$TESTING_$TE' will expand in this order '2 1 3'
+
+ for (EnvMap::const_iterator iter = map.begin();
+ iter != map.end(); ++iter)
+ {
+ newstr = pystring::replace(newstr,
+ ("${"+iter->first+"}"), iter->second);
+ newstr = pystring::replace(newstr,
+ ("$"+iter->first), iter->second);
+ newstr = pystring::replace(newstr,
+ ("%"+iter->first+"%"), iter->second);
+ }
+
+ // recursively call till string doesn't expand anymore
+ if(newstr != orig)
+ {
+ return EnvExpand(newstr, map);
+ }
+
+ return orig;
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(PathUtils, EnvExpand)
+{
+ // build env by hand for unit test
+ OCIO::EnvMap env_map; // = OCIO::GetEnvMap();
+
+ // add some fake env vars so the test runs
+ env_map.insert(OCIO::EnvMap::value_type("TEST1", "foo.bar"));
+ env_map.insert(OCIO::EnvMap::value_type("TEST1NG", "bar.foo"));
+ env_map.insert(OCIO::EnvMap::value_type("FOO_foo.bar", "cheese"));
+
+ //
+ std::string foo = "/a/b/${TEST1}/${TEST1NG}/$TEST1/$TEST1NG/${FOO_${TEST1}}/";
+ std::string foo_result = "/a/b/foo.bar/bar.foo/foo.bar/bar.foo/cheese/";
+ std::string testresult = OCIO::EnvExpand(foo, env_map);
+ OIIO_CHECK_ASSERT( testresult == foo_result );
+}
+
+#endif // OCIO_BUILD_TESTS
diff --git a/src/core/PathUtils.h b/src/core/PathUtils.h
new file mode 100644
index 0000000..649f52c
--- /dev/null
+++ b/src/core/PathUtils.h
@@ -0,0 +1,95 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_PATHUTILS_H
+#define INCLUDED_OCIO_PATHUTILS_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <map>
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace pystring
+ {
+ namespace os
+ {
+ namespace path
+ {
+ // This is not currently included in pystring, but we need it
+ // So let's define it locally for now
+
+ std::string abspath(const std::string & path);
+ }
+ }
+ }
+
+ // The EnvMap is ordered by the length of the keys (long -> short). This
+ // is so that recursive string expansion will deal with similar prefixed
+ // keys as expected.
+ // ie. '$TEST_$TESTING_$TE' will expand in this order '2 1 3'
+ template <class T>
+ struct EnvMapKey : std::binary_function <T, T, bool>
+ {
+ bool
+ operator() (const T &x, const T &y) const
+ {
+ // If the lengths are unequal, sort by length
+ if(x.length() != y.length())
+ {
+ return (x.length() > y.length());
+ }
+ // Otherwise, use the standard string sort comparison
+ else
+ {
+ return (x<y);
+ }
+ }
+ };
+ typedef std::map< std::string, std::string, EnvMapKey< std::string > > EnvMap;
+
+ // Get map of current env key = value,
+ void LoadEnvironment(EnvMap & map);
+
+ // Expand a string with $VAR, ${VAR} or %VAR% with the keys passed
+ // in the EnvMap.
+ std::string EnvExpand(const std::string & str, const EnvMap & map);
+
+ // Check if a file exists
+ bool FileExists(const std::string & filename);
+
+ // Get a fast hash for a file, without reading all the contents.
+ // Currently, this checks the mtime and the inode number.
+ std::string GetFastFileHash(const std::string & filename);
+
+ void ClearPathCaches();
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/Platform.h b/src/core/Platform.h
new file mode 100644
index 0000000..56d0971
--- /dev/null
+++ b/src/core/Platform.h
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_PLATFORM_H
+#define INCLUDED_OCIO_PLATFORM_H
+
+/*
+PTEX SOFTWARE
+Copyright 2009 Disney Enterprises, Inc. All rights reserved
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
+ Studios" or the names of its contributors may NOT be used to
+ endorse or promote products derived from this software without
+ specific prior written permission from Walt Disney Pictures.
+
+Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
+IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+*/
+
+// platform-specific includes
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+#ifndef WINDOWS
+#define WINDOWS
+#endif
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define NOMINMAX 1
+
+// windows - defined for both Win32 and Win64
+#include <Windows.h>
+#include <malloc.h>
+#include <io.h>
+#include <tchar.h>
+#include <process.h>
+
+#else
+
+// linux/unix/posix
+#include <stdlib.h>
+#include <alloca.h>
+#include <string.h>
+#include <pthread.h>
+// OS for spinlock
+#ifdef __APPLE__
+#include <libkern/OSAtomic.h>
+#include <sys/types.h>
+#endif
+#endif
+
+// general includes
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+
+// missing functions on Windows
+#ifdef WINDOWS
+#define snprintf sprintf_s
+#define strtok_r strtok_s
+typedef __int64 FilePos;
+#define fseeko _fseeki64
+#define ftello _ftelli64
+
+inline double log2(double x) {
+ return log(x) * 1.4426950408889634;
+}
+
+#else
+typedef off_t FilePos;
+#endif
+
+
+OCIO_NAMESPACE_ENTER
+{
+
+// TODO: Add proper endian detection using architecture / compiler mojo
+// In the meantime, hardcode to x86
+#define OCIO_LITTLE_ENDIAN 1 // This is correct on x86
+
+ /*
+ * Mutex/SpinLock classes
+ */
+
+#ifdef WINDOWS
+
+ class _Mutex {
+ public:
+ _Mutex() { _mutex = CreateMutex(NULL, FALSE, NULL); }
+ ~_Mutex() { CloseHandle(_mutex); }
+ void lock() { WaitForSingleObject(_mutex, INFINITE); }
+ void unlock() { ReleaseMutex(_mutex); }
+ private:
+ HANDLE _mutex;
+ };
+
+ class _SpinLock {
+ public:
+ _SpinLock() { InitializeCriticalSection(&_spinlock); }
+ ~_SpinLock() { DeleteCriticalSection(&_spinlock); }
+ void lock() { EnterCriticalSection(&_spinlock); }
+ void unlock() { LeaveCriticalSection(&_spinlock); }
+ private:
+ CRITICAL_SECTION _spinlock;
+ };
+
+#else
+ // assume linux/unix/posix
+
+ class _Mutex {
+ public:
+ _Mutex() { pthread_mutex_init(&_mutex, 0); }
+ ~_Mutex() { pthread_mutex_destroy(&_mutex); }
+ void lock() { pthread_mutex_lock(&_mutex); }
+ void unlock() { pthread_mutex_unlock(&_mutex); }
+ private:
+ pthread_mutex_t _mutex;
+ };
+
+#if __APPLE__
+ class _SpinLock {
+ public:
+ _SpinLock() { _spinlock = 0; }
+ ~_SpinLock() { }
+ void lock() { OSSpinLockLock(&_spinlock); }
+ void unlock() { OSSpinLockUnlock(&_spinlock); }
+ private:
+ OSSpinLock _spinlock;
+ };
+#elif ANDROID
+ // we don't have access to pthread on andriod so we just make an empty
+ // class that does nothing.
+ class _SpinLock {
+ public:
+ _SpinLock() { }
+ ~_SpinLock() { }
+ void lock() { }
+ void unlock() { }
+ };
+#else
+ class _SpinLock {
+ public:
+ _SpinLock() { pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); }
+ ~_SpinLock() { pthread_spin_destroy(&_spinlock); }
+ void lock() { pthread_spin_lock(&_spinlock); }
+ void unlock() { pthread_spin_unlock(&_spinlock); }
+ private:
+ pthread_spinlock_t _spinlock;
+ };
+#endif // __APPLE__
+#endif // WINDOWS
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif // INCLUDED_OCIO_PLATFORM_H
diff --git a/src/core/PrivateTypes.h b/src/core/PrivateTypes.h
new file mode 100644
index 0000000..4f0b1ee
--- /dev/null
+++ b/src/core/PrivateTypes.h
@@ -0,0 +1,54 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_PRIVATE_TYPES_H
+#define INCLUDED_OCIO_PRIVATE_TYPES_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <map>
+#include <set>
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+ // Stl types of OCIO classes
+ typedef std::map<std::string, std::string> StringMap;
+ typedef std::vector<std::string> StringVec;
+ typedef std::set<std::string> StringSet;
+
+ typedef std::vector<ConstTransformRcPtr> ConstTransformVec;
+ typedef std::vector<ColorSpaceRcPtr> ColorSpaceVec;
+ typedef std::vector<LookRcPtr> LookVec;
+
+ typedef std::vector<TransformDirection> TransformDirectionVec;
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/Processor.cpp b/src/core/Processor.cpp
new file mode 100644
index 0000000..06b08d2
--- /dev/null
+++ b/src/core/Processor.cpp
@@ -0,0 +1,640 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "AllocationOp.h"
+#include "GpuShaderUtils.h"
+#include "HashUtils.h"
+#include "Logging.h"
+#include "Lut3DOp.h"
+#include "NoOps.h"
+#include "OpBuilders.h"
+#include "Processor.h"
+#include "ScanlineHelper.h"
+
+#include <algorithm>
+#include <cstring>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+
+ class ProcessorMetadata::Impl
+ {
+ public:
+ StringSet files;
+ StringVec looks;
+
+ Impl()
+ { }
+
+ ~Impl()
+ { }
+ };
+
+ ProcessorMetadataRcPtr ProcessorMetadata::Create()
+ {
+ return ProcessorMetadataRcPtr(new ProcessorMetadata(), &deleter);
+ }
+
+ ProcessorMetadata::ProcessorMetadata()
+ : m_impl(new ProcessorMetadata::Impl)
+ { }
+
+ ProcessorMetadata::~ProcessorMetadata()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ void ProcessorMetadata::deleter(ProcessorMetadata* c)
+ {
+ delete c;
+ }
+
+ int ProcessorMetadata::getNumFiles() const
+ {
+ return static_cast<int>(getImpl()->files.size());
+ }
+
+ const char * ProcessorMetadata::getFile(int index) const
+ {
+ if(index < 0 ||
+ index >= (static_cast<int>(getImpl()->files.size())))
+ {
+ return "";
+ }
+
+ StringSet::const_iterator iter = getImpl()->files.begin();
+ std::advance( iter, index );
+
+ return iter->c_str();
+ }
+
+ void ProcessorMetadata::addFile(const char * fname)
+ {
+ getImpl()->files.insert(fname);
+ }
+
+
+
+ int ProcessorMetadata::getNumLooks() const
+ {
+ return static_cast<int>(getImpl()->looks.size());
+ }
+
+ const char * ProcessorMetadata::getLook(int index) const
+ {
+ if(index < 0 ||
+ index >= (static_cast<int>(getImpl()->looks.size())))
+ {
+ return "";
+ }
+
+ return getImpl()->looks[index].c_str();
+ }
+
+ void ProcessorMetadata::addLook(const char * look)
+ {
+ getImpl()->looks.push_back(look);
+ }
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+
+
+ ProcessorRcPtr Processor::Create()
+ {
+ return ProcessorRcPtr(new Processor(), &deleter);
+ }
+
+ void Processor::deleter(Processor* c)
+ {
+ delete c;
+ }
+
+ Processor::Processor()
+ : m_impl(new Processor::Impl)
+ {
+ }
+
+ Processor::~Processor()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ bool Processor::isNoOp() const
+ {
+ return getImpl()->isNoOp();
+ }
+
+ bool Processor::hasChannelCrosstalk() const
+ {
+ return getImpl()->hasChannelCrosstalk();
+ }
+
+ ConstProcessorMetadataRcPtr Processor::getMetadata() const
+ {
+ return getImpl()->getMetadata();
+ }
+
+ void Processor::apply(ImageDesc& img) const
+ {
+ getImpl()->apply(img);
+ }
+ void Processor::applyRGB(float * pixel) const
+ {
+ getImpl()->applyRGB(pixel);
+ }
+
+ void Processor::applyRGBA(float * pixel) const
+ {
+ getImpl()->applyRGBA(pixel);
+ }
+
+ const char * Processor::getCpuCacheID() const
+ {
+ return getImpl()->getCpuCacheID();
+ }
+
+ const char * Processor::getGpuShaderText(const GpuShaderDesc & shaderDesc) const
+ {
+ return getImpl()->getGpuShaderText(shaderDesc);
+ }
+
+ const char * Processor::getGpuShaderTextCacheID(const GpuShaderDesc & shaderDesc) const
+ {
+ return getImpl()->getGpuShaderTextCacheID(shaderDesc);
+ }
+
+ void Processor::getGpuLut3D(float* lut3d, const GpuShaderDesc & shaderDesc) const
+ {
+ return getImpl()->getGpuLut3D(lut3d, shaderDesc);
+ }
+
+ const char * Processor::getGpuLut3DCacheID(const GpuShaderDesc & shaderDesc) const
+ {
+ return getImpl()->getGpuLut3DCacheID(shaderDesc);
+ }
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+
+
+
+ namespace
+ {
+ void WriteShaderHeader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc)
+ {
+ if(!shader) return;
+
+ std::string lut3dName = "lut3d";
+
+ shader << "\n// Generated by OpenColorIO\n\n";
+
+ GpuLanguage lang = shaderDesc.getLanguage();
+
+ std::string fcnName = shaderDesc.getFunctionName();
+
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ shader << "half4 " << fcnName << "(in half4 inPixel," << "\n";
+ shader << " const uniform sampler3D " << lut3dName << ") \n";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0)
+ {
+ shader << "vec4 " << fcnName << "(vec4 inPixel, \n";
+ shader << " sampler3D " << lut3dName << ") \n";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ shader << "vec4 " << fcnName << "(in vec4 inPixel, \n";
+ shader << " const sampler3D " << lut3dName << ") \n";
+ }
+ else throw Exception("Unsupported shader language.");
+
+ shader << "{" << "\n";
+
+ if(lang == GPU_LANGUAGE_CG)
+ {
+ shader << "half4 " << pixelName << " = inPixel; \n";
+ }
+ else if(lang == GPU_LANGUAGE_GLSL_1_0 || lang == GPU_LANGUAGE_GLSL_1_3)
+ {
+ shader << "vec4 " << pixelName << " = inPixel; \n";
+ }
+ else throw Exception("Unsupported shader language.");
+ }
+
+
+ void WriteShaderFooter(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & /*shaderDesc*/)
+ {
+ shader << "return " << pixelName << ";\n";
+ shader << "}" << "\n\n";
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+
+
+ Processor::Impl::Impl():
+ m_metadata(ProcessorMetadata::Create())
+ {
+ }
+
+ Processor::Impl::~Impl()
+ { }
+
+ bool Processor::Impl::isNoOp() const
+ {
+ return IsOpVecNoOp(m_cpuOps);
+ }
+
+ bool Processor::Impl::hasChannelCrosstalk() const
+ {
+ for(OpRcPtrVec::size_type i=0, size = m_cpuOps.size(); i<size; ++i)
+ {
+ if(m_cpuOps[i]->hasChannelCrosstalk()) return true;
+ }
+
+ return false;
+ }
+
+ ConstProcessorMetadataRcPtr Processor::Impl::getMetadata() const
+ {
+ return m_metadata;
+ }
+
+ void Processor::Impl::apply(ImageDesc& img) const
+ {
+ if(m_cpuOps.empty()) return;
+
+ ScanlineHelper scanlineHelper(img);
+ float * rgbaBuffer = 0;
+ long numPixels = 0;
+
+ while(true)
+ {
+ scanlineHelper.prepRGBAScanline(&rgbaBuffer, &numPixels);
+ if(numPixels == 0) break;
+ if(!rgbaBuffer)
+ throw Exception("Cannot apply transform; null image.");
+
+ for(OpRcPtrVec::size_type i=0, size = m_cpuOps.size(); i<size; ++i)
+ {
+ m_cpuOps[i]->apply(rgbaBuffer, numPixels);
+ }
+
+ scanlineHelper.finishRGBAScanline();
+ }
+ }
+
+ void Processor::Impl::applyRGB(float * pixel) const
+ {
+ if(m_cpuOps.empty()) return;
+
+ // We need to allocate a temp array as the pixel must be 4 floats in size
+ // (otherwise, sse loads will potentially fail)
+
+ float rgbaBuffer[4] = { pixel[0], pixel[1], pixel[2], 0.0f };
+
+ for(OpRcPtrVec::size_type i=0, size = m_cpuOps.size(); i<size; ++i)
+ {
+ m_cpuOps[i]->apply(rgbaBuffer, 1);
+ }
+
+ pixel[0] = rgbaBuffer[0];
+ pixel[1] = rgbaBuffer[1];
+ pixel[2] = rgbaBuffer[2];
+ }
+
+ void Processor::Impl::applyRGBA(float * pixel) const
+ {
+ for(OpRcPtrVec::size_type i=0, size = m_cpuOps.size(); i<size; ++i)
+ {
+ m_cpuOps[i]->apply(pixel, 1);
+ }
+ }
+
+ const char * Processor::Impl::getCpuCacheID() const
+ {
+ AutoMutex lock(m_resultsCacheMutex);
+
+ if(!m_cpuCacheID.empty()) return m_cpuCacheID.c_str();
+
+ if(m_cpuOps.empty())
+ {
+ m_cpuCacheID = "<NOOP>";
+ }
+ else
+ {
+ std::ostringstream cacheid;
+ for(OpRcPtrVec::size_type i=0, size = m_cpuOps.size(); i<size; ++i)
+ {
+ cacheid << m_cpuOps[i]->getCacheID() << " ";
+ }
+ std::string fullstr = cacheid.str();
+
+ m_cpuCacheID = CacheIDHash(fullstr.c_str(), (int)fullstr.size());
+ }
+
+ return m_cpuCacheID.c_str();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+
+ const char * Processor::Impl::getGpuShaderText(const GpuShaderDesc & shaderDesc) const
+ {
+ AutoMutex lock(m_resultsCacheMutex);
+
+ if(m_lastShaderDesc != shaderDesc.getCacheID())
+ {
+ m_lastShaderDesc = shaderDesc.getCacheID();
+ m_shader = "";
+ m_shaderCacheID = "";
+ m_lut3D.clear();
+ m_lut3DCacheID = "";
+ }
+
+ if(m_shader.empty())
+ {
+ std::ostringstream shader;
+ calcGpuShaderText(shader, shaderDesc);
+ m_shader = shader.str();
+
+ if(IsDebugLoggingEnabled())
+ {
+ LogDebug("GPU Shader");
+ LogDebug(m_shader);
+ }
+ }
+
+ return m_shader.c_str();
+ }
+
+ const char * Processor::Impl::getGpuShaderTextCacheID(const GpuShaderDesc & shaderDesc) const
+ {
+ AutoMutex lock(m_resultsCacheMutex);
+
+ if(m_lastShaderDesc != shaderDesc.getCacheID())
+ {
+ m_lastShaderDesc = shaderDesc.getCacheID();
+ m_shader = "";
+ m_shaderCacheID = "";
+ m_lut3D.clear();
+ m_lut3DCacheID = "";
+ }
+
+ if(m_shader.empty())
+ {
+ std::ostringstream shader;
+ calcGpuShaderText(shader, shaderDesc);
+ m_shader = shader.str();
+ }
+
+ if(m_shaderCacheID.empty())
+ {
+ m_shaderCacheID = CacheIDHash(m_shader.c_str(), (int)m_shader.size());
+ }
+
+ return m_shaderCacheID.c_str();
+ }
+
+
+ const char * Processor::Impl::getGpuLut3DCacheID(const GpuShaderDesc & shaderDesc) const
+ {
+ AutoMutex lock(m_resultsCacheMutex);
+
+ if(m_lastShaderDesc != shaderDesc.getCacheID())
+ {
+ m_lastShaderDesc = shaderDesc.getCacheID();
+ m_shader = "";
+ m_shaderCacheID = "";
+ m_lut3D.clear();
+ m_lut3DCacheID = "";
+ }
+
+ if(m_lut3DCacheID.empty())
+ {
+ if(m_gpuOpsCpuLatticeProcess.empty())
+ {
+ m_lut3DCacheID = "<NULL>";
+ }
+ else
+ {
+ std::ostringstream cacheid;
+ for(OpRcPtrVec::size_type i=0, size = m_gpuOpsCpuLatticeProcess.size(); i<size; ++i)
+ {
+ cacheid << m_gpuOpsCpuLatticeProcess[i]->getCacheID() << " ";
+ }
+ // Also, add a hash of the shader description
+ cacheid << shaderDesc.getCacheID();
+ std::string fullstr = cacheid.str();
+ m_lut3DCacheID = CacheIDHash(fullstr.c_str(), (int)fullstr.size());
+ }
+ }
+
+ return m_lut3DCacheID.c_str();
+ }
+
+ void Processor::Impl::getGpuLut3D(float* lut3d, const GpuShaderDesc & shaderDesc) const
+ {
+ if(!lut3d) return;
+
+ AutoMutex lock(m_resultsCacheMutex);
+
+ if(m_lastShaderDesc != shaderDesc.getCacheID())
+ {
+ m_lastShaderDesc = shaderDesc.getCacheID();
+ m_shader = "";
+ m_shaderCacheID = "";
+ m_lut3D.clear();
+ m_lut3DCacheID = "";
+ }
+
+ int lut3DEdgeLen = shaderDesc.getLut3DEdgeLen();
+ int lut3DNumPixels = lut3DEdgeLen*lut3DEdgeLen*lut3DEdgeLen;
+
+ // Can we write the entire shader using only shader text?
+ // If so, the lut3D is not needed so clear it.
+ // This is preferable to identity, as it lets people notice if
+ // it's accidentally being used.
+ if(m_gpuOpsCpuLatticeProcess.empty())
+ {
+ memset(lut3d, 0, sizeof(float) * 3 * lut3DNumPixels);
+ return;
+ }
+
+ if(m_lut3D.empty())
+ {
+ // Allocate 3dlut image, RGBA
+ m_lut3D.resize(lut3DNumPixels*4);
+ GenerateIdentityLut3D(&m_lut3D[0], lut3DEdgeLen, 4, LUT3DORDER_FAST_RED);
+
+ // Apply the lattice ops to it
+ for(int i=0; i<(int)m_gpuOpsCpuLatticeProcess.size(); ++i)
+ {
+ m_gpuOpsCpuLatticeProcess[i]->apply(&m_lut3D[0], lut3DNumPixels);
+ }
+
+ // Convert the RGBA image to an RGB image, in place.
+ // Of course, this only works because we're doing it from left to right
+ // so old pixels are read before they're written over
+ // TODO: is this bad for memory access patterns?
+ // see if this is faster with a 2nd temp float array
+
+ for(int i=1; i<lut3DNumPixels; ++i) // skip the 1st pixel, it's ok.
+ {
+ m_lut3D[3*i+0] = m_lut3D[4*i+0];
+ m_lut3D[3*i+1] = m_lut3D[4*i+1];
+ m_lut3D[3*i+2] = m_lut3D[4*i+2];
+ }
+ }
+
+ // Copy to the destination
+ memcpy(lut3d, &m_lut3D[0], sizeof(float) * 3 * lut3DNumPixels);
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+ void Processor::Impl::addColorSpaceConversion(const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstColorSpaceRcPtr & srcColorSpace,
+ const ConstColorSpaceRcPtr & dstColorSpace)
+ {
+ BuildColorSpaceOps(m_cpuOps, config, context, srcColorSpace, dstColorSpace);
+ }
+
+
+ void Processor::Impl::addTransform(const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstTransformRcPtr& transform,
+ TransformDirection direction)
+ {
+ BuildOps(m_cpuOps, config, context, transform, direction);
+ }
+
+ void Processor::Impl::finalize()
+ {
+ // Pull out metadata, before the no-ops are removed.
+ for(unsigned int i=0; i<m_cpuOps.size(); ++i)
+ {
+ m_cpuOps[i]->dumpMetadata(m_metadata);
+ }
+
+ // GPU Process setup
+ //
+ // Partition the original, raw opvec into 3 segments for GPU Processing
+ //
+ // Interior index range does not support the gpu shader.
+ // This is used to bound our analytical shader text generation
+ // start index and end index are inclusive.
+
+ PartitionGPUOps(m_gpuOpsHwPreProcess,
+ m_gpuOpsCpuLatticeProcess,
+ m_gpuOpsHwPostProcess,
+ m_cpuOps);
+
+ LogDebug("GPU Ops: Pre-3DLUT");
+ FinalizeOpVec(m_gpuOpsHwPreProcess);
+
+ LogDebug("GPU Ops: 3DLUT");
+ FinalizeOpVec(m_gpuOpsCpuLatticeProcess);
+
+ LogDebug("GPU Ops: Post-3DLUT");
+ FinalizeOpVec(m_gpuOpsHwPostProcess);
+
+ LogDebug("CPU Ops");
+ FinalizeOpVec(m_cpuOps);
+ }
+
+ void Processor::Impl::calcGpuShaderText(std::ostream & shader,
+ const GpuShaderDesc & shaderDesc) const
+ {
+ std::string pixelName = "out_pixel";
+ std::string lut3dName = "lut3d";
+
+ WriteShaderHeader(shader, pixelName, shaderDesc);
+
+
+ for(unsigned int i=0; i<m_gpuOpsHwPreProcess.size(); ++i)
+ {
+ m_gpuOpsHwPreProcess[i]->writeGpuShader(shader, pixelName, shaderDesc);
+ }
+
+ if(!m_gpuOpsCpuLatticeProcess.empty())
+ {
+ // Sample the 3D LUT.
+ int lut3DEdgeLen = shaderDesc.getLut3DEdgeLen();
+ shader << pixelName << ".rgb = ";
+ Write_sampleLut3D_rgb(shader, pixelName,
+ lut3dName, lut3DEdgeLen,
+ shaderDesc.getLanguage());
+ }
+#ifdef __APPLE__
+ else
+ {
+ // Force a no-op sampling of the 3d lut on OSX to work around a segfault.
+ int lut3DEdgeLen = shaderDesc.getLut3DEdgeLen();
+ shader << "// OSX segfault work-around: Force a no-op sampling of the 3d lut.\n";
+ Write_sampleLut3D_rgb(shader, pixelName,
+ lut3dName, lut3DEdgeLen,
+ shaderDesc.getLanguage());
+ }
+#endif // __APPLE__
+ for(unsigned int i=0; i<m_gpuOpsHwPostProcess.size(); ++i)
+ {
+ m_gpuOpsHwPostProcess[i]->writeGpuShader(shader, pixelName, shaderDesc);
+ }
+
+ WriteShaderFooter(shader, pixelName, shaderDesc);
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/Processor.h b/src/core/Processor.h
new file mode 100644
index 0000000..c0bdb51
--- /dev/null
+++ b/src/core/Processor.h
@@ -0,0 +1,132 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_PROCESSOR_H
+#define INCLUDED_OCIO_PROCESSOR_H
+
+#include <sstream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Mutex.h"
+#include "Op.h"
+#include "PrivateTypes.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ class Processor::Impl
+ {
+ private:
+ ProcessorMetadataRcPtr m_metadata;
+
+ OpRcPtrVec m_cpuOps;
+
+ // These 3 op vecs represent the 3 stages in our gpu pipe.
+ // 1) preprocess shader text
+ // 2) 3d lut process lookup
+ // 3) postprocess shader text
+
+ OpRcPtrVec m_gpuOpsHwPreProcess;
+ OpRcPtrVec m_gpuOpsCpuLatticeProcess;
+ OpRcPtrVec m_gpuOpsHwPostProcess;
+
+ mutable std::string m_cpuCacheID;
+
+ // Cache the last last queried value,
+ // for the specified shader description
+ mutable std::string m_lastShaderDesc;
+ mutable std::string m_shader;
+ mutable std::string m_shaderCacheID;
+ mutable std::vector<float> m_lut3D;
+ mutable std::string m_lut3DCacheID;
+
+ mutable Mutex m_resultsCacheMutex;
+
+ public:
+ Impl();
+ ~Impl();
+
+ bool isNoOp() const;
+ bool hasChannelCrosstalk() const;
+
+ ConstProcessorMetadataRcPtr getMetadata() const;
+
+ void apply(ImageDesc& img) const;
+
+ void applyRGB(float * pixel) const;
+ void applyRGBA(float * pixel) const;
+ const char * getCpuCacheID() const;
+
+ const char * getGpuShaderText(const GpuShaderDesc & gpuDesc) const;
+ const char * getGpuShaderTextCacheID(const GpuShaderDesc & shaderDesc) const;
+
+ void getGpuLut3D(float* lut3d, const GpuShaderDesc & shaderDesc) const;
+ const char * getGpuLut3DCacheID(const GpuShaderDesc & shaderDesc) const;
+
+ ////////////////////////////////////////////
+ //
+ // Builder functions, Not exposed
+
+ void addColorSpaceConversion(const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstColorSpaceRcPtr & srcColorSpace,
+ const ConstColorSpaceRcPtr & dstColorSpace);
+
+ void addTransform(const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstTransformRcPtr& transform,
+ TransformDirection direction);
+
+ void finalize();
+
+ void calcGpuShaderText(std::ostream & shader,
+ const GpuShaderDesc & shaderDesc) const;
+
+ };
+
+ // TODO: Move these!
+ // TODO: Its not ideal that buildops requires a config to be passed around
+ // but the only alternative is to make build ops a function on it?
+ // and even if it were, what about the build calls it dispatches to...
+
+ // TODO: all of the build op functions shouldnt take a LocalProcessor class
+ // Instead, they should take an abstract interface class that defines
+ // registerOp(OpRcPtr op), annotateColorSpace, finalizeOps, etc.
+ // of which LocalProcessor happens to be one example.
+ // Then the only location in the codebase that knows of LocalProcessor is
+ // in Config.cpp, which creates one.
+
+ void BuildOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstTransformRcPtr & transform,
+ TransformDirection dir);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/SSE.h b/src/core/SSE.h
new file mode 100644
index 0000000..5b825e2
--- /dev/null
+++ b/src/core/SSE.h
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_SSE_H
+#define INCLUDED_OCIO_SSE_H
+
+#ifdef USE_SSE
+#include <xmmintrin.h>
+#endif
+
+#endif
diff --git a/src/core/ScanlineHelper.cpp b/src/core/ScanlineHelper.cpp
new file mode 100644
index 0000000..b090ae7
--- /dev/null
+++ b/src/core/ScanlineHelper.cpp
@@ -0,0 +1,123 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+#include "ScanlineHelper.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ const int PIXELS_PER_LINE = 4096;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ ScanlineHelper::ScanlineHelper(ImageDesc& img):
+ m_buffer(0),
+ m_imagePixelIndex(0),
+ m_numPixelsCopied(0),
+ m_yIndex(0),
+ m_inPlaceMode(false)
+ {
+ m_img.init(img);
+
+ if(m_img.isPackedRGBA())
+ {
+ m_inPlaceMode = true;
+ }
+ else
+ {
+ // TODO: Re-use memory from thread-safe memory pool, rather
+ // than doing a new allocation each time.
+
+ m_buffer = (float*)malloc(sizeof(float)*PIXELS_PER_LINE*4);
+ }
+ }
+
+ ScanlineHelper::~ScanlineHelper()
+ {
+ free(m_buffer);
+ }
+
+ // Copy from the src image to our scanline, in our preferred
+ // pixel layout.
+
+ void ScanlineHelper::prepRGBAScanline(float** buffer, long* numPixels)
+ {
+ if(m_inPlaceMode)
+ {
+ // TODO: what if scanline is too short, or too long?
+ if(m_yIndex >= m_img.height)
+ {
+ *numPixels = 0;
+ return;
+ }
+
+ char* rowPtr = reinterpret_cast<char*>(m_img.rData);
+ rowPtr += m_img.yStrideBytes*m_yIndex;
+
+ *buffer = reinterpret_cast<float*>(rowPtr);
+ *numPixels = m_img.width;
+ }
+ else
+ {
+ PackRGBAFromImageDesc(m_img, m_buffer,
+ &m_numPixelsCopied,
+ PIXELS_PER_LINE,
+ m_imagePixelIndex);
+ *buffer = m_buffer;
+ *numPixels = m_numPixelsCopied;
+ }
+ }
+
+ // Write back the result of our work, from the scanline to our
+ // destination image.
+
+ void ScanlineHelper::finishRGBAScanline()
+ {
+ if(m_inPlaceMode)
+ {
+ m_yIndex += 1;
+ }
+ else
+ {
+ UnpackRGBAToImageDesc(m_img,
+ m_buffer,
+ m_numPixelsCopied,
+ m_imagePixelIndex);
+ m_imagePixelIndex += m_numPixelsCopied;
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/ScanlineHelper.h b/src/core/ScanlineHelper.h
new file mode 100644
index 0000000..016f1d9
--- /dev/null
+++ b/src/core/ScanlineHelper.h
@@ -0,0 +1,78 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_OCIO_SCANLINEHELPER_H
+#define INCLUDED_OCIO_SCANLINEHELPER_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "ImagePacking.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+ class ScanlineHelper
+ {
+ public:
+
+ ScanlineHelper(ImageDesc& img);
+
+ ~ScanlineHelper();
+
+ // Copy from the src image to our scanline, in our preferred
+ // pixel layout. Return the number of pixels to process;
+
+ void prepRGBAScanline(float** buffer, long* numPixels);
+
+ // Write back the result of our work, from the scanline to our
+ // destination image.
+
+ void finishRGBAScanline();
+
+ private:
+ GenericImageDesc m_img;
+
+ // Copy mode
+ float* m_buffer;
+ long m_imagePixelIndex;
+ int m_numPixelsCopied;
+
+ // In place mode
+ int m_yIndex;
+
+ bool m_inPlaceMode;
+
+ ScanlineHelper(const ScanlineHelper &);
+ ScanlineHelper& operator= (const ScanlineHelper &);
+ };
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core/Transform.cpp b/src/core/Transform.cpp
new file mode 100644
index 0000000..2f4bf7f
--- /dev/null
+++ b/src/core/Transform.cpp
@@ -0,0 +1,175 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "OpBuilders.h"
+#include "Processor.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ Transform::~Transform()
+ { }
+
+
+ void BuildOps(OpRcPtrVec & ops,
+ const Config & config,
+ const ConstContextRcPtr & context,
+ const ConstTransformRcPtr & transform,
+ TransformDirection dir)
+ {
+ // A null transform is valid, and corresponds to a no-op.
+ if(!transform)
+ return;
+
+ if(ConstAllocationTransformRcPtr allocationTransform = \
+ DynamicPtrCast<const AllocationTransform>(transform))
+ {
+ BuildAllocationOps(ops, config, *allocationTransform, dir);
+ }
+ else if(ConstCDLTransformRcPtr cdlTransform = \
+ DynamicPtrCast<const CDLTransform>(transform))
+ {
+ BuildCDLOps(ops, config, *cdlTransform, dir);
+ }
+ else if(ConstColorSpaceTransformRcPtr colorSpaceTransform = \
+ DynamicPtrCast<const ColorSpaceTransform>(transform))
+ {
+ BuildColorSpaceOps(ops, config, context, *colorSpaceTransform, dir);
+ }
+ else if(ConstDisplayTransformRcPtr displayTransform = \
+ DynamicPtrCast<const DisplayTransform>(transform))
+ {
+ BuildDisplayOps(ops, config, context, *displayTransform, dir);
+ }
+ else if(ConstExponentTransformRcPtr exponentTransform = \
+ DynamicPtrCast<const ExponentTransform>(transform))
+ {
+ BuildExponentOps(ops, config, *exponentTransform, dir);
+ }
+ else if(ConstFileTransformRcPtr fileTransform = \
+ DynamicPtrCast<const FileTransform>(transform))
+ {
+ BuildFileOps(ops, config, context, *fileTransform, dir);
+ }
+ else if(ConstGroupTransformRcPtr groupTransform = \
+ DynamicPtrCast<const GroupTransform>(transform))
+ {
+ BuildGroupOps(ops, config, context, *groupTransform, dir);
+ }
+ else if(ConstLogTransformRcPtr logTransform = \
+ DynamicPtrCast<const LogTransform>(transform))
+ {
+ BuildLogOps(ops, config, *logTransform, dir);
+ }
+ else if(ConstLookTransformRcPtr lookTransform = \
+ DynamicPtrCast<const LookTransform>(transform))
+ {
+ BuildLookOps(ops, config, context, *lookTransform, dir);
+ }
+ else if(ConstMatrixTransformRcPtr matrixTransform = \
+ DynamicPtrCast<const MatrixTransform>(transform))
+ {
+ BuildMatrixOps(ops, config, *matrixTransform, dir);
+ }
+ else if(ConstTruelightTransformRcPtr truelightTransform = \
+ DynamicPtrCast<const TruelightTransform>(transform))
+ {
+ BuildTruelightOps(ops, config, *truelightTransform, dir);
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Unknown transform type for Op Creation.";
+ throw Exception(os.str().c_str());
+ }
+ }
+
+ std::ostream& operator<< (std::ostream & os, const Transform & transform)
+ {
+ const Transform* t = &transform;
+
+ if(const AllocationTransform * allocationTransform = \
+ dynamic_cast<const AllocationTransform*>(t))
+ {
+ os << *allocationTransform;
+ }
+ else if(const CDLTransform * cdlTransform = \
+ dynamic_cast<const CDLTransform*>(t))
+ {
+ os << *cdlTransform;
+ }
+ else if(const ColorSpaceTransform * colorSpaceTransform = \
+ dynamic_cast<const ColorSpaceTransform*>(t))
+ {
+ os << *colorSpaceTransform;
+ }
+ else if(const DisplayTransform * displayTransform = \
+ dynamic_cast<const DisplayTransform*>(t))
+ {
+ os << *displayTransform;
+ }
+ else if(const ExponentTransform * exponentTransform = \
+ dynamic_cast<const ExponentTransform*>(t))
+ {
+ os << *exponentTransform;
+ }
+ else if(const FileTransform * fileTransform = \
+ dynamic_cast<const FileTransform*>(t))
+ {
+ os << *fileTransform;
+ }
+ else if(const GroupTransform * groupTransform = \
+ dynamic_cast<const GroupTransform*>(t))
+ {
+ os << *groupTransform;
+ }
+ else if(const MatrixTransform * matrixTransform = \
+ dynamic_cast<const MatrixTransform*>(t))
+ {
+ os << *matrixTransform;
+ }
+ else if(const TruelightTransform * truelightTransform = \
+ dynamic_cast<const TruelightTransform*>(t))
+ {
+ os << *truelightTransform;
+ }
+ else
+ {
+ std::ostringstream error;
+ os << "Unknown transform type for serialization.";
+ throw Exception(error.str().c_str());
+ }
+
+ return os;
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/TruelightOp.cpp b/src/core/TruelightOp.cpp
new file mode 100644
index 0000000..50f3915
--- /dev/null
+++ b/src/core/TruelightOp.cpp
@@ -0,0 +1,395 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <iostream>
+
+#ifdef OCIO_TRUELIGHT_SUPPORT
+#include <truelight.h>
+#else
+#define TL_INPUT_LOG 0
+#define TL_INPUT_LIN 1
+#define TL_INPUT_VID 2
+#endif // OCIO_TRUELIGHT_SUPPORT
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "TruelightOp.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ class TruelightOp : public Op
+ {
+ public:
+ TruelightOp(const char * configroot,
+ const char * profile,
+ const char * camera,
+ const char * inputdisplay,
+ const char * recorder,
+ const char * print,
+ const char * lamp,
+ const char * outputcamera,
+ const char * display,
+ const char * cubeinput,
+ TransformDirection direction);
+ virtual ~TruelightOp();
+
+ virtual OpRcPtr clone() const;
+
+ virtual std::string getInfo() const;
+ virtual std::string getCacheID() const;
+
+ virtual bool isNoOp() const;
+ virtual bool isSameType(const OpRcPtr & op) const;
+ virtual bool isInverse(const OpRcPtr & op) const;
+ virtual bool hasChannelCrosstalk() const;
+
+ virtual void finalize();
+ virtual void apply(float* rgbaBuffer, long numPixels) const;
+
+ virtual bool supportsGpuShader() const;
+ virtual void writeGpuShader(std::ostream & shader,
+ const std::string & pixelName,
+ const GpuShaderDesc & shaderDesc) const;
+
+ private:
+ TransformDirection m_direction;
+ void *m_truelight;
+ std::string m_configroot;
+ std::string m_profile;
+ std::string m_camera;
+ std::string m_inputdisplay;
+ std::string m_recorder;
+ std::string m_print;
+ std::string m_lamp;
+ std::string m_outputcamera;
+ std::string m_display;
+ int m_cubeinput;
+ std::string m_cacheID;
+ };
+
+ TruelightOp::TruelightOp(const char * configroot,
+ const char * profile,
+ const char * camera,
+ const char * inputdisplay,
+ const char * recorder,
+ const char * print,
+ const char * lamp,
+ const char * outputcamera,
+ const char * display,
+ const char * cubeinput,
+ TransformDirection direction):
+ Op(),
+ m_direction(direction),
+ m_configroot(configroot),
+ m_profile(profile),
+ m_camera(camera),
+ m_inputdisplay(inputdisplay),
+ m_recorder(recorder),
+ m_print(print),
+ m_lamp(lamp),
+ m_outputcamera(outputcamera),
+ m_display(display)
+ {
+
+ if(m_direction == TRANSFORM_DIR_UNKNOWN)
+ {
+ throw Exception("Cannot apply TruelightOp op, unspecified transform direction.");
+ }
+
+ std::string _tmp = pystring::lower(cubeinput);
+ if(_tmp == "log") m_cubeinput = TL_INPUT_LOG;
+ else if(_tmp == "linear") m_cubeinput = TL_INPUT_LIN;
+ else if(_tmp == "video") m_cubeinput = TL_INPUT_VID;
+ else
+ {
+ std::ostringstream err;
+ err << "we don't support cubeinput of type " << cubeinput;
+ err << " try log, linear or video.";
+ throw Exception(err.str().c_str());
+ }
+
+#ifdef OCIO_TRUELIGHT_SUPPORT
+
+ if((TruelightBegin("")) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+
+ m_truelight = TruelightCreateInstance();
+ if(!m_truelight)
+ {
+ std::ostringstream err;
+ err << "Error: '" << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+
+ // floating point
+ TruelightInstanceSetMax(m_truelight, 1);
+
+ // where too look for the profiles, prints etc
+ TruelightSetRoot(m_configroot.c_str());
+
+ // invert the transform depending on direction
+ if(m_direction == TRANSFORM_DIR_FORWARD)
+ {
+ TruelightInstanceSetInvertFlag(m_truelight, 0);
+ }
+ else if(m_direction == TRANSFORM_DIR_INVERSE)
+ {
+ TruelightInstanceSetInvertFlag(m_truelight, 1);
+ }
+
+#endif // OCIO_TRUELIGHT_SUPPORT
+
+ }
+
+ OpRcPtr TruelightOp::clone() const
+ {
+ std::string _cubeinput = "unknown";
+ if(m_cubeinput == TL_INPUT_LOG) _cubeinput = "log";
+ else if(m_cubeinput == TL_INPUT_LIN) _cubeinput = "linear";
+ else if(m_cubeinput == TL_INPUT_VID) _cubeinput = "video";
+ OpRcPtr op = OpRcPtr(new TruelightOp(m_configroot.c_str(),
+ m_profile.c_str(),
+ m_camera.c_str(),
+ m_inputdisplay.c_str(),
+ m_recorder.c_str(),
+ m_print.c_str(),
+ m_lamp.c_str(),
+ m_outputcamera.c_str(),
+ m_display.c_str(),
+ _cubeinput.c_str(),
+ m_direction));
+ return op;
+ }
+
+ TruelightOp::~TruelightOp()
+ {
+#ifdef OCIO_TRUELIGHT_SUPPORT
+ if(m_truelight) TruelightDestroyInstance(m_truelight);
+#endif // OCIO_TRUELIGHT_SUPPORT
+ }
+
+ std::string TruelightOp::getInfo() const
+ {
+ return "<TruelightOp>";
+ }
+
+ std::string TruelightOp::getCacheID() const
+ {
+ return m_cacheID;
+ }
+
+ bool TruelightOp::isNoOp() const
+ {
+ return false;
+ }
+ bool TruelightOp::isSameType(const OpRcPtr & /*op*/) const
+ {
+ // TODO: TruelightOp::isSameType
+ return false;
+ }
+
+ bool TruelightOp::isInverse(const OpRcPtr & /*op*/) const
+ {
+ // TODO: TruelightOp::isInverse
+ return false;
+ }
+
+ bool TruelightOp::hasChannelCrosstalk() const
+ {
+ return true;
+ }
+
+ void TruelightOp::finalize()
+ {
+#ifndef OCIO_TRUELIGHT_SUPPORT
+ std::ostringstream err;
+ err << "OCIO has been built without Truelight support";
+ throw Exception(err.str().c_str());
+#else
+ if(m_profile != "")
+ {
+ if(TruelightInstanceSetProfile(m_truelight, m_profile.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_camera != "")
+ {
+ if(TruelightInstanceSetCamera(m_truelight, m_camera.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_inputdisplay != "")
+ {
+ if(TruelightInstanceSetInputDisplay(m_truelight, m_inputdisplay.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_recorder != "")
+ {
+ if(TruelightInstanceSetRecorder(m_truelight, m_recorder.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_print != "")
+ {
+ if(TruelightInstanceSetPrint(m_truelight, m_print.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_lamp != "")
+ {
+ if(TruelightInstanceSetLamp(m_truelight, m_lamp.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_outputcamera != "")
+ {
+ if(TruelightInstanceSetOutputCamera(m_truelight, m_outputcamera.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(m_display != "")
+ {
+ if(TruelightInstanceSetDisplay(m_truelight, m_display.c_str()) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+ }
+
+ if(TruelightInstanceSetCubeInput(m_truelight, m_cubeinput) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+
+ if(TruelightInstanceSetUp(m_truelight) == 0)
+ {
+ std::ostringstream err;
+ err << "Error: " << TruelightGetErrorString();
+ throw Exception(err.str().c_str());
+ }
+#endif // OCIO_TRUELIGHT_SUPPORT
+
+ // build cache id
+ std::ostringstream cacheIDStream;
+ cacheIDStream << "<TruelightOp ";
+ cacheIDStream << m_profile << " ";
+ cacheIDStream << m_camera << " ";
+ cacheIDStream << m_inputdisplay << " ";
+ cacheIDStream << m_recorder << " ";
+ cacheIDStream << m_print << " ";
+ cacheIDStream << m_lamp << " ";
+ cacheIDStream << m_outputcamera << " ";
+ cacheIDStream << m_display << " ";
+ cacheIDStream << m_cubeinput << " ";
+ cacheIDStream << TransformDirectionToString(m_direction) << " ";
+ cacheIDStream << ">";
+ m_cacheID = cacheIDStream.str();
+ }
+
+ void TruelightOp::apply(float* rgbaBuffer, long numPixels) const
+ {
+ for(long pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex)
+ {
+#ifdef OCIO_TRUELIGHT_SUPPORT
+ TruelightInstanceTransformF(m_truelight, rgbaBuffer);
+#endif // OCIO_TRUELIGHT_SUPPORT
+ rgbaBuffer += 4; // skip alpha
+ }
+ }
+
+ bool TruelightOp::supportsGpuShader() const
+ {
+ return false;
+ }
+
+ void TruelightOp::writeGpuShader(std::ostream & /*shader*/,
+ const std::string & /*pixelName*/,
+ const GpuShaderDesc & /*shaderDesc*/) const
+ {
+ throw Exception("TruelightOp does not define an gpu shader.");
+ }
+
+ } // anonymous namespace
+
+ void CreateTruelightOps(OpRcPtrVec & ops,
+ const TruelightTransform & data,
+ TransformDirection direction)
+ {
+ ops.push_back(OpRcPtr(new TruelightOp(data.getConfigRoot(),
+ data.getProfile(),
+ data.getCamera(),
+ data.getInputDisplay(),
+ data.getRecorder(),
+ data.getPrint(),
+ data.getLamp(),
+ data.getOutputCamera(),
+ data.getDisplay(),
+ data.getCubeInput(),
+ direction)));
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/TruelightOp.h b/src/core/TruelightOp.h
new file mode 100644
index 0000000..fe78b6a
--- /dev/null
+++ b/src/core/TruelightOp.h
@@ -0,0 +1,44 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_TRUELIGHTOP_H
+#define INCLUDED_OCIO_TRUELIGHTOP_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "Op.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ void CreateTruelightOps(OpRcPtrVec & ops,
+ const TruelightTransform & data,
+ TransformDirection dir);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif // INCLUDED_OCIO_TRUELIGHTOP_H
diff --git a/src/core/TruelightTransform.cpp b/src/core/TruelightTransform.cpp
new file mode 100644
index 0000000..7e95875
--- /dev/null
+++ b/src/core/TruelightTransform.cpp
@@ -0,0 +1,365 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <iostream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "OpBuilders.h"
+#include "TruelightOp.h"
+#include "pystring/pystring.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+ TruelightTransformRcPtr TruelightTransform::Create()
+ {
+ return TruelightTransformRcPtr(new TruelightTransform(), &deleter);
+ }
+
+ void TruelightTransform::deleter(TruelightTransform* t)
+ {
+ delete t;
+ }
+
+ class TruelightTransform::Impl
+ {
+ public:
+ TransformDirection dir_;
+ std::string configroot_;
+ std::string profile_;
+ std::string camera_;
+ std::string inputdisplay_;
+ std::string recorder_;
+ std::string print_;
+ std::string lamp_;
+ std::string outputcamera_;
+ std::string display_;
+ std::string cubeinput_;
+
+ Impl() : dir_(TRANSFORM_DIR_FORWARD)
+ { }
+
+ ~Impl()
+ { }
+
+ Impl& operator= (const Impl & rhs)
+ {
+ dir_ = rhs.dir_;
+ configroot_ = rhs.configroot_;
+ profile_ = rhs.profile_;
+ camera_ = rhs.camera_;
+ inputdisplay_ = rhs.inputdisplay_;
+ recorder_ = rhs.recorder_;
+ print_ = rhs.print_;
+ lamp_ = rhs.lamp_;
+ outputcamera_ = rhs.outputcamera_;
+ display_ = rhs.display_;
+ cubeinput_ = rhs.cubeinput_;
+ return *this;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ TruelightTransform::TruelightTransform()
+ : m_impl(new TruelightTransform::Impl)
+ {
+ getImpl()->configroot_ = "/usr/fl/truelight";
+ getImpl()->profile_ = "";
+ getImpl()->camera_ = "";
+ getImpl()->inputdisplay_ = "";
+ getImpl()->recorder_ = "";
+ getImpl()->print_ = "";
+ getImpl()->lamp_ = "";
+ getImpl()->outputcamera_ = "";
+ getImpl()->display_ = "";
+ getImpl()->cubeinput_ = "log";
+ }
+
+ TransformRcPtr TruelightTransform::createEditableCopy() const
+ {
+ TruelightTransformRcPtr transform = TruelightTransform::Create();
+ *(transform->m_impl) = *m_impl;
+ return transform;
+ }
+
+ TruelightTransform::~TruelightTransform()
+ {
+ delete m_impl;
+ m_impl = NULL;
+ }
+
+ TruelightTransform& TruelightTransform::operator= (const TruelightTransform & rhs)
+ {
+ *m_impl = *rhs.m_impl;
+ return *this;
+ }
+
+ TransformDirection TruelightTransform::getDirection() const
+ {
+ return getImpl()->dir_;
+ }
+
+ void TruelightTransform::setDirection(TransformDirection dir)
+ {
+ getImpl()->dir_ = dir;
+ }
+
+ void TruelightTransform::setConfigRoot(const char * configroot)
+ {
+ getImpl()->configroot_ = configroot;
+ }
+
+ const char * TruelightTransform::getConfigRoot() const
+ {
+ return getImpl()->configroot_.c_str();
+ }
+
+ void TruelightTransform::setProfile(const char * profile)
+ {
+ getImpl()->profile_ = profile;
+ }
+
+ const char * TruelightTransform::getProfile() const
+ {
+ return getImpl()->profile_.c_str();
+ }
+
+ void TruelightTransform::setCamera(const char * camera)
+ {
+ getImpl()->camera_ = camera;
+ }
+
+ const char * TruelightTransform::getCamera() const
+ {
+ return getImpl()->camera_.c_str();
+ }
+
+ void TruelightTransform::setInputDisplay(const char * display)
+ {
+ getImpl()->inputdisplay_ = display;
+ }
+
+ const char * TruelightTransform::getInputDisplay() const
+ {
+ return getImpl()->inputdisplay_.c_str();
+ }
+
+ void TruelightTransform::setRecorder(const char * recorder)
+ {
+ getImpl()->recorder_ = recorder;
+ }
+
+ const char * TruelightTransform::getRecorder() const
+ {
+ return getImpl()->recorder_.c_str();
+ }
+
+ void TruelightTransform::setPrint(const char * print)
+ {
+ getImpl()->print_ = print;
+ }
+
+ const char * TruelightTransform::getPrint() const
+ {
+ return getImpl()->print_.c_str();
+ }
+
+ void TruelightTransform::setLamp(const char * lamp)
+ {
+ getImpl()->lamp_ = lamp;
+ }
+
+ const char * TruelightTransform::getLamp() const
+ {
+ return getImpl()->lamp_.c_str();
+ }
+
+ void TruelightTransform::setOutputCamera(const char * camera)
+ {
+ getImpl()->outputcamera_ = camera;
+ }
+
+ const char * TruelightTransform::getOutputCamera() const
+ {
+ return getImpl()->outputcamera_.c_str();
+ }
+
+ void TruelightTransform::setDisplay(const char * display)
+ {
+ getImpl()->display_ = display;
+ }
+
+ const char * TruelightTransform::getDisplay() const
+ {
+ return getImpl()->display_.c_str();
+ }
+
+ void TruelightTransform::setCubeInput(const char * cubeinput)
+ {
+ getImpl()->cubeinput_ = pystring::lower(cubeinput);
+ }
+
+ const char * TruelightTransform::getCubeInput() const
+ {
+ return getImpl()->cubeinput_.c_str();
+ }
+
+ std::ostream& operator<< (std::ostream& os, const TruelightTransform& t)
+ {
+ os << "<TruelightTransform ";
+ os << "direction=" << TransformDirectionToString(t.getDirection()) << ", ";
+ os << ">\n";
+ return os;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ void BuildTruelightOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const TruelightTransform & transform,
+ TransformDirection dir)
+ {
+ TransformDirection combinedDir = CombineTransformDirections(dir,
+ transform.getDirection());
+ CreateTruelightOps(ops, transform, combinedDir);
+ }
+
+}
+OCIO_NAMESPACE_EXIT
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OCIO_UNIT_TEST
+
+namespace OCIO = OCIO_NAMESPACE;
+#include "UnitTest.h"
+
+OIIO_ADD_TEST(TruelightTransform, simpletest)
+{
+
+ OCIO::ConfigRcPtr config = OCIO::Config::Create();
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("log");
+ cs->setFamily("log");
+ config->addColorSpace(cs);
+ config->setRole(OCIO::ROLE_COMPOSITING_LOG, cs->getName());
+ }
+ {
+ OCIO::ColorSpaceRcPtr cs = OCIO::ColorSpace::Create();
+ cs->setName("sRGB");
+ cs->setFamily("srgb");
+ OCIO::TruelightTransformRcPtr transform1 = OCIO::TruelightTransform::Create();
+ transform1->setConfigRoot("/usr/fl/truelight");
+ transform1->setPrint("internal-LowContrast");
+ //transform1->setInputDisplay("DCIrgb");
+ transform1->setDisplay("sRGB");
+ transform1->setCubeInput("log");
+ cs->setTransform(transform1, OCIO::COLORSPACE_DIR_FROM_REFERENCE);
+ config->addColorSpace(cs);
+ }
+
+ // check the transform round trip
+ OCIO::ConstProcessorRcPtr tosrgb;
+ OCIO::ConstProcessorRcPtr tolog;
+
+#ifdef OCIO_TRUELIGHT_SUPPORT
+ OIIO_CHECK_NO_THOW(tosrgb = config->getProcessor("log", "sRGB"));
+ OIIO_CHECK_NO_THOW(tolog = config->getProcessor("sRGB", "log"));
+#else
+ OIIO_CHECK_THOW(tosrgb = config->getProcessor("log", "sRGB"), OCIO::Exception);
+ OIIO_CHECK_THOW(tolog = config->getProcessor("sRGB", "log"), OCIO::Exception);
+#endif
+
+#ifdef OCIO_TRUELIGHT_SUPPORT
+ float input[3] = {0.5f, 0.5f, 0.5f};
+ float output[3] = {0.500098f, 0.500317f, 0.501134f};
+ OIIO_CHECK_NO_THOW(tosrgb->applyRGB(input));
+ OIIO_CHECK_NO_THOW(tolog->applyRGB(input));
+ OIIO_CHECK_CLOSE(input[0], output[0], 1e-4);
+ OIIO_CHECK_CLOSE(input[1], output[1], 1e-4);
+ OIIO_CHECK_CLOSE(input[2], output[2], 1e-4);
+#endif
+
+ std::ostringstream os;
+ OIIO_CHECK_NO_THOW(config->serialize(os));
+
+ std::string referenceconfig =
+ "ocio_profile_version: 1\n"
+ "\n"
+ "search_path: \"\"\n"
+ "strictparsing: true\n"
+ "luma: [0.2126, 0.7152, 0.0722]\n"
+ "\n"
+ "roles:\n"
+ " compositing_log: log\n"
+ "\n"
+ "displays:\n"
+ " {}\n"
+ "\n"
+ "active_displays: []\n"
+ "active_views: []\n"
+ "\n"
+ "colorspaces:\n"
+ " - !<ColorSpace>\n"
+ " name: log\n"
+ " family: log\n"
+ " equalitygroup: \"\"\n"
+ " bitdepth: unknown\n"
+ " isdata: false\n"
+ " allocation: uniform\n"
+ "\n"
+ " - !<ColorSpace>\n"
+ " name: sRGB\n"
+ " family: srgb\n"
+ " equalitygroup: \"\"\n"
+ " bitdepth: unknown\n"
+ " isdata: false\n"
+ " allocation: uniform\n"
+ " from_reference: !<TruelightTransform> {config_root: /usr/fl/truelight, print: internal-LowContrast, display: sRGB, cube_input: log}\n";
+
+
+ std::vector<std::string> osvec;
+ OCIO::pystring::splitlines(os.str(), osvec);
+ std::vector<std::string> referenceconfigvec;
+ OCIO::pystring::splitlines(referenceconfig, referenceconfigvec);
+
+ OIIO_CHECK_EQUAL(osvec.size(), referenceconfigvec.size());
+ for(unsigned int i = 0; i < referenceconfigvec.size(); ++i)
+ OIIO_CHECK_EQUAL(osvec[i], referenceconfigvec[i]);
+
+ std::istringstream is;
+ is.str(referenceconfig);
+ OCIO::ConstConfigRcPtr rtconfig;
+ OIIO_CHECK_NO_THOW(rtconfig = OCIO::Config::CreateFromStream(is));
+
+}
+
+#endif // OCIO_BUILD_TESTS
diff --git a/src/core/UnitTest.cpp b/src/core/UnitTest.cpp
new file mode 100644
index 0000000..8b1270d
--- /dev/null
+++ b/src/core/UnitTest.cpp
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_UNITTEST_H
+#define INCLUDED_OCIO_UNITTEST_H
+
+#ifdef OCIO_UNIT_TEST
+#pragma GCC visibility push(default)
+#include <unittest.h> // OIIO unit tests header
+OIIO_TEST_APP(OpenColorIO_Core_Unit_Tests)
+#pragma GCC visibility pop
+#endif // OCIO_UNIT_TEST
+
+#endif // INCLUDED_OCIO_UNITTEST_H
diff --git a/src/core/UnitTest.h b/src/core/UnitTest.h
new file mode 100644
index 0000000..33625c5
--- /dev/null
+++ b/src/core/UnitTest.h
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_UNITTEST_H
+#define INCLUDED_OCIO_UNITTEST_H
+
+#ifdef OCIO_UNIT_TEST
+#pragma GCC visibility push(default)
+#include <unittest.h> // OIIO unit tests header
+#pragma GCC visibility pop
+#endif // OCIO_UNIT_TEST
+
+#endif // INCLUDED_OCIO_UNITTEST_H
diff --git a/src/core/md5/md5.cpp b/src/core/md5/md5.cpp
new file mode 100644
index 0000000..3eb5673
--- /dev/null
+++ b/src/core/md5/md5.cpp
@@ -0,0 +1,391 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+// This file was altered for OCIO compilation purposes
+
+#include "md5.h"
+#include <cstring>
+
+
+OCIO_NAMESPACE_ENTER
+{
+
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/md5/md5.h b/src/core/md5/md5.h
new file mode 100644
index 0000000..cb36edb
--- /dev/null
+++ b/src/core/md5/md5.h
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+// This file was altered for OCIO compilation purposes
+
+#ifndef INCLUDED_OCIO_md5_INCLUDED
+#define INCLUDED_OCIO_md5_INCLUDED
+
+
+#include <OpenColorIO/OpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+
+// Note: the md5 functions should not be wrapped in extern "C', otherwise
+// the symbols will not be appropriately wrapped in the OCIO namespace
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif /* md5_INCLUDED */
diff --git a/src/core/pystring/pystring.cpp b/src/core/pystring/pystring.cpp
new file mode 100644
index 0000000..7805162
--- /dev/null
+++ b/src/core/pystring/pystring.cpp
@@ -0,0 +1,1658 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// Neither the name of the organization Sony Pictures Imageworks nor the
+// names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "pystring.h"
+
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+
+namespace pystring
+{
+
+#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(_MSC_VER)
+#ifndef WINDOWS
+#define WINDOWS
+#endif
+#endif
+
+// This definition codes from configure.in in the python src.
+// Strictly speaking this limits us to str sizes of 2**31.
+// Should we wish to handle this limit, we could use an architecture
+// specific #defines and read from ssize_t (unistd.h) if the header exists.
+// But in the meantime, the use of int assures maximum arch compatibility.
+// This must also equal the size used in the end = MAX_32BIT_INT default arg.
+
+typedef int Py_ssize_t;
+
+/* helper macro to fixup start/end slice values */
+#define ADJUST_INDICES(start, end, len) \
+ if (end > len) \
+ end = len; \
+ else if (end < 0) { \
+ end += len; \
+ if (end < 0) \
+ end = 0; \
+ } \
+ if (start < 0) { \
+ start += len; \
+ if (start < 0) \
+ start = 0; \
+ }
+
+
+ namespace {
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// why doesn't the std::reverse work?
+ ///
+ void reverse_strings( std::vector< std::string > & result)
+ {
+ for (std::vector< std::string >::size_type i = 0; i < result.size() / 2; i++ )
+ {
+ std::swap(result[i], result[result.size() - 1 - i]);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void split_whitespace( const std::string & str, std::vector< std::string > & result, int maxsplit )
+ {
+ std::string::size_type i, j, len = str.size();
+ for (i = j = 0; i < len; )
+ {
+
+ while ( i < len && ::isspace( str[i] ) ) i++;
+ j = i;
+
+ while ( i < len && ! ::isspace( str[i]) ) i++;
+
+
+
+ if (j < i)
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( j, i - j ));
+
+ while ( i < len && ::isspace( str[i])) i++;
+ j = i;
+ }
+ }
+ if (j < len)
+ {
+ result.push_back( str.substr( j, len - j ));
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void rsplit_whitespace( const std::string & str, std::vector< std::string > & result, int maxsplit )
+ {
+ std::string::size_type len = str.size();
+ std::string::size_type i, j;
+ for (i = j = len; i > 0; )
+ {
+
+ while ( i > 0 && ::isspace( str[i - 1] ) ) i--;
+ j = i;
+
+ while ( i > 0 && ! ::isspace( str[i - 1]) ) i--;
+
+
+
+ if (j > i)
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( i, j - i ));
+
+ while ( i > 0 && ::isspace( str[i - 1])) i--;
+ j = i;
+ }
+ }
+ if (j > 0)
+ {
+ result.push_back( str.substr( 0, j ));
+ }
+ //std::reverse( result, result.begin(), result.end() );
+ reverse_strings( result );
+ }
+
+ } //anonymous namespace
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void split( const std::string & str, std::vector< std::string > & result, const std::string & sep, int maxsplit )
+ {
+ result.clear();
+
+ if ( maxsplit < 0 ) maxsplit = MAX_32BIT_INT;//result.max_size();
+
+
+ if ( sep.size() == 0 )
+ {
+ split_whitespace( str, result, maxsplit );
+ return;
+ }
+
+ std::string::size_type i,j, len = str.size(), n = sep.size();
+
+ i = j = 0;
+
+ while ( i+n <= len )
+ {
+ if ( str[i] == sep[0] && str.substr( i, n ) == sep )
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( j, i - j ) );
+ i = j = i + n;
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ result.push_back( str.substr( j, len-j ) );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep, int maxsplit )
+ {
+ if ( maxsplit < 0 )
+ {
+ split( str, result, sep, 0 );
+ return;
+ }
+
+ result.clear();
+
+ if ( sep.size() == 0 )
+ {
+ rsplit_whitespace( str, result, maxsplit );
+ return;
+ }
+
+ std::string::size_type i,j, len = str.size(), n = sep.size();
+
+ i = j = len;
+
+ while ( i > n )
+ {
+ if ( str[i - 1] == sep[n - 1] && str.substr( i - n, n ) == sep )
+ {
+ if ( maxsplit-- <= 0 ) break;
+
+ result.push_back( str.substr( i, j - i ) );
+ i = j = i - n;
+ }
+ else
+ {
+ i--;
+ }
+ }
+
+ result.push_back( str.substr( 0, j ) );
+ reverse_strings( result );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ #define LEFTSTRIP 0
+ #define RIGHTSTRIP 1
+ #define BOTHSTRIP 2
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string do_strip( const std::string & str, int striptype, const std::string & chars )
+ {
+ Py_ssize_t len = (Py_ssize_t) str.size(), i, j, charslen = (Py_ssize_t) chars.size();
+
+ if ( charslen == 0 )
+ {
+ i = 0;
+ if ( striptype != RIGHTSTRIP )
+ {
+ while ( i < len && ::isspace( str[i] ) )
+ {
+ i++;
+ }
+ }
+
+ j = len;
+ if ( striptype != LEFTSTRIP )
+ {
+ do
+ {
+ j--;
+ }
+ while (j >= i && ::isspace(str[j]));
+
+ j++;
+ }
+
+
+ }
+ else
+ {
+ const char * sep = chars.c_str();
+
+ i = 0;
+ if ( striptype != RIGHTSTRIP )
+ {
+ while ( i < len && memchr(sep, str[i], charslen) )
+ {
+ i++;
+ }
+ }
+
+ j = len;
+ if (striptype != LEFTSTRIP)
+ {
+ do
+ {
+ j--;
+ }
+ while (j >= i && memchr(sep, str[j], charslen) );
+ j++;
+ }
+
+
+ }
+
+ if ( i == 0 && j == len )
+ {
+ return str;
+ }
+ else
+ {
+ return str.substr( i, j - i );
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result )
+ {
+ result.resize(3);
+ int index = find( str, sep );
+ if ( index < 0 )
+ {
+ result[0] = str;
+ result[1] = "";
+ result[2] = "";
+ }
+ else
+ {
+ result[0] = str.substr( 0, index );
+ result[1] = sep;
+ result[2] = str.substr( index + sep.size(), str.size() );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result )
+ {
+ result.resize(3);
+ int index = rfind( str, sep );
+ if ( index < 0 )
+ {
+ result[0] = "";
+ result[1] = "";
+ result[2] = str;
+ }
+ else
+ {
+ result[0] = str.substr( 0, index );
+ result[1] = sep;
+ result[2] = str.substr( index + sep.size(), str.size() );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string strip( const std::string & str, const std::string & chars )
+ {
+ return do_strip( str, BOTHSTRIP, chars );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string lstrip( const std::string & str, const std::string & chars )
+ {
+ return do_strip( str, LEFTSTRIP, chars );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string rstrip( const std::string & str, const std::string & chars )
+ {
+ return do_strip( str, RIGHTSTRIP, chars );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string join( const std::string & str, const std::vector< std::string > & seq )
+ {
+ std::vector< std::string >::size_type seqlen = seq.size(), i;
+
+ if ( seqlen == 0 ) return "";
+ if ( seqlen == 1 ) return seq[0];
+
+ std::string result( seq[0] );
+
+ for ( i = 1; i < seqlen; ++i )
+ {
+ result += str + seq[i];
+
+ }
+
+
+ return result;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ namespace
+ {
+ /* Matches the end (direction >= 0) or start (direction < 0) of self
+ * against substr, using the start and end arguments. Returns
+ * -1 on error, 0 if not found and 1 if found.
+ */
+
+ int _string_tailmatch(const std::string & self, const std::string & substr,
+ Py_ssize_t start, Py_ssize_t end,
+ int direction)
+ {
+ Py_ssize_t len = (Py_ssize_t) self.size();
+ Py_ssize_t slen = (Py_ssize_t) substr.size();
+
+ const char* sub = substr.c_str();
+ const char* str = self.c_str();
+
+ ADJUST_INDICES(start, end, len);
+
+ if (direction < 0) {
+ // startswith
+ if (start+slen > len)
+ return 0;
+ } else {
+ // endswith
+ if (end-start < slen || start > len)
+ return 0;
+ if (end-slen > start)
+ start = end - slen;
+ }
+ if (end-start >= slen)
+ return (!std::memcmp(str+start, sub, slen));
+
+ return 0;
+ }
+ }
+
+ bool endswith( const std::string & str, const std::string & suffix, int start, int end )
+ {
+ int result = _string_tailmatch(str, suffix,
+ (Py_ssize_t) start, (Py_ssize_t) end, +1);
+ //if (result == -1) // TODO: Error condition
+
+ return static_cast<bool>(result);
+ }
+
+
+ bool startswith( const std::string & str, const std::string & prefix, int start, int end )
+ {
+ int result = _string_tailmatch(str, prefix,
+ (Py_ssize_t) start, (Py_ssize_t) end, -1);
+ //if (result == -1) // TODO: Error condition
+
+ return static_cast<bool>(result);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ bool isalnum( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+
+
+ if( len == 1 )
+ {
+ return ::isalnum( str[0] );
+ }
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isalnum( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isalpha( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isalpha( (int) str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isalpha( (int) str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isdigit( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isdigit( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ! ::isdigit( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool islower( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::islower( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::islower( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isspace( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isspace( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isspace( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool istitle( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+
+ if ( len == 0 ) return false;
+ if ( len == 1 ) return ::isupper( str[0] );
+
+ bool cased = false, previous_is_cased = false;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::isupper( str[i] ) )
+ {
+ if ( previous_is_cased )
+ {
+ return false;
+ }
+
+ previous_is_cased = true;
+ cased = true;
+ }
+ else if ( ::islower( str[i] ) )
+ {
+ if (!previous_is_cased)
+ {
+ return false;
+ }
+
+ previous_is_cased = true;
+ cased = true;
+
+ }
+ else
+ {
+ previous_is_cased = false;
+ }
+ }
+
+ return cased;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ bool isupper( const std::string & str )
+ {
+ std::string::size_type len = str.size(), i;
+ if ( len == 0 ) return false;
+ if( len == 1 ) return ::isupper( str[0] );
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( !::isupper( str[i] ) ) return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string capitalize( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+
+ if ( len > 0)
+ {
+ if (::islower(s[0])) s[0] = (char) ::toupper( s[0] );
+ }
+
+ for ( i = 1; i < len; ++i )
+ {
+ if (::isupper(s[i])) s[i] = (char) ::tolower( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string lower( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::isupper( s[i] ) ) s[i] = (char) ::tolower( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string upper( const std::string & str )
+ {
+ std::string s( str ) ;
+ std::string::size_type len = s.size(), i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::islower( s[i] ) ) s[i] = (char) ::toupper( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string swapcase( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( ::islower( s[i] ) ) s[i] = (char) ::toupper( s[i] );
+ else if (::isupper( s[i] ) ) s[i] = (char) ::tolower( s[i] );
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string title( const std::string & str )
+ {
+ std::string s( str );
+ std::string::size_type len = s.size(), i;
+ bool previous_is_cased = false;
+
+ for ( i = 0; i < len; ++i )
+ {
+ int c = s[i];
+ if ( ::islower(c) )
+ {
+ if ( !previous_is_cased )
+ {
+ s[i] = (char) ::toupper(c);
+ }
+ previous_is_cased = true;
+ }
+ else if ( ::isupper(c) )
+ {
+ if ( previous_is_cased )
+ {
+ s[i] = (char) ::tolower(c);
+ }
+ previous_is_cased = true;
+ }
+ else
+ {
+ previous_is_cased = false;
+ }
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string translate( const std::string & str, const std::string & table, const std::string & deletechars )
+ {
+ std::string s;
+ std::string::size_type len = str.size(), dellen = deletechars.size();
+
+ if ( table.size() != 256 )
+ {
+ // TODO : raise exception instead
+ return str;
+ }
+
+ //if nothing is deleted, use faster code
+ if ( dellen == 0 )
+ {
+ s = str;
+ for ( std::string::size_type i = 0; i < len; ++i )
+ {
+ s[i] = table[ s[i] ];
+ }
+ return s;
+ }
+
+
+ int trans_table[256];
+ for ( int i = 0; i < 256; i++)
+ {
+ trans_table[i] = table[i];
+ }
+
+ for ( std::string::size_type i = 0; i < dellen; i++)
+ {
+ trans_table[(int) deletechars[i] ] = -1;
+ }
+
+ for ( std::string::size_type i = 0; i < len; ++i )
+ {
+ if ( trans_table[ (int) str[i] ] != -1 )
+ {
+ s += table[ str[i] ];
+ }
+ }
+
+ return s;
+
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string zfill( const std::string & str, int width )
+ {
+ int len = (int)str.size();
+
+ if ( len >= width )
+ {
+ return str;
+ }
+
+ std::string s( str );
+
+ int fill = width - len;
+
+ s = std::string( fill, '0' ) + s;
+
+
+ if ( s[fill] == '+' || s[fill] == '-' )
+ {
+ s[0] = s[fill];
+ s[fill] = '0';
+ }
+
+ return s;
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string ljust( const std::string & str, int width )
+ {
+ std::string::size_type len = str.size();
+ if ( (( int ) len ) >= width ) return str;
+ return str + std::string( width - len, ' ' );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string rjust( const std::string & str, int width )
+ {
+ std::string::size_type len = str.size();
+ if ( (( int ) len ) >= width ) return str;
+ return std::string( width - len, ' ' ) + str;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string center( const std::string & str, int width )
+ {
+ int len = (int) str.size();
+ int marg, left;
+
+ if ( len >= width ) return str;
+
+ marg = width - len;
+ left = marg / 2 + (marg & width & 1);
+
+ return std::string( left, ' ' ) + str + std::string( marg - left, ' ' );
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string slice( const std::string & str, int start, int end )
+ {
+ ADJUST_INDICES(start, end, (int) str.size());
+ if ( start >= end ) return "";
+ return str.substr( start, end - start );
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int find( const std::string & str, const std::string & sub, int start, int end )
+ {
+ ADJUST_INDICES(start, end, (int) str.size());
+
+ std::string::size_type result = str.find( sub, start );
+
+ // If we cannot find the string, or if the end-point of our found substring is past
+ // the allowed end limit, return that it can't be found.
+ if( result == std::string::npos ||
+ (result + sub.size() > (std::string::size_type)end) )
+ {
+ return -1;
+ }
+
+ return (int) result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int index( const std::string & str, const std::string & sub, int start, int end )
+ {
+ return find( str, sub, start, end );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int rfind( const std::string & str, const std::string & sub, int start, int end )
+ {
+ ADJUST_INDICES(start, end, (int) str.size());
+
+ std::string::size_type result = str.rfind( sub, end );
+
+ if( result == std::string::npos ||
+ result < (std::string::size_type)start ||
+ (result + sub.size() > (std::string::size_type)end))
+ return -1;
+
+ return (int)result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int rindex( const std::string & str, const std::string & sub, int start, int end )
+ {
+ return rfind( str, sub, start, end );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string expandtabs( const std::string & str, int tabsize )
+ {
+ std::string s( str );
+
+ std::string::size_type len = str.size(), i = 0;
+ int offset = 0;
+
+ int j = 0;
+
+ for ( i = 0; i < len; ++i )
+ {
+ if ( str[i] == '\t' )
+ {
+
+ if ( tabsize > 0 )
+ {
+ int fillsize = tabsize - (j % tabsize);
+ j += fillsize;
+ s.replace( i + offset, 1, std::string( fillsize, ' ' ));
+ offset += fillsize - 1;
+ }
+ else
+ {
+ s.replace( i + offset, 1, "" );
+ offset -= 1;
+ }
+
+ }
+ else
+ {
+ j++;
+
+ if (str[i] == '\n' || str[i] == '\r')
+ {
+ j = 0;
+ }
+ }
+ }
+
+ return s;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ int count( const std::string & str, const std::string & substr, int start, int end )
+ {
+ int nummatches = 0;
+ int cursor = start;
+
+ while ( 1 )
+ {
+ cursor = find( str, substr, cursor, end );
+
+ if ( cursor < 0 ) break;
+
+ cursor += (int) substr.size();
+ nummatches += 1;
+ }
+
+ return nummatches;
+
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count )
+ {
+ int sofar = 0;
+ int cursor = 0;
+ std::string s( str );
+
+ std::string::size_type oldlen = oldstr.size(), newlen = newstr.size();
+
+ while ( ( cursor = find( s, oldstr, cursor ) ) != -1 )
+ {
+ if ( count > -1 && sofar >= count )
+ {
+ break;
+ }
+
+ s.replace( cursor, oldlen, newstr );
+
+ cursor += (int) newlen;
+ ++sofar;
+ }
+
+ return s;
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends )
+ {
+ result.clear();
+ std::string::size_type len = str.size(), i, j, eol;
+
+ for (i = j = 0; i < len; )
+ {
+ while (i < len && str[i] != '\n' && str[i] != '\r') i++;
+
+ eol = i;
+ if (i < len)
+ {
+ if (str[i] == '\r' && i + 1 < len && str[i+1] == '\n')
+ {
+ i += 2;
+ }
+ else
+ {
+ i++;
+ }
+ if (keepends)
+ eol = i;
+
+ }
+
+ result.push_back( str.substr( j, eol - j ) );
+ j = i;
+
+ }
+
+ if (j < len)
+ {
+ result.push_back( str.substr( j, len - j ) );
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ std::string mul( const std::string & str, int n )
+ {
+ // Early exits
+ if (n <= 0) return "";
+ if (n == 1) return str;
+
+ std::ostringstream os;
+ for(int i=0; i<n; ++i)
+ {
+ os << str;
+ }
+ return os.str();
+ }
+
+
+
+namespace os
+{
+namespace path
+{
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+ /// These functions are C++ ports of the python2.6 versions of os.path,
+ /// and come from genericpath.py, ntpath.py, posixpath.py
+
+ /// Split a pathname into drive and path specifiers.
+ /// Returns drivespec, pathspec. Either part may be empty.
+ void splitdrive_nt(std::string & drivespec, std::string & pathspec,
+ const std::string & p)
+ {
+ if(pystring::slice(p, 1, 2) == ":")
+ {
+ std::string path = p; // In case drivespec == p
+ drivespec = pystring::slice(path, 0, 2);
+ pathspec = pystring::slice(path, 2);
+ }
+ else
+ {
+ drivespec = "";
+ pathspec = p;
+ }
+ }
+
+ // On Posix, drive is always empty
+ void splitdrive_posix(std::string & drivespec, std::string & pathspec,
+ const std::string & path)
+ {
+ drivespec = "";
+ pathspec = path;
+ }
+
+ void splitdrive(std::string & drivespec, std::string & pathspec,
+ const std::string & path)
+ {
+#ifdef WINDOWS
+ return splitdrive_nt(drivespec, pathspec, path);
+#else
+ return splitdrive_posix(drivespec, pathspec, path);
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ // Test whether a path is absolute
+ // In windows, if the character to the right of the colon
+ // is a forward or backslash it's absolute.
+ bool isabs_nt(const std::string & path)
+ {
+ std::string drivespec, pathspec;
+ splitdrive_nt(drivespec, pathspec, path);
+ if(pathspec.empty()) return false;
+ return ((pathspec[0] == '/') || (pathspec[0] == '\\'));
+ }
+
+ bool isabs_posix(const std::string & s)
+ {
+ return pystring::startswith(s, "/");
+ }
+
+ bool isabs(const std::string & path)
+ {
+#ifdef WINDOWS
+ return isabs_nt(path);
+#else
+ return isabs_posix(path);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ std::string abspath_nt(const std::string & path, const std::string & cwd)
+ {
+ std::string p = path;
+ if(!isabs_nt(p)) p = join_nt(cwd, p);
+ return normpath_nt(p);
+ }
+
+ std::string abspath_posix(const std::string & path, const std::string & cwd)
+ {
+ std::string p = path;
+ if(!isabs_posix(p)) p = join_posix(cwd, p);
+ return normpath_posix(p);
+ }
+
+ std::string abspath(const std::string & path, const std::string & cwd)
+ {
+#ifdef WINDOWS
+ return abspath_nt(path, cwd);
+#else
+ return abspath_posix(path, cwd);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ std::string join_nt(const std::vector< std::string > & paths)
+ {
+ if(paths.empty()) return "";
+ if(paths.size() == 1) return paths[0];
+
+ std::string path = paths[0];
+
+ for(unsigned int i=1; i<paths.size(); ++i)
+ {
+ std::string b = paths[i];
+
+ bool b_nts = false;
+ if(path.empty())
+ {
+ b_nts = true;
+ }
+ else if(isabs_nt(b))
+ {
+ // This probably wipes out path so far. However, it's more
+ // complicated if path begins with a drive letter:
+ // 1. join('c:', '/a') == 'c:/a'
+ // 2. join('c:/', '/a') == 'c:/a'
+ // But
+ // 3. join('c:/a', '/b') == '/b'
+ // 4. join('c:', 'd:/') = 'd:/'
+ // 5. join('c:/', 'd:/') = 'd:/'
+
+ if( (pystring::slice(path, 1, 2) != ":") ||
+ (pystring::slice(b, 1, 2) == ":") )
+ {
+ // Path doesnt start with a drive letter
+ b_nts = true;
+ }
+ // Else path has a drive letter, and b doesn't but is absolute.
+ else if((path.size()>3) ||
+ ((path.size()==3) && !pystring::endswith(path, "/") && !pystring::endswith(path, "\\")))
+ {
+ b_nts = true;
+ }
+ }
+
+ if(b_nts)
+ {
+ path = b;
+ }
+ else
+ {
+ // Join, and ensure there's a separator.
+ // assert len(path) > 0
+ if( pystring::endswith(path, "/") || pystring::endswith(path, "\\"))
+ {
+ if(pystring::startswith(b,"/") || pystring::startswith(b,"\\"))
+ {
+ path += pystring::slice(b, 1);
+ }
+ else
+ {
+ path += b;
+ }
+ }
+ else if(pystring::endswith(path, ":"))
+ {
+ path += b;
+ }
+ else if(!b.empty())
+ {
+ if(pystring::startswith(b,"/") || pystring::startswith(b,"\\"))
+ {
+ path += b;
+ }
+ else
+ {
+ path += "\\" + b;
+ }
+ }
+ else
+ {
+ // path is not empty and does not end with a backslash,
+ // but b is empty; since, e.g., split('a/') produces
+ // ('a', ''), it's best if join() adds a backslash in
+ // this case.
+ path += "\\";
+ }
+ }
+ }
+
+ return path;
+ }
+
+ // Join two or more pathname components, inserting "\\" as needed.
+ std::string join_nt(const std::string & a, const std::string & b)
+ {
+ std::vector< std::string > paths(2);
+ paths[0] = a;
+ paths[1] = b;
+ return join_nt(paths);
+ }
+
+ // Join pathnames.
+ // If any component is an absolute path, all previous path components
+ // will be discarded.
+ // Ignore the previous parts if a part is absolute.
+ // Insert a '/' unless the first part is empty or already ends in '/'.
+
+ std::string join_posix(const std::vector< std::string > & paths)
+ {
+ if(paths.empty()) return "";
+ if(paths.size() == 1) return paths[0];
+
+ std::string path = paths[0];
+
+ for(unsigned int i=1; i<paths.size(); ++i)
+ {
+ std::string b = paths[i];
+ if(pystring::startswith(b, "/"))
+ {
+ path = b;
+ }
+ else if(path.empty() || pystring::endswith(path, "/"))
+ {
+ path += b;
+ }
+ else
+ {
+ path += "/" + b;
+ }
+ }
+
+ return path;
+ }
+
+ std::string join_posix(const std::string & a, const std::string & b)
+ {
+ std::vector< std::string > paths(2);
+ paths[0] = a;
+ paths[1] = b;
+ return join_posix(paths);
+ }
+
+ std::string join(const std::string & path1, const std::string & path2)
+ {
+#ifdef WINDOWS
+ return join_nt(path1, path2);
+#else
+ return join_posix(path1, path2);
+#endif
+ }
+
+
+ std::string join(const std::vector< std::string > & paths)
+ {
+#ifdef WINDOWS
+ return join_nt(paths);
+#else
+ return join_posix(paths);
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+
+ // Split a pathname.
+ // Return (head, tail) where tail is everything after the final slash.
+ // Either part may be empty
+
+ void split_nt(std::string & head, std::string & tail, const std::string & path)
+ {
+ std::string d, p;
+ splitdrive_nt(d, p, path);
+
+ // set i to index beyond p's last slash
+ int i = (int)p.size();
+
+ while(i>0 && (p[i-1] != '\\') && (p[i-1] != '/'))
+ {
+ i = i - 1;
+ }
+
+ head = pystring::slice(p,0,i);
+ tail = pystring::slice(p,i); // now tail has no slashes
+
+ // remove trailing slashes from head, unless it's all slashes
+ std::string head2 = head;
+ while(!head2.empty() && ((pystring::slice(head2,-1) == "/") ||
+ (pystring::slice(head2,-1) == "\\")))
+ {
+ head2 = pystring::slice(head,0,-1);
+ }
+
+ if(!head2.empty()) head = head2;
+ head = d + head;
+ }
+
+
+ // Split a path in head (everything up to the last '/') and tail (the
+ // rest). If the path ends in '/', tail will be empty. If there is no
+ // '/' in the path, head will be empty.
+ // Trailing '/'es are stripped from head unless it is the root.
+
+ void split_posix(std::string & head, std::string & tail, const std::string & p)
+ {
+ int i = pystring::rfind(p, "/") + 1;
+
+ head = pystring::slice(p,0,i);
+ tail = pystring::slice(p,i);
+
+ if(!head.empty() && (head != pystring::mul("/", (int) head.size())))
+ {
+ head = pystring::rstrip(head, "/");
+ }
+ }
+
+ void split(std::string & head, std::string & tail, const std::string & path)
+ {
+#ifdef WINDOWS
+ return split_nt(head, tail, path);
+#else
+ return split_posix(head, tail, path);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ std::string basename_nt(const std::string & path)
+ {
+ std::string head, tail;
+ split_nt(head, tail, path);
+ return tail;
+ }
+
+ std::string basename_posix(const std::string & path)
+ {
+ std::string head, tail;
+ split_posix(head, tail, path);
+ return tail;
+ }
+
+ std::string basename(const std::string & path)
+ {
+#ifdef WINDOWS
+ return basename_nt(path);
+#else
+ return basename_posix(path);
+#endif
+ }
+
+ std::string dirname_nt(const std::string & path)
+ {
+ std::string head, tail;
+ split_nt(head, tail, path);
+ return head;
+ }
+
+ std::string dirname_posix(const std::string & path)
+ {
+ std::string head, tail;
+ split_posix(head, tail, path);
+ return head;
+ }
+
+ std::string dirname(const std::string & path)
+ {
+#ifdef WINDOWS
+ return dirname_nt(path);
+#else
+ return dirname_posix(path);
+#endif
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ // Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
+ std::string normpath_nt(const std::string & p)
+ {
+ std::string path = p;
+ path = pystring::replace(path, "/","\\");
+
+ std::string prefix;
+ splitdrive_nt(prefix, path, path);
+
+ // We need to be careful here. If the prefix is empty, and the path starts
+ // with a backslash, it could either be an absolute path on the current
+ // drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It
+ // is therefore imperative NOT to collapse multiple backslashes blindly in
+ // that case.
+ // The code below preserves multiple backslashes when there is no drive
+ // letter. This means that the invalid filename \\\a\b is preserved
+ // unchanged, where a\\\b is normalised to a\b. It's not clear that there
+ // is any better behaviour for such edge cases.
+
+ if(prefix.empty())
+ {
+ // No drive letter - preserve initial backslashes
+ while(pystring::slice(path,0,1) == "\\")
+ {
+ prefix = prefix + "\\";
+ path = pystring::slice(path,1);
+ }
+ }
+ else
+ {
+ // We have a drive letter - collapse initial backslashes
+ if(pystring::startswith(path, "\\"))
+ {
+ prefix = prefix + "\\";
+ path = pystring::lstrip(path, "\\");
+ }
+ }
+
+ std::vector<std::string> comps;
+ pystring::split(path, comps, "\\");
+
+ int i = 0;
+
+ while(i<(int)comps.size())
+ {
+ if(comps[i].empty() || comps[i] == ".")
+ {
+ comps.erase(comps.begin()+i);
+ }
+ else if(comps[i] == "..")
+ {
+ if(i>0 && comps[i-1] != "..")
+ {
+ comps.erase(comps.begin()+i-1, comps.begin()+i+1);
+ i -= 1;
+ }
+ else if(i == 0 && pystring::endswith(prefix, "\\"))
+ {
+ comps.erase(comps.begin()+i);
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ // If the path is now empty, substitute '.'
+ if(prefix.empty() && comps.empty())
+ {
+ comps.push_back(".");
+ }
+
+ return prefix + pystring::join("\\", comps);
+ }
+
+ // Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
+ // It should be understood that this may change the meaning of the path
+ // if it contains symbolic links!
+ // Normalize path, eliminating double slashes, etc.
+
+ std::string normpath_posix(const std::string & p)
+ {
+ if(p.empty()) return ".";
+
+ std::string path = p;
+
+ int initial_slashes = pystring::startswith(path,"/") ? 1 : 0;
+
+ // POSIX allows one or two initial slashes, but treats three or more
+ // as single slash.
+
+ if (initial_slashes && pystring::startswith(path,"//")
+ && !pystring::startswith(path,"///"))
+ initial_slashes = 2;
+
+ std::vector<std::string> comps, new_comps;
+ pystring::split(path, comps, "/");
+
+ for(unsigned int i=0; i<comps.size(); ++i)
+ {
+ std::string comp = comps[i];
+ if(comp.empty() || comp == ".")
+ continue;
+
+ if( (comp != "..") || ((initial_slashes == 0) && new_comps.empty()) ||
+ (!new_comps.empty() && new_comps[new_comps.size()-1] == ".."))
+ {
+ new_comps.push_back(comp);
+ }
+ else if (!new_comps.empty())
+ {
+ new_comps.pop_back();
+ }
+ }
+
+ path = pystring::join("/", new_comps);
+
+ if (initial_slashes > 0)
+ path = pystring::mul("/",initial_slashes) + path;
+
+ if(path.empty()) return ".";
+ return path;
+ }
+
+ std::string normpath(const std::string & path)
+ {
+#ifdef WINDOWS
+ return normpath_nt(path);
+#else
+ return normpath_posix(path);
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ ///
+ ///
+
+ // Split the extension from a pathname.
+ // Extension is everything from the last dot to the end, ignoring
+ // leading dots. Returns "(root, ext)"; ext may be empty.
+ // It is always true that root + ext == p
+
+ void splitext_generic(std::string & root, std::string & ext,
+ const std::string & p,
+ const std::string & sep,
+ const std::string & altsep,
+ const std::string & extsep)
+ {
+ int sepIndex = pystring::rfind(p, sep);
+ if(!altsep.empty())
+ {
+ int altsepIndex = pystring::rfind(p, altsep);
+ sepIndex = std::max(sepIndex, altsepIndex);
+ }
+
+ int dotIndex = pystring::rfind(p, extsep);
+ if(dotIndex > sepIndex)
+ {
+ // Skip all leading dots
+ int filenameIndex = sepIndex + 1;
+
+ while(filenameIndex < dotIndex)
+ {
+ if(pystring::slice(p,filenameIndex) != extsep)
+ {
+ root = pystring::slice(p, 0, dotIndex);
+ ext = pystring::slice(p, dotIndex);
+ return;
+ }
+
+ filenameIndex += 1;
+ }
+ }
+
+ root = p;
+ ext = "";
+ }
+
+ void splitext_nt(std::string & root, std::string & ext, const std::string & path)
+ {
+ return splitext_generic(root, ext, path,
+ "\\", "/", ".");
+ }
+
+ void splitext_posix(std::string & root, std::string & ext, const std::string & path)
+ {
+ return splitext_generic(root, ext, path,
+ "/", "", ".");
+ }
+
+ void splitext(std::string & root, std::string & ext, const std::string & path)
+ {
+#ifdef WINDOWS
+ return splitext_nt(root, ext, path);
+#else
+ return splitext_posix(root, ext, path);
+#endif
+ }
+
+} // namespace path
+} // namespace os
+
+
+}//namespace pystring
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/core/pystring/pystring.h b/src/core/pystring/pystring.h
new file mode 100644
index 0000000..f0729db
--- /dev/null
+++ b/src/core/pystring/pystring.h
@@ -0,0 +1,438 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// Neither the name of the organization Sony Pictures Imageworks nor the
+// names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_OCIO_PYSTRING_H
+#define INCLUDED_OCIO_PYSTRING_H
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include <string>
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+// Version 1.1.2
+// https://github.com/imageworks/pystring/tarball/v1.1.2
+
+namespace pystring
+{
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @mainpage pystring
+ ///
+ /// This is a set of functions matching the interface and behaviors of python string methods
+ /// (as of python 2.3) using std::string.
+ ///
+ /// Overlapping functionality ( such as index and slice/substr ) of std::string is included
+ /// to match python interfaces.
+ ///
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @defgroup functions pystring
+ /// @{
+
+
+ #define MAX_32BIT_INT 2147483647
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with only its first character capitalized.
+ ///
+ std::string capitalize( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return centered in a string of length width. Padding is done using spaces.
+ ///
+ std::string center( const std::string & str, int width );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the number of occurrences of substring sub in string S[start:end]. Optional
+ /// arguments start and end are interpreted as in slice notation.
+ ///
+ int count( const std::string & str, const std::string & substr, int start = 0, int end = MAX_32BIT_INT);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return True if the string ends with the specified suffix, otherwise return False. With
+ /// optional start, test beginning at that position. With optional end, stop comparing at that position.
+ ///
+ bool endswith( const std::string & str, const std::string & suffix, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string where all tab characters are expanded using spaces. If tabsize
+ /// is not given, a tab size of 8 characters is assumed.
+ ///
+ std::string expandtabs( const std::string & str, int tabsize = 8);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the lowest index in the string where substring sub is found, such that sub is
+ /// contained in the range [start, end). Optional arguments start and end are interpreted as
+ /// in slice notation. Return -1 if sub is not found.
+ ///
+ int find( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Synonym of find right now. Python version throws exceptions. This one currently doesn't
+ ///
+ int index( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all characters in the string are alphanumeric and there is at least one
+ /// character, false otherwise.
+ ///
+ bool isalnum( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all characters in the string are alphabetic and there is at least one
+ /// character, false otherwise
+ ///
+ bool isalpha( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all characters in the string are digits and there is at least one
+ /// character, false otherwise.
+ ///
+ bool isdigit( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all cased characters in the string are lowercase and there is at least one
+ /// cased character, false otherwise.
+ ///
+ bool islower( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if there are only whitespace characters in the string and there is at least
+ /// one character, false otherwise.
+ ///
+ bool isspace( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if the string is a titlecased string and there is at least one character,
+ /// i.e. uppercase characters may only follow uncased characters and lowercase characters only
+ /// cased ones. Return false otherwise.
+ ///
+ bool istitle( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return true if all cased characters in the string are uppercase and there is at least one
+ /// cased character, false otherwise.
+ ///
+ bool isupper( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a string which is the concatenation of the strings in the sequence seq.
+ /// The separator between elements is the str argument
+ ///
+ std::string join( const std::string & str, const std::vector< std::string > & seq );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the string left justified in a string of length width. Padding is done using
+ /// spaces. The original string is returned if width is less than str.size().
+ ///
+ std::string ljust( const std::string & str, int width );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string converted to lowercase.
+ ///
+ std::string lower( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with leading characters removed. If chars is omitted or None,
+ /// whitespace characters are removed. If given and not "", chars must be a string; the
+ /// characters in the string will be stripped from the beginning of the string this method
+ /// is called on (argument "str" ).
+ ///
+ std::string lstrip( const std::string & str, const std::string & chars = "" );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string, concatenated N times, together.
+ /// Corresponds to the __mul__ operator.
+ ///
+ std::string mul( const std::string & str, int n);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the string around first occurance of sep.
+ /// Three strings will always placed into result. If sep is found, the strings will
+ /// be the text before sep, sep itself, and the remaining text. If sep is
+ /// not found, the original string will be returned with two empty strings.
+ ///
+ void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with all occurrences of substring old replaced by new. If
+ /// the optional argument count is given, only the first count occurrences are replaced.
+ ///
+ std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count = -1);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the highest index in the string where substring sub is found, such that sub is
+ /// contained within s[start,end]. Optional arguments start and end are interpreted as in
+ /// slice notation. Return -1 on failure.
+ ///
+ int rfind( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Currently a synonym of rfind. The python version raises exceptions. This one currently
+ /// does not
+ ///
+ int rindex( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the string right justified in a string of length width. Padding is done using
+ /// spaces. The original string is returned if width is less than str.size().
+ ///
+ std::string rjust( const std::string & str, int width);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the string around last occurance of sep.
+ /// Three strings will always placed into result. If sep is found, the strings will
+ /// be the text before sep, sep itself, and the remaining text. If sep is
+ /// not found, the original string will be returned with two empty strings.
+ ///
+ void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with trailing characters removed. If chars is "", whitespace
+ /// characters are removed. If not "", the characters in the string will be stripped from the
+ /// end of the string this method is called on.
+ ///
+ std::string rstrip( const std::string & str, const std::string & chars = "" );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
+ /// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
+ /// any whitespace string is a separator.
+ ///
+ void split( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
+ /// Does a number of splits starting at the end of the string, the result still has the
+ /// split strings in their original order.
+ /// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
+ /// any whitespace string is a separator.
+ ///
+ void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a list of the lines in the string, breaking at line boundaries. Line breaks
+ /// are not included in the resulting list unless keepends is given and true.
+ ///
+ void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends = false );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return True if string starts with the prefix, otherwise return False. With optional start,
+ /// test string beginning at that position. With optional end, stop comparing string at that
+ /// position
+ ///
+ bool startswith( const std::string & str, const std::string & prefix, int start = 0, int end = MAX_32BIT_INT );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with leading and trailing characters removed. If chars is "",
+ /// whitespace characters are removed. If given not "", the characters in the string will be
+ /// stripped from the both ends of the string this method is called on.
+ ///
+ std::string strip( const std::string & str, const std::string & chars = "" );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string with uppercase characters converted to lowercase and vice versa.
+ ///
+ std::string swapcase( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a titlecased version of the string: words start with uppercase characters,
+ /// all remaining cased characters are lowercase.
+ ///
+ std::string title( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string where all characters occurring in the optional argument
+ /// deletechars are removed, and the remaining characters have been mapped through the given
+ /// translation table, which must be a string of length 256.
+ ///
+ std::string translate( const std::string & str, const std::string & table, const std::string & deletechars = "");
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a copy of the string converted to uppercase.
+ ///
+ std::string upper( const std::string & str );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the numeric string left filled with zeros in a string of length width. The original
+ /// string is returned if width is less than str.size().
+ ///
+ std::string zfill( const std::string & str, int width );
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief function matching python's slice functionality.
+ ///
+ std::string slice( const std::string & str, int start = 0, int end = MAX_32BIT_INT);
+
+ ///
+ /// @ }
+ ///
+
+
+namespace os
+{
+namespace path
+{
+ // All of the function below have three versions.
+ // Example:
+ // join(...)
+ // join_nt(...)
+ // join_posix(...)
+ //
+ // The regular function dispatches to the other versions - based on the OS
+ // at compile time - to match the result you'd get from the python
+ // interepreter on the same operating system
+ //
+ // Should you want to 'lock off' to a particular version of the string
+ // manipulation across *all* operating systems, use the version with the
+ // _OS you are interested in. I.e., you can use posix style path joining,
+ // even on Windows, with join_posix.
+ //
+ // The naming, (nt, posix) matches the cpython source implementation.
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @defgroup functions pystring::os::path
+ /// @{
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the base name of pathname path. This is the second half of the pair returned
+ /// by split(path). Note that the result of this function is different from the Unix basename
+ /// program; where basename for '/foo/bar/' returns 'bar', the basename() function returns an
+ /// empty string ('').
+
+ std::string basename(const std::string & path);
+ std::string basename_nt(const std::string & path);
+ std::string basename_posix(const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return the directory name of pathname path. This is the first half of the pair
+ /// returned by split(path).
+
+ std::string dirname(const std::string & path);
+ std::string dirname_nt(const std::string & path);
+ std::string dirname_posix(const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return True if path is an absolute pathname. On Unix, that means it begins with a
+ /// slash, on Windows that it begins with a (back)slash after chopping off a potential drive
+ /// letter.
+
+ bool isabs(const std::string & path);
+ bool isabs_nt(const std::string & path);
+ bool isabs_posix(const std::string & s);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Return a normalized absolutized version of the pathname path.
+ ///
+ /// NOTE: This differs from the interface of the python equivalent in that it requires you
+ /// to pass in the current working directory as an argument.
+
+ std::string abspath(const std::string & path, const std::string & cwd);
+ std::string abspath_nt(const std::string & path, const std::string & cwd);
+ std::string abspath_posix(const std::string & path, const std::string & cwd);
+
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Join one or more path components intelligently. If any component is an absolute
+ /// path, all previous components (on Windows, including the previous drive letter, if there
+ /// was one) are thrown away, and joining continues. The return value is the concatenation of
+ /// path1, and optionally path2, etc., with exactly one directory separator (os.sep) inserted
+ /// between components, unless path2 is empty. Note that on Windows, since there is a current
+ /// directory for each drive, os.path.join("c:", "foo") represents a path relative to the
+ /// current directory on drive C: (c:foo), not c:\foo.
+
+ /// This dispatches based on the compilation OS
+ std::string join(const std::string & path1, const std::string & path2);
+ std::string join_nt(const std::string & path1, const std::string & path2);
+ std::string join_posix(const std::string & path1, const std::string & path2);
+
+ std::string join(const std::vector< std::string > & paths);
+ std::string join_nt(const std::vector< std::string > & paths);
+ std::string join_posix(const std::vector< std::string > & paths);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Normalize a pathname. This collapses redundant separators and up-level references
+ /// so that A//B, A/B/, A/./B and A/foo/../B all become A/B. It does not normalize the case
+ /// (use normcase() for that). On Windows, it converts forward slashes to backward slashes.
+ /// It should be understood that this may change the meaning of the path if it contains
+ /// symbolic links!
+
+ std::string normpath(const std::string & path);
+ std::string normpath_nt(const std::string & path);
+ std::string normpath_posix(const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the pathname path into a pair, (head, tail) where tail is the last pathname
+ /// component and head is everything leading up to that. The tail part will never contain a
+ /// slash; if path ends in a slash, tail will be empty. If there is no slash in path, head
+ /// will be empty. If path is empty, both head and tail are empty. Trailing slashes are
+ /// stripped from head unless it is the root (one or more slashes only). In all cases,
+ /// join(head, tail) returns a path to the same location as path (but the strings may
+ /// differ).
+
+ void split(std::string & head, std::string & tail, const std::string & path);
+ void split_nt(std::string & head, std::string & tail, const std::string & path);
+ void split_posix(std::string & head, std::string & tail, const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the pathname path into a pair (drive, tail) where drive is either a drive
+ /// specification or the empty string. On systems which do not use drive specifications,
+ /// drive will always be the empty string. In all cases, drive + tail will be the same as
+ /// path.
+
+ void splitdrive(std::string & drivespec, std::string & pathspec, const std::string & path);
+ void splitdrive_nt(std::string & drivespec, std::string & pathspec, const std::string & p);
+ void splitdrive_posix(std::string & drivespec, std::string & pathspec, const std::string & path);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ /// @brief Split the pathname path into a pair (root, ext) such that root + ext == path, and
+ /// ext is empty or begins with a period and contains at most one period. Leading periods on
+ /// the basename are ignored; splitext('.cshrc') returns ('.cshrc', '').
+
+ void splitext(std::string & root, std::string & ext, const std::string & path);
+ void splitext_nt(std::string & root, std::string & ext, const std::string & path);
+ void splitext_posix(std::string & root, std::string & ext, const std::string & path);
+
+ ///
+ /// @ }
+ ///
+} // namespace path
+} // namespace os
+
+} // namespace pystring
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/core_tests/CMakeLists.txt b/src/core_tests/CMakeLists.txt
new file mode 100644
index 0000000..de56210
--- /dev/null
+++ b/src/core_tests/CMakeLists.txt
@@ -0,0 +1,51 @@
+###############################################################################
+### CORE UNIT TESTS ###
+
+add_definitions("-DOCIO_UNIT_TEST")
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${EXTERNAL_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}/ext/oiio/src/include
+ )
+
+file( GLOB_RECURSE core_test_src_files "${CMAKE_SOURCE_DIR}/src/core/*.cpp" )
+
+add_executable(ocio_core_tests ${core_test_src_files})
+
+if(USE_EXTERNAL_TINYXML)
+ target_link_libraries(ocio_core_tests ${TINYXML_LIBRARIES})
+else(USE_EXTERNAL_TINYXML)
+ add_dependencies(ocio_core_tests tinyxml)
+endif(USE_EXTERNAL_TINYXML)
+
+if(USE_EXTERNAL_YAML)
+ target_link_libraries(ocio_core_tests ${YAML_CPP_LIBRARIES})
+else(USE_EXTERNAL_YAML)
+ add_dependencies(ocio_core_tests YAML_CPP_LOCAL)
+endif(USE_EXTERNAL_YAML)
+
+set_target_properties(ocio_core_tests PROPERTIES
+ COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
+ LINK_FLAGS "${EXTERNAL_LINK_FLAGS}")
+if(WIN32)
+ target_link_libraries(ocio_core_tests
+ debug ${EXTERNAL_DEBUG_LIBRARIES}
+ optimized ${EXTERNAL_OPTIMIZED_LIBRARIES}
+ general ${EXTERNAL_GENERAL_LIBRARIES})
+else()
+ target_link_libraries(ocio_core_tests ${EXTERNAL_GENERAL_LIBRARIES})
+endif()
+
+###############################################################################
+### CTEST ###
+
+set(OCIO_TEST_AREA ${CMAKE_CURRENT_BINARY_DIR})
+
+message(STATUS "Create ocio_core_tests.sh.in from ocio_core_tests.sh")
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ocio_core_tests.sh.in
+ ${CMAKE_CURRENT_BINARY_DIR}/ocio_core_tests.sh @ONLY)
+
+add_test(NAME ocio_core_tests
+ COMMAND /bin/sh ${CMAKE_CURRENT_BINARY_DIR}/ocio_core_tests.sh)
diff --git a/src/core_tests/ocio_core_tests.sh.in b/src/core_tests/ocio_core_tests.sh.in
new file mode 100644
index 0000000..5667a42
--- /dev/null
+++ b/src/core_tests/ocio_core_tests.sh.in
@@ -0,0 +1,8 @@
+#!/bin/sh
+OCIO_TEST_AREA=@OCIO_TEST_AREA@ \
+OCIO_DATA_ROOT=@OCIO_TEST_AREA@/test_search \
+OCIO_TEST1=foobar \
+OCIO_JOB=meatballs \
+OCIO_SEQ=cheesecake \
+OCIO_SHOT=mb-cc-001 \
+@CMAKE_CURRENT_BINARY_DIR@/ocio_core_tests --log_level=test_suite; \ No newline at end of file
diff --git a/src/jniglue/CMakeLists.txt b/src/jniglue/CMakeLists.txt
new file mode 100644
index 0000000..aedb514
--- /dev/null
+++ b/src/jniglue/CMakeLists.txt
@@ -0,0 +1,92 @@
+
+include_directories(
+ ${JNI_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+)
+
+set(JNIOCIO_CLASSES
+ # Core
+ org.OpenColorIO.ExceptionBase
+ org.OpenColorIO.ExceptionMissingFile
+ org.OpenColorIO.Globals
+ org.OpenColorIO.Config
+ org.OpenColorIO.ColorSpace
+ org.OpenColorIO.Processor
+ org.OpenColorIO.GpuShaderDesc
+ org.OpenColorIO.Context
+ org.OpenColorIO.Look
+ org.OpenColorIO.ImageDesc
+ org.OpenColorIO.Transform
+ org.OpenColorIO.PackedImageDesc
+ org.OpenColorIO.PlanarImageDesc
+ org.OpenColorIO.Baker
+ # Enums
+ org.OpenColorIO.LoggingLevel
+ org.OpenColorIO.ColorSpaceDirection
+ org.OpenColorIO.TransformDirection
+ org.OpenColorIO.Interpolation
+ org.OpenColorIO.BitDepth
+ org.OpenColorIO.Allocation
+ org.OpenColorIO.GpuLanguage
+ # Transforms
+ org.OpenColorIO.AllocationTransform
+ org.OpenColorIO.CDLTransform
+ org.OpenColorIO.ColorSpaceTransform
+ org.OpenColorIO.DisplayTransform
+ org.OpenColorIO.ExponentTransform
+ org.OpenColorIO.FileTransform
+ org.OpenColorIO.GroupTransform
+ org.OpenColorIO.LogTransform
+ org.OpenColorIO.LookTransform
+ org.OpenColorIO.MatrixTransform
+ org.OpenColorIO.TruelightTransform
+)
+
+file(GLOB JNIOCIO_JAVAS "org/OpenColorIO/*.java")
+
+message(STATUS "Creating Jar Manifest.txt")
+configure_file(${CMAKE_SOURCE_DIR}/src/jniglue/Manifest.txt.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Manifest.txt @ONLY)
+
+message(STATUS "Creating LoadLibrary.java")
+configure_file(${CMAKE_SOURCE_DIR}/src/jniglue/LoadLibrary.java.in
+ ${CMAKE_CURRENT_BINARY_DIR}/LoadLibrary.java @ONLY)
+list(APPEND JNIOCIO_JAVAS ${CMAKE_CURRENT_BINARY_DIR}/LoadLibrary.java)
+
+set(JNIOCIO_HEADERS)
+set(JNIOCIO_H_INCLUDE "/* DO NOT EDIT THIS FILE - it is machine generated */\n\n")
+foreach(_CLASS ${JNIOCIO_CLASSES})
+ string(REPLACE "." "_" _CLASS_H ${_CLASS})
+ set(_CLASS_H "${_CLASS_H}.h")
+ set(JNIOCIO_HEADERS ${JNIOCIO_HEADERS} "${_CLASS_H}")
+ set(JNIOCIO_H_INCLUDE "${JNIOCIO_H_INCLUDE}#include \"${_CLASS_H}\"\n")
+endforeach()
+message(STATUS "Creating OpenColorIOJNI.h that includes all the ocio jni headers")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/OpenColorIOJNI.h" "${JNIOCIO_H_INCLUDE}")
+
+set(JNIOCIO_JAR "${CMAKE_CURRENT_BINARY_DIR}/OpenColorIO-${OCIO_VERSION}.jar")
+add_custom_command(OUTPUT ${JNIOCIO_HEADERS}
+ COMMAND cmake -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/org/OpenColorIO
+ COMMAND ${Java_JAVAC_EXECUTABLE} -cp ${CMAKE_CURRENT_BINARY_DIR} -d ${CMAKE_CURRENT_BINARY_DIR} ${JNIOCIO_JAVAS}
+ COMMAND ${Java_JAVAH_EXECUTABLE} -jni -force ${JNIOCIO_CLASSES}
+ COMMAND ${Java_JAR_EXECUTABLE} vcfm ${JNIOCIO_JAR} Manifest.txt org
+ IMPLICIT_DEPENDS ${JNIOCIO_JAVAS}
+ COMMENT "Compiling .java files, packaged .jar and creating jni C headers")
+
+file(GLOB JNIOCIO_SRC "*.cpp")
+add_library(OpenColorIO-JNI SHARED ${JNIOCIO_SRC} ${JNIOCIO_HEADERS})
+set_target_properties(OpenColorIO-JNI PROPERTIES
+ VERSION ${OCIO_VERSION}
+ SOVERSION ${SOVERSION})
+if(OCIO_STATIC_JNIGLUE)
+ target_link_libraries(OpenColorIO-JNI OpenColorIO_STATIC)
+else()
+ target_link_libraries(OpenColorIO-JNI OpenColorIO)
+endif()
+
+add_subdirectory(tests)
+
+install(TARGETS OpenColorIO-JNI DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib${LIB_SUFFIX})
+install(FILES ${JNIOCIO_JAR} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/ocio/)
diff --git a/src/jniglue/JNIBaker.cpp b/src/jniglue/JNIBaker.cpp
new file mode 100644
index 0000000..c838b70
--- /dev/null
+++ b/src/jniglue/JNIBaker.cpp
@@ -0,0 +1,264 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<BakerJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Baker_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<BakerRcPtr, BakerJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Baker"), Baker::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Baker_createEditableCopy(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return BuildJObject<BakerRcPtr, BakerJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Baker"), bake->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setConfig(JNIEnv * env, jobject self, jobject config)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, config);
+ bake->setConfig(cfg);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Baker_getConfig(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return BuildJConstObject<ConstConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"), bake->getConfig());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setFormat(JNIEnv * env, jobject self, jstring formatName)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ bake->setFormat(GetJStringValue(env, formatName)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getFormat(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getFormat());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setType(JNIEnv * env, jobject self, jstring type)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ bake->setType(GetJStringValue(env, type)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getType(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getType());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setMetadata(JNIEnv * env, jobject self, jstring metadata)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ bake->setMetadata(GetJStringValue(env, metadata)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getMetadata(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getMetadata());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setInputSpace(JNIEnv * env, jobject self, jstring inputSpace)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ bake->setInputSpace(GetJStringValue(env, inputSpace)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getInputSpace(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getInputSpace());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setShaperSpace(JNIEnv * env, jobject self, jstring shaperSpace)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ bake->setShaperSpace(GetJStringValue(env, shaperSpace)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getShaperSpace(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getShaperSpace());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setTargetSpace(JNIEnv * env, jobject self, jstring targetSpace)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ bake->setTargetSpace(GetJStringValue(env, targetSpace)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getTargetSpace(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getTargetSpace());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setShaperSize(JNIEnv * env, jobject self, jint shapersize)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ return bake->setShaperSize((int)shapersize);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Baker_getShaperSize(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return (jint)bake->getShaperSize();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Baker_setCubeSize(JNIEnv * env, jobject self, jint cubesize)
+{
+ OCIO_JNITRY_ENTER()
+ BakerRcPtr bake = GetEditableJOCIO<BakerRcPtr, BakerJNI>(env, self);
+ return bake->setCubeSize((int)cubesize);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Baker_getCubeSize(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return (jint)bake->getCubeSize();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_bake(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ std::ostringstream os;
+ bake->bake(os);
+ return env->NewStringUTF(os.str().c_str());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Baker_getNumFormats(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return (jint)bake->getNumFormats();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getFormatNameByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getFormatNameByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Baker_getFormatExtensionByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstBakerRcPtr bake = GetConstJOCIO<ConstBakerRcPtr, BakerJNI>(env, self);
+ return env->NewStringUTF(bake->getFormatExtensionByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNIColorSpace.cpp b/src/jniglue/JNIColorSpace.cpp
new file mode 100644
index 0000000..e540ad2
--- /dev/null
+++ b/src/jniglue/JNIColorSpace.cpp
@@ -0,0 +1,239 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<ColorSpaceJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ColorSpace_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<ColorSpaceRcPtr, ColorSpaceJNI>(env, self,
+ env->FindClass("org/OpenColorIO/ColorSpace"), ColorSpace::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ColorSpace_createEditableCopy(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return BuildJObject<ColorSpaceRcPtr, ColorSpaceJNI>(env, self,
+ env->FindClass("org/OpenColorIO/ColorSpace"), col->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpace_getName(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return env->NewStringUTF(col->getName());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setName(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setName(GetJStringValue(env, name)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpace_getFamily(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return env->NewStringUTF(col->getFamily());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setFamily(JNIEnv * env, jobject self, jstring family)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setFamily(GetJStringValue(env, family)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpace_getEqualityGroup(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return env->NewStringUTF(col->getEqualityGroup());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setEqualityGroup(JNIEnv * env, jobject self, jstring equalityGroup)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setEqualityGroup(GetJStringValue(env, equalityGroup)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpace_getDescription(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return env->NewStringUTF(col->getDescription());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setDescription(JNIEnv * env, jobject self, jstring description)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setDescription(GetJStringValue(env, description)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ColorSpace_getBitDepth(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return BuildJEnum(env, "org/OpenColorIO/BitDepth", col->getBitDepth());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setBitDepth(JNIEnv * env, jobject self, jobject bitDepth)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setBitDepth(GetJEnum<BitDepth>(env, bitDepth));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_ColorSpace_isData(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return (jboolean)col->isData();
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setIsData(JNIEnv * env, jobject self, jboolean isData)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setIsData((bool)isData);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ColorSpace_getAllocation(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return BuildJEnum(env, "org/OpenColorIO/Allocation", col->getAllocation());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setAllocation(JNIEnv * env, jobject self, jobject allocation)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setAllocation(GetJEnum<Allocation>(env, allocation));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_ColorSpace_getAllocationNumVars(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ return (jint)col->getAllocationNumVars();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_getAllocationVars(JNIEnv * env, jobject self, jfloatArray vars)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->getAllocationVars(SetJFloatArrayValue(env, vars, "vars", col->getAllocationNumVars())());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setAllocationVars(JNIEnv * env, jobject self, jint numvars, jfloatArray vars)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ col->setAllocationVars((int)numvars, GetJFloatArrayValue(env, vars, "vars", numvars)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ColorSpace_getTransform(JNIEnv * env, jobject self, jobject dir)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceRcPtr col = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ ColorSpaceDirection cd = GetJEnum<ColorSpaceDirection>(env, dir);
+ ConstTransformRcPtr tr = col->getTransform(cd);
+ return BuildJConstObject<ConstTransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(tr)), tr);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpace_setTransform(JNIEnv * env, jobject self, jobject transform, jobject dir)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceRcPtr col = GetEditableJOCIO<ColorSpaceRcPtr, ColorSpaceJNI>(env, self);
+ ColorSpaceDirection cd = GetJEnum<ColorSpaceDirection>(env, dir);
+ ConstTransformRcPtr tran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ col->setTransform(tran, cd);
+ OCIO_JNITRY_EXIT()
+}
diff --git a/src/jniglue/JNIConfig.cpp b/src/jniglue/JNIConfig.cpp
new file mode 100644
index 0000000..fa3873a
--- /dev/null
+++ b/src/jniglue/JNIConfig.cpp
@@ -0,0 +1,607 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<ConfigJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<ConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"), Config::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_CreateFromEnv(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJConstObject<ConstConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"), Config::CreateFromEnv());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_CreateFromFile(JNIEnv * env, jobject self, jstring filename)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJConstObject<ConstConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"),
+ Config::CreateFromFile(GetJStringValue(env, filename)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_CreateFromStream(JNIEnv * env, jobject self, jstring istream)
+{
+ OCIO_JNITRY_ENTER()
+ std::istringstream is;
+ is.str(std::string(GetJStringValue(env, istream)()));
+ return BuildJConstObject<ConstConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"), Config::CreateFromStream(is));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_createEditableCopy(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return BuildJObject<ConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"), cfg->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_sanityCheck(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ cfg->sanityCheck();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getDescription(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getDescription());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setDescription(JNIEnv * env, jobject self, jstring description)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setDescription(GetJStringValue(env, description)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_serialize(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ std::ostringstream os;
+ cfg->serialize(os);
+ return env->NewStringUTF(os.str().c_str());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getCacheID__(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getCacheID());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getCacheID__Lorg_OpenColorIO_Context_2(JNIEnv * env, jobject self, jobject context)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, context);
+ return env->NewStringUTF(cfg->getCacheID(con));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getCurrentContext(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return BuildJConstObject<ConstContextRcPtr, ContextJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Context"), cfg->getCurrentContext());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getSearchPath(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getSearchPath());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setSearchPath(JNIEnv * env, jobject self, jstring path)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setSearchPath(GetJStringValue(env, path)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getWorkingDir(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getWorkingDir());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setWorkingDir(JNIEnv * env, jobject self, jstring dirname)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setWorkingDir(GetJStringValue(env, dirname)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Config_getNumColorSpaces(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jint)cfg->getNumColorSpaces();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getColorSpaceNameByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getColorSpaceNameByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getColorSpace(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return BuildJConstObject<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, self,
+ env->FindClass("org/OpenColorIO/ColorSpace"),
+ cfg->getColorSpace(GetJStringValue(env, name)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Config_getIndexForColorSpace(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jint)cfg->getIndexForColorSpace(GetJStringValue(env, name)());
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_addColorSpace(JNIEnv * env, jobject self, jobject cs)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ ConstColorSpaceRcPtr space = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, cs);
+ cfg->addColorSpace(space);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_clearColorSpaces(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->clearColorSpaces();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_parseColorSpaceFromString(JNIEnv * env, jobject self, jstring str)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->parseColorSpaceFromString(GetJStringValue(env, str)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Config_isStrictParsingEnabled(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jboolean)cfg->isStrictParsingEnabled();
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setStrictParsingEnabled(JNIEnv * env, jobject self, jboolean enabled)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setStrictParsingEnabled((bool)enabled);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setRole(JNIEnv * env, jobject self, jstring role, jstring colorSpaceName)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setRole(GetJStringValue(env, role)(), GetJStringValue(env, colorSpaceName)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Config_getNumRoles(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jint)cfg->getNumRoles();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Config_hasRole(JNIEnv * env, jobject self, jstring role)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jboolean)cfg->hasRole(GetJStringValue(env, role)());
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getRoleName(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getRoleName((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getDefaultDisplay(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getDefaultDisplay());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Config_getNumDisplays(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jint)cfg->getNumDisplays();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getDisplay(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getDisplay((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getDefaultView(JNIEnv * env, jobject self, jstring display)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getDefaultView(GetJStringValue(env, display)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Config_getNumViews(JNIEnv * env, jobject self, jstring display)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jint)cfg->getNumViews(GetJStringValue(env, display)());
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getView(JNIEnv * env, jobject self, jstring display, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getView(GetJStringValue(env, display)(), (int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getDisplayColorSpaceName(JNIEnv * env, jobject self, jstring display, jstring view)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getDisplayColorSpaceName(GetJStringValue(env, display)(),
+ GetJStringValue(env, view)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getDisplayLooks(JNIEnv * env, jobject self, jstring display, jstring view)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getDisplayLooks(GetJStringValue(env, display)(),
+ GetJStringValue(env, view)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// TODO: seems that 4 string params causes a memory error in the JNI layer?
+/*
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_addDisplay(JNIEnv * env, jobject self, jstring display, jstring view, jstring colorSpaceName, jstring looks)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->addDisplay(GetJStringValue(env, display)(),
+ GetJStringValue(env, view)(),
+ GetJStringValue(env, colorSpaceName)(),
+ GetJStringValue(env, looks)());
+
+ OCIO_JNITRY_EXIT()
+}
+*/
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_clearDisplays(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->clearDisplays();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setActiveDisplays(JNIEnv * env, jobject self, jstring displays)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setActiveDisplays(GetJStringValue(env, displays)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getActiveDisplays(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getActiveDisplays());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setActiveViews(JNIEnv * env, jobject self, jstring views)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setActiveViews(GetJStringValue(env, views)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getActiveViews(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getActiveViews());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_getDefaultLumaCoefs(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ cfg->getDefaultLumaCoefs(SetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_setDefaultLumaCoefs(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->setDefaultLumaCoefs(GetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getLook(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return BuildJConstObject<ConstLookRcPtr, LookJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Look"), cfg->getLook(GetJStringValue(env, name)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Config_getNumLooks(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return (jint)cfg->getNumLooks();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Config_getLookNameByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return env->NewStringUTF(cfg->getLookNameByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_addLook(JNIEnv * env, jobject self, jobject look)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ ConstLookRcPtr lok = GetConstJOCIO<ConstLookRcPtr, LookJNI>(env, look);
+ cfg->addLook(lok);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Config_clearLooks(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConfigRcPtr cfg = GetEditableJOCIO<ConfigRcPtr, ConfigJNI>(env, self);
+ cfg->clearLooks();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Lorg_OpenColorIO_Context_2Lorg_OpenColorIO_ColorSpace_2Lorg_OpenColorIO_ColorSpace_2
+ (JNIEnv * env, jobject self, jobject context, jobject srcColorSpace, jobject dstColorSpace)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, context);
+ ConstColorSpaceRcPtr src = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, srcColorSpace);
+ ConstColorSpaceRcPtr dst = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, dstColorSpace);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(con, src, dst));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Lorg_OpenColorIO_ColorSpace_2Lorg_OpenColorIO_ColorSpace_2
+ (JNIEnv * env, jobject self, jobject srcColorSpace, jobject dstColorSpace)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ ConstColorSpaceRcPtr src = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, srcColorSpace);
+ ConstColorSpaceRcPtr dst = GetConstJOCIO<ConstColorSpaceRcPtr, ColorSpaceJNI>(env, dstColorSpace);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(src, dst));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Ljava_lang_String_2Ljava_lang_String_2
+ (JNIEnv * env, jobject self, jstring srcName, jstring dstName)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(
+ GetJStringValue(env, srcName)(), GetJStringValue(env, dstName)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Lorg_OpenColorIO_Context_2Ljava_lang_String_2Ljava_lang_String_2
+ (JNIEnv * env, jobject self, jobject context, jstring srcName, jstring dstName)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, context);
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(con,
+ GetJStringValue(env, srcName)(), GetJStringValue(env, dstName)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Lorg_OpenColorIO_Transform_2
+ (JNIEnv * env, jobject self, jobject transform)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ ConstTransformRcPtr tran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(tran));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Lorg_OpenColorIO_Transform_2Lorg_OpenColorIO_TransformDirection_2
+ (JNIEnv * env, jobject self, jobject transform, jobject direction)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ ConstTransformRcPtr tran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ TransformDirection dir = GetJEnum<TransformDirection>(env, direction);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(tran, dir));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Config_getProcessor__Lorg_OpenColorIO_Context_2Lorg_OpenColorIO_Transform_2Lorg_OpenColorIO_TransformDirection_2
+ (JNIEnv * env, jobject self, jobject context, jobject transform, jobject direction)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, self);
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, context);
+ ConstTransformRcPtr tran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ TransformDirection dir = GetJEnum<TransformDirection>(env, direction);
+ return BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), cfg->getProcessor(con, tran, dir));
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNIContext.cpp b/src/jniglue/JNIContext.cpp
new file mode 100644
index 0000000..e1fcffd
--- /dev/null
+++ b/src/jniglue/JNIContext.cpp
@@ -0,0 +1,170 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Context_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<ContextJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Context_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<ContextRcPtr, ContextJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Context"), Context::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Context_createEditableCopy(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return BuildJObject<ContextRcPtr, ContextJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Context"), con->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_getCacheID(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->getCacheID());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Context_setSearchPath(JNIEnv * env, jobject self, jstring path)
+{
+ OCIO_JNITRY_ENTER()
+ ContextRcPtr con = GetEditableJOCIO<ContextRcPtr, ContextJNI>(env, self);
+ con->setSearchPath(GetJStringValue(env, path)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_getSearchPath(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->getSearchPath());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Context_setWorkingDir(JNIEnv * env, jobject self, jstring dirname)
+{
+ OCIO_JNITRY_ENTER()
+ ContextRcPtr con = GetEditableJOCIO<ContextRcPtr, ContextJNI>(env, self);
+ con->setWorkingDir(GetJStringValue(env, dirname)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_getWorkingDir(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->getWorkingDir());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Context_setStringVar(JNIEnv * env, jobject self, jstring name, jstring var)
+{
+ OCIO_JNITRY_ENTER()
+ ContextRcPtr con = GetEditableJOCIO<ContextRcPtr, ContextJNI>(env, self);
+ con->setStringVar(GetJStringValue(env, name)(), GetJStringValue(env, var)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_getStringVar(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->getStringVar(GetJStringValue(env, name)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Context_getNumStringVars(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return (jint)con->getNumStringVars();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_getStringVarNameByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->getStringVarNameByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Context_loadEnvironment(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ContextRcPtr con = GetEditableJOCIO<ContextRcPtr, ContextJNI>(env, self);
+ con->loadEnvironment();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_resolveStringVar(JNIEnv * env, jobject self, jstring val)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->resolveStringVar(GetJStringValue(env, val)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Context_resolveFileLocation(JNIEnv * env, jobject self, jstring filename)
+{
+ OCIO_JNITRY_ENTER()
+ ConstContextRcPtr con = GetConstJOCIO<ConstContextRcPtr, ContextJNI>(env, self);
+ return env->NewStringUTF(con->resolveFileLocation(GetJStringValue(env, filename)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNIGlobals.cpp b/src/jniglue/JNIGlobals.cpp
new file mode 100644
index 0000000..9d57c84
--- /dev/null
+++ b/src/jniglue/JNIGlobals.cpp
@@ -0,0 +1,417 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Globals_create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ jfieldID fid;
+ jclass wclass = env->GetObjectClass(self);
+ fid = env->GetFieldID(wclass, "ROLE_DEFAULT", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_DEFAULT));
+ fid = env->GetFieldID(wclass, "ROLE_REFERENCE", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_REFERENCE));
+ fid = env->GetFieldID(wclass, "ROLE_DATA", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_DATA));
+ fid = env->GetFieldID(wclass, "ROLE_COLOR_PICKING", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_COLOR_PICKING));
+ fid = env->GetFieldID(wclass, "ROLE_SCENE_LINEAR", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_SCENE_LINEAR));
+ fid = env->GetFieldID(wclass, "ROLE_COMPOSITING_LOG", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_COMPOSITING_LOG));
+ fid = env->GetFieldID(wclass, "ROLE_COLOR_TIMING", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_COLOR_TIMING));
+ fid = env->GetFieldID(wclass, "ROLE_TEXTURE_PAINT", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_TEXTURE_PAINT));
+ fid = env->GetFieldID(wclass, "ROLE_MATTE_PAINT", "Ljava/lang/String;");
+ env->SetObjectField(self, fid, env->NewStringUTF(ROLE_MATTE_PAINT));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Globals_ClearAllCaches(JNIEnv * env, jobject)
+{
+ OCIO_JNITRY_ENTER()
+ ClearAllCaches();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_GetVersion(JNIEnv * env, jobject)
+{
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(GetVersion());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Globals_GetVersionHex(JNIEnv * env, jobject)
+{
+ OCIO_JNITRY_ENTER()
+ return (jint)GetVersionHex();
+ OCIO_JNITRY_EXIT(-1)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_GetLoggingLevel(JNIEnv * env, jobject)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/LoggingLevel", GetLoggingLevel());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Globals_SetLoggingLevel(JNIEnv * env, jobject, jobject level)
+{
+ OCIO_JNITRY_ENTER()
+ SetLoggingLevel(GetJEnum<LoggingLevel>(env, level));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_GetCurrentConfig(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ jobject obj = BuildJConstObject<ConstConfigRcPtr, ConfigJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Config"), GetCurrentConfig());
+ return obj;
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Globals_SetCurrentConfig(JNIEnv * env, jobject, jobject config)
+{
+ OCIO_JNITRY_ENTER()
+ ConstConfigRcPtr cfg = GetConstJOCIO<ConstConfigRcPtr, ConfigJNI>(env, config);
+ SetCurrentConfig(cfg);
+ OCIO_JNITRY_EXIT()
+}
+
+// Bool
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_BoolToString(JNIEnv * env, jobject, jboolean val)
+{
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(BoolToString((bool)val));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Globals_BoolFromString(JNIEnv * env, jobject, jstring s)
+{
+ OCIO_JNITRY_ENTER()
+ return (jboolean)BoolFromString(GetJStringValue(env, s)());
+ OCIO_JNITRY_EXIT(false)
+}
+
+// LoggingLevel
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_LoggingLevel_toString(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ LoggingLevelToString(GetJEnum<LoggingLevel>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_LoggingLevel_equals(JNIEnv * env, jobject self, jobject obj)
+{
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<LoggingLevel>(env, self)
+ == GetJEnum<LoggingLevel>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_LoggingLevelToString(JNIEnv * env, jobject, jobject level)
+{
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ LoggingLevelToString(GetJEnum<LoggingLevel>(env, level)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_LoggingLevelFromString(JNIEnv * env, jobject, jstring s)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/LoggingLevel",
+ LoggingLevelFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// TransformDirection
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TransformDirection_toString(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ TransformDirectionToString(GetJEnum<TransformDirection>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_TransformDirection_equals(JNIEnv * env, jobject self, jobject obj)
+{
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<TransformDirection>(env, self)
+ == GetJEnum<TransformDirection>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_TransformDirectionToString(JNIEnv * env, jobject,
+ jobject dir)
+{
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ TransformDirectionToString(GetJEnum<TransformDirection>(env, dir)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_TransformDirectionFromString(JNIEnv * env, jobject,
+ jstring s)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/TransformDirection",
+ TransformDirectionFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_GetInverseTransformDirection(JNIEnv * env, jobject,
+ jobject dir) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/TransformDirection",
+ GetInverseTransformDirection(GetJEnum<TransformDirection>(env, dir)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_CombineTransformDirections(JNIEnv * env, jobject,
+ jobject d1, jobject d2) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/TransformDirection",
+ CombineTransformDirections(GetJEnum<TransformDirection>(env, d1),
+ GetJEnum<TransformDirection>(env, d2)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// ColorSpaceDirection
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpaceDirection_toString(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ ColorSpaceDirectionToString(GetJEnum<ColorSpaceDirection>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_ColorSpaceDirection_equals(JNIEnv * env, jobject self, jobject obj) {
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<ColorSpaceDirection>(env, self)
+ == GetJEnum<ColorSpaceDirection>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_ColorSpaceDirectionToString(JNIEnv * env, jobject, jobject dir) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ ColorSpaceDirectionToString(GetJEnum<ColorSpaceDirection>(env, dir)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_ColorSpaceDirectionFromString(JNIEnv * env, jobject, jstring s) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/ColorSpaceDirection",
+ ColorSpaceDirectionFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// BitDepth
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_BitDepth_toString(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ BitDepthToString(GetJEnum<BitDepth>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_BitDepth_equals(JNIEnv * env, jobject self, jobject obj) {
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<BitDepth>(env, self)
+ == GetJEnum<BitDepth>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_BitDepthToString(JNIEnv * env, jobject, jobject bitDepth) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ BitDepthToString(GetJEnum<BitDepth>(env, bitDepth)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_BitDepthFromString(JNIEnv * env, jobject, jstring s) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/BitDepth",
+ BitDepthFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Globals_BitDepthIsFloat(JNIEnv * env, jobject, jobject bitDepth) {
+ OCIO_JNITRY_ENTER()
+ return (jboolean)BitDepthIsFloat(GetJEnum<BitDepth>(env, bitDepth));
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_Globals_BitDepthToInt(JNIEnv * env, jobject, jobject bitDepth) {
+ OCIO_JNITRY_ENTER()
+ return (jint) BitDepthToInt(GetJEnum<BitDepth>(env, bitDepth));
+ OCIO_JNITRY_EXIT(-1)
+}
+
+// Allocation
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Allocation_toString(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ AllocationToString(GetJEnum<Allocation>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Allocation_equals(JNIEnv * env, jobject self, jobject obj) {
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<Allocation>(env, self)
+ == GetJEnum<Allocation>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_AllocationToString(JNIEnv * env, jobject, jobject allocation) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ AllocationToString(GetJEnum<Allocation>(env, allocation)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_AllocationFromString(JNIEnv * env, jobject, jstring s) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/Allocation",
+ AllocationFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// Interpolation
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Interpolation_toString(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ InterpolationToString(GetJEnum<Interpolation>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Interpolation_equals(JNIEnv * env, jobject self, jobject obj) {
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<Interpolation>(env, self)
+ == GetJEnum<Interpolation>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_InterpolationToString(JNIEnv * env, jobject, jobject interp) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ InterpolationToString(GetJEnum<Interpolation>(env, interp)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_InterpolationFromString(JNIEnv * env, jobject, jstring s) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/Interpolation",
+ InterpolationFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// GpuLanguage
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_GpuLanguage_toString(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ GpuLanguageToString(GetJEnum<GpuLanguage>(env, self)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_GpuLanguage_equals(JNIEnv * env, jobject self, jobject obj) {
+ OCIO_JNITRY_ENTER()
+ return GetJEnum<GpuLanguage>(env, self)
+ == GetJEnum<GpuLanguage>(env, obj);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Globals_GpuLanguageToString(JNIEnv * env, jobject, jobject language) {
+ OCIO_JNITRY_ENTER()
+ return env->NewStringUTF(
+ GpuLanguageToString(GetJEnum<GpuLanguage>(env, language)));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Globals_GpuLanguageFromString(JNIEnv * env, jobject, jstring s) {
+ OCIO_JNITRY_ENTER()
+ return BuildJEnum(env, "org/OpenColorIO/GpuLanguage",
+ GpuLanguageFromString(GetJStringValue(env, s)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNIGpuShaderDesc.cpp b/src/jniglue/JNIGpuShaderDesc.cpp
new file mode 100644
index 0000000..21a57ea
--- /dev/null
+++ b/src/jniglue/JNIGpuShaderDesc.cpp
@@ -0,0 +1,125 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+namespace
+{
+
+void GpuShaderDesc_deleter(GpuShaderDesc* d)
+{
+ delete d;
+}
+
+}; // end anon namespace
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_create(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ GpuShaderDescJNI * jnistruct = new GpuShaderDescJNI();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->constcppobj = new ConstGpuShaderDescRcPtr();
+ jnistruct->cppobj = new GpuShaderDescRcPtr();
+ *jnistruct->cppobj = GpuShaderDescRcPtr(new GpuShaderDesc(), &GpuShaderDesc_deleter);
+ jnistruct->isconst = false;
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ env->SetLongField(self, fid, (jlong)jnistruct);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_dispose(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<GpuShaderDescJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_setLanguage(JNIEnv * env, jobject self, jobject lang) {
+ OCIO_JNITRY_ENTER()
+ GpuShaderDescRcPtr ptr = GetEditableJOCIO<GpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ ptr->setLanguage(GetJEnum<GpuLanguage>(env, lang));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_getLanguage(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstGpuShaderDescRcPtr ptr = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ return BuildJEnum(env, "org/OpenColorIO/GpuLanguage", ptr->getLanguage());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_setFunctionName(JNIEnv * env, jobject self, jstring name) {
+ OCIO_JNITRY_ENTER()
+ const char *_name = env->GetStringUTFChars(name, 0);
+ GpuShaderDescRcPtr ptr = GetEditableJOCIO<GpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ ptr->setFunctionName(_name);
+ env->ReleaseStringUTFChars(name, _name);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_getFunctionName(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstGpuShaderDescRcPtr ptr = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ return env->NewStringUTF(ptr->getFunctionName());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_setLut3DEdgeLen(JNIEnv * env, jobject self, jint len) {
+ OCIO_JNITRY_ENTER()
+ GpuShaderDescRcPtr ptr = GetEditableJOCIO<GpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ ptr->setLut3DEdgeLen((int)len);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_getLut3DEdgeLen(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstGpuShaderDescRcPtr ptr = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ return (jint)ptr->getLut3DEdgeLen();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_GpuShaderDesc_getCacheID(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstGpuShaderDescRcPtr ptr = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, self);
+ return env->NewStringUTF(ptr->getCacheID());
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNIImageDesc.cpp b/src/jniglue/JNIImageDesc.cpp
new file mode 100644
index 0000000..c307984
--- /dev/null
+++ b/src/jniglue/JNIImageDesc.cpp
@@ -0,0 +1,309 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+namespace
+{
+void ImageDesc_deleter(ImageDesc* d)
+{
+ delete d;
+}
+
+void ImageDesc_dispose(JNIEnv * env, jobject self)
+{
+ DisposeJOCIO<ImageDescJNI>(env, self);
+}
+
+}; // end anon namespace
+
+// PackedImageDesc
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_PackedImageDesc_create__Ljava_nio_FloatBuffer_2JJJ(JNIEnv * env,
+ jobject self, jobject data, jlong width, jlong height, jlong numChannels)
+{
+ OCIO_JNITRY_ENTER()
+ float* _data = GetJFloatBuffer(env, data, width * height * numChannels);
+ if(!_data) throw Exception("Could not find direct buffer address for data");
+ ImageDescJNI * jnistruct = new ImageDescJNI();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->constcppobj = new ConstImageDescRcPtr();
+ jnistruct->cppobj = new ImageDescRcPtr();
+ *jnistruct->cppobj = ImageDescRcPtr(new PackedImageDesc(_data, (long)width,
+ (long)height, (long)numChannels), &ImageDesc_deleter);
+ jnistruct->isconst = false;
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ env->SetLongField(self, fid, (jlong)jnistruct);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_PackedImageDesc_create__Ljava_nio_FloatBuffer_2JJJJJJ(JNIEnv * env,
+ jobject self, jobject data, jlong width, jlong height, jlong numChannels,
+ jlong chanStrideBytes, jlong xStrideBytes, jlong yStrideBytes)
+{
+ OCIO_JNITRY_ENTER()
+ float* _data = GetJFloatBuffer(env, data, width * height * numChannels);
+ if(!_data) throw Exception("Could not find direct buffer address for data");
+ ImageDescJNI * jnistruct = new ImageDescJNI();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->constcppobj = new ConstImageDescRcPtr();
+ jnistruct->cppobj = new ImageDescRcPtr();
+ *jnistruct->cppobj = ImageDescRcPtr(new PackedImageDesc(_data, (long)width,
+ (long)height, (long)numChannels, (long)chanStrideBytes, (long) xStrideBytes,
+ (long)yStrideBytes), &ImageDesc_deleter);
+ jnistruct->isconst = false;
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ env->SetLongField(self, fid, (jlong)jnistruct);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_PackedImageDesc_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ImageDesc_dispose(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getData(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ int size = ptr->getWidth() * ptr->getHeight() * ptr->getNumChannels();
+ return NewJFloatBuffer(env, ptr->getData(), size);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getWidth(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ return (jlong)ptr->getWidth();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getHeight(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ return (jlong)ptr->getHeight();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getNumChannels(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ return (jlong)ptr->getNumChannels();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getChanStrideBytes(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ return (jlong)ptr->getChanStrideBytes();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getXStrideBytes(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ return (jlong)ptr->getXStrideBytes();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PackedImageDesc_getYStrideBytes(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPackedImageDescRcPtr ptr = DynamicPtrCast<const PackedImageDesc>(img);
+ return (jlong)ptr->getYStrideBytes();
+ OCIO_JNITRY_EXIT(0)
+}
+
+// PlanarImageDesc
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ImageDesc_dispose(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_create__Ljava_nio_FloatBuffer_2Ljava_nio_FloatBuffer_2Ljava_nio_FloatBuffer_2Ljava_nio_FloatBuffer_2JJ
+ (JNIEnv * env, jobject self, jobject rData, jobject gData, jobject bData,
+ jobject aData, jlong width, jlong height)
+{
+ OCIO_JNITRY_ENTER()
+ int32_t size = width * height;
+ float* _rdata = GetJFloatBuffer(env, rData, size);
+ if(!_rdata) throw Exception("Could not find direct buffer address for rData");
+ float* _gdata = GetJFloatBuffer(env, gData, size);
+ if(!_gdata) throw Exception("Could not find direct buffer address for gData");
+ float* _bdata = GetJFloatBuffer(env, bData, size);
+ if(!_bdata) throw Exception("Could not find direct buffer address for bData");
+ float* _adata = GetJFloatBuffer(env, aData, size);
+ if(!_adata) throw Exception("Could not find direct buffer address for aData");
+ ImageDescJNI * jnistruct = new ImageDescJNI();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->constcppobj = new ConstImageDescRcPtr();
+ jnistruct->cppobj = new ImageDescRcPtr();
+ *jnistruct->cppobj = ImageDescRcPtr(new PlanarImageDesc(_rdata, _gdata,
+ _bdata, _adata, (long)width, (long)height), &ImageDesc_deleter);
+ jnistruct->isconst = false;
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ env->SetLongField(self, fid, (jlong)jnistruct);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void
+JNICALL Java_org_OpenColorIO_PlanarImageDesc_create__Ljava_nio_FloatBuffer_2Ljava_nio_FloatBuffer_2Ljava_nio_FloatBuffer_2Ljava_nio_FloatBuffer_2JJJ
+ (JNIEnv * env, jobject self, jobject rData, jobject gData, jobject bData,
+ jobject aData, jlong width, jlong height, jlong yStrideBytes)
+{
+ OCIO_JNITRY_ENTER()
+ int32_t size = width * height;
+ float* _rdata = GetJFloatBuffer(env, rData, size);
+ if(!_rdata) throw Exception("Could not find direct buffer address for rData");
+ float* _gdata = GetJFloatBuffer(env, gData, size);
+ if(!_gdata) throw Exception("Could not find direct buffer address for gData");
+ float* _bdata = GetJFloatBuffer(env, bData, size);
+ if(!_bdata) throw Exception("Could not find direct buffer address for bData");
+ float* _adata = GetJFloatBuffer(env, aData, size);
+ if(!_adata) throw Exception("Could not find direct buffer address for aData");
+ ImageDescJNI * jnistruct = new ImageDescJNI();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->constcppobj = new ConstImageDescRcPtr();
+ jnistruct->cppobj = new ImageDescRcPtr();
+ *jnistruct->cppobj = ImageDescRcPtr(new PlanarImageDesc(_rdata, _gdata, _bdata,
+ _adata, (long)width, (long)height, (long)yStrideBytes), &ImageDesc_deleter);
+ jnistruct->isconst = false;
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ env->SetLongField(self, fid, (jlong)jnistruct);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getRData(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ int size = ptr->getWidth() * ptr->getHeight();
+ return NewJFloatBuffer(env, ptr->getRData(), size);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getGData(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ int size = ptr->getWidth() * ptr->getHeight();
+ return NewJFloatBuffer(env, ptr->getGData(), size);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getBData(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ int size = ptr->getWidth() * ptr->getHeight();
+ return NewJFloatBuffer(env, ptr->getBData(), size);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getAData(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ int size = ptr->getWidth() * ptr->getHeight();
+ return NewJFloatBuffer(env, ptr->getAData(), size);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getWidth(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ return (jlong)ptr->getWidth();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getHeight(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ return (jlong)ptr->getHeight();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_OpenColorIO_PlanarImageDesc_getYStrideBytes(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstImageDescRcPtr img = GetConstJOCIO<ConstImageDescRcPtr, ImageDescJNI>(env, self);
+ ConstPlanarImageDescRcPtr ptr = DynamicPtrCast<const PlanarImageDesc>(img);
+ return (jlong)ptr->getYStrideBytes();
+ OCIO_JNITRY_EXIT(0)
+}
diff --git a/src/jniglue/JNILook.cpp b/src/jniglue/JNILook.cpp
new file mode 100644
index 0000000..ebd7731
--- /dev/null
+++ b/src/jniglue/JNILook.cpp
@@ -0,0 +1,131 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Look_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<LookJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Look_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<LookRcPtr, LookJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Look"), Look::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Look_getName(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookRcPtr lok = GetConstJOCIO<ConstLookRcPtr, LookJNI>(env, self);
+ return env->NewStringUTF(lok->getName());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Look_setName(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ LookRcPtr lok = GetEditableJOCIO<LookRcPtr, LookJNI>(env, self);
+ lok->setName(GetJStringValue(env, name)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Look_getProcessSpace(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookRcPtr lok = GetConstJOCIO<ConstLookRcPtr, LookJNI>(env, self);
+ return env->NewStringUTF(lok->getProcessSpace());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Look_setProcessSpace(JNIEnv * env, jobject self, jstring processSpace)
+{
+ OCIO_JNITRY_ENTER()
+ LookRcPtr lok = GetEditableJOCIO<LookRcPtr, LookJNI>(env, self);
+ lok->setProcessSpace(GetJStringValue(env, processSpace)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Look_getTransform(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookRcPtr lok = GetConstJOCIO<ConstLookRcPtr, LookJNI>(env, self);
+ ConstTransformRcPtr tr = lok->getTransform();
+ return BuildJConstObject<ConstTransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(tr)), tr);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Look_setTransform(JNIEnv * env, jobject self, jobject transform)
+{
+ OCIO_JNITRY_ENTER()
+ LookRcPtr lok = GetEditableJOCIO<LookRcPtr, LookJNI>(env, self);
+ ConstTransformRcPtr tran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ lok->setTransform(tran);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Look_getInverseTransform(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookRcPtr lok = GetConstJOCIO<ConstLookRcPtr, LookJNI>(env, self);
+ ConstTransformRcPtr tr = lok->getInverseTransform();
+ return BuildJConstObject<ConstTransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(tr)), tr);
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Look_setInverseTransform(JNIEnv * env, jobject self, jobject transform)
+{
+ OCIO_JNITRY_ENTER()
+ LookRcPtr lok = GetEditableJOCIO<LookRcPtr, LookJNI>(env, self);
+ ConstTransformRcPtr tran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ lok->setInverseTransform(tran);
+ OCIO_JNITRY_EXIT()
+}
diff --git a/src/jniglue/JNIProcessor.cpp b/src/jniglue/JNIProcessor.cpp
new file mode 100644
index 0000000..ada897a
--- /dev/null
+++ b/src/jniglue/JNIProcessor.cpp
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Processor_Create(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ jobject obj = BuildJConstObject<ConstProcessorRcPtr, ProcessorJNI>(env, self,
+ env->FindClass("org/OpenColorIO/Processor"), Processor::Create());
+ return obj;
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Processor_isNoOp(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ return (jboolean)ptr->isNoOp();
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_Processor_hasChannelCrosstalk(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ return (jboolean)ptr->hasChannelCrosstalk();
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Processor_apply(JNIEnv * env, jobject self, jobject img) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ImageDescRcPtr _img = GetEditableJOCIO<ImageDescRcPtr, ImageDescJNI>(env, img);
+ ptr->apply(*_img.get());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Processor_applyRGB(JNIEnv * env, jobject self, jfloatArray pixel) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ptr->applyRGB(GetJFloatArrayValue(env, pixel, "pixel", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Processor_applyRGBA(JNIEnv * env, jobject self, jfloatArray pixel) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ptr->applyRGBA(GetJFloatArrayValue(env, pixel, "pixel", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Processor_getCpuCacheID(JNIEnv * env, jobject self) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ return env->NewStringUTF(ptr->getCpuCacheID());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Processor_getGpuShaderText(JNIEnv * env, jobject self, jobject shaderDesc) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ConstGpuShaderDescRcPtr desc = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, shaderDesc);
+ return env->NewStringUTF(ptr->getGpuShaderText(*desc.get()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Processor_getGpuShaderTextCacheID(JNIEnv * env, jobject self, jobject shaderDesc) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ConstGpuShaderDescRcPtr desc = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, shaderDesc);
+ return env->NewStringUTF(ptr->getGpuShaderTextCacheID(*desc.get()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Processor_getGpuLut3D(JNIEnv * env, jobject self, jobject lut3d, jobject shaderDesc) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ConstGpuShaderDescRcPtr desc = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, shaderDesc);
+ int len = desc->getLut3DEdgeLen();
+ int size = 3*len*len*len;
+ float* _lut3d = GetJFloatBuffer(env, lut3d, size);
+ ptr->getGpuLut3D(_lut3d, *desc.get());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_Processor_getGpuLut3DCacheID(JNIEnv * env, jobject self, jobject shaderDesc) {
+ OCIO_JNITRY_ENTER()
+ ConstProcessorRcPtr ptr = GetConstJOCIO<ConstProcessorRcPtr, ProcessorJNI>(env, self);
+ ConstGpuShaderDescRcPtr desc = GetConstJOCIO<ConstGpuShaderDescRcPtr, GpuShaderDescJNI>(env, shaderDesc);
+ return env->NewStringUTF(ptr->getGpuLut3DCacheID(*desc.get()));
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNITransforms.cpp b/src/jniglue/JNITransforms.cpp
new file mode 100644
index 0000000..6e2fe26
--- /dev/null
+++ b/src/jniglue/JNITransforms.cpp
@@ -0,0 +1,1151 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "OpenColorIO/OpenColorIO.h"
+#include "OpenColorIOJNI.h"
+#include "JNIUtil.h"
+OCIO_NAMESPACE_USING
+
+// Transform
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Transform_dispose(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ DisposeJOCIO<TransformJNI>(env, self);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Transform_createEditableCopy(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTransformRcPtr ctran = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, self);
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(ctran)), ctran->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_Transform_getDirection(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTransformRcPtr ptr = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, self);
+ return BuildJEnum(env, "org/OpenColorIO/TransformDirection", ptr->getDirection());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_Transform_setDirection(JNIEnv * env, jobject self, jobject dir)
+{
+ OCIO_JNITRY_ENTER()
+ TransformRcPtr ptr = GetEditableJOCIO<TransformRcPtr, TransformJNI>(env, self);
+ ptr->setDirection(GetJEnum<TransformDirection>(env, dir));
+ OCIO_JNITRY_EXIT()
+}
+
+// AllocationTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_AllocationTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<AllocationTransformRcPtr, AllocationTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/AllocationTransform"), AllocationTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_AllocationTransform_getAllocation(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstAllocationTransformRcPtr alctran = GetConstJOCIO<ConstAllocationTransformRcPtr, AllocationTransformJNI>(env, self);
+ return BuildJEnum(env, "org/OpenColorIO/Allocation", alctran->getAllocation());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_AllocationTransform_setAllocation(JNIEnv * env, jobject self, jobject allocation)
+{
+ OCIO_JNITRY_ENTER()
+ AllocationTransformRcPtr alctran = GetEditableJOCIO<AllocationTransformRcPtr, AllocationTransformJNI>(env, self);
+ alctran->setAllocation(GetJEnum<Allocation>(env, allocation));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_AllocationTransform_getNumVars(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstAllocationTransformRcPtr alctran = GetConstJOCIO<ConstAllocationTransformRcPtr, AllocationTransformJNI>(env, self);
+ return (jint)alctran->getNumVars();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_AllocationTransform_getVars(JNIEnv * env, jobject self, jfloatArray vars)
+{
+ OCIO_JNITRY_ENTER()
+ ConstAllocationTransformRcPtr alctran = GetConstJOCIO<ConstAllocationTransformRcPtr, AllocationTransformJNI>(env, self);
+ alctran->getVars(SetJFloatArrayValue(env, vars, "vars", alctran->getNumVars())());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_AllocationTransform_setVars(JNIEnv * env, jobject self, jint numvars, jfloatArray vars)
+{
+ OCIO_JNITRY_ENTER()
+ AllocationTransformRcPtr alctran = GetEditableJOCIO<AllocationTransformRcPtr, AllocationTransformJNI>(env, self);
+ alctran->setVars((int)numvars, GetJFloatArrayValue(env, vars, "vars", numvars)());
+ OCIO_JNITRY_EXIT()
+}
+
+// CDLTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_CDLTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<CDLTransformRcPtr, CDLTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/CDLTransform"), CDLTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_CDLTransform_CreateFromFile(JNIEnv * env, jobject self, jstring src, jstring cccid)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<CDLTransformRcPtr, CDLTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/CDLTransform"),
+ CDLTransform::CreateFromFile(GetJStringValue(env, src)(), GetJStringValue(env, cccid)()));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_CDLTransform_equals(JNIEnv * env, jobject self, jobject obj)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr left = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ ConstCDLTransformRcPtr right = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, obj);
+ return (jboolean)left->equals(right);
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_CDLTransform_getXML(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ return env->NewStringUTF(cdltran->getXML());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setXML(JNIEnv * env, jobject self, jstring xml)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setXML(GetJStringValue(env, xml)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setSlope(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setSlope(GetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_getSlope(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->getSlope(SetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setOffset(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setOffset(GetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_getOffset(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->getOffset(SetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setPower(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setPower(GetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_getPower(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->getPower(SetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setSOP(JNIEnv * env, jobject self, jfloatArray vec9)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setSOP(GetJFloatArrayValue(env, vec9, "vec9", 9)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_getSOP(JNIEnv * env, jobject self, jfloatArray vec9)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->getSOP(SetJFloatArrayValue(env, vec9, "vec9", 9)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setSat(JNIEnv * env, jobject self, jfloat sat)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setSat((float)sat);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jfloat JNICALL
+Java_org_OpenColorIO_CDLTransform_getSat(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ return (jfloat)cdltran->getSat();
+ OCIO_JNITRY_EXIT(1.f)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_getSatLumaCoefs(JNIEnv * env, jobject self, jfloatArray rgb)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->getSatLumaCoefs(SetJFloatArrayValue(env, rgb, "rgb", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setID(JNIEnv * env, jobject self, jstring id)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setID(GetJStringValue(env, id)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_CDLTransform_getID(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ return env->NewStringUTF(cdltran->getID());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_CDLTransform_setDescription(JNIEnv * env, jobject self, jstring desc)
+{
+ OCIO_JNITRY_ENTER()
+ CDLTransformRcPtr cdltran = GetEditableJOCIO<CDLTransformRcPtr, CDLTransformJNI>(env, self);
+ cdltran->setDescription(GetJStringValue(env, desc)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_CDLTransform_getDescription(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstCDLTransformRcPtr cdltran = GetConstJOCIO<ConstCDLTransformRcPtr, CDLTransformJNI>(env, self);
+ return env->NewStringUTF(cdltran->getDescription());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// ColorSpaceTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ColorSpaceTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<ColorSpaceTransformRcPtr, ColorSpaceTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/ColorSpaceTransform"), ColorSpaceTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpaceTransform_getSrc(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceTransformRcPtr coltran = GetConstJOCIO<ConstColorSpaceTransformRcPtr, ColorSpaceTransformJNI>(env, self);
+ return env->NewStringUTF(coltran->getSrc());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpaceTransform_setSrc(JNIEnv * env, jobject self, jstring src)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceTransformRcPtr coltran = GetEditableJOCIO<ColorSpaceTransformRcPtr, ColorSpaceTransformJNI>(env, self);
+ coltran->setSrc(GetJStringValue(env, src)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_ColorSpaceTransform_getDst(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstColorSpaceTransformRcPtr coltran = GetConstJOCIO<ConstColorSpaceTransformRcPtr, ColorSpaceTransformJNI>(env, self);
+ return env->NewStringUTF(coltran->getDst());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ColorSpaceTransform_setDst(JNIEnv * env, jobject self, jstring dst)
+{
+ OCIO_JNITRY_ENTER()
+ ColorSpaceTransformRcPtr coltran = GetEditableJOCIO<ColorSpaceTransformRcPtr, ColorSpaceTransformJNI>(env, self);
+ coltran->setDst(GetJStringValue(env, dst)());
+ OCIO_JNITRY_EXIT()
+}
+
+// DisplayTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_DisplayTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<DisplayTransformRcPtr, DisplayTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/DisplayTransform"), DisplayTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setInputColorSpaceName(JNIEnv * env, jobject self, jstring name)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ dtran->setInputColorSpaceName(GetJStringValue(env, name)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_DisplayTransform_getInputColorSpaceName(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ return env->NewStringUTF(dtran->getInputColorSpaceName());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setLinearCC(JNIEnv * env, jobject self, jobject cc)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr ptr = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, cc);
+ dtran->setLinearCC(ptr);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_DisplayTransform_getLinearCC(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr cctran = dtran->getLinearCC();
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(cctran)), cctran->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setColorTimingCC(JNIEnv * env, jobject self, jobject cc)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr ptr = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, cc);
+ dtran->setColorTimingCC(ptr);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_DisplayTransform_getColorTimingCC(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr cctran = dtran->getColorTimingCC();
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(cctran)), cctran->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setChannelView(JNIEnv * env, jobject self, jobject transform)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr ptr = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ dtran->setChannelView(ptr);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_DisplayTransform_getChannelView(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr cvtran = dtran->getChannelView();
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(cvtran)), cvtran->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setDisplay(JNIEnv * env, jobject self, jstring display)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ dtran->setDisplay(GetJStringValue(env, display)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_DisplayTransform_getDisplay(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ return env->NewStringUTF(dtran->getDisplay());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setView(JNIEnv * env, jobject self, jstring view)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ dtran->setView(GetJStringValue(env, view)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_DisplayTransform_getView(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ return env->NewStringUTF(dtran->getView());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setDisplayCC(JNIEnv * env, jobject self, jobject cc)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr ptr = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, cc);
+ dtran->setDisplayCC(ptr);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_DisplayTransform_getDisplayCC(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ ConstTransformRcPtr cctran = dtran->getDisplayCC();
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(cctran)), cctran->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setLooksOverride(JNIEnv * env, jobject self, jstring looks)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ dtran->setLooksOverride(GetJStringValue(env, looks)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_DisplayTransform_getLooksOverride(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ return env->NewStringUTF(dtran->getLooksOverride());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_DisplayTransform_setLooksOverrideEnabled(JNIEnv * env, jobject self, jboolean enabled)
+{
+ OCIO_JNITRY_ENTER()
+ DisplayTransformRcPtr dtran = GetEditableJOCIO<DisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ dtran->setLooksOverrideEnabled((bool)enabled);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_DisplayTransform_getLooksOverrideEnabled(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstDisplayTransformRcPtr dtran = GetConstJOCIO<ConstDisplayTransformRcPtr, DisplayTransformJNI>(env, self);
+ return (jboolean)dtran->getLooksOverrideEnabled();
+ OCIO_JNITRY_EXIT(false)
+}
+
+// ExponentTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_ExponentTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/ExponentTransform"), ExponentTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ExponentTransform_setValue(JNIEnv * env, jobject self, jfloatArray vec4)
+{
+ OCIO_JNITRY_ENTER()
+ ExponentTransformRcPtr exptran = GetEditableJOCIO<ExponentTransformRcPtr, ExponentTransformJNI>(env, self);
+ exptran->setValue(GetJFloatArrayValue(env, vec4, "vec4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_ExponentTransform_getValue(JNIEnv * env, jobject self, jfloatArray vec4)
+{
+ OCIO_JNITRY_ENTER()
+ ConstExponentTransformRcPtr exptran = GetConstJOCIO<ConstExponentTransformRcPtr, ExponentTransformJNI>(env, self);
+ exptran->getValue(SetJFloatArrayValue(env, vec4, "vec4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+// FileTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_FileTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<FileTransformRcPtr, FileTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/FileTransform"), FileTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_FileTransform_getSrc(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstFileTransformRcPtr filetran = GetConstJOCIO<ConstFileTransformRcPtr, FileTransformJNI>(env, self);
+ return env->NewStringUTF(filetran->getSrc());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_FileTransform_setSrc(JNIEnv * env, jobject self, jstring src)
+{
+ OCIO_JNITRY_ENTER()
+ FileTransformRcPtr filetran = GetEditableJOCIO<FileTransformRcPtr, FileTransformJNI>(env, self);
+ filetran->setSrc(GetJStringValue(env, src)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_FileTransform_getCCCId(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstFileTransformRcPtr filetran = GetConstJOCIO<ConstFileTransformRcPtr, FileTransformJNI>(env, self);
+ return env->NewStringUTF(filetran->getCCCId());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_FileTransform_setCCCId(JNIEnv * env, jobject self, jstring id)
+{
+ OCIO_JNITRY_ENTER()
+ FileTransformRcPtr filetran = GetEditableJOCIO<FileTransformRcPtr, FileTransformJNI>(env, self);
+ filetran->setCCCId(GetJStringValue(env, id)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_FileTransform_getInterpolation(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstFileTransformRcPtr filetran = GetConstJOCIO<ConstFileTransformRcPtr, FileTransformJNI>(env, self);
+ return BuildJEnum(env, "org/OpenColorIO/Interpolation", filetran->getInterpolation());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_FileTransform_setInterpolation(JNIEnv * env, jobject self, jobject interp)
+{
+ OCIO_JNITRY_ENTER()
+ FileTransformRcPtr filetran = GetEditableJOCIO<FileTransformRcPtr, FileTransformJNI>(env, self);
+ filetran->setInterpolation(GetJEnum<Interpolation>(env, interp));
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_FileTransform_getNumFormats(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstFileTransformRcPtr filetran = GetConstJOCIO<ConstFileTransformRcPtr, FileTransformJNI>(env, self);
+ return (jint)filetran->getNumFormats();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_FileTransform_getFormatNameByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstFileTransformRcPtr filetran = GetConstJOCIO<ConstFileTransformRcPtr, FileTransformJNI>(env, self);
+ return env->NewStringUTF(filetran->getFormatNameByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_FileTransform_getFormatExtensionByIndex(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstFileTransformRcPtr filetran = GetConstJOCIO<ConstFileTransformRcPtr, FileTransformJNI>(env, self);
+ return env->NewStringUTF(filetran->getFormatExtensionByIndex((int)index));
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// GroupTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_GroupTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<GroupTransformRcPtr, GroupTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/GroupTransform"), GroupTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_GroupTransform_getTransform(JNIEnv * env, jobject self, jint index)
+{
+ OCIO_JNITRY_ENTER()
+ ConstGroupTransformRcPtr gtran = GetConstJOCIO<ConstGroupTransformRcPtr, GroupTransformJNI>(env, self);
+ ConstTransformRcPtr ctran = gtran->getTransform((int)index);
+ return BuildJObject<TransformRcPtr, TransformJNI>(env, self,
+ env->FindClass(GetOCIOTClass(ctran)), ctran->createEditableCopy());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jint JNICALL
+Java_org_OpenColorIO_GroupTransform_size(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstGroupTransformRcPtr gtran = GetConstJOCIO<ConstGroupTransformRcPtr, GroupTransformJNI>(env, self);
+ return (jint)gtran->size();
+ OCIO_JNITRY_EXIT(0)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GroupTransform_push_1back(JNIEnv * env, jobject self, jobject transform)
+{
+ OCIO_JNITRY_ENTER()
+ GroupTransformRcPtr gtran = GetEditableJOCIO<GroupTransformRcPtr, GroupTransformJNI>(env, self);
+ ConstTransformRcPtr ptr = GetConstJOCIO<ConstTransformRcPtr, TransformJNI>(env, transform);
+ gtran->push_back(ptr);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_GroupTransform_clear(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ GroupTransformRcPtr gtran = GetEditableJOCIO<GroupTransformRcPtr, GroupTransformJNI>(env, self);
+ gtran->clear();
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_GroupTransform_empty(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstGroupTransformRcPtr gtran = GetConstJOCIO<ConstGroupTransformRcPtr, GroupTransformJNI>(env, self);
+ return (jboolean)gtran->empty();
+ OCIO_JNITRY_EXIT(false)
+}
+
+// LogTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_LogTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<LogTransformRcPtr, LogTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/LogTransform"), LogTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_LogTransform_setBase(JNIEnv * env, jobject self, jfloat val)
+{
+ OCIO_JNITRY_ENTER()
+ LogTransformRcPtr ltran = GetEditableJOCIO<LogTransformRcPtr, LogTransformJNI>(env, self);
+ ltran->setBase((float)val);
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jfloat JNICALL
+Java_org_OpenColorIO_LogTransform_getBase(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLogTransformRcPtr ltran = GetConstJOCIO<ConstLogTransformRcPtr, LogTransformJNI>(env, self);
+ return (jfloat)ltran->getBase();
+ OCIO_JNITRY_EXIT(0.f)
+}
+
+// LookTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_LookTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<LookTransformRcPtr, LookTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/LookTransform"), LookTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_LookTransform_getSrc(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookTransformRcPtr lktran = GetConstJOCIO<ConstLookTransformRcPtr, LookTransformJNI>(env, self);
+ return env->NewStringUTF(lktran->getSrc());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_LookTransform_setSrc(JNIEnv * env, jobject self, jstring src)
+{
+ OCIO_JNITRY_ENTER()
+ LookTransformRcPtr lktran = GetEditableJOCIO<LookTransformRcPtr, LookTransformJNI>(env, self);
+ lktran->setSrc(GetJStringValue(env, src)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_LookTransform_getDst(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookTransformRcPtr lktran = GetConstJOCIO<ConstLookTransformRcPtr, LookTransformJNI>(env, self);
+ return env->NewStringUTF(lktran->getDst());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_LookTransform_setDst(JNIEnv * env, jobject self, jstring dst)
+{
+ OCIO_JNITRY_ENTER()
+ LookTransformRcPtr lktran = GetEditableJOCIO<LookTransformRcPtr, LookTransformJNI>(env, self);
+ lktran->setDst(GetJStringValue(env, dst)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_LookTransform_setLooks(JNIEnv * env, jobject self, jstring looks)
+{
+ OCIO_JNITRY_ENTER()
+ LookTransformRcPtr lktran = GetEditableJOCIO<LookTransformRcPtr, LookTransformJNI>(env, self);
+ lktran->setLooks(GetJStringValue(env, looks)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_LookTransform_getLooks(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstLookTransformRcPtr lktran = GetConstJOCIO<ConstLookTransformRcPtr, LookTransformJNI>(env, self);
+ return env->NewStringUTF(lktran->getLooks());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+// MatrixTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_MatrixTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<MatrixTransformRcPtr, MatrixTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/MatrixTransform"), MatrixTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_OpenColorIO_MatrixTransform_equals(JNIEnv * env, jobject self, jobject obj)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr left = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ ConstMatrixTransformRcPtr right = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, obj);
+ return (jboolean)left->equals(*right.get());
+ OCIO_JNITRY_EXIT(false)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_setValue(JNIEnv * env, jobject self, jfloatArray m44, jfloatArray offset4)
+{
+ OCIO_JNITRY_ENTER()
+ MatrixTransformRcPtr mtran = GetEditableJOCIO<MatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->setValue(GetJFloatArrayValue(env, m44, "m44", 16)(),
+ GetJFloatArrayValue(env, offset4, "offset4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_getValue(JNIEnv * env, jobject self, jfloatArray m44, jfloatArray offset4)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->getValue(SetJFloatArrayValue(env, m44, "m44", 16)(),
+ SetJFloatArrayValue(env, offset4, "offset4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_setMatrix(JNIEnv * env, jobject self, jfloatArray m44)
+{
+ OCIO_JNITRY_ENTER()
+ MatrixTransformRcPtr mtran = GetEditableJOCIO<MatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->setMatrix(GetJFloatArrayValue(env, m44, "m44", 16)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_getMatrix(JNIEnv * env, jobject self, jfloatArray m44)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->getMatrix(SetJFloatArrayValue(env, m44, "m44", 16)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_setOffset(JNIEnv * env, jobject self, jfloatArray offset4)
+{
+ OCIO_JNITRY_ENTER()
+ MatrixTransformRcPtr mtran = GetEditableJOCIO<MatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->setOffset(GetJFloatArrayValue(env, offset4, "offset4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_getOffset(JNIEnv * env, jobject self, jfloatArray offset4)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->getOffset(SetJFloatArrayValue(env, offset4, "offset4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_Fit(JNIEnv * env, jobject self,
+ jfloatArray m44, jfloatArray offset4, jfloatArray oldmin4,
+ jfloatArray oldmax4, jfloatArray newmin4, jfloatArray newmax4)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->Fit(GetJFloatArrayValue(env, m44, "m44", 16)(),
+ GetJFloatArrayValue(env, offset4, "offset4", 4)(),
+ GetJFloatArrayValue(env, oldmin4, "oldmin4", 4)(),
+ GetJFloatArrayValue(env, oldmax4, "oldmax4", 4)(),
+ GetJFloatArrayValue(env, newmin4, "newmin4", 4)(),
+ GetJFloatArrayValue(env, newmax4, "newmax4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_Identity(JNIEnv * env, jobject self,
+ jfloatArray m44, jfloatArray offset4)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->Identity(GetJFloatArrayValue(env, m44, "m44", 16)(),
+ GetJFloatArrayValue(env, offset4, "offset4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_Sat(JNIEnv * env, jobject self,
+ jfloatArray m44, jfloatArray offset4, jfloat sat,
+ jfloatArray lumaCoef3)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->Sat(GetJFloatArrayValue(env, m44, "m44", 16)(),
+ GetJFloatArrayValue(env, offset4, "offset4", 4)(),
+ (float)sat,
+ GetJFloatArrayValue(env, lumaCoef3, "lumaCoef3", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_Scale(JNIEnv * env, jobject self,
+ jfloatArray m44, jfloatArray offset4, jfloatArray scale4)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->Scale(GetJFloatArrayValue(env, m44, "m44", 16)(),
+ GetJFloatArrayValue(env, offset4, "offset4", 4)(),
+ GetJFloatArrayValue(env, scale4, "scale4", 4)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_MatrixTransform_View(JNIEnv * env, jobject self,
+ jfloatArray m44, jfloatArray offset4, jintArray channelHot4,
+ jfloatArray lumaCoef3)
+{
+ OCIO_JNITRY_ENTER()
+ ConstMatrixTransformRcPtr mtran = GetConstJOCIO<ConstMatrixTransformRcPtr, MatrixTransformJNI>(env, self);
+ mtran->View(GetJFloatArrayValue(env, m44, "m44", 16)(),
+ GetJFloatArrayValue(env, offset4, "offset4", 4)(),
+ GetJIntArrayValue(env, channelHot4, "channelHot4", 4)(),
+ GetJFloatArrayValue(env, lumaCoef3, "lumaCoef3", 3)());
+ OCIO_JNITRY_EXIT()
+}
+
+// TruelightTransform
+
+JNIEXPORT jobject JNICALL
+Java_org_OpenColorIO_TruelightTransform_Create(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ return BuildJObject<TruelightTransformRcPtr, TruelightTransformJNI>(env, self,
+ env->FindClass("org/OpenColorIO/TruelightTransform"), TruelightTransform::Create());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setConfigRoot(JNIEnv * env, jobject self, jstring configroot)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setConfigRoot(GetJStringValue(env, configroot)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getConfigRoot(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getConfigRoot());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setProfile(JNIEnv * env, jobject self, jstring profile)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setProfile(GetJStringValue(env, profile)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getProfile(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getProfile());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setCamera(JNIEnv * env, jobject self, jstring camera)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setCamera(GetJStringValue(env, camera)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getCamera(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getCamera());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setInputDisplay(JNIEnv * env, jobject self, jstring display)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setInputDisplay(GetJStringValue(env, display)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getInputDisplay(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getInputDisplay());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setRecorder(JNIEnv * env, jobject self, jstring recorder)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setRecorder(GetJStringValue(env, recorder)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getRecorder(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getRecorder());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setPrint(JNIEnv * env, jobject self, jstring print)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setPrint(GetJStringValue(env, print)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getPrint(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getPrint());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setLamp(JNIEnv * env, jobject self, jstring lamp)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setLamp(GetJStringValue(env, lamp)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getLamp(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getLamp());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setOutputCamera(JNIEnv * env, jobject self, jstring camera)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setOutputCamera(GetJStringValue(env, camera)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getOutputCamera(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getOutputCamera());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setDisplay(JNIEnv * env, jobject self, jstring display)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setDisplay(GetJStringValue(env, display)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getDisplay(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getDisplay());
+ OCIO_JNITRY_EXIT(NULL)
+}
+
+JNIEXPORT void JNICALL
+Java_org_OpenColorIO_TruelightTransform_setCubeInput(JNIEnv * env, jobject self, jstring type)
+{
+ OCIO_JNITRY_ENTER()
+ TruelightTransformRcPtr ttran = GetEditableJOCIO<TruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ ttran->setCubeInput(GetJStringValue(env, type)());
+ OCIO_JNITRY_EXIT()
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_OpenColorIO_TruelightTransform_getCubeInput(JNIEnv * env, jobject self)
+{
+ OCIO_JNITRY_ENTER()
+ ConstTruelightTransformRcPtr ttran = GetConstJOCIO<ConstTruelightTransformRcPtr, TruelightTransformJNI>(env, self);
+ return env->NewStringUTF(ttran->getCubeInput());
+ OCIO_JNITRY_EXIT(NULL)
+}
diff --git a/src/jniglue/JNIUtil.cpp b/src/jniglue/JNIUtil.cpp
new file mode 100644
index 0000000..b893098
--- /dev/null
+++ b/src/jniglue/JNIUtil.cpp
@@ -0,0 +1,122 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "JNIUtil.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+jobject NewJFloatBuffer(JNIEnv * env, float* ptr, int32_t len) {
+ jobject byte_buf = env->NewDirectByteBuffer(ptr, len * sizeof(float));
+ jmethodID mid = env->GetMethodID(env->GetObjectClass(byte_buf),
+ "asFloatBuffer", "()Ljava/nio/FloatBuffer;");
+ if (mid == 0) throw Exception("Could not find asFloatBuffer() method");
+ return env->CallObjectMethod(byte_buf, mid);
+}
+
+float* GetJFloatBuffer(JNIEnv * env, jobject buffer, int32_t len) {
+ jmethodID mid = env->GetMethodID(env->GetObjectClass(buffer), "isDirect", "()Z");
+ if (mid == 0) throw Exception("Could not find isDirect() method");
+ if(!env->CallBooleanMethod(buffer, mid)) {
+ std::ostringstream err;
+ err << "the FloatBuffer object is not 'direct' it needs to be created ";
+ err << "from a ByteBuffer.allocateDirect(..).asFloatBuffer() call.";
+ throw Exception(err.str().c_str());
+ }
+ if(env->GetDirectBufferCapacity(buffer) != len) {
+ std::ostringstream err;
+ err << "the FloatBuffer object is not allocated correctly it needs to ";
+ err << "of size " << len << " but is ";
+ err << env->GetDirectBufferCapacity(buffer) << ".";
+ throw Exception(err.str().c_str());
+ }
+ return (float*)env->GetDirectBufferAddress(buffer);
+}
+
+const char* GetOCIOTClass(ConstTransformRcPtr tran) {
+ if(ConstAllocationTransformRcPtr at = DynamicPtrCast<const AllocationTransform>(tran))
+ return "org/OpenColorIO/AllocationTransform";
+ else if(ConstCDLTransformRcPtr ct = DynamicPtrCast<const CDLTransform>(tran))
+ return "org/OpenColorIO/CDLTransform";
+ else if(ConstColorSpaceTransformRcPtr cst = DynamicPtrCast<const ColorSpaceTransform>(tran))
+ return "org/OpenColorIO/ColorSpaceTransform";
+ else if(ConstDisplayTransformRcPtr dt = DynamicPtrCast<const DisplayTransform>(tran))
+ return "org/OpenColorIO/DisplayTransform";
+ else if(ConstExponentTransformRcPtr et = DynamicPtrCast<const ExponentTransform>(tran))
+ return "org/OpenColorIO/ExponentTransform";
+ else if(ConstFileTransformRcPtr ft = DynamicPtrCast<const FileTransform>(tran))
+ return "org/OpenColorIO/FileTransform";
+ else if(ConstGroupTransformRcPtr gt = DynamicPtrCast<const GroupTransform>(tran))
+ return "org/OpenColorIO/GroupTransform";
+ else if(ConstLogTransformRcPtr lt = DynamicPtrCast<const LogTransform>(tran))
+ return "org/OpenColorIO/LogTransform";
+ else if(ConstLookTransformRcPtr lkt = DynamicPtrCast<const LookTransform>(tran))
+ return "org/OpenColorIO/LookTransform";
+ else if(ConstMatrixTransformRcPtr mt = DynamicPtrCast<const MatrixTransform>(tran))
+ return "org/OpenColorIO/MatrixTransform";
+ else if(ConstTruelightTransformRcPtr tt = DynamicPtrCast<const TruelightTransform>(tran))
+ return "org/OpenColorIO/TruelightTransform";
+ else return "org/OpenColorIO/Transform";
+}
+
+void JNI_Handle_Exception(JNIEnv * env)
+{
+ try
+ {
+ throw;
+ }
+ catch (ExceptionMissingFile & e)
+ {
+ jclass je = env->FindClass("org/OpenColorIO/ExceptionMissingFile");
+ env->ThrowNew(je, e.what());
+ env->DeleteLocalRef(je);
+ }
+ catch (Exception & e)
+ {
+ jclass je = env->FindClass("org/OpenColorIO/ExceptionBase");
+ env->ThrowNew(je, e.what());
+ env->DeleteLocalRef(je);
+ }
+ catch (std::exception& e)
+ {
+ jclass je = env->FindClass("java/lang/Exception");
+ env->ThrowNew(je, e.what());
+ env->DeleteLocalRef(je);
+ }
+ catch (...)
+ {
+ jclass je = env->FindClass("java/lang/Exception");
+ env->ThrowNew(je, "Unknown C++ exception caught.");
+ env->DeleteLocalRef(je);
+ }
+}
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/jniglue/JNIUtil.h b/src/jniglue/JNIUtil.h
new file mode 100644
index 0000000..cf9381c
--- /dev/null
+++ b/src/jniglue/JNIUtil.h
@@ -0,0 +1,282 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef INCLUDED_OCIO_JNIUTIL_H
+#define INCLUDED_OCIO_JNIUTIL_H
+
+#include <sstream>
+#include <vector>
+#include "OpenColorIOJNI.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+template<typename C, typename E>
+struct JObject
+{
+ jobject back_ptr;
+ C * constcppobj;
+ E * cppobj;
+ bool isconst;
+};
+
+typedef OCIO_SHARED_PTR<const GpuShaderDesc> ConstGpuShaderDescRcPtr;
+typedef OCIO_SHARED_PTR<GpuShaderDesc> GpuShaderDescRcPtr;
+typedef OCIO_SHARED_PTR<const ImageDesc> ConstImageDescRcPtr;
+typedef OCIO_SHARED_PTR<ImageDesc> ImageDescRcPtr;
+typedef OCIO_SHARED_PTR<const PackedImageDesc> ConstPackedImageDescRcPtr;
+typedef OCIO_SHARED_PTR<PackedImageDesc> PackedImageDescRcPtr;
+typedef OCIO_SHARED_PTR<const PlanarImageDesc> ConstPlanarImageDescRcPtr;
+typedef OCIO_SHARED_PTR<PlanarImageDesc> PlanarImageDescRcPtr;
+
+typedef JObject <ConstConfigRcPtr, ConfigRcPtr> ConfigJNI;
+typedef JObject <ConstContextRcPtr, ContextRcPtr> ContextJNI;
+typedef JObject <ConstProcessorRcPtr, ProcessorRcPtr> ProcessorJNI;
+typedef JObject <ConstColorSpaceRcPtr, ColorSpaceRcPtr> ColorSpaceJNI;
+typedef JObject <ConstLookRcPtr, LookRcPtr> LookJNI;
+typedef JObject <ConstBakerRcPtr, BakerRcPtr> BakerJNI;
+typedef JObject <ConstGpuShaderDescRcPtr, GpuShaderDescRcPtr> GpuShaderDescJNI;
+typedef JObject <ConstImageDescRcPtr, ImageDescRcPtr> ImageDescJNI;
+typedef JObject <ConstTransformRcPtr, TransformRcPtr> TransformJNI;
+typedef JObject <ConstAllocationTransformRcPtr, AllocationTransformRcPtr> AllocationTransformJNI;
+typedef JObject <ConstCDLTransformRcPtr, CDLTransformRcPtr> CDLTransformJNI;
+typedef JObject <ConstColorSpaceTransformRcPtr, ColorSpaceTransformRcPtr> ColorSpaceTransformJNI;
+typedef JObject <ConstDisplayTransformRcPtr, DisplayTransformRcPtr> DisplayTransformJNI;
+typedef JObject <ConstExponentTransformRcPtr, ExponentTransformRcPtr> ExponentTransformJNI;
+typedef JObject <ConstFileTransformRcPtr, FileTransformRcPtr> FileTransformJNI;
+typedef JObject <ConstGroupTransformRcPtr, GroupTransformRcPtr> GroupTransformJNI;
+typedef JObject <ConstLogTransformRcPtr, LogTransformRcPtr> LogTransformJNI;
+typedef JObject <ConstLookTransformRcPtr, LookTransformRcPtr> LookTransformJNI;
+typedef JObject <ConstMatrixTransformRcPtr, MatrixTransformRcPtr> MatrixTransformJNI;
+typedef JObject <ConstTruelightTransformRcPtr, TruelightTransformRcPtr> TruelightTransformJNI;
+
+template<typename T, typename S>
+inline jobject BuildJConstObject(JNIEnv * env, jobject self, jclass cls, T ptr)
+{
+ S * jnistruct = new S ();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->constcppobj = new T ();
+ *jnistruct->constcppobj = ptr;
+ jnistruct->isconst = true;
+ jmethodID mid = env->GetMethodID(cls, "<init>", "(J)V");
+ return env->NewObject(cls, mid, (jlong)jnistruct);
+}
+
+template<typename T, typename S>
+inline jobject BuildJObject(JNIEnv * env, jobject self, jclass cls, T ptr)
+{
+ S * jnistruct = new S ();
+ jnistruct->back_ptr = env->NewGlobalRef(self);
+ jnistruct->cppobj = new T ();
+ *jnistruct->cppobj = ptr;
+ jnistruct->isconst = false;
+ jmethodID mid = env->GetMethodID(cls, "<init>", "(J)V");
+ return env->NewObject(cls, mid, (jlong)jnistruct);
+}
+
+template<typename S>
+inline void DisposeJOCIO(JNIEnv * env, jobject self)
+{
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ jlong m_impl = env->GetLongField(self, fid);
+ if(m_impl == 0) return; // nothing to do
+ S * jni = reinterpret_cast<S *> (m_impl);
+ delete jni->constcppobj;
+ delete jni->cppobj;
+ env->DeleteGlobalRef(jni->back_ptr);
+ delete jni;
+ env->SetLongField(self, fid, 0);
+ return;
+}
+
+template<typename T, typename S>
+inline T GetConstJOCIO(JNIEnv * env, jobject self)
+{
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ jlong m_impl = env->GetLongField(self, fid);
+ if(m_impl == 0) {
+ throw Exception("Java object doesn't point to a OCIO object");
+ }
+ S * jni = reinterpret_cast<S *> (m_impl);
+ if(jni->isconst && jni->constcppobj) {
+ return *jni->constcppobj;
+ }
+ if(!jni->isconst && jni->cppobj) {
+ return *jni->cppobj;
+ }
+ throw Exception("Could not get a const OCIO object");
+}
+
+template<typename T, typename S>
+inline T GetEditableJOCIO(JNIEnv * env, jobject self)
+{
+ jclass wclass = env->GetObjectClass(self);
+ jfieldID fid = env->GetFieldID(wclass, "m_impl", "J");
+ jlong m_impl = env->GetLongField(self, fid);
+ if(m_impl == 0) {
+ throw Exception("Java object doesn't point to a OCIO object");
+ }
+ S * jni = reinterpret_cast<S *> (m_impl);
+ if(!jni->isconst && jni->cppobj) {
+ return *jni->cppobj;
+ }
+ throw Exception("Could not get an editable OCIO object");
+}
+
+template<typename T>
+inline T GetJEnum(JNIEnv * env, jobject j_enum)
+{
+ jclass cls = env->GetObjectClass(j_enum);
+ jfieldID fid = env->GetFieldID(cls, "m_enum", "I");
+ return (T)env->GetIntField(j_enum, fid);
+}
+
+template<typename T>
+inline jobject BuildJEnum(JNIEnv * env, const char* ociotype, T val)
+{
+ jclass cls = env->FindClass(ociotype);
+ jmethodID mid = env->GetMethodID(cls, "<init>", "(I)V");
+ return env->NewObject(cls, mid, (int)val);
+}
+
+template<typename T>
+inline void CheckArrayLength(JNIEnv * env, const char* name, T ptr, int32_t length) {
+ if(ptr == NULL) return;
+ if(env->GetArrayLength(ptr) < length) {
+ std::ostringstream err;
+ err << name << " needs to have " << length;
+ err << " elements but found only " << env->GetArrayLength(ptr);
+ throw Exception(err.str().c_str());
+ }
+}
+
+class GetJFloatArrayValue
+{
+public:
+ GetJFloatArrayValue(JNIEnv* env, jfloatArray val, const char* name, int32_t len) {
+ CheckArrayLength(env, name, val, len);
+ m_env = env;
+ m_val = val;
+ if(val != NULL) m_ptr = env->GetFloatArrayElements(val, JNI_FALSE);
+ }
+ ~GetJFloatArrayValue() {
+ if(m_val != NULL) m_env->ReleaseFloatArrayElements(m_val, m_ptr, JNI_FALSE);
+ m_val = NULL;
+ m_ptr = NULL;
+ }
+ jfloat* operator() () {
+ return m_ptr;
+ }
+private:
+ JNIEnv* m_env;
+ jfloat* m_ptr;
+ jfloatArray m_val;
+};
+
+class SetJFloatArrayValue
+{
+public:
+ SetJFloatArrayValue(JNIEnv* env, jfloatArray val, const char* name, int32_t len) {
+ CheckArrayLength(env, name, val, len);
+ m_env = env;
+ m_val = val;
+ if(val != NULL) m_tmp.resize(len);
+ }
+ ~SetJFloatArrayValue() {
+ if(m_val != NULL) m_env->SetFloatArrayRegion(m_val, 0, m_tmp.size(), &m_tmp[0]);
+ m_val = NULL;
+ m_tmp.clear();
+ }
+ float* operator() () {
+ return &m_tmp[0];
+ }
+private:
+ JNIEnv* m_env;
+ std::vector<float> m_tmp;
+ jfloatArray m_val;
+};
+
+class GetJIntArrayValue
+{
+public:
+ GetJIntArrayValue(JNIEnv* env, jintArray val, const char* name, int32_t len) {
+ CheckArrayLength(env, name, val, len);
+ m_env = env;
+ m_val = val;
+ if(val != NULL) m_ptr = env->GetIntArrayElements(val, JNI_FALSE);
+ }
+ ~GetJIntArrayValue() {
+ if(m_val != NULL) m_env->ReleaseIntArrayElements(m_val, m_ptr, JNI_FALSE);
+ m_val = NULL;
+ m_ptr = NULL;
+ }
+ jint* operator() () {
+ return m_ptr;
+ }
+private:
+ JNIEnv* m_env;
+ jint* m_ptr;
+ jintArray m_val;
+};
+
+class GetJStringValue
+{
+public:
+ GetJStringValue(JNIEnv* env, jstring val) {
+ m_env = env;
+ m_val = val;
+ if(val != NULL) m_tmp = env->GetStringUTFChars(m_val, 0);
+ }
+ ~GetJStringValue() {
+ if(m_val != NULL) m_env->ReleaseStringUTFChars(m_val, m_tmp);
+ m_val = NULL;
+ m_tmp = NULL;
+ }
+ const char* operator() () {
+ return m_tmp;
+ }
+private:
+ JNIEnv* m_env;
+ const char* m_tmp;
+ jstring m_val;
+};
+
+jobject NewJFloatBuffer(JNIEnv * env, float* ptr, int32_t len);
+float* GetJFloatBuffer(JNIEnv * env, jobject buffer, int32_t len);
+const char* GetOCIOTClass(ConstTransformRcPtr tran);
+void JNI_Handle_Exception(JNIEnv * env);
+
+#define OCIO_JNITRY_ENTER() try {
+#define OCIO_JNITRY_EXIT(ret) } catch(...) { JNI_Handle_Exception(env); return ret; }
+
+}
+OCIO_NAMESPACE_EXIT
+
+#endif // INCLUDED_OCIO_JNIUTIL_H
diff --git a/src/jniglue/LoadLibrary.java.in b/src/jniglue/LoadLibrary.java.in
new file mode 100644
index 0000000..41818d6
--- /dev/null
+++ b/src/jniglue/LoadLibrary.java.in
@@ -0,0 +1,40 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+
+public class LoadLibrary
+{
+ public LoadLibrary() { }
+ protected LoadLibrary(long impl) { m_impl = impl; }
+ public long m_impl = 0;
+ static
+ {
+ System.loadLibrary("OpenColorIO-JNI.@OCIO_VERSION@");
+ }
+}
diff --git a/src/jniglue/Manifest.txt.in b/src/jniglue/Manifest.txt.in
new file mode 100644
index 0000000..71a5142
--- /dev/null
+++ b/src/jniglue/Manifest.txt.in
@@ -0,0 +1,7 @@
+Name: org/OpenColorIO/
+Specification-Title: OpenColorIO - Open Source Color Management
+Specification-Version: @OCIO_VERSION@
+Specification-Vendor: Sony Pictures Imageworks Inc., et al.
+Implementation-Title: org.OpenColorIO
+Implementation-Version: @OCIO_VERSION@
+Implementation-Vendor: Sony Pictures Imageworks Inc., et al. \ No newline at end of file
diff --git a/src/jniglue/org/OpenColorIO/Allocation.java b/src/jniglue/org/OpenColorIO/Allocation.java
new file mode 100644
index 0000000..3d80251
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Allocation.java
@@ -0,0 +1,44 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Allocation extends LoadLibrary
+{
+ private final int m_enum;
+ protected Allocation(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final Allocation
+ ALLOCATION_UNKNOWN = new Allocation(0);
+ public static final Allocation
+ ALLOCATION_UNIFORM = new Allocation(1);
+ public static final Allocation
+ ALLOCATION_LG2 = new Allocation(2);
+}
diff --git a/src/jniglue/org/OpenColorIO/AllocationTransform.java b/src/jniglue/org/OpenColorIO/AllocationTransform.java
new file mode 100644
index 0000000..b116d18
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/AllocationTransform.java
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class AllocationTransform extends Transform
+{
+ public AllocationTransform() { super(); }
+ protected AllocationTransform(long impl) { super(impl); }
+ public native AllocationTransform Create();
+ public native Allocation getAllocation();
+ public native void setAllocation(Allocation allocation);
+ public native int getNumVars();
+ public native void getVars(float[] vars);
+ public native void setVars(int numvars, float[] vars);
+}
diff --git a/src/jniglue/org/OpenColorIO/Baker.java b/src/jniglue/org/OpenColorIO/Baker.java
new file mode 100644
index 0000000..0464753
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Baker.java
@@ -0,0 +1,62 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Baker extends LoadLibrary
+{
+ public Baker() { super(); }
+ protected Baker(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native Baker Create();
+ public native Baker createEditableCopy();
+ public native void setConfig(Config config);
+ public native Config getConfig();
+ public native void setFormat(String formatName);
+ public native String getFormat();
+ public native void setType(String type);
+ public native String getType();
+ public native void setMetadata(String metadata);
+ public native String getMetadata();
+ public native void setInputSpace(String inputSpace);
+ public native String getInputSpace();
+ public native void setShaperSpace(String shaperSpace);
+ public native String getShaperSpace();
+ public native void setTargetSpace(String targetSpace);
+ public native String getTargetSpace();
+ public native void setShaperSize(int shapersize);
+ public native int getShaperSize();
+ public native void setCubeSize(int cubesize);
+ public native int getCubeSize();
+ public native String bake();
+ public native int getNumFormats();
+ public native String getFormatNameByIndex(int index);
+ public native String getFormatExtensionByIndex(int index);
+}
diff --git a/src/jniglue/org/OpenColorIO/BitDepth.java b/src/jniglue/org/OpenColorIO/BitDepth.java
new file mode 100644
index 0000000..afa0543
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/BitDepth.java
@@ -0,0 +1,56 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class BitDepth extends LoadLibrary
+{
+ private final int m_enum;
+ protected BitDepth(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final BitDepth
+ BIT_DEPTH_UNKNOWN = new BitDepth(0);
+ public static final BitDepth
+ BIT_DEPTH_UINT8 = new BitDepth(1);
+ public static final BitDepth
+ BIT_DEPTH_UINT10 = new BitDepth(2);
+ public static final BitDepth
+ BIT_DEPTH_UINT12 = new BitDepth(3);
+ public static final BitDepth
+ BIT_DEPTH_UINT14 = new BitDepth(4);
+ public static final BitDepth
+ BIT_DEPTH_UINT16 = new BitDepth(5);
+ public static final BitDepth
+ BIT_DEPTH_UINT32 = new BitDepth(6);
+ public static final BitDepth
+ BIT_DEPTH_F16 = new BitDepth(7);
+ public static final BitDepth
+ BIT_DEPTH_F32 = new BitDepth(8);
+}
diff --git a/src/jniglue/org/OpenColorIO/CDLTransform.java b/src/jniglue/org/OpenColorIO/CDLTransform.java
new file mode 100644
index 0000000..ce0fd00
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/CDLTransform.java
@@ -0,0 +1,56 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class CDLTransform extends Transform
+{
+ public CDLTransform() { super(); }
+ protected CDLTransform(long impl) { super(impl); }
+ public native CDLTransform Create();
+ public native CDLTransform CreateFromFile(String src, String cccid);
+ public native boolean equals(CDLTransform obj);
+ public native String getXML();
+ public native void setXML(String xml);
+ public native void setSlope(float[] rgb);
+ public native void getSlope(float[] rgb);
+ public native void setOffset(float[] rgb);
+ public native void getOffset(float[] rgb);
+ public native void setPower(float[] rgb);
+ public native void getPower(float[] rgb);
+ public native void setSOP(float[] vec9);
+ public native void getSOP(float[] vec9);
+ public native void setSat(float sat);
+ public native float getSat();
+ public native void getSatLumaCoefs(float[] rgb);
+ public native void setID(String id);
+ public native String getID();
+ public native void setDescription(String desc);
+ public native String getDescription();
+}
diff --git a/src/jniglue/org/OpenColorIO/ColorSpace.java b/src/jniglue/org/OpenColorIO/ColorSpace.java
new file mode 100644
index 0000000..11e7198
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ColorSpace.java
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ColorSpace extends LoadLibrary
+{
+ public ColorSpace() { super(); }
+ protected ColorSpace(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native ColorSpace Create();
+ public native ColorSpace createEditableCopy();
+ public native String getName();
+ public native void setName(String name);
+ public native String getFamily();
+ public native void setFamily(String family);
+ public native String getEqualityGroup();
+ public native void setEqualityGroup(String equalityGroup);
+ public native String getDescription();
+ public native void setDescription(String description);
+ public native BitDepth getBitDepth();
+ public native void setBitDepth(BitDepth bitDepth);
+ public native boolean isData();
+ public native void setIsData(boolean isData);
+ public native Allocation getAllocation();
+ public native void setAllocation(Allocation allocation);
+ public native int getAllocationNumVars();
+ public native void getAllocationVars(float[] vars);
+ public native void setAllocationVars(int numvars, float[] vars);
+ public native Transform getTransform(ColorSpaceDirection dir);
+ public native void setTransform(Transform transform, ColorSpaceDirection dir);
+}
diff --git a/src/jniglue/org/OpenColorIO/ColorSpaceDirection.java b/src/jniglue/org/OpenColorIO/ColorSpaceDirection.java
new file mode 100644
index 0000000..a822f6e
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ColorSpaceDirection.java
@@ -0,0 +1,44 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ColorSpaceDirection extends LoadLibrary
+{
+ private final int m_enum;
+ protected ColorSpaceDirection(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final ColorSpaceDirection
+ COLORSPACE_DIR_UNKNOWN = new ColorSpaceDirection(0);
+ public static final ColorSpaceDirection
+ COLORSPACE_DIR_TO_REFERENCE = new ColorSpaceDirection(1);
+ public static final ColorSpaceDirection
+ COLORSPACE_DIR_FROM_REFERENCE = new ColorSpaceDirection(2);
+}
diff --git a/src/jniglue/org/OpenColorIO/ColorSpaceTransform.java b/src/jniglue/org/OpenColorIO/ColorSpaceTransform.java
new file mode 100644
index 0000000..ffc856b
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ColorSpaceTransform.java
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ColorSpaceTransform extends Transform
+{
+ public ColorSpaceTransform() { super(); }
+ protected ColorSpaceTransform(long impl) { super(impl); }
+ public native ColorSpaceTransform Create();
+ public native String getSrc();
+ public native void setSrc(String src);
+ public native String getDst();
+ public native void setDst(String dst);
+}
diff --git a/src/jniglue/org/OpenColorIO/Config.java b/src/jniglue/org/OpenColorIO/Config.java
new file mode 100644
index 0000000..f35ca65
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Config.java
@@ -0,0 +1,96 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Config extends LoadLibrary
+{
+ public Config() { super(); }
+ protected Config(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native Config Create();
+ public native Config CreateFromEnv();
+ public native Config CreateFromFile(String filename);
+ public native Config CreateFromStream(String istream);
+ public native Config createEditableCopy();
+ public native void sanityCheck();
+ public native String getDescription();
+ public native void setDescription(String description);
+ public native String serialize();
+ public native String getCacheID();
+ public native String getCacheID(Context context);
+ public native Context getCurrentContext();
+ public native String getSearchPath();
+ public native void setSearchPath(String path);
+ public native String getWorkingDir();
+ public native void setWorkingDir(String dirname);
+ public native int getNumColorSpaces();
+ public native String getColorSpaceNameByIndex(int index);
+ public native ColorSpace getColorSpace(String name);
+ public native int getIndexForColorSpace(String name);
+ public native void addColorSpace(ColorSpace cs);
+ public native void clearColorSpaces();
+ public native String parseColorSpaceFromString(String str);
+ public native boolean isStrictParsingEnabled();
+ public native void setStrictParsingEnabled(boolean enabled);
+ public native void setRole(String role, String colorSpaceName);
+ public native int getNumRoles();
+ public native boolean hasRole(String role);
+ public native String getRoleName(int index);
+ public native String getDefaultDisplay();
+ public native int getNumDisplays();
+ public native String getDisplay(int index);
+ public native String getDefaultView(String display);
+ public native int getNumViews(String display);
+ public native String getView(String display, int index);
+ public native String getDisplayColorSpaceName(String display, String view);
+ public native String getDisplayLooks(String display, String view);
+ // TODO: seems that 4 string params causes a memory error in the JNI layer?
+ // public native void addDisplay(String display, String view, String colorSpaceName, int looks);
+ public native void clearDisplays();
+ public native void setActiveDisplays(String displays);
+ public native String getActiveDisplays();
+ public native void setActiveViews(String views);
+ public native String getActiveViews();
+ public native void getDefaultLumaCoefs(float[] rgb);
+ public native void setDefaultLumaCoefs(float[] rgb);
+ public native Look getLook(String name);
+ public native int getNumLooks();
+ public native String getLookNameByIndex(int index);
+ public native void addLook(Look look);
+ public native void clearLooks();
+ public native Processor getProcessor(Context context, ColorSpace srcColorSpace, ColorSpace dstColorSpace);
+ public native Processor getProcessor(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
+ public native Processor getProcessor(String srcName, String dstName);
+ public native Processor getProcessor(Context context, String srcName, String dstName);
+ public native Processor getProcessor(Transform transform);
+ public native Processor getProcessor(Transform transform, TransformDirection direction);
+ public native Processor getProcessor(Context context, Transform transform, TransformDirection direction);
+}
diff --git a/src/jniglue/org/OpenColorIO/Context.java b/src/jniglue/org/OpenColorIO/Context.java
new file mode 100644
index 0000000..eaec345
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Context.java
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Context extends LoadLibrary
+{
+ public Context() { super(); }
+ protected Context(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native Context Create();
+ public native Context createEditableCopy();
+ public native String getCacheID();
+ public native void setSearchPath(String path);
+ public native String getSearchPath();
+ public native void setWorkingDir(String dirname);
+ public native String getWorkingDir();
+ public native void setStringVar(String name, String value);
+ public native String getStringVar(String name);
+ public native int getNumStringVars();
+ public native String getStringVarNameByIndex(int index);
+ public native void loadEnvironment();
+ public native String resolveStringVar(String val);
+ public native String resolveFileLocation(String filename) throws ExceptionMissingFile;
+}
diff --git a/src/jniglue/org/OpenColorIO/DisplayTransform.java b/src/jniglue/org/OpenColorIO/DisplayTransform.java
new file mode 100644
index 0000000..0867029
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/DisplayTransform.java
@@ -0,0 +1,55 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class DisplayTransform extends Transform
+{
+ public DisplayTransform() { super(); }
+ protected DisplayTransform(long impl) { super(impl); }
+ public native DisplayTransform Create();
+ public native void setInputColorSpaceName(String name);
+ public native String getInputColorSpaceName();
+ public native void setLinearCC(Transform cc);
+ public native Transform getLinearCC();
+ public native void setColorTimingCC(Transform cc);
+ public native Transform getColorTimingCC();
+ public native void setChannelView(Transform transform);
+ public native Transform getChannelView();
+ public native void setDisplay(String display);
+ public native String getDisplay();
+ public native void setView(String view);
+ public native String getView();
+ public native void setDisplayCC(Transform cc);
+ public native Transform getDisplayCC();
+ public native void setLooksOverride(String looks);
+ public native String getLooksOverride();
+ public native void setLooksOverrideEnabled(boolean enabled);
+ public native boolean getLooksOverrideEnabled();
+}
diff --git a/src/jniglue/org/OpenColorIO/ExceptionBase.java b/src/jniglue/org/OpenColorIO/ExceptionBase.java
new file mode 100644
index 0000000..ba8639f
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ExceptionBase.java
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ExceptionBase extends java.lang.Exception
+{
+ public ExceptionBase(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/jniglue/org/OpenColorIO/ExceptionMissingFile.java b/src/jniglue/org/OpenColorIO/ExceptionMissingFile.java
new file mode 100644
index 0000000..a0c79ef
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ExceptionMissingFile.java
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ExceptionMissingFile extends ExceptionBase
+{
+ public ExceptionMissingFile(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/jniglue/org/OpenColorIO/ExponentTransform.java b/src/jniglue/org/OpenColorIO/ExponentTransform.java
new file mode 100644
index 0000000..4f763a9
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ExponentTransform.java
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ExponentTransform extends Transform
+{
+ public ExponentTransform() { super(); }
+ protected ExponentTransform(long impl) { super(impl); }
+ public native ExponentTransform Create();
+ public native void setValue(float[] vec4);
+ public native void getValue(float[] vec4);
+}
diff --git a/src/jniglue/org/OpenColorIO/FileTransform.java b/src/jniglue/org/OpenColorIO/FileTransform.java
new file mode 100644
index 0000000..bfe55cc
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/FileTransform.java
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class FileTransform extends Transform
+{
+ public FileTransform() { super(); }
+ protected FileTransform(long impl) { super(impl); }
+ public native FileTransform Create();
+ public native String getSrc();
+ public native void setSrc(String src);
+ public native String getCCCId();
+ public native void setCCCId(String id);
+ public native Interpolation getInterpolation();
+ public native void setInterpolation(Interpolation interp);
+ public native int getNumFormats();
+ public native String getFormatNameByIndex(int index);
+ public native String getFormatExtensionByIndex(int index);
+}
diff --git a/src/jniglue/org/OpenColorIO/Globals.java b/src/jniglue/org/OpenColorIO/Globals.java
new file mode 100644
index 0000000..5273bd7
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Globals.java
@@ -0,0 +1,78 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Globals extends LoadLibrary
+{
+ public native void ClearAllCaches();
+ public native String GetVersion();
+ public native int GetVersionHex();
+ public native LoggingLevel GetLoggingLevel();
+ public native void SetLoggingLevel(LoggingLevel level);
+ public native Config GetCurrentConfig();
+ public native void SetCurrentConfig(Config config);
+
+ // Types
+ public native String BoolToString(boolean val);
+ public native boolean BoolFromString(String s);
+ public native String LoggingLevelToString(LoggingLevel level);
+ public native LoggingLevel LoggingLevelFromString(String s);
+ public native String TransformDirectionToString(TransformDirection dir);
+ public native TransformDirection TransformDirectionFromString(String s);
+ public native TransformDirection GetInverseTransformDirection(TransformDirection dir);
+ public native TransformDirection CombineTransformDirections(TransformDirection d1, TransformDirection d2);
+ public native String ColorSpaceDirectionToString(ColorSpaceDirection dir);
+ public native ColorSpaceDirection ColorSpaceDirectionFromString(String s);
+ public native String BitDepthToString(BitDepth bitDepth);
+ public native BitDepth BitDepthFromString(String s);
+ public native boolean BitDepthIsFloat(BitDepth bitDepth);
+ public native int BitDepthToInt(BitDepth bitDepth);
+ public native String AllocationToString(Allocation allocation);
+ public native Allocation AllocationFromString(String s);
+ public native String InterpolationToString(Interpolation interp);
+ public native Interpolation InterpolationFromString(String s);
+ public native String GpuLanguageToString(GpuLanguage language);
+ public native GpuLanguage GpuLanguageFromString(String s);
+
+ // Roles
+ public String ROLE_DEFAULT;
+ public String ROLE_REFERENCE;
+ public String ROLE_DATA;
+ public String ROLE_COLOR_PICKING;
+ public String ROLE_SCENE_LINEAR;
+ public String ROLE_COMPOSITING_LOG;
+ public String ROLE_COLOR_TIMING;
+ public String ROLE_TEXTURE_PAINT;
+ public String ROLE_MATTE_PAINT;
+
+ //
+ public Globals() { super(); create(); }
+ private native void create();
+}
diff --git a/src/jniglue/org/OpenColorIO/GpuLanguage.java b/src/jniglue/org/OpenColorIO/GpuLanguage.java
new file mode 100644
index 0000000..3368a88
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/GpuLanguage.java
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class GpuLanguage extends LoadLibrary
+{
+ private final int m_enum;
+ protected GpuLanguage(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final GpuLanguage
+ GPU_LANGUAGE_UNKNOWN = new GpuLanguage(0);
+ public static final GpuLanguage
+ GPU_LANGUAGE_CG = new GpuLanguage(1);
+ public static final GpuLanguage
+ GPU_LANGUAGE_GLSL_1_0 = new GpuLanguage(2);
+ public static final GpuLanguage
+ GPU_LANGUAGE_GLSL_1_3 = new GpuLanguage(3);
+}
diff --git a/src/jniglue/org/OpenColorIO/GpuShaderDesc.java b/src/jniglue/org/OpenColorIO/GpuShaderDesc.java
new file mode 100644
index 0000000..bdaf855
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/GpuShaderDesc.java
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class GpuShaderDesc extends LoadLibrary
+{
+ public GpuShaderDesc() { super(); create(); }
+ protected GpuShaderDesc(long impl) { super(impl); }
+ private native void create();
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native void setLanguage(GpuLanguage lang);
+ public native GpuLanguage getLanguage();
+ public native void setFunctionName(String name);
+ public native String getFunctionName();
+ public native void setLut3DEdgeLen(int len);
+ public native int getLut3DEdgeLen();
+ public native String getCacheID();
+};
diff --git a/src/jniglue/org/OpenColorIO/GroupTransform.java b/src/jniglue/org/OpenColorIO/GroupTransform.java
new file mode 100644
index 0000000..b0a24e6
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/GroupTransform.java
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class GroupTransform extends Transform
+{
+ public GroupTransform() { super(); }
+ protected GroupTransform(long impl) { super(impl); }
+ public native GroupTransform Create();
+ public native Transform getTransform(int index);
+ public native int size();
+ public native void push_back(Transform transform);
+ public native void clear();
+ public native boolean empty();
+}
diff --git a/src/jniglue/org/OpenColorIO/ImageDesc.java b/src/jniglue/org/OpenColorIO/ImageDesc.java
new file mode 100644
index 0000000..f442ca1
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/ImageDesc.java
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class ImageDesc extends LoadLibrary
+{
+ public ImageDesc() { super(); }
+ protected ImageDesc(long impl) { super(impl); }
+};
diff --git a/src/jniglue/org/OpenColorIO/Interpolation.java b/src/jniglue/org/OpenColorIO/Interpolation.java
new file mode 100644
index 0000000..f807d99
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Interpolation.java
@@ -0,0 +1,48 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Interpolation extends LoadLibrary
+{
+ private final int m_enum;
+ protected Interpolation(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final Interpolation
+ INTERP_UNKNOWN = new Interpolation(0);
+ public static final Interpolation
+ INTERP_NEAREST = new Interpolation(1);
+ public static final Interpolation
+ INTERP_LINEAR = new Interpolation(2);
+ public static final Interpolation
+ INTERP_TETRAHEDRAL = new Interpolation(3);
+ public static final Interpolation
+ INTERP_BEST = new Interpolation(255);
+}
diff --git a/src/jniglue/org/OpenColorIO/LogTransform.java b/src/jniglue/org/OpenColorIO/LogTransform.java
new file mode 100644
index 0000000..0f5b435
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/LogTransform.java
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class LogTransform extends Transform
+{
+ public LogTransform() { super(); }
+ protected LogTransform(long impl) { super(impl); }
+ public native LogTransform Create();
+ public native void setBase(float val);
+ public native float getBase();
+}
diff --git a/src/jniglue/org/OpenColorIO/LoggingLevel.java b/src/jniglue/org/OpenColorIO/LoggingLevel.java
new file mode 100644
index 0000000..a8106e4
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/LoggingLevel.java
@@ -0,0 +1,48 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class LoggingLevel extends LoadLibrary
+{
+ private final int m_enum;
+ protected LoggingLevel(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final LoggingLevel
+ LOGGING_LEVEL_NONE = new LoggingLevel(0);
+ public static final LoggingLevel
+ LOGGING_LEVEL_WARNING = new LoggingLevel(1);
+ public static final LoggingLevel
+ LOGGING_LEVEL_INFO = new LoggingLevel(2);
+ public static final LoggingLevel
+ LOGGING_LEVEL_DEBUG = new LoggingLevel(3);
+ public static final LoggingLevel
+ LOGGING_LEVEL_UNKNOWN = new LoggingLevel(255);
+}
diff --git a/src/jniglue/org/OpenColorIO/Look.java b/src/jniglue/org/OpenColorIO/Look.java
new file mode 100644
index 0000000..c2fb0ef
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Look.java
@@ -0,0 +1,48 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Look extends LoadLibrary
+{
+ public Look() { super(); }
+ protected Look(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native Look Create();
+ public native String getName();
+ public native void setName(String name);
+ public native String getProcessSpace();
+ public native void setProcessSpace(String processSpace);
+ public native Transform getTransform();
+ public native void setTransform(Transform transform);
+ public native Transform getInverseTransform();
+ public native void setInverseTransform(Transform transform);
+};
+
diff --git a/src/jniglue/org/OpenColorIO/LookTransform.java b/src/jniglue/org/OpenColorIO/LookTransform.java
new file mode 100644
index 0000000..a6ca6b3
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/LookTransform.java
@@ -0,0 +1,43 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class LookTransform extends Transform
+{
+ public LookTransform() { super(); }
+ protected LookTransform(long impl) { super(impl); }
+ public native LookTransform Create();
+ public native String getSrc();
+ public native void setSrc(String src);
+ public native String getDst();
+ public native void setDst(String dst);
+ public native void setLooks(String looks);
+ public native String getLooks();
+}
diff --git a/src/jniglue/org/OpenColorIO/MatrixTransform.java b/src/jniglue/org/OpenColorIO/MatrixTransform.java
new file mode 100644
index 0000000..d4560f1
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/MatrixTransform.java
@@ -0,0 +1,54 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class MatrixTransform extends Transform
+{
+ public MatrixTransform() { super(); }
+ protected MatrixTransform(long impl) { super(impl); }
+ public native MatrixTransform Create();
+ public native boolean equals(MatrixTransform obj);
+ public native void setValue(float[] m44, float[] offset4);
+ public native void getValue(float[] m44, float[] offset4);
+ public native void setMatrix(float[] m44);
+ public native void getMatrix(float[] m44);
+ public native void setOffset(float[] offset4);
+ public native void getOffset(float[] offset4);
+ public native void Fit(float[] m44, float[] offset4,
+ float[] oldmin4, float[] oldmax4,
+ float[] newmin4, float[] newmax4);
+ public native void Identity(float[] m44, float[] offset4);
+ public native void Sat(float[] m44, float[] offset4,
+ float sat, float[] lumaCoef3);
+ public native void Scale(float[] m44, float[] offset4,
+ float[] scale4);
+ public native void View(float[] m44, float[] offset4,
+ int[] channelHot4, float[] lumaCoef3);
+}
diff --git a/src/jniglue/org/OpenColorIO/PackedImageDesc.java b/src/jniglue/org/OpenColorIO/PackedImageDesc.java
new file mode 100644
index 0000000..8cc6932
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/PackedImageDesc.java
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+import java.nio.FloatBuffer;
+
+public class PackedImageDesc extends ImageDesc
+{
+ public PackedImageDesc(FloatBuffer data, long width, long height, long numChannels)
+ {
+ super();
+ create(data, width, height, numChannels);
+ }
+ public PackedImageDesc(FloatBuffer data, long width, long height, long numChannels,
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes)
+ {
+ super();
+ create(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
+ }
+ protected PackedImageDesc(long impl) { super(impl); }
+ protected native void create(FloatBuffer data, long width, long height, long numChannels);
+ protected native void create(FloatBuffer data, long width, long height, long numChannels,
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes);
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native FloatBuffer getData();
+ public native long getWidth();
+ public native long getHeight();
+ public native long getNumChannels();
+ public native long getChanStrideBytes();
+ public native long getXStrideBytes();
+ public native long getYStrideBytes();
+};
diff --git a/src/jniglue/org/OpenColorIO/PlanarImageDesc.java b/src/jniglue/org/OpenColorIO/PlanarImageDesc.java
new file mode 100644
index 0000000..86fc5de
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/PlanarImageDesc.java
@@ -0,0 +1,63 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+import java.nio.FloatBuffer;
+
+public class PlanarImageDesc extends ImageDesc
+{
+ public PlanarImageDesc(FloatBuffer rData, FloatBuffer gData, FloatBuffer bData,
+ FloatBuffer aData, long width, long height)
+ {
+ super();
+ create(rData, gData, bData, aData, width, height);
+ }
+ public PlanarImageDesc(FloatBuffer rData, FloatBuffer gData, FloatBuffer bData,
+ FloatBuffer aData, long width, long height,
+ long yStrideBytes)
+ {
+ super();
+ create(rData, gData, bData, aData, width, height, yStrideBytes);
+ }
+ protected PlanarImageDesc(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ protected native void create(FloatBuffer rData, FloatBuffer gData, FloatBuffer bData,
+ FloatBuffer aData, long width, long height);
+ protected native void create(FloatBuffer rData, FloatBuffer gData, FloatBuffer bData,
+ FloatBuffer aData, long width, long height,
+ long yStrideBytes);
+ public native FloatBuffer getRData();
+ public native FloatBuffer getGData();
+ public native FloatBuffer getBData();
+ public native FloatBuffer getAData();
+ public native long getWidth();
+ public native long getHeight();
+ public native long getYStrideBytes();
+};
diff --git a/src/jniglue/org/OpenColorIO/Processor.java b/src/jniglue/org/OpenColorIO/Processor.java
new file mode 100644
index 0000000..a999992
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Processor.java
@@ -0,0 +1,51 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+import java.nio.FloatBuffer;
+
+public class Processor extends LoadLibrary
+{
+ public Processor() { super(); }
+ protected Processor(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native Processor Create();
+ public native boolean isNoOp();
+ public native boolean hasChannelCrosstalk();
+ public native void apply(ImageDesc img);
+ public native void applyRGB(float[] pixel);
+ public native void applyRGBA(float[] pixel);
+ public native String getCpuCacheID();
+ public native String getGpuShaderText(GpuShaderDesc shaderDesc);
+ public native String getGpuShaderTextCacheID(GpuShaderDesc shaderDesc);
+ public native void getGpuLut3D(FloatBuffer lut3d, GpuShaderDesc shaderDesc);
+ public native String getGpuLut3DCacheID(GpuShaderDesc shaderDesc);
+};
+
diff --git a/src/jniglue/org/OpenColorIO/Transform.java b/src/jniglue/org/OpenColorIO/Transform.java
new file mode 100644
index 0000000..52c6fb5
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/Transform.java
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class Transform extends LoadLibrary
+{
+ public Transform() { super(); }
+ protected Transform(long impl) { super(impl); }
+ public native void dispose();
+ protected void finalize() { dispose(); }
+ public native Transform createEditableCopy();
+ public native TransformDirection getDirection();
+ public native void setDirection(TransformDirection dir);
+}
diff --git a/src/jniglue/org/OpenColorIO/TransformDirection.java b/src/jniglue/org/OpenColorIO/TransformDirection.java
new file mode 100644
index 0000000..b034b5a
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/TransformDirection.java
@@ -0,0 +1,44 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class TransformDirection extends LoadLibrary
+{
+ private final int m_enum;
+ protected TransformDirection(int type) { super(); m_enum = type; }
+ public native String toString();
+ public native boolean equals(Object obj);
+ public static final TransformDirection
+ TRANSFORM_DIR_UNKNOWN = new TransformDirection(0);
+ public static final TransformDirection
+ TRANSFORM_DIR_FORWARD = new TransformDirection(1);
+ public static final TransformDirection
+ TRANSFORM_DIR_INVERSE = new TransformDirection(2);
+}
diff --git a/src/jniglue/org/OpenColorIO/TruelightTransform.java b/src/jniglue/org/OpenColorIO/TruelightTransform.java
new file mode 100644
index 0000000..1d966e9
--- /dev/null
+++ b/src/jniglue/org/OpenColorIO/TruelightTransform.java
@@ -0,0 +1,58 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.OpenColorIO;
+import org.OpenColorIO.*;
+
+public class TruelightTransform extends Transform
+{
+ public TruelightTransform() { super(); }
+ protected TruelightTransform(long impl) { super(impl); }
+ public native TruelightTransform Create();
+ public native void setConfigRoot(String configroot);
+ public native String getConfigRoot();
+ public native void setProfile(String profile);
+ public native String getProfile();
+ public native void setCamera(String camera);
+ public native String getCamera();
+ public native void setInputDisplay(String display);
+ public native String getInputDisplay();
+ public native void setRecorder(String recorder);
+ public native String getRecorder();
+ public native void setPrint(String print);
+ public native String getPrint();
+ public native void setLamp(String lamp);
+ public native String getLamp();
+ public native void setOutputCamera(String camera);
+ public native String getOutputCamera();
+ public native void setDisplay(String display);
+ public native String getDisplay();
+ public native void setCubeInput(String type);
+ public native String getCubeInput();
+}
+
diff --git a/src/jniglue/tests/CMakeLists.txt b/src/jniglue/tests/CMakeLists.txt
new file mode 100644
index 0000000..e201749
--- /dev/null
+++ b/src/jniglue/tests/CMakeLists.txt
@@ -0,0 +1,17 @@
+###############################################################################
+### JNI JUNIT TESTS ###
+
+
+file(GLOB _TESTS_FILES "org/OpenColorIO/*.java")
+set(_JCLASS_PATH "${CMAKE_CURRENT_BINARY_DIR}:${CMAKE_CURRENT_BINARY_DIR}/..:${CMAKE_SOURCE_DIR}/ext/junit-4.9b4.jar")
+set(_JLIB_PATH "${CMAKE_CURRENT_BINARY_DIR}/..")
+
+add_custom_target(JNITests
+ COMMAND javac -cp ${_JCLASS_PATH}
+ -d ${CMAKE_CURRENT_BINARY_DIR} ${_TESTS_FILES}
+ COMMAND java -cp ${_JCLASS_PATH}
+ -Djava.library.path=${_JLIB_PATH} junit.textui.TestRunner
+ OpenColorIOTestSuite
+ DEPENDS OpenColorIO-JNI
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Setting Up and Running JNI OCIO JUNIT tests")
diff --git a/src/jniglue/tests/org/OpenColorIO/BakerTest.java b/src/jniglue/tests/org/OpenColorIO/BakerTest.java
new file mode 100644
index 0000000..63f540a
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/BakerTest.java
@@ -0,0 +1,84 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class BakerTest extends TestCase {
+
+ String SIMPLE_PROFILE = ""
+ + "ocio_profile_version: 1\n"
+ + "\n"
+ + "strictparsing: false\n"
+ + "\n"
+ + "colorspaces:\n"
+ + "\n"
+ + " - !<ColorSpace>\n"
+ + " name: lnh\n"
+ + " bitdepth: 16f\n"
+ + " isdata: false\n"
+ + " allocation: lg2\n"
+ + "\n"
+ + " - !<ColorSpace>\n"
+ + " name: test\n"
+ + " bitdepth: 8ui\n"
+ + " isdata: false\n"
+ + " allocation: uniform\n"
+ + " to_reference: !<ExponentTransform> {value: [2.2, 2.2, 2.2, 1]}\n";
+
+ String EXPECTED_LUT = ""
+ + "CSPLUTV100\n"
+ + "3D\n"
+ + "BEGIN METADATA\n"
+ + "this is some metadata!\n"
+ + "END METADATA\n"
+ + "\n"
+ + "4\n"
+ + "0.000977 0.039373 1.587401 64.000000\n"
+ + "0.000000 0.333333 0.666667 1.000000\n"
+ + "4\n"
+ + "0.000977 0.039373 1.587401 64.000000\n"
+ + "0.000000 0.333333 0.666667 1.000000\n"
+ + "4\n"
+ + "0.000977 0.039373 1.587401 64.000000\n"
+ + "0.000000 0.333333 0.666667 1.000000\n"
+ + "\n"
+ + "2 2 2\n"
+ + "0.042823 0.042823 0.042823\n"
+ + "6.622026 0.042823 0.042823\n"
+ + "0.042823 6.622026 0.042823\n"
+ + "6.622026 6.622026 0.042823\n"
+ + "0.042823 0.042823 6.622026\n"
+ + "6.622026 0.042823 6.622026\n"
+ + "0.042823 6.622026 6.622026\n"
+ + "6.622026 6.622026 6.622026\n"
+ + "\n";
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+ Baker bake = new Baker().Create();
+ Baker bakee = bake.createEditableCopy();
+ Config cfg = new Config().CreateFromStream(SIMPLE_PROFILE);
+ bakee.setConfig(cfg);
+ bakee.setFormat("cinespace");
+ assertEquals("cinespace", bakee.getFormat());
+ bakee.setType("3D");
+ assertEquals("3D", bakee.getType());
+ bakee.setMetadata("this is some metadata!");
+ assertEquals("this is some metadata!", bakee.getMetadata());
+ bakee.setInputSpace("lnh");
+ assertEquals("lnh", bakee.getInputSpace());
+ bakee.setTargetSpace("test");
+ assertEquals("test", bakee.getTargetSpace());
+ bakee.setShaperSize(4);
+ assertEquals(4, bakee.getShaperSize());
+ bakee.setCubeSize(2);
+ assertEquals(2, bakee.getCubeSize());
+ String output = bakee.bake();
+ assertEquals(EXPECTED_LUT, output);
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/ColorSpaceTest.java b/src/jniglue/tests/org/OpenColorIO/ColorSpaceTest.java
new file mode 100644
index 0000000..f49e582
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/ColorSpaceTest.java
@@ -0,0 +1,41 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class ColorSpaceTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+ ColorSpace cs = new ColorSpace().Create();
+ cs.setName("mynewcolspace");
+ assertEquals("mynewcolspace", cs.getName());
+ cs.setFamily("fam1");
+ assertEquals("fam1", cs.getFamily());
+ cs.setEqualityGroup("match1");
+ assertEquals("match1", cs.getEqualityGroup());
+ cs.setDescription("this is a test");
+ assertEquals("this is a test", cs.getDescription());
+ cs.setBitDepth(BitDepth.BIT_DEPTH_F16);
+ assertEquals(BitDepth.BIT_DEPTH_F16, cs.getBitDepth());
+ cs.setIsData(false);
+ assertEquals(false, cs.isData());
+ cs.setAllocation(Allocation.ALLOCATION_LG2);
+ assertEquals(Allocation.ALLOCATION_LG2, cs.getAllocation());
+ float test[] = new float[]{0.1f, 0.2f, 0.3f};
+ cs.setAllocationVars(3, test);
+ assertEquals(3, cs.getAllocationNumVars());
+ float out[] = new float[3];
+ cs.getAllocationVars(out);
+ LogTransform lt = new LogTransform().Create();
+ lt.setBase(10.f);
+ cs.setTransform(lt, ColorSpaceDirection.COLORSPACE_DIR_TO_REFERENCE);
+ LogTransform ott = (LogTransform)cs.getTransform(ColorSpaceDirection.COLORSPACE_DIR_TO_REFERENCE);
+ assertEquals(10.f, ott.getBase());
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/ConfigTest.java b/src/jniglue/tests/org/OpenColorIO/ConfigTest.java
new file mode 100644
index 0000000..a676bae
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/ConfigTest.java
@@ -0,0 +1,220 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+import java.nio.*;
+
+public class ConfigTest extends TestCase {
+
+ String SIMPLE_PROFILE = ""
+ + "ocio_profile_version: 1\n"
+ + "\n"
+ + "search_path: luts\n"
+ + "strictparsing: false\n"
+ + "luma: [0.2126, 0.7152, 0.0722]\n"
+ + "\n"
+ + "roles:\n"
+ + " default: raw\n"
+ + " scene_linear: lnh\n"
+ + "\n"
+ + "displays:\n"
+ + " sRGB:\n"
+ + " - !<View> {name: Film1D, colorspace: vd8}\n"
+ + " - !<View> {name: Raw, colorspace: raw}\n"
+ + "\n"
+ + "active_displays: []\n"
+ + "active_views: []\n"
+ + "\n"
+ + "colorspaces:\n"
+ + " - !<ColorSpace>\n"
+ + " name: raw\n"
+ + " family: raw\n"
+ + " bitdepth: 32f\n"
+ + " description: |\n"
+ + " A raw color space. Conversions to and from this space are no-ops.\n"
+ + " \n"
+ + " isdata: true\n"
+ + " allocation: uniform\n"
+ + "\n"
+ + " - !<ColorSpace>\n"
+ + " name: lnh\n"
+ + " family: ln\n"
+ + " bitdepth: 16f\n"
+ + " description: |\n"
+ + " The show reference space. This is a sensor referred linear\n"
+ + " representation of the scene with primaries that correspond to\n"
+ + " scanned film. 0.18 in this space corresponds to a properly\n"
+ + " exposed 18% grey card.\n"
+ + " \n"
+ + " isdata: false\n"
+ + " allocation: lg2\n"
+ + "\n"
+ + " - !<ColorSpace>\n"
+ + " name: vd8\n"
+ + " family: vd8\n"
+ + " bitdepth: 8ui\n"
+ + " description: |\n"
+ + " how many transforms can we use?\n"
+ + " \n"
+ + " isdata: false\n"
+ + " allocation: uniform\n"
+ + " to_reference: !<GroupTransform>\n"
+ + " children:\n"
+ + " - !<ExponentTransform> {value: [2.2, 2.2, 2.2, 1]}\n"
+ + " - !<MatrixTransform> {matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], offset: [0, 0, 0, 0]}\n"
+ + " - !<CDLTransform> {slope: [1, 1, 1], offset: [0.1, 0.3, 0.4], power: [1.1, 1.1, 1.1], saturation: 0.9}\n";
+
+ String GLSLResult = ""
+ + "\n"
+ + "// Generated by OpenColorIO\n"
+ + "\n"
+ + "vec4 jnitestocio(in vec4 inPixel, \n"
+ + " const sampler3D lut3d) \n"
+ + "{\n"
+ + "vec4 out_pixel = inPixel; \n"
+ + "out_pixel = out_pixel * mat4(1.08749, -0.0794667, -0.00802222, 0, -0.0236222, 1.03164, -0.00802222, 0, -0.0236222, -0.0794667, 1.10309, 0, 0, 0, 0, 1);\n"
+ + "out_pixel = pow(max(out_pixel, vec4(0, 0, 0, 0)), vec4(0.909091, 0.909091, 0.909091, 1));\n"
+ + "out_pixel = vec4(-0.1, -0.3, -0.4, -0) + out_pixel;\n"
+ + "out_pixel = pow(max(out_pixel, vec4(0, 0, 0, 0)), vec4(0.454545, 0.454545, 0.454545, 1));\n"
+ + "// OSX segfault work-around: Force a no-op sampling of the 3d lut.\n"
+ + "texture3D(lut3d, -inf * out_pixel.rgb + inf).rgb;\n"
+ + "return out_pixel;\n"
+ + "}\n"
+ + "\n";
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+
+ Config _cfg = new Config().CreateFromStream(SIMPLE_PROFILE);
+ Config _cfge = _cfg.createEditableCopy();
+ assertEquals("luts", _cfge.getSearchPath());
+ _cfge.setSearchPath("otherdir");
+ assertEquals("otherdir", _cfge.getSearchPath());
+ _cfge.sanityCheck();
+ _cfge.setDescription("testdesc");
+ assertEquals("testdesc", _cfge.getDescription());
+ //assertEquals(SIMPLE_PROFILE, _cfg.serialize());
+ //assertEquals("$07d1fb1509eeae1837825fd4242f8a69:$885ad1683add38a11f7bbe34e8bf9ac0",
+ // _cfg.getCacheID());
+ Context con = _cfg.getCurrentContext();
+ assertNotSame(0, con.getNumStringVars());
+ //assertEquals("", _cfg.getCacheID(con)); // test env makes this fail
+ //assertEquals("", _cfge.getWorkingDir());
+ _cfge.setWorkingDir("/foobar");
+ assertEquals("/foobar", _cfge.getWorkingDir());
+ assertEquals(3, _cfge.getNumColorSpaces());
+ assertEquals("lnh", _cfge.getColorSpaceNameByIndex(1));
+ //public native ColorSpace getColorSpace(String name);
+ assertEquals(0, _cfge.getIndexForColorSpace("foobar"));
+ //public native void addColorSpace(ColorSpace cs);
+ //public native void clearColorSpaces();
+ //public native String parseColorSpaceFromString(String str);
+ if(_cfg.isStrictParsingEnabled()) fail("strict parsing should be off");
+ _cfge.setStrictParsingEnabled(true);
+ if(!_cfge.isStrictParsingEnabled()) fail("strict parsing should be on");
+ assertEquals(2, _cfge.getNumRoles());
+ if(_cfg.hasRole("foo")) fail("shouldn't have role foo");
+ _cfge.setRole("foo", "dfadfadf");
+ assertEquals(3, _cfge.getNumRoles());
+ if(!_cfge.hasRole("foo")) fail("should have role foo");
+ assertEquals("foo", _cfge.getRoleName(1));
+ assertEquals("sRGB", _cfge.getDefaultDisplay());
+ assertEquals(1, _cfge.getNumDisplays());
+ assertEquals("sRGB", _cfge.getDisplay(0));
+ assertEquals("Film1D", _cfge.getDefaultView("sRGB"));
+ assertEquals(2, _cfge.getNumViews("sRGB"));
+ assertEquals("Raw", _cfge.getView("sRGB", 1));
+ assertEquals("vd8", _cfge.getDisplayColorSpaceName("sRGB", "Film1D"));
+ assertEquals("", _cfg.getDisplayLooks("sRGB", "Film1D"));
+
+ // TODO: seems that 4 string params causes a memory error in the JNI layer?
+ //_cfge.addDisplay("foo", "bar", "foo", 0);
+
+ _cfge.clearDisplays();
+ _cfge.setActiveDisplays("sRGB");
+ assertEquals("sRGB", _cfge.getActiveDisplays());
+ _cfge.setActiveViews("Film1D");
+ assertEquals("Film1D", _cfge.getActiveViews());
+ float luma[] = new float[3];
+ _cfge.getDefaultLumaCoefs(luma);
+ assertEquals(0.2126, luma[0], 1e-8);
+ float[] newluma = new float[]{0.1f, 0.2f, 0.3f};
+ _cfge.setDefaultLumaCoefs(newluma);
+ float tnewluma[] = new float[3];
+ _cfge.getDefaultLumaCoefs(tnewluma);
+ assertEquals(0.1f, tnewluma[0], 1e-8);
+ assertEquals(0, _cfge.getNumLooks());
+ Look lk = new Look().Create();
+ lk.setName("coollook");
+ lk.setProcessSpace("somespace");
+ ExponentTransform et = new ExponentTransform().Create();
+ et.setValue(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
+ lk.setTransform(et);
+ ExponentTransform iet = new ExponentTransform().Create();
+ iet.setValue(new float[]{-0.1f, -0.2f, -0.3f, -0.4f});
+ lk.setInverseTransform(iet);
+ _cfge.addLook(lk);
+ assertEquals(1, _cfge.getNumLooks());
+ assertEquals("coollook", _cfge.getLookNameByIndex(0));
+ Look glk = _cfge.getLook("coollook");
+ assertEquals("somespace", glk.getProcessSpace());
+ _cfge.clearLooks();
+ assertEquals(0, _cfge.getNumLooks());
+
+ //public native Processor getProcessor(Context context, ColorSpace srcColorSpace, ColorSpace dstColorSpace);
+
+ Processor _proc = _cfg.getProcessor("lnh", "vd8");
+ assertEquals(false, _proc.isNoOp());
+ assertEquals(true, _proc.hasChannelCrosstalk());
+ float packedpix[] = new float[]{0.48f, 0.18f, 0.9f, 1.0f,
+ 0.48f, 0.18f, 0.18f, 1.0f,
+ 0.48f, 0.18f, 0.18f, 1.0f,
+ 0.48f, 0.18f, 0.18f, 1.0f };
+ FloatBuffer buf = ByteBuffer.allocateDirect(2 * 2 * 4 * Float.SIZE / 8).asFloatBuffer();
+ buf.put(packedpix);
+ PackedImageDesc foo = new PackedImageDesc(buf, 2, 2, 4);
+ _proc.apply(foo);
+ FloatBuffer wee = foo.getData();
+ assertEquals(-2.4307251581696764E-35f, wee.get(2), 1e-8);
+ float rgbfoo[] = new float[]{0.48f, 0.18f, 0.18f};
+ _proc.applyRGB(rgbfoo);
+ assertEquals(0.6875247f, rgbfoo[0], 1e-8);
+ float rgbafoo[] = new float[]{0.48f, 0.18f, 0.18f, 1.f};
+ _proc.applyRGBA(rgbafoo);
+ assertEquals(1.f, rgbafoo[3], 1e-8);
+ //assertEquals("$a92ef63abd9edf61ad5a7855da064648", _proc.getCpuCacheID());
+ GpuShaderDesc desc = new GpuShaderDesc();
+ desc.setLanguage(GpuLanguage.GPU_LANGUAGE_GLSL_1_3);
+ desc.setFunctionName("jnitestocio");
+ desc.setLut3DEdgeLen(32);
+ String glsl = _proc.getGpuShaderText(desc);
+ //assertEquals(GLSLResult, glsl);
+ //assertEquals("$1dead2bf42974cd1769164e45a0c9e40", _proc.getGpuShaderTextCacheID(desc));
+ int len = desc.getLut3DEdgeLen();
+ int size = 3 * len * len * len;
+ FloatBuffer lut3d = ByteBuffer.allocateDirect(size * Float.SIZE / 8).asFloatBuffer();
+ _proc.getGpuLut3D(lut3d, desc);
+ assertEquals(0.0f, lut3d.get(size-1));
+ assertEquals("<NULL>", _proc.getGpuLut3DCacheID(desc));
+
+ //public native Processor getProcessor(Context context, String srcName, String dstName);
+ //public native Processor getProcessor(Transform transform);
+ //public native Processor getProcessor(Transform transform, TransformDirection direction);
+ //public native Processor getProcessor(Context context, Transform transform, TransformDirection direction);
+
+ _cfge.dispose();
+ _cfg.dispose();
+
+ //System.out.println(_cfge.serialize());
+ //_cfge.sanityCheck();
+ //System.out.println(_cfge.getNumColorSpaces());
+ //System.out.println(_cfg.getCacheID());
+ //System.out.println(_cfge.serialize());
+
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/ContextTest.java b/src/jniglue/tests/org/OpenColorIO/ContextTest.java
new file mode 100644
index 0000000..87579e3
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/ContextTest.java
@@ -0,0 +1,38 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class ContextTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+ Context cont = new Context().Create();
+ cont.setSearchPath("testing123");
+ cont.setWorkingDir("/dir/123");
+ assertEquals("$af84c0ff921e48843d711a761e05b80f", cont.getCacheID());
+ assertEquals("testing123", cont.getSearchPath());
+ assertEquals("/dir/123", cont.getWorkingDir());
+ cont.setStringVar("TeSt", "foobar");
+ assertEquals("foobar", cont.getStringVar("TeSt"));
+ assertEquals(1, cont.getNumStringVars());
+ assertEquals("TeSt", cont.getStringVarNameByIndex(0));
+ cont.loadEnvironment();
+ assertNotSame(0, cont.getNumStringVars());
+ cont.setStringVar("TEST1", "foobar");
+ assertEquals("/foo/foobar/bar",
+ cont.resolveStringVar("/foo/${TEST1}/bar"));
+ try {
+ cont.setSearchPath("testing123");
+ String foo = cont.resolveFileLocation("test.lut");
+ System.out.println(foo);
+ } catch (ExceptionMissingFile e) {
+ //System.out.println(e);
+ }
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/GlobalsTest.java b/src/jniglue/tests/org/OpenColorIO/GlobalsTest.java
new file mode 100644
index 0000000..72f92f8
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/GlobalsTest.java
@@ -0,0 +1,150 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class GlobalsTest extends TestCase {
+
+ String FOO = ""
+ + "ocio_profile_version: 1\n"
+ + "\n"
+ + "search_path: \n"
+ + "strictparsing: false\n"
+ + "luma: [0.2126, 0.7152, 0.0722]\n"
+ + "\n"
+ + "roles:\n"
+ + " default: raw\n"
+ + "\n"
+ + "displays:\n"
+ + " sRGB:\n"
+ + " - !<View> {name: Raw, colorspace: raw}\n"
+ + "\n"
+ + "active_displays: []\n"
+ + "active_views: []\n"
+ + "\n"
+ + "colorspaces:\n"
+ + " - !<ColorSpace>\n"
+ + " name: raw\n"
+ + " family: raw\n"
+ + " equalitygroup: \n"
+ + " bitdepth: 32f\n"
+ + " description: |\n"
+ + " A raw color space. Conversions to and from this space are no-ops.\n"
+ + " isdata: true\n"
+ + " allocation: uniform\n";
+
+ protected void setUp() {
+ }
+
+ public void test_interface() {
+
+ Globals globals = new Globals();
+
+ // Globals
+ globals.ClearAllCaches();
+ //assertEquals("1.0.1", globals.GetVersion());
+ //assertEquals(16777472, globals.GetVersionHex());
+ assertEquals(LoggingLevel.LOGGING_LEVEL_INFO, globals.GetLoggingLevel());
+ globals.SetLoggingLevel(LoggingLevel.LOGGING_LEVEL_NONE);
+ assertEquals(LoggingLevel.LOGGING_LEVEL_NONE, globals.GetLoggingLevel());
+ Config foo = globals.GetCurrentConfig();
+ assertEquals(FOO, foo.serialize());
+ globals.SetLoggingLevel(LoggingLevel.LOGGING_LEVEL_INFO);
+ Config bar = new Config().CreateFromStream(foo.serialize());
+ globals.SetCurrentConfig(bar);
+ Config wee = globals.GetCurrentConfig();
+
+ // LoggingLevel
+ assertEquals(globals.LoggingLevelToString(LoggingLevel.LOGGING_LEVEL_NONE), "none");
+ assertEquals(globals.LoggingLevelFromString("none"), LoggingLevel.LOGGING_LEVEL_NONE);
+ assertEquals(globals.LoggingLevelToString(LoggingLevel.LOGGING_LEVEL_WARNING), "warning");
+ assertEquals(globals.LoggingLevelFromString("warning"), LoggingLevel.LOGGING_LEVEL_WARNING);
+ assertEquals(globals.LoggingLevelToString(LoggingLevel.LOGGING_LEVEL_INFO), "info");
+ assertEquals(globals.LoggingLevelFromString("info"), LoggingLevel.LOGGING_LEVEL_INFO);
+ assertEquals(globals.LoggingLevelToString(LoggingLevel.LOGGING_LEVEL_DEBUG), "debug");
+ assertEquals(globals.LoggingLevelFromString("debug"), LoggingLevel.LOGGING_LEVEL_DEBUG);
+ assertEquals(globals.LoggingLevelToString(LoggingLevel.LOGGING_LEVEL_UNKNOWN), "unknown");
+ assertEquals(globals.LoggingLevelFromString("unknown"), LoggingLevel.LOGGING_LEVEL_UNKNOWN);
+
+ // TransformDirection
+ assertEquals(globals.TransformDirectionToString(TransformDirection.TRANSFORM_DIR_UNKNOWN), "unknown");
+ assertEquals(globals.TransformDirectionFromString("unknown"), TransformDirection.TRANSFORM_DIR_UNKNOWN);
+ assertEquals(globals.TransformDirectionToString(TransformDirection.TRANSFORM_DIR_FORWARD), "forward");
+ assertEquals(globals.TransformDirectionFromString("forward"), TransformDirection.TRANSFORM_DIR_FORWARD);
+ assertEquals(globals.TransformDirectionToString(TransformDirection.TRANSFORM_DIR_INVERSE), "inverse");
+ assertEquals(globals.TransformDirectionFromString("inverse"), TransformDirection.TRANSFORM_DIR_INVERSE);
+ assertEquals(globals.GetInverseTransformDirection(TransformDirection.TRANSFORM_DIR_UNKNOWN), TransformDirection.TRANSFORM_DIR_UNKNOWN);
+ assertEquals(globals.GetInverseTransformDirection(TransformDirection.TRANSFORM_DIR_FORWARD), TransformDirection.TRANSFORM_DIR_INVERSE);
+ assertEquals(globals.GetInverseTransformDirection(TransformDirection.TRANSFORM_DIR_INVERSE), TransformDirection.TRANSFORM_DIR_FORWARD);
+
+ // ColorSpaceDirection
+ assertEquals(globals.ColorSpaceDirectionToString(ColorSpaceDirection.COLORSPACE_DIR_UNKNOWN), "unknown");
+ assertEquals(globals.ColorSpaceDirectionFromString("unknown"), ColorSpaceDirection.COLORSPACE_DIR_UNKNOWN);
+ assertEquals(globals.ColorSpaceDirectionToString(ColorSpaceDirection.COLORSPACE_DIR_TO_REFERENCE), "to_reference");
+ assertEquals(globals.ColorSpaceDirectionFromString("to_reference"), ColorSpaceDirection.COLORSPACE_DIR_TO_REFERENCE);
+ assertEquals(globals.ColorSpaceDirectionToString(ColorSpaceDirection.COLORSPACE_DIR_FROM_REFERENCE), "from_reference");
+ assertEquals(globals.ColorSpaceDirectionFromString("from_reference"), ColorSpaceDirection.COLORSPACE_DIR_FROM_REFERENCE);
+
+ // BitDepth
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UNKNOWN), "unknown");
+ assertEquals(globals.BitDepthFromString("unknown"), BitDepth.BIT_DEPTH_UNKNOWN);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UINT8), "8ui");
+ assertEquals(globals.BitDepthFromString("8ui"), BitDepth.BIT_DEPTH_UINT8);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UINT10), "10ui");
+ assertEquals(globals.BitDepthFromString("10ui"), BitDepth.BIT_DEPTH_UINT10);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UINT12), "12ui");
+ assertEquals(globals.BitDepthFromString("12ui"), BitDepth.BIT_DEPTH_UINT12);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UINT14), "14ui");
+ assertEquals(globals.BitDepthFromString("14ui"), BitDepth.BIT_DEPTH_UINT14);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UINT16), "16ui");
+ assertEquals(globals.BitDepthFromString("16ui"), BitDepth.BIT_DEPTH_UINT16);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_UINT32), "32ui");
+ assertEquals(globals.BitDepthFromString("32ui"), BitDepth.BIT_DEPTH_UINT32);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_F16), "16f");
+ assertEquals(globals.BitDepthFromString("16f"), BitDepth.BIT_DEPTH_F16);
+ assertEquals(globals.BitDepthToString(BitDepth.BIT_DEPTH_F32), "32f");
+ assertEquals(globals.BitDepthFromString("32f"), BitDepth.BIT_DEPTH_F32);
+
+ // Allocation
+ assertEquals(globals.AllocationToString(Allocation.ALLOCATION_UNKNOWN), "unknown");
+ assertEquals(globals.AllocationFromString("unknown"), Allocation.ALLOCATION_UNKNOWN);
+ assertEquals(globals.AllocationToString(Allocation.ALLOCATION_UNIFORM), "uniform");
+ assertEquals(globals.AllocationFromString("uniform"), Allocation.ALLOCATION_UNIFORM);
+ assertEquals(globals.AllocationToString(Allocation.ALLOCATION_LG2), "lg2");
+ assertEquals(globals.AllocationFromString("lg2"), Allocation.ALLOCATION_LG2);
+
+ // Interpolation
+ assertEquals(globals.InterpolationToString(Interpolation.INTERP_UNKNOWN), "unknown");
+ assertEquals(globals.InterpolationFromString("unknown"), Interpolation.INTERP_UNKNOWN);
+ assertEquals(globals.InterpolationToString(Interpolation.INTERP_NEAREST), "nearest");
+ assertEquals(globals.InterpolationFromString("nearest"), Interpolation.INTERP_NEAREST);
+ assertEquals(globals.InterpolationToString(Interpolation.INTERP_LINEAR), "linear");
+ assertEquals(globals.InterpolationFromString("linear"), Interpolation.INTERP_LINEAR);
+ assertEquals(globals.InterpolationToString(Interpolation.INTERP_TETRAHEDRAL), "tetrahedral");
+ assertEquals(globals.InterpolationFromString("tetrahedral"), Interpolation.INTERP_TETRAHEDRAL);
+ assertEquals(globals.InterpolationToString(Interpolation.INTERP_BEST), "best");
+ assertEquals(globals.InterpolationFromString("best"), Interpolation.INTERP_BEST);
+
+ // GpuLanguage
+ assertEquals(globals.GpuLanguageToString(GpuLanguage.GPU_LANGUAGE_UNKNOWN), "unknown");
+ assertEquals(globals.GpuLanguageFromString("unknown"), GpuLanguage.GPU_LANGUAGE_UNKNOWN);
+ assertEquals(globals.GpuLanguageToString(GpuLanguage.GPU_LANGUAGE_CG), "cg");
+ assertEquals(globals.GpuLanguageFromString("cg"), GpuLanguage.GPU_LANGUAGE_CG);
+ assertEquals(globals.GpuLanguageToString(GpuLanguage.GPU_LANGUAGE_GLSL_1_0), "glsl_1.0");
+ assertEquals(globals.GpuLanguageFromString("glsl_1.0"), GpuLanguage.GPU_LANGUAGE_GLSL_1_0);
+ assertEquals(globals.GpuLanguageToString(GpuLanguage.GPU_LANGUAGE_GLSL_1_3), "glsl_1.3");
+ assertEquals(globals.GpuLanguageFromString("glsl_1.3"), GpuLanguage.GPU_LANGUAGE_GLSL_1_3);
+
+ // Roles
+ assertEquals(globals.ROLE_DEFAULT, "default");
+ assertEquals(globals.ROLE_REFERENCE, "reference");
+ assertEquals(globals.ROLE_DATA, "data");
+ assertEquals(globals.ROLE_COLOR_PICKING, "color_picking");
+ assertEquals(globals.ROLE_SCENE_LINEAR, "scene_linear");
+ assertEquals(globals.ROLE_COMPOSITING_LOG, "compositing_log");
+ assertEquals(globals.ROLE_COLOR_TIMING, "color_timing");
+ assertEquals(globals.ROLE_TEXTURE_PAINT, "texture_paint");
+ assertEquals(globals.ROLE_MATTE_PAINT, "matte_paint");
+
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/GpuShaderDescTest.java b/src/jniglue/tests/org/OpenColorIO/GpuShaderDescTest.java
new file mode 100644
index 0000000..08b0a16
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/GpuShaderDescTest.java
@@ -0,0 +1,24 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class GpuShaderDescTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+ GpuShaderDesc desc = new GpuShaderDesc();
+ desc.setLanguage(GpuLanguage.GPU_LANGUAGE_GLSL_1_3);
+ assertEquals(GpuLanguage.GPU_LANGUAGE_GLSL_1_3, desc.getLanguage());
+ desc.setFunctionName("foo123");
+ assertEquals("foo123", desc.getFunctionName());
+ desc.setLut3DEdgeLen(32);
+ assertEquals(32, desc.getLut3DEdgeLen());
+ assertEquals("glsl_1.3 foo123 32", desc.getCacheID());
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/LookTest.java b/src/jniglue/tests/org/OpenColorIO/LookTest.java
new file mode 100644
index 0000000..778c124
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/LookTest.java
@@ -0,0 +1,35 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class LookTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+ Look lk = new Look().Create();
+ lk.setName("coollook");
+ assertEquals("coollook", lk.getName());
+ lk.setProcessSpace("somespace");
+ assertEquals("somespace", lk.getProcessSpace());
+ ExponentTransform et = new ExponentTransform().Create();
+ et.setValue(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
+ lk.setTransform(et);
+ ExponentTransform oet = (ExponentTransform)lk.getTransform();
+ float vals[] = new float[4];
+ oet.getValue(vals);
+ assertEquals(0.2f, vals[1], 1e-8);
+ ExponentTransform iet = new ExponentTransform().Create();
+ iet.setValue(new float[]{-0.1f, -0.2f, -0.3f, -0.4f});
+ lk.setInverseTransform(iet);
+ ExponentTransform ioet = (ExponentTransform)lk.getInverseTransform();
+ float vals2[] = new float[4];
+ ioet.getValue(vals2);
+ assertEquals(-0.2f, vals2[1], 1e-8);
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/OpenColorIOTestSuite.java b/src/jniglue/tests/org/OpenColorIO/OpenColorIOTestSuite.java
new file mode 100644
index 0000000..b847d96
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/OpenColorIOTestSuite.java
@@ -0,0 +1,30 @@
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class OpenColorIOTestSuite {
+
+ public static Test suite() {
+
+ TestSuite suite = new TestSuite();
+
+ // Core
+ suite.addTestSuite(GlobalsTest.class);
+ suite.addTestSuite(ConfigTest.class);
+ suite.addTestSuite(ColorSpaceTest.class);
+ suite.addTestSuite(LookTest.class);
+ suite.addTestSuite(BakerTest.class);
+ suite.addTestSuite(PackedImageDescTest.class);
+ suite.addTestSuite(PlanarImageDescTest.class);
+ suite.addTestSuite(GpuShaderDescTest.class);
+ suite.addTestSuite(ContextTest.class);
+ suite.addTestSuite(TransformsTest.class);
+
+ return suite;
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/PackedImageDescTest.java b/src/jniglue/tests/org/OpenColorIO/PackedImageDescTest.java
new file mode 100644
index 0000000..741a13d
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/PackedImageDescTest.java
@@ -0,0 +1,39 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+import java.nio.*;
+
+public class PackedImageDescTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+
+ int width = 2;
+ int height = 2;
+ int channels = 4;
+ float packedpix[] = new float[]{0.1f, 0.1f, 0.1f, 1.0f,
+ 0.2f, 0.2f, 0.2f, 1.0f,
+ 0.3f, 0.3f, 0.3f, 1.0f,
+ 0.4f, 0.4f, 0.4f, 1.0f };
+ FloatBuffer buf = ByteBuffer.allocateDirect(width * height * channels
+ * Float.SIZE / 8).asFloatBuffer();
+ buf.put(packedpix);
+ //
+ PackedImageDesc foo = new PackedImageDesc(buf, width, height, channels);
+ FloatBuffer wee = foo.getData();
+ assertEquals(0.3f, wee.get(10));
+ assertEquals(2, foo.getWidth());
+ assertEquals(2, foo.getHeight());
+ assertEquals(4, foo.getNumChannels());
+ assertEquals(4, foo.getChanStrideBytes());
+ assertEquals(16, foo.getXStrideBytes());
+ assertEquals(32, foo.getYStrideBytes());
+
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/PlanarImageDescTest.java b/src/jniglue/tests/org/OpenColorIO/PlanarImageDescTest.java
new file mode 100644
index 0000000..e0d4deb
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/PlanarImageDescTest.java
@@ -0,0 +1,51 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+import java.nio.*;
+
+public class PlanarImageDescTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+
+ int width = 2;
+ int height = 2;
+ int channels = 4;
+ //
+ float rpix[] = new float[]{0.1f, 0.2f, 0.3f, 0.4f};
+ float gpix[] = new float[]{0.1f, 0.2f, 0.3f, 0.4f};
+ float bpix[] = new float[]{0.1f, 0.2f, 0.3f, 0.4f};
+ float apix[] = new float[]{1.0f, 1.0f, 1.0f, 1.0f};
+ int alloc = width * height * Float.SIZE / 8;
+ //
+ FloatBuffer rbuf = ByteBuffer.allocateDirect(alloc).asFloatBuffer();
+ rbuf.put(rpix);
+ FloatBuffer gbuf = ByteBuffer.allocateDirect(alloc).asFloatBuffer();
+ gbuf.put(gpix);
+ FloatBuffer bbuf = ByteBuffer.allocateDirect(alloc).asFloatBuffer();
+ bbuf.put(bpix);
+ FloatBuffer abuf = ByteBuffer.allocateDirect(alloc).asFloatBuffer();
+ abuf.put(apix);
+ //
+ PlanarImageDesc foo = new PlanarImageDesc(rbuf, gbuf, bbuf, abuf,
+ width, height);
+ FloatBuffer trb = foo.getRData();
+ FloatBuffer tgb = foo.getGData();
+ FloatBuffer tbb = foo.getBData();
+ FloatBuffer tab = foo.getAData();
+ assertEquals(0.1f, trb.get(0));
+ assertEquals(0.2f, tgb.get(1));
+ assertEquals(0.3f, tbb.get(2));
+ assertEquals(1.0f, tab.get(3));
+ assertEquals(2, foo.getWidth());
+ assertEquals(2, foo.getHeight());
+ assertEquals(8, foo.getYStrideBytes());
+
+ }
+
+}
diff --git a/src/jniglue/tests/org/OpenColorIO/TransformsTest.java b/src/jniglue/tests/org/OpenColorIO/TransformsTest.java
new file mode 100644
index 0000000..6300079
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/TransformsTest.java
@@ -0,0 +1,237 @@
+
+import junit.framework.TestCase;
+import org.OpenColorIO.*;
+
+public class TransformsTest extends TestCase {
+
+ protected void setUp() {
+ }
+
+ protected void tearDown() {
+ }
+
+ public void test_interface() {
+
+ //// AllocationTransform ////
+ AllocationTransform at = new AllocationTransform().Create();
+ assertEquals(Allocation.ALLOCATION_UNIFORM, at.getAllocation());
+ at.setAllocation(Allocation.ALLOCATION_LG2);
+ assertEquals(Allocation.ALLOCATION_LG2, at.getAllocation());
+ assertEquals(0, at.getNumVars());
+ float[] vars = new float[]{0.1f, 0.2f, 0.3f};
+ at.setVars(3, vars);
+ assertEquals(3, at.getNumVars());
+ float newvars[] = new float[3];
+ at.getVars(newvars);
+ assertEquals(0.2f, newvars[1], 1e-8);
+
+ // Base Transform method tests
+ assertEquals(TransformDirection.TRANSFORM_DIR_FORWARD, at.getDirection());
+ at.setDirection(TransformDirection.TRANSFORM_DIR_UNKNOWN);
+ assertEquals(TransformDirection.TRANSFORM_DIR_UNKNOWN, at.getDirection());
+
+ //// CDLTransform ////
+ CDLTransform cdl = new CDLTransform().Create();
+ String CC = ""
+ +"<ColorCorrection id=\"foo\">"
+ +"<SOPNode>"
+ +"<Description>this is a descipt</Description>"
+ +"<Slope>1.1 1.2 1.3</Slope>"
+ +"<Offset>2.1 2.2 2.3</Offset>"
+ +"<Power>3.1 3.2 3.3</Power>"
+ +"</SOPNode>"
+ +"<SatNode><Saturation>0.7</Saturation></SatNode>"
+ +"</ColorCorrection>";
+ // Don't want to deal with getting the correct path so this runs
+ //CDLTransform cdlfile = new CDLTransform().CreateFromFile("../OpenColorIO/src/jniglue/tests/org/OpenColorIO/test.cc", "foo");
+ //assertEquals(CC, cdlfile.getXML());
+ cdl.setXML(CC);
+ assertEquals(CC, cdl.getXML());
+ //CDLTransform match = new CDLTransform().Create();
+ CDLTransform match = (CDLTransform)cdl.createEditableCopy();
+ match.setOffset(new float[]{1.0f, 1.0f, 1.f});
+ assertEquals(false, cdl.equals(match));
+ cdl.setSlope(new float[]{0.1f, 0.2f, 0.3f});
+ cdl.setOffset(new float[]{1.1f, 1.2f, 1.3f});
+ cdl.setPower(new float[]{2.1f, 2.2f, 2.3f});
+ cdl.setSat(0.5f);
+ String CC2 = ""
+ +"<ColorCorrection id=\"foo\">"
+ +"<SOPNode>"
+ +"<Description>this is a descipt</Description>"
+ +"<Slope>0.1 0.2 0.3</Slope>"
+ +"<Offset>1.1 1.2 1.3</Offset>"
+ +"<Power>2.1 2.2 2.3</Power>"
+ +"</SOPNode>"
+ +"<SatNode><Saturation>0.5</Saturation></SatNode>"
+ +"</ColorCorrection>";
+ assertEquals(CC2, cdl.getXML());
+ cdl.setSOP(new float[]{1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f});
+ float newsop[] = new float[9];
+ cdl.getSOP(newsop);
+ assertEquals(1.5f, newsop[4], 1e-8);
+ float slope[] = new float[3];
+ cdl.getSlope(slope);
+ assertEquals(1.2f, slope[1], 1e-8);
+ float offset[] = new float[3];
+ cdl.getOffset(offset);
+ assertEquals(1.6f, offset[2], 1e-8);
+ float power[] = new float[3];
+ cdl.getPower(power);
+ assertEquals(1.7f, power[0], 1e-8);
+ assertEquals(0.5f, cdl.getSat(), 1e-8);
+ float luma[] = new float[3];
+ cdl.getSatLumaCoefs(luma);
+ assertEquals(0.2126f, luma[0], 1e-8);
+ assertEquals(0.7152f, luma[1], 1e-8);
+ assertEquals(0.0722f, luma[2], 1e-8);
+ cdl.setID("foobar123");
+ assertEquals("foobar123", cdl.getID());
+ cdl.setDescription("bar");
+ assertEquals("bar", cdl.getDescription());
+
+ //// ColorSpaceTransform ////
+ ColorSpaceTransform ct = new ColorSpaceTransform().Create();
+ ct.setSrc("foo");
+ assertEquals("foo", ct.getSrc());
+ ct.setDst("bar");
+ assertEquals("bar", ct.getDst());
+
+ //// DisplayTransform ////
+ DisplayTransform dt = new DisplayTransform().Create();
+ dt.setInputColorSpaceName("lin18");
+ assertEquals("lin18", dt.getInputColorSpaceName());
+ //public native void setLinearCC(Transform cc);
+ //public native Transform getLinearCC();
+ //public native void setColorTimingCC(Transform cc);
+ //public native Transform getColorTimingCC();
+ //public native void setChannelView(Transform transform);
+ //public native Transform getChannelView();
+ dt.setDisplay("sRGB");
+ assertEquals("sRGB", dt.getDisplay());
+ dt.setView("foobar");
+ assertEquals("foobar", dt.getView());
+ cdl.setXML(CC);
+ dt.setDisplayCC(cdl);
+ CDLTransform cdldt = (CDLTransform)dt.getDisplayCC();
+ assertEquals(CC, cdldt.getXML());
+ dt.setLooksOverride("darkgrade");
+ assertEquals("darkgrade", dt.getLooksOverride());
+ dt.setLooksOverrideEnabled(true);
+ assertEquals(true, dt.getLooksOverrideEnabled());
+
+ //// ExponentTransform ////
+ ExponentTransform et = new ExponentTransform().Create();
+ et.setValue(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
+ float evals[] = new float[4];
+ et.getValue(evals);
+ assertEquals(0.3f, evals[2], 1e-8);
+
+ //// FileTransform ////
+ FileTransform ft = new FileTransform().Create();
+ ft.setSrc("foo");
+ assertEquals("foo", ft.getSrc());
+ ft.setCCCId("foobar");
+ assertEquals("foobar", ft.getCCCId());
+ ft.setInterpolation(Interpolation.INTERP_NEAREST);
+ assertEquals(Interpolation.INTERP_NEAREST, ft.getInterpolation());
+ assertEquals(15, ft.getNumFormats());
+ assertEquals("flame", ft.getFormatNameByIndex(0));
+ assertEquals("3dl", ft.getFormatExtensionByIndex(0));
+
+ //// GroupTransform ////
+ GroupTransform gt = new GroupTransform().Create();
+ gt.push_back(et);
+ gt.push_back(ft);
+ assertEquals(2, gt.size());
+ assertEquals(false, gt.empty());
+ Transform foo = gt.getTransform(0);
+ assertEquals(TransformDirection.TRANSFORM_DIR_FORWARD, foo.getDirection());
+ gt.clear();
+ assertEquals(0, gt.size());
+
+ //// LogTransform ////
+ LogTransform lt = new LogTransform().Create();
+ lt.setBase(10.f);
+ assertEquals(10.f, lt.getBase());
+
+ //// LookTransform ////
+ LookTransform lkt = new LookTransform().Create();
+ lkt.setSrc("foo");
+ assertEquals("foo", lkt.getSrc());
+ lkt.setDst("bar");
+ assertEquals("bar", lkt.getDst());
+ lkt.setLooks("bar;foo");
+ assertEquals("bar;foo", lkt.getLooks());
+
+ //// MatrixTransform ////
+ MatrixTransform mt = new MatrixTransform().Create();
+ MatrixTransform mmt = (MatrixTransform)mt.createEditableCopy();
+ mt.setValue(new float[]{0.1f, 0.2f, 0.3f, 0.4f,
+ 0.5f, 0.6f, 0.7f, 0.8f,
+ 0.9f, 1.0f, 1.1f, 1.2f,
+ 1.3f, 1.4f, 1.5f, 1.6f},
+ new float[]{0.1f, 0.2f, 0.3f, 0.4f});
+ assertEquals(false, mt.equals(mmt));
+ float m44_1[] = new float[16];
+ float offset_1[] = new float[4];
+ mt.getValue(m44_1, offset_1);
+ assertEquals(0.3f, m44_1[2]);
+ assertEquals(0.2f, offset_1[1]);
+ mt.setMatrix(new float[]{1.1f, 1.2f, 1.3f, 1.4f,
+ 1.5f, 1.6f, 1.7f, 1.8f,
+ 1.9f, 2.0f, 2.1f, 2.2f,
+ 2.3f, 2.4f, 2.5f, 2.6f});
+ float m44_2[] = new float[16];
+ mt.getMatrix(m44_2);
+ assertEquals(1.3f, m44_2[2]);
+ mt.setOffset(new float[]{1.1f, 1.2f, 1.3f, 1.4f});
+ float offset_2[] = new float[4];
+ mt.getOffset(offset_2);
+ assertEquals(1.4f, offset_2[3]);
+ mt.Fit(m44_2, offset_2,
+ new float[]{0.1f, 0.1f, 0.1f, 0.1f},
+ new float[]{0.9f, 0.9f, 0.9f, 0.9f},
+ new float[]{0.0f, 0.0f, 0.0f, 0.0f},
+ new float[]{1.1f, 1.1f, 1.1f, 1.1f});
+ float m44_3[] = new float[16];
+ mt.getMatrix(m44_3);
+ assertEquals(1.3f, m44_3[2]);
+ mt.Identity(m44_3, offset_2);
+ assertEquals(0.f, m44_3[1]);
+ mt.Sat(m44_2, offset_2, 0.5f, new float[]{0.2126f, 0.7152f, 0.0722f});
+ assertEquals(0.3576f, m44_2[1]);
+ mt.Scale(m44_2, offset_2, new float[]{0.9f, 0.8f, 0.7f, 1.f});
+ assertEquals(0.9f, m44_2[0]);
+ mt.View(m44_2, null, new int[]{1, 1, 1, 0}, new float[]{0.2126f, 0.7152f, 0.0722f});
+ assertEquals(0.0722f, m44_2[2]);
+
+ //// TruelightTransform ////
+ TruelightTransform tt = new TruelightTransform().Create();
+ tt.setConfigRoot("/some/path");
+ assertEquals("/some/path", tt.getConfigRoot());
+ tt.setProfile("profileA");
+ assertEquals("profileA", tt.getProfile());
+ tt.setCamera("incam");
+ assertEquals("incam", tt.getCamera());
+ tt.setInputDisplay("dellmon");
+ assertEquals("dellmon", tt.getInputDisplay());
+ tt.setRecorder("blah");
+ assertEquals("blah", tt.getRecorder());
+ tt.setPrint("kodasomething");
+ assertEquals("kodasomething", tt.getPrint());
+ tt.setLamp("foobar");
+ assertEquals("foobar", tt.getLamp());
+ tt.setOutputCamera("somecam");
+ assertEquals("somecam", tt.getOutputCamera());
+ tt.setDisplay("sRGB");
+ assertEquals("sRGB", tt.getDisplay());
+ tt.setCubeInput("log");
+ assertEquals("log", tt.getCubeInput());
+
+ try {
+ } catch (Exception e) { System.out.println(e); }
+
+ }
+
+} \ No newline at end of file
diff --git a/src/jniglue/tests/org/OpenColorIO/test.cc b/src/jniglue/tests/org/OpenColorIO/test.cc
new file mode 100644
index 0000000..121bf42
--- /dev/null
+++ b/src/jniglue/tests/org/OpenColorIO/test.cc
@@ -0,0 +1,11 @@
+<ColorCorrection id="foo">
+ <SOPNode>
+ <Description>this is a descipt</Description>
+ <Slope>1.1 1.2 1.3</Slope>
+ <Offset>2.1 2.2 2.3</Offset>
+ <Power>3.1 3.2 3.3</Power>
+ </SOPNode>
+ <SatNode>
+ <Saturation>0.7</Saturation>
+ </SatNode>
+</ColorCorrection> \ No newline at end of file
diff --git a/src/mari/1.4v1/README b/src/mari/1.4v1/README
new file mode 100644
index 0000000..ecfdf18
--- /dev/null
+++ b/src/mari/1.4v1/README
@@ -0,0 +1,10 @@
+These files ship with Mari, and are *not* required to be manually installed.
+
+They are provided as a reference example of using the OCIO API to create a GPU
+monitor implementation in python.
+
+Media/Scripts/mari/utils/ocio.py
+Media/Scripts/mari/system/_ocio_toolbar.py
+Media/Scripts/mari/system/_ocio_filter.py
+
+All code in these examples is Copyright (c) 2011 The Foundry Visionmongers Ltd.
diff --git a/src/mari/1.4v1/_ocio_filter.py b/src/mari/1.4v1/_ocio_filter.py
new file mode 100755
index 0000000..e3c3bf3
--- /dev/null
+++ b/src/mari/1.4v1/_ocio_filter.py
@@ -0,0 +1,127 @@
+#-------------------------------------------------------------------------------
+# Post processing (color management) related Mari scripts
+# coding: utf-8
+# Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved.
+#-------------------------------------------------------------------------------
+
+import mari, time, PythonQt, os, math
+ocio = mari.utils.ocio
+
+##############################################################################################
+
+filter = None
+
+class OcioFilter():
+
+ #-----------------------------------------------------------------------------------------
+
+ def __init__(self):
+ # Default all members...
+ self._config_file_list = mari.FileList(ocio.config_file_list_default)
+ self._config = ocio.config_default
+ self._input_color_space = ocio.color_space_default
+ self._output_color_space = ocio.color_space_default
+ self._filter = mari.gl_render.createQuickApplyGLSL('Color Correction', '', '', 'ColorManager.png')
+ self._filter_cache_id = None
+ self._texture_cache_id = None
+ self._sampler_name = None
+
+ self._filter.setMetadata('ConfigPath', self._config_file_list)
+ self._filter.setMetadataDisplayName('ConfigPath', 'Configuration File')
+ self._filter.setMetadataDefault('ConfigPath', ocio.CONFIG_FILE_LIST_RESET)
+ self._filter.setMetadataFlags('ConfigPath', self._filter.METADATA_VISIBLE | self._filter.METADATA_EDITABLE)
+
+ color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()]
+
+ color_space_reset = ocio.COLOR_SPACE_RESET
+ if color_spaces.count(color_space_reset) == 0:
+ color_space_reset = color_spaces[0]
+
+ self._filter.setMetadata('InputColorSpace', self._input_color_space)
+ self._filter.setMetadataDisplayName('InputColorSpace', 'Input Color Space')
+ self._filter.setMetadataDefault('InputColorSpace', color_space_reset)
+ self._filter.setMetadataItemList('InputColorSpace', color_spaces)
+ self._filter.setMetadataFlags('InputColorSpace', self._filter.METADATA_VISIBLE | self._filter.METADATA_EDITABLE)
+
+ self._filter.setMetadata('OutputColorSpace', self._output_color_space)
+ self._filter.setMetadataDisplayName('OutputColorSpace', 'Output Color Space')
+ self._filter.setMetadataDefault('OutputColorSpace', color_space_reset)
+ self._filter.setMetadataItemList('OutputColorSpace', color_spaces)
+ self._filter.setMetadataFlags('OutputColorSpace', self._filter.METADATA_VISIBLE | self._filter.METADATA_EDITABLE)
+
+ mari.utils.connect(self._filter.metadataValueChanged, self._metadataValueChanged)
+
+ self._rebuildFilter()
+
+ #-----------------------------------------------------------------------------------------
+
+ def _metadataValueChanged(self, name, value):
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Metadata \'%s\' changed to \'%s\'' % (name, value))
+
+ if name == 'ConfigPath':
+ if value == self._config_file_list:
+ return
+ self._config_file_list = mari.FileList(value)
+ self._config = ocio.loadConfig(self._config_file_list.at(0), False)
+
+ color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()]
+
+ color_space_reset = ocio.COLOR_SPACE_RESET
+ if color_spaces.count(color_space_reset) == 0:
+ color_space_reset = color_spaces[0]
+
+ if color_spaces.count(self._input_color_space) == 0:
+ self._input_color_space = color_space_reset
+
+ if color_spaces.count(self._output_color_space) == 0:
+ self._output_color_space = color_space_reset
+
+ self._filter.setMetadataItemList('InputColorSpace', color_spaces)
+ self._filter.setMetadataItemList('OutputColorSpace', color_spaces)
+ self._filter.setMetadataDefault('InputColorSpace', color_space_reset)
+ self._filter.setMetadataDefault('OutputColorSpace', color_space_reset)
+ self._filter.setMetadata('InputColorSpace', self._input_color_space )
+ self._filter.setMetadata('OutputColorSpace', self._output_color_space)
+
+ elif name == 'InputColorSpace':
+ if value == self._input_color_space:
+ return
+ self._input_color_space = value
+
+ elif name == 'OutputColorSpace':
+ if value == self._output_color_space:
+ return
+ self._output_color_space = value
+
+ else:
+ return
+
+ self._rebuildFilter()
+
+ #-----------------------------------------------------------------------------------------
+
+ def _rebuildFilter(self):
+ input_color_space = self._config.getColorSpace(self._input_color_space)
+ if input_color_space is not None:
+ output_color_space = self._config.getColorSpace(self._output_color_space)
+ if output_color_space is not None:
+ processor = self._config.getProcessor(input_color_space, output_color_space)
+
+ self._filter_cache_id, self._texture_cache_id, self._sampler_name = ocio.buildProcessorFilter(
+ processor,
+ self._filter,
+ self._filter_cache_id,
+ self._texture_cache_id)
+
+ current_canvas = mari.canvases.current()
+ if current_canvas is not None:
+ current_canvas.repaint()
+
+##############################################################################################
+
+if mari.app.isRunning():
+ if not hasattr(mari.gl_render, 'createQuickApplyGLSL'):
+ printMessage(MessageType.ERROR, 'This version of Mari does not support the mari.gl_render.createQuickApplyGLSL API')
+
+ elif ocio is not None:
+ filter = OcioFilter()
diff --git a/src/mari/1.4v1/_ocio_toolbar.py b/src/mari/1.4v1/_ocio_toolbar.py
new file mode 100755
index 0000000..84afb68
--- /dev/null
+++ b/src/mari/1.4v1/_ocio_toolbar.py
@@ -0,0 +1,1279 @@
+#-------------------------------------------------------------------------------
+# Post processing (color management) related Mari scripts
+# coding: utf-8
+# Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved.
+#-------------------------------------------------------------------------------
+
+import mari, time, PythonQt, os, math
+QtGui = PythonQt.QtGui
+QtCore = PythonQt.QtCore
+ocio = mari.utils.ocio
+
+##############################################################################################
+
+GAIN_GROUP_MAX_WIDTH = 312
+FSTOP_MAX_WIDTH = 50
+EXPOSURE_MAX_WIDTH = 102
+GAIN_MAX_WIDTH = 80
+GAMMA_MAX_WIDTH = 200
+TOOLBAR_SPACING = 3
+
+toolbar = None
+
+class OcioToolBar():
+
+ #-----------------------------------------------------------------------------------------
+
+ def __init__(self):
+ # Default all members...
+ self._config_file_list = mari.FileList(ocio.config_file_list_default)
+ self._config = ocio.config_default
+ self._lut_file_list = mari.FileList(ocio.lut_file_list_default)
+ self._lut_extrapolate = ocio.lut_extrapolate_default
+ self._color_space = ocio.color_space_default
+ self._display = ocio.display_default
+ self._view = ocio.view_default
+ self._swizzle = ocio.swizzle_default
+ self._gain = ocio.gain_default
+ self._gamma = ocio.gamma_default
+
+ self._lut_filter = None
+ self._lut_filter_cache_id = None
+ self._lut_texture_cache_id = None
+ self._lut_sampler_name = None
+
+ self._display_filter = None
+ self._display_filter_cache_id = None
+ self._display_texture_cache_id = None
+ self._display_sampler_name = None
+
+ self._lut_extrapolate_widget = None
+ self._color_space_widget = None
+ self._display_widget = None
+ self._view_widget = None
+ self._swizzle_widget = None
+ self._fstop_widget = None
+ self._fstop_decrement_widget = None
+ self._fstop_increment_widget = None
+ self._gain_widget = None
+ self._exposure_widget = None
+ self._gain_reset_widget = None
+ self._gamma_widget = None
+ self._gamma_reset_widget = None
+
+ self._buildWidgets()
+ self._toggle_color_management_action.setEnabled(False)
+ self._enableWidgets(False)
+
+ # Enable/disable color management.
+ mari.gl_render.setPostProcessingEnabled(self.isColorManagementEnabled())
+
+ # *** IMPORTANT *** The post filter collection used to be called 'OpenColorIO' but was renamed to hide the fact
+ # we use OpenColorIO from our users. So as a temporary workaround we need to check for the old filter collection
+ # on startup and remove it if found.
+ delete_filter_collection = mari.gl_render.findPostFilterCollection('OpenColorIO')
+ if delete_filter_collection is not None:
+ mari.gl_render.deletePostFilterCollection(delete_filter_collection)
+
+ # Create the OCIO post filter collection if not present.
+ self._filter_collection = mari.gl_render.findPostFilterCollection('Color Space')
+ if self._filter_collection is None:
+ self._filter_collection = mari.gl_render.createPostFilterCollection('Color Space')
+ else:
+ self._filter_collection.clear()
+ self._filter_collection.setReadOnly(True)
+
+ self._lut_filter = self._filter_collection.createGLSL('LUT Transform')
+ if not self._lut_file_list.isEmpty() and not self._rebuildLUTFilter(self._lut_file_list.at(0)):
+ self._lut_file_list.clear()
+
+ self._display_filter = self._filter_collection.createGLSL('Display Transform')
+ self._rebuildDisplayFilter()
+
+ self._buildMetadata()
+
+ # Set the color management filter stack as the current.
+ mari.gl_render.setPostFilterCollection(self._filter_collection)
+
+ # Attach ourselves to the applications toolbar created signal so we can rebuild the toolbar when it's been
+ # destoyed.
+ mari.utils.connect(mari.app.toolBarsCreated, self._toolBarsCreated)
+
+ # Attach ourselves to the appropriate GL signals so we can enable and disable widgets.
+ mari.utils.connect(mari.gl_render.postProcessingEnabled, self._postProcessingEnabled)
+ mari.utils.connect(mari.gl_render.setCurrentPostFilterCollection, self._setCurrentPostFilterCollection)
+
+ # Attach ourselves to the appropriate project signals so we can load and save settings.
+ mari.utils.connect(mari.projects.openedProject, self._openedProject)
+ mari.utils.connect(mari.projects.aboutToSaveProject, self._aboutToSaveProject)
+ mari.utils.connect(mari.projects.projectClosed, self._closedProject)
+
+ # Update the UI to match the current project, if we have one.
+ current_project = mari.projects.current()
+ if current_project is not None:
+ self._openedProject(current_project)
+
+ #-----------------------------------------------------------------------------------------
+
+ def isColorManagementEnabled(self):
+ return self._toggle_color_management_action.isChecked()
+
+ #-----------------------------------------------------------------------------------------
+
+ def setLUTPath(self, value, update_metadata = True, force_shader_build = False):
+ if (self._lut_file_list.isEmpty() and value != '') or \
+ (not self._lut_file_list.isEmpty() and value == '') or \
+ (not self._lut_file_list.isEmpty() and value != self._lut_file_list.at(0)) \
+ :
+ if self._rebuildLUTFilter(value, force_shader_build):
+ self._lut_file_list.clear()
+ if value != '':
+ self._lut_file_list.append(value)
+ self._lut_file_list.setPickedFile(value)
+
+ self._clear_lut_action.setEnabled(True)
+ self._lut_extrapolate_widget.setEnabled(True)
+ self._lut_filter.setEnabled(True)
+ else:
+ self._clear_lut_action.setEnabled(False)
+ self._lut_extrapolate_widget.setEnabled(False)
+ self._lut_filter.setEnabled(False)
+
+ if update_metadata:
+ mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+ self._lut_filter.setMetadata('File', self._lut_file_list)
+ mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+
+ else:
+ # If this was a request via the metadata system we will need to put the value back to what it was
+ # before.
+ if not update_metadata:
+ mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+ self._lut_filter.setMetadata('File', self._lut_file_list)
+ mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+
+ return False
+
+ return True
+
+ #-----------------------------------------------------------------------------------------
+
+ def resetLUT(self):
+ if ocio.lut_file_list_default.isEmpty() or not self.setLUTPath(ocio.lut_file_list_default.at(0)):
+ self.setLUTPath('')
+
+ #-----------------------------------------------------------------------------------------
+
+ def selectLUT(self):
+ lut_path = mari.utils.misc.getOpenFileName(None,
+ 'Select LUT File',
+ '' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0),
+ ocio.lutFileFilter(),
+ None,
+ 0)
+ if os.path.isfile(lut_path):
+ self.setLUTPath(lut_path)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setExtrapolateEnabled(self, value, update_widget = True, update_metadata = True):
+ if value != self._lut_extrapolate:
+ self._lut_extrapolate = value
+
+ if update_widget:
+ block = self._lut_extrapolate_widget.blockSignals(True)
+ self._lut_extrapolate_widget.setChecked(self._lut_extrapolate)
+ self._lut_extrapolate_widget.blockSignals(block)
+
+ if update_metadata:
+ mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+ self._lut_filter.setMetadata('Extrapolate', self._lut_extrapolate)
+ mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+
+ if not self._rebuildLUTFilter(lut_path = '' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0),
+ force_shader_build = True):
+ self.resetLUT()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed extrapolate to \'%s\'' % self._lut_extrapolate)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setConfigPath(self, value, update_metadata = True):
+ if self._config_file_list.isEmpty() or value != self._config_file_list.at(0):
+ config = ocio.loadConfig(value, True)
+ if config is not None:
+ self._config_file_list.clear()
+ self._config_file_list.append(value)
+ self._config_file_list.setPickedFile(value)
+
+ self._config = config
+
+ self._updateDisplayWidgets()
+ self._updateDisplayMetadata()
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed config to \'%s\'' % self._config_file_list.at(0))
+
+ else:
+ # If this was a request via the metadata system we will need to put the value back to what it was
+ # before.
+ if not update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('ConfigPath', self._config_file_list)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ return False
+
+ return True
+
+ #-----------------------------------------------------------------------------------------
+
+ def selectConfig(self):
+ config_path = mari.utils.misc.getOpenFileName(None,
+ 'Select Configuration File',
+ '' if self._config_file_list.isEmpty() else self._config_file_list.at(0),
+ ocio.configFileFilter(),
+ None,
+ 0)
+ if os.path.isfile(config_path):
+ self.setConfigPath(config_path)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setColorSpace(self, value, update_widget = True, update_metadata = True):
+ if value != self._color_space:
+ self._color_space = value
+
+ if update_widget:
+ block = self._color_space_widget.blockSignals(True)
+ index = self._color_space_widget.findText(self._color_space)
+ self._color_space_widget.setCurrentIndex(index)
+ self._color_space_widget.blockSignals(block)
+
+ if update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('InputColorSpace', self._color_space)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed input color space to \'%s\'' % self._color_space)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setDisplay(self, value, update_widget = True, update_metadata = True):
+ if value != self._display:
+ self._display = value
+
+ if update_widget:
+ block = self._display_widget.blockSignals(True)
+ index = self._display_widget.findText(self._display)
+ self._display_widget.setCurrentIndex(index)
+ self._display_widget.blockSignals(block)
+
+ if update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('Display', self._display)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self.setView(self._config.getDefaultView(self._display), update_widget, update_metadata)
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed display to \'%s\'' % self._display)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setView(self, value, update_widget = True, update_metadata = True):
+ if value != self._view:
+ self._view = value
+
+ if update_widget:
+ block = self._view_widget.blockSignals(True)
+ index = self._view_widget.findText(self._view)
+ self._view_widget.setCurrentIndex(index)
+ self._view_widget.blockSignals(block)
+
+ if update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('View', self._view)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed view to \'%s\'' % self._view)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setSwizzle(self, value, update_widget = True, update_metadata = True):
+ if value != self._swizzle:
+ self._swizzle = value
+
+ if update_widget:
+ block = self._swizzle_widget.blockSignals(True)
+ index = self._swizzle_widget.findText(self._swizzle)
+ self._swizzle_widget.setCurrentIndex(index)
+ self._swizzle_widget.blockSignals(block)
+
+ if update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('Swizzle', self._swizzle)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed swizzle to \'%s\'' % self._swizzle)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setGain(self, value, update_widget = True, update_metadata = True):
+ if value != self._gain:
+ self._gain = value
+
+ if update_widget:
+ self._updateGainWidgets()
+
+ if update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('Gain', self._gain)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed gain to \'%s\'' % self._gain)
+
+ #-----------------------------------------------------------------------------------------
+
+ def setGamma(self, value, update_widget = True, update_metadata = True):
+ if value != self._gamma:
+ self._gamma = value
+
+ if update_widget:
+ block = self._gamma_widget.blockSignals(True)
+ self._gamma_widget.setValue(self._gamma)
+ self._gamma_widget.blockSignals(block)
+
+ if update_metadata:
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._display_filter.setMetadata('Gamma', self._gamma)
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self._rebuildDisplayFilter()
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed gamma to \'%s\'' % self._gamma)
+
+ #-----------------------------------------------------------------------------------------
+
+ def updateLUTSize(self):
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Updating LUT size...')
+
+ # Rebuild the LUT filter.
+ if self._lut_sampler_name is not None:
+ self._lut_filter.deleteTexture(self._lut_sampler_name)
+ self._lut_sampler_name = None
+
+ self._lut_filter_cache_id = None
+ self._lut_texture_cache_id = None
+
+ if not self._rebuildLUTFilter(lut_path = '' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0),
+ force_shader_build = True):
+ self.resetLUT()
+
+ # Rebuild the display filter.
+ if self._display_sampler_name is not None:
+ self._display_filter.deleteTexture(self._display_sampler_name)
+ self._display_sampler_name = None
+
+ self._display_filter_cache_id = None
+ self._display_texture_cache_id = None
+
+ self._rebuildDisplayFilter()
+
+ #-----------------------------------------------------------------------------------------
+
+ def updateFStopCenter(self):
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Updating f-stop center...')
+
+ fstop = ocio.convertGainToFStop(self._gain)
+ self._updateFStopWidgetText(fstop)
+
+ #-----------------------------------------------------------------------------------------
+ # Widgets:
+ #-----------------------------------------------------------------------------------------
+
+ def _buildWidgets(self):
+ action_list = list()
+
+ self._toggle_color_management_action = self._addAction(
+ '/Mari/OpenColorIO/&Toggle Color Management',
+ 'mari.system._ocio_toolbar.toolbar._toggleColorManagement()',
+ 'ColorManager.png',
+ 'Toggle on/off color management',
+ 'Toggle color management')
+ self._toggle_color_management_action.setCheckable(True)
+ self._toggle_color_management_action.setChecked(ocio.enabled_default)
+ action_list.append('/Mari/OpenColorIO/&Toggle Color Management')
+
+ self._select_config_action = self._addAction(
+ '/Mari/OpenColorIO/&Select Config',
+ 'mari.system._ocio_toolbar.toolbar.selectConfig()',
+ 'LoadColorConfig.png',
+ 'Select color space configuration file',
+ 'Select config')
+ action_list.append('/Mari/OpenColorIO/&Select Config')
+
+ self._select_lut_action = self._addAction(
+ '/Mari/OpenColorIO/&Select LUT',
+ 'mari.system._ocio_toolbar.toolbar.selectLUT()',
+ 'LoadLookupTable.png',
+ 'Select LUT file',
+ 'Select LUT')
+ action_list.append('/Mari/OpenColorIO/&Select LUT')
+
+ self._clear_lut_action = self._addAction(
+ '/Mari/OpenColorIO/&Clear LUT',
+ 'mari.system._ocio_toolbar.toolbar._clearLUT()',
+ 'ClearLookupTable.png',
+ 'Clear current LUT',
+ 'Clear LUT')
+ action_list.append('/Mari/OpenColorIO/&Clear LUT')
+
+ mari.app.deleteToolBar('Color Space')
+ self._toolbar = mari.app.createToolBar('Color Space', True)
+ self._toolbar.addActionList(action_list, False)
+ self._toolbar.setLockedSlot(True)
+ self._toolbar.setSpacing(TOOLBAR_SPACING)
+
+ self._toolbar.insertSeparator('/Mari/OpenColorIO/&Select LUT')
+
+ # Extrapolate:
+ self._toolbar.addWidget(QtGui.QLabel('Extrapolate'))
+ self._lut_extrapolate_widget = QtGui.QCheckBox()
+ self._lut_extrapolate_widget.setToolTip('Extrapolate if outside LUT range');
+ self._lut_extrapolate_widget.setChecked(self._lut_extrapolate)
+ self._lut_extrapolate_widget.connect(
+ QtCore.SIGNAL('toggled(bool)'),
+ lambda value: self.setExtrapolateEnabled(value = value, update_widget = False, update_metadata = True))
+ self._toolbar.addWidget(self._lut_extrapolate_widget)
+
+ self._toolbar.addSeparator()
+
+ color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()]
+
+ # Color-Space:
+ self._color_space_widget = self._addComboBox(
+ 'Input Color Space',
+ color_spaces,
+ self._color_space,
+ ocio.color_space_default,
+ lambda value: self.setColorSpace(value = value, update_widget = False, update_metadata = True))
+ self._color_space = self._color_space_widget.currentText
+
+ # Display:
+ self._display_widget = self._addComboBox(
+ 'Display Device',
+ self._config.getDisplays(),
+ self._display,
+ ocio.display_default,
+ lambda value: self.setDisplay(value = value, update_widget = False, update_metadata = True))
+ self._display = self._display_widget.currentText
+
+ # View:
+ self._view_widget = self._addComboBox(
+ 'View Transform',
+ self._config.getViews(self._display),
+ self._view,
+ ocio.view_default,
+ lambda value: self.setView(value = value, update_widget = False, update_metadata = True))
+ self._view = self._view_widget.currentText
+
+ # Swizzle:
+ self._swizzle_widget = self._addComboBox(
+ 'Component',
+ ocio.SWIZZLE_TYPES,
+ self._swizzle,
+ ocio.swizzle_default,
+ lambda value: self.setSwizzle(value = value, update_widget = False, update_metadata = True))
+ self._swizzle = self._swizzle_widget.currentText
+
+ # Gain Group:
+ group_widget, layout = self._addWidgetGroup()
+ group_widget.setMaximumWidth(GAIN_GROUP_MAX_WIDTH)
+
+ layout.addWidget(QtGui.QLabel('Gain'))
+
+ # F-Stop:
+ subgroup_widget = QtGui.QWidget()
+ layout.addWidget(subgroup_widget)
+
+ sublayout = QtGui.QHBoxLayout()
+ sublayout.setSpacing(0)
+ sublayout.setMargin(0)
+ subgroup_widget.setLayout(sublayout)
+
+ exposure = ocio.convertGainToExposure(self._gain)
+ fstop = ocio.convertExposureToFStop(exposure)
+ scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE))
+ widget_value = scale * widget_max
+ self._fstop_widget = mari.LineEdit()
+ self._fstop_widget.setRange(widget_max)
+ self._fstop_widget.setMaximumWidth(FSTOP_MAX_WIDTH)
+ self._fstop_widget.setReadOnly(True)
+ self._updateFStopWidgetText(fstop)
+ self._fstop_widget.setValue(widget_value)
+ mari.utils.connect(self._fstop_widget.movedMouse, self._fstopMovedMouse)
+ self._fstop_widget.addToLayout(sublayout)
+
+ self._fstop_decrement_widget = self._addSmallButtom(
+ sublayout,
+ '-',
+ 'Decrease gain 1/2 stop',
+ lambda: self.setGain(ocio.convertExposureToGain(ocio.convertGainToExposure(self._gain) - 0.5)))
+ self._fstop_increment_widget = self._addSmallButtom(
+ sublayout,
+ '+',
+ 'Increase gain 1/2 stop',
+ lambda: self.setGain(ocio.convertExposureToGain(ocio.convertGainToExposure(self._gain) + 0.5)))
+
+ ocio.registerLUTSizeChanged(self.updateLUTSize)
+ ocio.registerFStopCenterChanged(self.updateFStopCenter)
+
+ # Gain:
+ subgroup_widget = QtGui.QWidget()
+ layout.addWidget(subgroup_widget)
+
+ sublayout = QtGui.QHBoxLayout()
+ sublayout.setSpacing(3)
+ sublayout.setMargin(0)
+ subgroup_widget.setLayout(sublayout)
+
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE))
+ widget_value = scale * widget_max
+ self._gain_widget = mari.LineEdit()
+ self._gain_widget.setRange(widget_max)
+ self._gain_widget.addFloatValidator(ocio.GAIN_MIN, ocio.GAIN_MAX, ocio.GAIN_PRECISION)
+ self._gain_widget.setMaximumWidth(GAIN_MAX_WIDTH)
+ self._updateGainWidgetText()
+ self._gain_widget.setValue(widget_value)
+ mari.utils.connect(
+ self._gain_widget.lostFocus,
+ lambda: self.setGain(max(min(float(self._gain_widget.text()), ocio.GAIN_MAX), ocio.GAIN_MIN)))
+ mari.utils.connect(self._gain_widget.movedMouse, self._gainMovedMouse)
+ self._gain_widget.addToLayout(sublayout)
+
+ # Exposure:
+ self._exposure_widget = QtGui.QSlider()
+ self._exposure_widget.orientation = 1
+ self._exposure_widget.setMaximum(widget_max)
+ self._exposure_widget.setValue(widget_value)
+ self._exposure_widget.setMinimumWidth(EXPOSURE_MAX_WIDTH)
+ self._exposure_widget.setMaximumWidth(EXPOSURE_MAX_WIDTH)
+ mari.utils.connect(self._exposure_widget.valueChanged, self._exposureChanged)
+ sublayout.addWidget(self._exposure_widget)
+
+ self._gain_reset_widget = self._addSmallButtom(
+ layout,
+ 'R',
+ 'Reset gain to default',
+ lambda: self.setGain(value = ocio.GAIN_RESET, update_widget = True, update_metadata = True))
+
+ # Gamma:
+ group_widget, layout = self._addWidgetGroup()
+ group_widget.setMaximumWidth(GAMMA_MAX_WIDTH)
+
+ layout.addWidget(QtGui.QLabel('Gamma'))
+
+ self._gamma_widget = mari.FloatSlider()
+ self._gamma_widget.setRange(ocio.GAMMA_MIN, ocio.GAMMA_MAX)
+ self._gamma_widget.setStepSize(ocio.GAMMA_STEP_SIZE)
+ self._gamma_widget.setPrecision(ocio.GAMMA_PRECISION)
+ self._gamma_widget.setValue(self._gamma)
+ mari.utils.connect(
+ self._gamma_widget.valueChanged,
+ lambda value: self.setGamma(value = value, update_widget = False, update_metadata = True))
+ self._gamma_widget.addToLayout(layout)
+
+ self._gamma_reset_widget = self._addSmallButtom(
+ layout,
+ 'R',
+ 'Reset gamma to default',
+ lambda: self.setGamma(value = ocio.GAMMA_RESET, update_widget = True, update_metadata = True))
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateDisplayWidgets(self):
+ color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()]
+
+ self._updateComboBox(self._color_space_widget, color_spaces, self._color_space, ocio.color_space_default)
+ self._color_space = self._color_space_widget.currentText
+
+ self._updateComboBox(self._display_widget, self._config.getDisplays(), self._display, ocio.display_default)
+ self._display = self._display_widget.currentText
+
+ self._updateComboBox(self._view_widget, self._config.getViews(self._display), self._view, ocio.view_default)
+ self._view = self._view_widget.currentText
+
+ self._updateComboBox(self._swizzle_widget, ocio.SWIZZLE_TYPES, self._swizzle, ocio.swizzle_default)
+ self._swizzle = self._swizzle_widget.currentText
+
+ self._updateGainWidgets()
+
+ self._gamma_widget.setValue(self._gamma)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _enableWidgets(self, enable):
+ self._select_config_action.setEnabled(enable)
+ self._select_lut_action.setEnabled(enable)
+ lut_enable = enable and not self._lut_file_list.isEmpty()
+ self._clear_lut_action.setEnabled(lut_enable)
+ self._lut_extrapolate_widget.setEnabled(lut_enable)
+
+ self._color_space_widget.setEnabled(enable)
+ self._display_widget.setEnabled(enable)
+ self._view_widget.setEnabled(enable)
+ self._swizzle_widget.setEnabled(enable)
+
+ self._fstop_widget.setEnabled(enable)
+ self._fstop_decrement_widget.setEnabled(enable)
+ self._fstop_increment_widget.setEnabled(enable)
+ self._gain_widget.setEnabled(enable)
+ self._exposure_widget.setEnabled(enable)
+ self._gain_reset_widget.setEnabled(enable)
+
+ self._gamma_widget.setEnabled(enable)
+ self._gamma_reset_widget.setEnabled(enable)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _addAction(self, identifier, command, icon_filename, tip, whats_this):
+ action = mari.actions.find(identifier)
+ if action is None:
+ action = mari.actions.create(identifier, command)
+
+ icon_path = mari.resources.path(mari.resources.ICONS) + '/' + icon_filename
+ action.setIconPath(icon_path)
+
+ action.setStatusTip(tip)
+ action.setToolTip(tip)
+ action.setWhatsThis(whats_this)
+
+ return action
+
+ #-----------------------------------------------------------------------------------------
+
+ def _addWidgetGroup(self):
+ group_widget = QtGui.QWidget()
+ self._toolbar.addWidget(group_widget)
+
+ layout = QtGui.QHBoxLayout()
+ layout.setSpacing(1)
+ layout.setMargin(1)
+ group_widget.setLayout(layout)
+
+ return (group_widget, layout)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _addComboBox(self, label, items, value, default, value_changed, *args):
+ group_widget, layout = self._addWidgetGroup()
+
+ layout.addWidget(QtGui.QLabel(label))
+
+ widget = QtGui.QComboBox()
+ self._updateComboBox(widget, items, value, default)
+ widget.connect(QtCore.SIGNAL('currentIndexChanged(const QString &)'), value_changed)
+ layout.addWidget(widget)
+
+ return widget
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateComboBox(self, widget, items, value, default):
+ block = widget.blockSignals(True)
+
+ widget.clear()
+ for item in items:
+ widget.addItem(item)
+
+ if items.count(value) != 0:
+ widget.setCurrentIndex(items.index(value))
+ elif items.count(default) != 0:
+ widget.setCurrentIndex(items.index(default))
+
+ widget.blockSignals(block)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _addSmallButtom(self, layout, label, tool_tip, value_changed, *args):
+ widget = QtGui.QPushButton(label);
+ widget.setToolTip(tool_tip);
+ widget.setFixedHeight(16);
+ widget.setFixedWidth(16);
+ widget.connect(QtCore.SIGNAL('released()'), value_changed)
+ layout.addWidget(widget);
+
+ return widget
+
+ #-----------------------------------------------------------------------------------------
+
+ def _convertFStopWidgetValueToGain(self, value):
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE))
+ scale = float(value) / float(widget_max)
+ exposure = ocio.EXPOSURE_MIN + scale * ocio.EXPOSURE_DELTA
+ return ocio.convertExposureToGain(exposure)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _convertExposureWidgetValueToGain(self, value):
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE))
+ scale = float(value) / float(widget_max)
+ exposure = ocio.EXPOSURE_MIN + scale * ocio.EXPOSURE_DELTA
+ return ocio.convertExposureToGain(exposure)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateFStopWidgetText(self, fstop):
+ block = self._fstop_widget.blockSignals(True)
+ if fstop < 10.0:
+ # Floor the value to one decimal place and only display the decimal point if necessary
+ text = '%f' % fstop
+ index = text.index('.')
+ if text[index + 1] == '0':
+ text = text[:index]
+ else:
+ text = text[:index + 2]
+ self._fstop_widget.setText('f/%s' % text)
+ else:
+ self._fstop_widget.setText('f/%d' % int(fstop))
+ self._fstop_widget.blockSignals(block)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateGainWidgetText(self):
+ block = self._gain_widget.blockSignals(True)
+ self._gain_widget.setText(('%.' + ('%d' % ocio.GAIN_PRECISION) + 'f') % self._gain)
+ self._gain_widget.home(False)
+ self._gain_widget.blockSignals(block)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateGainWidgets(self):
+ exposure = ocio.convertGainToExposure(self._gain)
+ fstop = ocio.convertExposureToFStop(exposure)
+ self._updateFStopWidgetText(fstop)
+
+ scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE))
+ widget_value = int(round(scale * float(widget_max)))
+ block = self._fstop_widget.blockSignals(True)
+ self._fstop_widget.setValue(widget_value)
+ self._fstop_widget.blockSignals(block)
+
+ self._updateGainWidgetText()
+
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE))
+ widget_value = int(round(scale * float(widget_max)))
+ block = self._gain_widget.blockSignals(True)
+ self._gain_widget.setValue(widget_value)
+ self._gain_widget.blockSignals(block)
+ block = self._exposure_widget.blockSignals(True)
+ self._exposure_widget.setValue(widget_value)
+ self._exposure_widget.blockSignals(block)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _toggleColorManagement(self):
+ enabled = self.isColorManagementEnabled()
+ mari.gl_render.setPostProcessingEnabled(enabled)
+ self._enableWidgets(enabled)
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Toggled color management to \'%s\'' % ('on' if enabled else 'off'))
+
+ #-----------------------------------------------------------------------------------------
+
+ def _clearLUT(self):
+ self.setLUTPath('')
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Cleared lut')
+
+ #-----------------------------------------------------------------------------------------
+
+ def _fstopMovedMouse(self, value):
+ self.setGain(self._convertFStopWidgetValueToGain(float(value)), False)
+
+ exposure = ocio.convertGainToExposure(self._gain)
+ fstop = ocio.convertExposureToFStop(exposure)
+ self._updateFStopWidgetText(fstop)
+
+ self._updateGainWidgetText()
+
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE))
+ scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA
+ value = int(round(scale * float(widget_max)))
+ self._gain_widget.setValue(value)
+
+ value = max(min(value, widget_max), 0)
+ self._exposure_widget.setValue(value)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _gainMovedMouse(self, value):
+ self.setGain(self._convertExposureWidgetValueToGain(float(value)), False)
+
+ self._updateGainWidgetText()
+
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE))
+ value = max(min(value, widget_max), 0)
+ self._exposure_widget.setValue(value)
+
+ exposure = ocio.convertGainToExposure(self._gain)
+ fstop = ocio.convertExposureToFStop(exposure)
+ self._updateFStopWidgetText(fstop)
+
+ scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE))
+ value = int(round(scale * float(widget_max)))
+ self._fstop_widget.setValue(value)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _exposureChanged(self, value):
+ self.setGain(value = self._convertExposureWidgetValueToGain(float(value)),
+ update_widget = False,
+ update_metadata = True)
+
+ self._updateGainWidgetText()
+
+ self._gain_widget.setValue(value)
+
+ exposure = ocio.convertGainToExposure(self._gain)
+ fstop = ocio.convertExposureToFStop(exposure)
+ self._updateFStopWidgetText(fstop)
+
+ scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA
+ widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE))
+ value = int(round(scale * float(widget_max)))
+ self._fstop_widget.setValue(value)
+
+ #-----------------------------------------------------------------------------------------
+ # Metadata:
+ #-----------------------------------------------------------------------------------------
+
+ def _buildMetadata(self):
+ # LUT:
+ # ---
+ mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+ self._updateLUTMetadata()
+
+ flags = self._lut_filter.METADATA_VISIBLE | self._lut_filter.METADATA_EDITABLE
+ self._lut_filter.setMetadataFlags('File', flags)
+
+ self._lut_filter.setMetadataFlags('Extrapolate', flags)
+
+ # Display:
+ # -------
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+ self._updateDisplayMetadata()
+
+ self._display_filter.setMetadataDisplayName('ConfigPath', 'Configuration File')
+ flags = self._display_filter.METADATA_VISIBLE | self._display_filter.METADATA_EDITABLE
+ self._display_filter.setMetadataFlags('ConfigPath', flags)
+
+ self._display_filter.setMetadataDisplayName('InputColorSpace', 'Input Color Space')
+ self._display_filter.setMetadataFlags('InputColorSpace', flags)
+
+ self._display_filter.setMetadataDisplayName('Display', 'Display Device')
+ self._display_filter.setMetadataFlags('Display', flags)
+
+ self._display_filter.setMetadataDisplayName('View', 'View Transform')
+ self._display_filter.setMetadataFlags('View', flags)
+
+ self._display_filter.setMetadataDisplayName('Swizzle', 'Component')
+ self._display_filter.setMetadataFlags('Swizzle', flags)
+
+ self._display_filter.setMetadataDefault('Gain', ocio.GAIN_RESET)
+ self._display_filter.setMetadataRange('Gain', ocio.GAIN_MIN, ocio.GAIN_MAX)
+ self._display_filter.setMetadataStep('Gain', ocio.GAIN_STEP_SIZE)
+ self._display_filter.setMetadataFlags('Gain', flags)
+
+ self._display_filter.setMetadataDefault('Gamma', ocio.GAMMA_RESET)
+ self._display_filter.setMetadataRange('Gamma', ocio.GAMMA_MIN, ocio.GAMMA_MAX)
+ self._display_filter.setMetadataStep('Gamma', ocio.GAMMA_STEP_SIZE)
+ self._display_filter.setMetadataFlags('Gamma', flags)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateLUTMetadata(self):
+ mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+
+ self._lut_filter.setMetadata('File', self._lut_file_list)
+
+ self._lut_filter.setMetadata('Extrapolate', self._lut_extrapolate)
+
+ mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _updateDisplayMetadata(self):
+ mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+ self._display_filter.setMetadata('ConfigPath', self._config_file_list)
+
+ color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()]
+
+ self._display_filter.setMetadata('InputColorSpace', self._color_space)
+ self._display_filter.setMetadataItemList('InputColorSpace', color_spaces)
+
+ self._display_filter.setMetadata('Display', self._display)
+ self._display_filter.setMetadataItemList('Display', self._config.getDisplays())
+
+ self._display_filter.setMetadata('View', self._view)
+ self._display_filter.setMetadataItemList('View', self._config.getViews(self._display))
+
+ self._display_filter.setMetadata('Swizzle', self._swizzle)
+ self._display_filter.setMetadataItemList('Swizzle', ocio.SWIZZLE_TYPES)
+
+ self._display_filter.setMetadata('Gain', self._gain)
+
+ self._display_filter.setMetadata('Gamma', self._gain)
+
+ mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged)
+
+
+ #-----------------------------------------------------------------------------------------
+ # External Connections:
+ #-----------------------------------------------------------------------------------------
+
+ def _openedProject(self, project):
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Loading settings for project \'%s\'' % project.name())
+
+ # Load the settings stored as metadata on the project...
+
+ # General:
+ # -------
+
+ self._toggle_color_management_action.setEnabled(True)
+ self._toggle_color_management_action.setChecked(project.metadata('ColorEnabled') if project.hasMetadata('ColorEnabled') else ocio.enabled_default)
+
+ # Enable/disable color management (MUST be done after modifications to 'self._toggle_color_management_action'.
+ mari.gl_render.setPostProcessingEnabled(self.isColorManagementEnabled())
+
+ filter_collection = None
+ if project.hasMetadata('ColorProfile'):
+ # *** IMPORTANT *** The post filter collection used to be called 'OpenColorIO' but was renamed to hide the
+ # fact we use OpenColorIO from our users. So as a temporary workaround we need to check for the old filter
+ # collection correct for it.
+ name = project.metadata('ColorProfile')
+ if name == 'OpenColorIO':
+ name = 'Color Space'
+ filter_collection = mari.gl_render.findPostFilterCollection(name)
+
+ # Default the color management filter stack if the working one doesn't exist.
+ if filter_collection is None:
+ filter_collection = mari.gl_render.findPostFilterCollection(ocio.profile_default)
+
+ mari.gl_render.setPostFilterCollection(filter_collection)
+
+ # LUT:
+ # ---
+
+ lut_extrapolate = project.metadata('OcioLutExtrapolate') if project.hasMetadata('OcioLutExtrapolate') else ocio.lut_extrapolate_default
+ force_shader_build = lut_extrapolate != self._lut_extrapolate
+ self._lut_extrapolate = lut_extrapolate
+ self._lut_extrapolate_widget.setChecked(self._lut_extrapolate)
+
+ if project.hasMetadata('OcioLutPath'):
+ lut_path = ocio.buildLoadPath(project.metadata('OcioLutPath'))
+ if not self.setLUTPath(value = lut_path, update_metadata = True, force_shader_build = force_shader_build):
+ self.resetLUT()
+ else:
+ self.resetLUT()
+
+ # Display:
+ # -------
+
+ self._color_space = project.metadata( 'OcioColorSpace') if project.hasMetadata('OcioColorSpace') else ocio.color_space_default
+ self._display = project.metadata( 'OcioDisplay') if project.hasMetadata( 'OcioDisplay') else ocio.display_default
+ self._view = project.metadata( 'OcioView') if project.hasMetadata( 'OcioView') else ocio.view_default
+ self._swizzle = project.metadata( 'OcioSwizzle') if project.hasMetadata( 'OcioSwizzle') else ocio.swizzle_default
+ self._gain = max(min(project.metadata('OcioGain'),
+ ocio.GAIN_MAX),
+ ocio.GAIN_MIN) if project.hasMetadata( 'OcioGain') else ocio.gain_default
+ self._gamma = project.metadata( 'OcioGamma') if project.hasMetadata( 'OcioGamma') else ocio.gamma_default
+
+ # Attempt to load a configuration file...
+ self._config_file_list.clear()
+ self._config = None
+
+ # 1. Environment variable.
+ config_path = os.getenv('OCIO')
+ if config_path is not None:
+ self.setConfigPath(config_path)
+
+ # 2. Project setting.
+ if self._config is None and project.hasMetadata('OcioConfigPath'):
+ self.setConfigPath(ocio.buildLoadPath(project.metadata('OcioConfigPath')))
+
+ # 3. Use the default if nothing was found.
+ if self._config is None:
+ self._config_file_list = mari.FileList(ocio.config_file_list_default)
+ self._config = ocio.config_default
+
+ self._updateDisplayWidgets()
+ self._rebuildDisplayFilter()
+
+ self._enableWidgets(filter_collection.name() == 'Color Space' and self._toggle_color_management_action.isChecked())
+ self._updateLUTMetadata()
+ self._updateDisplayMetadata()
+
+ self._printLog()
+
+ #-----------------------------------------------------------------------------------------
+
+ def _aboutToSaveProject(self, project):
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Saving settings for project \'%s\'' % project.name())
+
+ # Store the settings as metadata on the project.
+ project.setMetadata( 'ColorEnabled', self.isColorManagementEnabled())
+ filter_collection = mari.gl_render.currentPostFilterCollection()
+ if filter_collection is not None:
+ project.setMetadata( 'ColorProfile', filter_collection.name())
+ project.setMetadata('OcioLutExtrapolate', self._lut_extrapolate)
+ project.setMetadata( 'OcioLutPath', '' if self._lut_file_list.isEmpty() else ocio.buildSavePath(self._lut_file_list.at(0)))
+ if os.getenv('OCIO') is None:
+ project.setMetadata('OcioConfigPath', '' if self._config_file_list.isEmpty() else ocio.buildSavePath(self._config_file_list.at(0)))
+ project.setMetadata( 'OcioColorSpace', self._color_space)
+ project.setMetadata( 'OcioDisplay', self._display)
+ project.setMetadata( 'OcioView', self._view)
+ project.setMetadata( 'OcioSwizzle', self._swizzle)
+ project.setMetadata( 'OcioGain', self._gain)
+ project.setMetadata( 'OcioGamma', self._gamma)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _closedProject(self):
+ self._toggle_color_management_action.setEnabled(False)
+ self._enableWidgets(False)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _toolBarsCreated(self):
+ # Things like deleting Mari's configuration file and reseting the layout to the default will destroy the toolbar
+ # so we need to detect if this is the case and rebuild it!
+ toolbar = mari.app.findToolBar('Color Space')
+ if toolbar is None:
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Rebuilding missing toolbar...')
+ self._buildWidgets()
+
+ #-----------------------------------------------------------------------------------------
+
+ def _postProcessingEnabled(self, enabled):
+ self._toggle_color_management_action.setChecked(enabled)
+
+ # Only enable or disable UI if we have a current project.
+ current_project = mari.projects.current()
+ if current_project is not None:
+ self._enableWidgets(enabled)
+
+ #-----------------------------------------------------------------------------------------
+
+ def _setCurrentPostFilterCollection(self):
+ # Only enable or disable UI if we have a current project.
+ current_project = mari.projects.current()
+ if current_project is not None:
+ filter_collection = mari.gl_render.currentPostFilterCollection()
+ if filter_collection is None or filter_collection.name() != 'Color Space':
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Disabling OpenColorIO')
+ self._enableWidgets(False)
+ else:
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Enabling OpenColorIO')
+ self._enableWidgets(True)
+
+ #-----------------------------------------------------------------------------------------
+ # Filter:
+ #-----------------------------------------------------------------------------------------
+
+ def _rebuildLUTFilter(self, lut_path, force_shader_build = False):
+ if lut_path == '':
+ self._lut_filter.setDefinitionsSnippet('')
+ self._lut_filter.setBodySnippet('')
+
+ if self._lut_sampler_name is not None:
+ self._lut_filter.deleteTexture(self._lut_sampler_name)
+ self._lut_sampler_name = None
+
+ self._lut_filter_cache_id = None
+ self._lut_texture_cache_id = None
+
+ else:
+ # There is a chance this is a bad file so we need to guard against it.
+ try:
+ self._lut_filter_cache_id, self._lut_texture_cache_id, self._lut_sampler_name = ocio.buildLUTFilter(
+ self._config,
+ lut_path,
+ self._lut_filter,
+ self._lut_filter_cache_id,
+ self._lut_texture_cache_id,
+ self._lut_extrapolate,
+ force_shader_build)
+
+ except Exception, e:
+ message = 'Failed to load LUT file \'%s\' due to \'%s\'' % (lut_path, e)
+ ocio.printMessage(ocio.MessageType.ERROR, '%s' % message)
+ if not mari.app.inTerminalMode():
+ mari.utils.misc.message(message, 'Color Space', 1024, 2)
+
+ return False
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Changed LUT to \'%s\'' % lut_path)
+
+ return True
+
+ #-----------------------------------------------------------------------------------------
+
+ def _rebuildDisplayFilter(self):
+ display_transform = ocio.PyOpenColorIO.DisplayTransform()
+ display_transform.setInputColorSpaceName(self._color_space)
+
+ if hasattr(display_transform, 'setDisplay'):
+ # OCIO 1.0+
+ display_transform.setDisplay(self._display)
+ display_transform.setView(self._view)
+ else:
+ # OCIO 0.8.X
+ display_color_space = self._config.getDisplayColorSpaceName(self._display, self._view)
+ display_transform.setDisplayColorSpaceName(display_color_space)
+
+ # Add the channel sizzle.
+ luma_coefs = self._config.getDefaultLumaCoefs()
+ mtx, offset = ocio.PyOpenColorIO.MatrixTransform.View(ocio.SWIZZLE_VALUES[self._swizzle], luma_coefs)
+
+ transform = ocio.PyOpenColorIO.MatrixTransform()
+ transform.setValue(mtx, offset)
+ display_transform.setChannelView(transform)
+
+ # Add the linear gain.
+ transform = ocio.PyOpenColorIO.CDLTransform()
+ transform.setSlope((self._gain, self._gain, self._gain))
+ display_transform.setLinearCC(transform)
+
+ # Add the post-display CC.
+ transform = ocio.PyOpenColorIO.ExponentTransform()
+ transform.setValue([1.0 / max(1e-6, v) for v in (self._gamma, self._gamma, self._gamma, self._gamma)])
+ display_transform.setDisplayCC(transform)
+
+ processor = self._config.getProcessor(display_transform)
+
+ self._display_filter_cache_id, self._display_texture_cache_id, self._display_sampler_name = ocio.buildProcessorFilter(
+ processor,
+ self._display_filter,
+ self._display_filter_cache_id,
+ self._display_texture_cache_id)
+
+ current_canvas = mari.canvases.current()
+ if current_canvas is not None:
+ current_canvas.repaint()
+
+ #-----------------------------------------------------------------------------------------
+ # Debugging:
+ #-----------------------------------------------------------------------------------------
+
+ def _printLog(self):
+ ocio.printMessage( ocio.MessageType.INFO, '==============================================================')
+ ocio.printMessage( ocio.MessageType.INFO, 'Configuration:')
+ ocio.printMessage( ocio.MessageType.INFO, '==============================================================')
+ ocio.printMessage( ocio.MessageType.INFO, ' Enabled: %s; Default: %s' % (mari.gl_render.isPostProcessingEnabled(),
+ ocio.enabled_default))
+ filter_collection = mari.gl_render.currentPostFilterCollection()
+ if filter_collection is not None:
+ ocio.printMessage(ocio.MessageType.INFO, ' Profile: %s; Default: %s' % (filter_collection.name(),
+ ocio.profile_default))
+ else:
+ ocio.printMessage(ocio.MessageType.INFO, ' Profile: None; Default: %s' % (ocio.profile_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' LUT Path: %s; Default: %s' % ('' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0),
+ '' if ocio.lut_file_list_default.isEmpty() else ocio.lut_file_list_default.at(0)))
+ ocio.printMessage( ocio.MessageType.INFO, ' Extrapolate: %s; Default: %s' % (self._lut_extrapolate,
+ ocio.lut_extrapolate_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' Config Path: %s; Default: %s' % ('' if self._config_file_list.isEmpty() else self._config_file_list.at(0),
+ '' if ocio.config_file_list_default.isEmpty() else ocio.config_file_list_default.at(0)))
+ ocio.printMessage( ocio.MessageType.INFO, ' Color Space: %s; Default: %s' % (self._color_space,
+ ocio.color_space_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' Display: %s; Default: %s' % (self._display,
+ ocio.display_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' View: %s; Default: %s' % (self._view,
+ ocio.view_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' Swizzle: %s; Default: %s' % (self._swizzle,
+ ocio.swizzle_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' F-Stop: %f; Default: %f; Center: %f' % (ocio.convertGainToFStop(self._gain),
+ ocio.convertGainToFStop(ocio.gain_default),
+ ocio.fstop_center))
+ ocio.printMessage( ocio.MessageType.INFO, ' Gain: %f; Default: %f' % (self._gain,
+ ocio.gain_default))
+ ocio.printMessage( ocio.MessageType.INFO, ' Gamma: %f; Default: %f' % (self._gamma,
+ ocio.gamma_default))
+ ocio.printMessage( ocio.MessageType.INFO, '==============================================================')
+
+##############################################################################################
+# The following functions CAN'T be part of the toolbar class as a potential bug in PythonQt
+# causes the disconnect function to fail
+
+def lutMetadataValueChanged(name, value):
+ global toolbar
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'LUT metadata \'%s\' changed to \'%s\'' % (name, value))
+
+ if name == 'File':
+ toolbar.setLUTPath(value = '' if value.isEmpty() else value.at(0),
+ update_metadata = False,
+ force_shader_build = False)
+
+ elif name == 'Extrapolate':
+ toolbar.setExtrapolateEnabled(value = value, update_widget = True, update_metadata = False)
+
+#-----------------------------------------------------------------------------------------
+
+def displayMetadataValueChanged(name, value):
+ global toolbar
+
+ ocio.printMessage(ocio.MessageType.DEBUG, 'Display metadata \'%s\' changed to \'%s\'' % (name, value))
+
+ if name == 'ConfigPath':
+ toolbar.setConfigPath(value = '' if value.isEmpty() else value.at(0), update_metadata = False)
+
+ elif name == 'InputColorSpace':
+ toolbar.setColorSpace(value = value, update_widget = True, update_metadata = False)
+
+ elif name == 'Display':
+ toolbar.setDisplay(value = value, update_widget = True, update_metadata = False)
+
+ elif name == 'View':
+ toolbar.setView(value = value, update_widget = True, update_metadata = False)
+
+ elif name == 'Swizzle':
+ toolbar.setSwizzle(value = value, update_widget = True, update_metadata = False)
+
+ elif name == 'Gain':
+ toolbar.setGain(value = value, update_widget = True, update_metadata = False)
+
+ elif name == 'Gamma':
+ toolbar.setGamma(value = value, update_widget = True, update_metadata = False)
+
+##############################################################################################
+
+if mari.app.isRunning():
+ if not hasattr(mari.gl_render, 'createPostFilterCollection'):
+ ocio.printMessage(ocio.MessageType.ERROR, 'This version of Mari does not support the mari.gl_render.createPostFilterCollection API')
+
+ else:
+ if ocio.config_default is not None:
+ toolbar = OcioToolBar()
+
+ else:
+ # Destroy the OCIO post filter collection if present to prevent the user trying to use it.
+ filter_collection = mari.gl_render.findPostFilterCollection('Color Space')
+ if filter_collection is not None:
+ mari.gl_render.deletePostFilterCollection(filter_collection)
+
+ # Destroy the toolbar to prevent the user trying to use it.
+ mari.app.deleteToolBar('Color Space')
diff --git a/src/mari/1.4v1/ocio.py b/src/mari/1.4v1/ocio.py
new file mode 100755
index 0000000..4f0f61e
--- /dev/null
+++ b/src/mari/1.4v1/ocio.py
@@ -0,0 +1,789 @@
+#-------------------------------------------------------------------------------
+# OpenColorIO (color management) related Mari scripts
+# coding: utf-8
+# Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved.
+#-------------------------------------------------------------------------------
+
+import mari, time, PythonQt, os, math
+
+##############################################################################################
+
+# Enable to output extended debugging messages.
+VERBOSE_ENABLED = False
+
+# Message type identifiers.
+class MessageType:
+ DEBUG = 1
+ INFO = 2
+ WARNING = 3
+ ERROR = 4
+
+def printMessage(type, message):
+ if type == MessageType.DEBUG:
+ if VERBOSE_ENABLED:
+ mari.app.log('[ OpenColorIO ] %s' % message)
+ elif type == MessageType.INFO:
+ mari.app.log('[ OpenColorIO ] %s' % message)
+ elif type == MessageType.WARNING:
+ mari.app.log('[ OpenColorIO ] [ WARNING ] %s' % message)
+ elif type == MessageType.ERROR:
+ mari.app.log('[ OpenColorIO ] [ ERROR ] %s' % message)
+
+##############################################################################################
+
+def configFileFilter():
+ return 'OpenColorIO Configuration (*.ocio)'
+
+#---------------------------------------------------------------------------------------------
+
+def lutFileFilter():
+ result = 'All LUT Files (*.3dl *.ccc *.cc *.csp *.cub *.cube *.hdl *.m3d *.mga *.spi1d *.spi3d *.spimtx *.vf);;'
+ result += 'Autodesk LUT (*.3dl);;'
+ result += 'ASC CDL Color Correction Collection LUT (*.ccc);;'
+ result += 'ASC CDL Color Correction LUT (*.cc);;'
+ result += 'Cinespace LUT (*.csp);;'
+ result += 'Truelight LUT (*.cub);;'
+ result += 'Iridas LUT (*.cube);;'
+ result += 'Houdini LUT (*.hdl);;'
+ result += 'Pandora LUT (*.m3d *.mga);;'
+ result += 'Imageworks LUT (*.spi1d *.spi3d *.spimtx);;'
+ result += 'Inventor LUT (*.vf)'
+ return result
+
+##############################################################################################
+
+# Make sure the OpenColorIO python bindings are okay.
+try:
+ import PyOpenColorIO
+ printMessage(MessageType.INFO, 'Loaded Python bindings \'%s\' successfully' % PyOpenColorIO.__file__)
+except ImportError, e:
+ PyOpenColorIO = None
+ printMessage(MessageType.ERROR, 'Failed to load Python bindings \'%s\'' % e)
+
+LUT_FILE_LIST_RESET = mari.FileList(mari.FileList.TYPE_SINGLE_FILE)
+LUT_FILE_LIST_RESET.setAcceptNonExisting(True)
+LUT_FILE_LIST_RESET.setFilter(lutFileFilter())
+
+CONFIG_FILE_LIST_RESET = mari.FileList(mari.FileList.TYPE_SINGLE_FILE)
+if mari.app.isRunning():
+ CONFIG_FILE_LIST_RESET.append(mari.resources.path(mari.resources.COLOR) + '/OpenColorIO/nuke-default/config.ocio')
+else:
+ CONFIG_FILE_LIST_RESET.append('/OpenColorIO/nuke-default/config.ocio')
+CONFIG_FILE_LIST_RESET.setPickedFile(CONFIG_FILE_LIST_RESET.at(0))
+CONFIG_FILE_LIST_RESET.setAcceptNonExisting(True)
+CONFIG_FILE_LIST_RESET.setFilter(configFileFilter())
+
+SQRT_TWO = math.sqrt(2.0)
+LUT_SIZE_TYPES = ['Small', 'Medium', 'Large']
+LUT_SIZE_VALUES = {'Small': 16,
+ 'Medium': 32,
+ 'Large': 64}
+LUT_SIZE_RESET = LUT_SIZE_TYPES[1]
+ENABLED_RESET = True
+PROFILE_RESET = 'Color Space'
+LUT_EXTRAPOLATE_RESET = True
+COLOR_SPACE_RESET = 'sRGB'
+DISPLAY_RESET = 'default'
+VIEW_RESET = 'sRGB'
+SWIZZLE_TYPES = ['Luminance', 'RGB', 'R', 'G', 'B', 'A']
+SWIZZLE_VALUES = {'Luminance': ( True, True, True, False),
+ 'RGB': ( True, True, True, True),
+ 'R': ( True, False, False, False),
+ 'G': (False, True, False, False),
+ 'B': (False, False, True, False),
+ 'A': (False, False, False, True)}
+SWIZZLE_RESET = SWIZZLE_TYPES[1]
+FSTOP_STEP_SIZE = 0.5
+FSTOP_CENTER_MIN = 1.0
+FSTOP_CENTER_MAX = 64.0
+FSTOP_CENTER_STEP_SIZE = 0.001
+FSTOP_CENTER_RESET = 8.0
+EXPOSURE_MIN = -6.0
+EXPOSURE_MAX = +6.0
+EXPOSURE_DELTA = EXPOSURE_MAX - EXPOSURE_MIN
+EXPOSURE_STEP_SIZE = 0.1
+GAIN_RESET = 1.0
+GAIN_MIN = 2.0 ** EXPOSURE_MIN
+GAIN_MAX = 2.0 ** EXPOSURE_MAX
+GAIN_STEP_SIZE = 0.000001
+GAIN_PRECISION = 6
+GAMMA_RESET = 1.0
+GAMMA_MIN = 0.0
+GAMMA_MAX = 4.0
+GAMMA_STEP_SIZE = 0.01
+GAMMA_PRECISION = 2
+
+enabled_default = ENABLED_RESET
+profile_default = PROFILE_RESET
+lut_file_list_default = mari.FileList(LUT_FILE_LIST_RESET)
+lut_extrapolate_default = LUT_EXTRAPOLATE_RESET
+config_file_list_default = mari.FileList(CONFIG_FILE_LIST_RESET)
+color_space_default = COLOR_SPACE_RESET
+display_default = DISPLAY_RESET
+view_default = VIEW_RESET
+swizzle_default = SWIZZLE_RESET
+gain_default = GAIN_RESET
+gamma_default = GAMMA_RESET
+lut_size = LUT_SIZE_RESET
+fstop_center = FSTOP_CENTER_RESET
+
+config_default = None
+
+lut_size_functions = []
+fstop_center_functions = []
+
+##############################################################################################
+
+def registerLUTSizeChanged(function):
+ global lut_size_functions
+ lut_size_functions.append(function)
+
+#---------------------------------------------------------------------------------------------
+
+def registerFStopCenterChanged(function):
+ global fstop_center_functions
+ fstop_center_functions.append(function)
+
+#---------------------------------------------------------------------------------------------
+
+def _enabledDefaultChanged():
+ global enabled_default
+ enabled_default = mari.prefs.get('/Color/Color Management Defaults/colorEnabledDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _profileDefaultChanged():
+ global profile_default
+ profile_default = mari.prefs.get('/Color/Color Management Defaults/colorProfileDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _postFilterCollectionAdded(filter_collection):
+ mari.prefs.setItemList('/Color/Color Management Defaults/colorProfileDefault', mari.gl_render.postFilterCollectionNames())
+
+#---------------------------------------------------------------------------------------------
+
+def _postFilterCollectionRemoved(name):
+ collection_names = mari.gl_render.postFilterCollectionNames()
+ mari.prefs.setItemList('/Color/Color Management Defaults/colorProfileDefault', collection_names)
+
+ global PROFILE_RESET
+ if name == PROFILE_RESET:
+ PROFILE_RESET = collection_names[0]
+ mari.prefs.setDefault('/Color/Color Management Defaults/colorProfileDefault', PROFILE_RESET)
+
+ global profile_default
+ if name == profile_default:
+ profile_default = PROFILE_RESET
+ mari.prefs.set('/Color/Color Management Defaults/colorProfileDefault', profile_default)
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _lutPathDefaultChanged():
+ global lut_file_list_default
+ lut_file_list_default = mari.FileList(mari.prefs.get('/Color/LUT Defaults/lutPathDefault'))
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _lutExtrapolateDefaultChanged():
+ global lut_extrapolate_default
+ lut_extrapolate_default = mari.prefs.get('/Color/LUT Defaults/lutExtrapolateDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _configPathDefaultChanged():
+ global config_file_list_default
+
+ # Only replace the existing configuration file if the new one is valid!
+ config_file_list = mari.FileList(mari.prefs.get('/Color/Display Defaults/displayConfigPathDefault'))
+
+ if not config_file_list.isEmpty():
+ config = loadConfig(config_file_list.at(0), True)
+ if config is not None:
+ config_file_list_default = config_file_list
+
+ global config_default
+ config_default = config
+
+ _updateColorSpaceDefault()
+ _updateDisplayDefault()
+ _updateViewDefault()
+
+ _savePreferences()
+
+ else:
+ # Put back the existing configuration file that works...
+ mari.prefs.set('/Color/Display Defaults/displayConfigPathDefault', config_file_list_default)
+ else:
+ # Put back the existing configuration file that works...
+ mari.prefs.set('/Color/Display Defaults/displayConfigPathDefault', config_file_list_default)
+
+#---------------------------------------------------------------------------------------------
+
+def _colorSpaceDefaultChanged():
+ global color_space_default
+ color_space_default = mari.prefs.get('/Color/Display Defaults/displayColorSpaceDefault')
+ _updateDisplayDefault()
+ _updateViewDefault()
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _displayDefaultChanged():
+ global display_default
+ display_default = mari.prefs.get('/Color/Display Defaults/displayDisplayDefault')
+ _updateViewDefault()
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _viewDefaultChanged():
+ global view_default
+ view_default = mari.prefs.get('/Color/Display Defaults/displayViewDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _swizzleDefaultChanged():
+ global swizzle_default
+ swizzle_default = mari.prefs.get('/Color/Display Defaults/displaySwizzleDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _gainDefaultChanged():
+ global gain_default
+ gain_default = mari.prefs.get('/Color/Display Defaults/displayGainDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _gammaDefaultChanged():
+ global gamma_default
+ gamma_default = mari.prefs.get('/Color/Display Defaults/displayGammaDefault')
+ _savePreferences()
+
+#---------------------------------------------------------------------------------------------
+
+def _lutSizeChanged():
+ global lut_size
+ global lut_size_functions
+ lut_size = mari.prefs.get('/Color/Display General/displayLutSize')
+ _savePreferences()
+ for function in lut_size_functions:
+ function()
+
+#---------------------------------------------------------------------------------------------
+
+def _fstopCenterChanged():
+ global fstop_center
+ global fstop_center_functions
+ fstop_center = mari.prefs.get('/Color/Display General/displayFStopCenter')
+ _savePreferences()
+ for function in fstop_center_functions:
+ function()
+
+#---------------------------------------------------------------------------------------------
+
+def _registerPreferences():
+ global enabled_default
+ mari.prefs.set('/Color/Color Management Defaults/colorEnabledDefault', enabled_default)
+ mari.prefs.setChangedScript('/Color/Color Management Defaults/colorEnabledDefault', 'mari.utils.ocio._enabledDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Color Management Defaults/colorEnabledDefault', 'Enabled')
+ mari.prefs.setDefault('/Color/Color Management Defaults/colorEnabledDefault', ENABLED_RESET)
+
+ global profile_default
+ mari.prefs.set('/Color/Color Management Defaults/colorProfileDefault', profile_default)
+ mari.prefs.setChangedScript('/Color/Color Management Defaults/colorProfileDefault', 'mari.utils.ocio._profileDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Color Management Defaults/colorProfileDefault', 'Color Profile')
+ mari.prefs.setDefault('/Color/Color Management Defaults/colorProfileDefault', PROFILE_RESET)
+ mari.prefs.setItemList('/Color/Color Management Defaults/colorProfileDefault', mari.gl_render.postFilterCollectionNames())
+
+ global lut_file_list_default
+ if not lut_file_list_default.isEmpty() and not os.path.isfile(lut_file_list_default.at(0)):
+ message = 'LUT file \'%s\' does not exist' % lut_file_list_default.at(0)
+ printMessage(MessageType.ERROR, '%s' % message)
+ lut_file_list_default = mari.FileList(LUT_FILE_LIST_RESET)
+
+ mari.prefs.set('/Color/LUT Defaults/lutPathDefault', lut_file_list_default)
+ mari.prefs.setChangedScript('/Color/LUT Defaults/lutPathDefault', 'mari.utils.ocio._lutPathDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/LUT Defaults/lutPathDefault', 'File')
+ mari.prefs.setDefault('/Color/LUT Defaults/lutPathDefault', LUT_FILE_LIST_RESET)
+
+ global lut_extrapolate_default
+ mari.prefs.set('/Color/LUT Defaults/lutExtrapolateDefault', lut_extrapolate_default)
+ mari.prefs.setChangedScript('/Color/LUT Defaults/lutExtrapolateDefault', 'mari.utils.ocio._lutExtrapolateDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/LUT Defaults/lutExtrapolateDefault', 'Extrapolate')
+ mari.prefs.setDefault('/Color/LUT Defaults/lutExtrapolateDefault', LUT_EXTRAPOLATE_RESET)
+
+ global config_file_list_default
+ global config_default
+ if not config_file_list_default.isEmpty():
+ config = loadConfig(config_file_list_default.at(0), False)
+ if config is not None:
+ config_default = config
+ else:
+ config_file_list_default = mari.FileList(CONFIG_FILE_LIST_RESET)
+ else:
+ config_file_list_default = mari.FileList(CONFIG_FILE_LIST_RESET)
+
+ mari.prefs.set('/Color/Display Defaults/displayConfigPathDefault', config_file_list_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displayConfigPathDefault', 'mari.utils.ocio._configPathDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displayConfigPathDefault', 'Configuration File')
+ mari.prefs.setDefault('/Color/Display Defaults/displayConfigPathDefault', CONFIG_FILE_LIST_RESET)
+
+ color_spaces = [color_space.getName() for color_space in config_default.getColorSpaces()]
+
+ color_space_reset = COLOR_SPACE_RESET
+ if color_spaces.count(color_space_reset) == 0:
+ color_space_reset = color_spaces[0]
+
+ global color_space_default
+ if color_spaces.count(color_space_default) == 0:
+ color_space_default = color_space_reset
+
+ mari.prefs.set('/Color/Display Defaults/displayColorSpaceDefault', color_space_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displayColorSpaceDefault', 'mari.utils.ocio._colorSpaceDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displayColorSpaceDefault', 'Input Color Space')
+ mari.prefs.setDefault('/Color/Display Defaults/displayColorSpaceDefault', color_space_reset)
+ mari.prefs.setItemList('/Color/Display Defaults/displayColorSpaceDefault', color_spaces)
+
+ displays = config_default.getDisplays()
+
+ display_reset = DISPLAY_RESET
+ if displays.count(display_reset) == 0:
+ display_reset = config_default.getDefaultDisplay()
+
+ global display_default
+ if displays.count(display_default) == 0:
+ display_default = display_reset
+
+ mari.prefs.set('/Color/Display Defaults/displayDisplayDefault', display_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displayDisplayDefault', 'mari.utils.ocio._displayDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displayDisplayDefault', 'Display')
+ mari.prefs.setDefault('/Color/Display Defaults/displayDisplayDefault', display_reset)
+ mari.prefs.setItemList('/Color/Display Defaults/displayDisplayDefault', displays)
+
+ views = config_default.getViews(display_default)
+
+ view_reset = VIEW_RESET
+ if views.count(view_reset) == 0:
+ view_reset = config_default.getDefaultView(display_default)
+
+ global view_default
+ if views.count(view_default) == 0:
+ view_default = view_reset
+
+ mari.prefs.set('/Color/Display Defaults/displayViewDefault', view_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displayViewDefault', 'mari.utils.ocio._viewDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displayViewDefault', 'View')
+ mari.prefs.setDefault('/Color/Display Defaults/displayViewDefault', view_reset)
+ mari.prefs.setItemList('/Color/Display Defaults/displayViewDefault', views)
+
+ global swizzle_default
+ if SWIZZLE_TYPES.count(swizzle_default) == 0:
+ swizzle_default = SWIZZLE_RESET
+
+ mari.prefs.set('/Color/Display Defaults/displaySwizzleDefault', swizzle_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displaySwizzleDefault', 'mari.utils.ocio._swizzleDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displaySwizzleDefault', 'Component')
+ mari.prefs.setDefault('/Color/Display Defaults/displaySwizzleDefault', SWIZZLE_RESET)
+ mari.prefs.setItemList('/Color/Display Defaults/displaySwizzleDefault', SWIZZLE_TYPES)
+
+ global gain_default
+ mari.prefs.set('/Color/Display Defaults/displayGainDefault', gain_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displayGainDefault', 'mari.utils.ocio._gainDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displayGainDefault', 'Gain')
+ mari.prefs.setDefault('/Color/Display Defaults/displayGainDefault', GAIN_RESET)
+ mari.prefs.setRange('/Color/Display Defaults/displayGainDefault', GAIN_MIN, GAIN_MAX)
+ mari.prefs.setStep('/Color/Display Defaults/displayGainDefault', GAIN_STEP_SIZE)
+
+ global gamma_default
+ mari.prefs.set('/Color/Display Defaults/displayGammaDefault', gamma_default)
+ mari.prefs.setChangedScript('/Color/Display Defaults/displayGammaDefault', 'mari.utils.ocio._gammaDefaultChanged()')
+ mari.prefs.setDisplayName('/Color/Display Defaults/displayGammaDefault', 'Gamma')
+ mari.prefs.setDefault('/Color/Display Defaults/displayGammaDefault', GAMMA_RESET)
+ mari.prefs.setRange('/Color/Display Defaults/displayGammaDefault', GAMMA_MIN, GAMMA_MAX)
+ mari.prefs.setStep('/Color/Display Defaults/displayGammaDefault', GAMMA_STEP_SIZE)
+
+ global lut_size
+ mari.prefs.set('/Color/Display General/displayLutSize', lut_size)
+ mari.prefs.setChangedScript('/Color/Display General/displayLutSize', 'mari.utils.ocio._lutSizeChanged()')
+ mari.prefs.setDisplayName('/Color/Display General/displayLutSize', 'LUT Size')
+ mari.prefs.setDefault('/Color/Display General/displayLutSize', LUT_SIZE_RESET)
+ mari.prefs.setItemList('/Color/Display General/displayLutSize', LUT_SIZE_TYPES)
+
+ global fstop_center
+ mari.prefs.set('/Color/Display General/displayFStopCenter', fstop_center)
+ mari.prefs.setChangedScript('/Color/Display General/displayFStopCenter', 'mari.utils.ocio._fstopCenterChanged()')
+ mari.prefs.setDisplayName('/Color/Display General/displayFStopCenter', 'Center F-Stop')
+ mari.prefs.setDefault('/Color/Display General/displayFStopCenter', FSTOP_CENTER_RESET)
+ mari.prefs.setRange('/Color/Display General/displayFStopCenter', FSTOP_CENTER_MIN, FSTOP_CENTER_MAX)
+ mari.prefs.setStep('/Color/Display General/displayFStopCenter', FSTOP_CENTER_STEP_SIZE)
+
+ # Attach ourselves to the appropriate project signals so we can update widgets.
+ PythonQt.QtCore.QObject.connect(mari.gl_render.postFilterCollectionAdded.__self__,
+ mari.gl_render.postFilterCollectionAdded.__name__,
+ _postFilterCollectionAdded)
+ PythonQt.QtCore.QObject.connect(mari.gl_render.postFilterCollectionRemoved.__self__,
+ mari.gl_render.postFilterCollectionRemoved.__name__,
+ _postFilterCollectionRemoved)
+
+#---------------------------------------------------------------------------------------------
+
+def _updateColorSpaceDefault():
+ global config_default
+ global color_space_default
+
+ color_spaces = [color_space.getName() for color_space in config_default.getColorSpaces()]
+
+ color_space_reset = COLOR_SPACE_RESET
+ if color_spaces.count(color_space_reset) == 0:
+ color_space_reset = color_spaces[0]
+
+ if color_spaces.count(color_space_default) == 0:
+ color_space_default = color_space_reset
+
+ mari.prefs.setItemList('/Color/Display Defaults/displayColorSpaceDefault', color_spaces)
+ mari.prefs.set('/Color/Display Defaults/displayColorSpaceDefault', color_space_default)
+ mari.prefs.setDefault('/Color/Display Defaults/displayColorSpaceDefault', color_space_reset)
+
+
+#---------------------------------------------------------------------------------------------
+
+def _updateDisplayDefault():
+ global config_default
+ global display_default
+
+ displays = config_default.getDisplays()
+
+ display_reset = DISPLAY_RESET
+ if displays.count(display_reset) == 0:
+ display_reset = config_default.getDefaultDisplay()
+
+ if displays.count(display_default) == 0:
+ display_default = display_reset
+
+ mari.prefs.setItemList('/Color/Display Defaults/displayDisplayDefault', displays)
+ mari.prefs.set('/Color/Display Defaults/displayDisplayDefault', display_default)
+ mari.prefs.setDefault('/Color/Display Defaults/displayDisplayDefault', display_reset)
+
+#---------------------------------------------------------------------------------------------
+
+def _updateViewDefault():
+ global config_default
+ global display_default
+ global view_default
+
+ views = config_default.getViews(display_default)
+
+ view_reset = VIEW_RESET
+ if views.count(view_reset) == 0:
+ view_reset = config_default.getDefaultView(display_default)
+
+ if views.count(view_default) == 0:
+ view_default = view_reset
+
+ mari.prefs.setItemList('/Color/Display Defaults/displayViewDefault', views)
+ mari.prefs.set('/Color/Display Defaults/displayViewDefault', view_default)
+ mari.prefs.setDefault('/Color/Display Defaults/displayViewDefault', view_reset)
+
+#---------------------------------------------------------------------------------------------
+
+def _loadPreferences():
+ settings = mari.Settings()
+ settings.beginGroup('OpenColorIO')
+
+ try:
+ global enabled_default
+ global profile_default
+ global lut_file_list_default
+ global lut_extrapolate_default
+ global config_file_list_default
+ global color_space_default
+ global display_default
+ global view_default
+ global swizzle_default
+ global gain_default
+ global gamma_default
+ global lut_size
+ global fstop_center
+
+ enabled_default = False if int(settings.value('enabledDefault', ENABLED_RESET)) == 0 else True
+ profile_default = str(settings.value('profileDefault', PROFILE_RESET))
+ lut_path = buildLoadPath(str(settings.value('lutPathDefault', '' if LUT_FILE_LIST_RESET.isEmpty() else LUT_FILE_LIST_RESET.at(0))))
+ lut_extrapolate_default = False if int(settings.value('lutExtrapolateDefault', LUT_EXTRAPOLATE_RESET)) == 0 else True
+ config_path = buildLoadPath(str(settings.value('configPathDefault', '' if CONFIG_FILE_LIST_RESET.isEmpty() else CONFIG_FILE_LIST_RESET.at(0))))
+ color_space_default = str(settings.value('colorSpaceDefault', COLOR_SPACE_RESET))
+ display_default = str(settings.value('displayDefault', DISPLAY_RESET))
+ view_default = str(settings.value('viewDefault', VIEW_RESET))
+ swizzle_default = str(settings.value('swizzleDefault', SWIZZLE_RESET))
+ gain_default = max(min(float(settings.value('gainDefault', GAIN_RESET)), GAIN_MAX), GAIN_MIN)
+ gamma_default = max(min(float(settings.value('gammaDefault', GAMMA_RESET)), GAMMA_MAX), GAMMA_MIN)
+ lut_size = str(settings.value('lutSize', LUT_SIZE_RESET))
+ fstop_center = max(min(float(settings.value('fstopCenter', FSTOP_CENTER_RESET)), FSTOP_CENTER_MAX), FSTOP_CENTER_MIN)
+
+ if os.path.isfile(lut_path):
+ lut_file_list_default.clear()
+ lut_file_list_default.append(lut_path)
+ lut_file_list_default.setPickedFile(lut_path)
+
+ if os.path.isfile(config_path):
+ config_file_list_default.clear()
+ config_file_list_default.append(config_path)
+ config_file_list_default.setPickedFile(config_path)
+
+ except ValueError, e:
+ printMessage(MessageType.ERROR, 'Failed to load preferences \'%s\'' % e)
+
+ settings.endGroup()
+
+ _printPreferences(MessageType.DEBUG, 'Loaded Preferences:')
+
+#---------------------------------------------------------------------------------------------
+
+def _savePreferences():
+ settings = mari.Settings()
+ settings.beginGroup('OpenColorIO')
+
+ global enabled_default
+ global profile_default
+ global lut_file_list_default
+ global lut_extrapolate_default
+ global config_file_list_default
+ global color_space_default
+ global display_default
+ global view_default
+ global swizzle_default
+ global gain_default
+ global gamma_default
+ global lut_size
+ global fstop_center
+
+ settings.setValue( 'enabledDefault', 1 if enabled_default else 0)
+ settings.setValue( 'profileDefault', profile_default)
+ settings.setValue( 'lutPathDefault', '' if lut_file_list_default.isEmpty() else buildSavePath(lut_file_list_default.at(0)))
+ settings.setValue('lutExtrapolateDefault', 1 if lut_extrapolate_default else 0)
+ settings.setValue( 'configPathDefault', '' if config_file_list_default.isEmpty() else buildSavePath(config_file_list_default.at(0)))
+ settings.setValue( 'colorSpaceDefault', color_space_default)
+ settings.setValue( 'displayDefault', display_default)
+ settings.setValue( 'viewDefault', view_default)
+ settings.setValue( 'swizzleDefault', swizzle_default)
+ settings.setValue( 'gainDefault', gain_default)
+ settings.setValue( 'gammaDefault', gamma_default)
+ settings.setValue( 'lutSize', lut_size)
+ settings.setValue( 'fstopCenter', fstop_center)
+
+ settings.endGroup()
+
+ _printPreferences(MessageType.DEBUG, 'Saved Preferences:')
+
+#---------------------------------------------------------------------------------------------
+
+def _printPreferences(type, title):
+ global enabled_default
+ global profile_default
+ global lut_file_list_default
+ global lut_extrapolate_default
+ global config_file_list_default
+ global color_space_default
+ global display_default
+ global view_default
+ global swizzle_default
+ global gain_default
+ global fstop_center
+ global lut_size
+ global gamma_default
+
+ printMessage(type, '==============================================================')
+ printMessage(type, title)
+ printMessage(type, '==============================================================')
+ printMessage(type, ' Enabled: %s' % enabled_default)
+ printMessage(type, ' Profile: %s' % profile_default)
+ printMessage(type, ' LUT Path: %s' % '' if lut_file_list_default.isEmpty() else lut_file_list_default.at(0))
+ printMessage(type, ' Extrapolate: %s' % lut_extrapolate_default)
+ printMessage(type, ' Config Path: %s' % '' if config_file_list_default.isEmpty() else config_file_list_default.at(0))
+ printMessage(type, ' Color Space: %s' % color_space_default)
+ printMessage(type, ' Display: %s' % display_default)
+ printMessage(type, ' View: %s' % view_default)
+ printMessage(type, ' Swizzle: %s' % swizzle_default)
+ printMessage(type, ' F-Stop: %f; Center: %f' % (convertGainToFStop(gain_default), fstop_center))
+ printMessage(type, ' Gain: %f' % gain_default)
+ printMessage(type, ' Gamma: %f' % gamma_default)
+ printMessage(type, ' LUT Size: %s' % lut_size)
+ printMessage(type, '==============================================================')
+
+##############################################################################################
+
+def convertExposureToGain(exposure):
+ return 2.0 ** exposure
+
+#---------------------------------------------------------------------------------------------
+
+def convertGainToExposure(gain):
+ return math.log(gain, 2.0)
+
+#---------------------------------------------------------------------------------------------
+
+def convertExposureToFStop(exposure):
+ global fstop_center
+ exposure_center = math.log(fstop_center, SQRT_TWO)
+ return math.pow(SQRT_TWO, exposure_center - exposure)
+
+#---------------------------------------------------------------------------------------------
+
+def convertGainToFStop(gain):
+ exposure = convertGainToExposure(gain)
+ return convertExposureToFStop(exposure)
+
+#---------------------------------------------------------------------------------------------
+
+def buildProcessorFilter(processor, filter, filter_cache_id, texture_cache_id, extrapolate = False, force_shader_build = False):
+ # Create a name, using the filter's name, that can be used in uniquely naming parameters and functions.
+ name = filter.name();
+ name = name.lower()
+ name = name.replace(' ', '_')
+
+ sampler_name = 'ocio_' + name + '_lut_$ID_'
+ function_name = 'ocio_' + name + '_$ID_'
+
+ global lut_size
+ shader_desc = { 'language': PyOpenColorIO.Constants.GPU_LANGUAGE_GLSL_1_3,
+ 'functionName': function_name,
+ 'lut3DEdgeLen': LUT_SIZE_VALUES[lut_size]}
+
+ cache_id = processor.getGpuShaderTextCacheID(shader_desc)
+ if cache_id != filter_cache_id or force_shader_build:
+ filter_cache_id = cache_id
+ printMessage(MessageType.DEBUG, 'Creating new GLSL filter...')
+
+ desc = 'uniform sampler3D ' + sampler_name + ';\n'
+ desc += processor.getGpuShaderText(shader_desc)
+ body = ''
+ if extrapolate:
+ # The following code was taken from Nuke's 'LUT3D::Extrapolate' functionality. It attempts to estimate what
+ # the corresponding color value would be when the incoming color value is outside the normal range of [0-1],
+ # such as the case with HDR images.
+ rcp_lut_edge_length = 1.0 / float(LUT_SIZE_VALUES[lut_size])
+
+ body += '{\n'
+ body += ' if( 1.0 < Out.r || 1.0 < Out.g || 1.0 < Out.b )\n'
+ body += ' {\n'
+ body += ' vec4 closest;\n'
+ body += ' closest.rgb = clamp(Out.rgb, vec3(0.0), vec3(1.0));\n'
+ body += ' closest.a = Out.a;\n'
+ body += '\n'
+ body += ' vec3 offset = Out.rgb - closest.rgb;\n'
+ body += ' float offset_distance = length(offset);\n'
+ body += ' offset = normalize(offset);\n'
+ body += '\n'
+ body += ' vec4 nbr_position;\n'
+ body += ' nbr_position.rgb = closest.rgb - %f * offset;\n' % rcp_lut_edge_length
+ body += ' nbr_position.a = Out.a;\n'
+ body += '\n'
+ body += ' Out = ' + function_name + '(closest, ' + sampler_name + ');\n'
+ body += ' Out.rgb += (Out.rgb - ' + function_name + '(nbr_position, ' + sampler_name + ').rgb) / %f * offset_distance;\n' % rcp_lut_edge_length
+ body += ' }\n'
+ body += ' else\n'
+ body += ' {\n'
+ body += ' Out = ' + function_name + '(Out, ' + sampler_name + ');\n'
+ body += ' }\n'
+ body += '}\n'
+ else:
+ body += '{ Out = ' + function_name + '(Out, ' + sampler_name + '); }\n'
+
+ filter.setDefinitionsSnippet(desc)
+ filter.setBodySnippet(body)
+ else:
+ printMessage(MessageType.DEBUG, 'No GLSL filter update required')
+
+ cache_id = processor.getGpuLut3DCacheID(shader_desc)
+ if cache_id != texture_cache_id:
+ lut = processor.getGpuLut3D(shader_desc)
+
+ printMessage(MessageType.DEBUG, 'Updating LUT...')
+
+ if texture_cache_id is None:
+ filter.setTexture3D(sampler_name,
+ LUT_SIZE_VALUES[lut_size],
+ LUT_SIZE_VALUES[lut_size],
+ LUT_SIZE_VALUES[lut_size],
+ filter.FORMAT_RGB,
+ lut)
+ else:
+ filter.updateTexture3D(sampler_name, lut)
+
+ texture_cache_id = cache_id
+ else:
+ printMessage(MessageType.DEBUG, 'No LUT update required')
+
+ return (filter_cache_id, texture_cache_id, sampler_name)
+
+#---------------------------------------------------------------------------------------------
+
+def buildLUTFilter(config, path, filter, filter_cache_id, texture_cache_id, extrapolate, force_shader_build = False):
+ file_transform = PyOpenColorIO.FileTransform()
+ file_transform.setSrc(path)
+ file_transform.setInterpolation('linear')
+
+ processor = config.getProcessor(file_transform)
+
+ return buildProcessorFilter(processor, filter, filter_cache_id, texture_cache_id, extrapolate, force_shader_build)
+
+#---------------------------------------------------------------------------------------------
+
+def loadConfig(path, display_message_box = True):
+ try:
+ config = PyOpenColorIO.Config.CreateFromFile(path)
+ return config
+
+ except Exception, e:
+ message = 'Failed to load configuration file \'%s\' due to \'%s\'' % (path, e)
+ printMessage(MessageType.ERROR, '%s' % message)
+ if display_message_box and not mari.app.inTerminalMode():
+ mari.utils.misc.message(message, 'Color Space', 1024, 2)
+
+ return None
+
+#---------------------------------------------------------------------------------------------
+
+# This converts a path into a form which can be shared among different platforms and installations.
+def buildSavePath(path):
+ result = path.replace(mari.resources.path(mari.resources.COLOR), '$MARI_COLOR_PATH', 1)
+ return result
+
+#---------------------------------------------------------------------------------------------
+
+# This converts a path saved out to disk back into a form which can used by the application.
+def buildLoadPath(path):
+ result = path.replace('$MARI_COLOR_PATH', mari.resources.path(mari.resources.COLOR), 1)
+ return result
+
+##############################################################################################
+
+if mari.app.isRunning():
+ if PyOpenColorIO is not None:
+ # Attempt to load the default configuration file... without it we can't do nothing!
+ config_file_lists = [config_file_list_default, CONFIG_FILE_LIST_RESET]
+ for config_file_list in config_file_lists:
+ if not config_file_list.isEmpty():
+ config_default = loadConfig(config_file_list.at(0), False)
+ if config_default is not None:
+ config_file_list_default = mari.FileList(config_file_list)
+ break
+
+ if config_default is not None:
+ _loadPreferences()
+ _registerPreferences()
+ _savePreferences()
+
+ else:
+ message = 'Failed to find a working configuration file. OpenColorIO will be disabled!'
+ printMessage(MessageType.ERROR, message)
+ if not mari.app.inTerminalMode():
+ mari.utils.misc.message(message, 'OpenColorIO', 1024, 3)
diff --git a/src/mari/prototype/README b/src/mari/prototype/README
new file mode 100644
index 0000000..514cd65
--- /dev/null
+++ b/src/mari/prototype/README
@@ -0,0 +1,3 @@
+This is a prototype implemetation for a python display integration, which worked
+in early Mari versions. It's provided as a simple example of how to use the
+OCIO python API to query the GPU interface functions.
diff --git a/src/mari/prototype/ociodisplay.py b/src/mari/prototype/ociodisplay.py
new file mode 100644
index 0000000..5b0b949
--- /dev/null
+++ b/src/mari/prototype/ociodisplay.py
@@ -0,0 +1,242 @@
+"""
+This script allows the use of OpenColorIO display transforms (3d luts) in
+the Mari Viewer. Requires Mari 1.3v2+.
+
+This example is not represntative of the final Mari OCIO workflow, merely
+an API demonstration. This code is a work in progress, to demonstrate the
+integration of OpenColorIO and Mari. The APIs this code relies on are subject
+to change at any time, and as such should not be relied on for production use
+(yet).
+
+LINUX testing instructions:
+
+* Build OCIO
+mkdir -p dist_mari
+mkdir -p build_mari && cd build_mari
+cmake -D CMAKE_BUILD_TYPE=Release \
+ -D CMAKE_INSTALL_PREFIX=../dist_mari \
+ -D PYTHON=/usr/bin/python2.6 \
+ -D OCIO_NAMESPACE=OpenColorIO_Mari \
+ ../
+make install -j8
+
+* Set $OCIO color environment
+setenv OCIO setenv OCIO <YOURDIR>/ocio.configs/spi-vfx/config.ocio
+(Profiles available for download from opencolorio.org)
+
+* Run Mari with OpenColorIO added to the LD_LIBRARY_PATH, and Python
+env LD_LIBRARY_PATH=<YOURDIR>/dist_mari/lib/ PYTHONPATH=<YOURDIR>/dist_mari/lib/python2.6 mari
+
+* Source this script in the python console.
+Also - IMPORTANT - you must enable 'Use Color Correction' in the Color Manager.
+
+"""
+
+import mari, time, PythonQt
+QtGui = PythonQt.QtGui
+QtCore = PythonQt.QtCore
+
+try:
+ import PyOpenColorIO as OCIO
+ mari.app.log("OCIODisplay: %s" % OCIO.__file__)
+except Exception,e:
+ OCIO = None
+ mari.app.log("OCIODisplay: Error: Could not import OpenColorIO python bindings.")
+ mari.app.log("OCIODisplay: Please confirm PYTHONPATH has dir containing PyOpenColorIO.so")
+
+__all__ = [ 'OCIO', 'CreateOCIODisplayTransform', 'OCIODisplayUI']
+
+LUT3D_SIZE = 32
+WINDOW_NAME = "OpenColorIO Display Manager"
+CREATE_FLOATING = True
+
+
+class OCIODisplayUI(QtGui.QWidget):
+ def __init__(self):
+ QtGui.QWidget.__init__(self)
+ QtGui.QGridLayout(self)
+ self.setWindowTitle(WINDOW_NAME)
+ self.setMinimumWidth(300)
+
+ config = OCIO.GetCurrentConfig()
+
+ self.__inputColorSpace = OCIO.Constants.ROLE_DEFAULT
+ inputColorSpaces = [ OCIO.Constants.ROLE_TEXTURE_PAINT,
+ 'dt8',
+ OCIO.Constants.ROLE_SCENE_LINEAR ]
+ for cs in inputColorSpaces:
+ if config.getColorSpace(cs) is None: continue
+ self.__inputColorSpace = cs
+ break
+
+ self.__fStopOffset = 0.0
+ self.__viewGamma = 1.0
+ self.__swizzle = (True, True, True, True)
+
+ self.__filter_cacheID = None
+ self.__filter = None
+ self.__texture3d_cacheID = None
+ self.__counter_hack = 0
+
+ self.__buildUI()
+ self.__rebuildFilter()
+
+ def __buildUI(self):
+ config = OCIO.GetCurrentConfig()
+
+ self.layout().addWidget( QtGui.QLabel("Input Color Space", self), 0, 0)
+ csWidget = QtGui.QComboBox(self)
+ self.layout().addWidget( csWidget, 0, 1)
+ csIndex = None
+ for name in (cs.getName() for cs in config.getColorSpaces()):
+ csWidget.addItem(name)
+ if name == self.__inputColorSpace:
+ csIndex = csWidget.count - 1
+ if csIndex is not None:
+ csWidget.setCurrentIndex(csIndex)
+ csWidget.connect( QtCore.SIGNAL('currentIndexChanged(const QString &)'), self.__csChanged)
+
+
+ # This doesnt work until the Horizontal enum is exposed.
+ """
+ self.__fstopWidget_numStops = 3.0
+ self.__fstopWidget_ticksPerStop = 4
+
+ self.layout().addWidget( QtGui.QLabel("FStop", self), 1, 0)
+ fstopWidget = QtGui.QSlider(Horizontal, self)
+ self.layout().addWidget( fstopWidget, 1, 1)
+ fstopWidget.setMinimum(int(-self.__fstopWidget_numStops*self.__fstopWidget_ticksPerStop))
+ fstopWidget.setMaximum(int(self.__fstopWidget_numStops*self.__fstopWidget_ticksPerStop))
+ fstopWidget.setTickInterval(self.__fstopWidget_ticksPerStop)
+ """
+
+
+ def __csChanged(self, text):
+ text = str(text)
+ if text != self.__inputColorSpace:
+ self.__inputColorSpace = text
+ self.__rebuildFilter()
+
+ def __rebuildFilter(self):
+ config = OCIO.GetCurrentConfig()
+ display = config.getDefaultDisplay()
+ view = config.getDefaultView(display)
+ transform = CreateOCIODisplayTransform(config, self.__inputColorSpace,
+ display, view,
+ self.__swizzle,
+ self.__fStopOffset, self.__viewGamma)
+
+ processor = config.getProcessor(transform)
+
+ shaderDesc = dict( [('language', OCIO.Constants.GPU_LANGUAGE_GLSL_1_3),
+ ('functionName', 'display_ocio_$ID_'),
+ ('lut3DEdgeLen', LUT3D_SIZE)] )
+
+ filterCacheID = processor.getGpuShaderTextCacheID(shaderDesc)
+ if filterCacheID != self.__filter_cacheID:
+ self.__filter_cacheID = filterCacheID
+ mari.app.log("OCIODisplay: Creating filter %s" % self.__filter_cacheID)
+
+ desc = "sampler3D lut3d_ocio_$ID_;\n"
+ desc += processor.getGpuShaderText(shaderDesc)
+ body = "{ Out = display_ocio_$ID_(Out, lut3d_ocio_$ID_); }"
+
+ # Clear the existing color managment filter stack and create a new filter
+ # HACK: Increment a counter by 1 each time to force a refresh
+ #self.__counter_hack += 1
+ #name = "OCIO %s %s %s v%d" % (display, view, self.__inputColorSpace, self.__counter_hack)
+ name = "OCIO %s %s %s" % (display, view, self.__inputColorSpace)
+
+ self.__filter = None
+ self.__texture3d_cacheID = None
+
+ mari.gl_render.clearPostFilterStack()
+ self.__filter = mari.gl_render.createPostFilter(name, desc, body)
+ mari.gl_render.appendPostFilter(self.__filter)
+ else:
+ mari.app.log('OCIODisplay: no shader text update required')
+
+ texture3d_cacheID = processor.getGpuLut3DCacheID(shaderDesc)
+ if texture3d_cacheID != self.__texture3d_cacheID:
+ lut3d = processor.getGpuLut3D(shaderDesc)
+
+ mari.app.log("OCIODisplay: Updating 3dlut %s" % texture3d_cacheID)
+
+ if self.__texture3d_cacheID is None:
+ self.__filter.setTexture3D("lut3d_ocio_$ID_",
+ LUT3D_SIZE, LUT3D_SIZE, LUT3D_SIZE,
+ self.__filter.FORMAT_RGB, lut3d)
+ else:
+ self.__filter.updateTexture3D( "lut3d_ocio_$ID_", lut3d)
+
+ self.__texture3d_cacheID = texture3d_cacheID
+ else:
+ mari.app.log("OCIODisplay: No lut3d update required")
+
+
+
+def CreateOCIODisplayTransform(config,
+ inputColorSpace,
+ display, view,
+ swizzle,
+ fstopOffset, viewGamma):
+
+ displayTransform = OCIO.DisplayTransform()
+ displayTransform.setInputColorSpaceName( inputColorSpace )
+
+ displayColorSpace = config.getDisplayColorSpaceName(display, view)
+ displayTransform.setDisplayColorSpaceName( displayColorSpace )
+
+ # Add the channel sizzle
+ lumacoef = config.getDefaultLumaCoefs()
+ mtx, offset = OCIO.MatrixTransform.View(swizzle, lumacoef)
+
+ transform = OCIO.MatrixTransform()
+ transform.setValue(mtx, offset)
+ displayTransform.setChannelView(transform)
+
+ # Add the linear fstop gain
+ gain = 2**fstopOffset
+ mtx, offset = OCIO.MatrixTransform.Scale((gain,gain,gain,gain))
+ transform = OCIO.MatrixTransform()
+ transform.setValue(mtx, offset)
+ displayTransform.setLinearCC(transform)
+
+ # Add the post-display CC
+ transform = OCIO.ExponentTransform()
+ transform.setValue([1.0 / max(1e-6, v) for v in \
+ (viewGamma, viewGamma, viewGamma, viewGamma)])
+ displayTransform.setDisplayCC(transform)
+
+ return displayTransform
+
+"""
+SWIZZLE_COLOR = (True, True, True, True)
+SWIZZLE_RED = (True, False, False, False)
+SWIZZLE_GREEN = (False, True, False, False)
+SWIZZLE_BLUE = (False, False, True, False)
+SWIZZLE_ALPHA = (False, False, False, True)
+SWIZZLE_LUMA = (True, True, True, False)
+
+Timings
+
+OCIO Setup: 0.5 ms
+OCIO 3D Lut creation: 14.7 ms
+Mari Setup: 21.3 ms
+Mari Texture Upload: 44.2 ms
+"""
+
+
+if __name__ == '__main__':
+ if not hasattr(mari.gl_render,"createPostFilter"):
+ mari.app.log("OCIODisplay: Error: This version of Mari does not support the mari.gl_render.createPostFilter API")
+ else:
+ if OCIO is not None:
+ if CREATE_FLOATING:
+ w = OCIODisplayUI()
+ w.show()
+ else:
+ if WINDOW_NAME in mari.app.tabNames():
+ mari.app.removeTab(WINDOW_NAME)
+ w = OCIODisplayUI()
+ mari.app.addTab(WINDOW_NAME, w)
diff --git a/src/mari/prototype/ociofiletransform.py b/src/mari/prototype/ociofiletransform.py
new file mode 100644
index 0000000..318c656
--- /dev/null
+++ b/src/mari/prototype/ociofiletransform.py
@@ -0,0 +1,93 @@
+"""
+This script allows the loading of a specied lut (1d/3d/mtx) in
+the Mari Viewer. Requires Mari 1.3v2+.
+
+This example is not represntative of the final Mari OCIO workflow, merely
+an API demonstration. This code is a work in progress, to demonstrate the
+integration of OpenColorIO and Mari. The APIs this code relies on are subject
+to change at any time, and as such should not be relied on for production use
+(yet).
+
+LINUX testing instructions:
+
+* Build OCIO
+mkdir -p dist_mari
+mkdir -p build_mari && cd build_mari
+cmake -D CMAKE_BUILD_TYPE=Release \
+ -D CMAKE_INSTALL_PREFIX=../dist_mari \
+ -D PYTHON=/usr/bin/python2.6 \
+ -D OCIO_NAMESPACE=OpenColorIO_Mari \
+ ../
+make install -j8
+
+* Edit this file to point to use viewer lut you want to use
+
+* Run Mari with OpenColorIO added to the LD_LIBRARY_PATH, and Python
+env LD_LIBRARY_PATH=<YOURDIR>/dist_mari/lib/ PYTHONPATH=<YOURDIR>/dist_mari/lib/python2.6 mari
+
+* Source this script in the python console.
+Also - IMPORTANT - you must enable 'Use Color Correction' in the Color Manager.
+
+"""
+
+# YOU MUST CHANGE THIS TO MODIFY WHICH LUT TO USE
+LUT_FILENAME = "/shots/spi/home/lib/lut/dev/v29/luts/LC3DL_Kodak2383_Sony_GDM.3dl"
+LUT3D_SIZE = 32
+
+import mari, time, os
+
+try:
+ import PyOpenColorIO as OCIO
+ print OCIO.__file__
+except Exception,e:
+ print "Error: Could not import OpenColorIO python bindings."
+ print "Please confirm PYTHONPATH has dir containing PyOpenColorIO.so"
+
+def RegisterOCIOLut():
+ if not hasattr(mari.gl_render,"createPostFilter"):
+ print "Error: This version of Mari does not support the mari.gl_render.createPostFilter API"
+ return
+
+ config = OCIO.Config()
+ transform = OCIO.FileTransform(src = os.path.realpath(LUT_FILENAME),
+ interpolation = OCIO.Constants.INTERP_LINEAR,
+ direction = OCIO.Constants.TRANSFORM_DIR_FORWARD)
+ processor = config.getProcessor(transform)
+
+ shaderDesc = dict( [('language', OCIO.Constants.GPU_LANGUAGE_GLSL_1_3),
+ ('functionName', 'display_ocio_$ID_'),
+ ('lut3DEdgeLen', LUT3D_SIZE)] )
+ shaderText = processor.getGpuShaderText(shaderDesc)
+
+ lut3d = processor.getGpuLut3D(shaderDesc)
+
+ # Clear the existing color managment filter stack
+ mari.gl_render.clearPostFilterStack()
+
+ # Create variable pre-declarations
+ desc = "sampler3D lut3d_ocio_$ID_;\n"
+ desc += shaderText
+
+ # Set the body of the filter
+ body = "{ Out = display_ocio_$ID_(Out, lut3d_ocio_$ID_); }"
+
+ # HACK: Increment a counter by 1 each time to force a refresh
+ if not hasattr(mari, "ocio_lut_counter_hack"):
+ mari.ocio_lut_counter_hack = 0
+ else:
+ mari.ocio_lut_counter_hack += 1
+ ocio_lut_counter_hack = mari.ocio_lut_counter_hack
+
+ # Create a new filter
+ name = "OCIO %s v%d" % (os.path.basename(LUT_FILENAME), ocio_lut_counter_hack)
+ postfilter = mari.gl_render.createPostFilter(name, desc, body)
+
+ # Set the texture to use for the given sampler on this filter
+ postfilter.setTexture3D("lut3d_ocio_$ID_",
+ LUT3D_SIZE, LUT3D_SIZE, LUT3D_SIZE,
+ postfilter.FORMAT_RGB, lut3d)
+
+ # Append the filter to the end of the current list of filters
+ mari.gl_render.appendPostFilter(postfilter)
+
+RegisterOCIOLut()
diff --git a/src/nuke/CMakeLists.txt b/src/nuke/CMakeLists.txt
new file mode 100644
index 0000000..81b2cd5
--- /dev/null
+++ b/src/nuke/CMakeLists.txt
@@ -0,0 +1,138 @@
+if(APPLE)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -undefined dynamic_lookup")
+endif()
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${Nuke_INCLUDE_DIR}
+)
+
+###############################################################################
+### NukeOCIOColorSpace ###
+
+add_library(NukeOCIOColorSpace MODULE
+ OCIOColorSpace/OCIOColorSpace.cpp
+)
+target_link_libraries(NukeOCIOColorSpace
+ OpenColorIO
+ #${Nuke_LIBRARIES}
+)
+set_target_properties(NukeOCIOColorSpace
+ PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "OCIOColorSpace"
+)
+
+###############################################################################
+### NukeOCIODisplay ###
+
+add_library(NukeOCIODisplay MODULE
+ OCIODisplay/OCIODisplay.cpp
+)
+target_link_libraries(NukeOCIODisplay
+ OpenColorIO
+ #${Nuke_LIBRARIES}
+)
+set_target_properties(NukeOCIODisplay
+ PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "OCIODisplay"
+)
+
+###############################################################################
+### NukeOCIOFileTransform ###
+
+add_library(NukeOCIOFileTransform MODULE
+ OCIOFileTransform/OCIOFileTransform.cpp
+)
+target_link_libraries(NukeOCIOFileTransform
+ OpenColorIO
+ #${Nuke_LIBRARIES}
+)
+set_target_properties(NukeOCIOFileTransform
+ PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "OCIOFileTransform"
+)
+
+###############################################################################
+### NukeOCIOLogConvert ###
+
+add_library(NukeOCIOLogConvert MODULE
+ OCIOLogConvert/OCIOLogConvert.cpp
+)
+target_link_libraries(NukeOCIOLogConvert
+ OpenColorIO
+ #${Nuke_LIBRARIES}
+)
+set_target_properties(NukeOCIOLogConvert
+ PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "OCIOLogConvert"
+)
+
+###############################################################################
+### NukeOCIOLookTransform ###
+
+add_library(NukeOCIOLookTransform MODULE
+ OCIOLookTransform/OCIOLookTransform.cpp
+)
+target_link_libraries(NukeOCIOLookTransform
+ OpenColorIO
+ #${Nuke_LIBRARIES}
+)
+set_target_properties(NukeOCIOLookTransform
+ PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "OCIOLookTransform"
+)
+
+###############################################################################
+### NukeOCIOCDLTransform ###
+
+add_library(NukeOCIOCDLTransform MODULE
+ OCIOCDLTransform/OCIOCDLTransform.cpp
+)
+target_link_libraries(NukeOCIOCDLTransform
+ OpenColorIO
+ #${Nuke_LIBRARIES}
+)
+set_target_properties(NukeOCIOCDLTransform
+ PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "OCIOCDLTransform"
+)
+
+###############################################################################
+### Nuke Targets ###
+
+add_custom_target(Nuke
+ DEPENDS NukeOCIOColorSpace
+ DEPENDS NukeOCIODisplay
+ DEPENDS NukeOCIOFileTransform
+ DEPENDS NukeOCIOLogConvert
+ DEPENDS NukeOCIOCDLTransform
+)
+
+install(TARGETS NukeOCIOColorSpace
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib/nuke${Nuke_API_VERSION})
+
+install(TARGETS NukeOCIODisplay
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib/nuke${Nuke_API_VERSION})
+
+install(TARGETS NukeOCIOLogConvert
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib/nuke${Nuke_API_VERSION})
+
+install(TARGETS NukeOCIOFileTransform
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib/nuke${Nuke_API_VERSION})
+
+install(TARGETS NukeOCIOLookTransform
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib/nuke${Nuke_API_VERSION})
+
+install(TARGETS NukeOCIOCDLTransform
+ DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/lib/nuke${Nuke_API_VERSION})
+
+install(DIRECTORY ${CMAKE_SOURCE_DIR}/share/nuke
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/
+ PATTERN .svn EXCLUDE)
diff --git a/src/nuke/OCIOCDLTransform/OCIOCDLTransform.cpp b/src/nuke/OCIOCDLTransform/OCIOCDLTransform.cpp
new file mode 100644
index 0000000..51ec866
--- /dev/null
+++ b/src/nuke/OCIOCDLTransform/OCIOCDLTransform.cpp
@@ -0,0 +1,387 @@
+/**
+ * OpenColorIO conversion Iop.
+ */
+
+#include "OCIOCDLTransform.h"
+
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <DDImage/Channel.h>
+#include <DDImage/PixelIop.h>
+#include <DDImage/NukeWrapper.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knobs.h>
+
+
+const char* OCIOCDLTransform::dirs[] = { "forward", "inverse", 0 };
+
+OCIOCDLTransform::OCIOCDLTransform(Node *n) : DD::Image::PixelIop(n)
+{
+ for (int i = 0; i < 3; i++){
+ m_slope[i] = 1.0;
+ m_offset[i] = 0.0;
+ m_power[i] = 1.0;
+ }
+
+ m_saturation = 1.0;
+ m_readFromFile = false;
+ m_dirindex = 0;
+ m_file = NULL;
+ m_reload_version = 1;
+
+ m_slopeKnob = NULL;
+ m_offsetKnob = NULL;
+ m_powerKnob = NULL;
+ m_saturationKnob = NULL;
+ m_fileKnob = NULL;
+ m_cccidKnob = NULL;
+
+ m_firstLoad = true;
+}
+
+OCIOCDLTransform::~OCIOCDLTransform()
+{
+
+}
+
+void OCIOCDLTransform::knobs(DD::Image::Knob_Callback f)
+{
+ // ASC CDL grade numbers
+ m_slopeKnob = DD::Image::Color_knob(f, m_slope, DD::Image::IRange(0, 4.0), "slope");
+ m_offsetKnob = DD::Image::Color_knob(f, m_offset, DD::Image::IRange(-0.2, 0.2), "offset");
+ m_powerKnob = DD::Image::Color_knob(f, m_power, DD::Image::IRange(0.0, 4.0), "power");
+ m_saturationKnob = DD::Image::Float_knob(f, &m_saturation, DD::Image::IRange(0, 4.0), "saturation");
+
+ Enumeration_knob(f, &m_dirindex, dirs, "direction", "direction");
+ DD::Image::Tooltip(f, "Specify the transform direction.");
+
+ DD::Image::Divider(f);
+
+ DD::Image::Bool_knob(f, &m_readFromFile, "read_from_file", "read from file");
+ DD::Image::SetFlags(f, DD::Image::Knob::EARLY_STORE);
+ DD::Image::Tooltip(f, "Load color correction information from the .cc or .ccc file.");
+
+ m_fileKnob = File_knob(f, &m_file, "file", "file");
+ const char * filehelp = "Specify the src ASC CDL file, on disk, to use for this transform. "
+ "This can be either a .cc or .ccc file. If .ccc is specified, the cccid is required.";
+ DD::Image::Tooltip(f, filehelp);
+
+ // Reload button, and hidden "version" knob to invalidate cache on reload
+ Button(f, "reload", "reload");
+ DD::Image::Tooltip(f, "Reloads specified files");
+ Int_knob(f, &m_reload_version, "version");
+ DD::Image::SetFlags(f, DD::Image::Knob::HIDDEN);
+
+ DD::Image::SetFlags(f, DD::Image::Knob::ENDLINE);
+
+ m_cccidKnob = String_knob(f, &m_cccid, "cccid");
+ const char * ccchelp = "If the source file is an ASC CDL CCC (color correction collection), "
+ "this specifies the id to lookup. OpenColorIO::Contexts (envvars) are obeyed.";
+ DD::Image::Tooltip(f, ccchelp);
+
+ /* TODO:
+ These scripts should be updated to make use of native OCIO APIs, rather than convenience functions
+ exposed in ocionuke. Ideally, ocionuke would be a minimal module (essentially only ui code) that makes
+ use of OCIO for all heavy lifting.
+ */
+
+ DD::Image::PyScript_knob(f, "import ocionuke.cdl; ocionuke.cdl.select_cccid_for_filetransform()", "select_cccid", "select cccid");
+
+ // Import/export buttons
+ DD::Image::PyScript_knob(f, "import ocionuke.cdl; ocionuke.cdl.export_as_cc()", "export_cc", "export grade as .cc");
+ DD::Image::Tooltip(f, "Export this grade as a ColorCorrection XML file, which can be loaded with the OCIOFileTransform, or using a FileTransform in an OCIO config");
+
+ DD::Image::PyScript_knob(f, "import ocionuke.cdl; ocionuke.cdl.import_cc_from_xml()", "import_cc", "import from .cc");
+ DD::Image::Tooltip(f, "Import grade from a ColorCorrection XML file");
+
+
+ DD::Image::Divider(f);
+
+ /*
+ TODO: One thing thats sucks is that we dont apparently have a mechansism to call refreshKnobEnabledState
+ after the knobs have been loaded, but before scripts have a chance to run. I'd love to have a post-knob
+ finalize callback opportunity to reload the cdl from file, if needed. The current system will only do the
+ initial file refresh when either the ui is loaded, or a render is triggered.
+ */
+
+ if(!f.makeKnobs() && m_firstLoad)
+ {
+ m_firstLoad = false;
+ refreshKnobEnabledState();
+ if(m_readFromFile) loadCDLFromFile();
+ }
+}
+
+void OCIOCDLTransform::refreshKnobEnabledState()
+{
+ if(m_readFromFile)
+ {
+ m_slopeKnob->disable();
+ m_offsetKnob->disable();
+ m_powerKnob->disable();
+ m_saturationKnob->disable();
+
+ // We leave these active to allow knob re-use with the import/export buttons
+ //m_fileKnob->enable();
+ //m_cccidKnob->enable();
+
+ loadCDLFromFile();
+ }
+ else
+ {
+ m_slopeKnob->enable();
+ m_offsetKnob->enable();
+ m_powerKnob->enable();
+ m_saturationKnob->enable();
+
+ // We leave these active to allow knob re-use with the import/export buttons
+ //m_fileKnob->disable();
+ //m_cccidKnob->disable();
+ }
+}
+
+void OCIOCDLTransform::append(DD::Image::Hash& nodehash)
+{
+ // There is a bug where in Nuke <6.3 the String_knob (used for
+ // cccid) is not included in the node's hash. Include it manually
+ // so the node correctly redraws. Appears fixed in in 6.3
+ nodehash.append(m_cccid.c_str());
+
+ // Incremented to force reloading after rereading the LUT file
+ nodehash.append(m_reload_version);
+}
+
+int OCIOCDLTransform::knob_changed(DD::Image::Knob* k)
+{
+ // return true if you want to continue to receive changes for this knob
+ std::string knobname = k->name();
+
+ if(knobname == "read_from_file")
+ {
+ refreshKnobEnabledState();
+
+ if(m_readFromFile)
+ {
+ loadCDLFromFile();
+ }
+ return true;
+ }
+ else if(knobname == "file")
+ {
+ if(m_readFromFile)
+ {
+ loadCDLFromFile();
+ }
+ return true;
+ }
+
+ else if(knobname == "reload")
+ {
+ knob("version")->set_value(m_reload_version+1);
+ OCIO::ClearAllCaches();
+ m_firstLoad = true;
+
+ return true; // ensure callback is triggered again
+ }
+
+ return false;
+}
+
+// Check to see if file exists
+// read from file
+// set knob values
+// throw an error if anything goes wrong
+
+void OCIOCDLTransform::loadCDLFromFile()
+{
+ OCIO::CDLTransformRcPtr transform;
+
+ try
+ {
+ // This is inexpensive to call multiple times, as OCIO caches results
+ // internally.
+ transform = OCIO::CDLTransform::CreateFromFile(m_file, m_cccid.c_str());
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+
+
+ float sop[9];
+ transform->getSOP(sop);
+
+ m_slopeKnob->clear_animated(-1);
+ m_slopeKnob->set_value(sop[0], 0);
+ m_slopeKnob->set_value(sop[1], 1);
+ m_slopeKnob->set_value(sop[2], 2);
+
+ m_offsetKnob->clear_animated(-1);
+ m_offsetKnob->set_value(sop[3], 0);
+ m_offsetKnob->set_value(sop[4], 1);
+ m_offsetKnob->set_value(sop[5], 2);
+
+ m_powerKnob->clear_animated(-1);
+ m_powerKnob->set_value(sop[6], 0);
+ m_powerKnob->set_value(sop[7], 1);
+ m_powerKnob->set_value(sop[8], 2);
+
+ m_saturationKnob->clear_animated(-1);
+ m_saturationKnob->set_value(transform->getSat());
+}
+
+void OCIOCDLTransform::_validate(bool for_real)
+{
+ if(m_firstLoad)
+ {
+ m_firstLoad = false;
+ if(m_readFromFile) loadCDLFromFile();
+ }
+
+ // We must explicitly refresh the enable state here as well,
+ // as there are some changes (such as expressioned knob updates)
+ // that wont trigger the knob_changed callback. This allows
+ // us to catch these here.
+
+ refreshKnobEnabledState();
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ OCIO::CDLTransformRcPtr cc = OCIO::CDLTransform::Create();
+ cc->setSlope(m_slope);
+ cc->setOffset(m_offset);
+ cc->setPower(m_power);
+ cc->setSat(m_saturation);
+
+ if(m_dirindex == 0) cc->setDirection(OCIO::TRANSFORM_DIR_FORWARD);
+ else cc->setDirection(OCIO::TRANSFORM_DIR_INVERSE);
+
+ m_processor = config->getProcessor(cc);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+
+ if(m_processor->isNoOp())
+ {
+ set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
+ } else {
+ set_out_channels(DD::Image::Mask_All);
+ }
+
+ DD::Image::PixelIop::_validate(for_real);
+}
+
+// Note that this is copied by others (OCIODisplay)
+void OCIOCDLTransform::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
+{
+ DD::Image::ChannelSet done;
+ foreach(c, mask)
+ {
+ if (DD::Image::colourIndex(c) < 3 && !(done & c))
+ {
+ done.addBrothers(c, 3);
+ }
+ }
+ mask += done;
+}
+
+// See Saturation::pixel_engine for a well-commented example.
+// Note that this is copied by others (OCIODisplay)
+void OCIOCDLTransform::pixel_engine(
+ const DD::Image::Row& in,
+ int /* rowY unused */, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out)
+{
+ int rowWidth = rowXBound - rowX;
+
+ DD::Image::ChannelSet done;
+ foreach (requestedChannel, outputChannels)
+ {
+ // Skip channels which had their trios processed already,
+ if (done & requestedChannel)
+ {
+ continue;
+ }
+
+ // Pass through channels which are not selected for processing
+ // and non-rgb channels.
+ if (colourIndex(requestedChannel) >= 3)
+ {
+ out.copy(in, requestedChannel, rowX, rowXBound);
+ continue;
+ }
+
+ DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
+ DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
+ DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
+
+ done += rChannel;
+ done += gChannel;
+ done += bChannel;
+
+ const float *rIn = in[rChannel] + rowX;
+ const float *gIn = in[gChannel] + rowX;
+ const float *bIn = in[bChannel] + rowX;
+
+ float *rOut = out.writable(rChannel) + rowX;
+ float *gOut = out.writable(gChannel) + rowX;
+ float *bOut = out.writable(bChannel) + rowX;
+
+ // OCIO modifies in-place
+ // Note: xOut can equal xIn in some circumstances, such as when the
+ // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
+ // which does not allow for overlapping regions.
+ if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
+ if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
+ if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
+
+ try
+ {
+ OCIO::PlanarImageDesc img(rOut, gOut, bOut, NULL, rowWidth, /*height*/ 1);
+ m_processor->apply(img);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+ }
+}
+
+const DD::Image::Op::Description OCIOCDLTransform::description("OCIOCDLTransform", build);
+
+const char* OCIOCDLTransform::Class() const
+{
+ return description.name;
+}
+
+const char* OCIOCDLTransform::displayName() const
+{
+ return description.name;
+}
+
+const char* OCIOCDLTransform::node_help() const
+{
+ // TODO more detailed help text
+ return "Use OpenColorIO to apply an ASC CDL grade. Applied using:\n\n"\
+ "out = (i * s + o)^p\n\nWhere i is the input value, s is slope, "\
+ "o is offset and p is power";
+}
+
+
+DD::Image::Op* build(Node *node)
+{
+ DD::Image::NukeWrapper *op = new DD::Image::NukeWrapper(new OCIOCDLTransform(node));
+ op->channels(DD::Image::Mask_RGB);
+ return op;
+}
diff --git a/src/nuke/OCIOCDLTransform/OCIOCDLTransform.h b/src/nuke/OCIOCDLTransform/OCIOCDLTransform.h
new file mode 100644
index 0000000..6b7cc66
--- /dev/null
+++ b/src/nuke/OCIOCDLTransform/OCIOCDLTransform.h
@@ -0,0 +1,137 @@
+#ifndef INCLUDED_OCIO_NUKE_CDLTRANSFORM_H_
+#define INCLUDED_OCIO_NUKE_CDLTRANSFORM_H_
+
+// Include these early, for Nuke's headers under gcc 4.4.2.
+#include <memory>
+#include <cstdarg>
+
+#include <DDImage/PixelIop.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knob.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+/*!
+ * Iop that uses OpenColorIO to apply an ASC CDL transform
+ */
+class OCIOCDLTransform : public DD::Image::PixelIop {
+
+ protected:
+
+ // ASC CDL grade numbers
+ float m_slope[3];
+ float m_offset[3];
+ float m_power[3];
+ float m_saturation;
+
+ static const char* dirs[];
+ int m_dirindex;
+
+ bool m_readFromFile;
+
+ // ID used for exporting grades into .cc/.ccc files
+ const char* m_file;
+ std::string m_cccid;
+
+ DD::Image::Knob* m_slopeKnob;
+ DD::Image::Knob* m_offsetKnob;
+ DD::Image::Knob* m_powerKnob;
+ DD::Image::Knob* m_saturationKnob;
+ DD::Image::Knob* m_fileKnob;
+ DD::Image::Knob* m_cccidKnob;
+
+ OCIO::ConstProcessorRcPtr m_processor;
+ bool m_firstLoad;
+
+ /*! Controlled by hidden "version" knob, incremented to redraw image */
+ int m_reload_version;
+
+ public:
+ OCIOCDLTransform(Node *node);
+
+ virtual ~OCIOCDLTransform();
+
+ static const DD::Image::Op::Description description;
+
+ /*! Return the command name that will be stored in Nuke scripts. */
+ virtual const char *Class() const;
+
+ /*!
+ * Return a name for this class that will be shown to the user. The
+ * default implementation returns Class(). You can return a different
+ * (ie more user-friendly) name instead here, and there is no need for
+ * this to be unique.
+ *
+ * Nuke currently will remove any trailing digits and underscores from
+ * this and add a new number to make a unique name for the new node.
+ *
+ * \return "OCIOCDLTransform"
+ */
+ virtual const char *displayName() const;
+
+ /*!
+ * Return help information for this node. This information is in the
+ * pop-up window that the user gets when they hit the [?] button in
+ * the lower-left corner of the control panel.
+ */
+ virtual const char *node_help() const;
+
+ /*!
+ * Define the knobs that will be presented in the control panel.
+ */
+ virtual void knobs(DD::Image::Knob_Callback f);
+
+ //! The will handle the knob changes.
+ virtual int knob_changed(DD::Image::Knob*);
+
+ void refreshKnobEnabledState();
+ void loadCDLFromFile();
+
+
+ /*!
+ * Specify the channels required from input n to produce the channels
+ * in mask by modifying mask in-place. (At least one channel in the
+ * input is assumed.)
+ *
+ * Since OCIOCDLTransform conversions can have channel cross-talk, any rgb
+ * output channel requires all its rgb bretheren. (Non-rgb
+ * are passed through.)
+ */
+ virtual void in_channels(int n, DD::Image::ChannelSet& mask) const;
+
+ /*!
+ * Calculate the output pixel data.
+ * \param rowY vertical line number
+ * \param rowX inclusive left bound
+ * \param rowXBound exclusive right bound
+ * \param outputChannels a subset of out_channels(), the required channels to be produced
+ */
+ virtual void pixel_engine(
+ const DD::Image::Row& in,
+ int rowY, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out);
+
+
+ protected:
+
+ /*!
+ * Check that colorspaces are available, and that the transform
+ * is not a noop. (As OCIO whether a given transform is a noop, since it
+ * can do more analysis than just name matching.)
+ */
+ virtual void _validate(bool for_real);
+
+ /*!
+ * Ensure Node hash is reflects all parameters
+ */
+ void append(DD::Image::Hash& nodehash);
+
+};
+
+
+static DD::Image::Op* build(Node *node);
+
+#endif // INCLUDED_OCIO_NUKE_CDLTRANSFORM_H_
diff --git a/src/nuke/OCIOColorSpace/OCIOColorSpace.cpp b/src/nuke/OCIOColorSpace/OCIOColorSpace.cpp
new file mode 100644
index 0000000..091c1ef
--- /dev/null
+++ b/src/nuke/OCIOColorSpace/OCIOColorSpace.cpp
@@ -0,0 +1,376 @@
+/**
+ * OpenColorIO ColorSpace Iop.
+ */
+
+#include "OCIOColorSpace.h"
+
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <DDImage/Channel.h>
+#include <DDImage/PixelIop.h>
+#include <DDImage/NukeWrapper.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knobs.h>
+#include <DDImage/ddImageVersionNumbers.h>
+
+// Should we use cascasing ColorSpace menus
+#if defined kDDImageVersionInteger && (kDDImageVersionInteger>=62300)
+#define OCIO_CASCADE
+#endif
+
+OCIOColorSpace::OCIOColorSpace(Node *n) : DD::Image::PixelIop(n)
+{
+ m_hasColorSpaces = false;
+
+ m_inputColorSpaceIndex = 0;
+ m_outputColorSpaceIndex = 0;
+
+ // Query the color space names from the current config
+ // TODO (when to) re-grab the list of available color spaces? How to save/load?
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ OCIO::ConstColorSpaceRcPtr defaultcs = config->getColorSpace(OCIO::ROLE_SCENE_LINEAR);
+ if(!defaultcs) throw std::runtime_error("ROLE_SCENE_LINEAR not defined.");
+ std::string defaultColorSpaceName = defaultcs->getName();
+
+ for(int i = 0; i < config->getNumColorSpaces(); i++)
+ {
+ std::string csname = config->getColorSpaceNameByIndex(i);
+
+#ifdef OCIO_CASCADE
+ std::string family = config->getColorSpace(csname.c_str())->getFamily();
+ if(family.empty())
+ m_colorSpaceNames.push_back(csname.c_str());
+ else
+ m_colorSpaceNames.push_back(family + "/" + csname);
+#else
+ m_colorSpaceNames.push_back(csname);
+#endif
+
+ if(csname == defaultColorSpaceName)
+ {
+ m_inputColorSpaceIndex = i;
+ m_outputColorSpaceIndex = i;
+ }
+ }
+ }
+ catch (OCIO::Exception& e)
+ {
+ std::cerr << "OCIOColorSpace: " << e.what() << std::endl;
+ }
+ catch (...)
+ {
+ std::cerr << "OCIOColorSpace: Unknown exception during OCIO setup." << std::endl;
+ }
+
+ // Then, create a cstr array for passing to Nuke
+ // This must be done in a second pass, lest the original m_colorSpaceNames
+ // std::string be reallocated in the interim
+ for(unsigned int i=0; i<m_colorSpaceNames.size(); ++i)
+ {
+ m_inputColorSpaceCstrNames.push_back(m_colorSpaceNames[i].c_str());
+ m_outputColorSpaceCstrNames.push_back(m_colorSpaceNames[i].c_str());
+ }
+
+ m_inputColorSpaceCstrNames.push_back(NULL);
+ m_outputColorSpaceCstrNames.push_back(NULL);
+
+ m_hasColorSpaces = (!m_colorSpaceNames.empty());
+
+ if(!m_hasColorSpaces)
+ {
+ std::cerr << "OCIOColorSpace: No color spaces available for input and/or output." << std::endl;
+ }
+}
+
+OCIOColorSpace::~OCIOColorSpace()
+{
+
+}
+
+void OCIOColorSpace::knobs(DD::Image::Knob_Callback f)
+{
+#ifdef OCIO_CASCADE
+ DD::Image::CascadingEnumeration_knob(f,
+ &m_inputColorSpaceIndex, &m_inputColorSpaceCstrNames[0], "in_colorspace", "in");
+ DD::Image::Tooltip(f, "Input data is taken to be in this color space.");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+
+ DD::Image::CascadingEnumeration_knob(f,
+ &m_outputColorSpaceIndex, &m_outputColorSpaceCstrNames[0], "out_colorspace", "out");
+ DD::Image::Tooltip(f, "Image data is converted to this color space for output.");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+#else
+ DD::Image::Enumeration_knob(f,
+ &m_inputColorSpaceIndex, &m_inputColorSpaceCstrNames[0], "in_colorspace", "in");
+ DD::Image::Tooltip(f, "Input data is taken to be in this color space.");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+
+ DD::Image::Enumeration_knob(f,
+ &m_outputColorSpaceIndex, &m_outputColorSpaceCstrNames[0], "out_colorspace", "out");
+ DD::Image::Tooltip(f, "Image data is converted to this color space for output.");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+#endif
+
+}
+
+OCIO::ConstContextRcPtr OCIOColorSpace::getLocalContext()
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ OCIO::ConstContextRcPtr context = config->getCurrentContext();
+ OCIO::ContextRcPtr mutableContext;
+
+ if(!m_contextKey1.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey1.c_str(), m_contextValue1.c_str());
+ }
+ if(!m_contextKey2.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey2.c_str(), m_contextValue2.c_str());
+ }
+ if(!m_contextKey3.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey3.c_str(), m_contextValue3.c_str());
+ }
+ if(!m_contextKey4.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey4.c_str(), m_contextValue4.c_str());
+ }
+
+ if(mutableContext) context = mutableContext;
+ return context;
+}
+
+void OCIOColorSpace::append(DD::Image::Hash& localhash)
+{
+ // TODO: Hang onto the context, what if getting it
+ // (and querying getCacheID) is expensive?
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ OCIO::ConstContextRcPtr context = getLocalContext();
+ std::string configCacheID = config->getCacheID(context);
+ localhash.append(configCacheID);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+}
+
+void OCIOColorSpace::_validate(bool for_real)
+{
+ if(!m_hasColorSpaces)
+ {
+ error("No color spaces available for input and/or output.");
+ return;
+ }
+
+ int inputColorSpaceCount = static_cast<int>(m_inputColorSpaceCstrNames.size()) - 1;
+ if(m_inputColorSpaceIndex < 0 || m_inputColorSpaceIndex >= inputColorSpaceCount)
+ {
+ std::ostringstream err;
+ err << "Input color space index (" << m_inputColorSpaceIndex << ") out of range.";
+ error(err.str().c_str());
+ return;
+ }
+
+ int outputColorSpaceCount = static_cast<int>(m_outputColorSpaceCstrNames.size()) - 1;
+ if(m_outputColorSpaceIndex < 0 || m_outputColorSpaceIndex >= outputColorSpaceCount)
+ {
+ std::ostringstream err;
+ err << "Output color space index (" << m_outputColorSpaceIndex << ") out of range.";
+ error(err.str().c_str());
+ return;
+ }
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ const char * inputName = config->getColorSpaceNameByIndex(m_inputColorSpaceIndex);
+ const char * outputName = config->getColorSpaceNameByIndex(m_outputColorSpaceIndex);
+
+ OCIO::ConstContextRcPtr context = getLocalContext();
+ m_processor = config->getProcessor(context, inputName, outputName);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+
+ if(m_processor->isNoOp())
+ {
+ set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
+ } else {
+ set_out_channels(DD::Image::Mask_All);
+ }
+
+ DD::Image::PixelIop::_validate(for_real);
+}
+
+// Note that this is copied by others (OCIODisplay)
+void OCIOColorSpace::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
+{
+ DD::Image::ChannelSet done;
+ foreach(c, mask)
+ {
+ if (DD::Image::colourIndex(c) < 3 && !(done & c))
+ {
+ done.addBrothers(c, 3);
+ }
+ }
+ mask += done;
+}
+
+// See Saturation::pixel_engine for a well-commented example.
+// Note that this is copied by others (OCIODisplay)
+void OCIOColorSpace::pixel_engine(
+ const DD::Image::Row& in,
+ int /* rowY unused */, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out)
+{
+ int rowWidth = rowXBound - rowX;
+
+ DD::Image::ChannelSet done;
+ foreach (requestedChannel, outputChannels)
+ {
+ // Skip channels which had their trios processed already,
+ if (done & requestedChannel)
+ {
+ continue;
+ }
+
+ // Pass through channels which are not selected for processing
+ // and non-rgb channels.
+ if (colourIndex(requestedChannel) >= 3)
+ {
+ out.copy(in, requestedChannel, rowX, rowXBound);
+ continue;
+ }
+
+ DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
+ DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
+ DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
+
+ done += rChannel;
+ done += gChannel;
+ done += bChannel;
+
+ const float *rIn = in[rChannel] + rowX;
+ const float *gIn = in[gChannel] + rowX;
+ const float *bIn = in[bChannel] + rowX;
+
+ float *rOut = out.writable(rChannel) + rowX;
+ float *gOut = out.writable(gChannel) + rowX;
+ float *bOut = out.writable(bChannel) + rowX;
+
+ // OCIO modifies in-place
+ // Note: xOut can equal xIn in some circumstances, such as when the
+ // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
+ // which does not allow for overlapping regions.
+ if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
+ if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
+ if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
+
+ try
+ {
+ OCIO::PlanarImageDesc img(rOut, gOut, bOut, NULL, rowWidth, /*height*/ 1);
+ m_processor->apply(img);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+ }
+}
+
+const DD::Image::Op::Description OCIOColorSpace::description("OCIOColorSpace", build);
+
+const char* OCIOColorSpace::Class() const
+{
+ return description.name;
+}
+
+const char* OCIOColorSpace::displayName() const
+{
+ return description.name;
+}
+
+const char* OCIOColorSpace::node_help() const
+{
+ // TODO more detailed help text
+ return "Use OpenColorIO to convert from one color space to another.";
+}
+
+// This class is necessary in order to call knobsAtTheEnd(). Otherwise, the NukeWrapper knobs
+// will be added to the Context tab instead of the primary tab.
+class OCIOColorSpaceNukeWrapper : public DD::Image::NukeWrapper
+{
+public:
+ OCIOColorSpaceNukeWrapper(DD::Image::PixelIop* op) : DD::Image::NukeWrapper(op)
+ {
+ }
+
+ virtual void attach()
+ {
+ wrapped_iop()->attach();
+ }
+
+ virtual void detach()
+ {
+ wrapped_iop()->detach();
+ }
+
+ virtual void knobs(DD::Image::Knob_Callback f)
+ {
+ OCIOColorSpace* csIop = dynamic_cast<OCIOColorSpace*>(wrapped_iop());
+ if(!csIop) return;
+
+ DD::Image::NukeWrapper::knobs(f);
+
+ DD::Image::Tab_knob(f, "Context");
+ {
+ DD::Image::String_knob(f, &csIop->m_contextKey1, "key1");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &csIop->m_contextValue1, "value1");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &csIop->m_contextKey2, "key2");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &csIop->m_contextValue2, "value2");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &csIop->m_contextKey3, "key3");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &csIop->m_contextValue3, "value3");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &csIop->m_contextKey4, "key4");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &csIop->m_contextValue4, "value4");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+ }
+ }
+};
+
+static DD::Image::Op* build(Node *node)
+{
+ DD::Image::NukeWrapper *op = (new OCIOColorSpaceNukeWrapper(new OCIOColorSpace(node)));
+ op->channels(DD::Image::Mask_RGB);
+ return op;
+}
diff --git a/src/nuke/OCIOColorSpace/OCIOColorSpace.h b/src/nuke/OCIOColorSpace/OCIOColorSpace.h
new file mode 100644
index 0000000..12b243b
--- /dev/null
+++ b/src/nuke/OCIOColorSpace/OCIOColorSpace.h
@@ -0,0 +1,120 @@
+#ifndef INCLUDED_OCIO_NUKE_COLORSPACECONVERSION_H_
+#define INCLUDED_OCIO_NUKE_COLORSPACECONVERSION_H_
+
+// Include these early, for Nuke's headers under gcc 4.4.2.
+#include <memory>
+#include <cstdarg>
+
+#include <DDImage/PixelIop.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knob.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+/*!
+ * Iop that uses OpenColorIO to perform colorspace conversions
+ */
+class OCIOColorSpace : public DD::Image::PixelIop {
+
+ protected:
+
+ bool m_hasColorSpaces; //!< Were colorspaces found for both input and output? If not, always error.
+ int m_inputColorSpaceIndex; //!< index of input colorspace selection from the pulldown list knob
+ int m_outputColorSpaceIndex;
+ std::vector<std::string> m_colorSpaceNames; //!< list of input and output colorspace names (memory for const char* s below)
+ std::vector<const char*> m_inputColorSpaceCstrNames; //!< list for the pulldown list knob (used raw)
+ std::vector<const char*> m_outputColorSpaceCstrNames;
+
+ OCIO::ConstContextRcPtr getLocalContext();
+
+ OCIO::ConstProcessorRcPtr m_processor;
+ public:
+
+ OCIOColorSpace(Node *node);
+
+ virtual ~OCIOColorSpace();
+
+ // These are public so the nuke wrapper can introspect into it
+ // TODO: use 'friend' instead
+ std::string m_contextKey1;
+ std::string m_contextValue1;
+ std::string m_contextKey2;
+ std::string m_contextValue2;
+ std::string m_contextKey3;
+ std::string m_contextValue3;
+ std::string m_contextKey4;
+ std::string m_contextValue4;
+
+ static const DD::Image::Op::Description description;
+
+ /*! Return the command name that will be stored in Nuke scripts. */
+ virtual const char *Class() const;
+
+ /*!
+ * Return a name for this class that will be shown to the user. The
+ * default implementation returns Class(). You can return a different
+ * (ie more user-friendly) name instead here, and there is no need for
+ * this to be unique.
+ *
+ * Nuke currently will remove any trailing digits and underscores from
+ * this and add a new number to make a unique name for the new node.
+ *
+ * \return "OCIOColorSpace"
+ */
+ virtual const char *displayName() const;
+
+ /*!
+ * Return help information for this node. This information is in the
+ * pop-up window that the user gets when they hit the [?] button in
+ * the lower-left corner of the control panel.
+ */
+ virtual const char *node_help() const;
+
+ /*!
+ * Define the knobs that will be presented in the control panel.
+ */
+ virtual void knobs(DD::Image::Knob_Callback f);
+
+ /*!
+ * Specify the channels required from input n to produce the channels
+ * in mask by modifying mask in-place. (At least one channel in the
+ * input is assumed.)
+ *
+ * Since colorspace conversions can have channel cross-talk, any rgb
+ * output channel requires all its rgb bretheren. (Non-rgb
+ * are passed through.)
+ */
+ virtual void in_channels(int n, DD::Image::ChannelSet& mask) const;
+
+ /*!
+ * Calculate the output pixel data.
+ * \param rowY vertical line number
+ * \param rowX inclusive left bound
+ * \param rowXBound exclusive right bound
+ * \param outputChannels a subset of out_channels(), the required channels to be produced
+ */
+ virtual void pixel_engine(
+ const DD::Image::Row& in,
+ int rowY, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out);
+
+ virtual void append(DD::Image::Hash& hash);
+
+ protected:
+
+ /*!
+ * Check that colorspaces are available, and that the transform
+ * is not a noop. (As OCIO whether a given transform is a noop, since it
+ * can do more analysis than just name matching.)
+ */
+ virtual void _validate(bool for_real);
+
+};
+
+
+static DD::Image::Op* build(Node *node);
+
+#endif // INCLUDED_OCIO_NUKE_COLORSPACECONVERSION_H_
diff --git a/src/nuke/OCIODisplay/OCIODisplay.cpp b/src/nuke/OCIODisplay/OCIODisplay.cpp
new file mode 100644
index 0000000..bf82ab8
--- /dev/null
+++ b/src/nuke/OCIODisplay/OCIODisplay.cpp
@@ -0,0 +1,561 @@
+/**
+ * OpenColorIO Display Iop.
+ */
+
+#include "OCIODisplay.h"
+
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <algorithm>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <DDImage/Channel.h>
+#include <DDImage/PixelIop.h>
+#include <DDImage/NukeWrapper.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knobs.h>
+#include <DDImage/Enumeration_KnobI.h>
+#include <DDImage/ddImageVersionNumbers.h>
+
+// Should we use cascasing ColorSpace menus
+#if defined kDDImageVersionInteger && (kDDImageVersionInteger>=62300)
+#define OCIO_CASCADE
+#endif
+
+OCIODisplay::OCIODisplay(Node *n) : DD::Image::PixelIop(n)
+{
+ m_layersToProcess = DD::Image::Mask_RGBA;
+ m_hasLists = false;
+ m_colorSpaceIndex = m_displayIndex = m_viewIndex = 0;
+ m_displayKnob = m_viewKnob = NULL;
+ m_gain = 1.0;
+ m_gamma = 1.0;
+ m_channel = 2;
+ m_transform = OCIO::DisplayTransform::Create();
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ OCIO::ConstColorSpaceRcPtr defaultcs = config->getColorSpace(OCIO::ROLE_SCENE_LINEAR);
+ if(!defaultcs) throw std::runtime_error("ROLE_SCENE_LINEAR not defined.");
+ std::string defaultColorSpaceName = defaultcs->getName();
+
+ for(int i=0; i<config->getNumColorSpaces(); ++i)
+ {
+ std::string csname = config->getColorSpaceNameByIndex(i);
+
+#ifdef OCIO_CASCADE
+ std::string family = config->getColorSpace(csname.c_str())->getFamily();
+ if(family.empty())
+ m_colorSpaceNames.push_back(csname.c_str());
+ else
+ m_colorSpaceNames.push_back(family + "/" + csname);
+#else
+ m_colorSpaceNames.push_back(csname);
+#endif
+
+ if(defaultColorSpaceName == csname)
+ {
+ m_colorSpaceIndex = i;
+ }
+ }
+
+ std::string defaultDisplay = config->getDefaultDisplay();
+
+ for(int i=0; i<config->getNumDisplays(); ++i)
+ {
+ std::string display = config->getDisplay(i);
+ m_displayNames.push_back(display);
+
+ if(display == defaultDisplay)
+ {
+ m_displayIndex = i;
+ }
+ }
+ }
+ catch(OCIO::Exception& e)
+ {
+ std::cerr << "OCIODisplay: " << e.what() << std::endl;
+ }
+ catch(...)
+ {
+ std::cerr << "OCIODisplay: Unknown exception during OCIO setup." << std::endl;
+ }
+
+ // Build the cstr vectors on our second pass
+ for(unsigned int i=0; i<m_colorSpaceNames.size(); ++i)
+ {
+ m_colorSpaceCstrNames.push_back(m_colorSpaceNames[i].c_str());
+ }
+ m_colorSpaceCstrNames.push_back(NULL);
+
+ for(unsigned int i=0; i<m_displayNames.size(); ++i)
+ {
+ m_displayCstrNames.push_back(m_displayNames[i].c_str());
+ }
+ m_displayCstrNames.push_back(NULL);
+
+ refreshDisplayTransforms();
+
+ m_hasLists = !(m_colorSpaceNames.empty() || m_displayNames.empty() || m_viewNames.empty());
+
+ if(!m_hasLists)
+ {
+ std::cerr << "OCIODisplay: Missing one or more of colorspaces, display devices, or display transforms." << std::endl;
+ }
+}
+
+OCIODisplay::~OCIODisplay()
+{
+
+}
+
+void OCIODisplay::knobs(DD::Image::Knob_Callback f)
+{
+#ifdef OCIO_CASCADE
+ DD::Image::CascadingEnumeration_knob(f,
+ &m_colorSpaceIndex, &m_colorSpaceCstrNames[0], "colorspace", "input colorspace");
+#else
+ DD::Image::Enumeration_knob(f,
+ &m_colorSpaceIndex, &m_colorSpaceCstrNames[0], "colorspace", "input colorspace");
+#endif
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+ DD::Image::Tooltip(f, "Input data is taken to be in this colorspace.");
+
+ m_displayKnob = DD::Image::Enumeration_knob(f,
+ &m_displayIndex, &m_displayCstrNames[0], "display", "display device");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+ DD::Image::Tooltip(f, "Display device for output.");
+
+ m_viewKnob = DD::Image::Enumeration_knob(f,
+ &m_viewIndex, &m_viewCstrNames[0], "view", "view transform");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+ DD::Image::Tooltip(f, "Display transform for output.");
+
+ DD::Image::Float_knob(f, &m_gain, DD::Image::IRange(1.0 / 64.0f, 64.0f), "gain");
+ DD::Image::SetFlags(f, DD::Image::Knob::NO_ANIMATION | DD::Image::Knob::NO_UNDO | DD::Image::Knob::LOG_SLIDER);
+ DD::Image::Tooltip(f, "Exposure adjustment, in scene-linear, prior to the display transform.");
+
+ DD::Image::Float_knob(f, &m_gamma, DD::Image::IRange(0, 4), "gamma");
+ DD::Image::SetFlags(f, DD::Image::Knob::NO_ANIMATION | DD::Image::Knob::NO_UNDO | DD::Image::Knob::LOG_SLIDER);
+ DD::Image::Tooltip(f, "Gamma correction applied after the display transform.");
+
+ static const char* const channelvalues[] = {
+ "Luminance",
+ "Matte overlay",
+ "RGB",
+ "R",
+ "G",
+ "B",
+ "A",
+ 0
+ };
+ DD::Image::Enumeration_knob(f, &m_channel, channelvalues, "channel_selector", "channel view");
+ DD::Image::SetFlags(f, DD::Image::Knob::NO_ANIMATION | DD::Image::Knob::NO_UNDO);
+ DD::Image::Tooltip(f, "Specify which channels to view (prior to the display transform).");
+
+ DD::Image::Divider(f);
+
+ DD::Image::Input_ChannelSet_knob(f, &m_layersToProcess, 0, "layer", "layer");
+ // DD::Image::SetFlags(f, DD::Image::Knob::NO_CHECKMARKS | DD::Image::Knob::NO_ALPHA_PULLDOWN);
+ DD::Image::Tooltip(f, "Set which layer to process. This should be a layer with rgb data.");
+
+ DD::Image::Tab_knob(f, "Context");
+ {
+ DD::Image::String_knob(f, &m_contextKey1, "key1");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &m_contextValue1, "value1");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &m_contextKey2, "key2");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &m_contextValue2, "value2");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &m_contextKey3, "key3");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &m_contextValue3, "value3");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &m_contextKey4, "key4");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &m_contextValue4, "value4");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+ }
+}
+
+OCIO::ConstContextRcPtr OCIODisplay::getLocalContext()
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ OCIO::ConstContextRcPtr context = config->getCurrentContext();
+ OCIO::ContextRcPtr mutableContext;
+
+ if(!m_contextKey1.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey1.c_str(), m_contextValue1.c_str());
+ }
+ if(!m_contextKey2.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey2.c_str(), m_contextValue2.c_str());
+ }
+ if(!m_contextKey3.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey3.c_str(), m_contextValue3.c_str());
+ }
+ if(!m_contextKey4.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey4.c_str(), m_contextValue4.c_str());
+ }
+
+ if(mutableContext) context = mutableContext;
+
+ return context;
+}
+
+void OCIODisplay::append(DD::Image::Hash& localhash)
+{
+ // TODO: Hang onto the context, what if getting it
+ // (and querying getCacheID) is expensive?
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ OCIO::ConstContextRcPtr context = getLocalContext();
+ std::string configCacheID = config->getCacheID(context);
+ localhash.append(configCacheID);
+
+ // This is required due to our custom channel overlay mode post-processing
+ localhash.append(m_channel);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+}
+
+void OCIODisplay::_validate(bool for_real)
+{
+ input0().validate(for_real);
+
+ if(!m_hasLists)
+ {
+ error("Missing one or more of colorspaces, display devices, or display transforms.");
+ return;
+ }
+
+ int nColorSpaces = static_cast<int>(m_colorSpaceNames.size());
+ if(m_colorSpaceIndex < 0 || m_colorSpaceIndex >= nColorSpaces)
+ {
+ std::ostringstream err;
+ err << "ColorSpace index (" << m_colorSpaceIndex << ") out of range.";
+ error(err.str().c_str());
+ return;
+ }
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ m_transform->setInputColorSpaceName(config->getColorSpaceNameByIndex(m_colorSpaceIndex));
+ m_transform->setDisplay(m_displayCstrNames[m_displayIndex]);
+ m_transform->setView(m_viewCstrNames[m_viewIndex]);
+
+ // Specify an (optional) linear color correction
+ {
+ float m44[16];
+ float offset4[4];
+
+ const float slope4f[] = { m_gain, m_gain, m_gain, m_gain };
+ OCIO::MatrixTransform::Scale(m44, offset4, slope4f);
+
+ OCIO::MatrixTransformRcPtr mtx = OCIO::MatrixTransform::Create();
+ mtx->setValue(m44, offset4);
+
+ m_transform->setLinearCC(mtx);
+ }
+
+ // Specify an (optional) post-display transform.
+ {
+ float exponent = 1.0f/std::max(1e-6f, m_gamma);
+ const float exponent4f[] = { exponent, exponent, exponent, exponent };
+ OCIO::ExponentTransformRcPtr cc = OCIO::ExponentTransform::Create();
+ cc->setValue(exponent4f);
+ m_transform->setDisplayCC(cc);
+ }
+
+ // Add Channel swizzling
+ {
+ int channelHot[4] = { 0, 0, 0, 0};
+
+ switch(m_channel)
+ {
+ case 0: // Luma
+ channelHot[0] = 1;
+ channelHot[1] = 1;
+ channelHot[2] = 1;
+ break;
+ case 1: // Channel overlay mode. Do rgb, and then swizzle later
+ channelHot[0] = 1;
+ channelHot[1] = 1;
+ channelHot[2] = 1;
+ channelHot[3] = 1;
+ break;
+ case 2: // RGB
+ channelHot[0] = 1;
+ channelHot[1] = 1;
+ channelHot[2] = 1;
+ channelHot[3] = 1;
+ break;
+ case 3: // R
+ channelHot[0] = 1;
+ break;
+ case 4: // G
+ channelHot[1] = 1;
+ break;
+ case 5: // B
+ channelHot[2] = 1;
+ break;
+ case 6: // A
+ channelHot[3] = 1;
+ break;
+ default:
+ break;
+ }
+
+ float lumacoef[3];
+ config->getDefaultLumaCoefs(lumacoef);
+ float m44[16];
+ float offset[4];
+ OCIO::MatrixTransform::View(m44, offset, channelHot, lumacoef);
+ OCIO::MatrixTransformRcPtr swizzle = OCIO::MatrixTransform::Create();
+ swizzle->setValue(m44, offset);
+ m_transform->setChannelView(swizzle);
+ }
+
+ OCIO::ConstContextRcPtr context = getLocalContext();
+ m_processor = config->getProcessor(context,
+ m_transform,
+ OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+
+ if(m_processor->isNoOp())
+ {
+ set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
+ } else {
+ set_out_channels(DD::Image::Mask_All);
+ }
+
+ DD::Image::PixelIop::_validate(for_real);
+}
+
+// Note: Same as OCIO ColorSpace::in_channels.
+void OCIODisplay::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
+{
+ DD::Image::ChannelSet done;
+ foreach(c, mask)
+ {
+ if ((m_layersToProcess & c) && DD::Image::colourIndex(c) < 4 && !(done & c))
+ {
+ done.addBrothers(c, 4);
+ }
+ }
+ mask += done;
+}
+
+// Note: Same as OCIO ColorSpace::pixel_engine.
+void OCIODisplay::pixel_engine(
+ const DD::Image::Row& in,
+ int /* rowY unused */, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out)
+{
+ int rowWidth = rowXBound - rowX;
+
+ DD::Image::ChannelSet done;
+ foreach (requestedChannel, outputChannels)
+ {
+ // Skip channels which had their trios processed already,
+ if (done & requestedChannel)
+ {
+ continue;
+ }
+
+ // Pass through channels which are not selected for processing
+ // and non-rgb channels.
+ if (!(m_layersToProcess & requestedChannel))
+ {
+ out.copy(in, requestedChannel, rowX, rowXBound);
+ continue;
+ }
+
+ DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
+ DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
+ DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
+ DD::Image::Channel aChannel = outputChannels.next(bChannel);
+
+ done += rChannel;
+ done += gChannel;
+ done += bChannel;
+ done += aChannel;
+
+ const float *rIn = in[rChannel] + rowX;
+ const float *gIn = in[gChannel] + rowX;
+ const float *bIn = in[bChannel] + rowX;
+ const float *aIn = in[aChannel] + rowX;
+
+ float *rOut = out.writable(rChannel) + rowX;
+ float *gOut = out.writable(gChannel) + rowX;
+ float *bOut = out.writable(bChannel) + rowX;
+ float *aOut = out.writable(aChannel) + rowX;
+
+ // OCIO modifies in-place
+ // Note: xOut can equal xIn in some circumstances, such as when the
+ // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
+ // which does not allow for overlapping regions.
+ if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
+ if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
+ if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
+ if (aOut != aIn) memcpy(aOut, aIn, sizeof(float)*rowWidth);
+
+ try
+ {
+ OCIO::PlanarImageDesc img(rOut, gOut, bOut, aOut, rowWidth, /*height*/ 1);
+ m_processor->apply(img);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+
+ // Hack to emulate Channel overlay mode
+ if(m_channel == 1)
+ {
+ for(int i=0; i<rowWidth; ++i)
+ {
+ rOut[i] = rOut[i] + (1.0f - rOut[i]) * (0.5f * aOut[i]);
+ gOut[i] = gOut[i] - gOut[i] * (0.5f * aOut[i]);
+ bOut[i] = bOut[i] - bOut[i] * (0.5f * aOut[i]);
+ }
+ }
+ }
+}
+
+void OCIODisplay::refreshDisplayTransforms()
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ if (m_displayIndex < 0 || m_displayIndex >= static_cast<int>(m_displayNames.size()))
+ {
+ std::ostringstream err;
+ err << "No or invalid display specified (index " << m_displayIndex << ").";
+ std::cerr << err.str(); // This can't set an error, as it's called in the constructor
+ return;
+ }
+
+ const char * display = m_displayCstrNames[m_displayIndex];
+ int numViews = config->getNumViews(display);
+ std::string defaultViewName = config->getDefaultView(display);
+
+ // Try to maintain an old transform name, or use the default.
+ bool hasOldViewName = false;
+ std::string oldViewName = "";
+ if (m_viewIndex >= 0 && m_viewIndex < static_cast<int>(m_viewNames.size()))
+ {
+ hasOldViewName = true;
+ oldViewName = m_viewNames[m_viewIndex];
+ }
+ int defaultViewIndex = 0, newViewIndex = -1;
+
+ m_viewCstrNames.clear();
+ m_viewNames.clear();
+
+ for(int i = 0; i < numViews; i++)
+ {
+ std::string view = config->getView(display, i);
+ m_viewNames.push_back(view);
+ if (hasOldViewName && view == oldViewName)
+ {
+ newViewIndex = i;
+ }
+ if (view == defaultViewName)
+ {
+ defaultViewIndex = i;
+ }
+ }
+
+ for(unsigned int i=0; i<m_viewNames.size(); ++i)
+ {
+ m_viewCstrNames.push_back(m_viewNames[i].c_str());
+ }
+ m_viewCstrNames.push_back(NULL);
+
+ if (newViewIndex == -1)
+ {
+ newViewIndex = defaultViewIndex;
+ }
+
+ if (m_viewKnob == NULL)
+ {
+ m_viewIndex = newViewIndex;
+ }
+ else
+ {
+ DD::Image::Enumeration_KnobI *enumKnob = m_viewKnob->enumerationKnob();
+ enumKnob->menu(m_viewNames);
+ m_viewKnob->set_value(newViewIndex);
+ }
+}
+
+int OCIODisplay::knob_changed(DD::Image::Knob *k)
+{
+ if (k == m_displayKnob && m_displayKnob != NULL)
+ {
+ refreshDisplayTransforms();
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+const DD::Image::Op::Description OCIODisplay::description("OCIODisplay", build);
+
+const char* OCIODisplay::Class() const
+{
+ return description.name;
+}
+
+const char* OCIODisplay::displayName() const
+{
+ return description.name;
+}
+
+const char* OCIODisplay::node_help() const
+{
+ // TODO more detailed help text
+ return "Use OpenColorIO to convert for a display device.";
+}
+
+
+DD::Image::Op* build(Node *node)
+{
+ DD::Image::NukeWrapper *op = new DD::Image::NukeWrapper(new OCIODisplay(node));
+ op->noMix();
+ op->noMask();
+ op->noChannels(); // prefer our own channels control without checkboxes / alpha
+ op->noUnpremult();
+ return op;
+}
diff --git a/src/nuke/OCIODisplay/OCIODisplay.h b/src/nuke/OCIODisplay/OCIODisplay.h
new file mode 100644
index 0000000..a4521cf
--- /dev/null
+++ b/src/nuke/OCIODisplay/OCIODisplay.h
@@ -0,0 +1,133 @@
+#ifndef INCLUDED_OCIO_NUKE_DISPLAY_H_
+#define INCLUDED_OCIO_NUKE_DISPLAY_H_
+
+// Include these early, for Nuke's headers under gcc 4.4.2.
+#include <memory>
+#include <cstdarg>
+
+#include <DDImage/PixelIop.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knob.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+/*!
+ * Use OpenColorIO to convert for display output.
+ */
+class OCIODisplay : public DD::Image::PixelIop {
+ protected:
+
+ bool m_hasLists; //!< Were colorspaces, OCIODisplay devices, and transform names found? If not, always error.
+ DD::Image::ChannelSet m_layersToProcess; //!< layers (rgb channel groups) to process
+ int m_colorSpaceIndex; //!< index of colorspace selection from the pulldown list knob
+ int m_displayIndex, m_viewIndex;
+ std::vector<std::string> m_colorSpaceNames; //!< list of colorspace names (memory for const char* s below)
+ std::vector<std::string> m_displayNames, m_viewNames;
+ std::vector<const char*> m_colorSpaceCstrNames; //!< list for the pulldown list knob (used raw)
+ std::vector<const char*> m_displayCstrNames, m_viewCstrNames;
+ float m_gain;
+ float m_gamma;
+ int m_channel;
+
+ std::string m_contextKey1;
+ std::string m_contextValue1;
+ std::string m_contextKey2;
+ std::string m_contextValue2;
+ std::string m_contextKey3;
+ std::string m_contextValue3;
+ std::string m_contextKey4;
+ std::string m_contextValue4;
+ OCIO::ConstContextRcPtr getLocalContext();
+
+ OCIO::DisplayTransformRcPtr m_transform;
+ OCIO::ConstProcessorRcPtr m_processor;
+
+ DD::Image::Knob *m_displayKnob, *m_viewKnob;
+ void refreshDisplayTransforms();
+
+ public:
+
+ OCIODisplay(Node *node);
+
+ virtual ~OCIODisplay();
+
+ static const DD::Image::Op::Description description;
+
+ /*! Return the command name that will be stored in Nuke scripts. */
+ virtual const char *Class() const;
+
+ /*!
+ * Return a name for this class that will be shown to the user. The
+ * default implementation returns Class(). You can return a different
+ * (ie more user-friendly) name instead here, and there is no need for
+ * this to be unique.
+ *
+ * Nuke currently will remove any trailing digits and underscores from
+ * this and add a new number to make a unique name for the new node.
+ *
+ * \return "OCIODisplay"
+ */
+ virtual const char *displayName() const;
+
+ /*!
+ * Return help information for this node. This information is in the
+ * pop-up window that the user gets when they hit the [?] button in
+ * the lower-left corner of the control panel.
+ */
+ virtual const char *node_help() const;
+
+ /*!
+ * Define the knobs that will be presented in the control panel.
+ */
+ virtual void knobs(DD::Image::Knob_Callback f);
+
+ /*!
+ * Specify the channels required from input n to produce the channels
+ * in mask by modifying mask in-place. (At least one channel in the
+ * input is assumed.)
+ *
+ * Since colorspace conversions can have channel cross-talk, any rgb
+ * output channel requires all its rgb bretheren. (Non-rgb
+ * are passed through.)
+ */
+ virtual void in_channels(int n, DD::Image::ChannelSet& mask) const;
+
+ /*!
+ * Calculate the output pixel data.
+ * \param rowY vertical line number
+ * \param rowX inclusive left bound
+ * \param rowXBound exclusive right bound
+ * \param outputChannels a subset of out_channels(), the required channels to be produced
+ */
+ virtual void pixel_engine(
+ const DD::Image::Row& in,
+ int rowY, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out);
+
+ /*!
+ * When the display device changes,
+ * regenerate the display transform list.
+ */
+ virtual int knob_changed(DD::Image::Knob *k);
+
+ virtual void append(DD::Image::Hash& hash);
+
+
+ protected:
+
+ /*!
+ * Check that colorspaces are available, and that the transform
+ * is not a noop. (As OCIO whether a given transform is a noop, since it
+ * can do more analysis than just name matching.)
+ */
+ virtual void _validate(bool for_real);
+
+};
+
+
+static DD::Image::Op* build(Node *node);
+
+#endif // INCLUDED_OCIO_NUKE_DISPLAY_H_
diff --git a/src/nuke/OCIOFileTransform/OCIOFileTransform.cpp b/src/nuke/OCIOFileTransform/OCIOFileTransform.cpp
new file mode 100644
index 0000000..ff18f74
--- /dev/null
+++ b/src/nuke/OCIOFileTransform/OCIOFileTransform.cpp
@@ -0,0 +1,287 @@
+/**
+ * OpenColorIO FileTransform Iop.
+ */
+
+#include "OCIOFileTransform.h"
+
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <DDImage/Channel.h>
+#include <DDImage/PixelIop.h>
+#include <DDImage/NukeWrapper.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knobs.h>
+
+OCIOFileTransform::OCIOFileTransform(Node *n) : DD::Image::PixelIop(n)
+{
+ m_file = NULL;
+ m_dirindex = 0;
+ m_interpindex = 1;
+ m_reload_version = 1;
+}
+
+OCIOFileTransform::~OCIOFileTransform()
+{
+
+}
+
+const char* OCIOFileTransform::dirs[] = { "forward", "inverse", 0 };
+
+const char* OCIOFileTransform::interp[] = { "nearest", "linear", "tetrahedral", "best", 0 };
+
+void OCIOFileTransform::knobs(DD::Image::Knob_Callback f)
+{
+ File_knob(f, &m_file, "file", "file");
+ DD::Image::Tooltip(f, "Specify the file, on disk, to use for this transform. See the node help for the list of supported formats.");
+
+ // Reload button, and hidden "version" knob to invalidate cache on reload
+ Button(f, "reload", "reload");
+ DD::Image::Tooltip(f, "Reloads specified files");
+ Int_knob(f, &m_reload_version, "version");
+ DD::Image::SetFlags(f, DD::Image::Knob::HIDDEN);
+
+ String_knob(f, &m_cccid, "cccid");
+ const char * srchelp2 = "If the source file is an ASC CDL CCC (color correction collection), "
+ "this specifys the id to lookup. OpenColorIO::Contexts (envvars) are obeyed.";
+ DD::Image::Tooltip(f, srchelp2);
+
+ DD::Image::PyScript_knob(f, "import ocionuke.cdl; ocionuke.cdl.select_cccid_for_filetransform(fileknob='file', cccidknob = 'cccid')", "select_cccid", "select cccid");
+
+ Enumeration_knob(f, &m_dirindex, dirs, "direction", "direction");
+ DD::Image::Tooltip(f, "Specify the transform direction.");
+
+ Enumeration_knob(f, &m_interpindex, interp, "interpolation", "interpolation");
+ DD::Image::Tooltip(f, "Specify the interpolation method. For files that are not LUTs (mtx, etc) this is ignored.");
+}
+
+void OCIOFileTransform::_validate(bool for_real)
+{
+ if(!m_file)
+ {
+ error("The source file must be specified.");
+ return;
+ }
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ OCIO::FileTransformRcPtr transform = OCIO::FileTransform::Create();
+ transform->setSrc(m_file);
+
+ transform->setCCCId(m_cccid.c_str());
+
+ if(m_dirindex == 0) transform->setDirection(OCIO::TRANSFORM_DIR_FORWARD);
+ else transform->setDirection(OCIO::TRANSFORM_DIR_INVERSE);
+
+ if(m_interpindex == 0) transform->setInterpolation(OCIO::INTERP_NEAREST);
+ else if(m_interpindex == 1) transform->setInterpolation(OCIO::INTERP_LINEAR);
+ else if(m_interpindex == 2) transform->setInterpolation(OCIO::INTERP_TETRAHEDRAL);
+ else if(m_interpindex == 3) transform->setInterpolation(OCIO::INTERP_BEST);
+ else
+ {
+ // Should never happen
+ error("Interpolation value out of bounds");
+ return;
+ }
+
+ m_processor = config->getProcessor(transform, OCIO::TRANSFORM_DIR_FORWARD);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+
+ if(m_processor->isNoOp())
+ {
+ set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
+ } else {
+ set_out_channels(DD::Image::Mask_All);
+ }
+
+ DD::Image::PixelIop::_validate(for_real);
+}
+
+// Note that this is copied by others (OCIODisplay)
+void OCIOFileTransform::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
+{
+ DD::Image::ChannelSet done;
+ foreach(c, mask)
+ {
+ if (DD::Image::colourIndex(c) < 3 && !(done & c))
+ {
+ done.addBrothers(c, 3);
+ }
+ }
+ mask += done;
+}
+
+void OCIOFileTransform::append(DD::Image::Hash& nodehash)
+{
+ // There is a bug where in Nuke <6.3 the String_knob (used for
+ // cccid) is not included in the node's hash. Include it manually
+ // so the node correctly redraws. Appears fixed in in 6.3
+ nodehash.append(m_cccid.c_str());
+
+ // Incremented to force reloading after rereading the LUT file
+ nodehash.append(m_reload_version);
+}
+
+int OCIOFileTransform::knob_changed(DD::Image::Knob* k)
+{
+ // Only show the cccid knob when loading a .cc/.ccc file. Set
+ // hidden state when the src is changed, or the node properties
+ // are shown
+ if(k->is("file") | k->is("showPanel"))
+ {
+ // Convoluted equiv to pysting::endswith(m_file, ".ccc")
+ // TODO: Could this be queried from the processor?
+ const std::string srcstring = m_file;
+ const std::string cccext = "ccc";
+ const std::string ccext = "cc";
+ if(std::equal(cccext.rbegin(), cccext.rend(), srcstring.rbegin()) ||
+ std::equal(ccext.rbegin(), ccext.rend(), srcstring.rbegin()))
+ {
+ knob("cccid")->show();
+ knob("select_cccid")->show();
+ }
+ else
+ {
+ knob("cccid")->hide();
+ knob("select_cccid")->hide();
+ }
+
+ // Ensure this callback is always triggered (for src knob)
+ return true;
+ }
+
+ if(k->is("reload"))
+ {
+ knob("version")->set_value(m_reload_version+1);
+ OCIO::ClearAllCaches();
+
+ return true; // ensure callback is triggered again
+ }
+
+ // Return zero to avoid callbacks for other knobs
+ return false;
+}
+
+// See Saturation::pixel_engine for a well-commented example.
+// Note that this is copied by others (OCIODisplay)
+void OCIOFileTransform::pixel_engine(
+ const DD::Image::Row& in,
+ int /* rowY unused */, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out)
+{
+ int rowWidth = rowXBound - rowX;
+
+ DD::Image::ChannelSet done;
+ foreach (requestedChannel, outputChannels)
+ {
+ // Skip channels which had their trios processed already,
+ if (done & requestedChannel)
+ {
+ continue;
+ }
+
+ // Pass through channels which are not selected for processing
+ // and non-rgb channels.
+ if (colourIndex(requestedChannel) >= 3)
+ {
+ out.copy(in, requestedChannel, rowX, rowXBound);
+ continue;
+ }
+
+ DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
+ DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
+ DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
+
+ done += rChannel;
+ done += gChannel;
+ done += bChannel;
+
+ const float *rIn = in[rChannel] + rowX;
+ const float *gIn = in[gChannel] + rowX;
+ const float *bIn = in[bChannel] + rowX;
+
+ float *rOut = out.writable(rChannel) + rowX;
+ float *gOut = out.writable(gChannel) + rowX;
+ float *bOut = out.writable(bChannel) + rowX;
+
+ // OCIO modifies in-place
+ // Note: xOut can equal xIn in some circumstances, such as when the
+ // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
+ // which does not allow for overlapping regions.
+ if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
+ if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
+ if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
+
+ try
+ {
+ OCIO::PlanarImageDesc img(rOut, gOut, bOut, NULL, rowWidth, /*height*/ 1);
+ m_processor->apply(img);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+ }
+}
+
+const DD::Image::Op::Description OCIOFileTransform::description("OCIOFileTransform", build);
+
+const char* OCIOFileTransform::Class() const
+{
+ return description.name;
+}
+
+const char* OCIOFileTransform::displayName() const
+{
+ return description.name;
+}
+
+const char* OCIOFileTransform::node_help() const
+{
+ if(m_nodehelp.empty())
+ {
+ const char * helptext =
+ "Use OpenColorIO to apply a transform loaded from the given "
+ "file.\n\n"
+ "This is usually a 1D or 3D LUT file, but can be other file-based "
+ "transform, for example an ASC ColorCorrection XML file.\n\n"
+ "Note that the file's transform is applied with no special "
+ "input/output colorspace handling - so if the file expects "
+ "log-encoded pixels, but you apply the node to a linear "
+ "image, you will get incorrect results.\n\n";
+
+ std::ostringstream os;
+ os << helptext;
+
+ os << "Supported formats:\n";
+ for(int i=0; i<OCIO::FileTransform::getNumFormats(); ++i)
+ {
+ const char* name = OCIO::FileTransform::getFormatNameByIndex(i);
+ const char* exten = OCIO::FileTransform::getFormatExtensionByIndex(i);
+ os << "\n." << exten << " (" << name << ")";
+ }
+
+ m_nodehelp = os.str();
+ }
+
+ return m_nodehelp.c_str();
+}
+
+
+DD::Image::Op* build(Node *node)
+{
+ DD::Image::NukeWrapper *op = new DD::Image::NukeWrapper(new OCIOFileTransform(node));
+ op->channels(DD::Image::Mask_RGB);
+ return op;
+}
diff --git a/src/nuke/OCIOFileTransform/OCIOFileTransform.h b/src/nuke/OCIOFileTransform/OCIOFileTransform.h
new file mode 100644
index 0000000..0a848c5
--- /dev/null
+++ b/src/nuke/OCIOFileTransform/OCIOFileTransform.h
@@ -0,0 +1,128 @@
+#ifndef INCLUDED_OCIO_NUKE_FILETRANSFORM_H_
+#define INCLUDED_OCIO_NUKE_FILETRANSFORM_H_
+
+// Include these early, for Nuke's headers under gcc 4.4.2.
+#include <memory>
+#include <cstdarg>
+
+#include <DDImage/PixelIop.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knob.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+/*!
+ * Iop that uses OpenColorIO to perform colorspace conversions
+ */
+class OCIOFileTransform : public DD::Image::PixelIop {
+
+ protected:
+ const char* m_file;
+ std::string m_cccid;
+
+ /*! Transform direction dropdown index */
+ int m_dirindex;
+
+ /*! Interpolation dropdown index */
+ int m_interpindex;
+
+ /*! Processor used to apply the FileTransform */
+ OCIO::ConstProcessorRcPtr m_processor;
+
+ /*! Holds computed help string */
+ mutable std::string m_nodehelp;
+
+ /*! Controlled by hidden "version" knob, incremented to redraw image */
+ int m_reload_version;
+
+ public:
+ static const char* dirs[];
+ static const char* interp[];
+
+ OCIOFileTransform(Node *node);
+
+ virtual ~OCIOFileTransform();
+
+ static const DD::Image::Op::Description description;
+
+ /*! Return the command name that will be stored in Nuke scripts. */
+ virtual const char *Class() const;
+
+ /*!
+ * Return a name for this class that will be shown to the user. The
+ * default implementation returns Class(). You can return a different
+ * (ie more user-friendly) name instead here, and there is no need for
+ * this to be unique.
+ *
+ * Nuke currently will remove any trailing digits and underscores from
+ * this and add a new number to make a unique name for the new node.
+ *
+ * \return "OCIOFileTransform"
+ */
+ virtual const char *displayName() const;
+
+ /*!
+ * Return help information for this node. This information is in the
+ * pop-up window that the user gets when they hit the [?] button in
+ * the lower-left corner of the control panel.
+ */
+ virtual const char *node_help() const;
+
+ /*!
+ * Define the knobs that will be presented in the control panel.
+ */
+ virtual void knobs(DD::Image::Knob_Callback f);
+
+ /*!
+ * Specify the channels required from input n to produce the channels
+ * in mask by modifying mask in-place. (At least one channel in the
+ * input is assumed.)
+ *
+ * Since OCIOFileTransform conversions can have channel cross-talk, any rgb
+ * output channel requires all its rgb bretheren. (Non-rgb
+ * are passed through.)
+ */
+ virtual void in_channels(int n, DD::Image::ChannelSet& mask) const;
+
+ /*!
+ * Calculate the output pixel data.
+ * \param rowY vertical line number
+ * \param rowX inclusive left bound
+ * \param rowXBound exclusive right bound
+ * \param outputChannels a subset of out_channels(), the required channels to be produced
+ */
+ virtual void pixel_engine(
+ const DD::Image::Row& in,
+ int rowY, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out);
+
+
+ protected:
+
+ /*!
+ * Check that colorspaces are available, and that the transform
+ * is not a noop. (As OCIO whether a given transform is a noop, since it
+ * can do more analysis than just name matching.)
+ */
+ virtual void _validate(bool for_real);
+
+ /*!
+ * Ensure Node hash is reflects all parameters
+ */
+ virtual void append(DD::Image::Hash& nodehash);
+
+ /*!
+ * Hide and show UI elements based on other parameters.
+ Also handles reload button
+ */
+ virtual int knob_changed(DD::Image::Knob* k);
+
+};
+
+
+static DD::Image::Op* build(Node *node);
+
+#endif // INCLUDED_OCIO_NUKE_FILETRANSFORM_H_
diff --git a/src/nuke/OCIOLogConvert/OCIOLogConvert.cpp b/src/nuke/OCIOLogConvert/OCIOLogConvert.cpp
new file mode 100644
index 0000000..521847f
--- /dev/null
+++ b/src/nuke/OCIOLogConvert/OCIOLogConvert.cpp
@@ -0,0 +1,179 @@
+/**
+ * OpenColorIO LogConvert Iop.
+ */
+
+#include "OCIOLogConvert.h"
+
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <DDImage/Channel.h>
+#include <DDImage/PixelIop.h>
+#include <DDImage/NukeWrapper.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knobs.h>
+
+const char* OCIOLogConvert::modes[] = {
+ "log to lin", "lin to log", 0
+};
+
+OCIOLogConvert::OCIOLogConvert(Node *n) : DD::Image::PixelIop(n)
+{
+ modeindex = 0;
+}
+
+OCIOLogConvert::~OCIOLogConvert()
+{
+
+}
+
+void OCIOLogConvert::knobs(DD::Image::Knob_Callback f)
+{
+
+ Enumeration_knob(f, &modeindex, modes, "operation", "operation");
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+}
+
+void OCIOLogConvert::_validate(bool for_real)
+{
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ const char * src = 0;
+ const char * dst = 0;
+
+ if(modeindex == 0)
+ {
+ src = OCIO::ROLE_COMPOSITING_LOG;
+ dst = OCIO::ROLE_SCENE_LINEAR;
+ }
+ else
+ {
+ src = OCIO::ROLE_SCENE_LINEAR;
+ dst = OCIO::ROLE_COMPOSITING_LOG;
+ }
+
+ processor = config->getProcessor(src, dst);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+
+ if(processor->isNoOp())
+ {
+ set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
+ } else {
+ set_out_channels(DD::Image::Mask_All);
+ }
+
+ DD::Image::PixelIop::_validate(for_real);
+}
+
+// Note that this is copied by others (OCIODisplay)
+void OCIOLogConvert::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
+{
+ DD::Image::ChannelSet done;
+ foreach(c, mask)
+ {
+ if (DD::Image::colourIndex(c) < 3 && !(done & c))
+ {
+ done.addBrothers(c, 3);
+ }
+ }
+ mask += done;
+}
+
+// See Saturation::pixel_engine for a well-commented example.
+// Note that this is copied by others (OCIODisplay)
+void OCIOLogConvert::pixel_engine(
+ const DD::Image::Row& in,
+ int /* rowY unused */, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out)
+{
+ int rowWidth = rowXBound - rowX;
+
+ DD::Image::ChannelSet done;
+ foreach (requestedChannel, outputChannels)
+ {
+ // Skip channels which had their trios processed already,
+ if (done & requestedChannel)
+ {
+ continue;
+ }
+
+ // Pass through channels which are not selected for processing
+ // and non-rgb channels.
+ if (colourIndex(requestedChannel) >= 3)
+ {
+ out.copy(in, requestedChannel, rowX, rowXBound);
+ continue;
+ }
+
+ DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
+ DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
+ DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
+
+ done += rChannel;
+ done += gChannel;
+ done += bChannel;
+
+ const float *rIn = in[rChannel] + rowX;
+ const float *gIn = in[gChannel] + rowX;
+ const float *bIn = in[bChannel] + rowX;
+
+ float *rOut = out.writable(rChannel) + rowX;
+ float *gOut = out.writable(gChannel) + rowX;
+ float *bOut = out.writable(bChannel) + rowX;
+
+ // OCIO modifies in-place
+ // Note: xOut can equal xIn in some circumstances, such as when the
+ // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
+ // which does not allow for overlapping regions.
+ if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
+ if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
+ if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
+
+ try
+ {
+ OCIO::PlanarImageDesc img(rOut, gOut, bOut, NULL, rowWidth, /*height*/ 1);
+ processor->apply(img);
+ }
+ catch(OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+ }
+}
+
+const DD::Image::Op::Description OCIOLogConvert::description("OCIOLogConvert", build);
+
+const char* OCIOLogConvert::Class() const
+{
+ return description.name;
+}
+
+const char* OCIOLogConvert::displayName() const
+{
+ return description.name;
+}
+
+const char* OCIOLogConvert::node_help() const
+{
+ // TODO more detailed help text
+ return "Use OpenColorIO to convert from SCENE_LINEAR to COMPOSITING_LOG (or back).";
+}
+
+
+DD::Image::Op* build(Node *node)
+{
+ DD::Image::NukeWrapper *op = new DD::Image::NukeWrapper(new OCIOLogConvert(node));
+ op->channels(DD::Image::Mask_RGB);
+ return op;
+}
diff --git a/src/nuke/OCIOLogConvert/OCIOLogConvert.h b/src/nuke/OCIOLogConvert/OCIOLogConvert.h
new file mode 100644
index 0000000..0ce6aa8
--- /dev/null
+++ b/src/nuke/OCIOLogConvert/OCIOLogConvert.h
@@ -0,0 +1,101 @@
+#ifndef INCLUDED_OCIO_NUKE_LOGCONVERT_H_
+#define INCLUDED_OCIO_NUKE_LOGCONVERT_H_
+
+// Include these early, for Nuke's headers under gcc 4.4.2.
+#include <memory>
+#include <cstdarg>
+
+#include <DDImage/PixelIop.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knob.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+/*!
+ * Iop that uses OpenColorIO to perform colorspace conversions
+ */
+class OCIOLogConvert : public DD::Image::PixelIop {
+
+ protected:
+ int modeindex;
+
+ OCIO::ConstProcessorRcPtr processor;
+ public:
+ static const char* modes[];
+
+ OCIOLogConvert(Node *node);
+
+ virtual ~OCIOLogConvert();
+
+ static const DD::Image::Op::Description description;
+
+ /*! Return the command name that will be stored in Nuke scripts. */
+ virtual const char *Class() const;
+
+ /*!
+ * Return a name for this class that will be shown to the user. The
+ * default implementation returns Class(). You can return a different
+ * (ie more user-friendly) name instead here, and there is no need for
+ * this to be unique.
+ *
+ * Nuke currently will remove any trailing digits and underscores from
+ * this and add a new number to make a unique name for the new node.
+ *
+ * \return "OCIOLogConvert"
+ */
+ virtual const char *displayName() const;
+
+ /*!
+ * Return help information for this node. This information is in the
+ * pop-up window that the user gets when they hit the [?] button in
+ * the lower-left corner of the control panel.
+ */
+ virtual const char *node_help() const;
+
+ /*!
+ * Define the knobs that will be presented in the control panel.
+ */
+ virtual void knobs(DD::Image::Knob_Callback f);
+
+ /*!
+ * Specify the channels required from input n to produce the channels
+ * in mask by modifying mask in-place. (At least one channel in the
+ * input is assumed.)
+ *
+ * Since OCIOLogConvert conversions can have channel cross-talk, any rgb
+ * output channel requires all its rgb bretheren. (Non-rgb
+ * are passed through.)
+ */
+ virtual void in_channels(int n, DD::Image::ChannelSet& mask) const;
+
+ /*!
+ * Calculate the output pixel data.
+ * \param rowY vertical line number
+ * \param rowX inclusive left bound
+ * \param rowXBound exclusive right bound
+ * \param outputChannels a subset of out_channels(), the required channels to be produced
+ */
+ virtual void pixel_engine(
+ const DD::Image::Row& in,
+ int rowY, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out);
+
+
+ protected:
+
+ /*!
+ * Check that colorspaces are available, and that the transform
+ * is not a noop. (As OCIO whether a given transform is a noop, since it
+ * can do more analysis than just name matching.)
+ */
+ virtual void _validate(bool for_real);
+
+};
+
+
+static DD::Image::Op* build(Node *node);
+
+#endif // INCLUDED_OCIO_NUKE_LOGCONVERT_H_
diff --git a/src/nuke/OCIOLookTransform/OCIOLookTransform.cpp b/src/nuke/OCIOLookTransform/OCIOLookTransform.cpp
new file mode 100644
index 0000000..9dfac56
--- /dev/null
+++ b/src/nuke/OCIOLookTransform/OCIOLookTransform.cpp
@@ -0,0 +1,533 @@
+/**
+ * OpenColorIO ColorSpace Iop.
+ */
+
+#include "OCIOLookTransform.h"
+
+namespace OCIO = OCIO_NAMESPACE;
+
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <DDImage/Channel.h>
+#include <DDImage/PixelIop.h>
+#include <DDImage/NukeWrapper.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knobs.h>
+#include <DDImage/ddImageVersionNumbers.h>
+
+// Should we use cascasing ColorSpace menus
+#if defined kDDImageVersionInteger && (kDDImageVersionInteger>=62300)
+#define OCIO_CASCADE
+#endif
+
+OCIOLookTransform::OCIOLookTransform(Node *n) : DD::Image::PixelIop(n)
+{
+ m_hasColorSpaces = false;
+
+ m_inputColorSpaceIndex = 0;
+ m_outputColorSpaceIndex = 0;
+ m_dirIndex = 0;
+ m_ignoreErrors = false;
+ m_reload_version = 1;
+
+ // Query the colorspace names from the current config
+ // TODO (when to) re-grab the list of available colorspaces? How to save/load?
+
+ OCIO::ConstConfigRcPtr config;
+ std::string linear;
+
+ try
+ {
+ config = OCIO::GetCurrentConfig();
+
+ OCIO::ConstColorSpaceRcPtr linearcs = config->getColorSpace(OCIO::ROLE_SCENE_LINEAR);
+ if(!linearcs) throw std::runtime_error("ROLE_SCENE_LINEAR not defined.");
+ linear = linearcs->getName();
+
+ if(config->getNumLooks()>0)
+ {
+ m_look = config->getLookNameByIndex(0);
+ }
+
+ std::ostringstream os;
+ os << "Specify the look(s) to apply, as predefined in the OpenColorIO ";
+ os << "configuration. This may be the name of a single look, or a ";
+ os << "combination of looks using the 'look syntax' (outlined below)\n\n";
+
+ std::string firstlook = "a";
+ std::string secondlook = "b";
+ if(config->getNumLooks()>0)
+ {
+ os << "Looks: ";
+ for(int i = 0; i<config->getNumLooks(); ++i)
+ {
+ if(i!=0) os << ", ";
+ const char * lookname = config->getLookNameByIndex(i);
+ os << lookname;
+ if(i==0) firstlook = lookname;
+ if(i==1) secondlook = lookname;
+ }
+ os << "\n\n";
+ }
+ else
+ {
+ os << "NO LOOKS DEFINED -- ";
+ os << "This node cannot be used until looks are added to the OCIO Configuration. ";
+ os << "See opencolorio.org for examples.\n\n";
+ }
+
+ os << "Look Syntax:\n";
+ os << "Multiple looks are combined with commas: '";
+ os << firstlook << ", " << secondlook << "'\n";
+ os << "Direction is specified with +/- prefixes: '";
+ os << "+" << firstlook << ", -" << secondlook << "'\n";
+ os << "Missing look 'fallbacks' specified with |: '";
+ os << firstlook << ", -" << secondlook << " | -" << secondlook << "'";
+ m_lookhelp = os.str();
+ }
+ catch (const OCIO::Exception& e)
+ {
+ std::cerr << "OCIOLookTransform: " << e.what() << std::endl;
+ }
+ catch (...)
+ {
+ std::cerr << "OCIOLookTransform: Unknown exception during OCIO setup." << std::endl;
+ }
+
+ if(!config)
+ {
+ m_hasColorSpaces = false;
+ return;
+ }
+
+ for(int i = 0; i < config->getNumColorSpaces(); i++)
+ {
+ std::string csname = config->getColorSpaceNameByIndex(i);
+
+#ifdef OCIO_CASCADE
+ std::string family = config->getColorSpace(csname.c_str())->getFamily();
+ if(family.empty())
+ m_colorSpaceNames.push_back(csname.c_str());
+ else
+ m_colorSpaceNames.push_back(family + "/" + csname);
+#else
+ m_colorSpaceNames.push_back(csname);
+#endif
+ if(csname == linear)
+ {
+ m_inputColorSpaceIndex = i;
+ m_outputColorSpaceIndex = i;
+ }
+ }
+
+
+ // Step 2: Create a cstr array for passing to Nuke
+ // (This must be done in a second pass, lest the original strings be reallocated)
+
+ for(unsigned int i=0; i<m_colorSpaceNames.size(); ++i)
+ {
+ m_inputColorSpaceCstrNames.push_back(m_colorSpaceNames[i].c_str());
+ m_outputColorSpaceCstrNames.push_back(m_colorSpaceNames[i].c_str());
+ }
+
+ m_inputColorSpaceCstrNames.push_back(NULL);
+ m_outputColorSpaceCstrNames.push_back(NULL);
+
+ m_hasColorSpaces = (!m_colorSpaceNames.empty());
+
+ if(!m_hasColorSpaces)
+ {
+ std::cerr << "OCIOLookTransform: No ColorSpaces available for input and/or output." << std::endl;
+ }
+}
+
+OCIOLookTransform::~OCIOLookTransform()
+{
+
+}
+
+namespace
+{
+ static const char * directions[] = { "forward", "inverse", 0 };
+}
+
+void OCIOLookTransform::knobs(DD::Image::Knob_Callback f)
+{
+#ifdef OCIO_CASCADE
+ DD::Image::CascadingEnumeration_knob(f,
+ &m_inputColorSpaceIndex, &m_inputColorSpaceCstrNames[0], "in_colorspace", "in");
+#else
+ DD::Image::Enumeration_knob(f,
+ &m_inputColorSpaceIndex, &m_inputColorSpaceCstrNames[0], "in_colorspace", "in");
+#endif
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+ DD::Image::Tooltip(f, "Input data is taken to be in this colorspace.");
+
+ DD::Image::String_knob(f, &m_look, "look");
+ DD::Image::Tooltip(f, m_lookhelp.c_str());
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+
+ DD::Image::Spacer(f, 8);
+
+ Enumeration_knob(f, &m_dirIndex, directions, "direction", "direction");
+ DD::Image::Tooltip(f, "Specify the look transform direction. in/out colorspace handling is not affected.");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE );
+
+ // Reload button, and hidden "version" knob to invalidate cache on reload
+ DD::Image::Spacer(f, 8);
+
+ Button(f, "reload", "reload");
+ DD::Image::Tooltip(f, "Reload all files used in the underlying Look(s).");
+ Int_knob(f, &m_reload_version, "version");
+ DD::Image::SetFlags(f, DD::Image::Knob::HIDDEN);
+
+#ifdef OCIO_CASCADE
+ DD::Image::CascadingEnumeration_knob(f,
+ &m_outputColorSpaceIndex, &m_outputColorSpaceCstrNames[0], "out_colorspace", "out");
+#else
+ DD::Image::Enumeration_knob(f,
+ &m_outputColorSpaceIndex, &m_outputColorSpaceCstrNames[0], "out_colorspace", "out");
+#endif
+ DD::Image::SetFlags(f, DD::Image::Knob::ALWAYS_SAVE);
+ DD::Image::Tooltip(f, "Image data is converted to this colorspace for output.");
+
+
+ DD::Image::Bool_knob(f, &m_ignoreErrors, "ignore_errors", "ignore errors");
+ DD::Image::Tooltip(f, "If enabled, looks that cannot find the specified correction"
+ " are treated as a normal ColorSpace conversion instead of triggering a render error.");
+ DD::Image::SetFlags(f, DD::Image::Knob::STARTLINE );
+
+}
+
+OCIO::ConstContextRcPtr OCIOLookTransform::getLocalContext()
+{
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ OCIO::ConstContextRcPtr context = config->getCurrentContext();
+ OCIO::ContextRcPtr mutableContext;
+
+ if(!m_contextKey1.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey1.c_str(), m_contextValue1.c_str());
+ }
+ if(!m_contextKey2.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey2.c_str(), m_contextValue2.c_str());
+ }
+ if(!m_contextKey3.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey3.c_str(), m_contextValue3.c_str());
+ }
+ if(!m_contextKey4.empty())
+ {
+ if(!mutableContext) mutableContext = context->createEditableCopy();
+ mutableContext->setStringVar(m_contextKey4.c_str(), m_contextValue4.c_str());
+ }
+
+ if(mutableContext) context = mutableContext;
+ return context;
+}
+
+void OCIOLookTransform::append(DD::Image::Hash& nodehash)
+{
+ // Incremented to force reloading after rereading the LUT file
+ nodehash.append(m_reload_version);
+
+ // TODO: Hang onto the context, what if getting it
+ // (and querying getCacheID) is expensive?
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ OCIO::ConstContextRcPtr context = getLocalContext();
+ std::string configCacheID = config->getCacheID(context);
+ nodehash.append(configCacheID);
+ }
+ catch(const OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+ catch (...)
+ {
+ error("OCIOLookTransform: Unknown exception during hash generation.");
+ }
+}
+
+
+int OCIOLookTransform::knob_changed(DD::Image::Knob* k)
+{
+ if(k->is("reload"))
+ {
+ knob("version")->set_value(m_reload_version+1);
+ OCIO::ClearAllCaches();
+
+ return true; // ensure callback is triggered again
+ }
+
+ // Return zero to avoid callbacks for other knobs
+ return false;
+}
+
+
+void OCIOLookTransform::_validate(bool for_real)
+{
+ if(!m_hasColorSpaces)
+ {
+ error("No colorspaces available for input and/or output.");
+ return;
+ }
+
+ int inputColorSpaceCount = static_cast<int>(m_inputColorSpaceCstrNames.size()) - 1;
+ if(m_inputColorSpaceIndex < 0 || m_inputColorSpaceIndex >= inputColorSpaceCount)
+ {
+ std::ostringstream err;
+ err << "Input colorspace index (" << m_inputColorSpaceIndex << ") out of range.";
+ error(err.str().c_str());
+ return;
+ }
+
+ int outputColorSpaceCount = static_cast<int>(m_outputColorSpaceCstrNames.size()) - 1;
+ if(m_outputColorSpaceIndex < 0 || m_outputColorSpaceIndex >= outputColorSpaceCount)
+ {
+ std::ostringstream err;
+ err << "Output colorspace index (" << m_outputColorSpaceIndex << ") out of range.";
+ error(err.str().c_str());
+ return;
+ }
+
+ try
+ {
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+
+ const char * inputName = config->getColorSpaceNameByIndex(m_inputColorSpaceIndex);
+ const char * outputName = config->getColorSpaceNameByIndex(m_outputColorSpaceIndex);
+
+ OCIO::LookTransformRcPtr transform = OCIO::LookTransform::Create();
+ transform->setLooks(m_look.c_str());
+
+ OCIO::ConstContextRcPtr context = getLocalContext();
+ OCIO::TransformDirection direction = OCIO::TRANSFORM_DIR_UNKNOWN;
+ bool invertTransform = (m_dirIndex == 0) ? false : true;
+
+ // Forward
+ if(!invertTransform)
+ {
+ transform->setSrc(inputName);
+ transform->setDst(outputName);
+ direction = OCIO::TRANSFORM_DIR_FORWARD;
+ }
+ else
+ {
+ // The TRANSFORM_DIR_INVERSE applies an inverse for the end-to-end transform,
+ // which would otherwise do dst->inv look -> src.
+ // This is an unintuitive result for the artist (who would expect in, out to
+ // remain unchanged), so we account for that here by flipping src/dst
+
+ transform->setSrc(outputName);
+ transform->setDst(inputName);
+ direction = OCIO::TRANSFORM_DIR_INVERSE;
+ }
+
+ try
+ {
+ m_processor = config->getProcessor(context, transform, direction);
+ }
+ // We only catch the exceptions for missing files, and try to succeed
+ // in this case. All other errors represent more serious problems and
+ // should fail through.
+ catch(const OCIO::ExceptionMissingFile &e)
+ {
+ if(!m_ignoreErrors) throw;
+ m_processor = config->getProcessor(context, inputName, outputName);
+ }
+ }
+ catch(const OCIO::Exception &e)
+ {
+ error(e.what());
+ return;
+ }
+ catch (...)
+ {
+ error("OCIOLookTransform: Unknown exception during _validate.");
+ return;
+ }
+
+ if(m_processor->isNoOp())
+ {
+ set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
+ } else {
+ set_out_channels(DD::Image::Mask_All);
+ }
+
+ DD::Image::PixelIop::_validate(for_real);
+}
+
+// Note that this is copied by others (OCIODisplay)
+void OCIOLookTransform::in_channels(int /* n unused */, DD::Image::ChannelSet& mask) const
+{
+ DD::Image::ChannelSet done;
+ foreach(c, mask)
+ {
+ if (DD::Image::colourIndex(c) < 3 && !(done & c))
+ {
+ done.addBrothers(c, 3);
+ }
+ }
+ mask += done;
+}
+
+// See Saturation::pixel_engine for a well-commented example.
+// Note that this is copied by others (OCIODisplay)
+void OCIOLookTransform::pixel_engine(
+ const DD::Image::Row& in,
+ int /* rowY unused */, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out)
+{
+ int rowWidth = rowXBound - rowX;
+
+ DD::Image::ChannelSet done;
+ foreach (requestedChannel, outputChannels)
+ {
+ // Skip channels which had their trios processed already,
+ if (done & requestedChannel)
+ {
+ continue;
+ }
+
+ // Pass through channels which are not selected for processing
+ // and non-rgb channels.
+ if (colourIndex(requestedChannel) >= 3)
+ {
+ out.copy(in, requestedChannel, rowX, rowXBound);
+ continue;
+ }
+
+ DD::Image::Channel rChannel = DD::Image::brother(requestedChannel, 0);
+ DD::Image::Channel gChannel = DD::Image::brother(requestedChannel, 1);
+ DD::Image::Channel bChannel = DD::Image::brother(requestedChannel, 2);
+
+ done += rChannel;
+ done += gChannel;
+ done += bChannel;
+
+ const float *rIn = in[rChannel] + rowX;
+ const float *gIn = in[gChannel] + rowX;
+ const float *bIn = in[bChannel] + rowX;
+
+ float *rOut = out.writable(rChannel) + rowX;
+ float *gOut = out.writable(gChannel) + rowX;
+ float *bOut = out.writable(bChannel) + rowX;
+
+ // OCIO modifies in-place
+ // Note: xOut can equal xIn in some circumstances, such as when the
+ // 'Black' (throwaway) scanline is uses. We thus must guard memcpy,
+ // which does not allow for overlapping regions.
+ if (rOut != rIn) memcpy(rOut, rIn, sizeof(float)*rowWidth);
+ if (gOut != gIn) memcpy(gOut, gIn, sizeof(float)*rowWidth);
+ if (bOut != bIn) memcpy(bOut, bIn, sizeof(float)*rowWidth);
+
+ try
+ {
+ OCIO::PlanarImageDesc img(rOut, gOut, bOut, NULL, rowWidth, /*height*/ 1);
+ m_processor->apply(img);
+ }
+ catch(const OCIO::Exception &e)
+ {
+ error(e.what());
+ }
+ catch (...)
+ {
+ error("OCIOLookTransform: Unknown exception during pixel_engine.");
+ }
+ }
+}
+
+const DD::Image::Op::Description OCIOLookTransform::description("OCIOLookTransform", build);
+
+const char* OCIOLookTransform::Class() const
+{
+ return description.name;
+}
+
+const char* OCIOLookTransform::displayName() const
+{
+ return description.name;
+}
+
+const char* OCIOLookTransform::node_help() const
+{
+ static const char * help = "OpenColorIO LookTransform\n\n"
+ "A 'look' is a named color transform, intended to modify the look of an "
+ "image in a 'creative' manner (as opposed to a colorspace definion which "
+ "tends to be technically/mathematically defined).\n\n"
+ "Examples of looks may be a neutral grade, to be applied to film scans "
+ "prior to VFX work, or a per-shot DI grade decided on by the director, "
+ "to be applied just before the viewing transform.\n\n"
+ "OCIOLooks must be predefined in the OpenColorIO configuration before usage, "
+ "and often reference per-shot/sequence LUTs/CCs.\n\n"
+ "See the look knob for further syntax details.\n\n"
+ "See opencolorio.org for look configuration customization examples.";
+ return help;
+}
+
+// This class is necessary in order to call knobsAtTheEnd(). Otherwise, the NukeWrapper knobs
+// will be added to the Context tab instead of the primary tab.
+class OCIOLookTransformNukeWrapper : public DD::Image::NukeWrapper
+{
+public:
+ OCIOLookTransformNukeWrapper(DD::Image::PixelIop* op) : DD::Image::NukeWrapper(op)
+ {
+ }
+
+ virtual void attach()
+ {
+ wrapped_iop()->attach();
+ }
+
+ virtual void detach()
+ {
+ wrapped_iop()->detach();
+ }
+
+ virtual void knobs(DD::Image::Knob_Callback f)
+ {
+ OCIOLookTransform* lookIop = dynamic_cast<OCIOLookTransform*>(wrapped_iop());
+ if(!lookIop) return;
+
+ DD::Image::NukeWrapper::knobs(f);
+
+ DD::Image::Tab_knob(f, "Context");
+ {
+ DD::Image::String_knob(f, &lookIop->m_contextKey1, "key1");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &lookIop->m_contextValue1, "value1");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &lookIop->m_contextKey2, "key2");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &lookIop->m_contextValue2, "value2");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &lookIop->m_contextKey3, "key3");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &lookIop->m_contextValue3, "value3");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+
+ DD::Image::String_knob(f, &lookIop->m_contextKey4, "key4");
+ DD::Image::Spacer(f, 10);
+ DD::Image::String_knob(f, &lookIop->m_contextValue4, "value4");
+ DD::Image::ClearFlags(f, DD::Image::Knob::STARTLINE);
+ }
+ }
+};
+
+static DD::Image::Op* build(Node *node)
+{
+ DD::Image::NukeWrapper *op = (new OCIOLookTransformNukeWrapper(new OCIOLookTransform(node)));
+ op->channels(DD::Image::Mask_RGB);
+ return op;
+}
diff --git a/src/nuke/OCIOLookTransform/OCIOLookTransform.h b/src/nuke/OCIOLookTransform/OCIOLookTransform.h
new file mode 100644
index 0000000..9526bfa
--- /dev/null
+++ b/src/nuke/OCIOLookTransform/OCIOLookTransform.h
@@ -0,0 +1,140 @@
+#ifndef INCLUDED_OCIO_NUKE_COLORSPACECONVERSION_H_
+#define INCLUDED_OCIO_NUKE_COLORSPACECONVERSION_H_
+
+// Include these early, for Nuke's headers under gcc 4.4.2.
+#include <memory>
+#include <cstdarg>
+
+#include <DDImage/PixelIop.h>
+#include <DDImage/Row.h>
+#include <DDImage/Knob.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+
+/*!
+ * Iop that uses OpenColorIO to perform colorspace conversions
+ */
+class OCIOLookTransform : public DD::Image::PixelIop {
+
+ protected:
+
+ bool m_hasColorSpaces; //!< Were colorspaces found for both input and output? If not, always error.
+
+ std::string m_look;
+ std::string m_lookhelp;
+
+ int m_dirIndex;
+ int m_inputColorSpaceIndex;
+ int m_outputColorSpaceIndex;
+
+ std::vector<std::string> m_colorSpaceNames; //!< list of input and output colorspace names (memory for const char* s below)
+ std::vector<const char*> m_inputColorSpaceCstrNames; //!< list for the pulldown list knob (used raw)
+ std::vector<const char*> m_outputColorSpaceCstrNames;
+
+ bool m_ignoreErrors;
+
+ OCIO::ConstContextRcPtr getLocalContext();
+
+ OCIO::ConstProcessorRcPtr m_processor;
+
+ /*! Controlled by hidden "version" knob, incremented to redraw image */
+ int m_reload_version;
+ public:
+
+ OCIOLookTransform(Node *node);
+
+ virtual ~OCIOLookTransform();
+
+ // These are public so the nuke wrapper can introspect into it
+ // TODO: use 'friend' instead
+ std::string m_contextKey1;
+ std::string m_contextValue1;
+ std::string m_contextKey2;
+ std::string m_contextValue2;
+ std::string m_contextKey3;
+ std::string m_contextValue3;
+ std::string m_contextKey4;
+ std::string m_contextValue4;
+
+ static const DD::Image::Op::Description description;
+
+ /*! Return the command name that will be stored in Nuke scripts. */
+ virtual const char *Class() const;
+
+ /*!
+ * Return a name for this class that will be shown to the user. The
+ * default implementation returns Class(). You can return a different
+ * (ie more user-friendly) name instead here, and there is no need for
+ * this to be unique.
+ *
+ * Nuke currently will remove any trailing digits and underscores from
+ * this and add a new number to make a unique name for the new node.
+ *
+ * \return "OCIOLookTransform"
+ */
+ virtual const char *displayName() const;
+
+ /*!
+ * Return help information for this node. This information is in the
+ * pop-up window that the user gets when they hit the [?] button in
+ * the lower-left corner of the control panel.
+ */
+ virtual const char *node_help() const;
+
+ /*!
+ * Define the knobs that will be presented in the control panel.
+ */
+ virtual void knobs(DD::Image::Knob_Callback f);
+
+ /*!
+ * Specify the channels required from input n to produce the channels
+ * in mask by modifying mask in-place. (At least one channel in the
+ * input is assumed.)
+ *
+ * Since colorspace conversions can have channel cross-talk, any rgb
+ * output channel requires all its rgb bretheren. (Non-rgb
+ * are passed through.)
+ */
+ virtual void in_channels(int n, DD::Image::ChannelSet& mask) const;
+
+ /*!
+ * Calculate the output pixel data.
+ * \param rowY vertical line number
+ * \param rowX inclusive left bound
+ * \param rowXBound exclusive right bound
+ * \param outputChannels a subset of out_channels(), the required channels to be produced
+ */
+ virtual void pixel_engine(
+ const DD::Image::Row& in,
+ int rowY, int rowX, int rowXBound,
+ DD::Image::ChannelMask outputChannels,
+ DD::Image::Row& out);
+
+ protected:
+
+ /*!
+ * Check that colorspaces are available, and that the transform
+ * is not a noop. (As OCIO whether a given transform is a noop, since it
+ * can do more analysis than just name matching.)
+ */
+ virtual void _validate(bool for_real);
+
+ /*!
+ * Ensure Node hash is reflects all parameters
+ */
+ virtual void append(DD::Image::Hash& nodehash);
+
+ /*!
+ * Hide and show UI elements based on other parameters.
+ Also handles reload button
+ */
+ virtual int knob_changed(DD::Image::Knob* k);
+
+};
+
+
+static DD::Image::Op* build(Node *node);
+
+#endif // INCLUDED_OCIO_NUKE_COLORSPACECONVERSION_H_
diff --git a/src/pyglue/CMakeLists.txt b/src/pyglue/CMakeLists.txt
new file mode 100644
index 0000000..07188ea
--- /dev/null
+++ b/src/pyglue/CMakeLists.txt
@@ -0,0 +1,106 @@
+if(CMAKE_FIRST_RUN)
+ message(STATUS "Python library to include 'lib' prefix: ${OCIO_PYGLUE_LIB_PREFIX}")
+endif()
+
+if(CMAKE_FIRST_RUN)
+ message(STATUS "Python ${PYTHON_VERSION} okay (UCS: ${PYTHON_UCS}), will build the Python bindings against ${PYTHON_INCLUDE}")
+ message(STATUS "Python variant path is ${PYTHON_VARIANT_PATH}")
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+ # Python breaks strict-aliasing rules. Disable the warning here.
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")
+endif()
+
+if(NOT WIN32)
+ find_package(PythonLibs)
+ if(NOT PYTHONLIBS_FOUND)
+ message(FATAL "Python libraries were not found, exiting.")
+ endif()
+ SET(PYTHON_INCLUDES ${PYTHON_INCLUDE_DIRS})
+endif()
+
+add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/src/pyglue/PyDoc.h
+ COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/src/pyglue/createPyDocH.py ${CMAKE_BINARY_DIR}/src/pyglue/PyDoc.h
+ COMMENT "Creating PyDoc.h")
+
+file( GLOB pyglue_src_files "${CMAKE_SOURCE_DIR}/src/pyglue/*.cpp" )
+
+add_library(PyOpenColorIO MODULE ${pyglue_src_files} ${CMAKE_BINARY_DIR}/src/pyglue/PyDoc.h)
+
+if(OCIO_USE_BOOST_PTR)
+ include_directories(
+ ${PYTHON_INCLUDE}
+ ${Boost_INCLUDE_DIR}
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${CMAKE_CURRENT_BINARY_DIR}
+ )
+else()
+ include_directories(
+ ${PYTHON_INCLUDE}
+ ${CMAKE_SOURCE_DIR}/export/
+ ${CMAKE_BINARY_DIR}/export/
+ ${CMAKE_CURRENT_BINARY_DIR}
+ )
+endif()
+
+# Exclude the 'lib' prefix from the name.
+if(NOT OCIO_PYGLUE_LIB_PREFIX)
+ set_property(TARGET PyOpenColorIO
+ PROPERTY PREFIX ""
+ )
+endif()
+
+if(WIN32)
+ if(OCIO_PYGLUE_LINK)
+ target_link_libraries(PyOpenColorIO OpenColorIO
+ debug ${PYTHON_LIB}/python26_d.lib
+ optimized ${PYTHON_LIB}/python26.lib)
+ else()
+ target_link_libraries(PyOpenColorIO OpenColorIO)
+ endif(OCIO_PYGLUE_LINK)
+else()
+ if(OCIO_PYGLUE_LINK)
+ message(STATUS "Linking python bindings against: ${PYTHON_LIBRARY}")
+ message(STATUS "Python library dirs: ${PYTHON_LIBRARY_DIRS}")
+ link_directories(${PYTHON_LIBRARY})
+ target_link_libraries(PyOpenColorIO OpenColorIO
+ ${PYTHON_LIBRARIES})
+ else()
+ target_link_libraries(PyOpenColorIO OpenColorIO)
+ endif(OCIO_PYGLUE_LINK)
+endif()
+
+# PyOpenColorIO so serves dual roles:
+# - First, to provide the C API function necessary to act as a cpython module,
+# (extern "C" PyMODINIT_FUNC initPyOpenColorIO(void)
+# - Second, to act as a normal shared library, providing the C++ API functions
+# to convert between C++ and python representation of the OCIO object.
+#
+# To fulfill this second role, as a shared libary, we must continue to define
+# so version.
+#
+# TODO: This wont let the normal shared library symbols work on OSX.
+# We should explore whether this should be built as a normal dylib, instead
+# of as a bundle. See https://github.com/imageworks/OpenColorIO/pull/175
+
+if(OCIO_PYGLUE_SONAME)
+ message(STATUS "Setting PyOCIO SOVERSION to: ${SOVERSION}")
+ set_target_properties(PyOpenColorIO PROPERTIES
+ VERSION ${OCIO_VERSION}
+ SOVERSION ${SOVERSION}
+ )
+endif()
+
+if(APPLE)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -undefined dynamic_lookup")
+endif()
+
+
+message("PYTHON_VARIANT_PATH: ${PYTHON_VARIANT_PATH}")
+
+install(TARGETS PyOpenColorIO DESTINATION ${CMAKE_INSTALL_EXEC_PREFIX}/${PYTHON_VARIANT_PATH})
+
+install(FILES ${CMAKE_SOURCE_DIR}/export/PyOpenColorIO/PyOpenColorIO.h
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/PyOpenColorIO/)
diff --git a/src/pyglue/DocStrings/AllocationTransform.py b/src/pyglue/DocStrings/AllocationTransform.py
new file mode 100644
index 0000000..26bdaa2
--- /dev/null
+++ b/src/pyglue/DocStrings/AllocationTransform.py
@@ -0,0 +1,54 @@
+
+class AllocationTransform:
+ """
+ Respans the 'expanded' range into the specified (often compressed) range.
+
+ Performs both squeeze (offset) and log transforms.
+ """
+ def __init__(self):
+ pass
+
+ def getAllocation(self):
+ """
+ getAllocation()
+
+ Returns the allocation specified in the transform. Allocation is an
+ enum, defined in Constants.
+
+ :return: Allocation
+ :rtype: string
+ """
+ pass
+
+ def setAllocation(self, hwalloc):
+ """
+ setAllocation(hwalloc)
+
+ Sets the allocation of the transform.
+
+ :param hwalloc: Allocation
+ :type hwalloc: object
+ """
+ pass
+
+ def getVars(self):
+ """
+ getVars()
+
+ Returns the allocation values specified in the transform.
+
+ :return: allocation values
+ :rtype: list of floats
+ """
+ pass
+
+ def setVars(self, vars):
+ """
+ setVars(pyvars)
+
+ Sets the allocation in the transform.
+
+ :param pyvars: list of floats
+ :type pyvars: object
+ """
+ pass
diff --git a/src/pyglue/DocStrings/CDLTransform.py b/src/pyglue/DocStrings/CDLTransform.py
new file mode 100644
index 0000000..63acbd2
--- /dev/null
+++ b/src/pyglue/DocStrings/CDLTransform.py
@@ -0,0 +1,141 @@
+
+class CDLTransform:
+ """
+ CDLTransform
+ """
+ def __init__(self):
+ pass
+
+ def equals(self):
+ pass
+
+ def getXML(self):
+ pass
+
+ def setXML(self, xmltext):
+ pass
+
+ def getSlope(self):
+ pass
+
+ def getOffset(self):
+ pass
+
+ def getPower(self):
+ pass
+
+ def getSOP(self):
+ pass
+
+ def getSat(self):
+ pass
+
+ def setSlope(self, slope):
+ """
+ setSlope(pyData)
+
+ Sets the slope ('S' part of SOP) in :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param pyData:
+ :type pyData: object
+ """
+ pass
+
+ def setOffset(self, offset):
+ """
+ setOffset(pyData)
+
+ Sets the offset ('O' part of SOP) in :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param pyData: list of three floats
+ :type pyData: object
+ """
+ pass
+
+ def setPower(self, power):
+ """
+ setPower(pyData)
+
+ Sets the power ('P' part of SOP) in :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param pyData: list of three floats
+ :type pyData: object
+ """
+ pass
+
+ def setSOP(self, sop):
+ """
+ setSOP(pyData)
+
+ Sets SOP in :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param pyData: list of nine floats
+ :type pyData: object
+ """
+ pass
+
+ def setSat(self, sat):
+ """
+ setSAT(pyData)
+
+ Sets SAT (saturation) in :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param pyData: saturation
+ :type pyData: float
+ """
+ pass
+
+ def getSatLumaCoefs(self):
+ """
+ getSatLumaCoefs(pyData)
+
+ Returns the SAT (saturation) and luma coefficients in :py:class:`CDLTransform`.
+
+ :return: saturation and luma coefficients
+ :rtype: list of floats
+ """
+ pass
+
+ def getID(self):
+ """
+ getID()
+
+ Returns the ID from :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :return: ID
+ :rtype: string
+ """
+ pass
+
+ def setID(self, id):
+ """
+ setID(str)
+
+ Sets the ID in :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param str: ID
+ :type str: string
+ """
+ pass
+
+ def getDescription(self):
+ """
+ getDescription()
+
+ Returns the description of :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :return: description
+ :rtype: string
+ """
+ pass
+
+ def setDescription(self, desc):
+ """
+ setDescription(str)
+
+ Sets the description of :py:class:`PyOpenColorIO.CDLTransform`.
+
+ :param str: description
+ :type str: string
+ """
+ pass
diff --git a/src/pyglue/DocStrings/ColorSpace.py b/src/pyglue/DocStrings/ColorSpace.py
new file mode 100644
index 0000000..caf351b
--- /dev/null
+++ b/src/pyglue/DocStrings/ColorSpace.py
@@ -0,0 +1,103 @@
+
+class ColorSpace:
+ """
+ A color space is the state of an image in terms of colorimetry and color
+ encoding. I.e., it defines how an image's color information needs to be
+ interpreted.
+
+ Transforming images between different color spaces is the primary
+ motivation for the OCIO library.
+
+ While a complete discussion of color spaces is beyond the scope of this
+ documentation, traditional uses would be to have color spaces describing
+ image capture devices, such as cameras and scanners, and internal
+ 'convenience' spaces, such as scene-linear and logarithmic.
+
+ Color spaces are specific to a particular image precision
+ (float32, uint8, etc.). The set of color spaces that provide equivalent
+ mappings (at different precisions) are referred to as a 'family'.
+
+ .. code-block:: python
+
+ import PyOpenColorIO as OCIO
+ config = OCIO.Config()
+
+ """
+ def __init__(self):
+ pass
+
+ def isEditable(self):
+ pass
+
+ def createEditableCopy(self):
+ pass
+
+ def getName(self):
+ pass
+
+ def setName(self, name):
+ pass
+
+ def getFamily(self):
+ pass
+
+ def setFamily(self, family):
+ pass
+
+ def getEqualityGroup(self):
+ pass
+
+ def setEqualityGroup(self, equalityGroup):
+ pass
+
+ def getDescription(self):
+ pass
+
+ def setDescription(self, desc):
+ pass
+
+ def getBitDepth(self):
+ pass
+
+ def setBitDepth(self, bitDepth):
+ pass
+
+ def isData(self):
+ """
+ ColorSpaces that are data are treated a bit special. Basically, any
+ colorspace transforms you try to apply to them are ignored. (Think
+ of applying a gamut mapping transform to an ID pass). Also, the
+ :py:class:`PyOpenColorIO.DisplayTransform` process obeys special
+ 'data min' and 'data max' args.
+
+ This is traditionally used for pixel data that represents non-color
+ pixel data, such as normals, point positions, ID information, etc.
+ """
+ pass
+
+ def setIsData(self, isData):
+ pass
+
+ def getAllocation(self):
+ """
+ If this colorspace needs to be transferred to a limited dynamic
+ range coding space (such as during display with a GPU path), use this
+ allocation to maximize bit efficiency.
+ """
+ pass
+
+ def setAllocation(self, allocation):
+ pass
+
+ def getAllocationVars(self):
+ pass
+
+ def setAllocationVars(self, vars):
+ pass
+
+ def getTransform(self):
+ pass
+
+ def setTransform(self, transform, direction):
+ pass
+
diff --git a/src/pyglue/DocStrings/ColorSpaceTransform.py b/src/pyglue/DocStrings/ColorSpaceTransform.py
new file mode 100644
index 0000000..a4de30b
--- /dev/null
+++ b/src/pyglue/DocStrings/ColorSpaceTransform.py
@@ -0,0 +1,51 @@
+
+class ColorSpaceTransform:
+ """
+ ColorSpaceTransform
+ """
+ def __init__(self):
+ pass
+
+ def getSrc(self):
+ """
+ getSrc()
+
+ Returns the name of the source ColorSpace in this transform.
+
+ :return: ColorSpace
+ :rtype: string
+ """
+ pass
+
+ def setSrc(self, srcname):
+ """
+ setSrc(srcname)
+
+ Sets the source ColorSpace in this transform.
+
+ :param str: source ColorSpace
+ :type str: string
+ """
+ pass
+
+ def getDst(self):
+ """
+ getDst()
+
+ Returns the name of the destination ColorSpace in this transform.
+
+ :return: ColorSpace
+ :rtype: string
+ """
+ pass
+
+ def setDst(self, dstname):
+ """
+ setDst(dstname)
+
+ Sets the destination ColorSpace in this transform.
+
+ :param str: destination ColorSpace
+ :type str: string
+ """
+ pass
diff --git a/src/pyglue/DocStrings/Config.py b/src/pyglue/DocStrings/Config.py
new file mode 100644
index 0000000..688e822
--- /dev/null
+++ b/src/pyglue/DocStrings/Config.py
@@ -0,0 +1,527 @@
+
+class Config:
+ """
+ Config
+ """
+
+ def __init__(self):
+ pass
+
+ def CreateFromEnv(self):
+ """
+ CreateFromEnv()
+
+ Create a :py:class:`PyOpenColorIO.Config` object using the environment variable.
+
+ :returns: Config object
+ """
+ pass
+
+ def CreateFromFile(self):
+ """
+ CreateFromFile(filename)
+
+ Create a :py:class:`PyOpenColorIO.Config` object using the information in a file.
+
+ :param filename: name of file
+ :type filename: string
+ :return: Config object
+ """
+ pass
+
+ def isEditable(self):
+ """
+ isEditable()
+
+ Returns whether Config is editable.
+
+ The configurations returned from
+ :py:function:`PyOpenColorIO.GetCurrentConfig` are not editable, and if
+ you want to edit them you can use
+ :py:method:`PyOpenColorIO.Config.createEditableCopy`.
+
+ If you attempt to call any of the set functions on a noneditable
+ Config, an exception will be thrown.
+
+ :return: state of :py:class:`PyOpenColorIO.Config`'s editability
+ :rtype: bool
+ """
+ pass
+
+ def createEditableCopy(self):
+ """
+ createEditableCopy()
+
+ Returns an editable copy of :py:class:`PyOpenColorIO.Config`.
+
+ :return: editable copy of :py:class:`PyOpenColorIO.Config`
+ :rtype: Config object
+ """
+ pass
+
+ def sanityCheck(self):
+ """
+ sanityCheck()
+
+ This will throw an exception if :py:class:`PyOpenColorIO.Config` is
+ malformed. The most common error occurs when references are made to
+ colorspaces that do not exist.
+ """
+ pass
+
+ def getDescription(self):
+ """
+ getDescription()
+
+ Returns the stored description of :py:class:`PyOpenColorIO.Config`.
+
+ :return: stored description of :py:class:`PyOpenColorIO.Config`
+ :rtype: string
+ """
+ pass
+
+ def setDescription(self, desc):
+ """
+ setDescription(desc)
+
+ Sets the description of :py:class:`PyOpenColorIO.Config`.
+
+ :param desc: description of :py:class:`PyOpenColorIO.Config`
+ :type desc: string
+ """
+ pass
+
+ def serialize(self):
+ """
+ serialize()
+
+ Returns the string representation of :py:class:`PyOpenColorIO.Config`
+ in YAML text form. This is typically stored on disk in a file with the
+ .ocio extension.
+
+ :return: :py:class:`PyOpenColorIO.Config` in YAML text form
+ :rtype: string
+ """
+ pass
+
+ def getCacheID(self, pycontext=None):
+ """
+ getCacheID([, pycontext])
+
+ This will produce a hash of the all colorspace definitions, etc.
+
+ All external references, such as files used in FileTransforms, etc.,
+ will be incorporated into the cacheID. While the contents of the files
+ are not read, the file system is queried for relavent information
+ (mtime, inode) so that the :py:class:`PyOpenColorIO.Config`'s cacheID
+ will change when the underlying luts are updated.
+
+ If a context is not provided, the current Context will be used. If a
+ null context is provided, file references will not be taken into
+ account (this is essentially a hash of :py:method:`PyOpenColorIO.Config.serialize`).
+
+ :param pycontext: optional
+ :type pycontext: object
+ :return: hash of :py:class:`PyOpenColorIO.Config`
+ :rtype: string
+ """
+ pass
+
+ def getCurrentContext(self):
+ """
+ getCurrentContext()
+
+ Return the current context, which is essentially a record of all
+ the environment variables that are available for use in file path
+ lookups.
+
+ :return: context
+ :rtype: pycontext
+ """
+ pass
+
+ def getSearchPath(self):
+ """
+ getSearchPath()
+
+ Returns the search path.
+
+ :return: search path
+ :rtype: string
+ """
+ pass
+
+ def setSearchPath(self, searchpath):
+ """
+ setSearchPath(path)
+
+ Sets the search path.
+
+ :param path: the search path
+ :type path: string
+ """
+ pass
+
+ def getWorkingDir(self):
+ """
+ getWorkingDir()
+
+ Returns the working directory.
+
+ :return: the working directory
+ :rtype path: string
+ """
+ pass
+
+ def setWorkingDir(self, dirname):
+ """
+ setWorkingDir(path)
+
+ Sets the working directory.
+
+ :param path: the working directory
+ :type path: string
+ """
+ pass
+
+ def getColorSpaces(self):
+ """
+ getColorSpaces()
+
+ Returns all the ColorSpaces defined in :py:class:`Config`.
+
+ :return: ColorSpaces in :py:class:`PyOpenColorIO.Config`
+ :rtype: tuple
+ """
+ pass
+
+ def getColorSpace(self, name):
+ """
+ getColorSpace(name)
+
+ Returns the data for the specified color space in :py:class:`Config`.
+
+ This will return null if the specified name is not found.
+
+ :param name: name of color space
+ :type name: string
+ :return: data for specified color space
+ :rtype: pyColorSpace object
+ """
+ pass
+
+ def addColorSpace(self, colorSpace):
+ """
+ addColorSpace(pyColorSpace)
+
+ Add a specified color space to :py:class:`PyOpenColorIO.Config`.
+
+ :param pyColorSpace: color space
+ :type pyColorSpace: object
+
+ .. note::
+ If another color space is already registered with the same name,
+ this will overwrite it.
+ """
+ pass
+
+ def clearColorSpaces(self):
+ """
+ clearColorSpaces()
+
+ Clear the color spaces in :py:class:`PyOpenColorIO.Config`.
+ """
+ pass
+
+ def parseColorSpaceFromString(self, str):
+ """
+ parseColorSpaceFromString(str)
+
+ Parses out the color space from a string.
+
+ Given the specified string, gets the longest, right-most color space substring.
+ * If strict parsing is enabled, and no color space is found, return an empty string.
+ * If strict parsing is disabled, return the default role, if defined.
+ * If the default role is not defined, return an empty string.
+
+ :param str: ColorSpace data
+ :type str: string
+ :return: parsed data
+ :rtype: string
+ """
+ pass
+
+ def setRole(self, role, csname):
+ """
+ setRole(role, csname)
+
+ Set a role's ColorSpace.
+
+ Setting the colorSpaceName name to a null string unsets it.
+
+ :param role: role whose ColorSpace will be set
+ :type role: string
+ :param csname: name of ColorSpace
+ :type csname: string
+ """
+ pass
+
+ def getDefaultDisplay(self):
+ """
+ getDefaultDisplay()
+
+ Returns the default display set in :py:class:`PyOpenColorIO.Config`.
+
+ :return: default display
+ :rtype: string
+ """
+ pass
+
+ def getDisplays(self):
+ """
+ getDisplays()
+
+ Returns all the displays defined in :py:class:`PyOpenColorIO.Config`.
+
+ :return: displays in :py:class:`Config`
+ :rtype: list of strings
+ """
+ pass
+
+ def getDefaultView(self, display):
+ """
+ getDefaultView(display)
+
+ Returns the default view of :py:class:`PyOpenColorIO.Config`.
+
+ :param display: default view
+ :type display: string
+ :return: view
+ :rtype: string
+ """
+ pass
+
+ def getViews(self, display):
+ """
+ getViews(display)
+
+ Returns all the views defined in :py:class:`PyOpenColorIO.Config`.
+
+ :param display: views in :py:class:`Config`
+ :type display: string
+ :return: views in :py:class:`Config`.
+ :rtype: list of strings
+ """
+ pass
+
+ def getDisplayColorSpaceName(self, display, view):
+ """
+ getDisplayColorSpaceName(display, view)
+
+ Returns the ColorSpace name corresponding to the display and view
+ combination in :py:class:`PyOpenColorIO.Config`.
+
+ :param display: display
+ :type display: string
+ :param view: view
+ :type view: string
+ :return: display color space name
+ :rtype: string
+ """
+ pass
+
+ def getDisplayLooks(self, display, view):
+ """
+ getDisplayLooks(display, view)
+
+ Returns the looks corresponding to the display and view combination in
+ :py:class:`PyOpenColorIO.Config`.
+
+ :param display: display
+ :type display: string
+ :param view: view
+ :type view: string
+ :return: looks
+ :rtype: string
+ """
+ pass
+
+ def addDisplay(self, display, view, csname, looks=None):
+ """
+ addDisplay(display, view, colorSpaceName[, looks])
+
+ NEEDS WORK
+
+ :param display:
+ :type display: string
+ :param view:
+ :type view: string
+ :param colorSpaceName:
+ :type colorSpaceName: string
+ :param looks: optional
+ :type looks: string
+ """
+ pass
+
+ def clearDisplays(self):
+ """
+ clearDisplays()
+ """
+ pass
+
+ def setActiveDisplays(self, dislpays):
+ """
+ setActiveDisplays(displays)
+
+ Sets the active displays in :py:class:`PyOpenColorIO.Config`.
+
+ :param displays: active displays
+ :type displays: string
+ """
+ pass
+
+ def getActiveDisplays(self):
+ """
+ getActiveDisplays()
+
+ Returns the active displays in :py:class:`PyOpenColorIO.Config`.
+
+ :return: active displays
+ :rtype: string
+ """
+ pass
+
+ def setActiveViews(self, views):
+ """
+ setActiveViews(views)
+
+ Sets the active views in :py:class:`PyOpenColorIO.Config`.
+
+ :param views: active views
+ :type views: string
+ """
+ pass
+
+ def getActiveViews(self):
+ """
+ getActiveViews()
+
+ Returns the active views in :py:class:`PyOpenColorIO.Config`.
+
+ :return: active views
+ :rtype: string
+ """
+ pass
+
+ def getDefaultLumaCoefs(self):
+ """
+ getDefaultLumaCoefs()
+
+ Returns the default luma coefficients in :py:class:`PyOpenColorIO.Config`.
+
+ :return: luma coefficients
+ :rtype: list of floats
+ """
+ pass
+
+ def setDefaultLumaCoefs(self, coefficients):
+ """
+ setDefaultLumaCoefs(pyCoef)
+
+ Sets the default luma coefficients in :py:class:`PyOpenColorIO.Config`.
+
+ :param pyCoef: luma coefficients
+ :type pyCoef: object
+ """
+ pass
+
+ def getLook(self, lookname):
+ """
+ getLook(str)
+
+ Returns the information of a specified look in
+ :py:class:`PyOpenColorIO.Config`.
+
+ :param str: look
+ :type str: string
+ :return: specified look
+ :rtype: look object
+ """
+ pass
+
+ def getLooks(self):
+ """
+ getLooks()
+
+ Returns a list of all the looks defined in
+ :py:class:`PyOpenColorIO.Config`.
+
+ :return: looks
+ :rtype: tuple of look objects
+ """
+ pass
+
+ def addLook(self, look):
+ """
+ addLook(pylook)
+
+ Adds a look to :py:class:`PyOpenColorIO.Config`.
+
+ :param pylook: look
+ :type pylook: look object
+ """
+ pass
+
+ def clearLooks(self):
+ """
+ clearLooks()
+
+ Clear looks in :py:class:`PyOpenColorIO.Config`.
+ """
+ pass
+
+ def getProcessor(self, arg1, arg2=None, direction=None, context=None):
+ """
+ getProcessor(arg1[, arg2[, direction[, context]])
+
+ Returns a processor for a specified transform.
+
+ Although this is not often needed, it allows for the reuse of atomic
+ OCIO functionality, such as applying an individual LUT file.
+
+ There are two canonical ways of creating a
+ :py:class:`PyOpenColorIO.Processor`:
+
+ #. Pass a transform into arg1, in which case arg2 will be ignored.
+ #. Set arg1 as the source and arg2 as the destination. These can be
+ ColorSpace names, objects, or roles.
+
+ Both arguments, ``direction`` (of transform) and ``context``, are
+ optional and respected for both methods of
+ :py:class:`PyOpenColorIO.Processor` creation.
+
+ This will fail if either the source or destination color space is null.
+
+ See Python: Processor for more details.
+
+ .. note::
+ This may provide higher fidelity than anticipated due to internal
+ optimizations. For example, if inputColorSpace and outputColorSpace
+ are members of the same family, no conversion will be applied, even
+ though, strictly speaking, quantization should be added.
+
+ If you wish to test these calls for quantization characteristics,
+ apply in two steps; the image must contain RGB triples (though
+ arbitrary numbers of additional channels can be optionally
+ supported using the pixelStrideBytes arg). ???
+
+ :param arg1:
+ :type arg1: object
+ :param arg2: ignored if arg1 is a transform
+ :type arg2: object
+ :param direction: optional
+ :type direction: string
+ :param context: optional
+ :type context: object
+ """
+ pass
diff --git a/src/pyglue/DocStrings/Constants.py b/src/pyglue/DocStrings/Constants.py
new file mode 100644
index 0000000..a58a38c
--- /dev/null
+++ b/src/pyglue/DocStrings/Constants.py
@@ -0,0 +1,43 @@
+
+class Constants:
+
+ def __init__(self):
+ pass
+
+ def GetInverseTransformDirection(self, direction):
+ """
+ GetInverseTransformDirection(direction)
+
+ :param s:
+ :param type: string
+ """
+ pass
+
+ def CombineTransformDirections(self, dir1, dir2):
+ """
+ CombineTransformDirections(dir1, dir2)
+
+ :param s1:
+ :param type: string
+ :param s2:
+ :param type: string
+ """
+ pass
+
+ def BitDepthIsFloat(self, bitDepth):
+ """
+ BitDepthIsFloat(bitDepth)
+
+ :param s:
+ :param type: string
+ """
+ pass
+
+ def BitDepthToInt(self, bitDepth):
+ """
+ BitDepthToInt(bitDepth)
+
+ :param s:
+ :param type: string
+ """
+ pass
diff --git a/src/pyglue/DocStrings/Context.py b/src/pyglue/DocStrings/Context.py
new file mode 100644
index 0000000..ff73dbf
--- /dev/null
+++ b/src/pyglue/DocStrings/Context.py
@@ -0,0 +1,32 @@
+
+class Context:
+ """
+ Context
+ """
+ def __init__(self):
+ pass
+ def isEditable(self):
+ pass
+ def createEditableCopy(self):
+ pass
+ def getCacheID(self):
+ pass
+ def getSearchPath(self):
+ pass
+ def setSearchPath(self, searchPath):
+ pass
+ def getWorkingDir(self):
+ pass
+ def setWorkingDir(self, workingDir):
+ pass
+ def getStringVar(self):
+ pass
+ def setStringVar(self, stringVar):
+ pass
+ def loadEnvironment(self):
+ pass
+ def resolveStringVar(self, stringVar):
+ pass
+ def resolveFileLocation(self, fileLocation):
+ pass
+
diff --git a/src/pyglue/DocStrings/DisplayTransform.py b/src/pyglue/DocStrings/DisplayTransform.py
new file mode 100644
index 0000000..2d68ac3
--- /dev/null
+++ b/src/pyglue/DocStrings/DisplayTransform.py
@@ -0,0 +1,222 @@
+
+class DisplayTransform:
+ """
+ Used to create transforms for displays.
+ """
+ def __init__(self):
+ pass
+
+ def getInputColorSpaceName(self):
+ """
+ getInputColorSpaceName()
+
+ Returns the name of the input ColorSpace of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: name of input ColorSpace
+ :rtype: string
+ """
+ pass
+
+ def setInputColorSpaceName(self, name):
+ """
+ setInputColorSpaceName(name)
+
+ Sets the name of the input ColorSpace of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param name: name of input ColorSpace
+ :type name: string
+ """
+ pass
+
+ def getLinearCC(self):
+ """
+ getLinearCC()
+
+ Returns the linear CC transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: linear CC transform
+ :rtype: object
+ """
+ pass
+
+ def setLinearCC(self, transform):
+ """
+ setLinearCC(pyCC)
+
+ Sets the linear CC transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param pyCC: linear CC
+ :type pyCC: object
+ """
+ pass
+
+ def getColorTimingCC(self):
+ """
+ getColorTimingCC()
+
+ Returns the color timing CC transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: color timing CC transform
+ :rtype: object
+ """
+ pass
+
+ def setColorTimingCC(self, transform):
+ """
+ setColorTimingCC(pyCC)
+
+ Sets the color timing CC transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param pyCC: color timing CC
+ :type pyCC: object
+ """
+ pass
+
+ def getChannelView(self):
+ """
+ getChannelView()
+
+ Returns the channel view of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: channel view
+ :rtype: object
+ """
+ pass
+
+ def setChannelView(self, transform):
+ """
+ setChannelView(pyCC)
+
+ Sets the channel view transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param pyCC: channel view transform
+ :type pyCC: object
+ """
+ pass
+
+ def getDisplay(self):
+ """
+ getDisplay()
+
+ Returns the display of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: display
+ :rtype: string
+ """
+ pass
+
+ def setDisplay(self, displayName):
+ """
+ setDisplay(str)
+
+ Sets the display of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param str: display
+ :type str: string
+ """
+ pass
+
+ def getView(self):
+ """
+ getView()
+
+ Returns the view of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: view
+ :rtype: string
+ """
+ pass
+
+ def setView(self, viewName):
+ """
+ setView(str)
+
+ Sets the view of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param str: view
+ :type str: string
+ """
+ pass
+
+ def getDisplayCC(self):
+ """
+ getDisplayCC()
+
+ Returns the display CC transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :return: display CC
+ :rtype: object
+ """
+ pass
+
+ def setDisplayCC(self, transform):
+ """
+ setDisplayCC(pyCC)
+
+ Sets the display CC transform of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param pyCC: display CC
+ :type pyCC: object
+ """
+ pass
+
+ def getLooksOverride(self):
+ """
+ getLooksOverride()
+
+ Returns the looks in :py:class:`PyOpenColorIO.DisplayTransform` that's
+ overriding :py:class:`PyOpenColorIO.Config`'s.
+
+ :return: looks override
+ :rtype: string
+ """
+ pass
+
+ def setLooksOverride(self, looksStr):
+ """
+ setLooksOverride(str)
+
+ Sets the looks override of :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param str: looks override
+ :type str: string
+ """
+ pass
+
+ def getLooksOverrideEnabled(self):
+ """
+ getLooksOverrideEnabled()
+
+ Returns whether the looks override of
+ :py:class:`PyOpenColorIO.DisplayTransform` is enabled.
+
+ :return: looks override enabling
+ :rtype: bool
+ """
+ pass
+
+ def setLooksOverrideEnabled(self, enabled):
+ """
+ setLooksOverrideEnabled(enabled)
+
+ Sets the looks override enabling of
+ :py:class:`PyOpenColorIO.DisplayTransform`.
+
+ :param enabled: looks override enabling
+ :type enabled: object
+ """
+ pass
diff --git a/src/pyglue/DocStrings/Exception.py b/src/pyglue/DocStrings/Exception.py
new file mode 100644
index 0000000..75bba8e
--- /dev/null
+++ b/src/pyglue/DocStrings/Exception.py
@@ -0,0 +1,11 @@
+
+class Exception:
+ """
+ An exception class to throw for errors detected at runtime.
+
+ .. warning::
+ All functions in the Config class can potentially throw this exception.
+ """
+ def __init__(self):
+ pass
+
diff --git a/src/pyglue/DocStrings/ExceptionMissingFile.py b/src/pyglue/DocStrings/ExceptionMissingFile.py
new file mode 100644
index 0000000..6aa102a
--- /dev/null
+++ b/src/pyglue/DocStrings/ExceptionMissingFile.py
@@ -0,0 +1,11 @@
+
+class ExceptionMissingFile:
+ """
+ An exception class for errors detected at runtime, thrown when OCIO cannot
+ find a file that is expected to exist. This is provided as a custom type to
+ distinguish cases where one wants to continue looking for missing files,
+ but wants to properly fail for other error conditions.
+ """
+ def __init__(self):
+ pass
+
diff --git a/src/pyglue/DocStrings/ExponentTransform.py b/src/pyglue/DocStrings/ExponentTransform.py
new file mode 100644
index 0000000..930bb39
--- /dev/null
+++ b/src/pyglue/DocStrings/ExponentTransform.py
@@ -0,0 +1,31 @@
+
+class ExponentTransform:
+ """
+ ExponentTransform
+ """
+ def __init__(self):
+ pass
+
+ def getValue(self):
+ """
+ getValue()
+
+ Returns the values in the exponent transform of
+ :py:class:`PyOpenColorIO.ExponentTransform`.
+
+ :return: exponent transform values
+ :rtype: list of floats
+ """
+ pass
+
+ def setValue(self, value):
+ """
+ setValue()
+
+ Sets the values in the exponent transform of
+ :py:class:`PyOpenColorIO.ExponentTransform`.
+
+ :param pyData: exponent transform values
+ :type pyData: list of 4 floats
+ """
+ pass
diff --git a/src/pyglue/DocStrings/FileTransform.py b/src/pyglue/DocStrings/FileTransform.py
new file mode 100644
index 0000000..05a7026
--- /dev/null
+++ b/src/pyglue/DocStrings/FileTransform.py
@@ -0,0 +1,19 @@
+
+class FileTransform:
+ """
+ FileTransform
+ """
+ def __init__(self):
+ pass
+ def getSrc(self):
+ pass
+ def setSrc(self, src):
+ pass
+ def getCCCId(self):
+ pass
+ def setCCCId(self, cccid):
+ pass
+ def getInterpolation(self):
+ pass
+ def setInterpolation(self, interp):
+ pass
diff --git a/src/pyglue/DocStrings/GroupTransform.py b/src/pyglue/DocStrings/GroupTransform.py
new file mode 100644
index 0000000..80a5bf8
--- /dev/null
+++ b/src/pyglue/DocStrings/GroupTransform.py
@@ -0,0 +1,21 @@
+
+class GroupTransform:
+ """
+ GroupTransform
+ """
+ def __init__(self):
+ pass
+ def getTransform(self):
+ pass
+ def getTransforms(self):
+ pass
+ def setTransforms(self, transforms):
+ pass
+ def size(self):
+ pass
+ def push_back(self, transform):
+ pass
+ def clear(self):
+ pass
+ def empty(self):
+ pass
diff --git a/src/pyglue/DocStrings/LogTransform.py b/src/pyglue/DocStrings/LogTransform.py
new file mode 100644
index 0000000..ee823bb
--- /dev/null
+++ b/src/pyglue/DocStrings/LogTransform.py
@@ -0,0 +1,26 @@
+
+class LogTransform:
+ """
+ LogTransform
+ """
+ def __init__(self):
+ pass
+
+ def getBase(self):
+ """
+ getBase()
+
+ Returns the base of :py:class:`PyOpenColorIO.LogTransform`.
+ """
+ pass
+
+ def setBase(self, base):
+ """
+ setBase(base)
+
+ Sets the base in :py:class:`PyOpenColorIO.LogTransform`.
+
+ :param base: base of log transform
+ :type base: float
+ """
+ pass
diff --git a/src/pyglue/DocStrings/Look.py b/src/pyglue/DocStrings/Look.py
new file mode 100644
index 0000000..787fb5c
--- /dev/null
+++ b/src/pyglue/DocStrings/Look.py
@@ -0,0 +1,35 @@
+
+class Look:
+ """
+ The *Look* is an 'artistic' image modification, in a specified image state.
+
+ The processSpace defines the ColorSpace the image is required to be in, for
+ the math to apply correctly.
+ """
+ def __init__(self):
+ pass
+
+ def isEditable(self):
+ pass
+
+ def createEditableCopy(self):
+ pass
+
+ def getName(self):
+ pass
+
+ def setName(self, name):
+ pass
+
+ def getProcessSpace(self):
+ pass
+
+ def setProcessSpace(self, csname):
+ pass
+
+ def getTransform(self):
+ pass
+
+ def setTransform(self, transform):
+ pass
+
diff --git a/src/pyglue/DocStrings/LookTransform.py b/src/pyglue/DocStrings/LookTransform.py
new file mode 100644
index 0000000..9b0c62a
--- /dev/null
+++ b/src/pyglue/DocStrings/LookTransform.py
@@ -0,0 +1,19 @@
+
+class LookTransform:
+ """
+ LookTransform
+ """
+ def __init__(self):
+ pass
+ def getSrc(self):
+ pass
+ def setSrc(self, srcname):
+ pass
+ def getDst(self):
+ pass
+ def setDst(self, dstname):
+ pass
+ def getLooks(self):
+ pass
+ def setLooks(self, looks):
+ pass
diff --git a/src/pyglue/DocStrings/MatrixTransform.py b/src/pyglue/DocStrings/MatrixTransform.py
new file mode 100644
index 0000000..8b89ca5
--- /dev/null
+++ b/src/pyglue/DocStrings/MatrixTransform.py
@@ -0,0 +1,29 @@
+
+class MatrixTransform:
+ """
+ MatrixTransfom
+ """
+ def __init__(self):
+ pass
+ def getValue(self):
+ pass
+ def setValue(self, value):
+ pass
+ def getMatrix(self):
+ pass
+ def setMatrix(self, matrix):
+ pass
+ def getOffset(self):
+ pass
+ def setOffset(self, offset):
+ pass
+ def Identity(self):
+ pass
+ def Fit(self):
+ pass
+ def Sat(self):
+ pass
+ def Scale(self):
+ pass
+ def View(self):
+ pass
diff --git a/src/pyglue/DocStrings/OpenColorIO.py b/src/pyglue/DocStrings/OpenColorIO.py
new file mode 100644
index 0000000..0b7e376
--- /dev/null
+++ b/src/pyglue/DocStrings/OpenColorIO.py
@@ -0,0 +1,17 @@
+
+class OpenColorIO:
+ """
+ OpenColorIO API
+ """
+ def __init__(self):
+ pass
+ def ClearAllCaches(self):
+ pass
+ def GetLoggingLevel(self):
+ pass
+ def SetLoggingLevel(self, level):
+ pass
+ def GetCurrentConfig(self):
+ pass
+ def SetCurrentConfig(self, config):
+ pass
diff --git a/src/pyglue/DocStrings/Processor.py b/src/pyglue/DocStrings/Processor.py
new file mode 100644
index 0000000..7ce02bf
--- /dev/null
+++ b/src/pyglue/DocStrings/Processor.py
@@ -0,0 +1,141 @@
+
+class Processor:
+ """
+ Processor is the baked representation of a particular color transform.
+ Once you have a process for a particular transform created, you can hang
+ onto it to efficiently transform pixels.
+
+ Processors can only be created from the `PyOpenColorIO.Config`
+ getProcessor(...) call.
+ """
+
+ def __init__(self):
+ pass
+
+ def isNoOp(self):
+ """
+ isNoOp()
+
+ Returns whether the actual transformation represented by
+ :py:class:`PyOpenColorIO.Processor` is a no-op.
+
+ :return: whether transform is a no-op
+ :rtype: bool
+ """
+ pass
+
+ def hasChannelCrosstalk(self):
+ """
+ hasChannelCrosstalk()
+
+ Returns whether the transformation of
+ :py:class:`PyOpenColorIO.Processor` introduces crosstalk between the
+ image channels.
+
+ :return: whether there's crosstalk between channels
+ :rtype: bool
+ """
+ pass
+
+ def getMetadata(self):
+ """
+ getMetadata()
+
+ Returns information about the process that generated this processor.
+
+ :return: processor metadata
+ :rtype: `PyOpenColorIO.ProcessorMetadata`
+ """
+ pass
+
+ def applyRGB(self, pixeldata):
+ """
+ applyRGB(pixeldata)
+
+ Apply the RGB part of the transform represented by
+ :py:class:`PyOpenColorIO.Processor` to an image.
+
+ :param pixeldata: rgbrgb... array (length % 3 == 0)
+ :type pixeldata: object
+ :return: color converted pixeldata
+ :rtype: list
+ """
+ pass
+
+ def applyRGBA(self, pixeldata):
+ """
+ applyRGBA(pixeldata)
+
+ Apply the RGB and alpha part of the transform represented by
+ :py:class:`PyOpenColorIO.Processor` to an image.
+
+ :param pixeldata: rgbargba... array (length % 4 == 0)
+ :type pixeldata: object
+ :return: color converted pixeldata
+ :rtype: list
+ """
+ pass
+
+ def getCpuCacheID(self):
+ """
+ getCpuCacheID()
+
+ Returns the cache ID of the CPU that :py:class:`PyOpenColorIO.Processor`
+ will run on.
+
+ :return: CPU cache ID
+ :rtype: string
+ """
+ pass
+
+ def getGpuShaderText(self, shaderDesc):
+ """
+ getGpuShaderText(shaderDesc)
+
+ Returns the GPU shader text.
+
+ :param shaderDesc: define 'language','functionName','lut3DEdgeLen'
+ :type shaderDesc: dict
+ :return: GPU shader text
+ :rtype: string
+ """
+ pass
+
+ def getGpuShaderTextCacheID(self, shaderDesc):
+ """
+ getGpuShaderTextCacheID(shaderDesc)
+
+ Returns the GPU shader text cache ID.
+
+ :param shaderDesc: define 'language','functionName','lut3DEdgeLen'
+ :type shaderDesc: dict
+ :return: GPU shader text cache ID
+ :rtype: string
+ """
+ pass
+
+ def getGpuLut3D(self, shaderDesc):
+ """
+ getGpuLut3D(shaderDesc)
+
+ Returns the GPU LUT 3D.
+
+ :param shaderDesc: define 'language','functionName','lut3DEdgeLen'
+ :type shaderDesc: dict
+ :return: GPU LUT 3D
+ :rtype: list
+ """
+ pass
+
+ def getGpuLut3DCacheID(self, shaderDesc):
+ """
+ getGpuLut3DCacheID(shaderDesc)
+
+ Returns the GPU 3D LUT cache ID.
+
+ :param shaderDesc: two params
+ :type shaderDesc: dict
+ :return: GPU 3D LUT cache ID
+ :rtype: string
+ """
+ pass
diff --git a/src/pyglue/DocStrings/ProcessorMetadata.py b/src/pyglue/DocStrings/ProcessorMetadata.py
new file mode 100644
index 0000000..2e1d21a
--- /dev/null
+++ b/src/pyglue/DocStrings/ProcessorMetadata.py
@@ -0,0 +1,34 @@
+
+class ProcessorMetadata:
+ """
+ ProcessorMetadata
+
+ This contains meta information about the process that generated
+ this processor. The results of these functions do not
+ impact the pixel processing.
+
+ """
+ def __init__(self):
+ pass
+
+ def getFiles(self):
+ """
+ getFiles()
+
+ Returns a list of file references used internally by this processor
+
+ :return: list of filenames
+ :rtype: list
+ """
+ pass
+
+ def getLooks(self):
+ """
+ getLooks()
+
+ Returns a list of looks used internally by this processor
+
+ :return: list of look names
+ :rtype: list
+ """
+ pass
diff --git a/src/pyglue/DocStrings/Transform.py b/src/pyglue/DocStrings/Transform.py
new file mode 100644
index 0000000..b0819be
--- /dev/null
+++ b/src/pyglue/DocStrings/Transform.py
@@ -0,0 +1,19 @@
+
+class Transform:
+ """
+ These are typically only needed when creating or manipulating configurations.
+ """
+ def __init__(self):
+ pass
+
+ def isEditable(self):
+ pass
+
+ def createEditableCopy(self):
+ pass
+
+ def getDirection(self):
+ pass
+
+ def setDirection(self):
+ pass
diff --git a/src/pyglue/DocStrings/__init__.py b/src/pyglue/DocStrings/__init__.py
new file mode 100644
index 0000000..6afe720
--- /dev/null
+++ b/src/pyglue/DocStrings/__init__.py
@@ -0,0 +1,23 @@
+
+from Exception import *
+from ExceptionMissingFile import *
+from OpenColorIO import *
+from Constants import *
+from Config import *
+from ColorSpace import *
+from Processor import *
+from ProcessorMetadata import *
+from Context import *
+from Look import *
+from Transform import *
+
+from AllocationTransform import *
+from CDLTransform import *
+from ColorSpaceTransform import *
+from DisplayTransform import *
+from ExponentTransform import *
+from FileTransform import *
+from GroupTransform import *
+from LogTransform import *
+from LookTransform import *
+from MatrixTransform import *
diff --git a/src/pyglue/PyAllocationTransform.cpp b/src/pyglue/PyAllocationTransform.cpp
new file mode 100644
index 0000000..a977274
--- /dev/null
+++ b/src/pyglue/PyAllocationTransform.cpp
@@ -0,0 +1,300 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+//Rarely used. could use a log transform instead. This can sample by log when doing the offset to make best use of the data.
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddAllocationTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_AllocationTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_AllocationTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_AllocationTransformType );
+ PyModule_AddObject(m, "AllocationTransform",
+ (PyObject *)&PyOCIO_AllocationTransformType);
+
+ return true;
+ }
+
+ /*
+ bool IsPyAllocationTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_AllocationTransformType);
+ }
+ */
+
+ ConstAllocationTransformRcPtr GetConstAllocationTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstAllocationTransformRcPtr transform = \
+ DynamicPtrCast<const AllocationTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.AllocationTransform.");
+ }
+ return transform;
+ }
+
+ AllocationTransformRcPtr GetEditableAllocationTransform(PyObject * pyobject)
+ {
+ AllocationTransformRcPtr transform = \
+ DynamicPtrCast<AllocationTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.AllocationTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_AllocationTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_AllocationTransform_equals( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_AllocationTransform_getAllocation( PyObject * self );
+ PyObject * PyOCIO_AllocationTransform_setAllocation( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_AllocationTransform_getVars( PyObject * self );
+ PyObject * PyOCIO_AllocationTransform_setVars( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_AllocationTransform_methods[] = {
+ {"getAllocation",
+ (PyCFunction) PyOCIO_AllocationTransform_getAllocation, METH_NOARGS, ALLOCATIONTRANSFORM_GETALLOCATION__DOC__ },
+ {"setAllocation",
+ PyOCIO_AllocationTransform_setAllocation, METH_VARARGS, ALLOCATIONTRANSFORM_SETALLOCATION__DOC__ },
+ {"getVars",
+ (PyCFunction) PyOCIO_AllocationTransform_getVars, METH_NOARGS, ALLOCATIONTRANSFORM_GETVARS__DOC__ },
+ {"setVars",
+ PyOCIO_AllocationTransform_setVars, METH_VARARGS, ALLOCATIONTRANSFORM_SETVARS__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_AllocationTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.AllocationTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ ALLOCATIONTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_AllocationTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_AllocationTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ int PyOCIO_AllocationTransform_init( PyOCIO_Transform *self, PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ try
+ {
+ *self->cppobj = AllocationTransform::Create();
+ self->isconst = false;
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create AllocationTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_AllocationTransform_getAllocation( PyObject * self )
+ {
+ try
+ {
+ ConstAllocationTransformRcPtr transform = GetConstAllocationTransform(self, true);
+ return PyString_FromString( AllocationToString( transform->getAllocation()) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_AllocationTransform_setAllocation( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ Allocation hwalloc;
+ if (!PyArg_ParseTuple(args,"O&:setAllocation",
+ ConvertPyObjectToAllocation, &hwalloc)) return NULL;
+
+ AllocationTransformRcPtr transform = GetEditableAllocationTransform(self);
+ transform->setAllocation( hwalloc );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_AllocationTransform_getVars( PyObject * self )
+ {
+ try
+ {
+ ConstAllocationTransformRcPtr transform = GetConstAllocationTransform(self, true);
+
+ std::vector<float> vars(transform->getNumVars());
+ if(!vars.empty())
+ {
+ transform->getVars(&vars[0]);
+ }
+
+ return CreatePyListFromFloatVector(vars);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_AllocationTransform_setVars( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyvars = 0;
+ if (!PyArg_ParseTuple(args,"O:setVars", &pyvars)) return NULL;
+
+ std::vector<float> vars;
+ if(!FillFloatVectorFromPySequence(pyvars, vars))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array.");
+ return 0;
+ }
+
+ AllocationTransformRcPtr transform = GetEditableAllocationTransform(self);
+ if(!vars.empty())
+ {
+ transform->setVars(static_cast<int>(vars.size()), &vars[0]);
+ }
+
+ Py_RETURN_NONE;
+
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyCDLTransform.cpp b/src/pyglue/PyCDLTransform.cpp
new file mode 100644
index 0000000..5702940
--- /dev/null
+++ b/src/pyglue/PyCDLTransform.cpp
@@ -0,0 +1,611 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddCDLTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_CDLTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_CDLTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_CDLTransformType );
+ PyModule_AddObject(m, "CDLTransform",
+ (PyObject *)&PyOCIO_CDLTransformType);
+
+ return true;
+ }
+
+ bool IsPyCDLTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_CDLTransformType);
+ }
+
+ ConstCDLTransformRcPtr GetConstCDLTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstCDLTransformRcPtr transform = \
+ DynamicPtrCast<const CDLTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.CDLTransform.");
+ }
+ return transform;
+ }
+
+ CDLTransformRcPtr GetEditableCDLTransform(PyObject * pyobject)
+ {
+ CDLTransformRcPtr transform = \
+ DynamicPtrCast<CDLTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.CDLTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_CDLTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_CDLTransform_equals( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_CDLTransform_getXML( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_setXML( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_CDLTransform_getSlope( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_getOffset( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_getPower( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_getSOP( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_getSat( PyObject * self );
+
+ PyObject * PyOCIO_CDLTransform_setSlope( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_CDLTransform_setOffset( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_CDLTransform_setPower( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_CDLTransform_setSOP( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_CDLTransform_setSat( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_CDLTransform_getSatLumaCoefs( PyObject * self );
+
+ PyObject * PyOCIO_CDLTransform_getID( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_setID( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_CDLTransform_getDescription( PyObject * self );
+ PyObject * PyOCIO_CDLTransform_setDescription( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_CDLTransform_methods[] = {
+ {"equals",
+ PyOCIO_CDLTransform_equals, METH_VARARGS, CDLTRANSFORM_EQUALS__DOC__ },
+ {"getXML",
+ (PyCFunction) PyOCIO_CDLTransform_getXML, METH_NOARGS, CDLTRANSFORM_GETXML__DOC__ },
+ {"setXML",
+ PyOCIO_CDLTransform_setXML, METH_VARARGS, CDLTRANSFORM_SETXML__DOC__ },
+ {"getSlope",
+ (PyCFunction) PyOCIO_CDLTransform_getSlope, METH_NOARGS, CDLTRANSFORM_GETSLOPE__DOC__ },
+ {"getOffset",
+ (PyCFunction) PyOCIO_CDLTransform_getOffset, METH_NOARGS, CDLTRANSFORM_GETOFFSET__DOC__ },
+ {"getPower",
+ (PyCFunction) PyOCIO_CDLTransform_getPower, METH_NOARGS, CDLTRANSFORM_GETPOWER__DOC__ },
+ {"getSOP",
+ (PyCFunction) PyOCIO_CDLTransform_getSOP, METH_NOARGS, CDLTRANSFORM_GETSOP__DOC__ },
+ {"getSat",
+ (PyCFunction) PyOCIO_CDLTransform_getSat, METH_NOARGS, CDLTRANSFORM_GETSAT__DOC__ },
+ {"setSlope",
+ PyOCIO_CDLTransform_setSlope, METH_VARARGS, CDLTRANSFORM_SETSLOPE__DOC__ },
+ {"setOffset",
+ PyOCIO_CDLTransform_setOffset, METH_VARARGS, CDLTRANSFORM_SETOFFSET__DOC__ },
+ {"setPower",
+ PyOCIO_CDLTransform_setPower, METH_VARARGS, CDLTRANSFORM_SETPOWER__DOC__ },
+ {"setSOP",
+ PyOCIO_CDLTransform_setSOP, METH_VARARGS, CDLTRANSFORM_SETSOP__DOC__ },
+ {"setSat",
+ PyOCIO_CDLTransform_setSat, METH_VARARGS, CDLTRANSFORM_SETSAT__DOC__ },
+ {"getSatLumaCoefs",
+ (PyCFunction) PyOCIO_CDLTransform_getSatLumaCoefs, METH_NOARGS, CDLTRANSFORM_GETSATLUMACOEFS__DOC__ },
+ {"getID",
+ (PyCFunction) PyOCIO_CDLTransform_getID, METH_NOARGS, CDLTRANSFORM_GETID__DOC__ },
+ {"setID",
+ PyOCIO_CDLTransform_setID, METH_VARARGS, CDLTRANSFORM_SETID__DOC__ },
+ {"getDescription",
+ (PyCFunction) PyOCIO_CDLTransform_getDescription, METH_NOARGS, CDLTRANSFORM_GETDESCRIPTION__DOC__ },
+ {"setDescription",
+ PyOCIO_CDLTransform_setDescription, METH_VARARGS, CDLTRANSFORM_SETDESCRIPTION__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_CDLTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.CDLTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ CDLTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_CDLTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_CDLTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_CDLTransform_init( PyOCIO_Transform *self, PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ try
+ {
+ *self->cppobj = CDLTransform::Create();
+ self->isconst = false;
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create CDLTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_CDLTransform_equals( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyother = 0;
+
+ if (!PyArg_ParseTuple(args,"O:equals",
+ &pyother)) return NULL;
+
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ if(!IsPyCDLTransform(pyother))
+ {
+ return PyBool_FromLong(false);
+ }
+
+ ConstCDLTransformRcPtr other = GetConstCDLTransform(pyother, true);
+
+ return PyBool_FromLong(transform->equals(other));
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_CDLTransform_getXML( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ return PyString_FromString( transform->getXML() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setXML( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setXML",
+ &str)) return NULL;
+
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+ transform->setXML( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_CDLTransform_getSlope( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ std::vector<float> data(3);
+ transform->getSlope(&data[0]);
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_getOffset( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ std::vector<float> data(3);
+ transform->getOffset(&data[0]);
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_getPower( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ std::vector<float> data(3);
+ transform->getPower(&data[0]);
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_getSOP( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ std::vector<float> data(9);
+ transform->getSOP(&data[0]);
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_getSat( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ return PyFloat_FromDouble(transform->getSat());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_CDLTransform_setSlope( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:setSlope", &pyData)) return NULL;
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || (data.size() != 3))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array, size 3");
+ return 0;
+ }
+
+ transform->setSlope( &data[0] );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setOffset( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:setOffset", &pyData)) return NULL;
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || (data.size() != 3))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array, size 3");
+ return 0;
+ }
+
+ transform->setOffset( &data[0] );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setPower( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:setPower", &pyData)) return NULL;
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || (data.size() != 3))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array, size 3");
+ return 0;
+ }
+
+ transform->setPower( &data[0] );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setSOP( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:setSOP", &pyData)) return NULL;
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || (data.size() != 9))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array, size 9");
+ return 0;
+ }
+
+ transform->setSOP( &data[0] );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setSat( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ float sat;
+ if (!PyArg_ParseTuple(args,"f:setSat", &sat)) return NULL;
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+
+ transform->setSat( sat );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_CDLTransform_getSatLumaCoefs( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ std::vector<float> data(3);
+ transform->getSatLumaCoefs(&data[0]);
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+
+ PyObject * PyOCIO_CDLTransform_getID( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ return PyString_FromString( transform->getID() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setID( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setID",
+ &str)) return NULL;
+
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+ transform->setID( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_getDescription( PyObject * self )
+ {
+ try
+ {
+ ConstCDLTransformRcPtr transform = GetConstCDLTransform(self, true);
+ return PyString_FromString( transform->getDescription() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_CDLTransform_setDescription( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setDescription",
+ &str)) return NULL;
+
+ CDLTransformRcPtr transform = GetEditableCDLTransform(self);
+ transform->setDescription( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyColorSpace.cpp b/src/pyglue/PyColorSpace.cpp
new file mode 100644
index 0000000..f169ad6
--- /dev/null
+++ b/src/pyglue/PyColorSpace.cpp
@@ -0,0 +1,756 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyColorSpace.h"
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddColorSpaceObjectToModule( PyObject* m )
+ {
+ PyOCIO_ColorSpaceType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ColorSpaceType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ColorSpaceType );
+ PyModule_AddObject(m, "ColorSpace",
+ (PyObject *)&PyOCIO_ColorSpaceType);
+
+ return true;
+ }
+
+ PyObject * BuildConstPyColorSpace(ConstColorSpaceRcPtr colorSpace)
+ {
+ if (!colorSpace)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_ColorSpace * pycolorSpace = PyObject_New(
+ PyOCIO_ColorSpace, (PyTypeObject * ) &PyOCIO_ColorSpaceType);
+
+ pycolorSpace->constcppobj = new ConstColorSpaceRcPtr();
+ *pycolorSpace->constcppobj = colorSpace;
+
+ pycolorSpace->cppobj = new ColorSpaceRcPtr();
+ pycolorSpace->isconst = true;
+
+ return ( PyObject * ) pycolorSpace;
+ }
+
+ PyObject * BuildEditablePyColorSpace(ColorSpaceRcPtr colorSpace)
+ {
+ if (!colorSpace)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_ColorSpace * pycolorSpace = PyObject_New(
+ PyOCIO_ColorSpace, (PyTypeObject * ) &PyOCIO_ColorSpaceType);
+
+ pycolorSpace->constcppobj = new ConstColorSpaceRcPtr();
+ pycolorSpace->cppobj = new ColorSpaceRcPtr();
+ *pycolorSpace->cppobj = colorSpace;
+
+ pycolorSpace->isconst = false;
+
+ return ( PyObject * ) pycolorSpace;
+ }
+
+ bool IsPyColorSpace(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return (PyObject_Type(pyobject) == (PyObject *) (&PyOCIO_ColorSpaceType));
+ }
+
+ bool IsPyColorSpaceEditable(PyObject * pyobject)
+ {
+ if(!IsPyColorSpace(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.ColorSpace.");
+ }
+
+ PyOCIO_ColorSpace * pycolorSpace = reinterpret_cast<PyOCIO_ColorSpace *> (pyobject);
+ return (!pycolorSpace->isconst);
+ }
+
+ ConstColorSpaceRcPtr GetConstColorSpace(PyObject * pyobject, bool allowCast)
+ {
+ if(!IsPyColorSpace(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.ColorSpace.");
+ }
+
+ PyOCIO_ColorSpace * pycolorspace = reinterpret_cast<PyOCIO_ColorSpace *> (pyobject);
+ if(pycolorspace->isconst && pycolorspace->constcppobj)
+ {
+ return *pycolorspace->constcppobj;
+ }
+
+ if(allowCast && !pycolorspace->isconst && pycolorspace->cppobj)
+ {
+ return *pycolorspace->cppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.ColorSpace.");
+ }
+
+ ColorSpaceRcPtr GetEditableColorSpace(PyObject * pyobject)
+ {
+ if(!IsPyColorSpace(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.ColorSpace.");
+ }
+
+ PyOCIO_ColorSpace * pycolorspace = reinterpret_cast<PyOCIO_ColorSpace *> (pyobject);
+ if(!pycolorspace->isconst && pycolorspace->cppobj)
+ {
+ return *pycolorspace->cppobj;
+ }
+
+ throw Exception("PyObject must be an editable OCIO.ColorSpace.");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_ColorSpace_init( PyOCIO_ColorSpace * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_ColorSpace_delete( PyOCIO_ColorSpace * self, PyObject * args );
+ PyObject * PyOCIO_ColorSpace_isEditable( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_createEditableCopy( PyObject * self );
+
+ PyObject * PyOCIO_ColorSpace_getName( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setName( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_getFamily( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setFamily( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_getEqualityGroup( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setEqualityGroup( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_getDescription( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setDescription( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_ColorSpace_getBitDepth( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setBitDepth( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_isData( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setIsData( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_getAllocation( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setAllocation( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_getAllocationVars( PyObject * self );
+ PyObject * PyOCIO_ColorSpace_setAllocationVars( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_ColorSpace_getTransform( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpace_setTransform( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_ColorSpace_methods[] = {
+ {"isEditable",
+ (PyCFunction) PyOCIO_ColorSpace_isEditable, METH_NOARGS, COLORSPACE_ISEDITABLE__DOC__ },
+ {"createEditableCopy",
+ (PyCFunction) PyOCIO_ColorSpace_createEditableCopy, METH_NOARGS, COLORSPACE_CREATEEDITABLECOPY__DOC__ },
+ {"getName",
+ (PyCFunction) PyOCIO_ColorSpace_getName, METH_NOARGS, COLORSPACE_GETNAME__DOC__ },
+ {"setName",
+ PyOCIO_ColorSpace_setName, METH_VARARGS, COLORSPACE_SETNAME__DOC__ },
+ {"getFamily",
+ (PyCFunction) PyOCIO_ColorSpace_getFamily, METH_NOARGS, COLORSPACE_GETFAMILY__DOC__ },
+ {"setFamily",
+ PyOCIO_ColorSpace_setFamily, METH_VARARGS, COLORSPACE_SETFAMILY__DOC__ },
+ {"getEqualityGroup",
+ (PyCFunction) PyOCIO_ColorSpace_getEqualityGroup, METH_NOARGS, COLORSPACE_GETEQUALITYGROUP__DOC__ },
+ {"setEqualityGroup",
+ PyOCIO_ColorSpace_setEqualityGroup, METH_VARARGS, COLORSPACE_SETEQUALITYGROUP__DOC__ },
+ {"getDescription",
+ (PyCFunction) PyOCIO_ColorSpace_getDescription, METH_NOARGS, COLORSPACE_GETDESCRIPTION__DOC__ },
+ {"setDescription",
+ PyOCIO_ColorSpace_setDescription, METH_VARARGS, COLORSPACE_SETDESCRIPTION__DOC__ },
+ {"getBitDepth",
+ (PyCFunction) PyOCIO_ColorSpace_getBitDepth, METH_NOARGS, COLORSPACE_GETBITDEPTH__DOC__ },
+ {"setBitDepth",
+ PyOCIO_ColorSpace_setBitDepth, METH_VARARGS, COLORSPACE_SETBITDEPTH__DOC__ },
+ {"isData",
+ (PyCFunction) PyOCIO_ColorSpace_isData, METH_NOARGS, COLORSPACE_ISDATA__DOC__ },
+ {"setIsData",
+ PyOCIO_ColorSpace_setIsData, METH_VARARGS, COLORSPACE_SETISDATA__DOC__ },
+ {"getAllocation",
+ (PyCFunction) PyOCIO_ColorSpace_getAllocation, METH_NOARGS, COLORSPACE_GETALLOCATION__DOC__ },
+ {"setAllocation",
+ PyOCIO_ColorSpace_setAllocation, METH_VARARGS, COLORSPACE_SETALLOCATION__DOC__ },
+ {"getAllocationVars",
+ (PyCFunction) PyOCIO_ColorSpace_getAllocationVars, METH_NOARGS, COLORSPACE_GETALLOCATIONVARS__DOC__ },
+ {"setAllocationVars",
+ PyOCIO_ColorSpace_setAllocationVars, METH_VARARGS, COLORSPACE_SETALLOCATIONVARS__DOC__ },
+ {"getTransform",
+ PyOCIO_ColorSpace_getTransform, METH_VARARGS, COLORSPACE_GETTRANSFORM__DOC__ },
+ {"setTransform",
+ PyOCIO_ColorSpace_setTransform, METH_VARARGS, COLORSPACE_SETTRANSFORM__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ColorSpaceType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.ColorSpace", //tp_name
+ sizeof(PyOCIO_ColorSpace), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PyOCIO_ColorSpace_delete, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ COLORSPACE__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_ColorSpace_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_ColorSpace_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_ColorSpace_init( PyOCIO_ColorSpace *self, PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstColorSpaceRcPtr();
+ self->cppobj = new ColorSpaceRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ char * name = NULL;
+ char * family = NULL;
+ char * equalityGroup = NULL;
+ char * description = NULL;
+ char * bitDepth = NULL;
+ bool isData = false; // TODO: Do not rely on the default value
+ char * allocation = NULL;
+ PyObject * allocationVars = NULL;
+ PyObject * toRefTransform = NULL;
+ PyObject * fromRefTransform = NULL;
+
+
+ const char * toRefStr =
+ ColorSpaceDirectionToString(COLORSPACE_DIR_TO_REFERENCE);
+ const char * fromRefStr =
+ ColorSpaceDirectionToString(COLORSPACE_DIR_FROM_REFERENCE);
+ const char *kwlist[] = {
+ "name", "family", "equalityGroup",
+ "description", "bitDepth",
+ "isData",
+ "allocation", "allocationVars",
+ toRefStr, fromRefStr,
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|sssssO&sOOO",
+ const_cast<char **>(kwlist),
+ &name, &family, &equalityGroup, &description, &bitDepth,
+ ConvertPyObjectToBool, &isData,
+ &allocation, &allocationVars,
+ &toRefTransform, &fromRefTransform)) return -1;
+
+ try
+ {
+ ColorSpaceRcPtr colorSpace = ColorSpace::Create();
+ *self->cppobj = colorSpace;
+ self->isconst = false;
+
+ if(name) colorSpace->setName(name);
+ if(family) colorSpace->setFamily(family);
+ if(equalityGroup) colorSpace->setEqualityGroup(equalityGroup);
+ if(description) colorSpace->setDescription(description);
+ if(bitDepth) colorSpace->setBitDepth(BitDepthFromString(bitDepth));
+ colorSpace->setIsData(isData); // TODO: Do not rely on the default value
+ if(allocation) colorSpace->setAllocation(AllocationFromString(allocation));
+ if(allocationVars)
+ {
+ std::vector<float> vars;
+ if(!FillFloatVectorFromPySequence(allocationVars, vars))
+ {
+ PyErr_SetString(PyExc_TypeError, "allocationVars kwarg must be a float array.");
+ return -1;
+ }
+ colorSpace->setAllocationVars(static_cast<int>(vars.size()), &vars[0]);
+ }
+ if(toRefTransform)
+ {
+ ConstTransformRcPtr transform = GetConstTransform(toRefTransform, true);
+ colorSpace->setTransform(transform, COLORSPACE_DIR_TO_REFERENCE);
+ }
+ if(fromRefTransform)
+ {
+ ConstTransformRcPtr transform = GetConstTransform(fromRefTransform, true);
+ colorSpace->setTransform(transform, COLORSPACE_DIR_FROM_REFERENCE);
+ }
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create colorSpace: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ void PyOCIO_ColorSpace_delete( PyOCIO_ColorSpace *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ delete self->cppobj;
+
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_isEditable( PyObject * self )
+ {
+ return PyBool_FromLong(IsPyColorSpaceEditable(self));
+ }
+
+ PyObject * PyOCIO_ColorSpace_createEditableCopy( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ ColorSpaceRcPtr copy = colorSpace->createEditableCopy();
+ return BuildEditablePyColorSpace( copy );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getName( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyString_FromString( colorSpace->getName() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setName( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setName", &name)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setName( name );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getFamily( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyString_FromString( colorSpace->getFamily() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setFamily( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setFamily", &name)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setFamily( name );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getEqualityGroup( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyString_FromString( colorSpace->getEqualityGroup() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setEqualityGroup( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setEqualityGroup", &name)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setEqualityGroup( name );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getDescription( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyString_FromString( colorSpace->getDescription() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setDescription( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setDescription", &name)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setDescription( name );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getBitDepth( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyString_FromString( BitDepthToString( colorSpace->getBitDepth()) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setBitDepth( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setBitDepth", &name)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setBitDepth( BitDepthFromString( name ) );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_isData( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyBool_FromLong( colorSpace->isData() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setIsData( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ bool isData = false;
+ if (!PyArg_ParseTuple(args,"O&:setIsData",
+ ConvertPyObjectToBool, &isData)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setIsData( isData );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getAllocation( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ return PyString_FromString( AllocationToString( colorSpace->getAllocation()) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setAllocation( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ Allocation hwalloc;
+ if (!PyArg_ParseTuple(args,"O&:setAllocation",
+ ConvertPyObjectToAllocation, &hwalloc)) return NULL;
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setAllocation( hwalloc );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getAllocationVars( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+
+ std::vector<float> allocationvars(colorSpace->getAllocationNumVars());
+ if(!allocationvars.empty())
+ {
+ colorSpace->getAllocationVars(&allocationvars[0]);
+ }
+
+ return CreatePyListFromFloatVector(allocationvars);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpace_setAllocationVars( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyvars = 0;
+ if (!PyArg_ParseTuple(args,"O:setAllocationVars", &pyvars)) return NULL;
+
+ std::vector<float> vars;
+ if(!FillFloatVectorFromPySequence(pyvars, vars))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array.");
+ return 0;
+ }
+
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ if(!vars.empty())
+ {
+ colorSpace->setAllocationVars(static_cast<int>(vars.size()), &vars[0]);
+ }
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_getTransform( PyObject * self, PyObject *args )
+ {
+ try
+ {
+ ColorSpaceDirection dir;
+ if (!PyArg_ParseTuple(args,"O&:getTransform",
+ ConvertPyObjectToColorSpaceDirection, &dir)) return NULL;
+
+ ConstColorSpaceRcPtr colorSpace = GetConstColorSpace(self, true);
+ ConstTransformRcPtr transform = colorSpace->getTransform(dir);
+ return BuildConstPyTransform(transform);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_ColorSpace_setTransform( PyObject * self, PyObject *args )
+ {
+
+ try
+ {
+ PyObject * pytransform = 0;
+ ColorSpaceDirection dir;
+ if (!PyArg_ParseTuple(args,"OO&:setTransform", &pytransform,
+ ConvertPyObjectToColorSpaceDirection, &dir)) return NULL;
+
+ ConstTransformRcPtr transform = GetConstTransform(pytransform, true);
+ ColorSpaceRcPtr colorSpace = GetEditableColorSpace(self);
+ colorSpace->setTransform(transform, dir);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyColorSpace.h b/src/pyglue/PyColorSpace.h
new file mode 100644
index 0000000..ae7d7d0
--- /dev/null
+++ b/src/pyglue/PyColorSpace.h
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYCOLORSPACE_H
+#define INCLUDED_PYOCIO_PYCOLORSPACE_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Maybe put this in a pyinternal namespace?
+
+ typedef struct {
+ PyObject_HEAD
+ ConstColorSpaceRcPtr * constcppobj;
+ ColorSpaceRcPtr * cppobj;
+ bool isconst;
+ } PyOCIO_ColorSpace;
+
+ extern PyTypeObject PyOCIO_ColorSpaceType;
+
+ bool AddColorSpaceObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyColorSpaceTransform.cpp b/src/pyglue/PyColorSpaceTransform.cpp
new file mode 100644
index 0000000..a4dc0fa
--- /dev/null
+++ b/src/pyglue/PyColorSpaceTransform.cpp
@@ -0,0 +1,294 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddColorSpaceTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_ColorSpaceTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ColorSpaceTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ColorSpaceTransformType );
+ PyModule_AddObject(m, "ColorSpaceTransform",
+ (PyObject *)&PyOCIO_ColorSpaceTransformType);
+
+ return true;
+ }
+
+ bool IsPyColorSpaceTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_ColorSpaceTransformType);
+ }
+
+ ConstColorSpaceTransformRcPtr GetConstColorSpaceTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstColorSpaceTransformRcPtr transform = \
+ DynamicPtrCast<const ColorSpaceTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.ColorSpaceTransform.");
+ }
+ return transform;
+ }
+
+ ColorSpaceTransformRcPtr GetEditableColorSpaceTransform(PyObject * pyobject)
+ {
+ ColorSpaceTransformRcPtr transform = \
+ DynamicPtrCast<ColorSpaceTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.ColorSpaceTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_ColorSpaceTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_ColorSpaceTransform_getSrc( PyObject * self );
+ PyObject * PyOCIO_ColorSpaceTransform_setSrc( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_ColorSpaceTransform_getDst( PyObject * self );
+ PyObject * PyOCIO_ColorSpaceTransform_setDst( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_ColorSpaceTransform_methods[] = {
+ {"getSrc",
+ (PyCFunction) PyOCIO_ColorSpaceTransform_getSrc, METH_NOARGS, COLORSPACETRANSFORM_GETSRC__DOC__ },
+ {"setSrc",
+ PyOCIO_ColorSpaceTransform_setSrc, METH_VARARGS, COLORSPACETRANSFORM_SETSRC__DOC__ },
+ {"getDst",
+ (PyCFunction) PyOCIO_ColorSpaceTransform_getDst, METH_NOARGS, COLORSPACETRANSFORM_GETDST__DOC__ },
+ {"setDst",
+ PyOCIO_ColorSpaceTransform_setDst, METH_VARARGS, COLORSPACETRANSFORM_SETDST__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ColorSpaceTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.ColorSpaceTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ COLORSPACETRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_ColorSpaceTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_ColorSpaceTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_ColorSpaceTransform_init( PyOCIO_Transform *self,
+ PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ char * src = NULL;
+ char * dst = NULL;
+ char * direction = NULL;
+
+ static const char *kwlist[] = {
+ "src",
+ "dst",
+ "direction",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|sss",
+ const_cast<char **>(kwlist),
+ &src, &dst, &direction )) return -1;
+
+ try
+ {
+ ColorSpaceTransformRcPtr transform = ColorSpaceTransform::Create();
+ *self->cppobj = transform;
+ self->isconst = false;
+
+ if(src) transform->setSrc(src);
+ if(dst) transform->setDst(dst);
+ if(direction) transform->setDirection(TransformDirectionFromString(direction));
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create ColorSpaceTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_ColorSpaceTransform_getSrc( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceTransformRcPtr transform = GetConstColorSpaceTransform(self, true);
+ return PyString_FromString( transform->getSrc() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpaceTransform_setSrc( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setSrc",
+ &str)) return NULL;
+
+ ColorSpaceTransformRcPtr transform = GetEditableColorSpaceTransform(self);
+ transform->setSrc( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpaceTransform_getDst( PyObject * self )
+ {
+ try
+ {
+ ConstColorSpaceTransformRcPtr transform = GetConstColorSpaceTransform(self, true);
+ return PyString_FromString( transform->getDst() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ColorSpaceTransform_setDst( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setDst",
+ &str)) return NULL;
+
+ ColorSpaceTransformRcPtr transform = GetEditableColorSpaceTransform(self);
+ transform->setDst( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyConfig.cpp b/src/pyglue/PyConfig.cpp
new file mode 100644
index 0000000..2c6339d
--- /dev/null
+++ b/src/pyglue/PyConfig.cpp
@@ -0,0 +1,1220 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyColorSpace.h"
+#include "PyConfig.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+ bool AddConfigObjectToModule( PyObject* m )
+ {
+ PyOCIO_ConfigType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ConfigType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ConfigType );
+ PyModule_AddObject(m, "Config",
+ (PyObject *)&PyOCIO_ConfigType);
+
+ return true;
+ }
+
+ PyObject * BuildConstPyConfig(ConstConfigRcPtr config)
+ {
+ if (!config.get())
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Config * pyconfig = PyObject_New(
+ PyOCIO_Config, (PyTypeObject * ) &PyOCIO_ConfigType);
+
+ pyconfig->constcppobj = new ConstConfigRcPtr();
+ *pyconfig->constcppobj = config;
+
+ pyconfig->cppobj = new ConfigRcPtr();
+ pyconfig->isconst = true;
+
+ return ( PyObject * ) pyconfig;
+ }
+
+ PyObject * BuildEditablePyConfig(ConfigRcPtr config)
+ {
+ if (!config)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Config * pyconfig = PyObject_New(
+ PyOCIO_Config, (PyTypeObject * ) &PyOCIO_ConfigType);
+
+ pyconfig->constcppobj = new ConstConfigRcPtr();
+ pyconfig->cppobj = new ConfigRcPtr();
+ *pyconfig->cppobj = config;
+
+ pyconfig->isconst = false;
+
+ return ( PyObject * ) pyconfig;
+ }
+
+ bool IsPyConfig(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return (PyObject_Type(pyobject) == (PyObject *) (&PyOCIO_ConfigType));
+ }
+
+ bool IsPyConfigEditable(PyObject * pyobject)
+ {
+ if(!IsPyConfig(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Config.");
+ }
+
+ PyOCIO_Config * pyconfig = reinterpret_cast<PyOCIO_Config *> (pyobject);
+ return (!pyconfig->isconst);
+ }
+
+ ConstConfigRcPtr GetConstConfig(PyObject * pyobject, bool allowCast)
+ {
+ if(!IsPyConfig(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Config.");
+ }
+
+ PyOCIO_Config * pyconfig = reinterpret_cast<PyOCIO_Config *> (pyobject);
+ if(pyconfig->isconst && pyconfig->constcppobj)
+ {
+ return *pyconfig->constcppobj;
+ }
+
+ if(allowCast && !pyconfig->isconst && pyconfig->cppobj)
+ {
+ return *pyconfig->cppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.Config.");
+ }
+
+ ConfigRcPtr GetEditableConfig(PyObject * pyobject)
+ {
+ if(!IsPyConfig(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Config.");
+ }
+
+ PyOCIO_Config * pyconfig = reinterpret_cast<PyOCIO_Config *> (pyobject);
+ if(!pyconfig->isconst && pyconfig->cppobj)
+ {
+ return *pyconfig->cppobj;
+ }
+
+ throw Exception("PyObject must be an editable OCIO.Config.");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ PyObject * PyOCIO_Config_CreateFromEnv( PyObject * cls );
+ PyObject * PyOCIO_Config_CreateFromFile( PyObject * cls, PyObject * args );
+
+ int PyOCIO_Config_init( PyOCIO_Config * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_Config_delete( PyOCIO_Config * self, PyObject * args );
+
+ PyObject * PyOCIO_Config_isEditable( PyObject * self );
+ PyObject * PyOCIO_Config_createEditableCopy( PyObject * self );
+
+ PyObject * PyOCIO_Config_sanityCheck( PyObject * self );
+
+ PyObject * PyOCIO_Config_getDescription( PyObject * self );
+ PyObject * PyOCIO_Config_setDescription( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_Config_serialize( PyObject * self );
+ PyObject * PyOCIO_Config_getCacheID( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_Config_getCurrentContext( PyObject * self );
+
+ PyObject * PyOCIO_Config_getSearchPath( PyObject * self );
+ PyObject * PyOCIO_Config_setSearchPath( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_Config_getWorkingDir( PyObject * self );
+ PyObject * PyOCIO_Config_setWorkingDir( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_Config_getColorSpaces( PyObject * self );
+ PyObject * PyOCIO_Config_getColorSpace( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_addColorSpace( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_clearColorSpaces( PyObject * self );
+ PyObject * PyOCIO_Config_parseColorSpaceFromString( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_setRole( PyObject * self, PyObject * args );
+
+ PyObject * PyOCIO_Config_getDefaultDisplay( PyObject * self );
+ PyObject * PyOCIO_Config_getDisplays( PyObject * self );
+ PyObject * PyOCIO_Config_getDefaultView( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_getViews( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_getDisplayColorSpaceName( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_getDisplayLooks( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_addDisplay( PyObject * self, PyObject * args, PyObject * kwargs );
+ PyObject * PyOCIO_Config_clearDisplays( PyObject * self );
+ PyObject * PyOCIO_Config_setActiveDisplays( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_getActiveDisplays( PyObject * self );
+ PyObject * PyOCIO_Config_setActiveViews( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_getActiveViews( PyObject * self );
+
+ PyObject * PyOCIO_Config_getDefaultLumaCoefs( PyObject * self );
+ PyObject * PyOCIO_Config_setDefaultLumaCoefs( PyObject * self, PyObject * args );
+
+ PyObject * PyOCIO_Config_getLook( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_getLooks( PyObject * self );
+ PyObject * PyOCIO_Config_addLook( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Config_clearLooks( PyObject * self );
+
+ PyObject * PyOCIO_Config_getProcessor( PyObject * self, PyObject * args, PyObject * kwargs );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_Config_methods[] = {
+ {"CreateFromEnv",
+ (PyCFunction) PyOCIO_Config_CreateFromEnv, METH_NOARGS | METH_CLASS, CONFIG_CREATEFROMENV__DOC__ },
+ {"CreateFromFile",
+ PyOCIO_Config_CreateFromFile, METH_VARARGS | METH_CLASS, CONFIG_CREATEFROMFILE__DOC__ },
+ {"isEditable",
+ (PyCFunction) PyOCIO_Config_isEditable, METH_NOARGS, CONFIG_ISEDITABLE__DOC__ },
+ {"createEditableCopy",
+ (PyCFunction) PyOCIO_Config_createEditableCopy, METH_NOARGS, CONFIG_CREATEEDITABLECOPY__DOC__ },
+ {"sanityCheck",
+ (PyCFunction) PyOCIO_Config_sanityCheck, METH_NOARGS, CONFIG_SANITYCHECK__DOC__ },
+ {"getDescription",
+ (PyCFunction) PyOCIO_Config_getDescription, METH_NOARGS, CONFIG_GETDESCRIPTION__DOC__ },
+ {"setDescription",
+ PyOCIO_Config_setDescription, METH_VARARGS, CONFIG_SETDESCRIPTION__DOC__ },
+ {"serialize",
+ (PyCFunction) PyOCIO_Config_serialize, METH_NOARGS, CONFIG_SERIALIZE__DOC__ },
+ {"getCacheID",
+ PyOCIO_Config_getCacheID, METH_VARARGS, CONFIG_GETCACHEID__DOC__ },
+ {"getCurrentContext",
+ (PyCFunction) PyOCIO_Config_getCurrentContext, METH_NOARGS, CONFIG_GETCURRENTCONTEXT__DOC__ },
+ {"getSearchPath",
+ (PyCFunction) PyOCIO_Config_getSearchPath, METH_NOARGS, CONFIG_GETSEARCHPATH__DOC__ },
+ {"setSearchPath",
+ PyOCIO_Config_setSearchPath, METH_VARARGS, CONFIG_SETSEARCHPATH__DOC__ },
+ {"getWorkingDir",
+ (PyCFunction) PyOCIO_Config_getWorkingDir, METH_NOARGS, CONFIG_GETWORKINGDIR__DOC__ },
+ {"setWorkingDir",
+ PyOCIO_Config_setWorkingDir, METH_VARARGS, CONFIG_SETWORKINGDIR__DOC__ },
+ {"getColorSpaces",
+ (PyCFunction) PyOCIO_Config_getColorSpaces, METH_NOARGS, CONFIG_GETCOLORSPACES__DOC__ },
+ {"getColorSpace",
+ PyOCIO_Config_getColorSpace, METH_VARARGS, CONFIG_GETCOLORSPACE__DOC__ },
+ {"addColorSpace",
+ PyOCIO_Config_addColorSpace, METH_VARARGS, CONFIG_ADDCOLORSPACE__DOC__ },
+ {"clearColorSpaces",
+ (PyCFunction) PyOCIO_Config_clearColorSpaces, METH_NOARGS, CONFIG_CLEARCOLORSPACES__DOC__ },
+ {"parseColorSpaceFromString",
+ PyOCIO_Config_parseColorSpaceFromString, METH_VARARGS, CONFIG_PARSECOLORSPACEFROMSTRING__DOC__ },
+ {"setRole",
+ PyOCIO_Config_setRole, METH_VARARGS, CONFIG_SETROLE__DOC__ },
+ {"getDefaultDisplay",
+ (PyCFunction) PyOCIO_Config_getDefaultDisplay, METH_NOARGS, CONFIG_GETDEFAULTDISPLAY__DOC__ },
+ {"getDisplays",
+ (PyCFunction) PyOCIO_Config_getDisplays, METH_NOARGS, CONFIG_GETDISPLAYS__DOC__ },
+ {"getDefaultView",
+ PyOCIO_Config_getDefaultView, METH_VARARGS, CONFIG_GETDEFAULTVIEW__DOC__ },
+ {"getViews",
+ PyOCIO_Config_getViews, METH_VARARGS, CONFIG_GETVIEWS__DOC__ },
+ {"getDisplayColorSpaceName",
+ PyOCIO_Config_getDisplayColorSpaceName, METH_VARARGS, CONFIG_GETDISPLAYCOLORSPACENAME__DOC__ },
+ {"getDisplayLooks",
+ PyOCIO_Config_getDisplayLooks, METH_VARARGS, CONFIG_GETDISPLAYLOOKS__DOC__ },
+ {"addDisplay",
+ (PyCFunction) PyOCIO_Config_addDisplay, METH_KEYWORDS, CONFIG_ADDDISPLAY__DOC__ },
+ {"clearDisplays",
+ (PyCFunction) PyOCIO_Config_clearDisplays, METH_NOARGS, CONFIG_CLEARDISPLAYS__DOC__ },
+ {"setActiveDisplays",
+ PyOCIO_Config_setActiveDisplays, METH_VARARGS, CONFIG_SETACTIVEDISPLAYS__DOC__ },
+ {"getActiveDisplays",
+ (PyCFunction) PyOCIO_Config_getActiveDisplays, METH_NOARGS, CONFIG_GETACTIVEDISPLAYS__DOC__ },
+ {"setActiveViews",
+ PyOCIO_Config_setActiveViews, METH_VARARGS, CONFIG_SETACTIVEVIEWS__DOC__ },
+ {"getActiveViews",
+ (PyCFunction) PyOCIO_Config_getActiveViews, METH_NOARGS, CONFIG_GETACTIVEVIEWS__DOC__ },
+ {"getDefaultLumaCoefs",
+ (PyCFunction) PyOCIO_Config_getDefaultLumaCoefs, METH_NOARGS, CONFIG_GETDEFAULTLUMACOEFS__DOC__ },
+ {"setDefaultLumaCoefs",
+ PyOCIO_Config_setDefaultLumaCoefs, METH_VARARGS, CONFIG_SETDEFAULTLUMACOEFS__DOC__ },
+ {"getLook",
+ PyOCIO_Config_getLook, METH_VARARGS, CONFIG_GETLOOK__DOC__ },
+ {"getLooks",
+ (PyCFunction) PyOCIO_Config_getLooks, METH_NOARGS, CONFIG_GETLOOKS__DOC__ },
+ {"addLook",
+ PyOCIO_Config_addLook, METH_VARARGS, CONFIG_ADDLOOK__DOC__ },
+ {"clearLook", // THIS SHOULD BE REMOVED IN THE NEXT BINARY INCOMPATIBLE VERSION
+ (PyCFunction) PyOCIO_Config_clearLooks, METH_NOARGS, CONFIG_CLEARLOOKS__DOC__ },
+ {"clearLooks",
+ (PyCFunction) PyOCIO_Config_clearLooks, METH_NOARGS, CONFIG_CLEARLOOKS__DOC__ },
+ {"getProcessor",
+ (PyCFunction) PyOCIO_Config_getProcessor, METH_KEYWORDS, CONFIG_GETPROCESSOR__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ConfigType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.Config", //tp_name
+ sizeof(PyOCIO_Config), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PyOCIO_Config_delete, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ CONFIG__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_Config_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_Config_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// static methods
+
+ namespace
+ {
+ PyObject * PyOCIO_Config_CreateFromEnv( PyObject * /*cls*/ )
+ {
+ try
+ {
+ return BuildConstPyConfig( Config::CreateFromEnv() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_CreateFromFile( PyObject * /*cls*/, PyObject * args )
+ {
+ try
+ {
+ char * filename = 0;
+ if (!PyArg_ParseTuple(args,"s:CreateFromFile", &filename)) return NULL;
+
+ return BuildConstPyConfig( Config::CreateFromFile(filename) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // Insert class markup here
+ int PyOCIO_Config_init( PyOCIO_Config *self, PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+ self->constcppobj = new ConstConfigRcPtr();
+ self->cppobj = new ConfigRcPtr();
+ self->isconst = true;
+
+ try
+ {
+ *self->cppobj = Config::Create();
+ self->isconst = false;
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create config: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ void PyOCIO_Config_delete( PyOCIO_Config *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ delete self->cppobj;
+
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_isEditable( PyObject * self )
+ {
+ return PyBool_FromLong(IsPyConfigEditable(self));
+ }
+
+ PyObject * PyOCIO_Config_createEditableCopy( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ ConfigRcPtr copy = config->createEditableCopy();
+ return BuildEditablePyConfig( copy );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_sanityCheck( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ config->sanityCheck();
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_getDescription( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getDescription() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_setDescription( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * desc = 0;
+ if (!PyArg_ParseTuple(args,"s:setDescription", &desc)) return NULL;
+
+ ConfigRcPtr config = GetEditableConfig(self);
+ config->setDescription( desc );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_serialize( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ std::ostringstream os;
+
+ config->serialize(os);
+
+ return PyString_FromString( os.str().c_str() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+
+ }
+
+ PyObject * PyOCIO_Config_getCacheID( PyObject * self, PyObject * args )
+ {
+ try
+ { PyObject * pycontext = NULL;
+ if (!PyArg_ParseTuple(args,"|O:getCacheID", &pycontext)) return NULL;
+
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ // Parse the context
+ ConstContextRcPtr context;
+ if(pycontext != NULL)
+ {
+ context = GetConstContext(pycontext, true);
+ }
+ else
+ {
+ context = config->getCurrentContext();
+ }
+
+ return PyString_FromString( config->getCacheID(context) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getCurrentContext( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ return BuildConstPyContext(config->getCurrentContext());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getSearchPath( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getSearchPath() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_setSearchPath( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * path = 0;
+ if (!PyArg_ParseTuple(args,"s:setSearchPath", &path)) return NULL;
+
+ ConfigRcPtr config = GetEditableConfig(self);
+ config->setSearchPath( path );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getWorkingDir( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getWorkingDir() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_setWorkingDir( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * path = 0;
+ if (!PyArg_ParseTuple(args,"s:setWorkingDir", &path)) return NULL;
+
+ ConfigRcPtr config = GetEditableConfig(self);
+ config->setWorkingDir( path );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getColorSpaces( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ int numColorSpaces = config->getNumColorSpaces();
+
+ PyObject* tuple = PyTuple_New( numColorSpaces );
+ for(int i = 0; i<numColorSpaces; ++i)
+ {
+ const char * name = config->getColorSpaceNameByIndex(i);
+ ConstColorSpaceRcPtr cs = config->getColorSpace(name);
+ PyObject * pycs = BuildConstPyColorSpace(cs);
+ PyTuple_SetItem(tuple, i, pycs);
+ }
+
+ return tuple;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getColorSpace( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:getColorSpace", &name)) return NULL;
+
+ return BuildConstPyColorSpace(config->getColorSpace(name));
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_addColorSpace( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ PyObject * pyColorSpace = 0;
+ if (!PyArg_ParseTuple(args,"O:addColorSpace", &pyColorSpace)) return NULL;
+
+ config->addColorSpace( GetConstColorSpace(pyColorSpace, true) );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_clearColorSpaces( PyObject * self )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+ config->clearColorSpaces();
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_parseColorSpaceFromString( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ char * str = 0;
+
+ if (!PyArg_ParseTuple(args,"s:parseColorSpaceFromString",
+ &str)) return NULL;
+
+ const char * cs = config->parseColorSpaceFromString(str);
+ if(cs)
+ {
+ return PyString_FromString( cs );
+ }
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_setRole( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ char * role = 0;
+ char * csname = 0;
+
+ if (!PyArg_ParseTuple(args,"ss:setRole",
+ &role, &csname)) return NULL;
+
+ config->setRole(role, csname);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_getDefaultDisplay( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getDefaultDisplay() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getDisplays( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ std::vector<std::string> data;
+ int numDevices = config->getNumDisplays();
+
+ for(int i=0; i<numDevices; ++i)
+ {
+ data.push_back( config->getDisplay(i) );
+ }
+
+ return CreatePyListFromStringVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getDefaultView( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * display = 0;
+ if (!PyArg_ParseTuple(args,"s:getDefaultView",
+ &display)) return NULL;
+
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getDefaultView(display) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getViews( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * display = 0;
+ if (!PyArg_ParseTuple(args,"s:getViews",
+ &display)) return NULL;
+
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ std::vector<std::string> data;
+ int num = config->getNumViews(display);
+ for(int i=0; i<num; ++i)
+ {
+ data.push_back( config->getView(display, i) );
+ }
+
+ return CreatePyListFromStringVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getDisplayColorSpaceName( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * display = 0;
+ char * view = 0;
+ if (!PyArg_ParseTuple(args,"ss:getDisplayColorSpaceName",
+ &display, &view)) return NULL;
+
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getDisplayColorSpaceName(display, view) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getDisplayLooks( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * display = 0;
+ char * view = 0;
+ if (!PyArg_ParseTuple(args,"ss:getDisplayLooks",
+ &display, &view)) return NULL;
+
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getDisplayLooks(display, view) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_addDisplay( PyObject * self, PyObject * args, PyObject * kwargs)
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ char * display = 0;
+ char * view = 0;
+ char * colorSpaceName = 0;
+ char * looks = 0;
+
+ const char * kwlist[] = {"display", "view", "colorSpaceName", "looks", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|s",
+ const_cast<char**>(kwlist),
+ &display, &view, &colorSpaceName, &looks))
+ return 0;
+
+ std::string lookStr;
+ if(looks) lookStr = looks;
+
+ config->addDisplay(display, view, colorSpaceName, lookStr.c_str());
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_clearDisplays( PyObject * self )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+ config->clearDisplays();
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_setActiveDisplays( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ char * displays = 0;
+
+ if (!PyArg_ParseTuple(args,"s:setActiveDisplays",
+ &displays)) return NULL;
+
+ config->setActiveDisplays(displays);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getActiveDisplays( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getActiveDisplays() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_setActiveViews( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ char * views = 0;
+
+ if (!PyArg_ParseTuple(args,"s:setActiveViews",
+ &views)) return NULL;
+
+ config->setActiveViews(views);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getActiveViews( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ return PyString_FromString( config->getActiveViews() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_setDefaultLumaCoefs( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ PyObject* pyCoef = 0;
+ if (!PyArg_ParseTuple(args, "O:setDefaultLumaCoefs", &pyCoef))
+ {
+ return 0;
+ }
+
+ std::vector<float> coef;
+ if(!FillFloatVectorFromPySequence(pyCoef, coef) || (coef.size() != 3))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array, size 3");
+ return 0;
+ }
+
+ config->setDefaultLumaCoefs(&coef[0]);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getDefaultLumaCoefs( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ std::vector<float> coef(3);
+ config->getDefaultLumaCoefs(&coef[0]);
+
+ return CreatePyListFromFloatVector(coef);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_getLook( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:getLook",
+ &str)) return NULL;
+
+ return BuildConstPyLook(config->getLook(str));
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_getLooks( PyObject * self )
+ {
+ try
+ {
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+ int num = config->getNumLooks();
+
+ PyObject* tuple = PyTuple_New( num );
+ for(int i = 0; i<num; ++i)
+ {
+ const char * name = config->getLookNameByIndex(i);
+ ConstLookRcPtr look = config->getLook(name);
+ PyObject * pylook = BuildConstPyLook(look);
+ PyTuple_SetItem(tuple, i, pylook);
+ }
+
+ return tuple;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_addLook( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+
+ PyObject * pyLook = 0;
+ if (!PyArg_ParseTuple(args,"O:addLook", &pyLook)) return NULL;
+
+ config->addLook( GetConstLook(pyLook, true) );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Config_clearLooks( PyObject * self )
+ {
+ try
+ {
+ ConfigRcPtr config = GetEditableConfig(self);
+ config->clearLooks();
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Config_getProcessor( PyObject * self, PyObject * args, PyObject * kwargs)
+ {
+ try
+ {
+ // We want this call to be as flexible as possible.
+ // arg1 will either be a PyTransform
+ // or arg1, arg2 will be {str, ColorSpace}
+
+ PyObject * arg1 = Py_None;
+ PyObject * arg2 = Py_None;
+
+ const char * direction = 0;
+ PyObject * pycontext = Py_None;
+
+ const char * kwlist[] = {"arg1", "arg2", "direction", "context", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsO",
+ const_cast<char**>(kwlist),
+ &arg1, &arg2, &direction, &pycontext))
+ return 0;
+
+ ConstConfigRcPtr config = GetConstConfig(self, true);
+
+ // Parse the direction string
+ TransformDirection dir = TRANSFORM_DIR_FORWARD;
+ if(direction) dir = TransformDirectionFromString( direction );
+
+ // Parse the context
+ ConstContextRcPtr context;
+ if(pycontext != Py_None) context = GetConstContext(pycontext, true);
+ if(!context) context = config->getCurrentContext();
+
+ if(IsPyTransform(arg1))
+ {
+ ConstTransformRcPtr transform = GetConstTransform(arg1, true);
+ return BuildConstPyProcessor(config->getProcessor(context, transform, dir));
+ }
+
+ // Any two (Colorspaces, colorspace name, roles)
+ ConstColorSpaceRcPtr cs1, cs2;
+
+ if(IsPyColorSpace(arg1))
+ {
+ cs1 = GetConstColorSpace(arg1, true);
+ }
+ else if(PyString_Check(arg1))
+ {
+ cs1 = config->getColorSpace(PyString_AsString(arg1));
+ }
+ if(!cs1)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "Could not parse first arg. Allowed types include ColorSpace, ColorSpace name, Role.");
+ return NULL;
+ }
+
+ if(IsPyColorSpace(arg2))
+ {
+ cs2 = GetConstColorSpace(arg2, true);
+ }
+ else if(PyString_Check(arg2))
+ {
+ cs2 = config->getColorSpace(PyString_AsString(arg2));
+ }
+ if(!cs2)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "Could not parse second arg. Allowed types include ColorSpace, ColorSpace name, Role.");
+ return NULL;
+ }
+
+ return BuildConstPyProcessor(config->getProcessor(context, cs1, cs2));
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyConfig.h b/src/pyglue/PyConfig.h
new file mode 100644
index 0000000..05ba954
--- /dev/null
+++ b/src/pyglue/PyConfig.h
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYCONFIG_H
+#define INCLUDED_PYOCIO_PYCONFIG_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Maybe put this in a pyinternal namespace?
+
+ typedef struct {
+ PyObject_HEAD
+ ConstConfigRcPtr * constcppobj;
+ ConfigRcPtr * cppobj;
+ bool isconst;
+ } PyOCIO_Config;
+
+ extern PyTypeObject PyOCIO_ConfigType;
+
+ bool AddConfigObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyConstants.cpp b/src/pyglue/PyConstants.cpp
new file mode 100644
index 0000000..ff004bf
--- /dev/null
+++ b/src/pyglue/PyConstants.cpp
@@ -0,0 +1,239 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyColorSpace.h"
+#include "PyConstants.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+
+ namespace
+ {
+ PyObject * PyOCIO_Constants_GetInverseTransformDirection( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Constants_CombineTransformDirections( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Constants_BitDepthIsFloat( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Constants_BitDepthToInt( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef LocalModuleMethods[] = {
+ {"GetInverseTransformDirection",
+ PyOCIO_Constants_GetInverseTransformDirection, METH_VARARGS, CONSTANTS_GETINVERSETRANSFORMDIRECTION__DOC__ },
+ {"CombineTransformDirections",
+ PyOCIO_Constants_CombineTransformDirections, METH_VARARGS, CONSTANTS_COMBINETRANSFORMDIRECTIONS__DOC__ },
+ {"BitDepthIsFloat",
+ PyOCIO_Constants_BitDepthIsFloat, METH_VARARGS, CONSTANTS_BITDEPTHISFLOAT__DOC__ },
+ {"BitDepthToInt",
+ PyOCIO_Constants_BitDepthToInt, METH_VARARGS, CONSTANTS_BITDEPTHTOINT__DOC__ },
+ {NULL, NULL, 0, NULL} /* Sentinel */
+ };
+
+ }
+
+ void AddConstantsModule(PyObject *enclosingModule)
+ {
+ // Add sub-module
+ std::string moduleName = PyModule_GetName(enclosingModule);
+ moduleName += ".Constants";
+
+ PyObject * m = Py_InitModule3(const_cast<char*>(moduleName.c_str()),
+ LocalModuleMethods, CONSTANTS__DOC__);
+ Py_INCREF(m);
+
+ // Add Module Constants
+ PyModule_AddStringConstant(m, "LOGGING_LEVEL_NONE",
+ const_cast<char*>(LoggingLevelToString(LOGGING_LEVEL_NONE)));
+ PyModule_AddStringConstant(m, "LOGGING_LEVEL_WARNING",
+ const_cast<char*>(LoggingLevelToString(LOGGING_LEVEL_WARNING)));
+ PyModule_AddStringConstant(m, "LOGGING_LEVEL_INFO",
+ const_cast<char*>(LoggingLevelToString(LOGGING_LEVEL_INFO)));
+ PyModule_AddStringConstant(m, "LOGGING_LEVEL_UNKNOWN",
+ const_cast<char*>(LoggingLevelToString(LOGGING_LEVEL_UNKNOWN)));
+
+ PyModule_AddStringConstant(m, "TRANSFORM_DIR_UNKNOWN",
+ const_cast<char*>(TransformDirectionToString(TRANSFORM_DIR_UNKNOWN)));
+ PyModule_AddStringConstant(m, "TRANSFORM_DIR_FORWARD",
+ const_cast<char*>(TransformDirectionToString(TRANSFORM_DIR_FORWARD)));
+ PyModule_AddStringConstant(m, "TRANSFORM_DIR_INVERSE",
+ const_cast<char*>(TransformDirectionToString(TRANSFORM_DIR_INVERSE)));
+
+ PyModule_AddStringConstant(m, "COLORSPACE_DIR_UNKNOWN",
+ const_cast<char*>(ColorSpaceDirectionToString(COLORSPACE_DIR_UNKNOWN)));
+ PyModule_AddStringConstant(m, "COLORSPACE_DIR_TO_REFERENCE",
+ const_cast<char*>(ColorSpaceDirectionToString(COLORSPACE_DIR_TO_REFERENCE)));
+ PyModule_AddStringConstant(m, "COLORSPACE_DIR_FROM_REFERENCE",
+ const_cast<char*>(ColorSpaceDirectionToString(COLORSPACE_DIR_FROM_REFERENCE)));
+
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UNKNOWN",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UNKNOWN)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UINT8",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UINT8)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UINT10",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UINT10)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UINT12",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UINT12)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UINT14",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UINT14)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UINT16",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UINT16)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_UINT32",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_UINT32)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_F16",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_F16)));
+ PyModule_AddStringConstant(m, "BIT_DEPTH_F32",
+ const_cast<char*>(BitDepthToString(BIT_DEPTH_F32)));
+
+ PyModule_AddStringConstant(m, "ALLOCATION_UNKNOWN",
+ const_cast<char*>(AllocationToString(ALLOCATION_UNKNOWN)));
+ PyModule_AddStringConstant(m, "ALLOCATION_UNIFORM",
+ const_cast<char*>(AllocationToString(ALLOCATION_UNIFORM)));
+ PyModule_AddStringConstant(m, "ALLOCATION_LG2",
+ const_cast<char*>(AllocationToString(ALLOCATION_LG2)));
+
+ PyModule_AddStringConstant(m, "INTERP_UNKNOWN",
+ const_cast<char*>(InterpolationToString(INTERP_UNKNOWN)));
+ PyModule_AddStringConstant(m, "INTERP_NEAREST",
+ const_cast<char*>(InterpolationToString(INTERP_NEAREST)));
+ PyModule_AddStringConstant(m, "INTERP_LINEAR",
+ const_cast<char*>(InterpolationToString(INTERP_LINEAR)));
+ PyModule_AddStringConstant(m, "INTERP_TETRAHEDRAL",
+ const_cast<char*>(InterpolationToString(INTERP_TETRAHEDRAL)));
+ PyModule_AddStringConstant(m, "INTERP_BEST",
+ const_cast<char*>(InterpolationToString(INTERP_BEST)));
+
+ PyModule_AddStringConstant(m, "GPU_LANGUAGE_UNKNOWN",
+ const_cast<char*>(GpuLanguageToString(GPU_LANGUAGE_UNKNOWN)));
+ PyModule_AddStringConstant(m, "GPU_LANGUAGE_CG",
+ const_cast<char*>(GpuLanguageToString(GPU_LANGUAGE_CG)));
+ PyModule_AddStringConstant(m, "GPU_LANGUAGE_GLSL_1_0",
+ const_cast<char*>(GpuLanguageToString(GPU_LANGUAGE_GLSL_1_0)));
+ PyModule_AddStringConstant(m, "GPU_LANGUAGE_GLSL_1_3",
+ const_cast<char*>(GpuLanguageToString(GPU_LANGUAGE_GLSL_1_3)));
+
+ PyModule_AddStringConstant(m, "ROLE_DEFAULT", const_cast<char*>(ROLE_DEFAULT));
+ PyModule_AddStringConstant(m, "ROLE_REFERENCE", const_cast<char*>(ROLE_REFERENCE));
+ PyModule_AddStringConstant(m, "ROLE_DATA", const_cast<char*>(ROLE_DATA));
+ PyModule_AddStringConstant(m, "ROLE_COLOR_PICKING", const_cast<char*>(ROLE_COLOR_PICKING));
+ PyModule_AddStringConstant(m, "ROLE_SCENE_LINEAR", const_cast<char*>(ROLE_SCENE_LINEAR));
+ PyModule_AddStringConstant(m, "ROLE_COMPOSITING_LOG", const_cast<char*>(ROLE_COMPOSITING_LOG));
+ PyModule_AddStringConstant(m, "ROLE_COLOR_TIMING", const_cast<char*>(ROLE_COLOR_TIMING));
+ PyModule_AddStringConstant(m, "ROLE_TEXTURE_PAINT", const_cast<char*>(ROLE_TEXTURE_PAINT));
+ PyModule_AddStringConstant(m, "ROLE_MATTE_PAINT", const_cast<char*>(ROLE_MATTE_PAINT));
+
+ // Add the module
+ PyModule_AddObject(enclosingModule, "Constants", m);
+ }
+
+
+ namespace
+ {
+
+ PyObject * PyOCIO_Constants_GetInverseTransformDirection( PyObject * /*module*/, PyObject * args )
+ {
+ try
+ {
+ char * s = 0;
+ if (!PyArg_ParseTuple(args,"s:GetInverseTransformDirection", s)) return NULL;
+
+ TransformDirection dir = TransformDirectionFromString(s);
+ dir = GetInverseTransformDirection(dir);
+ return PyString_FromString( TransformDirectionToString(dir) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Constants_CombineTransformDirections( PyObject * /*module*/, PyObject * args )
+ {
+ try
+ {
+ char * s1 = 0;
+ char * s2 = 0;
+ if (!PyArg_ParseTuple(args,"ss:CombineTransformDirections", &s1, &s2)) return NULL;
+
+ TransformDirection dir1 = TransformDirectionFromString(s1);
+ TransformDirection dir2 = TransformDirectionFromString(s2);
+
+ TransformDirection dir = CombineTransformDirections(dir1, dir2);
+ return PyString_FromString( TransformDirectionToString(dir) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Constants_BitDepthIsFloat( PyObject * /*module*/, PyObject * args )
+ {
+ try
+ {
+ char * s = 0;
+ if (!PyArg_ParseTuple(args,"s:BitDepthIsFloat", &s)) return NULL;
+
+ BitDepth bitdepth = BitDepthFromString(s);
+ return PyBool_FromLong( BitDepthIsFloat(bitdepth) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Constants_BitDepthToInt( PyObject * /*module*/, PyObject * args )
+ {
+ try
+ {
+ char * s = 0;
+ if (!PyArg_ParseTuple(args,"s:BitDepthToInt", &s)) return NULL;
+
+ BitDepth bitdepth = BitDepthFromString(s);
+ return PyInt_FromLong( BitDepthToInt(bitdepth) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyConstants.h b/src/pyglue/PyConstants.h
new file mode 100644
index 0000000..28b1797
--- /dev/null
+++ b/src/pyglue/PyConstants.h
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYCONSTANTS_H
+#define INCLUDED_PYOCIO_PYCONSTANTS_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ void AddConstantsModule(PyObject *enclosingModule);
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyContext.cpp b/src/pyglue/PyContext.cpp
new file mode 100644
index 0000000..6a97aad
--- /dev/null
+++ b/src/pyglue/PyContext.cpp
@@ -0,0 +1,494 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyContext.h"
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddContextObjectToModule( PyObject* m )
+ {
+ PyOCIO_ContextType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ContextType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ContextType );
+ PyModule_AddObject(m, "Context",
+ (PyObject *)&PyOCIO_ContextType);
+
+ return true;
+ }
+
+ PyObject * BuildConstPyContext(ConstContextRcPtr context)
+ {
+ if (!context)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Context * pycontext = PyObject_New(
+ PyOCIO_Context, (PyTypeObject * ) &PyOCIO_ContextType);
+
+ pycontext->constcppobj = new ConstContextRcPtr();
+ *pycontext->constcppobj = context;
+
+ pycontext->cppobj = new ContextRcPtr();
+ pycontext->isconst = true;
+
+ return ( PyObject * ) pycontext;
+ }
+
+ PyObject * BuildEditablePyContext(ContextRcPtr context)
+ {
+ if (!context)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Context * pycontext = PyObject_New(
+ PyOCIO_Context, (PyTypeObject * ) &PyOCIO_ContextType);
+
+ pycontext->constcppobj = new ConstContextRcPtr();
+ pycontext->cppobj = new ContextRcPtr();
+ *pycontext->cppobj = context;
+
+ pycontext->isconst = false;
+
+ return ( PyObject * ) pycontext;
+ }
+
+ bool IsPyContext(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return (PyObject_Type(pyobject) == (PyObject *) (&PyOCIO_ContextType));
+ }
+
+ bool IsPyContextEditable(PyObject * pyobject)
+ {
+ if(!IsPyContext(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Context.");
+ }
+
+ PyOCIO_Context * pycontext = reinterpret_cast<PyOCIO_Context *> (pyobject);
+ return (!pycontext->isconst);
+ }
+
+ ConstContextRcPtr GetConstContext(PyObject * pyobject, bool allowCast)
+ {
+ if(!IsPyContext(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Context.");
+ }
+
+ PyOCIO_Context * pycontext = reinterpret_cast<PyOCIO_Context *> (pyobject);
+ if(pycontext->isconst && pycontext->constcppobj)
+ {
+ return *pycontext->constcppobj;
+ }
+
+ if(allowCast && !pycontext->isconst && pycontext->cppobj)
+ {
+ return *pycontext->cppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.Context.");
+ }
+
+ ContextRcPtr GetEditableContext(PyObject * pyobject)
+ {
+ if(!IsPyContext(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Context.");
+ }
+
+ PyOCIO_Context * pycontext = reinterpret_cast<PyOCIO_Context *> (pyobject);
+ if(!pycontext->isconst && pycontext->cppobj)
+ {
+ return *pycontext->cppobj;
+ }
+
+ throw Exception("PyObject must be an editable OCIO.Context.");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_Context_init( PyOCIO_Context * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_Context_delete( PyOCIO_Context * self, PyObject * args );
+ PyObject * PyOCIO_Context_isEditable( PyObject * self );
+ PyObject * PyOCIO_Context_createEditableCopy( PyObject * self );
+ PyObject * PyOCIO_Context_getCacheID( PyObject * self );
+
+ PyObject * PyOCIO_Context_getSearchPath( PyObject * self );
+ PyObject * PyOCIO_Context_setSearchPath( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Context_getWorkingDir( PyObject * self );
+ PyObject * PyOCIO_Context_setWorkingDir( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Context_getStringVar( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Context_setStringVar( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_Context_loadEnvironment( PyObject * self );
+
+ PyObject * PyOCIO_Context_resolveStringVar( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Context_resolveFileLocation( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_Context_methods[] = {
+ {"isEditable",
+ (PyCFunction) PyOCIO_Context_isEditable, METH_NOARGS, CONTEXT_ISEDITABLE__DOC__ },
+ {"createEditableCopy",
+ (PyCFunction) PyOCIO_Context_createEditableCopy, METH_NOARGS, CONTEXT_CREATEEDITABLECOPY__DOC__ },
+ {"getCacheID",
+ (PyCFunction) PyOCIO_Context_getCacheID, METH_NOARGS, CONTEXT_GETCACHEID__DOC__ },
+ {"getSearchPath",
+ (PyCFunction) PyOCIO_Context_getSearchPath, METH_NOARGS, CONTEXT_GETSEARCHPATH__DOC__ },
+ {"setSearchPath",
+ PyOCIO_Context_setSearchPath, METH_VARARGS, CONTEXT_SETSEARCHPATH__DOC__ },
+ {"getWorkingDir",
+ (PyCFunction) PyOCIO_Context_getWorkingDir, METH_NOARGS, CONTEXT_GETWORKINGDIR__DOC__ },
+ {"setWorkingDir",
+ PyOCIO_Context_setWorkingDir, METH_VARARGS, CONTEXT_SETWORKINGDIR__DOC__ },
+ {"getStringVar",
+ PyOCIO_Context_getStringVar, METH_VARARGS, CONTEXT_GETSTRINGVAR__DOC__ },
+ {"setStringVar",
+ PyOCIO_Context_setStringVar, METH_VARARGS, CONTEXT_SETSTRINGVAR__DOC__ },
+ {"loadEnvironment",
+ (PyCFunction) PyOCIO_Context_loadEnvironment, METH_NOARGS, CONTEXT_LOADENVIRONMENT__DOC__ },
+ {"resolveStringVar",
+ PyOCIO_Context_resolveStringVar, METH_VARARGS, CONTEXT_RESOLVESTRINGVAR__DOC__ },
+ {"resolveFileLocation",
+ PyOCIO_Context_resolveFileLocation, METH_VARARGS, CONTEXT_RESOLVEFILELOCATION__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ContextType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.Context", //tp_name
+ sizeof(PyOCIO_Context), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PyOCIO_Context_delete, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ CONTEXT__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_Context_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_Context_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_Context_init( PyOCIO_Context *self, PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstContextRcPtr();
+ self->cppobj = new ContextRcPtr();
+ self->isconst = true;
+
+ try
+ {
+ *self->cppobj = Context::Create();
+ self->isconst = false;
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create context: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ void PyOCIO_Context_delete( PyOCIO_Context *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ delete self->cppobj;
+
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_Context_isEditable( PyObject * self )
+ {
+ return PyBool_FromLong(IsPyContextEditable(self));
+ }
+
+ PyObject * PyOCIO_Context_createEditableCopy( PyObject * self )
+ {
+ try
+ {
+ ConstContextRcPtr context = GetConstContext(self, true);
+ ContextRcPtr copy = context->createEditableCopy();
+ return BuildEditablePyContext( copy );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_getCacheID( PyObject * self )
+ {
+ try
+ {
+ ConstContextRcPtr context = GetConstContext(self, true);
+ return PyString_FromString( context->getCacheID() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ PyObject * PyOCIO_Context_getSearchPath( PyObject * self )
+ {
+ try
+ {
+ ConstContextRcPtr context = GetConstContext(self, true);
+ return PyString_FromString( context->getSearchPath() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_setSearchPath( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * path = 0;
+ if (!PyArg_ParseTuple(args,"s:setSearchPath", &path)) return NULL;
+
+ ContextRcPtr context = GetEditableContext(self);
+ context->setSearchPath( path );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_getWorkingDir( PyObject * self )
+ {
+ try
+ {
+ ConstContextRcPtr context = GetConstContext(self, true);
+ return PyString_FromString( context->getWorkingDir() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_setWorkingDir( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * dirname = 0;
+ if (!PyArg_ParseTuple(args,"s:setWorkingDir", &dirname)) return NULL;
+
+ ContextRcPtr context = GetEditableContext(self);
+ context->setWorkingDir( dirname );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_getStringVar( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:getStringVar", &name)) return NULL;
+
+ ConstContextRcPtr context = GetConstContext(self, true);
+ return PyString_FromString( context->getStringVar(name) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_setStringVar( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ char * value = 0;
+ if (!PyArg_ParseTuple(args,"ss:setStringVar", &name, &value)) return NULL;
+
+ ContextRcPtr context = GetEditableContext(self);
+ context->setStringVar( name, value );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_loadEnvironment( PyObject * self )
+ {
+ try
+ {
+ ContextRcPtr context = GetEditableContext(self);
+ context->loadEnvironment();
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_resolveStringVar( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:resolveStringVar", &str)) return NULL;
+
+ ConstContextRcPtr context = GetConstContext(self, true);
+ return PyString_FromString( context->resolveStringVar(str) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Context_resolveFileLocation( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * filename = 0;
+ if (!PyArg_ParseTuple(args,"s:resolveFileLocation", &filename)) return NULL;
+
+ ConstContextRcPtr context = GetConstContext(self, true);
+ return PyString_FromString( context->resolveFileLocation(filename) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyContext.h b/src/pyglue/PyContext.h
new file mode 100644
index 0000000..02e5623
--- /dev/null
+++ b/src/pyglue/PyContext.h
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYCONTEXT_H
+#define INCLUDED_PYOCIO_PYCONTEXT_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Maybe put this in a pyinternal namespace?
+
+ typedef struct {
+ PyObject_HEAD
+ ConstContextRcPtr * constcppobj;
+ ContextRcPtr * cppobj;
+ bool isconst;
+ } PyOCIO_Context;
+
+ extern PyTypeObject PyOCIO_ContextType;
+
+ bool AddContextObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyDisplayTransform.cpp b/src/pyglue/PyDisplayTransform.cpp
new file mode 100644
index 0000000..6a29153
--- /dev/null
+++ b/src/pyglue/PyDisplayTransform.cpp
@@ -0,0 +1,577 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddDisplayTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_DisplayTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_DisplayTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_DisplayTransformType );
+ PyModule_AddObject(m, "DisplayTransform",
+ (PyObject *)&PyOCIO_DisplayTransformType);
+
+ return true;
+ }
+
+ bool IsPyDisplayTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_DisplayTransformType);
+ }
+
+ ConstDisplayTransformRcPtr GetConstDisplayTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstDisplayTransformRcPtr transform = \
+ DynamicPtrCast<const DisplayTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.DisplayTransform.");
+ }
+ return transform;
+ }
+
+ DisplayTransformRcPtr GetEditableDisplayTransform(PyObject * pyobject)
+ {
+ DisplayTransformRcPtr transform = \
+ DynamicPtrCast<DisplayTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.DisplayTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_DisplayTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_DisplayTransform_getInputColorSpaceName( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setInputColorSpaceName( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getLinearCC( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setLinearCC( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getColorTimingCC( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setColorTimingCC( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getChannelView( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setChannelView( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getDisplay( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setDisplay( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getView( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setView( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getDisplayCC( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setDisplayCC( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_DisplayTransform_getLooksOverride( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setLooksOverride( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_DisplayTransform_getLooksOverrideEnabled( PyObject * self );
+ PyObject * PyOCIO_DisplayTransform_setLooksOverrideEnabled( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_DisplayTransform_methods[] = {
+ {"getInputColorSpaceName",
+ (PyCFunction) PyOCIO_DisplayTransform_getInputColorSpaceName, METH_NOARGS, DISPLAYTRANSFORM_GETINPUTCOLORSPACENAME__DOC__ },
+ {"setInputColorSpaceName",
+ PyOCIO_DisplayTransform_setInputColorSpaceName, METH_VARARGS, DISPLAYTRANSFORM_SETINPUTCOLORSPACENAME__DOC__ },
+ {"getLinearCC",
+ (PyCFunction) PyOCIO_DisplayTransform_getLinearCC, METH_NOARGS, DISPLAYTRANSFORM_GETLINEARCC__DOC__ },
+ {"setLinearCC",
+ PyOCIO_DisplayTransform_setLinearCC, METH_VARARGS, DISPLAYTRANSFORM_SETLINEARCC__DOC__ },
+ {"getColorTimingCC",
+ (PyCFunction) PyOCIO_DisplayTransform_getColorTimingCC, METH_NOARGS, DISPLAYTRANSFORM_GETCOLORTIMINGCC__DOC__ },
+ {"setColorTimingCC",
+ PyOCIO_DisplayTransform_setColorTimingCC, METH_VARARGS, DISPLAYTRANSFORM_SETCOLORTIMINGCC__DOC__ },
+ {"getChannelView",
+ (PyCFunction) PyOCIO_DisplayTransform_getChannelView, METH_NOARGS, DISPLAYTRANSFORM_GETCHANNELVIEW__DOC__ },
+ {"setChannelView",
+ PyOCIO_DisplayTransform_setChannelView, METH_VARARGS, DISPLAYTRANSFORM_SETCHANNELVIEW__DOC__ },
+ {"getDisplay",
+ (PyCFunction) PyOCIO_DisplayTransform_getDisplay, METH_NOARGS, DISPLAYTRANSFORM_GETDISPLAY__DOC__ },
+ {"setDisplay",
+ PyOCIO_DisplayTransform_setDisplay, METH_VARARGS, DISPLAYTRANSFORM_SETDISPLAY__DOC__ },
+ {"getView",
+ (PyCFunction) PyOCIO_DisplayTransform_getView, METH_NOARGS, DISPLAYTRANSFORM_GETVIEW__DOC__ },
+ {"setView",
+ PyOCIO_DisplayTransform_setView, METH_VARARGS, DISPLAYTRANSFORM_SETVIEW__DOC__ },
+ {"getDisplayCC",
+ (PyCFunction) PyOCIO_DisplayTransform_getDisplayCC, METH_NOARGS, DISPLAYTRANSFORM_GETDISPLAYCC__DOC__ },
+ {"setDisplayCC",
+ PyOCIO_DisplayTransform_setDisplayCC, METH_VARARGS, DISPLAYTRANSFORM_SETDISPLAYCC__DOC__ },
+ {"getLooksOverride",
+ (PyCFunction) PyOCIO_DisplayTransform_getLooksOverride, METH_NOARGS, DISPLAYTRANSFORM_GETLOOKSOVERRIDE__DOC__ },
+ {"setLooksOverride",
+ PyOCIO_DisplayTransform_setLooksOverride, METH_VARARGS, DISPLAYTRANSFORM_SETLOOKSOVERRIDE__DOC__ },
+ {"getLooksOverrideEnabled",
+ (PyCFunction) PyOCIO_DisplayTransform_getLooksOverrideEnabled, METH_NOARGS, DISPLAYTRANSFORM_GETLOOKSOVERRIDEENABLED__DOC__ },
+ {"setLooksOverrideEnabled",
+ PyOCIO_DisplayTransform_setLooksOverrideEnabled, METH_VARARGS, DISPLAYTRANSFORM_SETLOOKSOVERRIDEENABLED__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_DisplayTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.DisplayTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ DISPLAYTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_DisplayTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_DisplayTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ int PyOCIO_DisplayTransform_init( PyOCIO_Transform *self, PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ try
+ {
+ *self->cppobj = DisplayTransform::Create();
+ self->isconst = false;
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create DisplayTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getInputColorSpaceName( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return PyString_FromString( transform->getInputColorSpaceName() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setInputColorSpaceName( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setInputColorSpaceName", &name)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+ transform->setInputColorSpaceName( name );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getLinearCC( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return BuildConstPyTransform(transform->getLinearCC());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setLinearCC( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyCC = 0;
+ if (!PyArg_ParseTuple(args,"O:setLinearCC", &pyCC)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+
+ ConstTransformRcPtr cc = GetConstTransform(pyCC, true);
+ transform->setLinearCC(cc);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getColorTimingCC( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return BuildConstPyTransform(transform->getColorTimingCC());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setColorTimingCC( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyCC = 0;
+ if (!PyArg_ParseTuple(args,"O:setColorTimingCC", &pyCC)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+
+ ConstTransformRcPtr cc = GetConstTransform(pyCC, true);
+ transform->setColorTimingCC(cc);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getChannelView( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return BuildConstPyTransform(transform->getChannelView());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setChannelView( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyCC = 0;
+ if (!PyArg_ParseTuple(args,"O:setChannelView", &pyCC)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+
+ ConstTransformRcPtr t = GetConstTransform(pyCC, true);
+ transform->setChannelView(t);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getDisplay( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return PyString_FromString( transform->getDisplay() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setDisplay( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setDisplay", &str)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+ transform->setDisplay( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_getView( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return PyString_FromString( transform->getView() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setView( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setView", &str)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+ transform->setView( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getDisplayCC( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return BuildConstPyTransform(transform->getDisplayCC());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setDisplayCC( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyCC = 0;
+ if (!PyArg_ParseTuple(args,"O:setDisplayCC", &pyCC)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+
+ ConstTransformRcPtr cc = GetConstTransform(pyCC, true);
+ transform->setDisplayCC(cc);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_DisplayTransform_getLooksOverride( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return PyString_FromString( transform->getLooksOverride() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setLooksOverride( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setLooksOverride", &str)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+ transform->setLooksOverride( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_getLooksOverrideEnabled( PyObject * self )
+ {
+ try
+ {
+ ConstDisplayTransformRcPtr transform = GetConstDisplayTransform(self, true);
+ return PyBool_FromLong( transform->getLooksOverrideEnabled() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_DisplayTransform_setLooksOverrideEnabled( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ bool enabled = false;
+ if (!PyArg_ParseTuple(args,"O&:setLooksOverrideEnabled",
+ ConvertPyObjectToBool, &enabled)) return NULL;
+
+ DisplayTransformRcPtr transform = GetEditableDisplayTransform(self);
+ transform->setLooksOverrideEnabled( enabled );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyExponentTransform.cpp b/src/pyglue/PyExponentTransform.cpp
new file mode 100644
index 0000000..2fa7ba3
--- /dev/null
+++ b/src/pyglue/PyExponentTransform.cpp
@@ -0,0 +1,269 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddExponentTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_ExponentTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ExponentTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ExponentTransformType );
+ PyModule_AddObject(m, "ExponentTransform",
+ (PyObject *)&PyOCIO_ExponentTransformType);
+
+ return true;
+ }
+
+ bool IsPyExponentTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_ExponentTransformType);
+ }
+
+ ConstExponentTransformRcPtr GetConstExponentTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstExponentTransformRcPtr transform = \
+ DynamicPtrCast<const ExponentTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.ExponentTransform.");
+ }
+ return transform;
+ }
+
+ ExponentTransformRcPtr GetEditableExponentTransform(PyObject * pyobject)
+ {
+ ExponentTransformRcPtr transform = \
+ DynamicPtrCast<ExponentTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.ExponentTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_ExponentTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_ExponentTransform_getValue( PyObject * self );
+ PyObject * PyOCIO_ExponentTransform_setValue( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_ExponentTransform_methods[] = {
+ {"getValue",
+ (PyCFunction) PyOCIO_ExponentTransform_getValue, METH_NOARGS, EXPONENTTRANSFORM_GETVALUE__DOC__ },
+ {"setValue",
+ PyOCIO_ExponentTransform_setValue, METH_VARARGS, EXPONENTTRANSFORM_SETVALUE__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ExponentTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.ExponentTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ EXPONENTTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_ExponentTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_ExponentTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_ExponentTransform_init( PyOCIO_Transform *self,
+ PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ PyObject * pyvalue = Py_None;
+ char * direction = NULL;
+
+ static const char *kwlist[] = {
+ "value",
+ "direction",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|Os",
+ const_cast<char **>(kwlist),
+ &pyvalue, &direction )) return -1;
+
+ try
+ {
+ ExponentTransformRcPtr transform = ExponentTransform::Create();
+ *self->cppobj = transform;
+ self->isconst = false;
+
+ if(pyvalue != Py_None)
+ {
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyvalue, data) || (data.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError, "Value argument must be a float array, size 4");
+ return -1;
+ }
+
+ transform->setValue( &data[0] );
+ }
+ if(direction) transform->setDirection(TransformDirectionFromString(direction));
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create ExponentTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_ExponentTransform_getValue( PyObject * self )
+ {
+ try
+ {
+ ConstExponentTransformRcPtr transform = GetConstExponentTransform(self, true);
+ std::vector<float> data(4);
+ transform->getValue(&data[0]);
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ExponentTransform_setValue( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:setValue", &pyData)) return NULL;
+ ExponentTransformRcPtr transform = GetEditableExponentTransform(self);
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || (data.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a float array, size 4");
+ return 0;
+ }
+
+ transform->setValue( &data[0] );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyFileTransform.cpp b/src/pyglue/PyFileTransform.cpp
new file mode 100644
index 0000000..2e85232
--- /dev/null
+++ b/src/pyglue/PyFileTransform.cpp
@@ -0,0 +1,344 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddFileTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_FileTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_FileTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_FileTransformType );
+ PyModule_AddObject(m, "FileTransform",
+ (PyObject *)&PyOCIO_FileTransformType);
+
+ return true;
+ }
+
+ bool IsPyFileTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_FileTransformType);
+ }
+
+ ConstFileTransformRcPtr GetConstFileTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstFileTransformRcPtr transform = \
+ DynamicPtrCast<const FileTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.FileTransform.");
+ }
+ return transform;
+ }
+
+ FileTransformRcPtr GetEditableFileTransform(PyObject * pyobject)
+ {
+ FileTransformRcPtr transform = \
+ DynamicPtrCast<FileTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.FileTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_FileTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_FileTransform_getSrc( PyObject * self );
+ PyObject * PyOCIO_FileTransform_setSrc( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_FileTransform_getCCCId( PyObject * self );
+ PyObject * PyOCIO_FileTransform_setCCCId( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_FileTransform_getInterpolation( PyObject * self );
+ PyObject * PyOCIO_FileTransform_setInterpolation( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_FileTransform_methods[] = {
+ {"getSrc",
+ (PyCFunction) PyOCIO_FileTransform_getSrc, METH_NOARGS, FILETRANSFORM_GETSRC__DOC__ },
+ {"setSrc",
+ PyOCIO_FileTransform_setSrc, METH_VARARGS, FILETRANSFORM_SETSRC__DOC__ },
+ {"getCCCId",
+ (PyCFunction) PyOCIO_FileTransform_getCCCId, METH_NOARGS, FILETRANSFORM_GETCCCID__DOC__ },
+ {"setCCCId",
+ PyOCIO_FileTransform_setCCCId, METH_VARARGS, FILETRANSFORM_SETCCCID__DOC__ },
+ {"getInterpolation",
+ (PyCFunction) PyOCIO_FileTransform_getInterpolation, METH_NOARGS, FILETRANSFORM_GETINTERPOLATION__DOC__ },
+ {"setInterpolation",
+ PyOCIO_FileTransform_setInterpolation, METH_VARARGS, FILETRANSFORM_SETINTERPOLATION__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_FileTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.FileTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ FILETRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_FileTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_FileTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_FileTransform_init( PyOCIO_Transform *self,
+ PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ char * src = NULL;
+ char * cccid = NULL;
+ char * interpolation = NULL;
+ char * direction = NULL;
+
+ static const char *kwlist[] = {
+ "src",
+ "cccid",
+ "interpolation",
+ "direction",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ssss",
+ const_cast<char **>(kwlist),
+ &src, &cccid, &interpolation, &direction )) return -1;
+
+ try
+ {
+ FileTransformRcPtr transform = FileTransform::Create();
+ *self->cppobj = transform;
+ self->isconst = false;
+
+ if(src) transform->setSrc(src);
+ if(cccid) transform->setCCCId(cccid);
+ if(interpolation) transform->setInterpolation(InterpolationFromString(interpolation));
+ if(direction) transform->setDirection(TransformDirectionFromString(direction));
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create FileTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_FileTransform_getSrc( PyObject * self )
+ {
+ try
+ {
+ ConstFileTransformRcPtr transform = GetConstFileTransform(self, true);
+ return PyString_FromString( transform->getSrc() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_FileTransform_setSrc( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * src = 0;
+ if (!PyArg_ParseTuple(args,"s:setSrc", &src)) return NULL;
+
+ FileTransformRcPtr transform = GetEditableFileTransform(self);
+ transform->setSrc( src );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_FileTransform_getCCCId( PyObject * self )
+ {
+ try
+ {
+ ConstFileTransformRcPtr transform = GetConstFileTransform(self, true);
+ return PyString_FromString( transform->getCCCId() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_FileTransform_setCCCId( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * id = 0;
+ if (!PyArg_ParseTuple(args,"s:setCCCId", &id)) return NULL;
+
+ FileTransformRcPtr transform = GetEditableFileTransform(self);
+ transform->setCCCId( id );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_FileTransform_getInterpolation( PyObject * self )
+ {
+ try
+ {
+ ConstFileTransformRcPtr transform = GetConstFileTransform(self, true);
+ Interpolation interp = transform->getInterpolation();
+ return PyString_FromString( InterpolationToString( interp ) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_FileTransform_setInterpolation( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ Interpolation interp;
+ if (!PyArg_ParseTuple(args,"O&:setInterpolation",
+ ConvertPyObjectToInterpolation, &interp)) return NULL;
+
+ FileTransformRcPtr transform = GetEditableFileTransform(self);
+ transform->setInterpolation(interp);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyGroupTransform.cpp b/src/pyglue/PyGroupTransform.cpp
new file mode 100644
index 0000000..32f5b8d
--- /dev/null
+++ b/src/pyglue/PyGroupTransform.cpp
@@ -0,0 +1,397 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddGroupTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_GroupTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_GroupTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_GroupTransformType );
+ PyModule_AddObject(m, "GroupTransform",
+ (PyObject *)&PyOCIO_GroupTransformType);
+
+ return true;
+ }
+
+ bool IsPyGroupTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_GroupTransformType);
+ }
+
+ ConstGroupTransformRcPtr GetConstGroupTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstGroupTransformRcPtr transform = \
+ DynamicPtrCast<const GroupTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.GroupTransform.");
+ }
+ return transform;
+ }
+
+ GroupTransformRcPtr GetEditableGroupTransform(PyObject * pyobject)
+ {
+ GroupTransformRcPtr transform = \
+ DynamicPtrCast<GroupTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.GroupTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_GroupTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_GroupTransform_getTransform( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_GroupTransform_getTransforms( PyObject * self );
+ PyObject * PyOCIO_GroupTransform_setTransforms( PyObject * self, PyObject *args );
+
+ // TODO: make these appear more like a pysequence. .append, len(), etc
+
+ PyObject * PyOCIO_GroupTransform_size( PyObject * self );
+ PyObject * PyOCIO_GroupTransform_push_back( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_GroupTransform_clear( PyObject * self );
+ PyObject * PyOCIO_GroupTransform_empty( PyObject * self );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_GroupTransform_methods[] = {
+ {"getTransform",
+ PyOCIO_GroupTransform_getTransform, METH_VARARGS, GROUPTRANSFORM_GETTRANSFORM__DOC__ },
+ {"getTransforms",
+ (PyCFunction) PyOCIO_GroupTransform_getTransforms, METH_NOARGS, GROUPTRANSFORM_GETTRANSFORMS__DOC__ },
+ {"setTransforms",
+ PyOCIO_GroupTransform_setTransforms, METH_VARARGS, GROUPTRANSFORM_SETTRANSFORMS__DOC__ },
+ {"size",
+ (PyCFunction) PyOCIO_GroupTransform_size, METH_NOARGS, GROUPTRANSFORM_SIZE__DOC__ },
+ {"push_back",
+ PyOCIO_GroupTransform_push_back, METH_VARARGS, GROUPTRANSFORM_PUSH_BACK__DOC__ },
+ {"clear",
+ (PyCFunction) PyOCIO_GroupTransform_clear, METH_NOARGS, GROUPTRANSFORM_CLEAR__DOC__ },
+ {"empty",
+ (PyCFunction) PyOCIO_GroupTransform_empty, METH_NOARGS, GROUPTRANSFORM_EMPTY__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_GroupTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.GroupTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ GROUPTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_GroupTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_GroupTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_GroupTransform_init( PyOCIO_Transform *self,
+ PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ PyObject * pytransforms = Py_None;
+ char * direction = NULL;
+
+ static const char *kwlist[] = {
+ "transforms",
+ "direction",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|Os",
+ const_cast<char **>(kwlist),
+ &pytransforms, &direction )) return -1;
+
+ try
+ {
+ GroupTransformRcPtr transform = GroupTransform::Create();
+ *self->cppobj = transform;
+ self->isconst = false;
+
+ if(pytransforms != Py_None)
+ {
+ std::vector<ConstTransformRcPtr> data;
+ if(!FillTransformVectorFromPySequence(pytransforms, data))
+ {
+ PyErr_SetString(PyExc_TypeError, "Kwarg 'transforms' must be a transform array.");
+ return -1;
+ }
+
+ for(unsigned int i=0; i<data.size(); ++i)
+ {
+ transform->push_back( data[i] );
+ }
+ }
+
+ if(direction) transform->setDirection(TransformDirectionFromString(direction));
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create GroupTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_GroupTransform_getTransform( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ int index = 0;
+
+ if (!PyArg_ParseTuple(args,"i:getTransform", &index)) return NULL;
+
+ ConstGroupTransformRcPtr transform = GetConstGroupTransform(self, true);
+ ConstTransformRcPtr childTransform = transform->getTransform(index);
+
+ return BuildConstPyTransform(childTransform);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GroupTransform_getTransforms( PyObject * self)
+ {
+ try
+ {
+ ConstGroupTransformRcPtr transform = GetConstGroupTransform(self, true);
+
+ std::vector<ConstTransformRcPtr> transforms;
+ for(int i=0; i<transform->size(); ++i)
+ {
+ transforms.push_back(transform->getTransform(i));
+ }
+
+ return CreatePyListFromTransformVector(transforms);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GroupTransform_setTransforms( PyObject * self, PyObject *args )
+ {
+ try
+ {
+ PyObject * pytransforms = 0;
+
+ if (!PyArg_ParseTuple(args,"O:setTransforms", &pytransforms)) return NULL;
+
+ GroupTransformRcPtr transform = GetEditableGroupTransform(self);
+
+ std::vector<ConstTransformRcPtr> data;
+ if(!FillTransformVectorFromPySequence(pytransforms, data))
+ {
+ PyErr_SetString(PyExc_TypeError, "First argument must be a transform array.");
+ return 0;
+ }
+
+ transform->clear();
+
+ for(unsigned int i=0; i<data.size(); ++i)
+ {
+ transform->push_back( data[i] );
+ }
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_GroupTransform_size( PyObject * self )
+ {
+ try
+ {
+ ConstGroupTransformRcPtr transform = GetConstGroupTransform(self, true);
+ return PyInt_FromLong( transform->size() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GroupTransform_push_back( PyObject * self, PyObject *args )
+ {
+ try
+ {
+ PyObject * pytransform = 0;
+
+ if (!PyArg_ParseTuple(args,"O:push_back", &pytransform)) return NULL;
+
+ GroupTransformRcPtr transform = GetEditableGroupTransform(self);
+
+ if(!IsPyTransform(pytransform))
+ {
+ throw Exception("GroupTransform.push_back requires a transform as the first arg.");
+ }
+
+ transform->push_back( GetConstTransform(pytransform, true) );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GroupTransform_clear( PyObject * self )
+ {
+ try
+ {
+ GroupTransformRcPtr transform = GetEditableGroupTransform(self);
+ transform->clear();
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GroupTransform_empty( PyObject * self )
+ {
+ try
+ {
+ ConstGroupTransformRcPtr transform = GetConstGroupTransform(self, true);
+ return PyBool_FromLong( transform->empty() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyLogTransform.cpp b/src/pyglue/PyLogTransform.cpp
new file mode 100644
index 0000000..e2c1462
--- /dev/null
+++ b/src/pyglue/PyLogTransform.cpp
@@ -0,0 +1,251 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddLogTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_LogTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_LogTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_LogTransformType );
+ PyModule_AddObject(m, "LogTransform",
+ (PyObject *)&PyOCIO_LogTransformType);
+
+ return true;
+ }
+
+ bool IsPyLogTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_LogTransformType);
+ }
+
+ ConstLogTransformRcPtr GetConstLogTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstLogTransformRcPtr transform = \
+ DynamicPtrCast<const LogTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.LogTransform.");
+ }
+ return transform;
+ }
+
+ LogTransformRcPtr GetEditableLogTransform(PyObject * pyobject)
+ {
+ LogTransformRcPtr transform = \
+ DynamicPtrCast<LogTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.LogTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_LogTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_LogTransform_getBase( PyObject * self );
+ PyObject * PyOCIO_LogTransform_setBase( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_LogTransform_methods[] = {
+ {"getBase",
+ (PyCFunction) PyOCIO_LogTransform_getBase, METH_NOARGS, LOGTRANSFORM_GETBASE__DOC__ },
+ {"setBase",
+ PyOCIO_LogTransform_setBase, METH_VARARGS, LOGTRANSFORM_SETBASE__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_LogTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.LogTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ LOGTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_LogTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_LogTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_LogTransform_init( PyOCIO_Transform *self,
+ PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ float base = -1.0f; // -1.0 is an illegal value for log transform base
+ char * direction = NULL;
+
+ static const char *kwlist[] = {
+ "base",
+ "direction",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|fs",
+ const_cast<char **>(kwlist),
+ &base, &direction )) return -1;
+
+ try
+ {
+ LogTransformRcPtr transform = LogTransform::Create();
+ *self->cppobj = transform;
+ self->isconst = false;
+
+ if(base != -1.0f) transform->setBase(base);
+ if(direction) transform->setDirection(TransformDirectionFromString(direction));
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create LogTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_LogTransform_getBase( PyObject * self )
+ {
+ try
+ {
+ ConstLogTransformRcPtr transform = GetConstLogTransform(self, true);
+ return PyFloat_FromDouble(transform->getBase());
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_LogTransform_setBase( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ float base;
+ if (!PyArg_ParseTuple(args,"f:setBase", &base)) return NULL;
+ LogTransformRcPtr transform = GetEditableLogTransform(self);
+
+ transform->setBase( base );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyLook.cpp b/src/pyglue/PyLook.cpp
new file mode 100644
index 0000000..3f1128f
--- /dev/null
+++ b/src/pyglue/PyLook.cpp
@@ -0,0 +1,450 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyLook.h"
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddLookObjectToModule( PyObject* m )
+ {
+ PyOCIO_LookType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_LookType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_LookType );
+ PyModule_AddObject(m, "Look",
+ (PyObject *)&PyOCIO_LookType);
+
+ return true;
+ }
+
+ PyObject * BuildConstPyLook(ConstLookRcPtr look)
+ {
+ if (!look)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Look * pyLook = PyObject_New(
+ PyOCIO_Look, (PyTypeObject * ) &PyOCIO_LookType);
+
+ pyLook->constcppobj = new ConstLookRcPtr();
+ *pyLook->constcppobj = look;
+
+ pyLook->cppobj = new LookRcPtr();
+ pyLook->isconst = true;
+
+ return ( PyObject * ) pyLook;
+ }
+
+ PyObject * BuildEditablePyLook(LookRcPtr look)
+ {
+ if (!look)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Look * pyLook = PyObject_New(
+ PyOCIO_Look, (PyTypeObject * ) &PyOCIO_LookType);
+
+ pyLook->constcppobj = new ConstLookRcPtr();
+ pyLook->cppobj = new LookRcPtr();
+ *pyLook->cppobj = look;
+
+ pyLook->isconst = false;
+
+ return ( PyObject * ) pyLook;
+ }
+
+ bool IsPyLook(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return (PyObject_Type(pyobject) == (PyObject *) (&PyOCIO_LookType));
+ }
+
+ bool IsPyLookEditable(PyObject * pyobject)
+ {
+ if(!IsPyLook(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Look.");
+ }
+
+ PyOCIO_Look * pyLook = reinterpret_cast<PyOCIO_Look *> (pyobject);
+ return (!pyLook->isconst);
+ }
+
+ ConstLookRcPtr GetConstLook(PyObject * pyobject, bool allowCast)
+ {
+ if(!IsPyLook(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Look.");
+ }
+
+ PyOCIO_Look * pylook = reinterpret_cast<PyOCIO_Look *> (pyobject);
+ if(pylook->isconst && pylook->constcppobj)
+ {
+ return *pylook->constcppobj;
+ }
+
+ if(allowCast && !pylook->isconst && pylook->cppobj)
+ {
+ return *pylook->cppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.Look.");
+ }
+
+ LookRcPtr GetEditableLook(PyObject * pyobject)
+ {
+ if(!IsPyLook(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Look.");
+ }
+
+ PyOCIO_Look * pylook = reinterpret_cast<PyOCIO_Look *> (pyobject);
+ if(!pylook->isconst && pylook->cppobj)
+ {
+ return *pylook->cppobj;
+ }
+
+ throw Exception("PyObject must be an editable OCIO.Look.");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_Look_init( PyOCIO_Look * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_Look_delete( PyOCIO_Look * self, PyObject * args );
+ PyObject * PyOCIO_Look_isEditable( PyObject * self );
+ PyObject * PyOCIO_Look_createEditableCopy( PyObject * self );
+
+ PyObject * PyOCIO_Look_getName( PyObject * self );
+ PyObject * PyOCIO_Look_setName( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_Look_getProcessSpace( PyObject * self );
+ PyObject * PyOCIO_Look_setProcessSpace( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_Look_getTransform( PyObject * self );
+ PyObject * PyOCIO_Look_setTransform( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_Look_methods[] = {
+ {"isEditable",
+ (PyCFunction) PyOCIO_Look_isEditable, METH_NOARGS, LOOK_ISEDITABLE__DOC__ },
+ {"createEditableCopy",
+ (PyCFunction) PyOCIO_Look_createEditableCopy, METH_NOARGS, LOOK_CREATEEDITABLECOPY__DOC__ },
+ {"getName",
+ (PyCFunction) PyOCIO_Look_getName, METH_NOARGS, LOOK_GETNAME__DOC__ },
+ {"setName",
+ PyOCIO_Look_setName, METH_VARARGS, LOOK_SETNAME__DOC__ },
+ {"getProcessSpace",
+ (PyCFunction) PyOCIO_Look_getProcessSpace, METH_NOARGS, LOOK_GETPROCESSSPACE__DOC__ },
+ {"setProcessSpace",
+ PyOCIO_Look_setProcessSpace, METH_VARARGS, LOOK_SETPROCESSSPACE__DOC__ },
+ {"getTransform",
+ (PyCFunction) PyOCIO_Look_getTransform, METH_NOARGS, LOOK_GETTRANSFORM__DOC__ },
+ {"setTransform",
+ PyOCIO_Look_setTransform, METH_VARARGS, LOOK_SETTRANSFORM__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_LookType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.Look", //tp_name
+ sizeof(PyOCIO_Look), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PyOCIO_Look_delete, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ LOOK__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_Look_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_Look_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_Look_init( PyOCIO_Look *self, PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstLookRcPtr();
+ self->cppobj = new LookRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ char * name = NULL;
+ char * processSpace = NULL;
+ PyObject * pytransform = NULL;
+
+ const char *kwlist[] = {
+ "name", "processSpace", "transform",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ssO",
+ const_cast<char **>(kwlist),
+ &name, &processSpace, &pytransform)) return -1;
+
+ try
+ {
+ LookRcPtr look = Look::Create();
+ *self->cppobj = look;
+ self->isconst = false;
+
+ if(name) look->setName(name);
+ if(processSpace) look->setProcessSpace(processSpace);
+
+ if(pytransform)
+ {
+ ConstTransformRcPtr transform = GetConstTransform(pytransform, true);
+ look->setTransform(transform);
+ }
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create look: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ void PyOCIO_Look_delete( PyOCIO_Look *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ delete self->cppobj;
+
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Look_isEditable( PyObject * self )
+ {
+ return PyBool_FromLong(IsPyLookEditable(self));
+ }
+
+ PyObject * PyOCIO_Look_createEditableCopy( PyObject * self )
+ {
+ try
+ {
+ ConstLookRcPtr look = GetConstLook(self, true);
+ LookRcPtr copy = look->createEditableCopy();
+ return BuildEditablePyLook( copy );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Look_getName( PyObject * self )
+ {
+ try
+ {
+ ConstLookRcPtr look = GetConstLook(self, true);
+ return PyString_FromString( look->getName() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Look_setName( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * name = 0;
+ if (!PyArg_ParseTuple(args,"s:setName", &name)) return NULL;
+
+ LookRcPtr look = GetEditableLook(self);
+ look->setName( name );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Look_getProcessSpace( PyObject * self )
+ {
+ try
+ {
+ ConstLookRcPtr look = GetConstLook(self, true);
+ return PyString_FromString( look->getProcessSpace() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Look_setProcessSpace( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ char * processSpace = 0;
+ if (!PyArg_ParseTuple(args,"s:setProcessSpace", &processSpace)) return NULL;
+
+ LookRcPtr look = GetEditableLook(self);
+ look->setProcessSpace( processSpace );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Look_getTransform( PyObject * self )
+ {
+ try
+ {
+ ConstLookRcPtr look = GetConstLook(self, true);
+ ConstTransformRcPtr transform = look->getTransform();
+ return BuildConstPyTransform(transform);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Look_setTransform( PyObject * self, PyObject *args )
+ {
+ try
+ {
+ PyObject * pytransform = 0;
+ if (!PyArg_ParseTuple(args,"O:setTransform", &pytransform))
+ return NULL;
+
+ ConstTransformRcPtr transform = GetConstTransform(pytransform, true);
+ LookRcPtr look = GetEditableLook(self);
+ look->setTransform(transform);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyLook.h b/src/pyglue/PyLook.h
new file mode 100644
index 0000000..371eafa
--- /dev/null
+++ b/src/pyglue/PyLook.h
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYLOOK_H
+#define INCLUDED_PYOCIO_PYLOOK_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ typedef struct {
+ PyObject_HEAD
+ ConstLookRcPtr * constcppobj;
+ LookRcPtr * cppobj;
+ bool isconst;
+ } PyOCIO_Look;
+
+ extern PyTypeObject PyOCIO_LookType;
+
+ bool AddLookObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyLookTransform.cpp b/src/pyglue/PyLookTransform.cpp
new file mode 100644
index 0000000..6b57afb
--- /dev/null
+++ b/src/pyglue/PyLookTransform.cpp
@@ -0,0 +1,343 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddLookTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_LookTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_LookTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_LookTransformType );
+ PyModule_AddObject(m, "LookTransform",
+ (PyObject *)&PyOCIO_LookTransformType);
+
+ return true;
+ }
+
+ bool IsPyLookTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_LookTransformType);
+ }
+
+ ConstLookTransformRcPtr GetConstLookTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstLookTransformRcPtr transform = \
+ DynamicPtrCast<const LookTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.LookTransform.");
+ }
+ return transform;
+ }
+
+ LookTransformRcPtr GetEditableLookTransform(PyObject * pyobject)
+ {
+ LookTransformRcPtr transform = \
+ DynamicPtrCast<LookTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.LookTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_LookTransform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_LookTransform_getSrc( PyObject * self );
+ PyObject * PyOCIO_LookTransform_setSrc( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_LookTransform_getDst( PyObject * self );
+ PyObject * PyOCIO_LookTransform_setDst( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_LookTransform_getLooks( PyObject * self );
+ PyObject * PyOCIO_LookTransform_setLooks( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_LookTransform_methods[] = {
+ {"getSrc",
+ (PyCFunction) PyOCIO_LookTransform_getSrc, METH_NOARGS, LOOKTRANSFORM_GETSRC__DOC__ },
+ {"setSrc",
+ PyOCIO_LookTransform_setSrc, METH_VARARGS, LOOKTRANSFORM_SETSRC__DOC__ },
+ {"getDst",
+ (PyCFunction) PyOCIO_LookTransform_getDst, METH_NOARGS, LOOKTRANSFORM_GETDST__DOC__ },
+ {"setDst",
+ PyOCIO_LookTransform_setDst, METH_VARARGS, LOOKTRANSFORM_SETDST__DOC__ },
+ {"getLooks",
+ (PyCFunction) PyOCIO_LookTransform_getLooks, METH_NOARGS, LOOKTRANSFORM_GETLOOKS__DOC__ },
+ {"setLooks",
+ PyOCIO_LookTransform_setLooks, METH_VARARGS, LOOKTRANSFORM_SETLOOKS__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_LookTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.LookTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ LOOKTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_LookTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_LookTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_LookTransform_init( PyOCIO_Transform *self,
+ PyObject * args, PyObject * kwds )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ // Parse optional kwargs
+ char * src = NULL;
+ char * dst = NULL;
+ char * looks = NULL;
+ char * direction = NULL;
+
+ static const char *kwlist[] = {
+ "src",
+ "dst",
+ "looks",
+ "direction",
+ NULL
+ };
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ssss",
+ const_cast<char **>(kwlist),
+ &src, &dst, &looks, &direction )) return -1;
+
+ try
+ {
+ LookTransformRcPtr transform = LookTransform::Create();
+ *self->cppobj = transform;
+ self->isconst = false;
+
+ if(src) transform->setSrc(src);
+ if(dst) transform->setDst(dst);
+ if(looks) transform->setLooks(looks);
+ if(direction) transform->setDirection(TransformDirectionFromString(direction));
+
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create LookTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_LookTransform_getSrc( PyObject * self )
+ {
+ try
+ {
+ ConstLookTransformRcPtr transform = GetConstLookTransform(self, true);
+ return PyString_FromString( transform->getSrc() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_LookTransform_setSrc( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setSrc",
+ &str)) return NULL;
+
+ LookTransformRcPtr transform = GetEditableLookTransform(self);
+ transform->setSrc( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_LookTransform_getDst( PyObject * self )
+ {
+ try
+ {
+ ConstLookTransformRcPtr transform = GetConstLookTransform(self, true);
+ return PyString_FromString( transform->getDst() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_LookTransform_setDst( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setDst",
+ &str)) return NULL;
+
+ LookTransformRcPtr transform = GetEditableLookTransform(self);
+ transform->setDst( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_LookTransform_getLooks( PyObject * self )
+ {
+ try
+ {
+ ConstLookTransformRcPtr transform = GetConstLookTransform(self, true);
+ return PyString_FromString( transform->getLooks() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_LookTransform_setLooks( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ const char * str = 0;
+ if (!PyArg_ParseTuple(args,"s:setLooks",
+ &str)) return NULL;
+
+ LookTransformRcPtr transform = GetEditableLookTransform(self);
+ transform->setLooks( str );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyMain.cpp b/src/pyglue/PyMain.cpp
new file mode 100644
index 0000000..4feea32
--- /dev/null
+++ b/src/pyglue/PyMain.cpp
@@ -0,0 +1,236 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+
+#include "PyColorSpace.h"
+#include "PyConfig.h"
+#include "PyContext.h"
+#include "PyConstants.h"
+#include "PyLook.h"
+#include "PyProcessor.h"
+#include "PyProcessorMetadata.h"
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+namespace
+{
+ PyObject * PyOCIO_ClearAllCaches(PyObject * /* self */)
+ {
+ try
+ {
+ OCIO::ClearAllCaches();
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ OCIO::Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GetLoggingLevel(PyObject * /* self */)
+ {
+ try
+ {
+ return PyString_FromString(
+ OCIO::LoggingLevelToString(OCIO::GetLoggingLevel()) );
+ }
+ catch(...)
+ {
+ OCIO::Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_SetLoggingLevel(PyObject * /*self*/, PyObject * args)
+ {
+ try
+ {
+ PyObject * pylevel;
+ if (!PyArg_ParseTuple(args, "O:SetLoggingLevel", &pylevel))
+ {
+ return NULL;
+ }
+
+ // We explicitly cast to a str to handle both the str and int cases.
+ PyObject * pystr = PyObject_Str(pylevel);
+ if(!pystr)
+ {
+ throw OCIO::Exception("Fist argument must be a LOGGING_LEVEL");
+ }
+
+ OCIO::LoggingLevel level = OCIO::LoggingLevelFromString(PyString_AsString(pystr));
+ OCIO::SetLoggingLevel(level);
+
+ Py_DECREF(pystr);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ OCIO::Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_GetCurrentConfig(PyObject * /* self */)
+ {
+ try
+ {
+ return OCIO::BuildConstPyConfig( OCIO::GetCurrentConfig() );
+ }
+ catch(...)
+ {
+ OCIO::Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_SetCurrentConfig(PyObject * /*self*/, PyObject * args)
+ {
+ try
+ {
+ PyObject * pyconfig;
+ if (!PyArg_ParseTuple(args, "O!:SetCurrentConfig",
+ &OCIO::PyOCIO_ConfigType, &pyconfig))
+ {
+ return NULL;
+ }
+
+ OCIO::ConstConfigRcPtr c = OCIO::GetConstConfig(pyconfig, true);
+ OCIO::SetCurrentConfig(c);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ OCIO::Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyMethodDef PyOCIO_methods[] = {
+ {"ClearAllCaches",
+ (PyCFunction) PyOCIO_ClearAllCaches, METH_NOARGS, OCIO::OPENCOLORIO_CLEARALLCACHES__DOC__ },
+ {"GetLoggingLevel",
+ (PyCFunction) PyOCIO_GetLoggingLevel, METH_NOARGS, OCIO::OPENCOLORIO_GETLOGGINGLEVEL__DOC__ },
+ {"SetLoggingLevel",
+ (PyCFunction) PyOCIO_SetLoggingLevel, METH_VARARGS, OCIO::OPENCOLORIO_SETLOGGINGLEVEL__DOC__ },
+ {"GetCurrentConfig",
+ (PyCFunction) PyOCIO_GetCurrentConfig, METH_NOARGS, OCIO::OPENCOLORIO_GETCURRENTCONFIG__DOC__ },
+ {"SetCurrentConfig",
+ (PyCFunction) PyOCIO_SetCurrentConfig, METH_VARARGS, OCIO::OPENCOLORIO_SETCURRENTCONFIG__DOC__ },
+ {NULL, NULL, 0, NULL} /* Sentinel */
+ };
+}
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ PyObject * g_exceptionType = NULL;
+ PyObject * g_exceptionMissingFileType = NULL;
+ }
+
+ // These are explicitly initialized in the init function
+ // to make sure they're not initialized until after the module is
+
+ PyObject * GetExceptionPyType()
+ {
+ return g_exceptionType;
+ }
+
+ void SetExceptionPyType(PyObject * pytypeobj)
+ {
+ g_exceptionType = pytypeobj;
+ }
+
+ PyObject * GetExceptionMissingFilePyType()
+ {
+ return g_exceptionMissingFileType;
+ }
+
+ void SetExceptionMissingFilePyType(PyObject * pytypeobj)
+ {
+ g_exceptionMissingFileType = pytypeobj;
+ }
+}
+OCIO_NAMESPACE_EXIT
+
+extern "C"
+PyMODINIT_FUNC
+initPyOpenColorIO(void)
+{
+ PyObject * m;
+ m = Py_InitModule3("PyOpenColorIO", PyOCIO_methods, OCIO::OPENCOLORIO__DOC__);
+
+ PyModule_AddStringConstant(m, "version", OCIO::GetVersion());
+ PyModule_AddIntConstant(m, "hexversion", OCIO::GetVersionHex());
+
+ // Create Exceptions, and add to the module
+ // TODO: add support for PyErr_NewExceptionWithDoc for python2.7+
+ OCIO::SetExceptionPyType(
+ PyErr_NewException(const_cast<char*>("PyOpenColorIO.Exception"),
+ PyExc_RuntimeError, NULL));
+ PyModule_AddObject(m, "Exception", OCIO::GetExceptionPyType());
+
+ // TODO: add support for PyErr_NewExceptionWithDoc for python2.7+
+ OCIO::SetExceptionMissingFilePyType(
+ PyErr_NewException(const_cast<char*>("PyOpenColorIO.ExceptionMissingFile"),
+ OCIO::GetExceptionPyType(), NULL));
+ PyModule_AddObject(m, "ExceptionMissingFile", OCIO::GetExceptionMissingFilePyType());
+
+ // Register Classes
+
+ OCIO::AddColorSpaceObjectToModule( m );
+ OCIO::AddConfigObjectToModule( m );
+ OCIO::AddConstantsModule( m );
+ OCIO::AddContextObjectToModule( m );
+ OCIO::AddLookObjectToModule( m );
+ OCIO::AddProcessorObjectToModule( m );
+ OCIO::AddProcessorMetadataObjectToModule( m );
+
+ OCIO::AddTransformObjectToModule( m );
+ {
+ OCIO::AddAllocationTransformObjectToModule( m );
+ OCIO::AddCDLTransformObjectToModule( m );
+ OCIO::AddColorSpaceTransformObjectToModule( m );
+ OCIO::AddDisplayTransformObjectToModule( m );
+ OCIO::AddExponentTransformObjectToModule( m );
+ OCIO::AddFileTransformObjectToModule( m );
+ OCIO::AddGroupTransformObjectToModule( m );
+ OCIO::AddLogTransformObjectToModule( m );
+ OCIO::AddLookTransformObjectToModule( m );
+ OCIO::AddMatrixTransformObjectToModule( m );
+ }
+}
diff --git a/src/pyglue/PyMatrixTransform.cpp b/src/pyglue/PyMatrixTransform.cpp
new file mode 100644
index 0000000..f0a0012
--- /dev/null
+++ b/src/pyglue/PyMatrixTransform.cpp
@@ -0,0 +1,630 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddMatrixTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_MatrixTransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_MatrixTransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_MatrixTransformType );
+ PyModule_AddObject(m, "MatrixTransform",
+ (PyObject *)&PyOCIO_MatrixTransformType);
+
+ return true;
+ }
+
+ bool IsPyMatrixTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_MatrixTransformType);
+ }
+
+ ConstMatrixTransformRcPtr GetConstMatrixTransform(PyObject * pyobject, bool allowCast)
+ {
+ ConstMatrixTransformRcPtr transform = \
+ DynamicPtrCast<const MatrixTransform>(GetConstTransform(pyobject, allowCast));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.MatrixTransform.");
+ }
+ return transform;
+ }
+
+ MatrixTransformRcPtr GetEditableMatrixTransform(PyObject * pyobject)
+ {
+ MatrixTransformRcPtr transform = \
+ DynamicPtrCast<MatrixTransform>(GetEditableTransform(pyobject));
+ if(!transform)
+ {
+ throw Exception("PyObject must be a valid OCIO.MatrixTransform.");
+ }
+ return transform;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_MatrixTransform_init( PyOCIO_Transform * self,
+ PyObject * args, PyObject * kwds );
+
+ PyObject * PyOCIO_MatrixTransform_getValue( PyObject * self );
+ PyObject * PyOCIO_MatrixTransform_setValue( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_MatrixTransform_getMatrix( PyObject * self );
+ PyObject * PyOCIO_MatrixTransform_setMatrix( PyObject * self, PyObject *args );
+ PyObject * PyOCIO_MatrixTransform_getOffset( PyObject * self );
+ PyObject * PyOCIO_MatrixTransform_setOffset( PyObject * self, PyObject *args );
+
+ PyObject * PyOCIO_MatrixTransform_Identity( PyObject * cls );
+ PyObject * PyOCIO_MatrixTransform_Fit( PyObject * cls, PyObject * args );
+ PyObject * PyOCIO_MatrixTransform_Sat( PyObject * cls, PyObject * args );
+ PyObject * PyOCIO_MatrixTransform_Scale( PyObject * cls, PyObject * args );
+ PyObject * PyOCIO_MatrixTransform_View( PyObject * cls, PyObject * args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_MatrixTransform_methods[] = {
+ {"getValue",
+ (PyCFunction) PyOCIO_MatrixTransform_getValue, METH_NOARGS, MATRIXTRANSFORM_GETVALUE__DOC__ },
+ {"setValue",
+ PyOCIO_MatrixTransform_setValue, METH_VARARGS, MATRIXTRANSFORM_SETVALUE__DOC__ },
+ {"getMatrix",
+ (PyCFunction) PyOCIO_MatrixTransform_getMatrix, METH_NOARGS, MATRIXTRANSFORM_GETMATRIX__DOC__ },
+ {"setMatrix",
+ PyOCIO_MatrixTransform_setMatrix, METH_VARARGS, MATRIXTRANSFORM_SETMATRIX__DOC__ },
+ {"getOffset",
+ (PyCFunction) PyOCIO_MatrixTransform_getOffset, METH_NOARGS, MATRIXTRANSFORM_GETOFFSET__DOC__ },
+ {"setOffset",
+ PyOCIO_MatrixTransform_setOffset, METH_VARARGS, MATRIXTRANSFORM_SETOFFSET__DOC__ },
+ {"Identity",
+ (PyCFunction) PyOCIO_MatrixTransform_Identity, METH_NOARGS | METH_CLASS, MATRIXTRANSFORM_IDENTITY__DOC__ },
+ {"Fit",
+ PyOCIO_MatrixTransform_Fit, METH_VARARGS | METH_CLASS, MATRIXTRANSFORM_FIT__DOC__ },
+ {"Sat",
+ PyOCIO_MatrixTransform_Sat, METH_VARARGS | METH_CLASS, MATRIXTRANSFORM_SAT__DOC__ },
+ {"Scale",
+ PyOCIO_MatrixTransform_Scale, METH_VARARGS | METH_CLASS, MATRIXTRANSFORM_SCALE__DOC__ },
+ {"View",
+ PyOCIO_MatrixTransform_View, METH_VARARGS | METH_CLASS, MATRIXTRANSFORM_VIEW__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_MatrixTransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.MatrixTransform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ 0, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ MATRIXTRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_MatrixTransform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ &PyOCIO_TransformType, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_MatrixTransform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_MatrixTransform_init( PyOCIO_Transform *self,
+ PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ try
+ {
+ *self->cppobj = MatrixTransform::Create();
+ self->isconst = false;
+ return 0;
+ }
+ catch ( const std::exception & e )
+ {
+ std::string message = "Cannot create MatrixTransform: ";
+ message += e.what();
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_MatrixTransform_getValue( PyObject * self )
+ {
+ try
+ {
+ ConstMatrixTransformRcPtr transform = GetConstMatrixTransform(self, true);
+
+ std::vector<float> matrix(16);
+ std::vector<float> offset(4);
+
+ transform->getValue(&matrix[0], &offset[0]);
+
+ PyObject* pymatrix = CreatePyListFromFloatVector(matrix);
+ PyObject* pyoffset = CreatePyListFromFloatVector(offset);
+
+ PyObject* pyreturnval = Py_BuildValue("(OO)", pymatrix, pyoffset);
+ Py_DECREF(pymatrix);
+ Py_DECREF(pyoffset);
+
+ return pyreturnval;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_setValue( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pymatrix = 0;
+ PyObject * pyoffset = 0;
+ if (!PyArg_ParseTuple(args,"OO:setValue",
+ &pymatrix, &pyoffset)) return NULL;
+
+ std::vector<float> matrix;
+ std::vector<float> offset;
+
+ if(!FillFloatVectorFromPySequence(pymatrix, matrix) ||
+ (matrix.size() != 16))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "First argument must be a float array, size 16");
+ return 0;
+ }
+
+ if(!FillFloatVectorFromPySequence(pyoffset, offset) ||
+ (offset.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Second argument must be a float array, size 4");
+ return 0;
+ }
+
+ MatrixTransformRcPtr transform = GetEditableMatrixTransform(self);
+ transform->setValue(&matrix[0], &offset[0]);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_MatrixTransform_getMatrix( PyObject * self )
+ {
+ try
+ {
+ ConstMatrixTransformRcPtr transform = GetConstMatrixTransform(self, true);
+
+ std::vector<float> matrix(16);
+ transform->getMatrix(&matrix[0]);
+
+ return CreatePyListFromFloatVector(matrix);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_setMatrix( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pymatrix = 0;
+ if (!PyArg_ParseTuple(args,"O:setValue", &pymatrix)) return NULL;
+
+ std::vector<float> matrix;
+
+ if(!FillFloatVectorFromPySequence(pymatrix, matrix) ||
+ (matrix.size() != 16))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "First argument must be a float array, size 16");
+ return 0;
+ }
+
+ MatrixTransformRcPtr transform = GetEditableMatrixTransform(self);
+ transform->setMatrix(&matrix[0]);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_MatrixTransform_getOffset( PyObject * self )
+ {
+ try
+ {
+ ConstMatrixTransformRcPtr transform = GetConstMatrixTransform(self, true);
+
+ std::vector<float> offset(4);
+ transform->getOffset(&offset[0]);
+
+ return CreatePyListFromFloatVector(offset);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_setOffset( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyoffset = 0;
+ if (!PyArg_ParseTuple(args,"O:setValue", &pyoffset)) return NULL;
+
+ std::vector<float> offset;
+
+ if(!FillFloatVectorFromPySequence(pyoffset, offset) ||
+ (offset.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "First argument must be a float array, size 4");
+ return 0;
+ }
+
+ MatrixTransformRcPtr transform = GetEditableMatrixTransform(self);
+ transform->setOffset(&offset[0]);
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_MatrixTransform_Identity( PyObject * /*cls*/ )
+ {
+ try
+ {
+ std::vector<float> matrix(16);
+ std::vector<float> offset(4);
+
+ MatrixTransform::Identity(&matrix[0], &offset[0]);
+
+ PyObject* pymatrix = CreatePyListFromFloatVector(matrix);
+ PyObject* pyoffset = CreatePyListFromFloatVector(offset);
+
+ PyObject* pyreturnval = Py_BuildValue("(OO)", pymatrix, pyoffset);
+ Py_DECREF(pymatrix);
+ Py_DECREF(pyoffset);
+
+ return pyreturnval;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_Fit( PyObject * /*cls*/, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyoldmin = 0;
+ PyObject * pyoldmax = 0;
+ PyObject * pynewmin = 0;
+ PyObject * pynewmax = 0;
+
+ if (!PyArg_ParseTuple(args,"OOOO:Fit",
+ &pyoldmin, &pyoldmax, &pynewmin, &pynewmax)) return NULL;
+
+ std::vector<float> oldmin;
+ std::vector<float> oldmax;
+ std::vector<float> newmin;
+ std::vector<float> newmax;
+
+ if(!FillFloatVectorFromPySequence(pyoldmin, oldmin) ||
+ (oldmin.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "First argument must be a float array, size 4");
+ return 0;
+ }
+
+ if(!FillFloatVectorFromPySequence(pyoldmax, oldmax) ||
+ (oldmax.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Second argument must be a float array, size 4");
+ return 0;
+ }
+
+ if(!FillFloatVectorFromPySequence(pynewmin, newmin) ||
+ (newmin.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Third argument must be a float array, size 4");
+ return 0;
+ }
+
+ if(!FillFloatVectorFromPySequence(pynewmax, newmax) ||
+ (newmax.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Fourth argument must be a float array, size 4");
+ return 0;
+ }
+
+
+ std::vector<float> matrix(16);
+ std::vector<float> offset(4);
+
+ MatrixTransform::Fit(&matrix[0], &offset[0],
+ &oldmin[0], &oldmax[0],
+ &newmin[0], &newmax[0]);
+
+ PyObject* pymatrix = CreatePyListFromFloatVector(matrix);
+ PyObject* pyoffset = CreatePyListFromFloatVector(offset);
+
+ PyObject* pyreturnval = Py_BuildValue("(OO)", pymatrix, pyoffset);
+ Py_DECREF(pymatrix);
+ Py_DECREF(pyoffset);
+
+ return pyreturnval;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_Sat( PyObject * /*cls*/, PyObject * args )
+ {
+ try
+ {
+ float sat = 0.0;
+ PyObject * pyluma = 0;
+
+ if (!PyArg_ParseTuple(args,"fO:Sat",
+ &sat, &pyluma)) return NULL;
+
+ std::vector<float> luma;
+
+ if(!FillFloatVectorFromPySequence(pyluma, luma) ||
+ (luma.size() != 3))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Second argument must be a float array, size 3");
+ return 0;
+ }
+
+ std::vector<float> matrix(16);
+ std::vector<float> offset(4);
+
+ MatrixTransform::Sat(&matrix[0], &offset[0],
+ sat, &luma[0]);
+
+ PyObject* pymatrix = CreatePyListFromFloatVector(matrix);
+ PyObject* pyoffset = CreatePyListFromFloatVector(offset);
+
+ PyObject* pyreturnval = Py_BuildValue("(OO)", pymatrix, pyoffset);
+ Py_DECREF(pymatrix);
+ Py_DECREF(pyoffset);
+
+ return pyreturnval;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_Scale( PyObject * /*cls*/, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyscale = 0;
+
+ if (!PyArg_ParseTuple(args,"O:Scale",
+ &pyscale)) return NULL;
+
+ std::vector<float> scale;
+
+ if(!FillFloatVectorFromPySequence(pyscale, scale) ||
+ (scale.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Second argument must be a float array, size 4");
+ return 0;
+ }
+
+ std::vector<float> matrix(16);
+ std::vector<float> offset(4);
+
+ MatrixTransform::Scale(&matrix[0], &offset[0],
+ &scale[0]);
+
+ PyObject* pymatrix = CreatePyListFromFloatVector(matrix);
+ PyObject* pyoffset = CreatePyListFromFloatVector(offset);
+
+ PyObject* pyreturnval = Py_BuildValue("(OO)", pymatrix, pyoffset);
+ Py_DECREF(pymatrix);
+ Py_DECREF(pyoffset);
+
+ return pyreturnval;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_MatrixTransform_View( PyObject * /*cls*/, PyObject * args )
+ {
+ try
+ {
+ PyObject * pychannelhot = 0;
+ PyObject * pyluma = 0;
+
+ if (!PyArg_ParseTuple(args,"OO:View",
+ &pychannelhot, &pyluma)) return NULL;
+
+ std::vector<int> channelhot;
+ std::vector<float> luma;
+
+ if(!FillIntVectorFromPySequence(pychannelhot, channelhot) ||
+ (channelhot.size() != 4))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "First argument must be a bool/int array, size 4");
+ return 0;
+ }
+
+ if(!FillFloatVectorFromPySequence(pyluma, luma) ||
+ (luma.size() != 3))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Second argument must be a float array, size 3");
+ return 0;
+ }
+
+ std::vector<float> matrix(16);
+ std::vector<float> offset(4);
+
+ MatrixTransform::View(&matrix[0], &offset[0],
+ &channelhot[0], &luma[0]);
+
+ PyObject* pymatrix = CreatePyListFromFloatVector(matrix);
+ PyObject* pyoffset = CreatePyListFromFloatVector(offset);
+
+ PyObject* pyreturnval = Py_BuildValue("(OO)", pymatrix, pyoffset);
+ Py_DECREF(pymatrix);
+ Py_DECREF(pyoffset);
+
+ return pyreturnval;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyProcessor.cpp b/src/pyglue/PyProcessor.cpp
new file mode 100644
index 0000000..e393041
--- /dev/null
+++ b/src/pyglue/PyProcessor.cpp
@@ -0,0 +1,500 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyProcessor.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddProcessorObjectToModule( PyObject* m )
+ {
+ PyOCIO_ProcessorType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ProcessorType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ProcessorType );
+ PyModule_AddObject(m, "Processor",
+ (PyObject *)&PyOCIO_ProcessorType);
+
+ return true;
+ }
+
+ PyObject * BuildConstPyProcessor(ConstProcessorRcPtr processor)
+ {
+ if (!processor)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Processor * pyProcessor = PyObject_New(
+ PyOCIO_Processor, (PyTypeObject * ) &PyOCIO_ProcessorType);
+
+ pyProcessor->constcppobj = new ConstProcessorRcPtr();
+ *pyProcessor->constcppobj = processor;
+
+ return ( PyObject * ) pyProcessor;
+ }
+
+ bool IsPyProcessor(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return (PyObject_Type(pyobject) == (PyObject *) (&PyOCIO_ProcessorType));
+ }
+
+ ConstProcessorRcPtr GetConstProcessor(PyObject * pyobject)
+ {
+ if(!IsPyProcessor(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Processor.");
+ }
+
+ PyOCIO_Processor * pyProcessor = reinterpret_cast<PyOCIO_Processor *> (pyobject);
+ if(pyProcessor->constcppobj)
+ {
+ return *pyProcessor->constcppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.Processor.");
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_Processor_init( PyOCIO_Processor * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_Processor_delete( PyOCIO_Processor * self, PyObject * args );
+
+ PyObject * PyOCIO_Processor_isNoOp( PyObject * self );
+ PyObject * PyOCIO_Processor_hasChannelCrosstalk( PyObject * self );
+ PyObject * PyOCIO_Processor_getMetadata( PyObject * self );
+ PyObject * PyOCIO_Processor_applyRGB( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Processor_applyRGBA( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Processor_getCpuCacheID( PyObject * self );
+
+ PyObject * PyOCIO_Processor_getGpuShaderText( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Processor_getGpuShaderTextCacheID( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Processor_getGpuLut3D( PyObject * self, PyObject * args );
+ PyObject * PyOCIO_Processor_getGpuLut3DCacheID( PyObject * self, PyObject * args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_Processor_methods[] = {
+ {"isNoOp",
+ (PyCFunction) PyOCIO_Processor_isNoOp, METH_NOARGS, PROCESSOR_ISNOOP__DOC__ },
+ {"hasChannelCrosstalk",
+ (PyCFunction) PyOCIO_Processor_hasChannelCrosstalk, METH_NOARGS, PROCESSOR_HASCHANNELCROSSTALK__DOC__ },
+ {"getMetadata",
+ (PyCFunction) PyOCIO_Processor_getMetadata, METH_NOARGS, PROCESSOR_GETMETADATA__DOC__ },
+ {"applyRGB",
+ PyOCIO_Processor_applyRGB, METH_VARARGS, PROCESSOR_APPLYRGB__DOC__ },
+ {"applyRGBA",
+ PyOCIO_Processor_applyRGBA, METH_VARARGS, PROCESSOR_APPLYRGBA__DOC__ },
+ {"getCpuCacheID",
+ (PyCFunction) PyOCIO_Processor_getCpuCacheID, METH_NOARGS, PROCESSOR_GETCPUCACHEID__DOC__ },
+ {"getGpuShaderText",
+ PyOCIO_Processor_getGpuShaderText, METH_VARARGS, PROCESSOR_GETGPUSHADERTEXT__DOC__ },
+ {"getGpuShaderTextCacheID",
+ PyOCIO_Processor_getGpuShaderTextCacheID, METH_VARARGS, PROCESSOR_GETGPUSHADERTEXTCACHEID__DOC__ },
+ {"getGpuLut3D",
+ PyOCIO_Processor_getGpuLut3D, METH_VARARGS, PROCESSOR_GETGPULUT3D__DOC__ },
+ {"getGpuLut3DCacheID",
+ PyOCIO_Processor_getGpuLut3DCacheID, METH_VARARGS, PROCESSOR_GETGPULUT3DCACHEID__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+
+ const char initMessage[] =
+ "Processor objects cannot be instantiated directly. "
+ "Please use config.getProcessor() instead.";
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ProcessorType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.Processor", //tp_name
+ sizeof(PyOCIO_Processor), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PyOCIO_Processor_delete, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ PROCESSOR__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_Processor_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_Processor_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ // TODO: The use of a dict, rather than a native class is not ideal
+ // in the next API revision, use a native type.
+
+ void FillShaderDescFromPyDict(GpuShaderDesc & shaderDesc,
+ PyObject * dict)
+ {
+ if(!PyDict_Check(dict))
+ {
+ throw Exception("GpuShaderDesc must be a dict type.");
+ }
+
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(dict, &pos, &key, &value))
+ {
+ std::string keystr;
+ if(!GetStringFromPyObject(key, &keystr))
+ throw Exception("GpuShaderDesc keys must be strings.");
+
+ if(keystr == "language")
+ {
+ GpuLanguage language = GPU_LANGUAGE_UNKNOWN;
+ if(ConvertPyObjectToGpuLanguage(value, &language) == 0)
+ throw Exception("GpuShaderDesc language must be a GpuLanguage.");
+ shaderDesc.setLanguage(language);
+ }
+ else if(keystr == "functionName")
+ {
+ std::string functionName;
+ if(!GetStringFromPyObject(value, &functionName))
+ throw Exception("GpuShaderDesc functionName must be a string.");
+ shaderDesc.setFunctionName(functionName.c_str());
+ }
+ else if(keystr == "lut3DEdgeLen")
+ {
+ int lut3DEdgeLen = 0;
+ if(!GetIntFromPyObject(value, &lut3DEdgeLen))
+ throw Exception("GpuShaderDesc lut3DEdgeLen must be an integer.");
+ shaderDesc.setLut3DEdgeLen(lut3DEdgeLen);
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "Unknown GpuShaderDesc key, '";
+ os << keystr << "'. ";
+ os << "Allowed keys: (";
+ os << "'language', 'functionName', 'lut3DEdgeLen').";
+ throw Exception(os.str().c_str());
+ }
+ }
+ }
+ }
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_Processor_init( PyOCIO_Processor */*self*/,
+ PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ PyErr_SetString( PyExc_RuntimeError, initMessage);
+ return -1;
+ }
+
+ void PyOCIO_Processor_delete( PyOCIO_Processor *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ PyObject * PyOCIO_Processor_isNoOp( PyObject * self )
+ {
+ try
+ {
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+ return PyBool_FromLong( processor->isNoOp() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_hasChannelCrosstalk( PyObject * self )
+ {
+ try
+ {
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+ return PyBool_FromLong( processor->hasChannelCrosstalk() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_getMetadata( PyObject * self )
+ {
+ try
+ {
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+ return BuildConstPyProcessorMetadata( processor->getMetadata() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_applyRGB( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:applyRGB", &pyData)) return NULL;
+
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+ if(processor->isNoOp())
+ {
+ Py_INCREF(pyData);
+ return pyData;
+ }
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || ((data.size()%3) != 0))
+ {
+ std::ostringstream os;
+ os << "First argument must be a float array, size multiple of 3. ";
+ os << "Size: " << data.size() << ".";
+ PyErr_SetString(PyExc_TypeError, os.str().c_str());
+ return 0;
+ }
+
+ PackedImageDesc img(&data[0], data.size()/3, 1, 3);
+ processor->apply(img);
+
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_applyRGBA( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O:applyRGBA", &pyData)) return NULL;
+
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+ if(processor->isNoOp())
+ {
+ Py_INCREF(pyData);
+ return pyData;
+ }
+
+ std::vector<float> data;
+ if(!FillFloatVectorFromPySequence(pyData, data) || ((data.size()%4) != 0))
+ {
+ std::ostringstream os;
+ os << "First argument must be a float array, size multiple of 4. ";
+ os << "Size: " << data.size() << ".";
+ PyErr_SetString(PyExc_TypeError, os.str().c_str());
+ return 0;
+ }
+
+ PackedImageDesc img(&data[0], data.size()/4, 1, 4);
+ processor->apply(img);
+
+ return CreatePyListFromFloatVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_getCpuCacheID( PyObject * self )
+ {
+ try
+ {
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+ return PyString_FromString( processor->getCpuCacheID() );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_getGpuShaderText( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O!:getGpuShaderText",
+ &PyDict_Type, &pyData)) return NULL;
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+
+ GpuShaderDesc shaderDesc;
+ FillShaderDescFromPyDict(shaderDesc, pyData);
+
+ return PyString_FromString( processor->getGpuShaderText(shaderDesc) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_getGpuShaderTextCacheID( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O!:getGpuShaderTextCacheID",
+ &PyDict_Type, &pyData)) return NULL;
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+
+ GpuShaderDesc shaderDesc;
+ FillShaderDescFromPyDict(shaderDesc, pyData);
+
+ return PyString_FromString( processor->getGpuShaderTextCacheID(shaderDesc) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_getGpuLut3D( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O!:getGpuLut3D",
+ &PyDict_Type, &pyData)) return NULL;
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+
+ GpuShaderDesc shaderDesc;
+ FillShaderDescFromPyDict(shaderDesc, pyData);
+
+ int len = shaderDesc.getLut3DEdgeLen();
+ std::vector<float> lut3d(3*len*len*len);
+
+ // TODO: return more compact binary data? (ex array, ...)
+ processor->getGpuLut3D(&lut3d[0], shaderDesc);
+ return CreatePyListFromFloatVector(lut3d);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Processor_getGpuLut3DCacheID( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ PyObject * pyData = 0;
+ if (!PyArg_ParseTuple(args,"O!:getGpuLut3DCacheID",
+ &PyDict_Type, &pyData)) return NULL;
+ ConstProcessorRcPtr processor = GetConstProcessor(self);
+
+ GpuShaderDesc shaderDesc;
+ FillShaderDescFromPyDict(shaderDesc, pyData);
+
+ return PyString_FromString( processor->getGpuLut3DCacheID(shaderDesc) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyProcessor.h b/src/pyglue/PyProcessor.h
new file mode 100644
index 0000000..571847d
--- /dev/null
+++ b/src/pyglue/PyProcessor.h
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYPROCESSOR_H
+#define INCLUDED_PYOCIO_PYPROCESSOR_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Maybe put this in a pyinternal namespace?
+
+ typedef struct {
+ PyObject_HEAD
+ ConstProcessorRcPtr * constcppobj;
+ } PyOCIO_Processor;
+
+ extern PyTypeObject PyOCIO_ProcessorType;
+
+ bool AddProcessorObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyProcessorMetadata.cpp b/src/pyglue/PyProcessorMetadata.cpp
new file mode 100644
index 0000000..f8a4a92
--- /dev/null
+++ b/src/pyglue/PyProcessorMetadata.cpp
@@ -0,0 +1,245 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyProcessorMetadata.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddProcessorMetadataObjectToModule( PyObject* m )
+ {
+ PyOCIO_ProcessorMetadataType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_ProcessorMetadataType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_ProcessorMetadataType );
+ PyModule_AddObject(m, "ProcessorMetadata",
+ (PyObject *)&PyOCIO_ProcessorMetadataType);
+
+ return true;
+ }
+
+ PyObject * BuildConstPyProcessorMetadata(ConstProcessorMetadataRcPtr metadata)
+ {
+ if (!metadata)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_ProcessorMetadata * pyMetadata = PyObject_New(
+ PyOCIO_ProcessorMetadata, (PyTypeObject * ) &PyOCIO_ProcessorMetadataType);
+
+ pyMetadata->constcppobj = new ConstProcessorMetadataRcPtr();
+ *pyMetadata->constcppobj = metadata;
+
+ return ( PyObject * ) pyMetadata;
+ }
+
+ bool IsPyProcessorMetadata(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return (PyObject_Type(pyobject) == (PyObject *) (&PyOCIO_ProcessorMetadataType));
+ }
+
+ ConstProcessorMetadataRcPtr GetConstProcessorMetadata(PyObject * pyobject)
+ {
+ if(!IsPyProcessorMetadata(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.ProcessorMetadata.");
+ }
+
+ PyOCIO_ProcessorMetadata * pyMetadata = reinterpret_cast<PyOCIO_ProcessorMetadata *> (pyobject);
+ if(pyMetadata->constcppobj)
+ {
+ return *pyMetadata->constcppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.ProcessorMetadata.");
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ int PyOCIO_ProcessorMetadata_init( PyOCIO_ProcessorMetadata * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_ProcessorMetadata_delete( PyOCIO_ProcessorMetadata * self, PyObject * args );
+
+ PyObject * PyOCIO_ProcessorMetadata_getFiles( PyObject * self );
+ PyObject * PyOCIO_ProcessorMetadata_getLooks( PyObject * self );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_ProcessorMetadata_methods[] = {
+ {"getFiles",
+ (PyCFunction) PyOCIO_ProcessorMetadata_getFiles, METH_NOARGS,
+ PROCESSORMETADATA_GETFILES__DOC__ },
+ {"getLooks",
+ (PyCFunction) PyOCIO_ProcessorMetadata_getLooks, METH_NOARGS,
+ PROCESSORMETADATA_GETLOOKS__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+
+ const char initMessage[] =
+ "ProcessorMetadata objects cannot be instantiated directly. "
+ "Please use processor.getMetadata() instead.";
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_ProcessorMetadataType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.ProcessorMetadata", //tp_name
+ sizeof(PyOCIO_ProcessorMetadata), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)PyOCIO_ProcessorMetadata_delete,//tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ PROCESSORMETADATA__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_ProcessorMetadata_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_ProcessorMetadata_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_ProcessorMetadata_init( PyOCIO_ProcessorMetadata */*self*/,
+ PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ PyErr_SetString( PyExc_RuntimeError, initMessage);
+ return -1;
+ }
+
+ void PyOCIO_ProcessorMetadata_delete( PyOCIO_ProcessorMetadata *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ PyObject * PyOCIO_ProcessorMetadata_getFiles( PyObject * self )
+ {
+ try
+ {
+ ConstProcessorMetadataRcPtr metadata = GetConstProcessorMetadata(self);
+
+ std::vector<std::string> data;
+ for(int i=0; i<metadata->getNumFiles(); ++i)
+ {
+ data.push_back(metadata->getFile(i));
+ }
+
+ return CreatePyListFromStringVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_ProcessorMetadata_getLooks( PyObject * self )
+ {
+ try
+ {
+ ConstProcessorMetadataRcPtr metadata = GetConstProcessorMetadata(self);
+
+ std::vector<std::string> data;
+ for(int i=0; i<metadata->getNumLooks(); ++i)
+ {
+ data.push_back(metadata->getLook(i));
+ }
+
+ return CreatePyListFromStringVector(data);
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ } // anon namespace
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyProcessorMetadata.h b/src/pyglue/PyProcessorMetadata.h
new file mode 100644
index 0000000..4aada84
--- /dev/null
+++ b/src/pyglue/PyProcessorMetadata.h
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYPROCESSORMETADATA_H
+#define INCLUDED_PYOCIO_PYPROCESSORMETADATA_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Maybe put this in a pyinternal namespace?
+
+ typedef struct {
+ PyObject_HEAD
+ ConstProcessorMetadataRcPtr * constcppobj;
+ } PyOCIO_ProcessorMetadata;
+
+ extern PyTypeObject PyOCIO_ProcessorMetadataType;
+
+ bool AddProcessorMetadataObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyTransform.cpp b/src/pyglue/PyTransform.cpp
new file mode 100644
index 0000000..848e966
--- /dev/null
+++ b/src/pyglue/PyTransform.cpp
@@ -0,0 +1,411 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyTransform.h"
+#include "PyUtil.h"
+#include "PyDoc.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+ namespace
+ {
+ PyOCIO_Transform * PyTransform_New(ConstTransformRcPtr transform)
+ {
+ if (!transform)
+ {
+ return 0x0;
+ }
+
+ PyOCIO_Transform * pyobj = 0x0;
+
+ if(ConstAllocationTransformRcPtr allocationTransform = \
+ DynamicPtrCast<const AllocationTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_AllocationTransformType);
+ }
+ else if(ConstCDLTransformRcPtr cdlTransform = \
+ DynamicPtrCast<const CDLTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_CDLTransformType);
+ }
+ else if(ConstColorSpaceTransformRcPtr colorSpaceTransform = \
+ DynamicPtrCast<const ColorSpaceTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_ColorSpaceTransformType);
+ }
+ else if(ConstDisplayTransformRcPtr displayTransform = \
+ DynamicPtrCast<const DisplayTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_DisplayTransformType);
+ }
+ else if(ConstExponentTransformRcPtr exponentTransform = \
+ DynamicPtrCast<const ExponentTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_ExponentTransformType);
+ }
+ else if(ConstFileTransformRcPtr fileTransform = \
+ DynamicPtrCast<const FileTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_FileTransformType);
+ }
+ else if(ConstGroupTransformRcPtr groupTransform = \
+ DynamicPtrCast<const GroupTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_GroupTransformType);
+ }
+ else if(ConstLogTransformRcPtr logTransform = \
+ DynamicPtrCast<const LogTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_LogTransformType);
+ }
+ else if(ConstLookTransformRcPtr lookTransform = \
+ DynamicPtrCast<const LookTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_LookTransformType);
+ }
+ else if(ConstMatrixTransformRcPtr matrixTransform = \
+ DynamicPtrCast<const MatrixTransform>(transform))
+ {
+ pyobj = PyObject_New(PyOCIO_Transform,
+ (PyTypeObject * ) &PyOCIO_MatrixTransformType);
+ }
+
+ return pyobj;
+ }
+ }
+
+ PyObject * BuildConstPyTransform(ConstTransformRcPtr transform)
+ {
+ if (!transform)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Transform * pyobj = PyTransform_New(transform);
+
+ if(!pyobj)
+ {
+ std::ostringstream os;
+ os << "Unknown transform type for BuildConstPyTransform.";
+ throw Exception(os.str().c_str());
+ }
+
+ pyobj->constcppobj = new ConstTransformRcPtr();
+ pyobj->cppobj = new TransformRcPtr();
+
+ *pyobj->constcppobj = transform;
+ pyobj->isconst = true;
+
+ return (PyObject *) pyobj;
+ }
+
+ PyObject * BuildEditablePyTransform(TransformRcPtr transform)
+ {
+ if (!transform)
+ {
+ Py_RETURN_NONE;
+ }
+
+ PyOCIO_Transform * pyobj = PyTransform_New(transform);
+
+ pyobj->constcppobj = new ConstTransformRcPtr();
+ pyobj->cppobj = new TransformRcPtr();
+
+ *pyobj->cppobj = transform;
+ pyobj->isconst = false;
+
+ return (PyObject *) pyobj;
+ }
+
+ bool IsPyTransform(PyObject * pyobject)
+ {
+ if(!pyobject) return false;
+ return PyObject_TypeCheck(pyobject, &PyOCIO_TransformType);
+ }
+
+ bool IsPyTransformEditable(PyObject * pyobject)
+ {
+ if(!IsPyTransform(pyobject)) return false;
+
+ PyOCIO_Transform * pyobj = reinterpret_cast<PyOCIO_Transform *> (pyobject);
+ return (!pyobj->isconst);
+ }
+
+ TransformRcPtr GetEditableTransform(PyObject * pyobject)
+ {
+ if(!IsPyTransform(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Transform.");
+ }
+
+ PyOCIO_Transform * pytransform = reinterpret_cast<PyOCIO_Transform *> (pyobject);
+ if(!pytransform->isconst && pytransform->cppobj)
+ {
+ return *pytransform->cppobj;
+ }
+
+ throw Exception("PyObject must be an editable OCIO.Transform.");
+ }
+
+ ConstTransformRcPtr GetConstTransform(PyObject * pyobject, bool allowCast)
+ {
+ if(!IsPyTransform(pyobject))
+ {
+ throw Exception("PyObject must be an OCIO.Transform.");
+ }
+
+ PyOCIO_Transform * pytransform = reinterpret_cast<PyOCIO_Transform *> (pyobject);
+ if(pytransform->isconst && pytransform->constcppobj)
+ {
+ return *pytransform->constcppobj;
+ }
+
+ if(allowCast && !pytransform->isconst && pytransform->cppobj)
+ {
+ return *pytransform->cppobj;
+ }
+
+ throw Exception("PyObject must be a valid OCIO.Transform.");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ bool AddTransformObjectToModule( PyObject* m )
+ {
+ PyOCIO_TransformType.tp_new = PyType_GenericNew;
+ if ( PyType_Ready(&PyOCIO_TransformType) < 0 ) return false;
+
+ Py_INCREF( &PyOCIO_TransformType );
+ PyModule_AddObject(m, "Transform",
+ (PyObject *)&PyOCIO_TransformType);
+
+ return true;
+ }
+
+ namespace
+ {
+ int PyOCIO_Transform_init( PyOCIO_Transform * self, PyObject * args, PyObject * kwds );
+ void PyOCIO_Transform_delete( PyOCIO_Transform * self, PyObject * args );
+
+ PyObject * PyOCIO_Transform_isEditable( PyObject * self );
+ PyObject * PyOCIO_Transform_createEditableCopy( PyObject * self );
+ PyObject * PyOCIO_Transform_getDirection( PyObject * self );
+ PyObject * PyOCIO_Transform_setDirection( PyObject * self, PyObject *args );
+
+ ///////////////////////////////////////////////////////////////////////
+ ///
+
+ PyMethodDef PyOCIO_Transform_methods[] = {
+ {"isEditable",
+ (PyCFunction) PyOCIO_Transform_isEditable, METH_NOARGS, TRANSFORM_ISEDITABLE__DOC__ },
+ {"createEditableCopy",
+ (PyCFunction) PyOCIO_Transform_createEditableCopy, METH_NOARGS, TRANSFORM_CREATEEDITABLECOPY__DOC__ },
+ {"getDirection",
+ (PyCFunction) PyOCIO_Transform_getDirection, METH_NOARGS, TRANSFORM_GETDIRECTION__DOC__ },
+ {"setDirection",
+ PyOCIO_Transform_setDirection, METH_VARARGS, TRANSFORM_SETDIRECTION__DOC__ },
+ {NULL, NULL, 0, NULL}
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyTypeObject PyOCIO_TransformType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, //ob_size
+ "OCIO.Transform", //tp_name
+ sizeof(PyOCIO_Transform), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor) PyOCIO_Transform_delete, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ 0, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
+ TRANSFORM__DOC__, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ PyOCIO_Transform_methods, //tp_methods
+ 0, //tp_members
+ 0, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ (initproc) PyOCIO_Transform_init, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0, //tp_del
+ #if PY_VERSION_HEX > 0x02060000
+ 0, //tp_version_tag
+ #endif
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///
+
+ namespace
+ {
+ ///////////////////////////////////////////////////////////////////////
+ ///
+ int PyOCIO_Transform_init( PyOCIO_Transform *self, PyObject * /*args*/, PyObject * /*kwds*/ )
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// init pyobject fields
+
+ self->constcppobj = new ConstTransformRcPtr();
+ self->cppobj = new TransformRcPtr();
+ self->isconst = true;
+
+ std::string message = "Base Transforms class can not be instantiated.";
+ PyErr_SetString( PyExc_RuntimeError, message.c_str() );
+ return -1;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ void PyOCIO_Transform_delete( PyOCIO_Transform *self, PyObject * /*args*/ )
+ {
+ delete self->constcppobj;
+ delete self->cppobj;
+
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Transform_isEditable( PyObject * self )
+ {
+ return PyBool_FromLong(IsPyTransformEditable(self));
+ }
+
+ PyObject * PyOCIO_Transform_createEditableCopy( PyObject * self )
+ {
+ try
+ {
+ ConstTransformRcPtr transform = GetConstTransform(self, true);
+ TransformRcPtr copy = transform->createEditableCopy();
+
+ PyOCIO_Transform * pycopy = PyTransform_New(copy);
+ pycopy->constcppobj = new ConstTransformRcPtr();
+ pycopy->cppobj = new TransformRcPtr();
+ *pycopy->cppobj = copy;
+ pycopy->isconst = false;
+
+ return (PyObject *) pycopy;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ ///
+
+ PyObject * PyOCIO_Transform_getDirection( PyObject * self )
+ {
+ try
+ {
+ ConstTransformRcPtr transform = GetConstTransform(self, true);
+ TransformDirection dir = transform->getDirection();
+ return PyString_FromString( TransformDirectionToString( dir ) );
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+
+ PyObject * PyOCIO_Transform_setDirection( PyObject * self, PyObject * args )
+ {
+ try
+ {
+ TransformDirection dir;
+ if (!PyArg_ParseTuple(args,"O&:setDirection",
+ ConvertPyObjectToTransformDirection, &dir)) return NULL;
+
+ TransformRcPtr transform = GetEditableTransform(self);
+ transform->setDirection( dir );
+
+ Py_RETURN_NONE;
+ }
+ catch(...)
+ {
+ Python_Handle_Exception();
+ return NULL;
+ }
+ }
+ }
+
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyTransform.h b/src/pyglue/PyTransform.h
new file mode 100644
index 0000000..0ff3e6b
--- /dev/null
+++ b/src/pyglue/PyTransform.h
@@ -0,0 +1,81 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYTRANSFORM_H
+#define INCLUDED_PYOCIO_PYTRANSFORM_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+OCIO_NAMESPACE_ENTER
+{
+ // TODO: Maybe put this in a pyinternal namespace?
+
+ typedef struct {
+ PyObject_HEAD
+ ConstTransformRcPtr * constcppobj;
+ TransformRcPtr * cppobj;
+ bool isconst;
+ } PyOCIO_Transform;
+
+ extern PyTypeObject PyOCIO_TransformType;
+ bool AddTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_AllocationTransformType;
+ bool AddAllocationTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_CDLTransformType;
+ bool AddCDLTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_ColorSpaceTransformType;
+ bool AddColorSpaceTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_DisplayTransformType;
+ bool AddDisplayTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_ExponentTransformType;
+ bool AddExponentTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_FileTransformType;
+ bool AddFileTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_GroupTransformType;
+ bool AddGroupTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_LogTransformType;
+ bool AddLogTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_LookTransformType;
+ bool AddLookTransformObjectToModule( PyObject* m );
+
+ extern PyTypeObject PyOCIO_MatrixTransformType;
+ bool AddMatrixTransformObjectToModule( PyObject* m );
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/PyUtil.cpp b/src/pyglue/PyUtil.cpp
new file mode 100644
index 0000000..3058c9d
--- /dev/null
+++ b/src/pyglue/PyUtil.cpp
@@ -0,0 +1,742 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <Python.h>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "PyUtil.h"
+
+#include <sstream>
+
+OCIO_NAMESPACE_ENTER
+{
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ // http://docs.python.org/c-api/object.html#PyObject_IsTrue
+ int ConvertPyObjectToBool(PyObject *object, void *valuePtr)
+ {
+ bool *boolPtr = static_cast<bool*>(valuePtr);
+ int status = PyObject_IsTrue(object);
+
+ if (status == -1 || PyErr_Occurred())
+ {
+ if (!PyErr_Occurred())
+ {
+ PyErr_SetString(PyExc_ValueError, "could not convert object to bool.");
+ }
+
+ return 0;
+ }
+
+ *boolPtr = (status == 1) ? true : false;
+
+ return 1;
+ }
+
+ int ConvertPyObjectToAllocation(PyObject *object, void *valuePtr)
+ {
+ Allocation* allocPtr = static_cast<Allocation*>(valuePtr);
+
+ if(!PyString_Check(object))
+ {
+ PyErr_SetString(PyExc_ValueError, "Object is not a string.");
+ return 0;
+ }
+
+ *allocPtr = AllocationFromString(PyString_AsString( object ));
+
+ return 1;
+ }
+
+
+
+ int ConvertPyObjectToInterpolation(PyObject *object, void *valuePtr)
+ {
+ Interpolation* interpPtr = static_cast<Interpolation*>(valuePtr);
+
+ if(!PyString_Check(object))
+ {
+ PyErr_SetString(PyExc_ValueError, "Object is not a string.");
+ return 0;
+ }
+
+ *interpPtr = InterpolationFromString(PyString_AsString( object ));
+
+ return 1;
+ }
+
+ int ConvertPyObjectToTransformDirection(PyObject *object, void *valuePtr)
+ {
+ TransformDirection* dirPtr = static_cast<TransformDirection*>(valuePtr);
+
+ if(!PyString_Check(object))
+ {
+ PyErr_SetString(PyExc_ValueError, "Object is not a string.");
+ return 0;
+ }
+
+ *dirPtr = TransformDirectionFromString(PyString_AsString( object ));
+
+ return 1;
+ }
+
+
+ int ConvertPyObjectToColorSpaceDirection(PyObject *object, void *valuePtr)
+ {
+ ColorSpaceDirection* dirPtr = static_cast<ColorSpaceDirection*>(valuePtr);
+
+ if(!PyString_Check(object))
+ {
+ PyErr_SetString(PyExc_ValueError, "Object is not a string.");
+ return 0;
+ }
+
+ *dirPtr = ColorSpaceDirectionFromString(PyString_AsString( object ));
+
+ return 1;
+ }
+
+
+ int ConvertPyObjectToGpuLanguage(PyObject *object, void *valuePtr)
+ {
+ GpuLanguage* gpuLanguagePtr = static_cast<GpuLanguage*>(valuePtr);
+
+ if(!PyString_Check(object))
+ {
+ PyErr_SetString(PyExc_ValueError, "Object is not a string.");
+ return 0;
+ }
+
+ *gpuLanguagePtr = GpuLanguageFromString(PyString_AsString( object ));
+
+ return 1;
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool GetIntFromPyObject(PyObject* object, int* val)
+ {
+ if(!val || !object) return false;
+
+ if( PyInt_Check( object ) )
+ {
+ *val = static_cast<int>( PyInt_AS_LONG( object ) );
+ return true;
+ }
+
+ if( PyFloat_Check( object ) )
+ {
+ *val = static_cast<int>( PyFloat_AS_DOUBLE( object ) );
+ return true;
+ }
+
+ PyObject* intObject = PyNumber_Int(object);
+ if(intObject)
+ {
+ *val = static_cast<int>( PyInt_AS_LONG( intObject ) );
+ Py_DECREF(intObject);
+ return true;
+ }
+
+ PyErr_Clear();
+ return false;
+ }
+
+ bool GetFloatFromPyObject(PyObject* object, float* val)
+ {
+ if(!val || !object) return false;
+
+ if( PyFloat_Check( object ) )
+ {
+ *val = static_cast<float>( PyFloat_AS_DOUBLE( object ) );
+ return true;
+ }
+
+ if( PyInt_Check( object ) )
+ {
+ *val = static_cast<float>( PyInt_AS_LONG( object ) );
+ return true;
+ }
+
+ PyObject* floatObject = PyNumber_Float(object);
+ if(floatObject)
+ {
+ *val = static_cast<float>( PyFloat_AS_DOUBLE( floatObject ) );
+ Py_DECREF(floatObject);
+ return true;
+ }
+
+ PyErr_Clear();
+ return false;
+ }
+
+ bool GetDoubleFromPyObject(PyObject* object, double* val)
+ {
+ if(!val || !object) return false;
+
+ if( PyFloat_Check( object ) )
+ {
+ *val = PyFloat_AS_DOUBLE( object );
+ return true;
+ }
+
+ if( PyInt_Check( object ) )
+ {
+ *val = static_cast<double>( PyInt_AS_LONG( object ) );
+ return true;
+ }
+
+ PyObject* floatObject = PyNumber_Float(object);
+ if(floatObject)
+ {
+ *val = PyFloat_AS_DOUBLE( floatObject );
+ Py_DECREF(floatObject);
+ return true;
+ }
+
+ PyErr_Clear();
+ return false;
+ }
+
+ bool GetStringFromPyObject(PyObject* object, std::string* val)
+ {
+ if(!val || !object) return false;
+
+ if( PyString_Check( object ) )
+ {
+ *val = std::string(PyString_AS_STRING(object));
+ return true;
+ }
+
+ PyObject* strObject = PyObject_Str(object);
+ if(strObject)
+ {
+ *val = std::string(PyString_AS_STRING(strObject));
+ Py_DECREF(strObject);
+ return true;
+ }
+
+ PyErr_Clear();
+ return false;
+ }
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ PyObject* CreatePyListFromIntVector(const std::vector<int> &data)
+ {
+ PyObject* returnlist = PyList_New( data.size() );
+ if(!returnlist) return 0;
+
+ for(unsigned int i =0; i<data.size(); ++i)
+ {
+ PyList_SET_ITEM(returnlist, i, PyInt_FromLong(data[i]));
+ }
+
+ return returnlist;
+ }
+
+ PyObject* CreatePyListFromFloatVector(const std::vector<float> &data)
+ {
+ PyObject* returnlist = PyList_New( data.size() );
+ if(!returnlist) return 0;
+
+ for(unsigned int i =0; i<data.size(); ++i)
+ {
+ PyList_SET_ITEM(returnlist, i, PyFloat_FromDouble(data[i]));
+ }
+
+ return returnlist;
+ }
+
+ PyObject* CreatePyListFromDoubleVector(const std::vector<double> &data)
+ {
+ PyObject* returnlist = PyList_New( data.size() );
+ if(!returnlist) return 0;
+
+ for(unsigned int i =0; i<data.size(); ++i)
+ {
+ PyList_SET_ITEM(returnlist, i, PyFloat_FromDouble(data[i]));
+ }
+
+ return returnlist;
+ }
+
+ PyObject* CreatePyListFromStringVector(const std::vector<std::string> &data)
+ {
+ PyObject* returnlist = PyList_New( data.size() );
+ if(!returnlist) return 0;
+
+ for(unsigned int i =0; i<data.size(); ++i)
+ {
+ PyObject *str = PyString_FromString(data[i].c_str());
+ if (str == NULL)
+ {
+ Py_DECREF(returnlist);
+ return NULL;
+ }
+ PyList_SET_ITEM(returnlist, i, str);
+ }
+
+ return returnlist;
+ }
+
+ PyObject* CreatePyListFromTransformVector(const std::vector<ConstTransformRcPtr> &data)
+ {
+ PyObject* returnlist = PyList_New( data.size() );
+ if(!returnlist) return 0;
+
+ for(unsigned int i =0; i<data.size(); ++i)
+ {
+ PyList_SET_ITEM(returnlist, i, BuildConstPyTransform(data[i]));
+ }
+
+ return returnlist;
+ }
+
+
+ namespace
+ {
+ // These are safer than PySequence_Fast, as we can
+ // Confirm that no exceptions will be set in the python runtime.
+
+ inline bool PyListOrTuple_Check(PyObject* pyobj)
+ {
+ return (PyTuple_Check(pyobj) || PyList_Check(pyobj));
+ }
+
+ inline int PyListOrTuple_GET_SIZE(PyObject* pyobj)
+ {
+ if(PyList_Check(pyobj))
+ {
+ return static_cast<int>(PyList_GET_SIZE(pyobj));
+ }
+ else if(PyTuple_Check(pyobj))
+ {
+ return static_cast<int>(PyTuple_GET_SIZE(pyobj));
+ }
+ return -1;
+ }
+
+ // Return a boworrowed reference
+ inline PyObject* PyListOrTuple_GET_ITEM(PyObject* pyobj, int index)
+ {
+ if(PyList_Check(pyobj))
+ {
+ return PyList_GET_ITEM(pyobj, index);
+ }
+ else if(PyTuple_Check(pyobj))
+ {
+ return PyTuple_GET_ITEM(pyobj, index);
+ }
+ return 0;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /*
+ A note on why PyErr_Clear is needed in multiple locations...
+
+ Even though it's not immediately apparent, almost every function
+ in the Abstract Objects Layer,
+ http://www.python.org/doc/2.5/api/abstract.html
+ can set a global excpetion under certain circumstances.
+
+ For example, calling the equivalent of int( obj ) will set
+ an exception if the object cannot be casted (such as None),
+ or if it's a custom type that implements the number protocol
+ but throws an exception during the cast.
+
+ During iteration, even an object that implements the sequence
+ protocol can raise an exception if the iteration fails.
+
+ As we want to guarantee that an exception *never* remains on
+ the stack after an internal failure, the simplest way to
+ guarantee this is to always call PyErr_Clear() before
+ returing the failure condition.
+ */
+
+ bool FillIntVectorFromPySequence(PyObject* datalist, std::vector<int> &data)
+ {
+ data.clear();
+
+ // First, try list or tuple iteration (for speed).
+ if(PyListOrTuple_Check(datalist))
+ {
+ int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
+ data.reserve(sequenceSize);
+
+ for(int i=0; i < sequenceSize; i++)
+ {
+ PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
+
+ int val;
+ if (!GetIntFromPyObject(item, &val))
+ {
+ data.clear();
+ return false;
+ }
+ data.push_back(val);
+ }
+
+ return true;
+ }
+ // As a fallback, try general iteration.
+ else
+ {
+ PyObject *item;
+ PyObject *iter = PyObject_GetIter(datalist);
+ if (iter == NULL)
+ {
+ PyErr_Clear();
+ return false;
+ }
+ while((item = PyIter_Next(iter)) != NULL)
+ {
+ int val;
+ if (!GetIntFromPyObject(item, &val))
+ {
+ Py_DECREF(item);
+ Py_DECREF(iter);
+
+ data.clear();
+ return false;
+ }
+ data.push_back(val);
+ Py_DECREF(item);
+ }
+
+ Py_DECREF(iter);
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ data.clear();
+ return false;
+ }
+ return true;
+ }
+ }
+
+ bool FillFloatVectorFromPySequence(PyObject* datalist, std::vector<float> &data)
+ {
+ data.clear();
+
+ if(PyListOrTuple_Check(datalist))
+ {
+ int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
+ data.reserve(sequenceSize);
+
+ for(int i=0; i < sequenceSize; i++)
+ {
+ PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
+
+ float val;
+ if (!GetFloatFromPyObject(item, &val))
+ {
+ data.clear();
+ return false;
+ }
+ data.push_back(val);
+ }
+ return true;
+ }
+ else
+ {
+ PyObject *item;
+ PyObject *iter = PyObject_GetIter(datalist);
+ if (iter == NULL)
+ {
+ PyErr_Clear();
+ return false;
+ }
+ while((item = PyIter_Next(iter)) != NULL)
+ {
+ float val;
+ if (!GetFloatFromPyObject(item, &val))
+ {
+ Py_DECREF(item);
+ Py_DECREF(iter);
+
+ data.clear();
+ return false;
+ }
+ data.push_back(val);
+ Py_DECREF(item);
+ }
+ Py_DECREF(iter);
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ data.clear();
+ return false;
+ }
+ return true;
+ }
+ }
+
+ bool FillDoubleVectorFromPySequence(PyObject* datalist, std::vector<double> &data)
+ {
+ data.clear();
+
+ if(PyListOrTuple_Check(datalist))
+ {
+ int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
+ data.reserve(sequenceSize);
+
+ for(int i=0; i < sequenceSize; i++)
+ {
+ PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
+ double val;
+ if (!GetDoubleFromPyObject(item, &val))
+ {
+ data.clear();
+ return false;
+ }
+ data.push_back( val );
+ }
+ return true;
+ }
+ else
+ {
+ PyObject *item;
+ PyObject *iter = PyObject_GetIter(datalist);
+ if (iter == NULL)
+ {
+ PyErr_Clear();
+ return false;
+ }
+ while((item = PyIter_Next(iter)) != NULL)
+ {
+ double val;
+ if (!GetDoubleFromPyObject(item, &val))
+ {
+ Py_DECREF(item);
+ Py_DECREF(iter);
+
+ data.clear();
+ return false;
+ }
+ data.push_back(val);
+ Py_DECREF(item);
+ }
+
+ Py_DECREF(iter);
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ data.clear();
+ return false;
+ }
+ return true;
+ }
+ }
+
+
+ bool FillStringVectorFromPySequence(PyObject* datalist, std::vector<std::string> &data)
+ {
+ data.clear();
+
+ if(PyListOrTuple_Check(datalist))
+ {
+ int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
+ data.reserve(sequenceSize);
+
+ for(int i=0; i < sequenceSize; i++)
+ {
+ PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
+ std::string val;
+ if (!GetStringFromPyObject(item, &val))
+ {
+ data.clear();
+ return false;
+ }
+ data.push_back( val );
+ }
+ return true;
+ }
+ else
+ {
+ PyObject *item;
+ PyObject *iter = PyObject_GetIter(datalist);
+ if (iter == NULL)
+ {
+ PyErr_Clear();
+ return false;
+ }
+ while((item = PyIter_Next(iter)) != NULL)
+ {
+ std::string val;
+ if (!GetStringFromPyObject(item, &val))
+ {
+ Py_DECREF(item);
+ Py_DECREF(iter);
+
+ data.clear();
+ return false;
+ }
+ data.push_back(val);
+ Py_DECREF(item);
+ }
+
+ Py_DECREF(iter);
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ data.clear();
+ return false;
+ }
+ return true;
+ }
+ }
+
+
+
+ bool FillTransformVectorFromPySequence(PyObject* datalist, std::vector<ConstTransformRcPtr> &data)
+ {
+ data.clear();
+
+ if(PyListOrTuple_Check(datalist))
+ {
+ int sequenceSize = PyListOrTuple_GET_SIZE(datalist);
+ data.reserve(sequenceSize);
+
+ for(int i=0; i < sequenceSize; i++)
+ {
+ PyObject* item = PyListOrTuple_GET_ITEM(datalist, i);
+ ConstTransformRcPtr val;
+ try
+ {
+ val = GetConstTransform(item, true);
+ }
+ catch(...)
+ {
+ data.clear();
+ return false;
+ }
+
+ data.push_back( val );
+ }
+ return true;
+ }
+ else
+ {
+ PyObject *item;
+ PyObject *iter = PyObject_GetIter(datalist);
+ if (iter == NULL)
+ {
+ PyErr_Clear();
+ return false;
+ }
+ while((item = PyIter_Next(iter)) != NULL)
+ {
+ ConstTransformRcPtr val;
+ try
+ {
+ val = GetConstTransform(item, true);
+ }
+ catch(...)
+ {
+ Py_DECREF(item);
+ Py_DECREF(iter);
+
+ data.clear();
+ return false;
+ }
+
+ data.push_back(val);
+ Py_DECREF(item);
+ }
+
+ Py_DECREF(iter);
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ data.clear();
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /* See the header for the justification for this function.
+
+ The trick to making this technique work is that we know
+ we've been called from within a catch block, so there
+ is an exception on the stack. We can re-throw this
+ exception, using the throw statement. By doing this
+ inside a try...catch block, it's possible to use the
+ standard catch mechanism to categorize whatever exception
+ was actually caught by the caller.
+ */
+
+ void Python_Handle_Exception()
+ {
+ try
+ {
+ // Re-throw whatever exception is already on the stack.
+ // This will fail horribly if no exception is already
+ // on the stack, so this function must only be called
+ // from inside an exception handler catch block!
+ throw;
+ }
+ catch (ExceptionMissingFile & e)
+ {
+ PyErr_SetString(GetExceptionMissingFilePyType(), e.what());
+ }
+ catch (Exception & e)
+ {
+ PyErr_SetString(GetExceptionPyType(), e.what());
+ }
+ catch (std::exception& e)
+ {
+ PyErr_SetString(PyExc_RuntimeError, e.what());
+ }
+ catch (...)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception caught.");
+ }
+ }
+}
+OCIO_NAMESPACE_EXIT
diff --git a/src/pyglue/PyUtil.h b/src/pyglue/PyUtil.h
new file mode 100644
index 0000000..589a7b8
--- /dev/null
+++ b/src/pyglue/PyUtil.h
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef INCLUDED_PYOCIO_PYUTIL_H
+#define INCLUDED_PYOCIO_PYUTIL_H
+
+#include <PyOpenColorIO/PyOpenColorIO.h>
+
+#include <vector>
+
+OCIO_NAMESPACE_ENTER
+{
+
+ int ConvertPyObjectToBool(PyObject *object, void *valuePtr);
+
+ int ConvertPyObjectToAllocation(PyObject *object, void *valuePtr);
+
+ int ConvertPyObjectToInterpolation(PyObject *object, void *valuePtr);
+
+ int ConvertPyObjectToTransformDirection(PyObject *object, void *valuePtr);
+
+ int ConvertPyObjectToColorSpaceDirection(PyObject *object, void *valuePtr);
+
+ int ConvertPyObjectToGpuLanguage(PyObject *object, void *valuePtr);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // Generics.
+ // None of these allow an interpreter error to leak
+
+ //! Use a variety of methods to get the value, as the specified type
+ //! from the specified PyObject. (Return true on success, false on failure)
+ //!
+ //! 1. See if object is PyFloat, return value
+ //! 2. See if object is PyInt, return value
+ //! 3. Attempt to cast to PyFloat / PyInt (equivalent to calling float(obj)/int(obj) in python)
+
+ bool GetIntFromPyObject(PyObject* object, int* val);
+ bool GetFloatFromPyObject(PyObject* object, float* val);
+ bool GetDoubleFromPyObject(PyObject* object, double* val);
+
+ //! 1. See if object is a PyString, return value
+ //! 2. Attempt to cast to a PyString (equivalent to calling str(obj) in python
+ //! Note: This will basically always succeed, even if the object is not string-like
+ //! (such as passing Py_None as val), so you cannot use this to check str type.
+
+ bool GetStringFromPyObject(PyObject* object, std::string* val);
+
+
+ // Can return a null pointer if PyList_New(size) fails.
+ PyObject* CreatePyListFromIntVector(const std::vector<int> &data);
+ PyObject* CreatePyListFromFloatVector(const std::vector<float> &data);
+ PyObject* CreatePyListFromDoubleVector(const std::vector<double> &data);
+ PyObject* CreatePyListFromStringVector(const std::vector<std::string> &data);
+ PyObject* CreatePyListFromTransformVector(const std::vector<ConstTransformRcPtr> &data);
+
+ //! Fill the specified vector type from the given pyobject
+ //! Return true on success, false on failure.
+ //! The PyObject must be a tuple or list, filled with the appropriate data types
+ //! (either PyInt, PyFloat, or something convertible to one)
+
+ bool FillIntVectorFromPySequence(PyObject* datalist, std::vector<int> &data);
+ bool FillFloatVectorFromPySequence(PyObject* datalist, std::vector<float> &data);
+ bool FillDoubleVectorFromPySequence(PyObject* datalist, std::vector<double> &data);
+ bool FillStringVectorFromPySequence(PyObject* datalist, std::vector<std::string> &data);
+ bool FillTransformVectorFromPySequence(PyObject* datalist, std::vector<ConstTransformRcPtr> &data);
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ void Python_Handle_Exception();
+}
+OCIO_NAMESPACE_EXIT
+
+#endif
diff --git a/src/pyglue/createPyDocH.py b/src/pyglue/createPyDocH.py
new file mode 100644
index 0000000..fd2e795
--- /dev/null
+++ b/src/pyglue/createPyDocH.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+
+"""
+This script contains mock OpenColorIO classes which define the __doc__
+strings that will end up in the final binding. These __doc__ strings are
+also used by sphinx's autodoc extension to also include this documentation
+in the html and pdf formats.
+"""
+
+import re, sys
+
+from DocStrings import *
+
+def DocStringToCString(name, doc_string):
+ _cstr = doc_string
+ _cstr = _cstr.rstrip(' ')
+ _cstr = _cstr.rstrip('\n')
+ _cstr = _cstr.lstrip('\n')
+ _cstr = _cstr.lstrip(' ')
+ _cstr = _cstr.replace("\"", "\\\"")
+ _cstr = _cstr.replace("\n", "\\n")
+ _cstr = _cstr.replace("\r", "\\n")
+ return "const char %s[%d] = \"%s\";" % (name, len(_cstr)+1, _cstr)
+
+def GetDocStrings(inst):
+ _out = ""
+ _cname = inst.__name__
+ _cdoc = inst.__doc__
+ if _cdoc == None:
+ _cdoc = ""
+ _out = "%s\n" % DocStringToCString("%s__DOC__" % _cname.upper(), _cdoc)
+ for mem in dir(inst):
+ if mem[0:2] == "__":
+ continue # skip
+ _doc = eval("inst.%s.__doc__" % mem)
+ if _doc == None:
+ _doc = ""
+ _name = "%s_%s__DOC__" % (_cname.upper(), eval("inst.%s.__name__" % mem).upper())
+ _out += "%s\n" % DocStringToCString(_name, _doc)
+ #print mem
+ return _out
+
+if __name__ == "__main__":
+
+ if len(sys.argv) <= 1:
+ sys.stderr.write("\nYou need to specify an output file\n\n")
+ sys.exit(1)
+
+ fileh = file(sys.argv[1], 'w')
+ fileh.write('\n')
+ fileh.write("/* DO NOT EDIT THIS FILE - it is machine generated */\n")
+ fileh.write("\n")
+ fileh.write("#include <OpenColorIO/OpenColorIO.h>\n")
+ fileh.write("\n")
+ fileh.write("OCIO_NAMESPACE_ENTER\n")
+ fileh.write("{\n")
+ fileh.write("\n")
+ fileh.write("%s\n" % GetDocStrings(Exception))
+ fileh.write("%s\n" % GetDocStrings(ExceptionMissingFile))
+ fileh.write("%s\n" % GetDocStrings(OpenColorIO))
+ fileh.write("%s\n" % GetDocStrings(Constants))
+ fileh.write("%s\n" % GetDocStrings(Config))
+ #fileh.write("%s\n" % GetDocStrings(Baker))
+ fileh.write("%s\n" % GetDocStrings(ColorSpace))
+ fileh.write("%s\n" % GetDocStrings(Processor))
+ fileh.write("%s\n" % GetDocStrings(ProcessorMetadata))
+ fileh.write("%s\n" % GetDocStrings(Context))
+ fileh.write("%s\n" % GetDocStrings(Look))
+ fileh.write("%s\n" % GetDocStrings(Transform))
+ fileh.write("\n")
+ fileh.write("%s\n" % GetDocStrings(AllocationTransform))
+ fileh.write("%s\n" % GetDocStrings(CDLTransform))
+ fileh.write("%s\n" % GetDocStrings(ColorSpaceTransform))
+ fileh.write("%s\n" % GetDocStrings(DisplayTransform))
+ fileh.write("%s\n" % GetDocStrings(ExponentTransform))
+ fileh.write("%s\n" % GetDocStrings(FileTransform))
+ fileh.write("%s\n" % GetDocStrings(GroupTransform))
+ fileh.write("%s\n" % GetDocStrings(LogTransform))
+ fileh.write("%s\n" % GetDocStrings(LookTransform))
+ fileh.write("%s\n" % GetDocStrings(MatrixTransform))
+ fileh.write("\n")
+ fileh.write("}\n")
+ fileh.write("OCIO_NAMESPACE_EXIT\n")
+ fileh.write("\n")
+ fileh.flush()
+ fileh.close()
diff --git a/src/rv/Makefile b/src/rv/Makefile
new file mode 100644
index 0000000..ed68cd3
--- /dev/null
+++ b/src/rv/Makefile
@@ -0,0 +1,6 @@
+.phony:
+all: ociorv.zip
+
+ociorv.zip:
+ mkdir -p Packages
+ zip Packages/ociorv.zip Python/ociorv.py Python/PACKAGE
diff --git a/src/rv/Mu/rvload b/src/rv/Mu/rvload
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/src/rv/Mu/rvload
@@ -0,0 +1 @@
+1
diff --git a/src/rv/Mu/rvload2 b/src/rv/Mu/rvload2
new file mode 100644
index 0000000..01904d4
--- /dev/null
+++ b/src/rv/Mu/rvload2
@@ -0,0 +1,2 @@
+3
+ociorv,ociorv.zip,nil,nil,nil,true,true,3.12,false
diff --git a/src/rv/Packages/.gitignore b/src/rv/Packages/.gitignore
new file mode 100644
index 0000000..61bce34
--- /dev/null
+++ b/src/rv/Packages/.gitignore
@@ -0,0 +1 @@
+ociorv.zip
diff --git a/src/rv/Packages/rvinstall b/src/rv/Packages/rvinstall
new file mode 100644
index 0000000..501708e
--- /dev/null
+++ b/src/rv/Packages/rvinstall
@@ -0,0 +1 @@
+*ociorv.zip
diff --git a/src/rv/Python/PACKAGE b/src/rv/Python/PACKAGE
new file mode 100644
index 0000000..3a7889f
--- /dev/null
+++ b/src/rv/Python/PACKAGE
@@ -0,0 +1,12 @@
+package: OpenColorIO
+version: 1.0
+rv: 3.12
+requires: ''
+
+modes:
+ - file: ociorv.py
+ load: immediate
+
+description: |
+
+ Integrates OCIO, and that's about it
diff --git a/src/rv/Python/ociorv.py b/src/rv/Python/ociorv.py
new file mode 100644
index 0000000..77e10cf
--- /dev/null
+++ b/src/rv/Python/ociorv.py
@@ -0,0 +1,288 @@
+import time
+import itertools
+import contextlib
+
+import PyOpenColorIO as OCIO
+
+import rv
+from rv.commands import setStringProperty, setIntProperty, setFloatProperty
+
+
+@contextlib.contextmanager
+def timer(msg):
+ start = time.time()
+ yield
+ end = time.time()
+ print "%s: %.02fms" % (msg, (end-start)*1000)
+
+
+def set_lut(proc, nodename):
+ """Given an PyOpenColorIO.Processor instance, create a LUT and
+ sets it for the specified node
+ """
+
+ if proc.isNoOp():
+ return
+
+ if hasattr(proc, "hasChannelCrosstalk"):
+ # Determine if transform has crosstalk, and switch 1D/3D based on this
+ crosstalk = proc.hasChannelCrosstalk()
+ else:
+ # Assume crosstalk in lieu of latest OCIO Python bindings
+ crosstalk = True
+
+ # TODO: Maybe allow configuration of LUT sizes?
+ size_1d = 2048
+ size_3d = 32
+
+ if crosstalk:
+ _set_lut_3d(proc = proc, nodename = nodename, size = size_3d)
+ else:
+ _set_lut_1d(proc = proc, nodename = nodename, size = size_1d)
+
+ # TODO: Can also set nodename.lut.inMatrix - could maybe avoid creating a
+ # 3D LUT for linear transforms
+
+
+def _set_lut_3d(proc, nodename, size = 32):
+ # FIXME: This clips with >1 scene-linear values, use allocation
+ # vars
+
+ # Make noop cube
+ size_minus_one = float(size-1)
+ one_axis = (x/size_minus_one for x in range(size))
+ cube_raw = itertools.product(one_axis, repeat=3)
+
+ # Unpack and fix ordering, by turning [(0, 0, 0), (0, 0, 1), ...]
+ # into [0, 0, 0, 1, 0, 0] as generator
+ cube_raw = (item for sublist in cube_raw for item in sublist[::-1])
+
+ # Apply transform
+ cube_processed = proc.applyRGB(cube_raw)
+
+ # Set LUT type and size, then LUT values
+ setStringProperty("%s.lut.type" % nodename, ["RGB"], False)
+ setIntProperty("%s.lut.size" % nodename, [size, size, size], False)
+ setFloatProperty("%s.lut.lut" % nodename, cube_processed, True)
+
+ # Activate
+ setIntProperty("%s.lut.active" % nodename, [1], False)
+
+
+def _set_lut_1d(proc, nodename, size = 1024):
+ # TODO: Use allocation vars also
+
+ # Make noop ramp
+ def gen_noop_ramp(size):
+ size_minus_one = float(size-1)
+ for x in range(size):
+ val = x/size_minus_one
+ for i in range(3):
+ yield val
+
+ ramp_raw = gen_noop_ramp(size = size)
+
+ # Apply transform
+ # TODO: Make applyRGB accept an iterable, rather than requiring a
+ # list, to avoid making the intermediate list
+ ramp_transformed = proc.applyRGB(ramp_raw)
+
+ # Set LUT type and size, then LUT values
+ setStringProperty("%s.lut.type" % nodename, ["RGB"], False)
+ setIntProperty("%s.lut.size" % nodename, [size], False)
+ setFloatProperty("%s.lut.lut" % nodename, ramp_transformed, True)
+
+ # Activate
+ setIntProperty("%s.lut.active" % nodename, [1], False)
+
+
+def set_noop(nodename):
+ """Just ensure sure the LUT is deactivated, in case source changes
+ from switch from a non-noop to a noop processor
+ """
+
+ is_active = False
+ setIntProperty("%s.lut.active" % nodename, [is_active], False)
+
+
+def view_to_uistr(view):
+ # sRGB/Film
+ return "/".join(view)
+
+
+class PyMyStuffMode(rv.rvtypes.MinorMode):
+
+ def set_display(self, event):
+ avail = self.get_views()
+ cur = self.active_view
+ curindex = avail.index(cur)
+ newindex = (curindex + 1) % len(avail)
+ self.active_view = avail[newindex]
+ rv.extra_commands.displayFeedback(
+ "Changing display to %s" % view_to_uistr(self.active_view),
+ 2.0, # timeout
+ )
+ self.refresh()
+
+ def get_cfg(self):
+ return OCIO.GetCurrentConfig()
+
+ def refresh(self):
+ """Refresh LUT on all sources
+ """
+ for src in rv.commands.nodesOfType("RVSource"):
+ path = rv.commands.getStringProperty(
+ "%s.media.movie" % src,
+ 0, 99999999)[0] # defaultish arguments
+ self._config_source(src = src, srcpath = path)
+
+ def source_setup(self, event):
+ # Event content example:
+ # sourceGroup000001_source;;RVSource;;/path/to/myimg.exr
+ print event.contents()
+ args = event.contents().split(";;")
+ src = args[0]
+ srcpath = args[2]
+
+ self._config_source(src = src, srcpath = srcpath)
+
+ def _config_source(self, src, srcpath):
+ filelut_node = rv.extra_commands.associatedNode("RVColor", src)
+ looklut_node = rv.extra_commands.associatedNode("RVLookLUT", src)
+
+ # Set 3D LUT, and activate
+ cfg = self.get_cfg()
+
+ # FIXME: Need a way to customise this per-facility without
+ # modifying this file (try: import ociorv_custom_stuff ?)
+ inspace = cfg.parseColorSpaceFromString(srcpath)
+
+ test_transform = OCIO.DisplayTransform()
+ test_transform.setInputColorSpaceName(inspace)
+ display, view = self.active_view
+ test_transform.setDisplay(display)
+ test_transform.setView(view)
+
+ try:
+ test_proc = cfg.getProcessor(test_transform)
+ except OCIO.Exception, e:
+ print "INFO: Cannot create test OCIODisplay for %s - display LUT disabled. OCIO message was %s" % (
+ inspace,
+ e)
+ set_noop(nodename = filelut_node)
+ set_noop(nodename = looklut_node)
+ return
+
+ if test_proc.isNoOp():
+ print "Source is NoOp"
+ set_noop(nodename = filelut_node)
+ set_noop(nodename = looklut_node)
+ return
+
+ # Input -> scene-linear processor. Allow grading controls etc
+ # to work as expected
+ try:
+ input_proc = cfg.getProcessor(inspace, OCIO.Constants.ROLE_SCENE_LINEAR)
+ except OCIO.Exception, e:
+ # TODO: This mostly catches "3D Luts can only be applied
+ # in the forward direction.", could handle this better
+ print "INFO: Cannot linearise %s - display LUT disabled. OCIO message was %s" % (
+ inspace,
+ e)
+ set_noop(nodename = filelut_node)
+ set_noop(nodename = looklut_node)
+ return
+
+ # Scene-linear -> output display transform
+ transform = OCIO.DisplayTransform()
+ transform.setDisplay(self.active_view[0])
+ transform.setView(self.active_view[1])
+
+ transform.setInputColorSpaceName(OCIO.Constants.ROLE_SCENE_LINEAR)
+
+ try:
+ output_proc = cfg.getProcessor(transform)
+ except OCIO.Exception, e:
+ print "INFO: Cannot apply scene-linear to %s - OCIO error was %s" % (
+ srcpath,
+ e)
+ set_noop(nodename = filelut_node)
+ set_noop(nodename = looklut_node)
+ return
+
+ # LUT to be applied to input file, before any grading etc
+ set_lut(proc = input_proc, nodename = filelut_node)
+
+ # LUT after grading etc performed
+ set_lut(proc = output_proc, nodename = looklut_node)
+
+ # Update LUT
+ rv.commands.updateLUT()
+
+ def set_view(self, display, view):
+ """Set view, and update all sources
+ """
+ print "display: %s, view: %s" % (display, view)
+ self.active_view = (display, view)
+ self.refresh()
+
+ def get_views(self):
+ """Return [("sRGB", "Film"), ("sRGB", "Log"), ...]
+ """
+ available_views = []
+
+ cfg = self.get_cfg()
+ for a_display in cfg.getDisplays():
+ if a_display not in cfg.getActiveDisplays().split(", "):
+ continue
+
+ for a_view in cfg.getViews(a_display):
+ if a_view not in cfg.getActiveViews():
+ continue
+
+ available_views.append(
+ (a_display, a_view))
+ return available_views
+
+ def __init__(self):
+ rv.rvtypes.MinorMode.__init__(self)
+
+ mode_name = "ociorv-mode"
+
+ global_bindings = [
+ ("key-down--d", self.set_display, "set display"),
+ ("new-source", self.source_setup, "OCIO source setup"),
+ ]
+
+ local_bindings = []
+
+ # Create [("sRGB/Film", self.set_menu(...)), ("sRGB/Log", ...)]
+ views_menu = []
+ for cur_view in self.get_views():
+ def set_view(event, cur_view = cur_view):
+ display, view = cur_view
+ self.set_view(display = display, view = view)
+ mi = (
+ "/".join(cur_view), # label
+ set_view, # actionHook
+ )
+ views_menu.append(mi)
+
+ # Set default view
+ cfg = self.get_cfg()
+ self.active_view = (
+ cfg.getDefaultDisplay(),
+ cfg.getDefaultView(cfg.getDefaultDisplay()))
+
+ # Construct top-level menu
+ menu = [("OCIO", [
+ ("Display/Views", views_menu)])]
+
+ self.init(mode_name,
+ global_bindings,
+ local_bindings,
+ menu)
+
+
+def createMode():
+ return PyMyStuffMode()
diff --git a/testdata/3dl.zip b/testdata/3dl.zip
new file mode 100644
index 0000000..2dd58c9
--- /dev/null
+++ b/testdata/3dl.zip
Binary files differ
diff --git a/testdata/csp.zip b/testdata/csp.zip
new file mode 100644
index 0000000..9561554
--- /dev/null
+++ b/testdata/csp.zip
Binary files differ
diff --git a/testdata/cub.zip b/testdata/cub.zip
new file mode 100644
index 0000000..27922b6
--- /dev/null
+++ b/testdata/cub.zip
Binary files differ
diff --git a/testdata/cube.zip b/testdata/cube.zip
new file mode 100644
index 0000000..ead0100
--- /dev/null
+++ b/testdata/cube.zip
Binary files differ
diff --git a/testdata/iridas.zip b/testdata/iridas.zip
new file mode 100644
index 0000000..b0e2ad5
--- /dev/null
+++ b/testdata/iridas.zip
Binary files differ
diff --git a/testdata/itx.zip b/testdata/itx.zip
new file mode 100644
index 0000000..bf3cca2
--- /dev/null
+++ b/testdata/itx.zip
Binary files differ
diff --git a/testdata/mga.zip b/testdata/mga.zip
new file mode 100644
index 0000000..7bb1ed0
--- /dev/null
+++ b/testdata/mga.zip
Binary files differ
diff --git a/testdata/spi.zip b/testdata/spi.zip
new file mode 100644
index 0000000..d2caf18
--- /dev/null
+++ b/testdata/spi.zip
Binary files differ