From de6ba15c31f8f2d7f7efffc152a32bdc66cddac1 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sun, 21 Aug 2016 00:14:15 -0500 Subject: [PATCH] Initial commit. --- Makefile | 7 + OpenEXR/include/OpenEXR/Iex.h | 60 + OpenEXR/include/OpenEXR/IexBaseExc.h | 264 ++ OpenEXR/include/OpenEXR/IexErrnoExc.h | 208 + OpenEXR/include/OpenEXR/IexExport.h | 51 + OpenEXR/include/OpenEXR/IexForward.h | 229 ++ OpenEXR/include/OpenEXR/IexMacros.h | 170 + OpenEXR/include/OpenEXR/IexMathExc.h | 57 + OpenEXR/include/OpenEXR/IexMathFloatExc.h | 146 + OpenEXR/include/OpenEXR/IexMathFpu.h | 91 + OpenEXR/include/OpenEXR/IexMathIeeeExc.h | 62 + OpenEXR/include/OpenEXR/IexNamespace.h | 112 + OpenEXR/include/OpenEXR/IexThrowErrnoExc.h | 97 + OpenEXR/include/OpenEXR/IlmBaseConfig.h | 72 + OpenEXR/include/OpenEXR/IlmThread.h | 143 + OpenEXR/include/OpenEXR/IlmThreadExport.h | 46 + OpenEXR/include/OpenEXR/IlmThreadForward.h | 52 + OpenEXR/include/OpenEXR/IlmThreadMutex.h | 160 + OpenEXR/include/OpenEXR/IlmThreadNamespace.h | 114 + OpenEXR/include/OpenEXR/IlmThreadPool.h | 160 + OpenEXR/include/OpenEXR/IlmThreadSemaphore.h | 112 + OpenEXR/include/OpenEXR/ImathBox.h | 849 ++++ OpenEXR/include/OpenEXR/ImathBoxAlgo.h | 1016 +++++ OpenEXR/include/OpenEXR/ImathColor.h | 736 ++++ OpenEXR/include/OpenEXR/ImathColorAlgo.h | 257 ++ OpenEXR/include/OpenEXR/ImathEuler.h | 926 +++++ OpenEXR/include/OpenEXR/ImathExc.h | 73 + OpenEXR/include/OpenEXR/ImathExport.h | 46 + OpenEXR/include/OpenEXR/ImathForward.h | 72 + OpenEXR/include/OpenEXR/ImathFrame.h | 192 + OpenEXR/include/OpenEXR/ImathFrustum.h | 741 ++++ OpenEXR/include/OpenEXR/ImathFrustumTest.h | 417 ++ OpenEXR/include/OpenEXR/ImathFun.h | 269 ++ OpenEXR/include/OpenEXR/ImathGL.h | 166 + OpenEXR/include/OpenEXR/ImathGLU.h | 54 + OpenEXR/include/OpenEXR/ImathHalfLimits.h | 68 + OpenEXR/include/OpenEXR/ImathInt64.h | 62 + OpenEXR/include/OpenEXR/ImathInterval.h | 226 ++ OpenEXR/include/OpenEXR/ImathLimits.h | 268 ++ OpenEXR/include/OpenEXR/ImathLine.h | 185 + OpenEXR/include/OpenEXR/ImathLineAlgo.h | 288 ++ OpenEXR/include/OpenEXR/ImathMath.h | 208 + OpenEXR/include/OpenEXR/ImathMatrix.h | 3441 +++++++++++++++++ OpenEXR/include/OpenEXR/ImathMatrixAlgo.h | 1425 +++++++ OpenEXR/include/OpenEXR/ImathNamespace.h | 115 + OpenEXR/include/OpenEXR/ImathPlane.h | 257 ++ OpenEXR/include/OpenEXR/ImathPlatform.h | 112 + OpenEXR/include/OpenEXR/ImathQuat.h | 964 +++++ OpenEXR/include/OpenEXR/ImathRandom.h | 401 ++ OpenEXR/include/OpenEXR/ImathRoots.h | 219 ++ OpenEXR/include/OpenEXR/ImathShear.h | 656 ++++ OpenEXR/include/OpenEXR/ImathSphere.h | 177 + OpenEXR/include/OpenEXR/ImathVec.h | 2227 +++++++++++ OpenEXR/include/OpenEXR/ImathVecAlgo.h | 147 + OpenEXR/include/OpenEXR/ImfAcesFile.h | 324 ++ OpenEXR/include/OpenEXR/ImfArray.h | 285 ++ OpenEXR/include/OpenEXR/ImfAttribute.h | 407 ++ OpenEXR/include/OpenEXR/ImfB44Compressor.h | 118 + OpenEXR/include/OpenEXR/ImfBoxAttribute.h | 87 + OpenEXR/include/OpenEXR/ImfCRgbaFile.h | 555 +++ OpenEXR/include/OpenEXR/ImfChannelList.h | 436 +++ .../include/OpenEXR/ImfChannelListAttribute.h | 74 + OpenEXR/include/OpenEXR/ImfChromaticities.h | 131 + .../OpenEXR/ImfChromaticitiesAttribute.h | 73 + .../OpenEXR/ImfCompositeDeepScanLine.h | 142 + OpenEXR/include/OpenEXR/ImfCompression.h | 84 + .../include/OpenEXR/ImfCompressionAttribute.h | 64 + OpenEXR/include/OpenEXR/ImfConvert.h | 107 + OpenEXR/include/OpenEXR/ImfDeepCompositing.h | 132 + OpenEXR/include/OpenEXR/ImfDeepFrameBuffer.h | 339 ++ OpenEXR/include/OpenEXR/ImfDeepImageState.h | 96 + .../OpenEXR/ImfDeepImageStateAttribute.h | 68 + .../OpenEXR/ImfDeepScanLineInputFile.h | 276 ++ .../OpenEXR/ImfDeepScanLineInputPart.h | 181 + .../OpenEXR/ImfDeepScanLineOutputFile.h | 244 ++ .../OpenEXR/ImfDeepScanLineOutputPart.h | 168 + .../include/OpenEXR/ImfDeepTiledInputFile.h | 437 +++ .../include/OpenEXR/ImfDeepTiledInputPart.h | 362 ++ .../include/OpenEXR/ImfDeepTiledOutputFile.h | 475 +++ .../include/OpenEXR/ImfDeepTiledOutputPart.h | 394 ++ OpenEXR/include/OpenEXR/ImfDoubleAttribute.h | 59 + OpenEXR/include/OpenEXR/ImfEnvmap.h | 336 ++ OpenEXR/include/OpenEXR/ImfEnvmapAttribute.h | 68 + OpenEXR/include/OpenEXR/ImfExport.h | 46 + OpenEXR/include/OpenEXR/ImfFloatAttribute.h | 58 + OpenEXR/include/OpenEXR/ImfForward.h | 127 + OpenEXR/include/OpenEXR/ImfFrameBuffer.h | 386 ++ OpenEXR/include/OpenEXR/ImfFramesPerSecond.h | 94 + OpenEXR/include/OpenEXR/ImfGenericInputFile.h | 58 + .../include/OpenEXR/ImfGenericOutputFile.h | 62 + OpenEXR/include/OpenEXR/ImfHeader.h | 699 ++++ OpenEXR/include/OpenEXR/ImfHuf.h | 82 + OpenEXR/include/OpenEXR/ImfIO.h | 255 ++ OpenEXR/include/OpenEXR/ImfInputFile.h | 240 ++ OpenEXR/include/OpenEXR/ImfInputPart.h | 84 + OpenEXR/include/OpenEXR/ImfInt64.h | 56 + OpenEXR/include/OpenEXR/ImfIntAttribute.h | 58 + OpenEXR/include/OpenEXR/ImfKeyCode.h | 167 + OpenEXR/include/OpenEXR/ImfKeyCodeAttribute.h | 73 + OpenEXR/include/OpenEXR/ImfLineOrder.h | 69 + .../include/OpenEXR/ImfLineOrderAttribute.h | 72 + OpenEXR/include/OpenEXR/ImfLut.h | 188 + OpenEXR/include/OpenEXR/ImfMatrixAttribute.h | 83 + OpenEXR/include/OpenEXR/ImfMisc.h | 466 +++ .../include/OpenEXR/ImfMultiPartInputFile.h | 128 + .../include/OpenEXR/ImfMultiPartOutputFile.h | 118 + OpenEXR/include/OpenEXR/ImfMultiView.h | 187 + OpenEXR/include/OpenEXR/ImfName.h | 150 + OpenEXR/include/OpenEXR/ImfNamespace.h | 115 + OpenEXR/include/OpenEXR/ImfOpaqueAttribute.h | 110 + OpenEXR/include/OpenEXR/ImfOutputFile.h | 263 ++ OpenEXR/include/OpenEXR/ImfOutputPart.h | 77 + OpenEXR/include/OpenEXR/ImfPartHelper.h | 262 ++ OpenEXR/include/OpenEXR/ImfPartType.h | 62 + OpenEXR/include/OpenEXR/ImfPixelType.h | 67 + OpenEXR/include/OpenEXR/ImfPreviewImage.h | 135 + .../OpenEXR/ImfPreviewImageAttribute.h | 70 + OpenEXR/include/OpenEXR/ImfRational.h | 98 + .../include/OpenEXR/ImfRationalAttribute.h | 69 + OpenEXR/include/OpenEXR/ImfRgba.h | 109 + OpenEXR/include/OpenEXR/ImfRgbaFile.h | 346 ++ OpenEXR/include/OpenEXR/ImfRgbaYca.h | 259 ++ .../include/OpenEXR/ImfStandardAttributes.h | 382 ++ OpenEXR/include/OpenEXR/ImfStringAttribute.h | 71 + .../OpenEXR/ImfStringVectorAttribute.h | 74 + OpenEXR/include/OpenEXR/ImfTestFile.h | 97 + OpenEXR/include/OpenEXR/ImfThreading.h | 95 + OpenEXR/include/OpenEXR/ImfTileDescription.h | 107 + .../OpenEXR/ImfTileDescriptionAttribute.h | 72 + OpenEXR/include/OpenEXR/ImfTiledInputFile.h | 401 ++ OpenEXR/include/OpenEXR/ImfTiledInputPart.h | 100 + OpenEXR/include/OpenEXR/ImfTiledOutputFile.h | 495 +++ OpenEXR/include/OpenEXR/ImfTiledOutputPart.h | 105 + OpenEXR/include/OpenEXR/ImfTiledRgbaFile.h | 482 +++ OpenEXR/include/OpenEXR/ImfTimeCode.h | 242 ++ .../include/OpenEXR/ImfTimeCodeAttribute.h | 74 + OpenEXR/include/OpenEXR/ImfVecAttribute.h | 100 + OpenEXR/include/OpenEXR/ImfVersion.h | 136 + OpenEXR/include/OpenEXR/ImfWav.h | 78 + OpenEXR/include/OpenEXR/ImfXdr.h | 927 +++++ OpenEXR/include/OpenEXR/OpenEXRConfig.h | 73 + OpenEXR/include/OpenEXR/half.h | 757 ++++ OpenEXR/include/OpenEXR/halfExport.h | 27 + OpenEXR/include/OpenEXR/halfFunction.h | 179 + OpenEXR/include/OpenEXR/halfLimits.h | 102 + OpenEXR/lib/Half.lib | Bin 0 -> 5192 bytes OpenEXR/lib/Iex-2_2.lib | Bin 0 -> 36992 bytes OpenEXR/lib/IexMath-2_2.lib | Bin 0 -> 2514 bytes OpenEXR/lib/IlmImf-2_2.lib | Bin 0 -> 627250 bytes OpenEXR/lib/IlmImfUtil-2_2.lib | Bin 0 -> 99540 bytes OpenEXR/lib/IlmThread-2_2.lib | Bin 0 -> 14870 bytes OpenEXR/lib/Imath-2_2.lib | Bin 0 -> 54536 bytes README.md | 83 + bin/.gitignore | 1 + bin/Half.dll | Bin 0 -> 276480 bytes bin/Iex-2_2.dll | Bin 0 -> 77824 bytes bin/IexMath-2_2.dll | Bin 0 -> 19968 bytes bin/IlmImf-2_2.dll | Bin 0 -> 2961408 bytes bin/IlmImfUtil-2_2.dll | Bin 0 -> 158208 bytes bin/IlmThread-2_2.dll | Bin 0 -> 43520 bytes bin/Imath-2_2.dll | Bin 0 -> 84480 bytes empty | 0 exrflatten.cpp | 699 ++++ exrflatten.sln | 22 + exrflatten.vcxproj | 101 + exrflatten.vcxproj.filters | 6 + 166 files changed, 38331 insertions(+) create mode 100644 Makefile create mode 100644 OpenEXR/include/OpenEXR/Iex.h create mode 100644 OpenEXR/include/OpenEXR/IexBaseExc.h create mode 100644 OpenEXR/include/OpenEXR/IexErrnoExc.h create mode 100644 OpenEXR/include/OpenEXR/IexExport.h create mode 100644 OpenEXR/include/OpenEXR/IexForward.h create mode 100644 OpenEXR/include/OpenEXR/IexMacros.h create mode 100644 OpenEXR/include/OpenEXR/IexMathExc.h create mode 100644 OpenEXR/include/OpenEXR/IexMathFloatExc.h create mode 100644 OpenEXR/include/OpenEXR/IexMathFpu.h create mode 100644 OpenEXR/include/OpenEXR/IexMathIeeeExc.h create mode 100644 OpenEXR/include/OpenEXR/IexNamespace.h create mode 100644 OpenEXR/include/OpenEXR/IexThrowErrnoExc.h create mode 100644 OpenEXR/include/OpenEXR/IlmBaseConfig.h create mode 100644 OpenEXR/include/OpenEXR/IlmThread.h create mode 100644 OpenEXR/include/OpenEXR/IlmThreadExport.h create mode 100644 OpenEXR/include/OpenEXR/IlmThreadForward.h create mode 100644 OpenEXR/include/OpenEXR/IlmThreadMutex.h create mode 100644 OpenEXR/include/OpenEXR/IlmThreadNamespace.h create mode 100644 OpenEXR/include/OpenEXR/IlmThreadPool.h create mode 100644 OpenEXR/include/OpenEXR/IlmThreadSemaphore.h create mode 100644 OpenEXR/include/OpenEXR/ImathBox.h create mode 100644 OpenEXR/include/OpenEXR/ImathBoxAlgo.h create mode 100644 OpenEXR/include/OpenEXR/ImathColor.h create mode 100644 OpenEXR/include/OpenEXR/ImathColorAlgo.h create mode 100644 OpenEXR/include/OpenEXR/ImathEuler.h create mode 100644 OpenEXR/include/OpenEXR/ImathExc.h create mode 100644 OpenEXR/include/OpenEXR/ImathExport.h create mode 100644 OpenEXR/include/OpenEXR/ImathForward.h create mode 100644 OpenEXR/include/OpenEXR/ImathFrame.h create mode 100644 OpenEXR/include/OpenEXR/ImathFrustum.h create mode 100644 OpenEXR/include/OpenEXR/ImathFrustumTest.h create mode 100644 OpenEXR/include/OpenEXR/ImathFun.h create mode 100644 OpenEXR/include/OpenEXR/ImathGL.h create mode 100644 OpenEXR/include/OpenEXR/ImathGLU.h create mode 100644 OpenEXR/include/OpenEXR/ImathHalfLimits.h create mode 100644 OpenEXR/include/OpenEXR/ImathInt64.h create mode 100644 OpenEXR/include/OpenEXR/ImathInterval.h create mode 100644 OpenEXR/include/OpenEXR/ImathLimits.h create mode 100644 OpenEXR/include/OpenEXR/ImathLine.h create mode 100644 OpenEXR/include/OpenEXR/ImathLineAlgo.h create mode 100644 OpenEXR/include/OpenEXR/ImathMath.h create mode 100644 OpenEXR/include/OpenEXR/ImathMatrix.h create mode 100644 OpenEXR/include/OpenEXR/ImathMatrixAlgo.h create mode 100644 OpenEXR/include/OpenEXR/ImathNamespace.h create mode 100644 OpenEXR/include/OpenEXR/ImathPlane.h create mode 100644 OpenEXR/include/OpenEXR/ImathPlatform.h create mode 100644 OpenEXR/include/OpenEXR/ImathQuat.h create mode 100644 OpenEXR/include/OpenEXR/ImathRandom.h create mode 100644 OpenEXR/include/OpenEXR/ImathRoots.h create mode 100644 OpenEXR/include/OpenEXR/ImathShear.h create mode 100644 OpenEXR/include/OpenEXR/ImathSphere.h create mode 100644 OpenEXR/include/OpenEXR/ImathVec.h create mode 100644 OpenEXR/include/OpenEXR/ImathVecAlgo.h create mode 100644 OpenEXR/include/OpenEXR/ImfAcesFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfArray.h create mode 100644 OpenEXR/include/OpenEXR/ImfAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfB44Compressor.h create mode 100644 OpenEXR/include/OpenEXR/ImfBoxAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfCRgbaFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfChannelList.h create mode 100644 OpenEXR/include/OpenEXR/ImfChannelListAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfChromaticities.h create mode 100644 OpenEXR/include/OpenEXR/ImfChromaticitiesAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfCompositeDeepScanLine.h create mode 100644 OpenEXR/include/OpenEXR/ImfCompression.h create mode 100644 OpenEXR/include/OpenEXR/ImfCompressionAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfConvert.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepCompositing.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepFrameBuffer.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepImageState.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepImageStateAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepScanLineInputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepScanLineInputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepScanLineOutputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepScanLineOutputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepTiledInputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepTiledInputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepTiledOutputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfDeepTiledOutputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfDoubleAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfEnvmap.h create mode 100644 OpenEXR/include/OpenEXR/ImfEnvmapAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfExport.h create mode 100644 OpenEXR/include/OpenEXR/ImfFloatAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfForward.h create mode 100644 OpenEXR/include/OpenEXR/ImfFrameBuffer.h create mode 100644 OpenEXR/include/OpenEXR/ImfFramesPerSecond.h create mode 100644 OpenEXR/include/OpenEXR/ImfGenericInputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfGenericOutputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfHeader.h create mode 100644 OpenEXR/include/OpenEXR/ImfHuf.h create mode 100644 OpenEXR/include/OpenEXR/ImfIO.h create mode 100644 OpenEXR/include/OpenEXR/ImfInputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfInputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfInt64.h create mode 100644 OpenEXR/include/OpenEXR/ImfIntAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfKeyCode.h create mode 100644 OpenEXR/include/OpenEXR/ImfKeyCodeAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfLineOrder.h create mode 100644 OpenEXR/include/OpenEXR/ImfLineOrderAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfLut.h create mode 100644 OpenEXR/include/OpenEXR/ImfMatrixAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfMisc.h create mode 100644 OpenEXR/include/OpenEXR/ImfMultiPartInputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfMultiPartOutputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfMultiView.h create mode 100644 OpenEXR/include/OpenEXR/ImfName.h create mode 100644 OpenEXR/include/OpenEXR/ImfNamespace.h create mode 100644 OpenEXR/include/OpenEXR/ImfOpaqueAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfOutputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfOutputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfPartHelper.h create mode 100644 OpenEXR/include/OpenEXR/ImfPartType.h create mode 100644 OpenEXR/include/OpenEXR/ImfPixelType.h create mode 100644 OpenEXR/include/OpenEXR/ImfPreviewImage.h create mode 100644 OpenEXR/include/OpenEXR/ImfPreviewImageAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfRational.h create mode 100644 OpenEXR/include/OpenEXR/ImfRationalAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfRgba.h create mode 100644 OpenEXR/include/OpenEXR/ImfRgbaFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfRgbaYca.h create mode 100644 OpenEXR/include/OpenEXR/ImfStandardAttributes.h create mode 100644 OpenEXR/include/OpenEXR/ImfStringAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfStringVectorAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfTestFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfThreading.h create mode 100644 OpenEXR/include/OpenEXR/ImfTileDescription.h create mode 100644 OpenEXR/include/OpenEXR/ImfTileDescriptionAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfTiledInputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfTiledInputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfTiledOutputFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfTiledOutputPart.h create mode 100644 OpenEXR/include/OpenEXR/ImfTiledRgbaFile.h create mode 100644 OpenEXR/include/OpenEXR/ImfTimeCode.h create mode 100644 OpenEXR/include/OpenEXR/ImfTimeCodeAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfVecAttribute.h create mode 100644 OpenEXR/include/OpenEXR/ImfVersion.h create mode 100644 OpenEXR/include/OpenEXR/ImfWav.h create mode 100644 OpenEXR/include/OpenEXR/ImfXdr.h create mode 100644 OpenEXR/include/OpenEXR/OpenEXRConfig.h create mode 100644 OpenEXR/include/OpenEXR/half.h create mode 100644 OpenEXR/include/OpenEXR/halfExport.h create mode 100644 OpenEXR/include/OpenEXR/halfFunction.h create mode 100644 OpenEXR/include/OpenEXR/halfLimits.h create mode 100644 OpenEXR/lib/Half.lib create mode 100644 OpenEXR/lib/Iex-2_2.lib create mode 100644 OpenEXR/lib/IexMath-2_2.lib create mode 100644 OpenEXR/lib/IlmImf-2_2.lib create mode 100644 OpenEXR/lib/IlmImfUtil-2_2.lib create mode 100644 OpenEXR/lib/IlmThread-2_2.lib create mode 100644 OpenEXR/lib/Imath-2_2.lib create mode 100644 README.md create mode 100644 bin/.gitignore create mode 100644 bin/Half.dll create mode 100644 bin/Iex-2_2.dll create mode 100644 bin/IexMath-2_2.dll create mode 100644 bin/IlmImf-2_2.dll create mode 100644 bin/IlmImfUtil-2_2.dll create mode 100644 bin/IlmThread-2_2.dll create mode 100644 bin/Imath-2_2.dll delete mode 100644 empty create mode 100644 exrflatten.cpp create mode 100644 exrflatten.sln create mode 100644 exrflatten.vcxproj create mode 100644 exrflatten.vcxproj.filters diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..43de5ff --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CXXFLAGS=-std=c++1y -Wall -Wno-sign-compare -O2 -g +LDFLAGS=-lIlmImf -g +CC=g++ + +all: exrflatten +exrflatten: exrflatten.o + diff --git a/OpenEXR/include/OpenEXR/Iex.h b/OpenEXR/include/OpenEXR/Iex.h new file mode 100644 index 0000000..a0fd31d --- /dev/null +++ b/OpenEXR/include/OpenEXR/Iex.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEX_H +#define INCLUDED_IEX_H + + +//-------------------------------- +// +// Exception handling +// +//-------------------------------- + + +#include "IexMacros.h" +#include "IexBaseExc.h" +#include "IexMathExc.h" +#include "IexThrowErrnoExc.h" + +// Note that we do not include file IexErrnoExc.h here. That file +// defines over 150 classes and significantly slows down compilation. +// If you throw ErrnoExc exceptions using the throwErrnoExc() function, +// you don't need IexErrnoExc.h. You have to include IexErrnoExc.h +// only if you want to catch specific subclasses of ErrnoExc. + + +#endif diff --git a/OpenEXR/include/OpenEXR/IexBaseExc.h b/OpenEXR/include/OpenEXR/IexBaseExc.h new file mode 100644 index 0000000..bf016f7 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexBaseExc.h @@ -0,0 +1,264 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXBASEEXC_H +#define INCLUDED_IEXBASEEXC_H + +#include "IexNamespace.h" +#include "IexExport.h" + +//---------------------------------------------------------- +// +// A general exception base class, and a few +// useful exceptions derived from the base class. +// +//---------------------------------------------------------- + +#include +#include +#include + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + + +//------------------------------- +// Our most basic exception class +//------------------------------- + +class BaseExc: public std::string, public std::exception +{ + public: + + //---------------------------- + // Constructors and destructor + //---------------------------- + + IEX_EXPORT BaseExc (const char *s = 0) throw(); // std::string (s) + IEX_EXPORT BaseExc (const std::string &s) throw(); // std::string (s) + IEX_EXPORT BaseExc (std::stringstream &s) throw(); // std::string (s.str()) + + IEX_EXPORT BaseExc (const BaseExc &be) throw(); + IEX_EXPORT virtual ~BaseExc () throw (); + + //-------------------------------------------- + // what() method -- e.what() returns e.c_str() + //-------------------------------------------- + + IEX_EXPORT virtual const char * what () const throw (); + + + //-------------------------------------------------- + // Convenient methods to change the exception's text + //-------------------------------------------------- + + IEX_EXPORT BaseExc & assign (std::stringstream &s); // assign (s.str()) + IEX_EXPORT BaseExc & operator = (std::stringstream &s); + + IEX_EXPORT BaseExc & append (std::stringstream &s); // append (s.str()) + IEX_EXPORT BaseExc & operator += (std::stringstream &s); + + + //-------------------------------------------------- + // These methods from the base class get obscured by + // the definitions above. + //-------------------------------------------------- + + IEX_EXPORT BaseExc & assign (const char *s); + IEX_EXPORT BaseExc & operator = (const char *s); + + IEX_EXPORT BaseExc & append (const char *s); + IEX_EXPORT BaseExc & operator += (const char *s); + + + //-------------------------------------------------- + // Stack trace for the point at which the exception + // was thrown. The stack trace will be an empty + // string unless a working stack-tracing routine + // has been installed (see below, setStackTracer()). + //-------------------------------------------------- + + IEX_EXPORT const std::string & stackTrace () const; + + private: + + std::string _stackTrace; +}; + + +//----------------------------------------------------- +// A macro to save typing when declararing an exception +// class derived directly or indirectly from BaseExc: +//----------------------------------------------------- + +#define DEFINE_EXC_EXP(exp, name, base) \ + class exp name: public base \ + { \ + public: \ + name() throw(): base (0) {} \ + name (const char* text) throw(): base (text) {} \ + name (const std::string &text) throw(): base (text) {} \ + name (std::stringstream &text) throw(): base (text) {} \ + ~name() throw() { } \ + }; + +// For backward compatibility. +#define DEFINE_EXC(name, base) DEFINE_EXC_EXP(, name, base) + + +//-------------------------------------------------------- +// Some exceptions which should be useful in most programs +//-------------------------------------------------------- +DEFINE_EXC_EXP (IEX_EXPORT, ArgExc, BaseExc) // Invalid arguments to a function call + +DEFINE_EXC_EXP (IEX_EXPORT, LogicExc, BaseExc) // General error in a program's logic, + // for example, a function was called + // in a context where the call does + // not make sense. + +DEFINE_EXC_EXP (IEX_EXPORT, InputExc, BaseExc) // Invalid input data, e.g. from a file + +DEFINE_EXC_EXP (IEX_EXPORT, IoExc, BaseExc) // Input or output operation failed + +DEFINE_EXC_EXP (IEX_EXPORT, MathExc, BaseExc) // Arithmetic exception; more specific + // exceptions derived from this class + // are defined in ExcMath.h + +DEFINE_EXC_EXP (IEX_EXPORT, ErrnoExc, BaseExc) // Base class for exceptions corresponding + // to errno values (see errno.h); more + // specific exceptions derived from this + // class are defined in ExcErrno.h + +DEFINE_EXC_EXP (IEX_EXPORT, NoImplExc, BaseExc) // Missing method exception e.g. from a + // call to a method that is only partially + // or not at all implemented. A reminder + // to lazy software people to get back + // to work. + +DEFINE_EXC_EXP (IEX_EXPORT, NullExc, BaseExc) // A pointer is inappropriately null. + +DEFINE_EXC_EXP (IEX_EXPORT, TypeExc, BaseExc) // An object is an inappropriate type, + // i.e. a dynamnic_cast failed. + + +//---------------------------------------------------------------------- +// Stack-tracing support: +// +// setStackTracer(st) +// +// installs a stack-tracing routine, st, which will be called from +// class BaseExc's constructor every time an exception derived from +// BaseExc is thrown. The stack-tracing routine should return a +// string that contains a printable representation of the program's +// current call stack. This string will be stored in the BaseExc +// object; the string is accesible via the BaseExc::stackTrace() +// method. +// +// setStackTracer(0) +// +// removes the current stack tracing routine. When an exception +// derived from BaseExc is thrown, the stack trace string stored +// in the BaseExc object will be empty. +// +// stackTracer() +// +// returns a pointer to the current stack-tracing routine, or 0 +// if there is no current stack stack-tracing routine. +// +//---------------------------------------------------------------------- + +typedef std::string (* StackTracer) (); + +IEX_EXPORT void setStackTracer (StackTracer stackTracer); +IEX_EXPORT StackTracer stackTracer (); + + +//----------------- +// Inline functions +//----------------- + +inline BaseExc & +BaseExc::operator = (std::stringstream &s) +{ + return assign (s); +} + + +inline BaseExc & +BaseExc::operator += (std::stringstream &s) +{ + return append (s); +} + + +inline BaseExc & +BaseExc::assign (const char *s) +{ + std::string::assign(s); + return *this; +} + + +inline BaseExc & +BaseExc::operator = (const char *s) +{ + return assign(s); +} + + +inline BaseExc & +BaseExc::append (const char *s) +{ + std::string::append(s); + return *this; +} + + +inline BaseExc & +BaseExc::operator += (const char *s) +{ + return append(s); +} + + +inline const std::string & +BaseExc::stackTrace () const +{ + return _stackTrace; +} + + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IEXBASEEXC_H diff --git a/OpenEXR/include/OpenEXR/IexErrnoExc.h b/OpenEXR/include/OpenEXR/IexErrnoExc.h new file mode 100644 index 0000000..027c7a4 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexErrnoExc.h @@ -0,0 +1,208 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXERRNOEXC_H +#define INCLUDED_IEXERRNOEXC_H + +//---------------------------------------------------------------- +// +// Exceptions which correspond to "errno" error codes. +// +//---------------------------------------------------------------- + +#include "IexBaseExc.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + +DEFINE_EXC (EpermExc, ErrnoExc) +DEFINE_EXC (EnoentExc, ErrnoExc) +DEFINE_EXC (EsrchExc, ErrnoExc) +DEFINE_EXC (EintrExc, ErrnoExc) +DEFINE_EXC (EioExc, ErrnoExc) +DEFINE_EXC (EnxioExc, ErrnoExc) +DEFINE_EXC (E2bigExc, ErrnoExc) +DEFINE_EXC (EnoexecExc, ErrnoExc) +DEFINE_EXC (EbadfExc, ErrnoExc) +DEFINE_EXC (EchildExc, ErrnoExc) +DEFINE_EXC (EagainExc, ErrnoExc) +DEFINE_EXC (EnomemExc, ErrnoExc) +DEFINE_EXC (EaccesExc, ErrnoExc) +DEFINE_EXC (EfaultExc, ErrnoExc) +DEFINE_EXC (EnotblkExc, ErrnoExc) +DEFINE_EXC (EbusyExc, ErrnoExc) +DEFINE_EXC (EexistExc, ErrnoExc) +DEFINE_EXC (ExdevExc, ErrnoExc) +DEFINE_EXC (EnodevExc, ErrnoExc) +DEFINE_EXC (EnotdirExc, ErrnoExc) +DEFINE_EXC (EisdirExc, ErrnoExc) +DEFINE_EXC (EinvalExc, ErrnoExc) +DEFINE_EXC (EnfileExc, ErrnoExc) +DEFINE_EXC (EmfileExc, ErrnoExc) +DEFINE_EXC (EnottyExc, ErrnoExc) +DEFINE_EXC (EtxtbsyExc, ErrnoExc) +DEFINE_EXC (EfbigExc, ErrnoExc) +DEFINE_EXC (EnospcExc, ErrnoExc) +DEFINE_EXC (EspipeExc, ErrnoExc) +DEFINE_EXC (ErofsExc, ErrnoExc) +DEFINE_EXC (EmlinkExc, ErrnoExc) +DEFINE_EXC (EpipeExc, ErrnoExc) +DEFINE_EXC (EdomExc, ErrnoExc) +DEFINE_EXC (ErangeExc, ErrnoExc) +DEFINE_EXC (EnomsgExc, ErrnoExc) +DEFINE_EXC (EidrmExc, ErrnoExc) +DEFINE_EXC (EchrngExc, ErrnoExc) +DEFINE_EXC (El2nsyncExc, ErrnoExc) +DEFINE_EXC (El3hltExc, ErrnoExc) +DEFINE_EXC (El3rstExc, ErrnoExc) +DEFINE_EXC (ElnrngExc, ErrnoExc) +DEFINE_EXC (EunatchExc, ErrnoExc) +DEFINE_EXC (EnocsiExc, ErrnoExc) +DEFINE_EXC (El2hltExc, ErrnoExc) +DEFINE_EXC (EdeadlkExc, ErrnoExc) +DEFINE_EXC (EnolckExc, ErrnoExc) +DEFINE_EXC (EbadeExc, ErrnoExc) +DEFINE_EXC (EbadrExc, ErrnoExc) +DEFINE_EXC (ExfullExc, ErrnoExc) +DEFINE_EXC (EnoanoExc, ErrnoExc) +DEFINE_EXC (EbadrqcExc, ErrnoExc) +DEFINE_EXC (EbadsltExc, ErrnoExc) +DEFINE_EXC (EdeadlockExc, ErrnoExc) +DEFINE_EXC (EbfontExc, ErrnoExc) +DEFINE_EXC (EnostrExc, ErrnoExc) +DEFINE_EXC (EnodataExc, ErrnoExc) +DEFINE_EXC (EtimeExc, ErrnoExc) +DEFINE_EXC (EnosrExc, ErrnoExc) +DEFINE_EXC (EnonetExc, ErrnoExc) +DEFINE_EXC (EnopkgExc, ErrnoExc) +DEFINE_EXC (EremoteExc, ErrnoExc) +DEFINE_EXC (EnolinkExc, ErrnoExc) +DEFINE_EXC (EadvExc, ErrnoExc) +DEFINE_EXC (EsrmntExc, ErrnoExc) +DEFINE_EXC (EcommExc, ErrnoExc) +DEFINE_EXC (EprotoExc, ErrnoExc) +DEFINE_EXC (EmultihopExc, ErrnoExc) +DEFINE_EXC (EbadmsgExc, ErrnoExc) +DEFINE_EXC (EnametoolongExc, ErrnoExc) +DEFINE_EXC (EoverflowExc, ErrnoExc) +DEFINE_EXC (EnotuniqExc, ErrnoExc) +DEFINE_EXC (EbadfdExc, ErrnoExc) +DEFINE_EXC (EremchgExc, ErrnoExc) +DEFINE_EXC (ElibaccExc, ErrnoExc) +DEFINE_EXC (ElibbadExc, ErrnoExc) +DEFINE_EXC (ElibscnExc, ErrnoExc) +DEFINE_EXC (ElibmaxExc, ErrnoExc) +DEFINE_EXC (ElibexecExc, ErrnoExc) +DEFINE_EXC (EilseqExc, ErrnoExc) +DEFINE_EXC (EnosysExc, ErrnoExc) +DEFINE_EXC (EloopExc, ErrnoExc) +DEFINE_EXC (ErestartExc, ErrnoExc) +DEFINE_EXC (EstrpipeExc, ErrnoExc) +DEFINE_EXC (EnotemptyExc, ErrnoExc) +DEFINE_EXC (EusersExc, ErrnoExc) +DEFINE_EXC (EnotsockExc, ErrnoExc) +DEFINE_EXC (EdestaddrreqExc, ErrnoExc) +DEFINE_EXC (EmsgsizeExc, ErrnoExc) +DEFINE_EXC (EprototypeExc, ErrnoExc) +DEFINE_EXC (EnoprotooptExc, ErrnoExc) +DEFINE_EXC (EprotonosupportExc, ErrnoExc) +DEFINE_EXC (EsocktnosupportExc, ErrnoExc) +DEFINE_EXC (EopnotsuppExc, ErrnoExc) +DEFINE_EXC (EpfnosupportExc, ErrnoExc) +DEFINE_EXC (EafnosupportExc, ErrnoExc) +DEFINE_EXC (EaddrinuseExc, ErrnoExc) +DEFINE_EXC (EaddrnotavailExc, ErrnoExc) +DEFINE_EXC (EnetdownExc, ErrnoExc) +DEFINE_EXC (EnetunreachExc, ErrnoExc) +DEFINE_EXC (EnetresetExc, ErrnoExc) +DEFINE_EXC (EconnabortedExc, ErrnoExc) +DEFINE_EXC (EconnresetExc, ErrnoExc) +DEFINE_EXC (EnobufsExc, ErrnoExc) +DEFINE_EXC (EisconnExc, ErrnoExc) +DEFINE_EXC (EnotconnExc, ErrnoExc) +DEFINE_EXC (EshutdownExc, ErrnoExc) +DEFINE_EXC (EtoomanyrefsExc, ErrnoExc) +DEFINE_EXC (EtimedoutExc, ErrnoExc) +DEFINE_EXC (EconnrefusedExc, ErrnoExc) +DEFINE_EXC (EhostdownExc, ErrnoExc) +DEFINE_EXC (EhostunreachExc, ErrnoExc) +DEFINE_EXC (EalreadyExc, ErrnoExc) +DEFINE_EXC (EinprogressExc, ErrnoExc) +DEFINE_EXC (EstaleExc, ErrnoExc) +DEFINE_EXC (EioresidExc, ErrnoExc) +DEFINE_EXC (EucleanExc, ErrnoExc) +DEFINE_EXC (EnotnamExc, ErrnoExc) +DEFINE_EXC (EnavailExc, ErrnoExc) +DEFINE_EXC (EisnamExc, ErrnoExc) +DEFINE_EXC (EremoteioExc, ErrnoExc) +DEFINE_EXC (EinitExc, ErrnoExc) +DEFINE_EXC (EremdevExc, ErrnoExc) +DEFINE_EXC (EcanceledExc, ErrnoExc) +DEFINE_EXC (EnolimfileExc, ErrnoExc) +DEFINE_EXC (EproclimExc, ErrnoExc) +DEFINE_EXC (EdisjointExc, ErrnoExc) +DEFINE_EXC (EnologinExc, ErrnoExc) +DEFINE_EXC (EloginlimExc, ErrnoExc) +DEFINE_EXC (EgrouploopExc, ErrnoExc) +DEFINE_EXC (EnoattachExc, ErrnoExc) +DEFINE_EXC (EnotsupExc, ErrnoExc) +DEFINE_EXC (EnoattrExc, ErrnoExc) +DEFINE_EXC (EdircorruptedExc, ErrnoExc) +DEFINE_EXC (EdquotExc, ErrnoExc) +DEFINE_EXC (EnfsremoteExc, ErrnoExc) +DEFINE_EXC (EcontrollerExc, ErrnoExc) +DEFINE_EXC (EnotcontrollerExc, ErrnoExc) +DEFINE_EXC (EenqueuedExc, ErrnoExc) +DEFINE_EXC (EnotenqueuedExc, ErrnoExc) +DEFINE_EXC (EjoinedExc, ErrnoExc) +DEFINE_EXC (EnotjoinedExc, ErrnoExc) +DEFINE_EXC (EnoprocExc, ErrnoExc) +DEFINE_EXC (EmustrunExc, ErrnoExc) +DEFINE_EXC (EnotstoppedExc, ErrnoExc) +DEFINE_EXC (EclockcpuExc, ErrnoExc) +DEFINE_EXC (EinvalstateExc, ErrnoExc) +DEFINE_EXC (EnoexistExc, ErrnoExc) +DEFINE_EXC (EendofminorExc, ErrnoExc) +DEFINE_EXC (EbufsizeExc, ErrnoExc) +DEFINE_EXC (EemptyExc, ErrnoExc) +DEFINE_EXC (EnointrgroupExc, ErrnoExc) +DEFINE_EXC (EinvalmodeExc, ErrnoExc) +DEFINE_EXC (EcantextentExc, ErrnoExc) +DEFINE_EXC (EinvaltimeExc, ErrnoExc) +DEFINE_EXC (EdestroyedExc, ErrnoExc) + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/IexExport.h b/OpenEXR/include/OpenEXR/IexExport.h new file mode 100644 index 0000000..270c1cf --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexExport.h @@ -0,0 +1,51 @@ +#ifndef IEXEXPORT_H +#define IEXEXPORT_H + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(IEX_EXPORTS) + #define IEX_EXPORT __declspec(dllexport) + #else + #define IEX_EXPORT __declspec(dllimport) + #endif + #define IEX_EXPORT_CONST +#else + #define IEX_EXPORT + #define IEX_EXPORT_CONST const +#endif + +#endif // #ifndef IEXEXPORT_H + diff --git a/OpenEXR/include/OpenEXR/IexForward.h b/OpenEXR/include/OpenEXR/IexForward.h new file mode 100644 index 0000000..743771c --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexForward.h @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXFORWARD_H +#define INCLUDED_IEXFORWARD_H + +#include "IexNamespace.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Base exceptions. +// + +class BaseExc; +class ArgExc; +class LogicExc; +class InputExc; +class IoExc; +class MathExc; +class ErrnoExc; +class NoImplExc; +class NullExc; +class TypeExc; + +// +// Math exceptions. +// + +class OverflowExc; +class UnderflowExc; +class DivzeroExc; +class InexactExc; +class InvalidFpOpExc; + +// +// Errno exceptions. +// + +class EpermExc; +class EnoentExc; +class EsrchExc; +class EintrExc; +class EioExc; +class EnxioExc; +class E2bigExc; +class EnoexecExc; +class EbadfExc; +class EchildExc; +class EagainExc; +class EnomemExc; +class EaccesExc; +class EfaultExc; +class EnotblkExc; +class EbusyExc; +class EexistExc; +class ExdevExc; +class EnodevExc; +class EnotdirExc; +class EisdirExc; +class EinvalExc; +class EnfileExc; +class EmfileExc; +class EnottyExc; +class EtxtbsyExc; +class EfbigExc; +class EnospcExc; +class EspipeExc; +class ErofsExc; +class EmlinkExc; +class EpipeExc; +class EdomExc; +class ErangeExc; +class EnomsgExc; +class EidrmExc; +class EchrngExc; +class El2nsyncExc; +class El3hltExc; +class El3rstExc; +class ElnrngExc; +class EunatchExc; +class EnocsiExc; +class El2hltExc; +class EdeadlkExc; +class EnolckExc; +class EbadeExc; +class EbadrExc; +class ExfullExc; +class EnoanoExc; +class EbadrqcExc; +class EbadsltExc; +class EdeadlockExc; +class EbfontExc; +class EnostrExc; +class EnodataExc; +class EtimeExc; +class EnosrExc; +class EnonetExc; +class EnopkgExc; +class EremoteExc; +class EnolinkExc; +class EadvExc; +class EsrmntExc; +class EcommExc; +class EprotoExc; +class EmultihopExc; +class EbadmsgExc; +class EnametoolongExc; +class EoverflowExc; +class EnotuniqExc; +class EbadfdExc; +class EremchgExc; +class ElibaccExc; +class ElibbadExc; +class ElibscnExc; +class ElibmaxExc; +class ElibexecExc; +class EilseqExc; +class EnosysExc; +class EloopExc; +class ErestartExc; +class EstrpipeExc; +class EnotemptyExc; +class EusersExc; +class EnotsockExc; +class EdestaddrreqExc; +class EmsgsizeExc; +class EprototypeExc; +class EnoprotooptExc; +class EprotonosupportExc; +class EsocktnosupportExc; +class EopnotsuppExc; +class EpfnosupportExc; +class EafnosupportExc; +class EaddrinuseExc; +class EaddrnotavailExc; +class EnetdownExc; +class EnetunreachExc; +class EnetresetExc; +class EconnabortedExc; +class EconnresetExc; +class EnobufsExc; +class EisconnExc; +class EnotconnExc; +class EshutdownExc; +class EtoomanyrefsExc; +class EtimedoutExc; +class EconnrefusedExc; +class EhostdownExc; +class EhostunreachExc; +class EalreadyExc; +class EinprogressExc; +class EstaleExc; +class EioresidExc; +class EucleanExc; +class EnotnamExc; +class EnavailExc; +class EisnamExc; +class EremoteioExc; +class EinitExc; +class EremdevExc; +class EcanceledExc; +class EnolimfileExc; +class EproclimExc; +class EdisjointExc; +class EnologinExc; +class EloginlimExc; +class EgrouploopExc; +class EnoattachExc; +class EnotsupExc; +class EnoattrExc; +class EdircorruptedExc; +class EdquotExc; +class EnfsremoteExc; +class EcontrollerExc; +class EnotcontrollerExc; +class EenqueuedExc; +class EnotenqueuedExc; +class EjoinedExc; +class EnotjoinedExc; +class EnoprocExc; +class EmustrunExc; +class EnotstoppedExc; +class EclockcpuExc; +class EinvalstateExc; +class EnoexistExc; +class EendofminorExc; +class EbufsizeExc; +class EemptyExc; +class EnointrgroupExc; +class EinvalmodeExc; +class EcantextentExc; +class EinvaltimeExc; +class EdestroyedExc; + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IEXFORWARD_H diff --git a/OpenEXR/include/OpenEXR/IexMacros.h b/OpenEXR/include/OpenEXR/IexMacros.h new file mode 100644 index 0000000..18d37bd --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexMacros.h @@ -0,0 +1,170 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXMACROS_H +#define INCLUDED_IEXMACROS_H + +//-------------------------------------------------------------------- +// +// Macros which make throwing exceptions more convenient +// +//-------------------------------------------------------------------- + +#include + + +//---------------------------------------------------------------------------- +// A macro to throw exceptions whose text is assembled using stringstreams. +// +// Example: +// +// THROW (InputExc, "Syntax error in line " << line ", " << file << "."); +// +//---------------------------------------------------------------------------- + +#include "IexExport.h" +#include "IexForward.h" + +IEX_EXPORT void iex_debugTrap(); + +#define THROW(type, text) \ + do \ + { \ + iex_debugTrap(); \ + std::stringstream s; \ + s << text; \ + throw type (s); \ + } \ + while (0) + + +//---------------------------------------------------------------------------- +// Macros to add to or to replace the text of an exception. +// The new text is assembled using stringstreams. +// +// Examples: +// +// Append to end of an exception's text: +// +// catch (BaseExc &e) +// { +// APPEND_EXC (e, " Directory " << name << " does not exist."); +// throw; +// } +// +// Replace an exception's text: +// +// catch (BaseExc &e) +// { +// REPLACE_EXC (e, "Directory " << name << " does not exist. " << e); +// throw; +// } +//---------------------------------------------------------------------------- + +#define APPEND_EXC(exc, text) \ + do \ + { \ + std::stringstream s; \ + s << text; \ + exc.append (s); \ + } \ + while (0) + +#define REPLACE_EXC(exc, text) \ + do \ + { \ + std::stringstream s; \ + s << text; \ + exc.assign (s); \ + } \ + while (0) + + +//------------------------------------------------------------- +// A macro to throw ErrnoExc exceptions whose text is assembled +// using stringstreams: +// +// Example: +// +// THROW_ERRNO ("Cannot open file " << name << " (%T)."); +// +//------------------------------------------------------------- + +#define THROW_ERRNO(text) \ + do \ + { \ + std::stringstream s; \ + s << text; \ + ::IEX_NAMESPACE::throwErrnoExc (s.str()); \ + } \ + while (0) + + +//------------------------------------------------------------- +// A macro to throw exceptions if an assertion is false. +// +// Example: +// +// ASSERT (ptr != 0, NullExc, "Null pointer" ); +// +//------------------------------------------------------------- + +#define ASSERT(assertion, type, text) \ + do \ + { \ + if( (assertion) == false ) \ + { \ + THROW( type, text ); \ + } \ + } \ + while (0) + +//------------------------------------------------------------- +// A macro to throw an IEX_NAMESPACE::LogicExc if an assertion is false, +// with the text composed from the source code file, line number, +// and assertion argument text. +// +// Example: +// +// LOGIC_ASSERT (i < n); +// +//------------------------------------------------------------- +#define LOGIC_ASSERT(assertion) \ + ASSERT(assertion, \ + IEX_NAMESPACE::LogicExc, \ + __FILE__ << "(" << __LINE__ << "): logical assertion failed: " << #assertion ) + +#endif diff --git a/OpenEXR/include/OpenEXR/IexMathExc.h b/OpenEXR/include/OpenEXR/IexMathExc.h new file mode 100644 index 0000000..795f500 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexMathExc.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXMATHEXC_H +#define INCLUDED_IEXMATHEXC_H + +#include "IexBaseExc.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + +//--------------------------------------------------------- +// Exception classess which correspond to specific floating +// point exceptions. +//--------------------------------------------------------- + +DEFINE_EXC (OverflowExc, MathExc) // Overflow +DEFINE_EXC (UnderflowExc, MathExc) // Underflow +DEFINE_EXC (DivzeroExc, MathExc) // Division by zero +DEFINE_EXC (InexactExc, MathExc) // Inexact result +DEFINE_EXC (InvalidFpOpExc, MathExc) // Invalid operation + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IEXMATHEXC_H diff --git a/OpenEXR/include/OpenEXR/IexMathFloatExc.h b/OpenEXR/include/OpenEXR/IexMathFloatExc.h new file mode 100644 index 0000000..825dba1 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexMathFloatExc.h @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXMATHFLOATEXC_H +#define INCLUDED_IEXMATHFLOATEXC_H + +#ifndef IEXMATH_EXPORT_H +#define IEXMATH_EXPORT_H + +#if defined(OPENEXR_DLL) + #if defined(IEX_EXPORTS) + #define IEXMATH_EXPORT __declspec(dllexport) + #else + #define IEXMATH_EXPORT __declspec(dllimport) + #endif + #define IEXMATH_EXPORT_CONST +#else + #define IEXMATH_EXPORT + #define IEXMATH_EXPORT_CONST const +#endif + +#endif + +#include "IexNamespace.h" +#include "IexMathExc.h" +//#include +#include "IexMathIeeeExc.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + + +//------------------------------------------------------------- +// Function mathExcOn() defines which floating point exceptions +// will be trapped and converted to C++ exceptions. +//------------------------------------------------------------- + +IEXMATH_EXPORT +void mathExcOn (int when = (IEEE_OVERFLOW | IEEE_DIVZERO | IEEE_INVALID)); + + +//---------------------------------------------------------------------- +// Function getMathExcOn() tells you for which floating point exceptions +// trapping and conversion to C++ exceptions is currently enabled. +//---------------------------------------------------------------------- + +IEXMATH_EXPORT +int getMathExcOn(); + + +//------------------------------------------------------------------------ +// A classs that temporarily sets floating point exception trapping +// and conversion, and later restores the previous settings. +// +// Example: +// +// float +// trickyComputation (float x) +// { +// MathExcOn meo (0); // temporarily disable floating +// // point exception trapping +// +// float result = ...; // computation which may cause +// // floating point exceptions +// +// return result; // destruction of meo restores +// } // the program's previous floating +// // point exception settings +//------------------------------------------------------------------------ + +class IEXMATH_EXPORT MathExcOn +{ + public: + + MathExcOn (int when) + : + _changed (false) + { + _saved = getMathExcOn(); + + if (_saved != when) + { + _changed = true; + mathExcOn (when); + } + } + + ~MathExcOn () + { + if (_changed) + mathExcOn (_saved); + } + + // It is possible for functions to set the exception registers + // yet not trigger a SIGFPE. Specifically, the implementation + // of pow(x, y) we're using can generates a NaN from a negative x + // and fractional y but a SIGFPE is not generated. + // This function examimes the exception registers and calls the + // fpHandler if those registers modulo the exception mask are set. + // It should be called wherever this class is commonly used where it has + // been found that certain floating point exceptions are not being thrown. + + void handleOutstandingExceptions(); + + private: + + bool _changed; + int _saved; +}; + + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/IexMathFpu.h b/OpenEXR/include/OpenEXR/IexMathFpu.h new file mode 100644 index 0000000..df2a3e5 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexMathFpu.h @@ -0,0 +1,91 @@ +#ifndef INCLUDED_IEXMATHFPU_H +#define INCLUDED_IEXMATHFPU_H + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 1997, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + + +//------------------------------------------------------------------------ +// +// Functions to control floating point exceptions. +// +//------------------------------------------------------------------------ + +#include "IexMathIeeeExc.h" +#include "IexNamespace.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + + +//----------------------------------------- +// setFpExceptions() defines which floating +// point exceptions cause SIGFPE signals. +//----------------------------------------- + +void setFpExceptions (int when = (IEEE_OVERFLOW | IEEE_DIVZERO | IEEE_INVALID)); + + +//---------------------------------------- +// fpExceptions() tells you which floating +// point exceptions cause SIGFPE signals. +//---------------------------------------- + +int fpExceptions (); + + +//------------------------------------------ +// setFpExceptionHandler() defines a handler +// that will be called when SIGFPE occurs. +//------------------------------------------ + +extern "C" typedef void (* FpExceptionHandler) (int type, const char explanation[]); + +void setFpExceptionHandler (FpExceptionHandler handler); + +// ----------------------------------------- +// handleExceptionsSetInRegisters() examines +// the exception registers and calls the +// floating point exception handler if the +// bits are set. This function exists to +// allow trapping of exception register states +// that can get set though no SIGFPE occurs. +// ----------------------------------------- + +void handleExceptionsSetInRegisters(); + + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/IexMathIeeeExc.h b/OpenEXR/include/OpenEXR/IexMathIeeeExc.h new file mode 100644 index 0000000..efadebe --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexMathIeeeExc.h @@ -0,0 +1,62 @@ +#ifndef INCLUDED_IEXMATHIEEE_EXC_H +#define INCLUDED_IEXMATHIEEE_EXC_H + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 1997, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + + +//--------------------------------------------------------------------------- +// +// Names for the loating point exceptions defined by IEEE standard 754 +// +//--------------------------------------------------------------------------- + +#include "IexNamespace.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + + +enum IeeeExcType +{ + IEEE_OVERFLOW = 1, + IEEE_UNDERFLOW = 2, + IEEE_DIVZERO = 4, + IEEE_INEXACT = 8, + IEEE_INVALID = 16 +}; + + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/IexNamespace.h b/OpenEXR/include/OpenEXR/IexNamespace.h new file mode 100644 index 0000000..bef1572 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexNamespace.h @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXNAMESPACE_H +#define INCLUDED_IEXNAMESPACE_H + +// +// The purpose of this file is to make it possible to specify an +// IEX_INTERNAL_NAMESPACE as a preprocessor definition and have all of the +// Iex symbols defined within that namespace rather than the standard +// Iex namespace. Those symbols are made available to client code through +// the IEX_NAMESPACE in addition to the IEX_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the IEX_NAMESPACE defaults to Iex +// and then "using namespace IEX_INTERNAL_NAMESPACE;" brings all of the +// declarations from the IEX_INTERNAL_NAMESPACE into the IEX_NAMESPACE. This +// means that client code can continue to use syntax like Iex::BaseExc, but +// at link time it will resolve to a mangled symbol based on the +// IEX_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of Iex and +// have it run alongside an older version in the same application, it is now +// possible to use an internal namespace to prevent collisions between the +// older versions of Iex symbols and the newer ones. To do this, the +// following could be defined at build time: +// +// IEX_INTERNAL_NAMESPACE = Iex_v2 +// +// This means that declarations inside Iex headers look like this (after the +// preprocessor has done its work): +// +// namespace Iex_v2 { +// ... +// class declarations +// ... +// } +// +// namespace Iex { +// using namespace Iex_v2; +// } +// + +// +// Open Source version of this file pulls in the IlmBaseConfig.h file +// for the configure time options. +// +#include "IlmBaseConfig.h" + +#ifndef IEX_NAMESPACE +#define IEX_NAMESPACE Iex +#endif + +#ifndef IEX_INTERNAL_NAMESPACE +#define IEX_INTERNAL_NAMESPACE IEX_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// IEX_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// IEX_NAMESPACE and pulls the internal symbols into the public namespace. +// + +namespace IEX_INTERNAL_NAMESPACE {} +namespace IEX_NAMESPACE { + using namespace IEX_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define IEX_INTERNAL_NAMESPACE_HEADER_ENTER namespace IEX_INTERNAL_NAMESPACE { +#define IEX_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define IEX_INTERNAL_NAMESPACE_SOURCE_ENTER namespace IEX_INTERNAL_NAMESPACE { +#define IEX_INTERNAL_NAMESPACE_SOURCE_EXIT } + +#endif // INCLUDED_IEXNAMESPACE_H diff --git a/OpenEXR/include/OpenEXR/IexThrowErrnoExc.h b/OpenEXR/include/OpenEXR/IexThrowErrnoExc.h new file mode 100644 index 0000000..224ed2b --- /dev/null +++ b/OpenEXR/include/OpenEXR/IexThrowErrnoExc.h @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IEXTHROWERRNOEXC_H +#define INCLUDED_IEXTHROWERRNOEXC_H + +//---------------------------------------------------------- +// +// A function which throws ExcErrno exceptions +// +//---------------------------------------------------------- + +#include "IexBaseExc.h" +#include "IexExport.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + + +//-------------------------------------------------------------------------- +// +// Function throwErrnoExc() throws an exception which corresponds to +// error code errnum. The exception text is initialized with a copy +// of the string passed to throwErrnoExc(), where all occurrences of +// "%T" have been replaced with the output of strerror(oserror()). +// +// Example: +// +// If opening file /tmp/output failed with an ENOENT error code, +// calling +// +// throwErrnoExc (); +// +// or +// +// throwErrnoExc ("%T."); +// +// will throw an EnoentExc whose text reads +// +// No such file or directory. +// +// More detailed messages can be assembled using stringstreams: +// +// std::stringstream s; +// s << "Cannot open file " << name << " (%T)."; +// throwErrnoExc (s); +// +// The resulting exception contains the following text: +// +// Cannot open file /tmp/output (No such file or directory). +// +// Alternatively, you may want to use the THROW_ERRNO macro defined +// in IexMacros.h: +// +// THROW_ERRNO ("Cannot open file " << name << " (%T).") +// +//-------------------------------------------------------------------------- + +IEX_EXPORT void throwErrnoExc(const std::string &txt, int errnum); +IEX_EXPORT void throwErrnoExc(const std::string &txt); +IEX_EXPORT void throwErrnoExc(); + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IEXTHROWERRNOEXC_H diff --git a/OpenEXR/include/OpenEXR/IlmBaseConfig.h b/OpenEXR/include/OpenEXR/IlmBaseConfig.h new file mode 100644 index 0000000..b626ede --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmBaseConfig.h @@ -0,0 +1,72 @@ +/* config/IlmBaseConfig.h. Generated from IlmBaseConfig.h.in by configure. */ +// +// Define and set to 1 if the target system has POSIX thread support +// and you want IlmBase to use it for multithreaded file I/O. +// + +#define HAVE_PTHREAD 1 + +// +// Define and set to 1 if the target system supports POSIX semaphores +// and you want OpenEXR to use them; otherwise, OpenEXR will use its +// own semaphore implementation. +// + +#define HAVE_POSIX_SEMAPHORES 1 + + +#define HAVE_UCONTEXT_H 1 + + +// +// Dealing with FPEs +// +#define ILMBASE_HAVE_CONTROL_REGISTER_SUPPORT 1 + + +// +// Define and set to 1 if the target system has support for large +// stack sizes. +// + +#define ILMBASE_HAVE_LARGE_STACK 1 + +// +// Current (internal) library namepace name and corresponding public +// client namespaces. +// +#define ILMBASE_INTERNAL_NAMESPACE_CUSTOM 1 +#define IMATH_INTERNAL_NAMESPACE Imath_2_2 +#define IEX_INTERNAL_NAMESPACE Iex_2_2 +#define ILMTHREAD_INTERNAL_NAMESPACE IlmThread_2_2 + +/* #undef ILMBASE_NAMESPACE_CUSTOM */ +#define IMATH_NAMESPACE Imath +#define IEX_NAMESPACE Iex +#define ILMTHREAD_NAMESPACE IlmThread + + +// +// Define and set to 1 if the target system has support for large +// stack sizes. +// + +#define ILMBASE_HAVE_LARGE_STACK 1 + + +// +// Version information +// +#define ILMBASE_VERSION_STRING "2.2.0" +#define ILMBASE_PACKAGE_STRING "IlmBase 2.2.0" + +#define ILMBASE_VERSION_MAJOR 2 +#define ILMBASE_VERSION_MINOR 2 +#define ILMBASE_VERSION_PATCH 0 + +// Version as a single hex number, e.g. 0x01000300 == 1.0.3 +#define ILMBASE_VERSION_HEX ((ILMBASE_VERSION_MAJOR << 24) | \ + (ILMBASE_VERSION_MINOR << 16) | \ + (ILMBASE_VERSION_PATCH << 8)) + + diff --git a/OpenEXR/include/OpenEXR/IlmThread.h b/OpenEXR/include/OpenEXR/IlmThread.h new file mode 100644 index 0000000..1f6d9e6 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThread.h @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_ILM_THREAD_H +#define INCLUDED_ILM_THREAD_H + +//----------------------------------------------------------------------------- +// +// class Thread +// +// Class Thread is a portable interface to a system-dependent thread +// primitive. In order to make a thread actually do something useful, +// you must derive a subclass from class Thread and implement the +// run() function. If the operating system supports threading then +// the run() function will be executed int a new thread. +// +// The actual creation of the thread is done by the start() routine +// which then calls the run() function. In general the start() +// routine should be called from the constructor of the derived class. +// +// The base-class thread destructor will join/destroy the thread. +// +// IMPORTANT: Due to the mechanisms that encapsulate the low-level +// threading primitives in a C++ class there is a race condition +// with code resembling the following: +// +// { +// WorkerThread myThread; +// } // myThread goes out of scope, is destroyed +// // and the thread is joined +// +// The race is between the parent thread joining the child thread +// in the destructor of myThread, and the run() function in the +// child thread. If the destructor gets executed first then run() +// will be called with an invalid "this" pointer. +// +// This issue can be fixed by using a Semaphore to keep track of +// whether the run() function has already been called. You can +// include a Semaphore member variable within your derived class +// which you post() on in the run() function, and wait() on in the +// destructor before the thread is joined. Alternatively you could +// do something like this: +// +// Semaphore runStarted; +// +// void WorkerThread::run () +// { +// runStarted.post() +// // do some work +// ... +// } +// +// { +// WorkerThread myThread; +// runStarted.wait (); // ensure that we have started +// // the run function +// } // myThread goes out of scope, is destroyed +// // and the thread is joined +// +//----------------------------------------------------------------------------- + +#include "IlmBaseConfig.h" +#include "IlmThreadExport.h" +#include "IlmThreadNamespace.h" + +#if defined _WIN32 || defined _WIN64 + #ifdef NOMINMAX + #undef NOMINMAX + #endif + #define NOMINMAX + #include + #include +#elif HAVE_PTHREAD + #include +#endif + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Query function to determine if the current platform supports +// threads AND this library was compiled with threading enabled. +// + +ILMTHREAD_EXPORT bool supportsThreads (); + + +class ILMTHREAD_EXPORT Thread +{ + public: + + Thread (); + virtual ~Thread (); + + void start (); + virtual void run () = 0; + + private: + + #if defined _WIN32 || defined _WIN64 + HANDLE _thread; + #elif HAVE_PTHREAD + pthread_t _thread; + #endif + + void operator = (const Thread& t); // not implemented + Thread (const Thread& t); // not implemented +}; + + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_ILM_THREAD_H diff --git a/OpenEXR/include/OpenEXR/IlmThreadExport.h b/OpenEXR/include/OpenEXR/IlmThreadExport.h new file mode 100644 index 0000000..96d2200 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThreadExport.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(ILMTHREAD_EXPORTS) + #define ILMTHREAD_EXPORT __declspec(dllexport) + #define ILMTHREAD_EXPORT_CONST extern __declspec(dllexport) + #else + #define ILMTHREAD_EXPORT __declspec(dllimport) + #define ILMTHREAD_EXPORT_CONST extern __declspec(dllimport) + #endif +#else + #define ILMTHREAD_EXPORT + #define ILMTHREAD_EXPORT_CONST extern const +#endif diff --git a/OpenEXR/include/OpenEXR/IlmThreadForward.h b/OpenEXR/include/OpenEXR/IlmThreadForward.h new file mode 100644 index 0000000..b52bdac --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThreadForward.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_ILMTHREADFORWARD_H +#define INCLUDED_ILMTHREADFORWARD_H + +#include "IlmThreadNamespace.h" + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER + +class Thread; +class Mutex; +class Lock; +class ThreadPool; +class Task; +class TaskGroup; +class Semaphore; + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_ILMTHREADFORWARD_H diff --git a/OpenEXR/include/OpenEXR/IlmThreadMutex.h b/OpenEXR/include/OpenEXR/IlmThreadMutex.h new file mode 100644 index 0000000..dd42067 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThreadMutex.h @@ -0,0 +1,160 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_ILM_THREAD_MUTEX_H +#define INCLUDED_ILM_THREAD_MUTEX_H + +//----------------------------------------------------------------------------- +// +// class Mutex, class Lock +// +// Class Mutex is a wrapper for a system-dependent mutual exclusion +// mechanism. Actual locking and unlocking of a Mutex object must +// be performed using an instance of a Lock (defined below). +// +// Class lock provides safe locking and unlocking of mutexes even in +// the presence of C++ exceptions. Constructing a Lock object locks +// the mutex; destroying the Lock unlocks the mutex. +// +// Lock objects are not themselves thread-safe. You should never +// share a Lock object among multiple threads. +// +// Typical usage: +// +// Mutex mtx; // Create a Mutex object that is visible +// //to multiple threads +// +// ... // create some threads +// +// // Then, within each thread, construct a critical section like so: +// +// { +// Lock lock (mtx); // Lock constructor locks the mutex +// ... // do some computation on shared data +// } // leaving the block unlocks the mutex +// +//----------------------------------------------------------------------------- + +#include "IlmThreadExport.h" +#include "IlmBaseConfig.h" +#include "IlmThreadNamespace.h" + +#if defined _WIN32 || defined _WIN64 + #ifdef NOMINMAX + #undef NOMINMAX + #endif + #define NOMINMAX + #include +#elif HAVE_PTHREAD + #include +#endif + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER + +class Lock; + + +class ILMTHREAD_EXPORT Mutex +{ + public: + + Mutex (); + virtual ~Mutex (); + + private: + + void lock () const; + void unlock () const; + + #if defined _WIN32 || defined _WIN64 + mutable CRITICAL_SECTION _mutex; + #elif HAVE_PTHREAD + mutable pthread_mutex_t _mutex; + #endif + + void operator = (const Mutex& M); // not implemented + Mutex (const Mutex& M); // not implemented + + friend class Lock; +}; + + +class ILMTHREAD_EXPORT Lock +{ + public: + + Lock (const Mutex& m, bool autoLock = true): + _mutex (m), + _locked (false) + { + if (autoLock) + { + _mutex.lock(); + _locked = true; + } + } + + ~Lock () + { + if (_locked) + _mutex.unlock(); + } + + void acquire () + { + _mutex.lock(); + _locked = true; + } + + void release () + { + _mutex.unlock(); + _locked = false; + } + + bool locked () + { + return _locked; + } + + private: + + const Mutex & _mutex; + bool _locked; +}; + + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_ILM_THREAD_MUTEX_H diff --git a/OpenEXR/include/OpenEXR/IlmThreadNamespace.h b/OpenEXR/include/OpenEXR/IlmThreadNamespace.h new file mode 100644 index 0000000..a412997 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThreadNamespace.h @@ -0,0 +1,114 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_ILMTHREADNAMESPACE_H +#define INCLUDED_ILMTHREADNAMESPACE_H + +// +// The purpose of this file is to make it possible to specify an +// ILMTHREAD_INTERNAL_NAMESPACE as a preprocessor definition and have all of +// the IlmThread symbols defined within that namespace rather than the +// standard IlmThread namespace. Those symbols are made available to client +// code through the ILMTHREAD_NAMESPACE in addition to the +// ILMTHREAD_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the ILMTHREAD_NAMESPACE defaults to +// IlmThread and then "using namespace ILMTHREAD_INTERNAL_NAMESPACE;" brings +// all of the declarations from the ILMTHREAD_INTERNAL_NAMESPACE into the +// ILMTHREAD_NAMESPACE. This means that client code can continue to use +// syntax like IlmThread::Thread, but at link time it will resolve to a +// mangled symbol based on the ILMTHREAD_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of IlmThread +// and have it run alongside an older version in the same application, it is +// now possible to use an internal namespace to prevent collisions between +// the older versions of IlmThread symbols and the newer ones. To do this, +// the following could be defined at build time: +// +// ILMTHREAD_INTERNAL_NAMESPACE = IlmThread_v2 +// +// This means that declarations inside IlmThread headers look like this +// (after the preprocessor has done its work): +// +// namespace IlmThread_v2 { +// ... +// class declarations +// ... +// } +// +// namespace IlmThread { +// using namespace IlmThread_v2; +// } +// + +// +// Open Source version of this file pulls in the IlmBaseConfig.h file +// for the configure time options. +// +#include "IlmBaseConfig.h" + +#ifndef ILMTHREAD_NAMESPACE +#define ILMTHREAD_NAMESPACE IlmThread +#endif + +#ifndef ILMTHREAD_INTERNAL_NAMESPACE +#define ILMTHREAD_INTERNAL_NAMESPACE ILMTHREAD_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// ILMTHREAD_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// ILMTHREAD_NAMESPACE and pulls the internal symbols into the public +// namespace. +// + +namespace ILMTHREAD_INTERNAL_NAMESPACE {} +namespace ILMTHREAD_NAMESPACE { + using namespace ILMTHREAD_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER namespace ILMTHREAD_INTERNAL_NAMESPACE { +#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER namespace ILMTHREAD_INTERNAL_NAMESPACE { +#define ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT } + +#endif // INCLUDED_ILMTHREADNAMESPACE_H diff --git a/OpenEXR/include/OpenEXR/IlmThreadPool.h b/OpenEXR/include/OpenEXR/IlmThreadPool.h new file mode 100644 index 0000000..d436d4e --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThreadPool.h @@ -0,0 +1,160 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_ILM_THREAD_POOL_H +#define INCLUDED_ILM_THREAD_POOL_H + + +//----------------------------------------------------------------------------- +// +// class Task, class ThreadPool, class TaskGroup +// +// Class ThreadPool manages a set of worker threads and accepts +// tasks for processing. Tasks added to the thread pool are +// executed concurrently by the worker threads. +// +// Class Task provides an abstract interface for a task which +// a ThreadPool works on. Derived classes need to implement the +// execute() function which performs the actual task. +// +// Class TaskGroup allows synchronization on the completion of a set +// of tasks. Every task that is added to a ThreadPool belongs to a +// single TaskGroup. The destructor of the TaskGroup waits for all +// tasks in the group to finish. +// +// Note: if you plan to use the ThreadPool interface in your own +// applications note that the implementation of the ThreadPool calls +// operator delete on tasks as they complete. If you define a custom +// operator new for your tasks, for instance to use a custom heap, +// then you must also write an appropriate operator delete. +// +//----------------------------------------------------------------------------- + +#include "IlmThreadNamespace.h" +#include "IlmThreadExport.h" + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER + +class TaskGroup; +class Task; + + +class ILMTHREAD_EXPORT ThreadPool +{ + public: + + //------------------------------------------------------- + // Constructor -- creates numThreads worker threads which + // wait until a task is available. + //------------------------------------------------------- + + ThreadPool (unsigned numThreads = 0); + + + //----------------------------------------------------------- + // Destructor -- waits for all tasks to complete, joins all + // the threads to the calling thread, and then destroys them. + //----------------------------------------------------------- + + virtual ~ThreadPool (); + + + //-------------------------------------------------------- + // Query and set the number of worker threads in the pool. + // + // Warning: never call setNumThreads from within a worker + // thread as this will almost certainly cause a deadlock + // or crash. + //-------------------------------------------------------- + + int numThreads () const; + void setNumThreads (int count); + + + //------------------------------------------------------------ + // Add a task for processing. The ThreadPool can handle any + // number of tasks regardless of the number of worker threads. + // The tasks are first added onto a queue, and are executed + // by threads as they become available, in FIFO order. + //------------------------------------------------------------ + + void addTask (Task* task); + + + //------------------------------------------- + // Access functions for the global threadpool + //------------------------------------------- + + static ThreadPool& globalThreadPool (); + static void addGlobalTask (Task* task); + + struct Data; + + protected: + + Data * _data; +}; + + +class ILMTHREAD_EXPORT Task +{ + public: + + Task (TaskGroup* g); + virtual ~Task (); + + virtual void execute () = 0; + TaskGroup * group(); + + protected: + + TaskGroup * _group; +}; + + +class ILMTHREAD_EXPORT TaskGroup +{ + public: + + TaskGroup(); + ~TaskGroup(); + + struct Data; + Data* const _data; +}; + + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_ILM_THREAD_POOL_H diff --git a/OpenEXR/include/OpenEXR/IlmThreadSemaphore.h b/OpenEXR/include/OpenEXR/IlmThreadSemaphore.h new file mode 100644 index 0000000..46cfd02 --- /dev/null +++ b/OpenEXR/include/OpenEXR/IlmThreadSemaphore.h @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_ILM_THREAD_SEMAPHORE_H +#define INCLUDED_ILM_THREAD_SEMAPHORE_H + +//----------------------------------------------------------------------------- +// +// class Semaphore -- a wrapper class for +// system-dependent counting semaphores +// +//----------------------------------------------------------------------------- + +#include "IlmBaseConfig.h" +#include "IlmThreadExport.h" +#include "IlmThreadNamespace.h" + +#if defined _WIN32 || defined _WIN64 + #ifdef NOMINMAX + #undef NOMINMAX + #endif + #define NOMINMAX + #include +#elif HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES + #include +#elif HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES + #include +#endif + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER + + +class ILMTHREAD_EXPORT Semaphore +{ + public: + + Semaphore (unsigned int value = 0); + virtual ~Semaphore(); + + void wait(); + bool tryWait(); + void post(); + int value() const; + + private: + + #if defined _WIN32 || defined _WIN64 + + mutable HANDLE _semaphore; + + #elif HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES + + // + // If the platform has Posix threads but no semapohores, + // then we implement them ourselves using condition variables + // + + struct sema_t + { + unsigned int count; + unsigned long numWaiting; + pthread_mutex_t mutex; + pthread_cond_t nonZero; + }; + + mutable sema_t _semaphore; + + #elif HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES + + mutable sem_t _semaphore; + + #endif + + void operator = (const Semaphore& s); // not implemented + Semaphore (const Semaphore& s); // not implemented +}; + + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_ILM_THREAD_SEMAPHORE_H diff --git a/OpenEXR/include/OpenEXR/ImathBox.h b/OpenEXR/include/OpenEXR/ImathBox.h new file mode 100644 index 0000000..45165ff --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathBox.h @@ -0,0 +1,849 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHBOX_H +#define INCLUDED_IMATHBOX_H + +//------------------------------------------------------------------- +// +// class Imath::Box +// -------------------------------- +// +// This class imposes the following requirements on its +// parameter class: +// +// 1) The class T must implement these operators: +// + - < > <= >= = +// with the signature (T,T) and the expected +// return values for a numeric type. +// +// 2) The class T must implement operator= +// with the signature (T,float and/or double) +// +// 3) The class T must have a constructor which takes +// a float (and/or double) for use in initializing the box. +// +// 4) The class T must have a function T::dimensions() +// which returns the number of dimensions in the class +// (since its assumed its a vector) -- preferably, this +// returns a constant expression. +// +//------------------------------------------------------------------- + +#include "ImathVec.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +class Box +{ + public: + + //------------------------- + // Data Members are public + //------------------------- + + T min; + T max; + + //----------------------------------------------------- + // Constructors - an "empty" box is created by default + //----------------------------------------------------- + + Box (); + Box (const T &point); + Box (const T &minT, const T &maxT); + + //-------------------- + // Operators: ==, != + //-------------------- + + bool operator == (const Box &src) const; + bool operator != (const Box &src) const; + + //------------------ + // Box manipulation + //------------------ + + void makeEmpty (); + void extendBy (const T &point); + void extendBy (const Box &box); + void makeInfinite (); + + //--------------------------------------------------- + // Query functions - these compute results each time + //--------------------------------------------------- + + T size () const; + T center () const; + bool intersects (const T &point) const; + bool intersects (const Box &box) const; + + unsigned int majorAxis () const; + + //---------------- + // Classification + //---------------- + + bool isEmpty () const; + bool hasVolume () const; + bool isInfinite () const; +}; + + +//-------------------- +// Convenient typedefs +//-------------------- + +typedef Box Box2s; +typedef Box Box2i; +typedef Box Box2f; +typedef Box Box2d; +typedef Box Box3s; +typedef Box Box3i; +typedef Box Box3f; +typedef Box Box3d; + + +//---------------- +// Implementation + + +template +inline Box::Box() +{ + makeEmpty(); +} + + +template +inline Box::Box (const T &point) +{ + min = point; + max = point; +} + + +template +inline Box::Box (const T &minT, const T &maxT) +{ + min = minT; + max = maxT; +} + + +template +inline bool +Box::operator == (const Box &src) const +{ + return (min == src.min && max == src.max); +} + + +template +inline bool +Box::operator != (const Box &src) const +{ + return (min != src.min || max != src.max); +} + + +template +inline void Box::makeEmpty() +{ + min = T(T::baseTypeMax()); + max = T(T::baseTypeMin()); +} + +template +inline void Box::makeInfinite() +{ + min = T(T::baseTypeMin()); + max = T(T::baseTypeMax()); +} + + +template +inline void +Box::extendBy(const T &point) +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (point[i] < min[i]) + min[i] = point[i]; + + if (point[i] > max[i]) + max[i] = point[i]; + } +} + + +template +inline void +Box::extendBy(const Box &box) +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (box.min[i] < min[i]) + min[i] = box.min[i]; + + if (box.max[i] > max[i]) + max[i] = box.max[i]; + } +} + + +template +inline bool +Box::intersects(const T &point) const +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (point[i] < min[i] || point[i] > max[i]) + return false; + } + + return true; +} + + +template +inline bool +Box::intersects(const Box &box) const +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (box.max[i] < min[i] || box.min[i] > max[i]) + return false; + } + + return true; +} + + +template +inline T +Box::size() const +{ + if (isEmpty()) + return T (0); + + return max - min; +} + + +template +inline T +Box::center() const +{ + return (max + min) / 2; +} + + +template +inline bool +Box::isEmpty() const +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (max[i] < min[i]) + return true; + } + + return false; +} + +template +inline bool +Box::isInfinite() const +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (min[i] != T::baseTypeMin() || max[i] != T::baseTypeMax()) + return false; + } + + return true; +} + + +template +inline bool +Box::hasVolume() const +{ + for (unsigned int i = 0; i < min.dimensions(); i++) + { + if (max[i] <= min[i]) + return false; + } + + return true; +} + + +template +inline unsigned int +Box::majorAxis() const +{ + unsigned int major = 0; + T s = size(); + + for (unsigned int i = 1; i < min.dimensions(); i++) + { + if (s[i] > s[major]) + major = i; + } + + return major; +} + +//------------------------------------------------------------------- +// +// Partial class specializations for Imath::Vec2 and Imath::Vec3 +// +//------------------------------------------------------------------- + +template class Box; + +template +class Box > +{ + public: + + //------------------------- + // Data Members are public + //------------------------- + + Vec2 min; + Vec2 max; + + //----------------------------------------------------- + // Constructors - an "empty" box is created by default + //----------------------------------------------------- + + Box(); + Box (const Vec2 &point); + Box (const Vec2 &minT, const Vec2 &maxT); + + //-------------------- + // Operators: ==, != + //-------------------- + + bool operator == (const Box > &src) const; + bool operator != (const Box > &src) const; + + //------------------ + // Box manipulation + //------------------ + + void makeEmpty(); + void extendBy (const Vec2 &point); + void extendBy (const Box > &box); + void makeInfinite(); + + //--------------------------------------------------- + // Query functions - these compute results each time + //--------------------------------------------------- + + Vec2 size() const; + Vec2 center() const; + bool intersects (const Vec2 &point) const; + bool intersects (const Box > &box) const; + + unsigned int majorAxis() const; + + //---------------- + // Classification + //---------------- + + bool isEmpty() const; + bool hasVolume() const; + bool isInfinite() const; +}; + + +//---------------- +// Implementation + +template +inline Box >::Box() +{ + makeEmpty(); +} + + +template +inline Box >::Box (const Vec2 &point) +{ + min = point; + max = point; +} + + +template +inline Box >::Box (const Vec2 &minT, const Vec2 &maxT) +{ + min = minT; + max = maxT; +} + + +template +inline bool +Box >::operator == (const Box > &src) const +{ + return (min == src.min && max == src.max); +} + + +template +inline bool +Box >::operator != (const Box > &src) const +{ + return (min != src.min || max != src.max); +} + + +template +inline void Box >::makeEmpty() +{ + min = Vec2(Vec2::baseTypeMax()); + max = Vec2(Vec2::baseTypeMin()); +} + +template +inline void Box >::makeInfinite() +{ + min = Vec2(Vec2::baseTypeMin()); + max = Vec2(Vec2::baseTypeMax()); +} + + +template +inline void +Box >::extendBy (const Vec2 &point) +{ + if (point[0] < min[0]) + min[0] = point[0]; + + if (point[0] > max[0]) + max[0] = point[0]; + + if (point[1] < min[1]) + min[1] = point[1]; + + if (point[1] > max[1]) + max[1] = point[1]; +} + + +template +inline void +Box >::extendBy (const Box > &box) +{ + if (box.min[0] < min[0]) + min[0] = box.min[0]; + + if (box.max[0] > max[0]) + max[0] = box.max[0]; + + if (box.min[1] < min[1]) + min[1] = box.min[1]; + + if (box.max[1] > max[1]) + max[1] = box.max[1]; +} + + +template +inline bool +Box >::intersects (const Vec2 &point) const +{ + if (point[0] < min[0] || point[0] > max[0] || + point[1] < min[1] || point[1] > max[1]) + return false; + + return true; +} + + +template +inline bool +Box >::intersects (const Box > &box) const +{ + if (box.max[0] < min[0] || box.min[0] > max[0] || + box.max[1] < min[1] || box.min[1] > max[1]) + return false; + + return true; +} + + +template +inline Vec2 +Box >::size() const +{ + if (isEmpty()) + return Vec2 (0); + + return max - min; +} + + +template +inline Vec2 +Box >::center() const +{ + return (max + min) / 2; +} + + +template +inline bool +Box >::isEmpty() const +{ + if (max[0] < min[0] || + max[1] < min[1]) + return true; + + return false; +} + +template +inline bool +Box > ::isInfinite() const +{ + if (min[0] != limits::min() || max[0] != limits::max() || + min[1] != limits::min() || max[1] != limits::max()) + return false; + + return true; +} + + +template +inline bool +Box >::hasVolume() const +{ + if (max[0] <= min[0] || + max[1] <= min[1]) + return false; + + return true; +} + + +template +inline unsigned int +Box >::majorAxis() const +{ + unsigned int major = 0; + Vec2 s = size(); + + if (s[1] > s[major]) + major = 1; + + return major; +} + + +template +class Box > +{ + public: + + //------------------------- + // Data Members are public + //------------------------- + + Vec3 min; + Vec3 max; + + //----------------------------------------------------- + // Constructors - an "empty" box is created by default + //----------------------------------------------------- + + Box(); + Box (const Vec3 &point); + Box (const Vec3 &minT, const Vec3 &maxT); + + //-------------------- + // Operators: ==, != + //-------------------- + + bool operator == (const Box > &src) const; + bool operator != (const Box > &src) const; + + //------------------ + // Box manipulation + //------------------ + + void makeEmpty(); + void extendBy (const Vec3 &point); + void extendBy (const Box > &box); + void makeInfinite (); + + //--------------------------------------------------- + // Query functions - these compute results each time + //--------------------------------------------------- + + Vec3 size() const; + Vec3 center() const; + bool intersects (const Vec3 &point) const; + bool intersects (const Box > &box) const; + + unsigned int majorAxis() const; + + //---------------- + // Classification + //---------------- + + bool isEmpty() const; + bool hasVolume() const; + bool isInfinite() const; +}; + + +//---------------- +// Implementation + + +template +inline Box >::Box() +{ + makeEmpty(); +} + + +template +inline Box >::Box (const Vec3 &point) +{ + min = point; + max = point; +} + + +template +inline Box >::Box (const Vec3 &minT, const Vec3 &maxT) +{ + min = minT; + max = maxT; +} + + +template +inline bool +Box >::operator == (const Box > &src) const +{ + return (min == src.min && max == src.max); +} + + +template +inline bool +Box >::operator != (const Box > &src) const +{ + return (min != src.min || max != src.max); +} + + +template +inline void Box >::makeEmpty() +{ + min = Vec3(Vec3::baseTypeMax()); + max = Vec3(Vec3::baseTypeMin()); +} + +template +inline void Box >::makeInfinite() +{ + min = Vec3(Vec3::baseTypeMin()); + max = Vec3(Vec3::baseTypeMax()); +} + + +template +inline void +Box >::extendBy (const Vec3 &point) +{ + if (point[0] < min[0]) + min[0] = point[0]; + + if (point[0] > max[0]) + max[0] = point[0]; + + if (point[1] < min[1]) + min[1] = point[1]; + + if (point[1] > max[1]) + max[1] = point[1]; + + if (point[2] < min[2]) + min[2] = point[2]; + + if (point[2] > max[2]) + max[2] = point[2]; +} + + +template +inline void +Box >::extendBy (const Box > &box) +{ + if (box.min[0] < min[0]) + min[0] = box.min[0]; + + if (box.max[0] > max[0]) + max[0] = box.max[0]; + + if (box.min[1] < min[1]) + min[1] = box.min[1]; + + if (box.max[1] > max[1]) + max[1] = box.max[1]; + + if (box.min[2] < min[2]) + min[2] = box.min[2]; + + if (box.max[2] > max[2]) + max[2] = box.max[2]; +} + + +template +inline bool +Box >::intersects (const Vec3 &point) const +{ + if (point[0] < min[0] || point[0] > max[0] || + point[1] < min[1] || point[1] > max[1] || + point[2] < min[2] || point[2] > max[2]) + return false; + + return true; +} + + +template +inline bool +Box >::intersects (const Box > &box) const +{ + if (box.max[0] < min[0] || box.min[0] > max[0] || + box.max[1] < min[1] || box.min[1] > max[1] || + box.max[2] < min[2] || box.min[2] > max[2]) + return false; + + return true; +} + + +template +inline Vec3 +Box >::size() const +{ + if (isEmpty()) + return Vec3 (0); + + return max - min; +} + + +template +inline Vec3 +Box >::center() const +{ + return (max + min) / 2; +} + + +template +inline bool +Box >::isEmpty() const +{ + if (max[0] < min[0] || + max[1] < min[1] || + max[2] < min[2]) + return true; + + return false; +} + +template +inline bool +Box >::isInfinite() const +{ + if (min[0] != limits::min() || max[0] != limits::max() || + min[1] != limits::min() || max[1] != limits::max() || + min[2] != limits::min() || max[2] != limits::max()) + return false; + + return true; +} + + +template +inline bool +Box >::hasVolume() const +{ + if (max[0] <= min[0] || + max[1] <= min[1] || + max[2] <= min[2]) + return false; + + return true; +} + + +template +inline unsigned int +Box >::majorAxis() const +{ + unsigned int major = 0; + Vec3 s = size(); + + if (s[1] > s[major]) + major = 1; + + if (s[2] > s[major]) + major = 2; + + return major; +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHBOX_H diff --git a/OpenEXR/include/OpenEXR/ImathBoxAlgo.h b/OpenEXR/include/OpenEXR/ImathBoxAlgo.h new file mode 100644 index 0000000..63bd2f6 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathBoxAlgo.h @@ -0,0 +1,1016 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHBOXALGO_H +#define INCLUDED_IMATHBOXALGO_H + + +//--------------------------------------------------------------------------- +// +// This file contains algorithms applied to or in conjunction +// with bounding boxes (Imath::Box). These algorithms require +// more headers to compile. The assumption made is that these +// functions are called much less often than the basic box +// functions or these functions require more support classes. +// +// Contains: +// +// T clip(const T& in, const Box& box) +// +// Vec3 closestPointOnBox(const Vec3&, const Box>& ) +// +// Vec3 closestPointInBox(const Vec3&, const Box>& ) +// +// Box< Vec3 > transform(const Box>&, const Matrix44&) +// Box< Vec3 > affineTransform(const Box>&, const Matrix44&) +// +// void transform(const Box>&, const Matrix44&, Box>&) +// void affineTransform(const Box>&, +// const Matrix44&, +// Box>&) +// +// bool findEntryAndExitPoints(const Line &line, +// const Box< Vec3 > &box, +// Vec3 &enterPoint, +// Vec3 &exitPoint) +// +// bool intersects(const Box> &box, +// const Line3 &ray, +// Vec3 intersectionPoint) +// +// bool intersects(const Box> &box, const Line3 &ray) +// +//--------------------------------------------------------------------------- + +#include "ImathBox.h" +#include "ImathMatrix.h" +#include "ImathLineAlgo.h" +#include "ImathPlane.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +inline T +clip (const T &p, const Box &box) +{ + // + // Clip the coordinates of a point, p, against a box. + // The result, q, is the closest point to p that is inside the box. + // + + T q; + + for (int i = 0; i < int (box.min.dimensions()); i++) + { + if (p[i] < box.min[i]) + q[i] = box.min[i]; + else if (p[i] > box.max[i]) + q[i] = box.max[i]; + else + q[i] = p[i]; + } + + return q; +} + + +template +inline T +closestPointInBox (const T &p, const Box &box) +{ + return clip (p, box); +} + + +template +Vec3 +closestPointOnBox (const Vec3 &p, const Box< Vec3 > &box) +{ + // + // Find the point, q, on the surface of + // the box, that is closest to point p. + // + // If the box is empty, return p. + // + + if (box.isEmpty()) + return p; + + Vec3 q = closestPointInBox (p, box); + + if (q == p) + { + Vec3 d1 = p - box.min; + Vec3 d2 = box.max - p; + + Vec3 d ((d1.x < d2.x)? d1.x: d2.x, + (d1.y < d2.y)? d1.y: d2.y, + (d1.z < d2.z)? d1.z: d2.z); + + if (d.x < d.y && d.x < d.z) + { + q.x = (d1.x < d2.x)? box.min.x: box.max.x; + } + else if (d.y < d.z) + { + q.y = (d1.y < d2.y)? box.min.y: box.max.y; + } + else + { + q.z = (d1.z < d2.z)? box.min.z: box.max.z; + } + } + + return q; +} + + +template +Box< Vec3 > +transform (const Box< Vec3 > &box, const Matrix44 &m) +{ + // + // Transform a 3D box by a matrix, and compute a new box that + // tightly encloses the transformed box. + // + // If m is an affine transform, then we use James Arvo's fast + // method as described in "Graphics Gems", Academic Press, 1990, + // pp. 548-550. + // + + // + // A transformed empty box is still empty, and a transformed infinite box + // is still infinite + // + + if (box.isEmpty() || box.isInfinite()) + return box; + + // + // If the last column of m is (0 0 0 1) then m is an affine + // transform, and we use the fast Graphics Gems trick. + // + + if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1) + { + Box< Vec3 > newBox; + + for (int i = 0; i < 3; i++) + { + newBox.min[i] = newBox.max[i] = (S) m[3][i]; + + for (int j = 0; j < 3; j++) + { + S a, b; + + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; + + if (a < b) + { + newBox.min[i] += a; + newBox.max[i] += b; + } + else + { + newBox.min[i] += b; + newBox.max[i] += a; + } + } + } + + return newBox; + } + + // + // M is a projection matrix. Do things the naive way: + // Transform the eight corners of the box, and find an + // axis-parallel box that encloses the transformed corners. + // + + Vec3 points[8]; + + points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0]; + points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0]; + + points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1]; + points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1]; + + points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2]; + points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2]; + + Box< Vec3 > newBox; + + for (int i = 0; i < 8; i++) + newBox.extendBy (points[i] * m); + + return newBox; +} + +template +void +transform (const Box< Vec3 > &box, + const Matrix44 &m, + Box< Vec3 > &result) +{ + // + // Transform a 3D box by a matrix, and compute a new box that + // tightly encloses the transformed box. + // + // If m is an affine transform, then we use James Arvo's fast + // method as described in "Graphics Gems", Academic Press, 1990, + // pp. 548-550. + // + + // + // A transformed empty box is still empty, and a transformed infinite + // box is still infinite + // + + if (box.isEmpty() || box.isInfinite()) + { + return; + } + + // + // If the last column of m is (0 0 0 1) then m is an affine + // transform, and we use the fast Graphics Gems trick. + // + + if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1) + { + for (int i = 0; i < 3; i++) + { + result.min[i] = result.max[i] = (S) m[3][i]; + + for (int j = 0; j < 3; j++) + { + S a, b; + + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; + + if (a < b) + { + result.min[i] += a; + result.max[i] += b; + } + else + { + result.min[i] += b; + result.max[i] += a; + } + } + } + + return; + } + + // + // M is a projection matrix. Do things the naive way: + // Transform the eight corners of the box, and find an + // axis-parallel box that encloses the transformed corners. + // + + Vec3 points[8]; + + points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0]; + points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0]; + + points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1]; + points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1]; + + points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2]; + points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2]; + + for (int i = 0; i < 8; i++) + result.extendBy (points[i] * m); +} + + +template +Box< Vec3 > +affineTransform (const Box< Vec3 > &box, const Matrix44 &m) +{ + // + // Transform a 3D box by a matrix whose rightmost column + // is (0 0 0 1), and compute a new box that tightly encloses + // the transformed box. + // + // As in the transform() function, above, we use James Arvo's + // fast method. + // + + if (box.isEmpty() || box.isInfinite()) + { + // + // A transformed empty or infinite box is still empty or infinite + // + + return box; + } + + Box< Vec3 > newBox; + + for (int i = 0; i < 3; i++) + { + newBox.min[i] = newBox.max[i] = (S) m[3][i]; + + for (int j = 0; j < 3; j++) + { + S a, b; + + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; + + if (a < b) + { + newBox.min[i] += a; + newBox.max[i] += b; + } + else + { + newBox.min[i] += b; + newBox.max[i] += a; + } + } + } + + return newBox; +} + +template +void +affineTransform (const Box< Vec3 > &box, + const Matrix44 &m, + Box > &result) +{ + // + // Transform a 3D box by a matrix whose rightmost column + // is (0 0 0 1), and compute a new box that tightly encloses + // the transformed box. + // + // As in the transform() function, above, we use James Arvo's + // fast method. + // + + if (box.isEmpty()) + { + // + // A transformed empty box is still empty + // + result.makeEmpty(); + return; + } + + if (box.isInfinite()) + { + // + // A transformed infinite box is still infinite + // + result.makeInfinite(); + return; + } + + for (int i = 0; i < 3; i++) + { + result.min[i] = result.max[i] = (S) m[3][i]; + + for (int j = 0; j < 3; j++) + { + S a, b; + + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; + + if (a < b) + { + result.min[i] += a; + result.max[i] += b; + } + else + { + result.min[i] += b; + result.max[i] += a; + } + } + } +} + + +template +bool +findEntryAndExitPoints (const Line3 &r, + const Box > &b, + Vec3 &entry, + Vec3 &exit) +{ + // + // Compute the points where a ray, r, enters and exits a box, b: + // + // findEntryAndExitPoints() returns + // + // - true if the ray starts inside the box or if the + // ray starts outside and intersects the box + // + // - false otherwise (that is, if the ray does not + // intersect the box) + // + // The entry and exit points are + // + // - points on two of the faces of the box when + // findEntryAndExitPoints() returns true + // (The entry end exit points may be on either + // side of the ray's origin) + // + // - undefined when findEntryAndExitPoints() + // returns false + // + + if (b.isEmpty()) + { + // + // No ray intersects an empty box + // + + return false; + } + + // + // The following description assumes that the ray's origin is outside + // the box, but the code below works even if the origin is inside the + // box: + // + // Between one and three "frontfacing" sides of the box are oriented + // towards the ray's origin, and between one and three "backfacing" + // sides are oriented away from the ray's origin. + // We intersect the ray with the planes that contain the sides of the + // box, and compare the distances between the ray's origin and the + // ray-plane intersections. The ray intersects the box if the most + // distant frontfacing intersection is nearer than the nearest + // backfacing intersection. If the ray does intersect the box, then + // the most distant frontfacing ray-plane intersection is the entry + // point and the nearest backfacing ray-plane intersection is the + // exit point. + // + + const T TMAX = limits::max(); + + T tFrontMax = -TMAX; + T tBackMin = TMAX; + + // + // Minimum and maximum X sides. + // + + if (r.dir.x >= 0) + { + T d1 = b.max.x - r.pos.x; + T d2 = b.min.x - r.pos.x; + + if (r.dir.x > 1 || + (abs (d1) < TMAX * r.dir.x && + abs (d2) < TMAX * r.dir.x)) + { + T t1 = d1 / r.dir.x; + T t2 = d2 / r.dir.x; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = b.max.x; + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = b.min.x; + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.x < b.min.x || r.pos.x > b.max.x) + { + return false; + } + } + else // r.dir.x < 0 + { + T d1 = b.min.x - r.pos.x; + T d2 = b.max.x - r.pos.x; + + if (r.dir.x < -1 || + (abs (d1) < -TMAX * r.dir.x && + abs (d2) < -TMAX * r.dir.x)) + { + T t1 = d1 / r.dir.x; + T t2 = d2 / r.dir.x; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = b.min.x; + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = b.max.x; + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.x < b.min.x || r.pos.x > b.max.x) + { + return false; + } + } + + // + // Minimum and maximum Y sides. + // + + if (r.dir.y >= 0) + { + T d1 = b.max.y - r.pos.y; + T d2 = b.min.y - r.pos.y; + + if (r.dir.y > 1 || + (abs (d1) < TMAX * r.dir.y && + abs (d2) < TMAX * r.dir.y)) + { + T t1 = d1 / r.dir.y; + T t2 = d2 / r.dir.y; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = b.max.y; + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = b.min.y; + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.y < b.min.y || r.pos.y > b.max.y) + { + return false; + } + } + else // r.dir.y < 0 + { + T d1 = b.min.y - r.pos.y; + T d2 = b.max.y - r.pos.y; + + if (r.dir.y < -1 || + (abs (d1) < -TMAX * r.dir.y && + abs (d2) < -TMAX * r.dir.y)) + { + T t1 = d1 / r.dir.y; + T t2 = d2 / r.dir.y; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = b.min.y; + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = b.max.y; + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.y < b.min.y || r.pos.y > b.max.y) + { + return false; + } + } + + // + // Minimum and maximum Z sides. + // + + if (r.dir.z >= 0) + { + T d1 = b.max.z - r.pos.z; + T d2 = b.min.z - r.pos.z; + + if (r.dir.z > 1 || + (abs (d1) < TMAX * r.dir.z && + abs (d2) < TMAX * r.dir.z)) + { + T t1 = d1 / r.dir.z; + T t2 = d2 / r.dir.z; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = b.max.z; + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = b.min.z; + } + } + else if (r.pos.z < b.min.z || r.pos.z > b.max.z) + { + return false; + } + } + else // r.dir.z < 0 + { + T d1 = b.min.z - r.pos.z; + T d2 = b.max.z - r.pos.z; + + if (r.dir.z < -1 || + (abs (d1) < -TMAX * r.dir.z && + abs (d2) < -TMAX * r.dir.z)) + { + T t1 = d1 / r.dir.z; + T t2 = d2 / r.dir.z; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = b.min.z; + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = b.max.z; + } + } + else if (r.pos.z < b.min.z || r.pos.z > b.max.z) + { + return false; + } + } + + return tFrontMax <= tBackMin; +} + + +template +bool +intersects (const Box< Vec3 > &b, const Line3 &r, Vec3 &ip) +{ + // + // Intersect a ray, r, with a box, b, and compute the intersection + // point, ip: + // + // intersect() returns + // + // - true if the ray starts inside the box or if the + // ray starts outside and intersects the box + // + // - false if the ray starts outside the box and intersects it, + // but the intersection is behind the ray's origin. + // + // - false if the ray starts outside and does not intersect it + // + // The intersection point is + // + // - the ray's origin if the ray starts inside the box + // + // - a point on one of the faces of the box if the ray + // starts outside the box + // + // - undefined when intersect() returns false + // + + if (b.isEmpty()) + { + // + // No ray intersects an empty box + // + + return false; + } + + if (b.intersects (r.pos)) + { + // + // The ray starts inside the box + // + + ip = r.pos; + return true; + } + + // + // The ray starts outside the box. Between one and three "frontfacing" + // sides of the box are oriented towards the ray, and between one and + // three "backfacing" sides are oriented away from the ray. + // We intersect the ray with the planes that contain the sides of the + // box, and compare the distances between ray's origin and the ray-plane + // intersections. + // The ray intersects the box if the most distant frontfacing intersection + // is nearer than the nearest backfacing intersection. If the ray does + // intersect the box, then the most distant frontfacing ray-plane + // intersection is the ray-box intersection. + // + + const T TMAX = limits::max(); + + T tFrontMax = -1; + T tBackMin = TMAX; + + // + // Minimum and maximum X sides. + // + + if (r.dir.x > 0) + { + if (r.pos.x > b.max.x) + return false; + + T d = b.max.x - r.pos.x; + + if (r.dir.x > 1 || d < TMAX * r.dir.x) + { + T t = d / r.dir.x; + + if (tBackMin > t) + tBackMin = t; + } + + if (r.pos.x <= b.min.x) + { + T d = b.min.x - r.pos.x; + T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; + + ip.x = b.min.x; + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } + } + else if (r.dir.x < 0) + { + if (r.pos.x < b.min.x) + return false; + + T d = b.min.x - r.pos.x; + + if (r.dir.x < -1 || d > TMAX * r.dir.x) + { + T t = d / r.dir.x; + + if (tBackMin > t) + tBackMin = t; + } + + if (r.pos.x >= b.max.x) + { + T d = b.max.x - r.pos.x; + T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; + + ip.x = b.max.x; + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } + } + else // r.dir.x == 0 + { + if (r.pos.x < b.min.x || r.pos.x > b.max.x) + return false; + } + + // + // Minimum and maximum Y sides. + // + + if (r.dir.y > 0) + { + if (r.pos.y > b.max.y) + return false; + + T d = b.max.y - r.pos.y; + + if (r.dir.y > 1 || d < TMAX * r.dir.y) + { + T t = d / r.dir.y; + + if (tBackMin > t) + tBackMin = t; + } + + if (r.pos.y <= b.min.y) + { + T d = b.min.y - r.pos.y; + T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; + + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = b.min.y; + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } + } + else if (r.dir.y < 0) + { + if (r.pos.y < b.min.y) + return false; + + T d = b.min.y - r.pos.y; + + if (r.dir.y < -1 || d > TMAX * r.dir.y) + { + T t = d / r.dir.y; + + if (tBackMin > t) + tBackMin = t; + } + + if (r.pos.y >= b.max.y) + { + T d = b.max.y - r.pos.y; + T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; + + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = b.max.y; + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } + } + else // r.dir.y == 0 + { + if (r.pos.y < b.min.y || r.pos.y > b.max.y) + return false; + } + + // + // Minimum and maximum Z sides. + // + + if (r.dir.z > 0) + { + if (r.pos.z > b.max.z) + return false; + + T d = b.max.z - r.pos.z; + + if (r.dir.z > 1 || d < TMAX * r.dir.z) + { + T t = d / r.dir.z; + + if (tBackMin > t) + tBackMin = t; + } + + if (r.pos.z <= b.min.z) + { + T d = b.min.z - r.pos.z; + T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; + + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = b.min.z; + } + } + } + else if (r.dir.z < 0) + { + if (r.pos.z < b.min.z) + return false; + + T d = b.min.z - r.pos.z; + + if (r.dir.z < -1 || d > TMAX * r.dir.z) + { + T t = d / r.dir.z; + + if (tBackMin > t) + tBackMin = t; + } + + if (r.pos.z >= b.max.z) + { + T d = b.max.z - r.pos.z; + T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; + + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = b.max.z; + } + } + } + else // r.dir.z == 0 + { + if (r.pos.z < b.min.z || r.pos.z > b.max.z) + return false; + } + + return tFrontMax <= tBackMin; +} + + +template +bool +intersects (const Box< Vec3 > &box, const Line3 &ray) +{ + Vec3 ignored; + return intersects (box, ray, ignored); +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHBOXALGO_H diff --git a/OpenEXR/include/OpenEXR/ImathColor.h b/OpenEXR/include/OpenEXR/ImathColor.h new file mode 100644 index 0000000..743c72d --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathColor.h @@ -0,0 +1,736 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHCOLOR_H +#define INCLUDED_IMATHCOLOR_H + +//---------------------------------------------------- +// +// A three and four component color class template. +// +//---------------------------------------------------- + +#include "ImathVec.h" +#include "ImathNamespace.h" +#include "half.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +class Color3: public Vec3 +{ + public: + + //------------- + // Constructors + //------------- + + Color3 (); // no initialization + explicit Color3 (T a); // (a a a) + Color3 (T a, T b, T c); // (a b c) + + + //--------------------------------- + // Copy constructors and assignment + //--------------------------------- + + Color3 (const Color3 &c); + template Color3 (const Vec3 &v); + + const Color3 & operator = (const Color3 &c); + + + //------------------------ + // Component-wise addition + //------------------------ + + const Color3 & operator += (const Color3 &c); + Color3 operator + (const Color3 &c) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Color3 & operator -= (const Color3 &c); + Color3 operator - (const Color3 &c) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Color3 operator - () const; + const Color3 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Color3 & operator *= (const Color3 &c); + const Color3 & operator *= (T a); + Color3 operator * (const Color3 &c) const; + Color3 operator * (T a) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Color3 & operator /= (const Color3 &c); + const Color3 & operator /= (T a); + Color3 operator / (const Color3 &c) const; + Color3 operator / (T a) const; +}; + +template class Color4 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T r, g, b, a; + + T & operator [] (int i); + const T & operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Color4 (); // no initialization + explicit Color4 (T a); // (a a a a) + Color4 (T a, T b, T c, T d); // (a b c d) + + + //--------------------------------- + // Copy constructors and assignment + //--------------------------------- + + Color4 (const Color4 &v); + template Color4 (const Color4 &v); + + const Color4 & operator = (const Color4 &v); + + + //---------------------- + // Compatibility with Sb + //---------------------- + + template + void setValue (S a, S b, S c, S d); + + template + void setValue (const Color4 &v); + + template + void getValue (S &a, S &b, S &c, S &d) const; + + template + void getValue (Color4 &v) const; + + T * getValue(); + const T * getValue() const; + + + //--------- + // Equality + //--------- + + template + bool operator == (const Color4 &v) const; + + template + bool operator != (const Color4 &v) const; + + + //------------------------ + // Component-wise addition + //------------------------ + + const Color4 & operator += (const Color4 &v); + Color4 operator + (const Color4 &v) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Color4 & operator -= (const Color4 &v); + Color4 operator - (const Color4 &v) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Color4 operator - () const; + const Color4 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Color4 & operator *= (const Color4 &v); + const Color4 & operator *= (T a); + Color4 operator * (const Color4 &v) const; + Color4 operator * (T a) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Color4 & operator /= (const Color4 &v); + const Color4 & operator /= (T a); + Color4 operator / (const Color4 &v) const; + Color4 operator / (T a) const; + + + //---------------------------------------------------------- + // Number of dimensions, i.e. number of elements in a Color4 + //---------------------------------------------------------- + + static unsigned int dimensions() {return 4;} + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + + //-------------------------------------------------------------- + // Base type -- in templates, which accept a parameter, V, which + // could be a Color4, you can refer to T as + // V::BaseType + //-------------------------------------------------------------- + + typedef T BaseType; +}; + +//-------------- +// Stream output +//-------------- + +template +std::ostream & operator << (std::ostream &s, const Color4 &v); + +//---------------------------------------------------- +// Reverse multiplication: S * Color4 +//---------------------------------------------------- + +template Color4 operator * (S a, const Color4 &v); + +//------------------------- +// Typedefs for convenience +//------------------------- + +typedef Color3 Color3f; +typedef Color3 Color3h; +typedef Color3 Color3c; +typedef Color3 C3h; +typedef Color3 C3f; +typedef Color3 C3c; +typedef Color4 Color4f; +typedef Color4 Color4h; +typedef Color4 Color4c; +typedef Color4 C4f; +typedef Color4 C4h; +typedef Color4 C4c; +typedef unsigned int PackedColor; + + +//------------------------- +// Implementation of Color3 +//------------------------- + +template +inline +Color3::Color3 (): Vec3 () +{ + // empty +} + +template +inline +Color3::Color3 (T a): Vec3 (a) +{ + // empty +} + +template +inline +Color3::Color3 (T a, T b, T c): Vec3 (a, b, c) +{ + // empty +} + +template +inline +Color3::Color3 (const Color3 &c): Vec3 (c) +{ + // empty +} + +template +template +inline +Color3::Color3 (const Vec3 &v): Vec3 (v) +{ + //empty +} + +template +inline const Color3 & +Color3::operator = (const Color3 &c) +{ + *((Vec3 *) this) = c; + return *this; +} + +template +inline const Color3 & +Color3::operator += (const Color3 &c) +{ + *((Vec3 *) this) += c; + return *this; +} + +template +inline Color3 +Color3::operator + (const Color3 &c) const +{ + return Color3 (*(Vec3 *)this + (const Vec3 &)c); +} + +template +inline const Color3 & +Color3::operator -= (const Color3 &c) +{ + *((Vec3 *) this) -= c; + return *this; +} + +template +inline Color3 +Color3::operator - (const Color3 &c) const +{ + return Color3 (*(Vec3 *)this - (const Vec3 &)c); +} + +template +inline Color3 +Color3::operator - () const +{ + return Color3 (-(*(Vec3 *)this)); +} + +template +inline const Color3 & +Color3::negate () +{ + ((Vec3 *) this)->negate(); + return *this; +} + +template +inline const Color3 & +Color3::operator *= (const Color3 &c) +{ + *((Vec3 *) this) *= c; + return *this; +} + +template +inline const Color3 & +Color3::operator *= (T a) +{ + *((Vec3 *) this) *= a; + return *this; +} + +template +inline Color3 +Color3::operator * (const Color3 &c) const +{ + return Color3 (*(Vec3 *)this * (const Vec3 &)c); +} + +template +inline Color3 +Color3::operator * (T a) const +{ + return Color3 (*(Vec3 *)this * a); +} + +template +inline const Color3 & +Color3::operator /= (const Color3 &c) +{ + *((Vec3 *) this) /= c; + return *this; +} + +template +inline const Color3 & +Color3::operator /= (T a) +{ + *((Vec3 *) this) /= a; + return *this; +} + +template +inline Color3 +Color3::operator / (const Color3 &c) const +{ + return Color3 (*(Vec3 *)this / (const Vec3 &)c); +} + +template +inline Color3 +Color3::operator / (T a) const +{ + return Color3 (*(Vec3 *)this / a); +} + +//----------------------- +// Implementation of Color4 +//----------------------- + +template +inline T & +Color4::operator [] (int i) +{ + return (&r)[i]; +} + +template +inline const T & +Color4::operator [] (int i) const +{ + return (&r)[i]; +} + +template +inline +Color4::Color4 () +{ + // empty +} + +template +inline +Color4::Color4 (T x) +{ + r = g = b = a = x; +} + +template +inline +Color4::Color4 (T x, T y, T z, T w) +{ + r = x; + g = y; + b = z; + a = w; +} + +template +inline +Color4::Color4 (const Color4 &v) +{ + r = v.r; + g = v.g; + b = v.b; + a = v.a; +} + +template +template +inline +Color4::Color4 (const Color4 &v) +{ + r = T (v.r); + g = T (v.g); + b = T (v.b); + a = T (v.a); +} + +template +inline const Color4 & +Color4::operator = (const Color4 &v) +{ + r = v.r; + g = v.g; + b = v.b; + a = v.a; + return *this; +} + +template +template +inline void +Color4::setValue (S x, S y, S z, S w) +{ + r = T (x); + g = T (y); + b = T (z); + a = T (w); +} + +template +template +inline void +Color4::setValue (const Color4 &v) +{ + r = T (v.r); + g = T (v.g); + b = T (v.b); + a = T (v.a); +} + +template +template +inline void +Color4::getValue (S &x, S &y, S &z, S &w) const +{ + x = S (r); + y = S (g); + z = S (b); + w = S (a); +} + +template +template +inline void +Color4::getValue (Color4 &v) const +{ + v.r = S (r); + v.g = S (g); + v.b = S (b); + v.a = S (a); +} + +template +inline T * +Color4::getValue() +{ + return (T *) &r; +} + +template +inline const T * +Color4::getValue() const +{ + return (const T *) &r; +} + +template +template +inline bool +Color4::operator == (const Color4 &v) const +{ + return r == v.r && g == v.g && b == v.b && a == v.a; +} + +template +template +inline bool +Color4::operator != (const Color4 &v) const +{ + return r != v.r || g != v.g || b != v.b || a != v.a; +} + +template +inline const Color4 & +Color4::operator += (const Color4 &v) +{ + r += v.r; + g += v.g; + b += v.b; + a += v.a; + return *this; +} + +template +inline Color4 +Color4::operator + (const Color4 &v) const +{ + return Color4 (r + v.r, g + v.g, b + v.b, a + v.a); +} + +template +inline const Color4 & +Color4::operator -= (const Color4 &v) +{ + r -= v.r; + g -= v.g; + b -= v.b; + a -= v.a; + return *this; +} + +template +inline Color4 +Color4::operator - (const Color4 &v) const +{ + return Color4 (r - v.r, g - v.g, b - v.b, a - v.a); +} + +template +inline Color4 +Color4::operator - () const +{ + return Color4 (-r, -g, -b, -a); +} + +template +inline const Color4 & +Color4::negate () +{ + r = -r; + g = -g; + b = -b; + a = -a; + return *this; +} + +template +inline const Color4 & +Color4::operator *= (const Color4 &v) +{ + r *= v.r; + g *= v.g; + b *= v.b; + a *= v.a; + return *this; +} + +template +inline const Color4 & +Color4::operator *= (T x) +{ + r *= x; + g *= x; + b *= x; + a *= x; + return *this; +} + +template +inline Color4 +Color4::operator * (const Color4 &v) const +{ + return Color4 (r * v.r, g * v.g, b * v.b, a * v.a); +} + +template +inline Color4 +Color4::operator * (T x) const +{ + return Color4 (r * x, g * x, b * x, a * x); +} + +template +inline const Color4 & +Color4::operator /= (const Color4 &v) +{ + r /= v.r; + g /= v.g; + b /= v.b; + a /= v.a; + return *this; +} + +template +inline const Color4 & +Color4::operator /= (T x) +{ + r /= x; + g /= x; + b /= x; + a /= x; + return *this; +} + +template +inline Color4 +Color4::operator / (const Color4 &v) const +{ + return Color4 (r / v.r, g / v.g, b / v.b, a / v.a); +} + +template +inline Color4 +Color4::operator / (T x) const +{ + return Color4 (r / x, g / x, b / x, a / x); +} + + +template +std::ostream & +operator << (std::ostream &s, const Color4 &v) +{ + return s << '(' << v.r << ' ' << v.g << ' ' << v.b << ' ' << v.a << ')'; +} + +//----------------------------------------- +// Implementation of reverse multiplication +//----------------------------------------- + +template +inline Color4 +operator * (S x, const Color4 &v) +{ + return Color4 (x * v.r, x * v.g, x * v.b, x * v.a); +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHCOLOR_H diff --git a/OpenEXR/include/OpenEXR/ImathColorAlgo.h b/OpenEXR/include/OpenEXR/ImathColorAlgo.h new file mode 100644 index 0000000..cbc3be4 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathColorAlgo.h @@ -0,0 +1,257 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHCOLORALGO_H +#define INCLUDED_IMATHCOLORALGO_H + + +#include "ImathColor.h" +#include "ImathExport.h" +#include "ImathMath.h" +#include "ImathLimits.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// Non-templated helper routines for color conversion. +// These routines eliminate type warnings under g++. +// + +IMATH_EXPORT Vec3 hsv2rgb_d(const Vec3 &hsv); + +IMATH_EXPORT Color4 hsv2rgb_d(const Color4 &hsv); + +IMATH_EXPORT Vec3 rgb2hsv_d(const Vec3 &rgb); + +IMATH_EXPORT Color4 rgb2hsv_d(const Color4 &rgb); + + +// +// Color conversion functions and general color algorithms +// +// hsv2rgb(), rgb2hsv(), rgb2packed(), packed2rgb() +// see each funtion definition for details. +// + +template +Vec3 +hsv2rgb(const Vec3 &hsv) +{ + if ( limits::isIntegral() ) + { + Vec3 v = Vec3(hsv.x / double(limits::max()), + hsv.y / double(limits::max()), + hsv.z / double(limits::max())); + Vec3 c = hsv2rgb_d(v); + return Vec3((T) (c.x * limits::max()), + (T) (c.y * limits::max()), + (T) (c.z * limits::max())); + } + else + { + Vec3 v = Vec3(hsv.x, hsv.y, hsv.z); + Vec3 c = hsv2rgb_d(v); + return Vec3((T) c.x, (T) c.y, (T) c.z); + } +} + + +template +Color4 +hsv2rgb(const Color4 &hsv) +{ + if ( limits::isIntegral() ) + { + Color4 v = Color4(hsv.r / float(limits::max()), + hsv.g / float(limits::max()), + hsv.b / float(limits::max()), + hsv.a / float(limits::max())); + Color4 c = hsv2rgb_d(v); + return Color4((T) (c.r * limits::max()), + (T) (c.g * limits::max()), + (T) (c.b * limits::max()), + (T) (c.a * limits::max())); + } + else + { + Color4 v = Color4(hsv.r, hsv.g, hsv.b, hsv.a); + Color4 c = hsv2rgb_d(v); + return Color4((T) c.r, (T) c.g, (T) c.b, (T) c.a); + } +} + + +template +Vec3 +rgb2hsv(const Vec3 &rgb) +{ + if ( limits::isIntegral() ) + { + Vec3 v = Vec3(rgb.x / double(limits::max()), + rgb.y / double(limits::max()), + rgb.z / double(limits::max())); + Vec3 c = rgb2hsv_d(v); + return Vec3((T) (c.x * limits::max()), + (T) (c.y * limits::max()), + (T) (c.z * limits::max())); + } + else + { + Vec3 v = Vec3(rgb.x, rgb.y, rgb.z); + Vec3 c = rgb2hsv_d(v); + return Vec3((T) c.x, (T) c.y, (T) c.z); + } +} + + +template +Color4 +rgb2hsv(const Color4 &rgb) +{ + if ( limits::isIntegral() ) + { + Color4 v = Color4(rgb.r / float(limits::max()), + rgb.g / float(limits::max()), + rgb.b / float(limits::max()), + rgb.a / float(limits::max())); + Color4 c = rgb2hsv_d(v); + return Color4((T) (c.r * limits::max()), + (T) (c.g * limits::max()), + (T) (c.b * limits::max()), + (T) (c.a * limits::max())); + } + else + { + Color4 v = Color4(rgb.r, rgb.g, rgb.b, rgb.a); + Color4 c = rgb2hsv_d(v); + return Color4((T) c.r, (T) c.g, (T) c.b, (T) c.a); + } +} + +template +PackedColor +rgb2packed(const Vec3 &c) +{ + if ( limits::isIntegral() ) + { + float x = c.x / float(limits::max()); + float y = c.y / float(limits::max()); + float z = c.z / float(limits::max()); + return rgb2packed( V3f(x,y,z) ); + } + else + { + return ( (PackedColor) (c.x * 255) | + (((PackedColor) (c.y * 255)) << 8) | + (((PackedColor) (c.z * 255)) << 16) | 0xFF000000 ); + } +} + +template +PackedColor +rgb2packed(const Color4 &c) +{ + if ( limits::isIntegral() ) + { + float r = c.r / float(limits::max()); + float g = c.g / float(limits::max()); + float b = c.b / float(limits::max()); + float a = c.a / float(limits::max()); + return rgb2packed( C4f(r,g,b,a) ); + } + else + { + return ( (PackedColor) (c.r * 255) | + (((PackedColor) (c.g * 255)) << 8) | + (((PackedColor) (c.b * 255)) << 16) | + (((PackedColor) (c.a * 255)) << 24)); + } +} + +// +// This guy can't return the result because the template +// parameter would not be in the function signiture. So instead, +// its passed in as an argument. +// + +template +void +packed2rgb(PackedColor packed, Vec3 &out) +{ + if ( limits::isIntegral() ) + { + T f = limits::max() / ((PackedColor)0xFF); + out.x = (packed & 0xFF) * f; + out.y = ((packed & 0xFF00) >> 8) * f; + out.z = ((packed & 0xFF0000) >> 16) * f; + } + else + { + T f = T(1) / T(255); + out.x = (packed & 0xFF) * f; + out.y = ((packed & 0xFF00) >> 8) * f; + out.z = ((packed & 0xFF0000) >> 16) * f; + } +} + +template +void +packed2rgb(PackedColor packed, Color4 &out) +{ + if ( limits::isIntegral() ) + { + T f = limits::max() / ((PackedColor)0xFF); + out.r = (packed & 0xFF) * f; + out.g = ((packed & 0xFF00) >> 8) * f; + out.b = ((packed & 0xFF0000) >> 16) * f; + out.a = ((packed & 0xFF000000) >> 24) * f; + } + else + { + T f = T(1) / T(255); + out.r = (packed & 0xFF) * f; + out.g = ((packed & 0xFF00) >> 8) * f; + out.b = ((packed & 0xFF0000) >> 16) * f; + out.a = ((packed & 0xFF000000) >> 24) * f; + } +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHCOLORALGO_H diff --git a/OpenEXR/include/OpenEXR/ImathEuler.h b/OpenEXR/include/OpenEXR/ImathEuler.h new file mode 100644 index 0000000..254c76f --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathEuler.h @@ -0,0 +1,926 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHEULER_H +#define INCLUDED_IMATHEULER_H + +//---------------------------------------------------------------------- +// +// template class Euler +// +// This class represents euler angle orientations. The class +// inherits from Vec3 to it can be freely cast. The additional +// information is the euler priorities rep. This class is +// essentially a rip off of Ken Shoemake's GemsIV code. It has +// been modified minimally to make it more understandable, but +// hardly enough to make it easy to grok completely. +// +// There are 24 possible combonations of Euler angle +// representations of which 12 are common in CG and you will +// probably only use 6 of these which in this scheme are the +// non-relative-non-repeating types. +// +// The representations can be partitioned according to two +// criteria: +// +// 1) Are the angles measured relative to a set of fixed axis +// or relative to each other (the latter being what happens +// when rotation matrices are multiplied together and is +// almost ubiquitous in the cg community) +// +// 2) Is one of the rotations repeated (ala XYX rotation) +// +// When you construct a given representation from scratch you +// must order the angles according to their priorities. So, the +// easiest is a softimage or aerospace (yaw/pitch/roll) ordering +// of ZYX. +// +// float x_rot = 1; +// float y_rot = 2; +// float z_rot = 3; +// +// Eulerf angles(z_rot, y_rot, x_rot, Eulerf::ZYX); +// -or- +// Eulerf angles( V3f(z_rot,y_rot,z_rot), Eulerf::ZYX ); +// +// If instead, the order was YXZ for instance you would have to +// do this: +// +// float x_rot = 1; +// float y_rot = 2; +// float z_rot = 3; +// +// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ); +// -or- +// Eulerf angles( V3f(y_rot,x_rot,z_rot), Eulerf::YXZ ); +// +// Notice how the order you put the angles into the three slots +// should correspond to the enum (YXZ) ordering. The input angle +// vector is called the "ijk" vector -- not an "xyz" vector. The +// ijk vector order is the same as the enum. If you treat the +// Euler<> as a Vec<> (which it inherts from) you will find the +// angles are ordered in the same way, i.e.: +// +// V3f v = angles; +// // v.x == y_rot, v.y == x_rot, v.z == z_rot +// +// If you just want the x, y, and z angles stored in a vector in +// that order, you can do this: +// +// V3f v = angles.toXYZVector() +// // v.x == x_rot, v.y == y_rot, v.z == z_rot +// +// If you want to set the Euler with an XYZVector use the +// optional layout argument: +// +// Eulerf angles(x_rot, y_rot, z_rot, +// Eulerf::YXZ, +// Eulerf::XYZLayout); +// +// This is the same as: +// +// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ); +// +// Note that this won't do anything intelligent if you have a +// repeated axis in the euler angles (e.g. XYX) +// +// If you need to use the "relative" versions of these, you will +// need to use the "r" enums. +// +// The units of the rotation angles are assumed to be radians. +// +//---------------------------------------------------------------------- + + +#include "ImathMath.h" +#include "ImathVec.h" +#include "ImathQuat.h" +#include "ImathMatrix.h" +#include "ImathLimits.h" +#include "ImathNamespace.h" + +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +// Disable MS VC++ warnings about conversion from double to float +#pragma warning(disable:4244) +#endif + +template +class Euler : public Vec3 +{ + public: + + using Vec3::x; + using Vec3::y; + using Vec3::z; + + enum Order + { + // + // All 24 possible orderings + // + + XYZ = 0x0101, // "usual" orderings + XZY = 0x0001, + YZX = 0x1101, + YXZ = 0x1001, + ZXY = 0x2101, + ZYX = 0x2001, + + XZX = 0x0011, // first axis repeated + XYX = 0x0111, + YXY = 0x1011, + YZY = 0x1111, + ZYZ = 0x2011, + ZXZ = 0x2111, + + XYZr = 0x2000, // relative orderings -- not common + XZYr = 0x2100, + YZXr = 0x1000, + YXZr = 0x1100, + ZXYr = 0x0000, + ZYXr = 0x0100, + + XZXr = 0x2110, // relative first axis repeated + XYXr = 0x2010, + YXYr = 0x1110, + YZYr = 0x1010, + ZYZr = 0x0110, + ZXZr = 0x0010, + // |||| + // VVVV + // Legend: ABCD + // A -> Initial Axis (0==x, 1==y, 2==z) + // B -> Parity Even (1==true) + // C -> Initial Repeated (1==true) + // D -> Frame Static (1==true) + // + + Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX | + XZX | XYX | YXY | YZY | ZYZ | ZXZ | + XYZr| XZYr| YZXr| YXZr| ZXYr| ZYXr| + XZXr| XYXr| YXYr| YZYr| ZYZr| ZXZr, + + Min = 0x0000, + Max = 0x2111, + Default = XYZ + }; + + enum Axis { X = 0, Y = 1, Z = 2 }; + + enum InputLayout { XYZLayout, IJKLayout }; + + //-------------------------------------------------------------------- + // Constructors -- all default to ZYX non-relative ala softimage + // (where there is no argument to specify it) + // + // The Euler-from-matrix constructors assume that the matrix does + // not include shear or non-uniform scaling, but the constructors + // do not examine the matrix to verify this assumption. If necessary, + // you can adjust the matrix by calling the removeScalingAndShear() + // function, defined in ImathMatrixAlgo.h. + //-------------------------------------------------------------------- + + Euler(); + Euler(const Euler&); + Euler(Order p); + Euler(const Vec3 &v, Order o = Default, InputLayout l = IJKLayout); + Euler(T i, T j, T k, Order o = Default, InputLayout l = IJKLayout); + Euler(const Euler &euler, Order newp); + Euler(const Matrix33 &, Order o = Default); + Euler(const Matrix44 &, Order o = Default); + + //--------------------------------- + // Algebraic functions/ Operators + //--------------------------------- + + const Euler& operator= (const Euler&); + const Euler& operator= (const Vec3&); + + //-------------------------------------------------------- + // Set the euler value + // This does NOT convert the angles, but setXYZVector() + // does reorder the input vector. + //-------------------------------------------------------- + + static bool legal(Order); + + void setXYZVector(const Vec3 &); + + Order order() const; + void setOrder(Order); + + void set(Axis initial, + bool relative, + bool parityEven, + bool firstRepeats); + + //------------------------------------------------------------ + // Conversions, toXYZVector() reorders the angles so that + // the X rotation comes first, followed by the Y and Z + // in cases like XYX ordering, the repeated angle will be + // in the "z" component + // + // The Euler-from-matrix extract() functions assume that the + // matrix does not include shear or non-uniform scaling, but + // the extract() functions do not examine the matrix to verify + // this assumption. If necessary, you can adjust the matrix + // by calling the removeScalingAndShear() function, defined + // in ImathMatrixAlgo.h. + //------------------------------------------------------------ + + void extract(const Matrix33&); + void extract(const Matrix44&); + void extract(const Quat&); + + Matrix33 toMatrix33() const; + Matrix44 toMatrix44() const; + Quat toQuat() const; + Vec3 toXYZVector() const; + + //--------------------------------------------------- + // Use this function to unpack angles from ijk form + //--------------------------------------------------- + + void angleOrder(int &i, int &j, int &k) const; + + //--------------------------------------------------- + // Use this function to determine mapping from xyz to ijk + // - reshuffles the xyz to match the order + //--------------------------------------------------- + + void angleMapping(int &i, int &j, int &k) const; + + //---------------------------------------------------------------------- + // + // Utility methods for getting continuous rotations. None of these + // methods change the orientation given by its inputs (or at least + // that is the intent). + // + // angleMod() converts an angle to its equivalent in [-PI, PI] + // + // simpleXYZRotation() adjusts xyzRot so that its components differ + // from targetXyzRot by no more than +-PI + // + // nearestRotation() adjusts xyzRot so that its components differ + // from targetXyzRot by as little as possible. + // Note that xyz here really means ijk, because + // the order must be provided. + // + // makeNear() adjusts "this" Euler so that its components differ + // from target by as little as possible. This method + // might not make sense for Eulers with different order + // and it probably doesn't work for repeated axis and + // relative orderings (TODO). + // + //----------------------------------------------------------------------- + + static float angleMod (T angle); + static void simpleXYZRotation (Vec3 &xyzRot, + const Vec3 &targetXyzRot); + static void nearestRotation (Vec3 &xyzRot, + const Vec3 &targetXyzRot, + Order order = XYZ); + + void makeNear (const Euler &target); + + bool frameStatic() const { return _frameStatic; } + bool initialRepeated() const { return _initialRepeated; } + bool parityEven() const { return _parityEven; } + Axis initialAxis() const { return _initialAxis; } + + protected: + + bool _frameStatic : 1; // relative or static rotations + bool _initialRepeated : 1; // init axis repeated as last + bool _parityEven : 1; // "parity of axis permutation" +#if defined _WIN32 || defined _WIN64 + Axis _initialAxis ; // First axis of rotation +#else + Axis _initialAxis : 2; // First axis of rotation +#endif +}; + + +//-------------------- +// Convenient typedefs +//-------------------- + +typedef Euler Eulerf; +typedef Euler Eulerd; + + +//--------------- +// Implementation +//--------------- + +template +inline void + Euler::angleOrder(int &i, int &j, int &k) const +{ + i = _initialAxis; + j = _parityEven ? (i+1)%3 : (i > 0 ? i-1 : 2); + k = _parityEven ? (i > 0 ? i-1 : 2) : (i+1)%3; +} + +template +inline void + Euler::angleMapping(int &i, int &j, int &k) const +{ + int m[3]; + + m[_initialAxis] = 0; + m[(_initialAxis+1) % 3] = _parityEven ? 1 : 2; + m[(_initialAxis+2) % 3] = _parityEven ? 2 : 1; + i = m[0]; + j = m[1]; + k = m[2]; +} + +template +inline void +Euler::setXYZVector(const Vec3 &v) +{ + int i,j,k; + angleMapping(i,j,k); + (*this)[i] = v.x; + (*this)[j] = v.y; + (*this)[k] = v.z; +} + +template +inline Vec3 +Euler::toXYZVector() const +{ + int i,j,k; + angleMapping(i,j,k); + return Vec3((*this)[i],(*this)[j],(*this)[k]); +} + + +template +Euler::Euler() : + Vec3(0,0,0), + _frameStatic(true), + _initialRepeated(false), + _parityEven(true), + _initialAxis(X) +{} + +template +Euler::Euler(typename Euler::Order p) : + Vec3(0,0,0), + _frameStatic(true), + _initialRepeated(false), + _parityEven(true), + _initialAxis(X) +{ + setOrder(p); +} + +template +inline Euler::Euler( const Vec3 &v, + typename Euler::Order p, + typename Euler::InputLayout l ) +{ + setOrder(p); + if ( l == XYZLayout ) setXYZVector(v); + else { x = v.x; y = v.y; z = v.z; } +} + +template +inline Euler::Euler(const Euler &euler) +{ + operator=(euler); +} + +template +inline Euler::Euler(const Euler &euler,Order p) +{ + setOrder(p); + Matrix33 M = euler.toMatrix33(); + extract(M); +} + +template +inline Euler::Euler( T xi, T yi, T zi, + typename Euler::Order p, + typename Euler::InputLayout l) +{ + setOrder(p); + if ( l == XYZLayout ) setXYZVector(Vec3(xi,yi,zi)); + else { x = xi; y = yi; z = zi; } +} + +template +inline Euler::Euler( const Matrix33 &M, typename Euler::Order p ) +{ + setOrder(p); + extract(M); +} + +template +inline Euler::Euler( const Matrix44 &M, typename Euler::Order p ) +{ + setOrder(p); + extract(M); +} + +template +inline void Euler::extract(const Quat &q) +{ + extract(q.toMatrix33()); +} + +template +void Euler::extract(const Matrix33 &M) +{ + int i,j,k; + angleOrder(i,j,k); + + if (_initialRepeated) + { + // + // Extract the first angle, x. + // + + x = Math::atan2 (M[j][i], M[k][i]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); + + Matrix44 N; + N.rotate (r); + + N = N * Matrix44 (M[0][0], M[0][1], M[0][2], 0, + M[1][0], M[1][1], M[1][2], 0, + M[2][0], M[2][1], M[2][2], 0, + 0, 0, 0, 1); + // + // Extract the other two angles, y and z, from N. + // + + T sy = Math::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]); + y = Math::atan2 (sy, N[i][i]); + z = Math::atan2 (N[j][k], N[j][j]); + } + else + { + // + // Extract the first angle, x. + // + + x = Math::atan2 (M[j][k], M[k][k]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); + + Matrix44 N; + N.rotate (r); + + N = N * Matrix44 (M[0][0], M[0][1], M[0][2], 0, + M[1][0], M[1][1], M[1][2], 0, + M[2][0], M[2][1], M[2][2], 0, + 0, 0, 0, 1); + // + // Extract the other two angles, y and z, from N. + // + + T cy = Math::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]); + y = Math::atan2 (-N[i][k], cy); + z = Math::atan2 (-N[j][i], N[j][j]); + } + + if (!_parityEven) + *this *= -1; + + if (!_frameStatic) + { + T t = x; + x = z; + z = t; + } +} + +template +void Euler::extract(const Matrix44 &M) +{ + int i,j,k; + angleOrder(i,j,k); + + if (_initialRepeated) + { + // + // Extract the first angle, x. + // + + x = Math::atan2 (M[j][i], M[k][i]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); + + Matrix44 N; + N.rotate (r); + N = N * M; + + // + // Extract the other two angles, y and z, from N. + // + + T sy = Math::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]); + y = Math::atan2 (sy, N[i][i]); + z = Math::atan2 (N[j][k], N[j][j]); + } + else + { + // + // Extract the first angle, x. + // + + x = Math::atan2 (M[j][k], M[k][k]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); + + Matrix44 N; + N.rotate (r); + N = N * M; + + // + // Extract the other two angles, y and z, from N. + // + + T cy = Math::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]); + y = Math::atan2 (-N[i][k], cy); + z = Math::atan2 (-N[j][i], N[j][j]); + } + + if (!_parityEven) + *this *= -1; + + if (!_frameStatic) + { + T t = x; + x = z; + z = t; + } +} + +template +Matrix33 Euler::toMatrix33() const +{ + int i,j,k; + angleOrder(i,j,k); + + Vec3 angles; + + if ( _frameStatic ) angles = (*this); + else angles = Vec3(z,y,x); + + if ( !_parityEven ) angles *= -1.0; + + T ci = Math::cos(angles.x); + T cj = Math::cos(angles.y); + T ch = Math::cos(angles.z); + T si = Math::sin(angles.x); + T sj = Math::sin(angles.y); + T sh = Math::sin(angles.z); + + T cc = ci*ch; + T cs = ci*sh; + T sc = si*ch; + T ss = si*sh; + + Matrix33 M; + + if ( _initialRepeated ) + { + M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci; + M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc; + M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss; + } + else + { + M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss; + M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc; + M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci; + } + + return M; +} + +template +Matrix44 Euler::toMatrix44() const +{ + int i,j,k; + angleOrder(i,j,k); + + Vec3 angles; + + if ( _frameStatic ) angles = (*this); + else angles = Vec3(z,y,x); + + if ( !_parityEven ) angles *= -1.0; + + T ci = Math::cos(angles.x); + T cj = Math::cos(angles.y); + T ch = Math::cos(angles.z); + T si = Math::sin(angles.x); + T sj = Math::sin(angles.y); + T sh = Math::sin(angles.z); + + T cc = ci*ch; + T cs = ci*sh; + T sc = si*ch; + T ss = si*sh; + + Matrix44 M; + + if ( _initialRepeated ) + { + M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci; + M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc; + M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss; + } + else + { + M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss; + M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc; + M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci; + } + + return M; +} + +template +Quat Euler::toQuat() const +{ + Vec3 angles; + int i,j,k; + angleOrder(i,j,k); + + if ( _frameStatic ) angles = (*this); + else angles = Vec3(z,y,x); + + if ( !_parityEven ) angles.y = -angles.y; + + T ti = angles.x*0.5; + T tj = angles.y*0.5; + T th = angles.z*0.5; + T ci = Math::cos(ti); + T cj = Math::cos(tj); + T ch = Math::cos(th); + T si = Math::sin(ti); + T sj = Math::sin(tj); + T sh = Math::sin(th); + T cc = ci*ch; + T cs = ci*sh; + T sc = si*ch; + T ss = si*sh; + + T parity = _parityEven ? 1.0 : -1.0; + + Quat q; + Vec3 a; + + if ( _initialRepeated ) + { + a[i] = cj*(cs + sc); + a[j] = sj*(cc + ss) * parity, + a[k] = sj*(cs - sc); + q.r = cj*(cc - ss); + } + else + { + a[i] = cj*sc - sj*cs, + a[j] = (cj*ss + sj*cc) * parity, + a[k] = cj*cs - sj*sc; + q.r = cj*cc + sj*ss; + } + + q.v = a; + + return q; +} + +template +inline bool +Euler::legal(typename Euler::Order order) +{ + return (order & ~Legal) ? false : true; +} + +template +typename Euler::Order +Euler::order() const +{ + int foo = (_initialAxis == Z ? 0x2000 : (_initialAxis == Y ? 0x1000 : 0)); + + if (_parityEven) foo |= 0x0100; + if (_initialRepeated) foo |= 0x0010; + if (_frameStatic) foo++; + + return (Order)foo; +} + +template +inline void Euler::setOrder(typename Euler::Order p) +{ + set( p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis + !(p & 0x1), // static? + !!(p & 0x100), // permutation even? + !!(p & 0x10)); // initial repeats? +} + +template +void Euler::set(typename Euler::Axis axis, + bool relative, + bool parityEven, + bool firstRepeats) +{ + _initialAxis = axis; + _frameStatic = !relative; + _parityEven = parityEven; + _initialRepeated = firstRepeats; +} + +template +const Euler& Euler::operator= (const Euler &euler) +{ + x = euler.x; + y = euler.y; + z = euler.z; + _initialAxis = euler._initialAxis; + _frameStatic = euler._frameStatic; + _parityEven = euler._parityEven; + _initialRepeated = euler._initialRepeated; + return *this; +} + +template +const Euler& Euler::operator= (const Vec3 &v) +{ + x = v.x; + y = v.y; + z = v.z; + return *this; +} + +template +std::ostream& operator << (std::ostream &o, const Euler &euler) +{ + char a[3] = { 'X', 'Y', 'Z' }; + + const char* r = euler.frameStatic() ? "" : "r"; + int i,j,k; + euler.angleOrder(i,j,k); + + if ( euler.initialRepeated() ) k = i; + + return o << "(" + << euler.x << " " + << euler.y << " " + << euler.z << " " + << a[i] << a[j] << a[k] << r << ")"; +} + +template +float +Euler::angleMod (T angle) +{ + angle = fmod(T (angle), T (2 * M_PI)); + + if (angle < -M_PI) angle += 2 * M_PI; + if (angle > +M_PI) angle -= 2 * M_PI; + + return angle; +} + +template +void +Euler::simpleXYZRotation (Vec3 &xyzRot, const Vec3 &targetXyzRot) +{ + Vec3 d = xyzRot - targetXyzRot; + xyzRot[0] = targetXyzRot[0] + angleMod(d[0]); + xyzRot[1] = targetXyzRot[1] + angleMod(d[1]); + xyzRot[2] = targetXyzRot[2] + angleMod(d[2]); +} + +template +void +Euler::nearestRotation (Vec3 &xyzRot, const Vec3 &targetXyzRot, + Order order) +{ + int i,j,k; + Euler e (0,0,0, order); + e.angleOrder(i,j,k); + + simpleXYZRotation(xyzRot, targetXyzRot); + + Vec3 otherXyzRot; + otherXyzRot[i] = M_PI+xyzRot[i]; + otherXyzRot[j] = M_PI-xyzRot[j]; + otherXyzRot[k] = M_PI+xyzRot[k]; + + simpleXYZRotation(otherXyzRot, targetXyzRot); + + Vec3 d = xyzRot - targetXyzRot; + Vec3 od = otherXyzRot - targetXyzRot; + T dMag = d.dot(d); + T odMag = od.dot(od); + + if (odMag < dMag) + { + xyzRot = otherXyzRot; + } +} + +template +void +Euler::makeNear (const Euler &target) +{ + Vec3 xyzRot = toXYZVector(); + Vec3 targetXyz; + if (order() != target.order()) + { + Euler targetSameOrder = Euler(target, order()); + targetXyz = targetSameOrder.toXYZVector(); + } + else + { + targetXyz = target.toXYZVector(); + } + + nearestRotation(xyzRot, targetXyz, order()); + + setXYZVector(xyzRot); +} + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +#pragma warning(default:4244) +#endif + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif // INCLUDED_IMATHEULER_H diff --git a/OpenEXR/include/OpenEXR/ImathExc.h b/OpenEXR/include/OpenEXR/ImathExc.h new file mode 100644 index 0000000..65af3b5 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathExc.h @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHEXC_H +#define INCLUDED_IMATHEXC_H + + +//----------------------------------------------- +// +// Imath library-specific exceptions +// +//----------------------------------------------- + +#include "ImathNamespace.h" +#include "IexBaseExc.h" +#include "ImathExport.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +// Attempt to normalize null vector +DEFINE_EXC_EXP (IMATH_EXPORT, NullVecExc, ::IEX_NAMESPACE::MathExc) + +// Attempt to normalize a point at infinity +DEFINE_EXC_EXP (IMATH_EXPORT, InfPointExc, ::IEX_NAMESPACE::MathExc) + +// Attempt to normalize null quaternion +DEFINE_EXC_EXP (IMATH_EXPORT, NullQuatExc, ::IEX_NAMESPACE::MathExc) + +// Attempt to invert singular matrix +DEFINE_EXC_EXP (IMATH_EXPORT, SingMatrixExc, ::IEX_NAMESPACE::MathExc) + +// Attempt to remove zero scaling from matrix +DEFINE_EXC_EXP (IMATH_EXPORT, ZeroScaleExc, ::IEX_NAMESPACE::MathExc) + +// Attempt to normalize a vector of whose elementsare an integer type +DEFINE_EXC_EXP (IMATH_EXPORT, IntVecNormalizeExc, ::IEX_NAMESPACE::MathExc) + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHEXC_H diff --git a/OpenEXR/include/OpenEXR/ImathExport.h b/OpenEXR/include/OpenEXR/ImathExport.h new file mode 100644 index 0000000..4357c12 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathExport.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(IMATH_EXPORTS) + #define IMATH_EXPORT __declspec(dllexport) + #define IMATH_EXPORT_CONST extern __declspec(dllexport) + #else + #define IMATH_EXPORT __declspec(dllimport) + #define IMATH_EXPORT_CONST extern __declspec(dllimport) + #endif +#else + #define IMATH_EXPORT + #define IMATH_EXPORT_CONST extern const +#endif diff --git a/OpenEXR/include/OpenEXR/ImathForward.h b/OpenEXR/include/OpenEXR/ImathForward.h new file mode 100644 index 0000000..39d398c --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathForward.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHFORWARD_H +#define INCLUDED_IMATHFORWARD_H + +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Basic template type declarations. +// + +template class Box; +template class Color3; +template class Color4; +template class Euler; +template class Frustum; +template class FrustumTest; +template class Interval; +template class Line3; +template class Matrix33; +template class Matrix44; +template class Plane3; +template class Quat; +template class Shear6; +template class Sphere3; +template class TMatrix; +template class TMatrixBase; +template class TMatrixData; +template class Vec2; +template class Vec3; +template class Vec4; + +class Rand32; +class Rand48; + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHFORWARD_H diff --git a/OpenEXR/include/OpenEXR/ImathFrame.h b/OpenEXR/include/OpenEXR/ImathFrame.h new file mode 100644 index 0000000..95ebb66 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathFrame.h @@ -0,0 +1,192 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHFRAME_H +#define INCLUDED_IMATHFRAME_H + +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +template class Vec3; +template class Matrix44; + +// +// These methods compute a set of reference frames, defined by their +// transformation matrix, along a curve. It is designed so that the +// array of points and the array of matrices used to fetch these routines +// don't need to be ordered as the curve. +// +// A typical usage would be : +// +// m[0] = IMATH_INTERNAL_NAMESPACE::firstFrame( p[0], p[1], p[2] ); +// for( int i = 1; i < n - 1; i++ ) +// { +// m[i] = IMATH_INTERNAL_NAMESPACE::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] ); +// } +// m[n-1] = IMATH_INTERNAL_NAMESPACE::lastFrame( m[n-2], p[n-2], p[n-1] ); +// +// See Graphics Gems I for the underlying algorithm. +// + +template Matrix44 firstFrame( const Vec3&, // First point + const Vec3&, // Second point + const Vec3& ); // Third point + +template Matrix44 nextFrame( const Matrix44&, // Previous matrix + const Vec3&, // Previous point + const Vec3&, // Current point + Vec3&, // Previous tangent + Vec3& ); // Current tangent + +template Matrix44 lastFrame( const Matrix44&, // Previous matrix + const Vec3&, // Previous point + const Vec3& ); // Last point + +// +// firstFrame - Compute the first reference frame along a curve. +// +// This function returns the transformation matrix to the reference frame +// defined by the three points 'pi', 'pj' and 'pk'. Note that if the two +// vectors and are colinears, an arbitrary twist value will +// be choosen. +// +// Throw 'NullVecExc' if 'pi' and 'pj' are equals. +// + +template Matrix44 firstFrame +( + const Vec3& pi, // First point + const Vec3& pj, // Second point + const Vec3& pk ) // Third point +{ + Vec3 t = pj - pi; t.normalizeExc(); + + Vec3 n = t.cross( pk - pi ); n.normalize(); + if( n.length() == 0.0f ) + { + int i = fabs( t[0] ) < fabs( t[1] ) ? 0 : 1; + if( fabs( t[2] ) < fabs( t[i] )) i = 2; + + Vec3 v( 0.0, 0.0, 0.0 ); v[i] = 1.0; + n = t.cross( v ); n.normalize(); + } + + Vec3 b = t.cross( n ); + + Matrix44 M; + + M[0][0] = t[0]; M[0][1] = t[1]; M[0][2] = t[2]; M[0][3] = 0.0, + M[1][0] = n[0]; M[1][1] = n[1]; M[1][2] = n[2]; M[1][3] = 0.0, + M[2][0] = b[0]; M[2][1] = b[1]; M[2][2] = b[2]; M[2][3] = 0.0, + M[3][0] = pi[0]; M[3][1] = pi[1]; M[3][2] = pi[2]; M[3][3] = 1.0; + + return M; +} + +// +// nextFrame - Compute the next reference frame along a curve. +// +// This function returns the transformation matrix to the next reference +// frame defined by the previously computed transformation matrix and the +// new point and tangent vector along the curve. +// + +template Matrix44 nextFrame +( + const Matrix44& Mi, // Previous matrix + const Vec3& pi, // Previous point + const Vec3& pj, // Current point + Vec3& ti, // Previous tangent vector + Vec3& tj ) // Current tangent vector +{ + Vec3 a(0.0, 0.0, 0.0); // Rotation axis. + T r = 0.0; // Rotation angle. + + if( ti.length() != 0.0 && tj.length() != 0.0 ) + { + ti.normalize(); tj.normalize(); + T dot = ti.dot( tj ); + + // + // This is *really* necessary : + // + + if( dot > 1.0 ) dot = 1.0; + else if( dot < -1.0 ) dot = -1.0; + + r = acosf( dot ); + a = ti.cross( tj ); + } + + if( a.length() != 0.0 && r != 0.0 ) + { + Matrix44 R; R.setAxisAngle( a, r ); + Matrix44 Tj; Tj.translate( pj ); + Matrix44 Ti; Ti.translate( -pi ); + + return Mi * Ti * R * Tj; + } + else + { + Matrix44 Tr; Tr.translate( pj - pi ); + + return Mi * Tr; + } +} + +// +// lastFrame - Compute the last reference frame along a curve. +// +// This function returns the transformation matrix to the last reference +// frame defined by the previously computed transformation matrix and the +// last point along the curve. +// + +template Matrix44 lastFrame +( + const Matrix44& Mi, // Previous matrix + const Vec3& pi, // Previous point + const Vec3& pj ) // Last point +{ + Matrix44 Tr; Tr.translate( pj - pi ); + + return Mi * Tr; +} + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHFRAME_H diff --git a/OpenEXR/include/OpenEXR/ImathFrustum.h b/OpenEXR/include/OpenEXR/ImathFrustum.h new file mode 100644 index 0000000..4df92c9 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathFrustum.h @@ -0,0 +1,741 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHFRUSTUM_H +#define INCLUDED_IMATHFRUSTUM_H + + +#include "ImathVec.h" +#include "ImathPlane.h" +#include "ImathLine.h" +#include "ImathMatrix.h" +#include "ImathLimits.h" +#include "ImathFun.h" +#include "ImathNamespace.h" + +#include "IexMathExc.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// template class Frustum +// +// The frustum is always located with the eye point at the +// origin facing down -Z. This makes the Frustum class +// compatable with OpenGL (or anything that assumes a camera +// looks down -Z, hence with a right-handed coordinate system) +// but not with RenderMan which assumes the camera looks down +// +Z. Additional functions are provided for conversion from +// and from various camera coordinate spaces. +// +// nearPlane/farPlane: near/far are keywords used by Microsoft's +// compiler, so we use nearPlane/farPlane instead to avoid +// issues. + + +template +class Frustum +{ + public: + Frustum(); + Frustum(const Frustum &); + Frustum(T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho=false); + Frustum(T nearPlane, T farPlane, T fovx, T fovy, T aspect); + virtual ~Frustum(); + + //-------------------- + // Assignment operator + //-------------------- + + const Frustum & operator = (const Frustum &); + + //-------------------- + // Operators: ==, != + //-------------------- + + bool operator == (const Frustum &src) const; + bool operator != (const Frustum &src) const; + + //-------------------------------------------------------- + // Set functions change the entire state of the Frustum + //-------------------------------------------------------- + + void set(T nearPlane, T farPlane, + T left, T right, + T top, T bottom, + bool ortho=false); + + void set(T nearPlane, T farPlane, T fovx, T fovy, T aspect); + + //------------------------------------------------------ + // These functions modify an already valid frustum state + //------------------------------------------------------ + + void modifyNearAndFar(T nearPlane, T farPlane); + void setOrthographic(bool); + + //-------------- + // Access + //-------------- + + bool orthographic() const { return _orthographic; } + T nearPlane() const { return _nearPlane; } + T hither() const { return _nearPlane; } + T farPlane() const { return _farPlane; } + T yon() const { return _farPlane; } + T left() const { return _left; } + T right() const { return _right; } + T bottom() const { return _bottom; } + T top() const { return _top; } + + //----------------------------------------------------------------------- + // Sets the planes in p to be the six bounding planes of the frustum, in + // the following order: top, right, bottom, left, near, far. + // Note that the planes have normals that point out of the frustum. + // The version of this routine that takes a matrix applies that matrix + // to transform the frustum before setting the planes. + //----------------------------------------------------------------------- + + void planes(Plane3 p[6]) const; + void planes(Plane3 p[6], const Matrix44 &M) const; + + //---------------------- + // Derived Quantities + //---------------------- + + T fovx() const; + T fovy() const; + T aspect() const; + Matrix44 projectionMatrix() const; + bool degenerate() const; + + //----------------------------------------------------------------------- + // Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1 + // and -1 <= bottom <= top <= 1) of this Frustum, and returns a new + // Frustum whose near clipping-plane window is that rectangle in local + // space. + //----------------------------------------------------------------------- + + Frustum window(T left, T right, T top, T bottom) const; + + //---------------------------------------------------------- + // Projection is in screen space / Conversion from Z-Buffer + //---------------------------------------------------------- + + Line3 projectScreenToRay( const Vec2 & ) const; + Vec2 projectPointToScreen( const Vec3 & ) const; + + T ZToDepth(long zval, long min, long max) const; + T normalizedZToDepth(T zval) const; + long DepthToZ(T depth, long zmin, long zmax) const; + + T worldRadius(const Vec3 &p, T radius) const; + T screenRadius(const Vec3 &p, T radius) const; + + + protected: + + Vec2 screenToLocal( const Vec2 & ) const; + Vec2 localToScreen( const Vec2 & ) const; + + protected: + T _nearPlane; + T _farPlane; + T _left; + T _right; + T _top; + T _bottom; + bool _orthographic; +}; + + +template +inline Frustum::Frustum() +{ + set(T (0.1), + T (1000.0), + T (-1.0), + T (1.0), + T (1.0), + T (-1.0), + false); +} + +template +inline Frustum::Frustum(const Frustum &f) +{ + *this = f; +} + +template +inline Frustum::Frustum(T n, T f, T l, T r, T t, T b, bool o) +{ + set(n,f,l,r,t,b,o); +} + +template +inline Frustum::Frustum(T nearPlane, T farPlane, T fovx, T fovy, T aspect) +{ + set(nearPlane,farPlane,fovx,fovy,aspect); +} + +template +Frustum::~Frustum() +{ +} + +template +const Frustum & +Frustum::operator = (const Frustum &f) +{ + _nearPlane = f._nearPlane; + _farPlane = f._farPlane; + _left = f._left; + _right = f._right; + _top = f._top; + _bottom = f._bottom; + _orthographic = f._orthographic; + + return *this; +} + +template +bool +Frustum::operator == (const Frustum &src) const +{ + return + _nearPlane == src._nearPlane && + _farPlane == src._farPlane && + _left == src._left && + _right == src._right && + _top == src._top && + _bottom == src._bottom && + _orthographic == src._orthographic; +} + +template +inline bool +Frustum::operator != (const Frustum &src) const +{ + return !operator== (src); +} + +template +void Frustum::set(T n, T f, T l, T r, T t, T b, bool o) +{ + _nearPlane = n; + _farPlane = f; + _left = l; + _right = r; + _bottom = b; + _top = t; + _orthographic = o; +} + +template +void Frustum::modifyNearAndFar(T n, T f) +{ + if ( _orthographic ) + { + _nearPlane = n; + } + else + { + Line3 lowerLeft( Vec3(0,0,0), Vec3(_left,_bottom,-_nearPlane) ); + Line3 upperRight( Vec3(0,0,0), Vec3(_right,_top,-_nearPlane) ); + Plane3 nearPlane( Vec3(0,0,-1), n ); + + Vec3 ll,ur; + nearPlane.intersect(lowerLeft,ll); + nearPlane.intersect(upperRight,ur); + + _left = ll.x; + _right = ur.x; + _top = ur.y; + _bottom = ll.y; + _nearPlane = n; + _farPlane = f; + } + + _farPlane = f; +} + +template +void Frustum::setOrthographic(bool ortho) +{ + _orthographic = ortho; +} + +template +void Frustum::set(T nearPlane, T farPlane, T fovx, T fovy, T aspect) +{ + if (fovx != 0 && fovy != 0) + throw IEX_NAMESPACE::ArgExc ("fovx and fovy cannot both be non-zero."); + + const T two = static_cast(2); + + if (fovx != 0) + { + _right = nearPlane * Math::tan(fovx / two); + _left = -_right; + _top = ((_right - _left) / aspect) / two; + _bottom = -_top; + } + else + { + _top = nearPlane * Math::tan(fovy / two); + _bottom = -_top; + _right = (_top - _bottom) * aspect / two; + _left = -_right; + } + _nearPlane = nearPlane; + _farPlane = farPlane; + _orthographic = false; +} + +template +T Frustum::fovx() const +{ + return Math::atan2(_right,_nearPlane) - Math::atan2(_left,_nearPlane); +} + +template +T Frustum::fovy() const +{ + return Math::atan2(_top,_nearPlane) - Math::atan2(_bottom,_nearPlane); +} + +template +T Frustum::aspect() const +{ + T rightMinusLeft = _right-_left; + T topMinusBottom = _top-_bottom; + + if (abs(topMinusBottom) < 1 && + abs(rightMinusLeft) > limits::max() * abs(topMinusBottom)) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "aspect ratio cannot be computed."); + } + + return rightMinusLeft / topMinusBottom; +} + +template +Matrix44 Frustum::projectionMatrix() const +{ + T rightPlusLeft = _right+_left; + T rightMinusLeft = _right-_left; + + T topPlusBottom = _top+_bottom; + T topMinusBottom = _top-_bottom; + + T farPlusNear = _farPlane+_nearPlane; + T farMinusNear = _farPlane-_nearPlane; + + if ((abs(rightMinusLeft) < 1 && + abs(rightPlusLeft) > limits::max() * abs(rightMinusLeft)) || + (abs(topMinusBottom) < 1 && + abs(topPlusBottom) > limits::max() * abs(topMinusBottom)) || + (abs(farMinusNear) < 1 && + abs(farPlusNear) > limits::max() * abs(farMinusNear))) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + if ( _orthographic ) + { + T tx = -rightPlusLeft / rightMinusLeft; + T ty = -topPlusBottom / topMinusBottom; + T tz = -farPlusNear / farMinusNear; + + if ((abs(rightMinusLeft) < 1 && + 2 > limits::max() * abs(rightMinusLeft)) || + (abs(topMinusBottom) < 1 && + 2 > limits::max() * abs(topMinusBottom)) || + (abs(farMinusNear) < 1 && + 2 > limits::max() * abs(farMinusNear))) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + T A = 2 / rightMinusLeft; + T B = 2 / topMinusBottom; + T C = -2 / farMinusNear; + + return Matrix44( A, 0, 0, 0, + 0, B, 0, 0, + 0, 0, C, 0, + tx, ty, tz, 1.f ); + } + else + { + T A = rightPlusLeft / rightMinusLeft; + T B = topPlusBottom / topMinusBottom; + T C = -farPlusNear / farMinusNear; + + T farTimesNear = -2 * _farPlane * _nearPlane; + if (abs(farMinusNear) < 1 && + abs(farTimesNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + T D = farTimesNear / farMinusNear; + + T twoTimesNear = 2 * _nearPlane; + + if ((abs(rightMinusLeft) < 1 && + abs(twoTimesNear) > limits::max() * abs(rightMinusLeft)) || + (abs(topMinusBottom) < 1 && + abs(twoTimesNear) > limits::max() * abs(topMinusBottom))) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + T E = twoTimesNear / rightMinusLeft; + T F = twoTimesNear / topMinusBottom; + + return Matrix44( E, 0, 0, 0, + 0, F, 0, 0, + A, B, C, -1, + 0, 0, D, 0 ); + } +} + +template +bool Frustum::degenerate() const +{ + return (_nearPlane == _farPlane) || + (_left == _right) || + (_top == _bottom); +} + +template +Frustum Frustum::window(T l, T r, T t, T b) const +{ + // move it to 0->1 space + + Vec2 bl = screenToLocal( Vec2(l,b) ); + Vec2 tr = screenToLocal( Vec2(r,t) ); + + return Frustum(_nearPlane, _farPlane, bl.x, tr.x, tr.y, bl.y, _orthographic); +} + + +template +Vec2 Frustum::screenToLocal(const Vec2 &s) const +{ + return Vec2( _left + (_right-_left) * (1.f+s.x) / 2.f, + _bottom + (_top-_bottom) * (1.f+s.y) / 2.f ); +} + +template +Vec2 Frustum::localToScreen(const Vec2 &p) const +{ + T leftPlusRight = _left - T (2) * p.x + _right; + T leftMinusRight = _left-_right; + T bottomPlusTop = _bottom - T (2) * p.y + _top; + T bottomMinusTop = _bottom-_top; + + if ((abs(leftMinusRight) < T (1) && + abs(leftPlusRight) > limits::max() * abs(leftMinusRight)) || + (abs(bottomMinusTop) < T (1) && + abs(bottomPlusTop) > limits::max() * abs(bottomMinusTop))) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: " + "local-to-screen transformation cannot be computed"); + } + + return Vec2( leftPlusRight / leftMinusRight, + bottomPlusTop / bottomMinusTop ); +} + +template +Line3 Frustum::projectScreenToRay(const Vec2 &p) const +{ + Vec2 point = screenToLocal(p); + if (orthographic()) + return Line3( Vec3(point.x,point.y, 0.0), + Vec3(point.x,point.y,-1.0)); + else + return Line3( Vec3(0, 0, 0), Vec3(point.x,point.y,-_nearPlane)); +} + +template +Vec2 Frustum::projectPointToScreen(const Vec3 &point) const +{ + if (orthographic() || point.z == T (0)) + return localToScreen( Vec2( point.x, point.y ) ); + else + return localToScreen( Vec2( point.x * _nearPlane / -point.z, + point.y * _nearPlane / -point.z ) ); +} + +template +T Frustum::ZToDepth(long zval,long zmin,long zmax) const +{ + int zdiff = zmax - zmin; + + if (zdiff == 0) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad call to Frustum::ZToDepth: zmax == zmin"); + } + + if ( zval > zmax+1 ) zval -= zdiff; + + T fzval = (T(zval) - T(zmin)) / T(zdiff); + return normalizedZToDepth(fzval); +} + +template +T Frustum::normalizedZToDepth(T zval) const +{ + T Zp = zval * 2.0 - 1; + + if ( _orthographic ) + { + return -(Zp*(_farPlane-_nearPlane) + (_farPlane+_nearPlane))/2; + } + else + { + T farTimesNear = 2 * _farPlane * _nearPlane; + T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane; + + if (abs(farMinusNear) < 1 && + abs(farTimesNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Frustum::normalizedZToDepth cannot be computed. The " + "near and far clipping planes of the viewing frustum " + "may be too close to each other"); + } + + return farTimesNear / farMinusNear; + } +} + +template +long Frustum::DepthToZ(T depth,long zmin,long zmax) const +{ + long zdiff = zmax - zmin; + T farMinusNear = _farPlane-_nearPlane; + + if ( _orthographic ) + { + T farPlusNear = 2*depth + _farPlane + _nearPlane; + + if (abs(farMinusNear) < 1 && + abs(farPlusNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: near and far clipping planes " + "are too close to each other"); + } + + T Zp = -farPlusNear/farMinusNear; + return long(0.5*(Zp+1)*zdiff) + zmin; + } + else + { + // Perspective + + T farTimesNear = 2*_farPlane*_nearPlane; + if (abs(depth) < 1 && + abs(farTimesNear) > limits::max() * abs(depth)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad call to DepthToZ function: value of `depth' " + "is too small"); + } + + T farPlusNear = farTimesNear/depth + _farPlane + _nearPlane; + if (abs(farMinusNear) < 1 && + abs(farPlusNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: near and far clipping planes " + "are too close to each other"); + } + + T Zp = farPlusNear/farMinusNear; + return long(0.5*(Zp+1)*zdiff) + zmin; + } +} + +template +T Frustum::screenRadius(const Vec3 &p, T radius) const +{ + // Derivation: + // Consider X-Z plane. + // X coord of projection of p = xp = p.x * (-_nearPlane / p.z) + // Let q be p + (radius, 0, 0). + // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z) + // X coord of projection of segment from p to q = r = xp - xq + // = radius * (-_nearPlane / p.z) + // A similar analysis holds in the Y-Z plane. + // So r is the quantity we want to return. + + if (abs(p.z) > 1 || abs(-_nearPlane) < limits::max() * abs(p.z)) + { + return radius * (-_nearPlane / p.z); + } + else + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad call to Frustum::screenRadius: the magnitude of `p' " + "is too small"); + } + + return radius * (-_nearPlane / p.z); +} + +template +T Frustum::worldRadius(const Vec3 &p, T radius) const +{ + if (abs(-_nearPlane) > 1 || abs(p.z) < limits::max() * abs(-_nearPlane)) + { + return radius * (p.z / -_nearPlane); + } + else + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: the near clipping plane is too " + "close to zero"); + } +} + +template +void Frustum::planes(Plane3 p[6]) const +{ + // + // Plane order: Top, Right, Bottom, Left, Near, Far. + // Normals point outwards. + // + + if (! _orthographic) + { + Vec3 a( _left, _bottom, -_nearPlane); + Vec3 b( _left, _top, -_nearPlane); + Vec3 c( _right, _top, -_nearPlane); + Vec3 d( _right, _bottom, -_nearPlane); + Vec3 o(0,0,0); + + p[0].set( o, c, b ); + p[1].set( o, d, c ); + p[2].set( o, a, d ); + p[3].set( o, b, a ); + } + else + { + p[0].set( Vec3( 0, 1, 0), _top ); + p[1].set( Vec3( 1, 0, 0), _right ); + p[2].set( Vec3( 0,-1, 0),-_bottom ); + p[3].set( Vec3(-1, 0, 0),-_left ); + } + p[4].set( Vec3(0, 0, 1), -_nearPlane ); + p[5].set( Vec3(0, 0,-1), _farPlane ); +} + + +template +void Frustum::planes(Plane3 p[6], const Matrix44 &M) const +{ + // + // Plane order: Top, Right, Bottom, Left, Near, Far. + // Normals point outwards. + // + + Vec3 a = Vec3( _left, _bottom, -_nearPlane) * M; + Vec3 b = Vec3( _left, _top, -_nearPlane) * M; + Vec3 c = Vec3( _right, _top, -_nearPlane) * M; + Vec3 d = Vec3( _right, _bottom, -_nearPlane) * M; + if (! _orthographic) + { + double s = _farPlane / double(_nearPlane); + T farLeft = (T) (s * _left); + T farRight = (T) (s * _right); + T farTop = (T) (s * _top); + T farBottom = (T) (s * _bottom); + Vec3 e = Vec3( farLeft, farBottom, -_farPlane) * M; + Vec3 f = Vec3( farLeft, farTop, -_farPlane) * M; + Vec3 g = Vec3( farRight, farTop, -_farPlane) * M; + Vec3 o = Vec3(0,0,0) * M; + p[0].set( o, c, b ); + p[1].set( o, d, c ); + p[2].set( o, a, d ); + p[3].set( o, b, a ); + p[4].set( a, d, c ); + p[5].set( e, f, g ); + } + else + { + Vec3 e = Vec3( _left, _bottom, -_farPlane) * M; + Vec3 f = Vec3( _left, _top, -_farPlane) * M; + Vec3 g = Vec3( _right, _top, -_farPlane) * M; + Vec3 h = Vec3( _right, _bottom, -_farPlane) * M; + p[0].set( c, g, f ); + p[1].set( d, h, g ); + p[2].set( a, e, h ); + p[3].set( b, f, e ); + p[4].set( a, d, c ); + p[5].set( e, f, g ); + } +} + +typedef Frustum Frustumf; +typedef Frustum Frustumd; + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + + +#if defined _WIN32 || defined _WIN64 + #ifdef _redef_near + #define near + #endif + #ifdef _redef_far + #define far + #endif +#endif + +#endif // INCLUDED_IMATHFRUSTUM_H diff --git a/OpenEXR/include/OpenEXR/ImathFrustumTest.h b/OpenEXR/include/OpenEXR/ImathFrustumTest.h new file mode 100644 index 0000000..d9c10cc --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathFrustumTest.h @@ -0,0 +1,417 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHFRUSTUMTEST_H +#define INCLUDED_IMATHFRUSTUMTEST_H + +//------------------------------------------------------------------------- +// +// This file contains algorithms applied to or in conjunction with +// Frustum visibility testing (Imath::Frustum). +// +// Methods for frustum-based rejection of primitives are contained here. +// +//------------------------------------------------------------------------- + +#include "ImathFrustum.h" +#include "ImathBox.h" +#include "ImathSphere.h" +#include "ImathMatrix.h" +#include "ImathVec.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +///////////////////////////////////////////////////////////////// +// FrustumTest +// +// template class FrustumTest +// +// This is a helper class, designed to accelerate the case +// where many tests are made against the same frustum. +// That's a really common case. +// +// The acceleration is achieved by pre-computing the planes of +// the frustum, along with the ablsolute values of the plane normals. +// + + + +////////////////////////////////////////////////////////////////// +// How to use this +// +// Given that you already have: +// Imath::Frustum myFrustum +// Imath::Matrix44 myCameraWorldMatrix +// +// First, make a frustum test object: +// FrustumTest myFrustumTest(myFrustum, myCameraWorldMatrix) +// +// Whenever the camera or frustum changes, call: +// myFrustumTest.setFrustum(myFrustum, myCameraWorldMatrix) +// +// For each object you want to test for visibility, call: +// myFrustumTest.isVisible(myBox) +// myFrustumTest.isVisible(mySphere) +// myFrustumTest.isVisible(myVec3) +// myFrustumTest.completelyContains(myBox) +// myFrustumTest.completelyContains(mySphere) +// + + + + +////////////////////////////////////////////////////////////////// +// Explanation of how it works +// +// +// We store six world-space Frustum planes (nx, ny, nz, offset) +// +// Points: To test a Vec3 for visibility, test it against each plane +// using the normal (v dot n - offset) method. (the result is exact) +// +// BBoxes: To test an axis-aligned bbox, test the center against each plane +// using the normal (v dot n - offset) method, but offset by the +// box extents dot the abs of the plane normal. (the result is NOT +// exact, but will not return false-negatives.) +// +// Spheres: To test a sphere, test the center against each plane +// using the normal (v dot n - offset) method, but offset by the +// sphere's radius. (the result is NOT exact, but will not return +// false-negatives.) +// +// +// SPECIAL NOTE: "Where are the dot products?" +// Actual dot products are currently slow for most SIMD architectures. +// In order to keep this code optimization-ready, the dot products +// are all performed using vector adds and multipies. +// +// In order to do this, the plane equations are stored in "transpose" +// form, with the X components grouped into an X vector, etc. +// + + +template +class FrustumTest +{ +public: + FrustumTest() + { + Frustum frust; + Matrix44 cameraMat; + cameraMat.makeIdentity(); + setFrustum(frust, cameraMat); + } + FrustumTest(const Frustum &frustum, const Matrix44 &cameraMat) + { + setFrustum(frustum, cameraMat); + } + + //////////////////////////////////////////////////////////////////// + // setFrustum() + // This updates the frustum test with a new frustum and matrix. + // This should usually be called just once per frame. + void setFrustum(const Frustum &frustum, const Matrix44 &cameraMat); + + //////////////////////////////////////////////////////////////////// + // isVisible() + // Check to see if shapes are visible. + bool isVisible(const Sphere3 &sphere) const; + bool isVisible(const Box > &box) const; + bool isVisible(const Vec3 &vec) const; + + //////////////////////////////////////////////////////////////////// + // completelyContains() + // Check to see if shapes are entirely contained. + bool completelyContains(const Sphere3 &sphere) const; + bool completelyContains(const Box > &box) const; + + // These next items are kept primarily for debugging tools. + // It's useful for drawing the culling environment, and also + // for getting an "outside view" of the culling frustum. + IMATH_INTERNAL_NAMESPACE::Matrix44 cameraMat() const {return cameraMatrix;} + IMATH_INTERNAL_NAMESPACE::Frustum currentFrustum() const {return currFrustum;} + +protected: + // To understand why the planes are stored this way, see + // the SPECIAL NOTE above. + Vec3 planeNormX[2]; // The X compunents from 6 plane equations + Vec3 planeNormY[2]; // The Y compunents from 6 plane equations + Vec3 planeNormZ[2]; // The Z compunents from 6 plane equations + + Vec3 planeOffsetVec[2]; // The distance offsets from 6 plane equations + + // The absolute values are stored to assist with bounding box tests. + Vec3 planeNormAbsX[2]; // The abs(X) compunents from 6 plane equations + Vec3 planeNormAbsY[2]; // The abs(X) compunents from 6 plane equations + Vec3 planeNormAbsZ[2]; // The abs(X) compunents from 6 plane equations + + // These are kept primarily for debugging tools. + Frustum currFrustum; + Matrix44 cameraMatrix; +}; + + +//////////////////////////////////////////////////////////////////// +// setFrustum() +// This should usually only be called once per frame, or however +// often the camera moves. +template +void FrustumTest::setFrustum(const Frustum &frustum, + const Matrix44 &cameraMat) +{ + Plane3 frustumPlanes[6]; + frustum.planes(frustumPlanes, cameraMat); + + // Here's where we effectively transpose the plane equations. + // We stuff all six X's into the two planeNormX vectors, etc. + for (int i = 0; i < 2; ++i) + { + int index = i * 3; + + planeNormX[i] = Vec3(frustumPlanes[index + 0].normal.x, + frustumPlanes[index + 1].normal.x, + frustumPlanes[index + 2].normal.x); + planeNormY[i] = Vec3(frustumPlanes[index + 0].normal.y, + frustumPlanes[index + 1].normal.y, + frustumPlanes[index + 2].normal.y); + planeNormZ[i] = Vec3(frustumPlanes[index + 0].normal.z, + frustumPlanes[index + 1].normal.z, + frustumPlanes[index + 2].normal.z); + + planeNormAbsX[i] = Vec3(IMATH_INTERNAL_NAMESPACE::abs(planeNormX[i].x), + IMATH_INTERNAL_NAMESPACE::abs(planeNormX[i].y), + IMATH_INTERNAL_NAMESPACE::abs(planeNormX[i].z)); + planeNormAbsY[i] = Vec3(IMATH_INTERNAL_NAMESPACE::abs(planeNormY[i].x), + IMATH_INTERNAL_NAMESPACE::abs(planeNormY[i].y), + IMATH_INTERNAL_NAMESPACE::abs(planeNormY[i].z)); + planeNormAbsZ[i] = Vec3(IMATH_INTERNAL_NAMESPACE::abs(planeNormZ[i].x), + IMATH_INTERNAL_NAMESPACE::abs(planeNormZ[i].y), + IMATH_INTERNAL_NAMESPACE::abs(planeNormZ[i].z)); + + planeOffsetVec[i] = Vec3(frustumPlanes[index + 0].distance, + frustumPlanes[index + 1].distance, + frustumPlanes[index + 2].distance); + } + currFrustum = frustum; + cameraMatrix = cameraMat; +} + + +//////////////////////////////////////////////////////////////////// +// isVisible(Sphere) +// Returns true if any part of the sphere is inside +// the frustum. +// The result MAY return close false-positives, but not false-negatives. +// +template +bool FrustumTest::isVisible(const Sphere3 &sphere) const +{ + Vec3 center = sphere.center; + Vec3 radiusVec = Vec3(sphere.radius, sphere.radius, sphere.radius); + + // This is a vertical dot-product on three vectors at once. + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + + planeNormZ[0] * center.z + - radiusVec + - planeOffsetVec[0]; + + if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) + return false; + + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + + planeNormZ[1] * center.z + - radiusVec + - planeOffsetVec[1]; + + if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////// +// completelyContains(Sphere) +// Returns true if every part of the sphere is inside +// the frustum. +// The result MAY return close false-negatives, but not false-positives. +// +template +bool FrustumTest::completelyContains(const Sphere3 &sphere) const +{ + Vec3 center = sphere.center; + Vec3 radiusVec = Vec3(sphere.radius, sphere.radius, sphere.radius); + + // This is a vertical dot-product on three vectors at once. + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + + planeNormZ[0] * center.z + + radiusVec + - planeOffsetVec[0]; + + if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) + return false; + + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + + planeNormZ[1] * center.z + + radiusVec + - planeOffsetVec[1]; + + if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////// +// isVisible(Box) +// Returns true if any part of the axis-aligned box +// is inside the frustum. +// The result MAY return close false-positives, but not false-negatives. +// +template +bool FrustumTest::isVisible(const Box > &box) const +{ + if (box.isEmpty()) + return false; + + Vec3 center = (box.min + box.max) / 2; + Vec3 extent = (box.max - center); + + // This is a vertical dot-product on three vectors at once. + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + + planeNormZ[0] * center.z + - planeNormAbsX[0] * extent.x + - planeNormAbsY[0] * extent.y + - planeNormAbsZ[0] * extent.z + - planeOffsetVec[0]; + + if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) + return false; + + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + + planeNormZ[1] * center.z + - planeNormAbsX[1] * extent.x + - planeNormAbsY[1] * extent.y + - planeNormAbsZ[1] * extent.z + - planeOffsetVec[1]; + + if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////// +// completelyContains(Box) +// Returns true if every part of the axis-aligned box +// is inside the frustum. +// The result MAY return close false-negatives, but not false-positives. +// +template +bool FrustumTest::completelyContains(const Box > &box) const +{ + if (box.isEmpty()) + return false; + + Vec3 center = (box.min + box.max) / 2; + Vec3 extent = (box.max - center); + + // This is a vertical dot-product on three vectors at once. + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + + planeNormZ[0] * center.z + + planeNormAbsX[0] * extent.x + + planeNormAbsY[0] * extent.y + + planeNormAbsZ[0] * extent.z + - planeOffsetVec[0]; + + if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) + return false; + + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + + planeNormZ[1] * center.z + + planeNormAbsX[1] * extent.x + + planeNormAbsY[1] * extent.y + + planeNormAbsZ[1] * extent.z + - planeOffsetVec[1]; + + if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) + return false; + + return true; +} + + +//////////////////////////////////////////////////////////////////// +// isVisible(Vec3) +// Returns true if the point is inside the frustum. +// +template +bool FrustumTest::isVisible(const Vec3 &vec) const +{ + // This is a vertical dot-product on three vectors at once. + Vec3 d0 = (planeNormX[0] * vec.x) + + (planeNormY[0] * vec.y) + + (planeNormZ[0] * vec.z) + - planeOffsetVec[0]; + + if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) + return false; + + Vec3 d1 = (planeNormX[1] * vec.x) + + (planeNormY[1] * vec.y) + + (planeNormZ[1] * vec.z) + - planeOffsetVec[1]; + + if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) + return false; + + return true; +} + + +typedef FrustumTest FrustumTestf; +typedef FrustumTest FrustumTestd; + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHFRUSTUMTEST_H diff --git a/OpenEXR/include/OpenEXR/ImathFun.h b/OpenEXR/include/OpenEXR/ImathFun.h new file mode 100644 index 0000000..068c682 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathFun.h @@ -0,0 +1,269 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHFUN_H +#define INCLUDED_IMATHFUN_H + +//----------------------------------------------------------------------------- +// +// Miscellaneous utility functions +// +//----------------------------------------------------------------------------- + +#include "ImathExport.h" +#include "ImathLimits.h" +#include "ImathInt64.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +template +inline T +abs (T a) +{ + return (a > T(0)) ? a : -a; +} + + +template +inline int +sign (T a) +{ + return (a > T(0))? 1 : ((a < T(0)) ? -1 : 0); +} + + +template +inline T +lerp (T a, T b, Q t) +{ + return (T) (a * (1 - t) + b * t); +} + + +template +inline T +ulerp (T a, T b, Q t) +{ + return (T) ((a > b)? (a - (a - b) * t): (a + (b - a) * t)); +} + + +template +inline T +lerpfactor(T m, T a, T b) +{ + // + // Return how far m is between a and b, that is return t such that + // if: + // t = lerpfactor(m, a, b); + // then: + // m = lerp(a, b, t); + // + // If a==b, return 0. + // + + T d = b - a; + T n = m - a; + + if (abs(d) > T(1) || abs(n) < limits::max() * abs(d)) + return n / d; + + return T(0); +} + + +template +inline T +clamp (T a, T l, T h) +{ + return (a < l)? l : ((a > h)? h : a); +} + + +template +inline int +cmp (T a, T b) +{ + return IMATH_INTERNAL_NAMESPACE::sign (a - b); +} + + +template +inline int +cmpt (T a, T b, T t) +{ + return (IMATH_INTERNAL_NAMESPACE::abs (a - b) <= t)? 0 : cmp (a, b); +} + + +template +inline bool +iszero (T a, T t) +{ + return (IMATH_INTERNAL_NAMESPACE::abs (a) <= t) ? 1 : 0; +} + + +template +inline bool +equal (T1 a, T2 b, T3 t) +{ + return IMATH_INTERNAL_NAMESPACE::abs (a - b) <= t; +} + +template +inline int +floor (T x) +{ + return (x >= 0)? int (x): -(int (-x) + (-x > int (-x))); +} + + +template +inline int +ceil (T x) +{ + return -floor (-x); +} + +template +inline int +trunc (T x) +{ + return (x >= 0) ? int(x) : -int(-x); +} + + +// +// Integer division and remainder where the +// remainder of x/y has the same sign as x: +// +// divs(x,y) == (abs(x) / abs(y)) * (sign(x) * sign(y)) +// mods(x,y) == x - y * divs(x,y) +// + +inline int +divs (int x, int y) +{ + return (x >= 0)? ((y >= 0)? ( x / y): -( x / -y)): + ((y >= 0)? -(-x / y): (-x / -y)); +} + + +inline int +mods (int x, int y) +{ + return (x >= 0)? ((y >= 0)? ( x % y): ( x % -y)): + ((y >= 0)? -(-x % y): -(-x % -y)); +} + + +// +// Integer division and remainder where the +// remainder of x/y is always positive: +// +// divp(x,y) == floor (double(x) / double (y)) +// modp(x,y) == x - y * divp(x,y) +// + +inline int +divp (int x, int y) +{ + return (x >= 0)? ((y >= 0)? ( x / y): -( x / -y)): + ((y >= 0)? -((y-1-x) / y): ((-y-1-x) / -y)); +} + + +inline int +modp (int x, int y) +{ + return x - y * divp (x, y); +} + +//---------------------------------------------------------- +// Successor and predecessor for floating-point numbers: +// +// succf(f) returns float(f+e), where e is the smallest +// positive number such that float(f+e) != f. +// +// predf(f) returns float(f-e), where e is the smallest +// positive number such that float(f-e) != f. +// +// succd(d) returns double(d+e), where e is the smallest +// positive number such that double(d+e) != d. +// +// predd(d) returns double(d-e), where e is the smallest +// positive number such that double(d-e) != d. +// +// Exceptions: If the input value is an infinity or a nan, +// succf(), predf(), succd(), and predd() all +// return the input value without changing it. +// +//---------------------------------------------------------- + +IMATH_EXPORT float succf (float f); +IMATH_EXPORT float predf (float f); + +IMATH_EXPORT double succd (double d); +IMATH_EXPORT double predd (double d); + +// +// Return true if the number is not a NaN or Infinity. +// + +inline bool +finitef (float f) +{ + union {float f; int i;} u; + u.f = f; + + return (u.i & 0x7f800000) != 0x7f800000; +} + +inline bool +finited (double d) +{ + union {double d; Int64 i;} u; + u.d = d; + + return (u.i & 0x7ff0000000000000LL) != 0x7ff0000000000000LL; +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHFUN_H diff --git a/OpenEXR/include/OpenEXR/ImathGL.h b/OpenEXR/include/OpenEXR/ImathGL.h new file mode 100644 index 0000000..e3b9405 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathGL.h @@ -0,0 +1,166 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHGL_H +#define INCLUDED_IMATHGL_H + +#include + +#include "ImathVec.h" +#include "ImathMatrix.h" +#include "IexMathExc.h" +#include "ImathFun.h" +#include "ImathNamespace.h" + +inline void glVertex ( const IMATH_INTERNAL_NAMESPACE::V3f &v ) { glVertex3f(v.x,v.y,v.z); } +inline void glVertex ( const IMATH_INTERNAL_NAMESPACE::V2f &v ) { glVertex2f(v.x,v.y); } +inline void glNormal ( const IMATH_INTERNAL_NAMESPACE::V3f &n ) { glNormal3f(n.x,n.y,n.z); } +inline void glColor ( const IMATH_INTERNAL_NAMESPACE::V3f &c ) { glColor3f(c.x,c.y,c.z); } +inline void glTranslate ( const IMATH_INTERNAL_NAMESPACE::V3f &t ) { glTranslatef(t.x,t.y,t.z); } + +inline void glTexCoord( const IMATH_INTERNAL_NAMESPACE::V2f &t ) +{ + glTexCoord2f(t.x,t.y); +} + +inline void glDisableTexture() +{ + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glActiveTexture(GL_TEXTURE0); +} + +namespace { + +const float GL_FLOAT_MAX = 1.8e+19; // sqrt (FLT_MAX) + +inline bool +badFloat (float f) +{ + return !IMATH_INTERNAL_NAMESPACE::finitef (f) || f < - GL_FLOAT_MAX || f > GL_FLOAT_MAX; +} + +} // namespace + +inline void +throwBadMatrix (const IMATH_INTERNAL_NAMESPACE::M44f& m) +{ + if (badFloat (m[0][0]) || + badFloat (m[0][1]) || + badFloat (m[0][2]) || + badFloat (m[0][3]) || + badFloat (m[1][0]) || + badFloat (m[1][1]) || + badFloat (m[1][2]) || + badFloat (m[1][3]) || + badFloat (m[2][0]) || + badFloat (m[2][1]) || + badFloat (m[2][2]) || + badFloat (m[2][3]) || + badFloat (m[3][0]) || + badFloat (m[3][1]) || + badFloat (m[3][2]) || + badFloat (m[3][3])) + throw IEX_NAMESPACE::OverflowExc ("GL matrix overflow"); +} + +inline void +glMultMatrix( const IMATH_INTERNAL_NAMESPACE::M44f& m ) +{ + throwBadMatrix (m); + glMultMatrixf( (GLfloat*)m[0] ); +} + +inline void +glMultMatrix( const IMATH_INTERNAL_NAMESPACE::M44f* m ) +{ + throwBadMatrix (*m); + glMultMatrixf( (GLfloat*)(*m)[0] ); +} + +inline void +glLoadMatrix( const IMATH_INTERNAL_NAMESPACE::M44f& m ) +{ + throwBadMatrix (m); + glLoadMatrixf( (GLfloat*)m[0] ); +} + +inline void +glLoadMatrix( const IMATH_INTERNAL_NAMESPACE::M44f* m ) +{ + throwBadMatrix (*m); + glLoadMatrixf( (GLfloat*)(*m)[0] ); +} + + + + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// Class objects that push/pop the GL state. These objects assist with +// proper cleanup of the state when exceptions are thrown. +// + +class GLPushMatrix { + public: + + GLPushMatrix () { glPushMatrix(); } + ~GLPushMatrix() { glPopMatrix(); } +}; + +class GLPushAttrib { + public: + + GLPushAttrib (GLbitfield mask) { glPushAttrib (mask); } + ~GLPushAttrib() { glPopAttrib(); } +}; + +class GLBegin { + public: + + GLBegin (GLenum mode) { glBegin (mode); } + ~GLBegin() { glEnd(); } +}; + + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImathGLU.h b/OpenEXR/include/OpenEXR/ImathGLU.h new file mode 100644 index 0000000..52a43af --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathGLU.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHGLU_H +#define INCLUDED_IMATHGLU_H + +#include +#include + +#include "ImathVec.h" + +inline +void +gluLookAt(const IMATH_INTERNAL_NAMESPACE::V3f &pos, const IMATH_INTERNAL_NAMESPACE::V3f &interest, const IMATH_INTERNAL_NAMESPACE::V3f &up) +{ + gluLookAt(pos.x, pos.y, pos.z, + interest.x, interest.y, interest.z, + up.x, up.y, up.z); +} + +#endif diff --git a/OpenEXR/include/OpenEXR/ImathHalfLimits.h b/OpenEXR/include/OpenEXR/ImathHalfLimits.h new file mode 100644 index 0000000..de54bd6 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathHalfLimits.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHHALFLIMITS_H +#define INCLUDED_IMATHHALFLIMITS_H + +//-------------------------------------------------- +// +// Imath-style limits for class half. +// +//-------------------------------------------------- + +#include "ImathLimits.h" +#include "ImathNamespace.h" + +#include "half.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template <> +struct limits +{ + static float min() {return -HALF_MAX;} + static float max() {return HALF_MAX;} + static float smallest() {return HALF_MIN;} + static float epsilon() {return HALF_EPSILON;} + static bool isIntegral() {return false;} + static bool isSigned() {return true;} +}; + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHHALFLIMITS_H diff --git a/OpenEXR/include/OpenEXR/ImathInt64.h b/OpenEXR/include/OpenEXR/ImathInt64.h new file mode 100644 index 0000000..3b867dc --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathInt64.h @@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATH_INT64_H +#define INCLUDED_IMATH_INT64_H + +//---------------------------------------------------------------------------- +// +// Int64 -- unsigned 64-bit integers +// +//---------------------------------------------------------------------------- + +#include "ImathNamespace.h" +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +#if (defined _WIN32 || defined _WIN64) && _MSC_VER >= 1300 + typedef unsigned __int64 Int64; +#elif ULONG_MAX == 18446744073709551615LU + typedef long unsigned int Int64; +#else + typedef long long unsigned int Int64; +#endif + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATH_INT64_H diff --git a/OpenEXR/include/OpenEXR/ImathInterval.h b/OpenEXR/include/OpenEXR/ImathInterval.h new file mode 100644 index 0000000..0062f4d --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathInterval.h @@ -0,0 +1,226 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHINTERVAL_H +#define INCLUDED_IMATHINTERVAL_H + + +//------------------------------------------------------------------- +// +// class Imath::Interval +// -------------------------------- +// +// An Interval has a min and a max and some miscellaneous +// functions. It is basically a Box that allows T to be +// a scalar. +// +//------------------------------------------------------------------- + +#include "ImathVec.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +class Interval +{ + public: + + //------------------------- + // Data Members are public + //------------------------- + + T min; + T max; + + //----------------------------------------------------- + // Constructors - an "empty" Interval is created by default + //----------------------------------------------------- + + Interval(); + Interval(const T& point); + Interval(const T& minT, const T& maxT); + + //-------------------------------- + // Operators: we get != from STL + //-------------------------------- + + bool operator == (const Interval &src) const; + + //------------------ + // Interval manipulation + //------------------ + + void makeEmpty(); + void extendBy(const T& point); + void extendBy(const Interval& interval); + + //--------------------------------------------------- + // Query functions - these compute results each time + //--------------------------------------------------- + + T size() const; + T center() const; + bool intersects(const T &point) const; + bool intersects(const Interval &interval) const; + + //---------------- + // Classification + //---------------- + + bool hasVolume() const; + bool isEmpty() const; +}; + + +//-------------------- +// Convenient typedefs +//-------------------- + + +typedef Interval Intervalf; +typedef Interval Intervald; +typedef Interval Intervals; +typedef Interval Intervali; + +//---------------- +// Implementation +//---------------- + + +template +inline Interval::Interval() +{ + makeEmpty(); +} + +template +inline Interval::Interval(const T& point) +{ + min = point; + max = point; +} + +template +inline Interval::Interval(const T& minV, const T& maxV) +{ + min = minV; + max = maxV; +} + +template +inline bool +Interval::operator == (const Interval &src) const +{ + return (min == src.min && max == src.max); +} + +template +inline void +Interval::makeEmpty() +{ + min = limits::max(); + max = limits::min(); +} + +template +inline void +Interval::extendBy(const T& point) +{ + if ( point < min ) + min = point; + + if ( point > max ) + max = point; +} + +template +inline void +Interval::extendBy(const Interval& interval) +{ + if ( interval.min < min ) + min = interval.min; + + if ( interval.max > max ) + max = interval.max; +} + +template +inline bool +Interval::intersects(const T& point) const +{ + return point >= min && point <= max; +} + +template +inline bool +Interval::intersects(const Interval& interval) const +{ + return interval.max >= min && interval.min <= max; +} + +template +inline T +Interval::size() const +{ + return max-min; +} + +template +inline T +Interval::center() const +{ + return (max+min)/2; +} + +template +inline bool +Interval::isEmpty() const +{ + return max < min; +} + +template +inline bool Interval::hasVolume() const +{ + return max > min; +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHINTERVAL_H diff --git a/OpenEXR/include/OpenEXR/ImathLimits.h b/OpenEXR/include/OpenEXR/ImathLimits.h new file mode 100644 index 0000000..eb6f999 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathLimits.h @@ -0,0 +1,268 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHLIMITS_H +#define INCLUDED_IMATHLIMITS_H + +//---------------------------------------------------------------- +// +// Limitations of the basic C++ numerical data types +// +//---------------------------------------------------------------- + +#include "ImathNamespace.h" +#include +#include + +//------------------------------------------ +// In Windows, min and max are macros. Yay. +//------------------------------------------ + +#if defined _WIN32 || defined _WIN64 + #ifdef min + #undef min + #endif + #ifdef max + #undef max + #endif +#endif + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +//----------------------------------------------------------------- +// +// Template class limits returns information about the limits +// of numerical data type T: +// +// min() largest possible negative value of type T +// +// max() largest possible positive value of type T +// +// smallest() smallest possible positive value of type T +// (for float and double: smallest normalized +// positive value) +// +// epsilon() smallest possible e of type T, for which +// 1 + e != 1 +// +// isIntegral() returns true if T is an integral type +// +// isSigned() returns true if T is signed +// +// Class limits is useful to implement template classes or +// functions which depend on the limits of a numerical type +// which is not known in advance; for example: +// +// template max (T x[], int n) +// { +// T m = limits::min(); +// +// for (int i = 0; i < n; i++) +// if (m < x[i]) +// m = x[i]; +// +// return m; +// } +// +// Class limits has been implemented for the following types: +// +// char, signed char, unsigned char +// short, unsigned short +// int, unsigned int +// long, unsigned long +// float +// double +// long double +// +// Class limits has only static member functions, all of which +// are implemented as inlines. No objects of type limits are +// ever created. +// +//----------------------------------------------------------------- + + +template struct limits +{ + static T min(); + static T max(); + static T smallest(); + static T epsilon(); + static bool isIntegral(); + static bool isSigned(); +}; + + +//--------------- +// Implementation +//--------------- + +template <> +struct limits +{ + static char min() {return CHAR_MIN;} + static char max() {return CHAR_MAX;} + static char smallest() {return 1;} + static char epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return (char) ~0 < 0;} +}; + +template <> +struct limits +{ + static signed char min() {return SCHAR_MIN;} + static signed char max() {return SCHAR_MAX;} + static signed char smallest() {return 1;} + static signed char epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return true;} +}; + +template <> +struct limits +{ + static unsigned char min() {return 0;} + static unsigned char max() {return UCHAR_MAX;} + static unsigned char smallest() {return 1;} + static unsigned char epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return false;} +}; + +template <> +struct limits +{ + static short min() {return SHRT_MIN;} + static short max() {return SHRT_MAX;} + static short smallest() {return 1;} + static short epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return true;} +}; + +template <> +struct limits +{ + static unsigned short min() {return 0;} + static unsigned short max() {return USHRT_MAX;} + static unsigned short smallest() {return 1;} + static unsigned short epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return false;} +}; + +template <> +struct limits +{ + static int min() {return INT_MIN;} + static int max() {return INT_MAX;} + static int smallest() {return 1;} + static int epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return true;} +}; + +template <> +struct limits +{ + static unsigned int min() {return 0;} + static unsigned int max() {return UINT_MAX;} + static unsigned int smallest() {return 1;} + static unsigned int epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return false;} +}; + +template <> +struct limits +{ + static long min() {return LONG_MIN;} + static long max() {return LONG_MAX;} + static long smallest() {return 1;} + static long epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return true;} +}; + +template <> +struct limits +{ + static unsigned long min() {return 0;} + static unsigned long max() {return ULONG_MAX;} + static unsigned long smallest() {return 1;} + static unsigned long epsilon() {return 1;} + static bool isIntegral() {return true;} + static bool isSigned() {return false;} +}; + +template <> +struct limits +{ + static float min() {return -FLT_MAX;} + static float max() {return FLT_MAX;} + static float smallest() {return FLT_MIN;} + static float epsilon() {return FLT_EPSILON;} + static bool isIntegral() {return false;} + static bool isSigned() {return true;} +}; + +template <> +struct limits +{ + static double min() {return -DBL_MAX;} + static double max() {return DBL_MAX;} + static double smallest() {return DBL_MIN;} + static double epsilon() {return DBL_EPSILON;} + static bool isIntegral() {return false;} + static bool isSigned() {return true;} +}; + +template <> +struct limits +{ + static long double min() {return -LDBL_MAX;} + static long double max() {return LDBL_MAX;} + static long double smallest() {return LDBL_MIN;} + static long double epsilon() {return LDBL_EPSILON;} + static bool isIntegral() {return false;} + static bool isSigned() {return true;} +}; + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHLIMITS_H diff --git a/OpenEXR/include/OpenEXR/ImathLine.h b/OpenEXR/include/OpenEXR/ImathLine.h new file mode 100644 index 0000000..61e4508 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathLine.h @@ -0,0 +1,185 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHLINE_H +#define INCLUDED_IMATHLINE_H + +//------------------------------------- +// +// A 3D line class template +// +//------------------------------------- + +#include "ImathVec.h" +#include "ImathLimits.h" +#include "ImathMatrix.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +class Line3 +{ + public: + + Vec3 pos; + Vec3 dir; + + //------------------------------------------------------------- + // Constructors - default is normalized units along direction + //------------------------------------------------------------- + + Line3() {} + Line3(const Vec3& point1, const Vec3& point2); + + //------------------ + // State Query/Set + //------------------ + + void set(const Vec3& point1, + const Vec3& point2); + + //------- + // F(t) + //------- + + Vec3 operator() (T parameter) const; + + //--------- + // Query + //--------- + + T distanceTo(const Vec3& point) const; + T distanceTo(const Line3& line) const; + Vec3 closestPointTo(const Vec3& point) const; + Vec3 closestPointTo(const Line3& line) const; +}; + + +//-------------------- +// Convenient typedefs +//-------------------- + +typedef Line3 Line3f; +typedef Line3 Line3d; + + +//--------------- +// Implementation +//--------------- + +template +inline Line3::Line3(const Vec3 &p0, const Vec3 &p1) +{ + set(p0,p1); +} + +template +inline void Line3::set(const Vec3 &p0, const Vec3 &p1) +{ + pos = p0; dir = p1-p0; + dir.normalize(); +} + +template +inline Vec3 Line3::operator()(T parameter) const +{ + return pos + dir * parameter; +} + +template +inline T Line3::distanceTo(const Vec3& point) const +{ + return (closestPointTo(point)-point).length(); +} + +template +inline Vec3 Line3::closestPointTo(const Vec3& point) const +{ + return ((point - pos) ^ dir) * dir + pos; +} + +template +inline T Line3::distanceTo(const Line3& line) const +{ + T d = (dir % line.dir) ^ (line.pos - pos); + return (d >= 0)? d: -d; +} + +template +inline Vec3 +Line3::closestPointTo(const Line3& line) const +{ + // Assumes the lines are normalized + + Vec3 posLpos = pos - line.pos ; + T c = dir ^ posLpos; + T a = line.dir ^ dir; + T f = line.dir ^ posLpos ; + T num = c - a * f; + + T denom = a*a - 1; + + T absDenom = ((denom >= 0)? denom: -denom); + + if (absDenom < 1) + { + T absNum = ((num >= 0)? num: -num); + + if (absNum >= absDenom * limits::max()) + return pos; + } + + return pos + dir * (num / denom); +} + +template +std::ostream& operator<< (std::ostream &o, const Line3 &line) +{ + return o << "(" << line.pos << ", " << line.dir << ")"; +} + +template +inline Line3 operator * (const Line3 &line, const Matrix44 &M) +{ + return Line3( line.pos * M, (line.pos + line.dir) * M ); +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHLINE_H diff --git a/OpenEXR/include/OpenEXR/ImathLineAlgo.h b/OpenEXR/include/OpenEXR/ImathLineAlgo.h new file mode 100644 index 0000000..b08a1ff --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathLineAlgo.h @@ -0,0 +1,288 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHLINEALGO_H +#define INCLUDED_IMATHLINEALGO_H + +//------------------------------------------------------------------ +// +// This file contains algorithms applied to or in conjunction +// with lines (Imath::Line). These algorithms may require +// more headers to compile. The assumption made is that these +// functions are called much less often than the basic line +// functions or these functions require more support classes +// +// Contains: +// +// bool closestPoints(const Line& line1, +// const Line& line2, +// Vec3& point1, +// Vec3& point2) +// +// bool intersect( const Line3 &line, +// const Vec3 &v0, +// const Vec3 &v1, +// const Vec3 &v2, +// Vec3 &pt, +// Vec3 &barycentric, +// bool &front) +// +// V3f +// closestVertex(const Vec3 &v0, +// const Vec3 &v1, +// const Vec3 &v2, +// const Line3 &l) +// +// V3f +// rotatePoint(const Vec3 p, Line3 l, float angle) +// +//------------------------------------------------------------------ + +#include "ImathLine.h" +#include "ImathVecAlgo.h" +#include "ImathFun.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +bool +closestPoints + (const Line3& line1, + const Line3& line2, + Vec3& point1, + Vec3& point2) +{ + // + // Compute point1 and point2 such that point1 is on line1, point2 + // is on line2 and the distance between point1 and point2 is minimal. + // This function returns true if point1 and point2 can be computed, + // or false if line1 and line2 are parallel or nearly parallel. + // This function assumes that line1.dir and line2.dir are normalized. + // + + Vec3 w = line1.pos - line2.pos; + T d1w = line1.dir ^ w; + T d2w = line2.dir ^ w; + T d1d2 = line1.dir ^ line2.dir; + T n1 = d1d2 * d2w - d1w; + T n2 = d2w - d1d2 * d1w; + T d = 1 - d1d2 * d1d2; + T absD = abs (d); + + if ((absD > 1) || + (abs (n1) < limits::max() * absD && + abs (n2) < limits::max() * absD)) + { + point1 = line1 (n1 / d); + point2 = line2 (n2 / d); + return true; + } + else + { + return false; + } +} + + +template +bool +intersect + (const Line3 &line, + const Vec3 &v0, + const Vec3 &v1, + const Vec3 &v2, + Vec3 &pt, + Vec3 &barycentric, + bool &front) +{ + // + // Given a line and a triangle (v0, v1, v2), the intersect() function + // finds the intersection of the line and the plane that contains the + // triangle. + // + // If the intersection point cannot be computed, either because the + // line and the triangle's plane are nearly parallel or because the + // triangle's area is very small, intersect() returns false. + // + // If the intersection point is outside the triangle, intersect + // returns false. + // + // If the intersection point, pt, is inside the triangle, intersect() + // computes a front-facing flag and the barycentric coordinates of + // the intersection point, and returns true. + // + // The front-facing flag is true if the dot product of the triangle's + // normal, (v2-v1)%(v1-v0), and the line's direction is negative. + // + // The barycentric coordinates have the following property: + // + // pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z + // + + Vec3 edge0 = v1 - v0; + Vec3 edge1 = v2 - v1; + Vec3 normal = edge1 % edge0; + + T l = normal.length(); + + if (l != 0) + normal /= l; + else + return false; // zero-area triangle + + // + // d is the distance of line.pos from the plane that contains the triangle. + // The intersection point is at line.pos + (d/nd) * line.dir. + // + + T d = normal ^ (v0 - line.pos); + T nd = normal ^ line.dir; + + if (abs (nd) > 1 || abs (d) < limits::max() * abs (nd)) + pt = line (d / nd); + else + return false; // line and plane are nearly parallel + + // + // Compute the barycentric coordinates of the intersection point. + // The intersection is inside the triangle if all three barycentric + // coordinates are between zero and one. + // + + { + Vec3 en = edge0.normalized(); + Vec3 a = pt - v0; + Vec3 b = v2 - v0; + Vec3 c = (a - en * (en ^ a)); + Vec3 d = (b - en * (en ^ b)); + T e = c ^ d; + T f = d ^ d; + + if (e >= 0 && e <= f) + barycentric.z = e / f; + else + return false; // outside + } + + { + Vec3 en = edge1.normalized(); + Vec3 a = pt - v1; + Vec3 b = v0 - v1; + Vec3 c = (a - en * (en ^ a)); + Vec3 d = (b - en * (en ^ b)); + T e = c ^ d; + T f = d ^ d; + + if (e >= 0 && e <= f) + barycentric.x = e / f; + else + return false; // outside + } + + barycentric.y = 1 - barycentric.x - barycentric.z; + + if (barycentric.y < 0) + return false; // outside + + front = ((line.dir ^ normal) < 0); + return true; +} + + +template +Vec3 +closestVertex + (const Vec3 &v0, + const Vec3 &v1, + const Vec3 &v2, + const Line3 &l) +{ + Vec3 nearest = v0; + T neardot = (v0 - l.closestPointTo(v0)).length2(); + + T tmp = (v1 - l.closestPointTo(v1)).length2(); + + if (tmp < neardot) + { + neardot = tmp; + nearest = v1; + } + + tmp = (v2 - l.closestPointTo(v2)).length2(); + if (tmp < neardot) + { + neardot = tmp; + nearest = v2; + } + + return nearest; +} + + +template +Vec3 +rotatePoint (const Vec3 p, Line3 l, T angle) +{ + // + // Rotate the point p around the line l by the given angle. + // + + // + // Form a coordinate frame with . The rotation is the in xy + // plane. + // + + Vec3 q = l.closestPointTo(p); + Vec3 x = p - q; + T radius = x.length(); + + x.normalize(); + Vec3 y = (x % l.dir).normalize(); + + T cosangle = Math::cos(angle); + T sinangle = Math::sin(angle); + + Vec3 r = q + x * radius * cosangle + y * radius * sinangle; + + return r; +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHLINEALGO_H diff --git a/OpenEXR/include/OpenEXR/ImathMath.h b/OpenEXR/include/OpenEXR/ImathMath.h new file mode 100644 index 0000000..1961d5a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathMath.h @@ -0,0 +1,208 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHMATH_H +#define INCLUDED_IMATHMATH_H + +//---------------------------------------------------------------------------- +// +// ImathMath.h +// +// This file contains template functions which call the double- +// precision math functions defined in math.h (sin(), sqrt(), +// exp() etc.), with specializations that call the faster +// single-precision versions (sinf(), sqrtf(), expf() etc.) +// when appropriate. +// +// Example: +// +// double x = Math::sqrt (3); // calls ::sqrt(double); +// float y = Math::sqrt (3); // calls ::sqrtf(float); +// +// When would I want to use this? +// +// You may be writing a template which needs to call some function +// defined in math.h, for example to extract a square root, but you +// don't know whether to call the single- or the double-precision +// version of this function (sqrt() or sqrtf()): +// +// template +// T +// glorp (T x) +// { +// return sqrt (x + 1); // should call ::sqrtf(float) +// } // if x is a float, but we +// // don't know if it is +// +// Using the templates in this file, you can make sure that +// the appropriate version of the math function is called: +// +// template +// T +// glorp (T x, T y) +// { +// return Math::sqrt (x + 1); // calls ::sqrtf(float) if x +// } // is a float, ::sqrt(double) +// // otherwise +// +//---------------------------------------------------------------------------- + +#include "ImathPlatform.h" +#include "ImathLimits.h" +#include "ImathNamespace.h" +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +struct Math +{ + static T acos (T x) {return ::acos (double(x));} + static T asin (T x) {return ::asin (double(x));} + static T atan (T x) {return ::atan (double(x));} + static T atan2 (T x, T y) {return ::atan2 (double(x), double(y));} + static T cos (T x) {return ::cos (double(x));} + static T sin (T x) {return ::sin (double(x));} + static T tan (T x) {return ::tan (double(x));} + static T cosh (T x) {return ::cosh (double(x));} + static T sinh (T x) {return ::sinh (double(x));} + static T tanh (T x) {return ::tanh (double(x));} + static T exp (T x) {return ::exp (double(x));} + static T log (T x) {return ::log (double(x));} + static T log10 (T x) {return ::log10 (double(x));} + static T modf (T x, T *iptr) + { + double ival; + T rval( ::modf (double(x),&ival)); + *iptr = ival; + return rval; + } + static T pow (T x, T y) {return ::pow (double(x), double(y));} + static T sqrt (T x) {return ::sqrt (double(x));} + static T ceil (T x) {return ::ceil (double(x));} + static T fabs (T x) {return ::fabs (double(x));} + static T floor (T x) {return ::floor (double(x));} + static T fmod (T x, T y) {return ::fmod (double(x), double(y));} + static T hypot (T x, T y) {return ::hypot (double(x), double(y));} +}; + + +template <> +struct Math +{ + static float acos (float x) {return ::acosf (x);} + static float asin (float x) {return ::asinf (x);} + static float atan (float x) {return ::atanf (x);} + static float atan2 (float x, float y) {return ::atan2f (x, y);} + static float cos (float x) {return ::cosf (x);} + static float sin (float x) {return ::sinf (x);} + static float tan (float x) {return ::tanf (x);} + static float cosh (float x) {return ::coshf (x);} + static float sinh (float x) {return ::sinhf (x);} + static float tanh (float x) {return ::tanhf (x);} + static float exp (float x) {return ::expf (x);} + static float log (float x) {return ::logf (x);} + static float log10 (float x) {return ::log10f (x);} + static float modf (float x, float *y) {return ::modff (x, y);} + static float pow (float x, float y) {return ::powf (x, y);} + static float sqrt (float x) {return ::sqrtf (x);} + static float ceil (float x) {return ::ceilf (x);} + static float fabs (float x) {return ::fabsf (x);} + static float floor (float x) {return ::floorf (x);} + static float fmod (float x, float y) {return ::fmodf (x, y);} +#if !defined(_MSC_VER) + static float hypot (float x, float y) {return ::hypotf (x, y);} +#else + static float hypot (float x, float y) {return ::sqrtf(x*x + y*y);} +#endif +}; + + +//-------------------------------------------------------------------------- +// Don Hatch's version of sin(x)/x, which is accurate for very small x. +// Returns 1 for x == 0. +//-------------------------------------------------------------------------- + +template +inline T +sinx_over_x (T x) +{ + if (x * x < limits::epsilon()) + return T (1); + else + return Math::sin (x) / x; +} + + +//-------------------------------------------------------------------------- +// 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 +// +//-------------------------------------------------------------------------- + +template +inline bool +equalWithAbsError (T x1, T x2, T e) +{ + return ((x1 > x2)? x1 - x2: x2 - x1) <= e; +} + + +template +inline bool +equalWithRelError (T x1, T x2, T e) +{ + return ((x1 > x2)? x1 - x2: x2 - x1) <= e * ((x1 > 0)? x1: -x1); +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHMATH_H diff --git a/OpenEXR/include/OpenEXR/ImathMatrix.h b/OpenEXR/include/OpenEXR/ImathMatrix.h new file mode 100644 index 0000000..3e96c2f --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathMatrix.h @@ -0,0 +1,3441 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHMATRIX_H +#define INCLUDED_IMATHMATRIX_H + +//---------------------------------------------------------------- +// +// 2D (3x3) and 3D (4x4) transformation matrix templates. +// +//---------------------------------------------------------------- + +#include "ImathPlatform.h" +#include "ImathFun.h" +#include "ImathExc.h" +#include "ImathVec.h" +#include "ImathShear.h" +#include "ImathNamespace.h" + +#include +#include +#include +#include + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +// suppress exception specification warnings +#pragma warning(disable:4290) +#endif + + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +enum Uninitialized {UNINITIALIZED}; + + +template class Matrix33 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T x[3][3]; + + T * operator [] (int i); + const T * operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Matrix33 (Uninitialized) {} + + Matrix33 (); + // 1 0 0 + // 0 1 0 + // 0 0 1 + + Matrix33 (T a); + // a a a + // a a a + // a a a + + Matrix33 (const T a[3][3]); + // a[0][0] a[0][1] a[0][2] + // a[1][0] a[1][1] a[1][2] + // a[2][0] a[2][1] a[2][2] + + Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i); + + // a b c + // d e f + // g h i + + + //-------------------------------- + // Copy constructor and assignment + //-------------------------------- + + Matrix33 (const Matrix33 &v); + template explicit Matrix33 (const Matrix33 &v); + + const Matrix33 & operator = (const Matrix33 &v); + const Matrix33 & operator = (T a); + + + //---------------------- + // Compatibility with Sb + //---------------------- + + T * getValue (); + const T * getValue () const; + + template + void getValue (Matrix33 &v) const; + template + Matrix33 & setValue (const Matrix33 &v); + + template + Matrix33 & setTheMatrix (const Matrix33 &v); + + + //--------- + // Identity + //--------- + + void makeIdentity(); + + + //--------- + // Equality + //--------- + + bool operator == (const Matrix33 &v) const; + bool operator != (const Matrix33 &v) const; + + //----------------------------------------------------------------------- + // Compare two matrices and test if they are "approximately equal": + // + // equalWithAbsError (m, e) + // + // Returns true if the coefficients of this and m are the same with + // an absolute error of no more than e, i.e., for all i, j + // + // abs (this[i][j] - m[i][j]) <= e + // + // equalWithRelError (m, e) + // + // Returns true if the coefficients of this and m are the same with + // a relative error of no more than e, i.e., for all i, j + // + // abs (this[i] - v[i][j]) <= e * abs (this[i][j]) + //----------------------------------------------------------------------- + + bool equalWithAbsError (const Matrix33 &v, T e) const; + bool equalWithRelError (const Matrix33 &v, T e) const; + + + //------------------------ + // Component-wise addition + //------------------------ + + const Matrix33 & operator += (const Matrix33 &v); + const Matrix33 & operator += (T a); + Matrix33 operator + (const Matrix33 &v) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Matrix33 & operator -= (const Matrix33 &v); + const Matrix33 & operator -= (T a); + Matrix33 operator - (const Matrix33 &v) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Matrix33 operator - () const; + const Matrix33 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Matrix33 & operator *= (T a); + Matrix33 operator * (T a) const; + + + //----------------------------------- + // Matrix-times-matrix multiplication + //----------------------------------- + + const Matrix33 & operator *= (const Matrix33 &v); + Matrix33 operator * (const Matrix33 &v) const; + + + //----------------------------------------------------------------- + // Vector-times-matrix multiplication; see also the "operator *" + // functions defined below. + // + // m.multVecMatrix(src,dst) implements a homogeneous transformation + // by computing Vec3 (src.x, src.y, 1) * m and dividing by the + // result's third element. + // + // m.multDirMatrix(src,dst) multiplies src by the upper left 2x2 + // submatrix, ignoring the rest of matrix m. + //----------------------------------------------------------------- + + template + void multVecMatrix(const Vec2 &src, Vec2 &dst) const; + + template + void multDirMatrix(const Vec2 &src, Vec2 &dst) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Matrix33 & operator /= (T a); + Matrix33 operator / (T a) const; + + + //------------------ + // Transposed matrix + //------------------ + + const Matrix33 & transpose (); + Matrix33 transposed () const; + + + //------------------------------------------------------------ + // Inverse matrix: If singExc is false, inverting a singular + // matrix produces an identity matrix. If singExc is true, + // inverting a singular matrix throws a SingMatrixExc. + // + // inverse() and invert() invert matrices using determinants; + // gjInverse() and gjInvert() use the Gauss-Jordan method. + // + // inverse() and invert() are significantly faster than + // gjInverse() and gjInvert(), but the results may be slightly + // less accurate. + // + //------------------------------------------------------------ + + const Matrix33 & invert (bool singExc = false) + throw (IEX_NAMESPACE::MathExc); + + Matrix33 inverse (bool singExc = false) const + throw (IEX_NAMESPACE::MathExc); + + const Matrix33 & gjInvert (bool singExc = false) + throw (IEX_NAMESPACE::MathExc); + + Matrix33 gjInverse (bool singExc = false) const + throw (IEX_NAMESPACE::MathExc); + + + //------------------------------------------------ + // Calculate the matrix minor of the (r,c) element + //------------------------------------------------ + + T minorOf (const int r, const int c) const; + + //--------------------------------------------------- + // Build a minor using the specified rows and columns + //--------------------------------------------------- + + T fastMinor (const int r0, const int r1, + const int c0, const int c1) const; + + //------------ + // Determinant + //------------ + + T determinant() const; + + //----------------------------------------- + // Set matrix to rotation by r (in radians) + //----------------------------------------- + + template + const Matrix33 & setRotation (S r); + + + //----------------------------- + // Rotate the given matrix by r + //----------------------------- + + template + const Matrix33 & rotate (S r); + + + //-------------------------------------------- + // Set matrix to scale by given uniform factor + //-------------------------------------------- + + const Matrix33 & setScale (T s); + + + //------------------------------------ + // Set matrix to scale by given vector + //------------------------------------ + + template + const Matrix33 & setScale (const Vec2 &s); + + + //---------------------- + // Scale the matrix by s + //---------------------- + + template + const Matrix33 & scale (const Vec2 &s); + + + //------------------------------------------ + // Set matrix to translation by given vector + //------------------------------------------ + + template + const Matrix33 & setTranslation (const Vec2 &t); + + + //----------------------------- + // Return translation component + //----------------------------- + + Vec2 translation () const; + + + //-------------------------- + // Translate the matrix by t + //-------------------------- + + template + const Matrix33 & translate (const Vec2 &t); + + + //----------------------------------------------------------- + // Set matrix to shear x for each y coord. by given factor xy + //----------------------------------------------------------- + + template + const Matrix33 & setShear (const S &h); + + + //------------------------------------------------------------- + // Set matrix to shear x for each y coord. by given factor h[0] + // and to shear y for each x coord. by given factor h[1] + //------------------------------------------------------------- + + template + const Matrix33 & setShear (const Vec2 &h); + + + //----------------------------------------------------------- + // Shear the matrix in x for each y coord. by given factor xy + //----------------------------------------------------------- + + template + const Matrix33 & shear (const S &xy); + + + //----------------------------------------------------------- + // Shear the matrix in x for each y coord. by given factor xy + // and shear y for each x coord. by given factor yx + //----------------------------------------------------------- + + template + const Matrix33 & shear (const Vec2 &h); + + + //-------------------------------------------------------- + // Number of the row and column dimensions, since + // Matrix33 is a square matrix. + //-------------------------------------------------------- + + static unsigned int dimensions() {return 3;} + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + typedef T BaseType; + typedef Vec3 BaseVecType; + + private: + + template + struct isSameType + { + enum {value = 0}; + }; + + template + struct isSameType + { + enum {value = 1}; + }; +}; + + +template class Matrix44 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T x[4][4]; + + T * operator [] (int i); + const T * operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Matrix44 (Uninitialized) {} + + Matrix44 (); + // 1 0 0 0 + // 0 1 0 0 + // 0 0 1 0 + // 0 0 0 1 + + Matrix44 (T a); + // a a a a + // a a a a + // a a a a + // a a a a + + Matrix44 (const T a[4][4]) ; + // a[0][0] a[0][1] a[0][2] a[0][3] + // a[1][0] a[1][1] a[1][2] a[1][3] + // a[2][0] a[2][1] a[2][2] a[2][3] + // a[3][0] a[3][1] a[3][2] a[3][3] + + Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h, + T i, T j, T k, T l, T m, T n, T o, T p); + + // a b c d + // e f g h + // i j k l + // m n o p + + Matrix44 (Matrix33 r, Vec3 t); + // r r r 0 + // r r r 0 + // r r r 0 + // t t t 1 + + + //-------------------------------- + // Copy constructor and assignment + //-------------------------------- + + Matrix44 (const Matrix44 &v); + template explicit Matrix44 (const Matrix44 &v); + + const Matrix44 & operator = (const Matrix44 &v); + const Matrix44 & operator = (T a); + + + //---------------------- + // Compatibility with Sb + //---------------------- + + T * getValue (); + const T * getValue () const; + + template + void getValue (Matrix44 &v) const; + template + Matrix44 & setValue (const Matrix44 &v); + + template + Matrix44 & setTheMatrix (const Matrix44 &v); + + //--------- + // Identity + //--------- + + void makeIdentity(); + + + //--------- + // Equality + //--------- + + bool operator == (const Matrix44 &v) const; + bool operator != (const Matrix44 &v) const; + + //----------------------------------------------------------------------- + // Compare two matrices and test if they are "approximately equal": + // + // equalWithAbsError (m, e) + // + // Returns true if the coefficients of this and m are the same with + // an absolute error of no more than e, i.e., for all i, j + // + // abs (this[i][j] - m[i][j]) <= e + // + // equalWithRelError (m, e) + // + // Returns true if the coefficients of this and m are the same with + // a relative error of no more than e, i.e., for all i, j + // + // abs (this[i] - v[i][j]) <= e * abs (this[i][j]) + //----------------------------------------------------------------------- + + bool equalWithAbsError (const Matrix44 &v, T e) const; + bool equalWithRelError (const Matrix44 &v, T e) const; + + + //------------------------ + // Component-wise addition + //------------------------ + + const Matrix44 & operator += (const Matrix44 &v); + const Matrix44 & operator += (T a); + Matrix44 operator + (const Matrix44 &v) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Matrix44 & operator -= (const Matrix44 &v); + const Matrix44 & operator -= (T a); + Matrix44 operator - (const Matrix44 &v) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Matrix44 operator - () const; + const Matrix44 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Matrix44 & operator *= (T a); + Matrix44 operator * (T a) const; + + + //----------------------------------- + // Matrix-times-matrix multiplication + //----------------------------------- + + const Matrix44 & operator *= (const Matrix44 &v); + Matrix44 operator * (const Matrix44 &v) const; + + static void multiply (const Matrix44 &a, // assumes that + const Matrix44 &b, // &a != &c and + Matrix44 &c); // &b != &c. + + + //----------------------------------------------------------------- + // Vector-times-matrix multiplication; see also the "operator *" + // functions defined below. + // + // m.multVecMatrix(src,dst) implements a homogeneous transformation + // by computing Vec4 (src.x, src.y, src.z, 1) * m and dividing by + // the result's third element. + // + // m.multDirMatrix(src,dst) multiplies src by the upper left 3x3 + // submatrix, ignoring the rest of matrix m. + //----------------------------------------------------------------- + + template + void multVecMatrix(const Vec3 &src, Vec3 &dst) const; + + template + void multDirMatrix(const Vec3 &src, Vec3 &dst) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Matrix44 & operator /= (T a); + Matrix44 operator / (T a) const; + + + //------------------ + // Transposed matrix + //------------------ + + const Matrix44 & transpose (); + Matrix44 transposed () const; + + + //------------------------------------------------------------ + // Inverse matrix: If singExc is false, inverting a singular + // matrix produces an identity matrix. If singExc is true, + // inverting a singular matrix throws a SingMatrixExc. + // + // inverse() and invert() invert matrices using determinants; + // gjInverse() and gjInvert() use the Gauss-Jordan method. + // + // inverse() and invert() are significantly faster than + // gjInverse() and gjInvert(), but the results may be slightly + // less accurate. + // + //------------------------------------------------------------ + + const Matrix44 & invert (bool singExc = false) + throw (IEX_NAMESPACE::MathExc); + + Matrix44 inverse (bool singExc = false) const + throw (IEX_NAMESPACE::MathExc); + + const Matrix44 & gjInvert (bool singExc = false) + throw (IEX_NAMESPACE::MathExc); + + Matrix44 gjInverse (bool singExc = false) const + throw (IEX_NAMESPACE::MathExc); + + + //------------------------------------------------ + // Calculate the matrix minor of the (r,c) element + //------------------------------------------------ + + T minorOf (const int r, const int c) const; + + //--------------------------------------------------- + // Build a minor using the specified rows and columns + //--------------------------------------------------- + + T fastMinor (const int r0, const int r1, const int r2, + const int c0, const int c1, const int c2) const; + + //------------ + // Determinant + //------------ + + T determinant() const; + + //-------------------------------------------------------- + // Set matrix to rotation by XYZ euler angles (in radians) + //-------------------------------------------------------- + + template + const Matrix44 & setEulerAngles (const Vec3& r); + + + //-------------------------------------------------------- + // Set matrix to rotation around given axis by given angle + //-------------------------------------------------------- + + template + const Matrix44 & setAxisAngle (const Vec3& ax, S ang); + + + //------------------------------------------- + // Rotate the matrix by XYZ euler angles in r + //------------------------------------------- + + template + const Matrix44 & rotate (const Vec3 &r); + + + //-------------------------------------------- + // Set matrix to scale by given uniform factor + //-------------------------------------------- + + const Matrix44 & setScale (T s); + + + //------------------------------------ + // Set matrix to scale by given vector + //------------------------------------ + + template + const Matrix44 & setScale (const Vec3 &s); + + + //---------------------- + // Scale the matrix by s + //---------------------- + + template + const Matrix44 & scale (const Vec3 &s); + + + //------------------------------------------ + // Set matrix to translation by given vector + //------------------------------------------ + + template + const Matrix44 & setTranslation (const Vec3 &t); + + + //----------------------------- + // Return translation component + //----------------------------- + + const Vec3 translation () const; + + + //-------------------------- + // Translate the matrix by t + //-------------------------- + + template + const Matrix44 & translate (const Vec3 &t); + + + //------------------------------------------------------------- + // Set matrix to shear by given vector h. The resulting matrix + // will shear x for each y coord. by a factor of h[0] ; + // will shear x for each z coord. by a factor of h[1] ; + // will shear y for each z coord. by a factor of h[2] . + //------------------------------------------------------------- + + template + const Matrix44 & setShear (const Vec3 &h); + + + //------------------------------------------------------------ + // Set matrix to shear by given factors. The resulting matrix + // will shear x for each y coord. by a factor of h.xy ; + // will shear x for each z coord. by a factor of h.xz ; + // will shear y for each z coord. by a factor of h.yz ; + // will shear y for each x coord. by a factor of h.yx ; + // will shear z for each x coord. by a factor of h.zx ; + // will shear z for each y coord. by a factor of h.zy . + //------------------------------------------------------------ + + template + const Matrix44 & setShear (const Shear6 &h); + + + //-------------------------------------------------------- + // Shear the matrix by given vector. The composed matrix + // will be * , where the shear matrix ... + // will shear x for each y coord. by a factor of h[0] ; + // will shear x for each z coord. by a factor of h[1] ; + // will shear y for each z coord. by a factor of h[2] . + //-------------------------------------------------------- + + template + const Matrix44 & shear (const Vec3 &h); + + //-------------------------------------------------------- + // Number of the row and column dimensions, since + // Matrix44 is a square matrix. + //-------------------------------------------------------- + + static unsigned int dimensions() {return 4;} + + + //------------------------------------------------------------ + // Shear the matrix by the given factors. The composed matrix + // will be * , where the shear matrix ... + // will shear x for each y coord. by a factor of h.xy ; + // will shear x for each z coord. by a factor of h.xz ; + // will shear y for each z coord. by a factor of h.yz ; + // will shear y for each x coord. by a factor of h.yx ; + // will shear z for each x coord. by a factor of h.zx ; + // will shear z for each y coord. by a factor of h.zy . + //------------------------------------------------------------ + + template + const Matrix44 & shear (const Shear6 &h); + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + typedef T BaseType; + typedef Vec4 BaseVecType; + + private: + + template + struct isSameType + { + enum {value = 0}; + }; + + template + struct isSameType + { + enum {value = 1}; + }; +}; + + +//-------------- +// Stream output +//-------------- + +template +std::ostream & operator << (std::ostream & s, const Matrix33 &m); + +template +std::ostream & operator << (std::ostream & s, const Matrix44 &m); + + +//--------------------------------------------- +// Vector-times-matrix multiplication operators +//--------------------------------------------- + +template +const Vec2 & operator *= (Vec2 &v, const Matrix33 &m); + +template +Vec2 operator * (const Vec2 &v, const Matrix33 &m); + +template +const Vec3 & operator *= (Vec3 &v, const Matrix33 &m); + +template +Vec3 operator * (const Vec3 &v, const Matrix33 &m); + +template +const Vec3 & operator *= (Vec3 &v, const Matrix44 &m); + +template +Vec3 operator * (const Vec3 &v, const Matrix44 &m); + +template +const Vec4 & operator *= (Vec4 &v, const Matrix44 &m); + +template +Vec4 operator * (const Vec4 &v, const Matrix44 &m); + +//------------------------- +// Typedefs for convenience +//------------------------- + +typedef Matrix33 M33f; +typedef Matrix33 M33d; +typedef Matrix44 M44f; +typedef Matrix44 M44d; + + +//--------------------------- +// Implementation of Matrix33 +//--------------------------- + +template +inline T * +Matrix33::operator [] (int i) +{ + return x[i]; +} + +template +inline const T * +Matrix33::operator [] (int i) const +{ + return x[i]; +} + +template +inline +Matrix33::Matrix33 () +{ + memset (x, 0, sizeof (x)); + x[0][0] = 1; + x[1][1] = 1; + x[2][2] = 1; +} + +template +inline +Matrix33::Matrix33 (T a) +{ + x[0][0] = a; + x[0][1] = a; + x[0][2] = a; + x[1][0] = a; + x[1][1] = a; + x[1][2] = a; + x[2][0] = a; + x[2][1] = a; + x[2][2] = a; +} + +template +inline +Matrix33::Matrix33 (const T a[3][3]) +{ + memcpy (x, a, sizeof (x)); +} + +template +inline +Matrix33::Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i) +{ + x[0][0] = a; + x[0][1] = b; + x[0][2] = c; + x[1][0] = d; + x[1][1] = e; + x[1][2] = f; + x[2][0] = g; + x[2][1] = h; + x[2][2] = i; +} + +template +inline +Matrix33::Matrix33 (const Matrix33 &v) +{ + memcpy (x, v.x, sizeof (x)); +} + +template +template +inline +Matrix33::Matrix33 (const Matrix33 &v) +{ + x[0][0] = T (v.x[0][0]); + x[0][1] = T (v.x[0][1]); + x[0][2] = T (v.x[0][2]); + x[1][0] = T (v.x[1][0]); + x[1][1] = T (v.x[1][1]); + x[1][2] = T (v.x[1][2]); + x[2][0] = T (v.x[2][0]); + x[2][1] = T (v.x[2][1]); + x[2][2] = T (v.x[2][2]); +} + +template +inline const Matrix33 & +Matrix33::operator = (const Matrix33 &v) +{ + memcpy (x, v.x, sizeof (x)); + return *this; +} + +template +inline const Matrix33 & +Matrix33::operator = (T a) +{ + x[0][0] = a; + x[0][1] = a; + x[0][2] = a; + x[1][0] = a; + x[1][1] = a; + x[1][2] = a; + x[2][0] = a; + x[2][1] = a; + x[2][2] = a; + return *this; +} + +template +inline T * +Matrix33::getValue () +{ + return (T *) &x[0][0]; +} + +template +inline const T * +Matrix33::getValue () const +{ + return (const T *) &x[0][0]; +} + +template +template +inline void +Matrix33::getValue (Matrix33 &v) const +{ + if (isSameType::value) + { + memcpy (v.x, x, sizeof (x)); + } + else + { + v.x[0][0] = x[0][0]; + v.x[0][1] = x[0][1]; + v.x[0][2] = x[0][2]; + v.x[1][0] = x[1][0]; + v.x[1][1] = x[1][1]; + v.x[1][2] = x[1][2]; + v.x[2][0] = x[2][0]; + v.x[2][1] = x[2][1]; + v.x[2][2] = x[2][2]; + } +} + +template +template +inline Matrix33 & +Matrix33::setValue (const Matrix33 &v) +{ + if (isSameType::value) + { + memcpy (x, v.x, sizeof (x)); + } + else + { + x[0][0] = v.x[0][0]; + x[0][1] = v.x[0][1]; + x[0][2] = v.x[0][2]; + x[1][0] = v.x[1][0]; + x[1][1] = v.x[1][1]; + x[1][2] = v.x[1][2]; + x[2][0] = v.x[2][0]; + x[2][1] = v.x[2][1]; + x[2][2] = v.x[2][2]; + } + + return *this; +} + +template +template +inline Matrix33 & +Matrix33::setTheMatrix (const Matrix33 &v) +{ + if (isSameType::value) + { + memcpy (x, v.x, sizeof (x)); + } + else + { + x[0][0] = v.x[0][0]; + x[0][1] = v.x[0][1]; + x[0][2] = v.x[0][2]; + x[1][0] = v.x[1][0]; + x[1][1] = v.x[1][1]; + x[1][2] = v.x[1][2]; + x[2][0] = v.x[2][0]; + x[2][1] = v.x[2][1]; + x[2][2] = v.x[2][2]; + } + + return *this; +} + +template +inline void +Matrix33::makeIdentity() +{ + memset (x, 0, sizeof (x)); + x[0][0] = 1; + x[1][1] = 1; + x[2][2] = 1; +} + +template +bool +Matrix33::operator == (const Matrix33 &v) const +{ + return x[0][0] == v.x[0][0] && + x[0][1] == v.x[0][1] && + x[0][2] == v.x[0][2] && + x[1][0] == v.x[1][0] && + x[1][1] == v.x[1][1] && + x[1][2] == v.x[1][2] && + x[2][0] == v.x[2][0] && + x[2][1] == v.x[2][1] && + x[2][2] == v.x[2][2]; +} + +template +bool +Matrix33::operator != (const Matrix33 &v) const +{ + return x[0][0] != v.x[0][0] || + x[0][1] != v.x[0][1] || + x[0][2] != v.x[0][2] || + x[1][0] != v.x[1][0] || + x[1][1] != v.x[1][1] || + x[1][2] != v.x[1][2] || + x[2][0] != v.x[2][0] || + x[2][1] != v.x[2][1] || + x[2][2] != v.x[2][2]; +} + +template +bool +Matrix33::equalWithAbsError (const Matrix33 &m, T e) const +{ + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) + return false; + + return true; +} + +template +bool +Matrix33::equalWithRelError (const Matrix33 &m, T e) const +{ + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) + return false; + + return true; +} + +template +const Matrix33 & +Matrix33::operator += (const Matrix33 &v) +{ + x[0][0] += v.x[0][0]; + x[0][1] += v.x[0][1]; + x[0][2] += v.x[0][2]; + x[1][0] += v.x[1][0]; + x[1][1] += v.x[1][1]; + x[1][2] += v.x[1][2]; + x[2][0] += v.x[2][0]; + x[2][1] += v.x[2][1]; + x[2][2] += v.x[2][2]; + + return *this; +} + +template +const Matrix33 & +Matrix33::operator += (T a) +{ + x[0][0] += a; + x[0][1] += a; + x[0][2] += a; + x[1][0] += a; + x[1][1] += a; + x[1][2] += a; + x[2][0] += a; + x[2][1] += a; + x[2][2] += a; + + return *this; +} + +template +Matrix33 +Matrix33::operator + (const Matrix33 &v) const +{ + return Matrix33 (x[0][0] + v.x[0][0], + x[0][1] + v.x[0][1], + x[0][2] + v.x[0][2], + x[1][0] + v.x[1][0], + x[1][1] + v.x[1][1], + x[1][2] + v.x[1][2], + x[2][0] + v.x[2][0], + x[2][1] + v.x[2][1], + x[2][2] + v.x[2][2]); +} + +template +const Matrix33 & +Matrix33::operator -= (const Matrix33 &v) +{ + x[0][0] -= v.x[0][0]; + x[0][1] -= v.x[0][1]; + x[0][2] -= v.x[0][2]; + x[1][0] -= v.x[1][0]; + x[1][1] -= v.x[1][1]; + x[1][2] -= v.x[1][2]; + x[2][0] -= v.x[2][0]; + x[2][1] -= v.x[2][1]; + x[2][2] -= v.x[2][2]; + + return *this; +} + +template +const Matrix33 & +Matrix33::operator -= (T a) +{ + x[0][0] -= a; + x[0][1] -= a; + x[0][2] -= a; + x[1][0] -= a; + x[1][1] -= a; + x[1][2] -= a; + x[2][0] -= a; + x[2][1] -= a; + x[2][2] -= a; + + return *this; +} + +template +Matrix33 +Matrix33::operator - (const Matrix33 &v) const +{ + return Matrix33 (x[0][0] - v.x[0][0], + x[0][1] - v.x[0][1], + x[0][2] - v.x[0][2], + x[1][0] - v.x[1][0], + x[1][1] - v.x[1][1], + x[1][2] - v.x[1][2], + x[2][0] - v.x[2][0], + x[2][1] - v.x[2][1], + x[2][2] - v.x[2][2]); +} + +template +Matrix33 +Matrix33::operator - () const +{ + return Matrix33 (-x[0][0], + -x[0][1], + -x[0][2], + -x[1][0], + -x[1][1], + -x[1][2], + -x[2][0], + -x[2][1], + -x[2][2]); +} + +template +const Matrix33 & +Matrix33::negate () +{ + x[0][0] = -x[0][0]; + x[0][1] = -x[0][1]; + x[0][2] = -x[0][2]; + x[1][0] = -x[1][0]; + x[1][1] = -x[1][1]; + x[1][2] = -x[1][2]; + x[2][0] = -x[2][0]; + x[2][1] = -x[2][1]; + x[2][2] = -x[2][2]; + + return *this; +} + +template +const Matrix33 & +Matrix33::operator *= (T a) +{ + x[0][0] *= a; + x[0][1] *= a; + x[0][2] *= a; + x[1][0] *= a; + x[1][1] *= a; + x[1][2] *= a; + x[2][0] *= a; + x[2][1] *= a; + x[2][2] *= a; + + return *this; +} + +template +Matrix33 +Matrix33::operator * (T a) const +{ + return Matrix33 (x[0][0] * a, + x[0][1] * a, + x[0][2] * a, + x[1][0] * a, + x[1][1] * a, + x[1][2] * a, + x[2][0] * a, + x[2][1] * a, + x[2][2] * a); +} + +template +inline Matrix33 +operator * (T a, const Matrix33 &v) +{ + return v * a; +} + +template +const Matrix33 & +Matrix33::operator *= (const Matrix33 &v) +{ + Matrix33 tmp (T (0)); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + tmp.x[i][j] += x[i][k] * v.x[k][j]; + + *this = tmp; + return *this; +} + +template +Matrix33 +Matrix33::operator * (const Matrix33 &v) const +{ + Matrix33 tmp (T (0)); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + tmp.x[i][j] += x[i][k] * v.x[k][j]; + + return tmp; +} + +template +template +void +Matrix33::multVecMatrix(const Vec2 &src, Vec2 &dst) const +{ + S a, b, w; + + a = src[0] * x[0][0] + src[1] * x[1][0] + x[2][0]; + b = src[0] * x[0][1] + src[1] * x[1][1] + x[2][1]; + w = src[0] * x[0][2] + src[1] * x[1][2] + x[2][2]; + + dst.x = a / w; + dst.y = b / w; +} + +template +template +void +Matrix33::multDirMatrix(const Vec2 &src, Vec2 &dst) const +{ + S a, b; + + a = src[0] * x[0][0] + src[1] * x[1][0]; + b = src[0] * x[0][1] + src[1] * x[1][1]; + + dst.x = a; + dst.y = b; +} + +template +const Matrix33 & +Matrix33::operator /= (T a) +{ + x[0][0] /= a; + x[0][1] /= a; + x[0][2] /= a; + x[1][0] /= a; + x[1][1] /= a; + x[1][2] /= a; + x[2][0] /= a; + x[2][1] /= a; + x[2][2] /= a; + + return *this; +} + +template +Matrix33 +Matrix33::operator / (T a) const +{ + return Matrix33 (x[0][0] / a, + x[0][1] / a, + x[0][2] / a, + x[1][0] / a, + x[1][1] / a, + x[1][2] / a, + x[2][0] / a, + x[2][1] / a, + x[2][2] / a); +} + +template +const Matrix33 & +Matrix33::transpose () +{ + Matrix33 tmp (x[0][0], + x[1][0], + x[2][0], + x[0][1], + x[1][1], + x[2][1], + x[0][2], + x[1][2], + x[2][2]); + *this = tmp; + return *this; +} + +template +Matrix33 +Matrix33::transposed () const +{ + return Matrix33 (x[0][0], + x[1][0], + x[2][0], + x[0][1], + x[1][1], + x[2][1], + x[0][2], + x[1][2], + x[2][2]); +} + +template +const Matrix33 & +Matrix33::gjInvert (bool singExc) throw (IEX_NAMESPACE::MathExc) +{ + *this = gjInverse (singExc); + return *this; +} + +template +Matrix33 +Matrix33::gjInverse (bool singExc) const throw (IEX_NAMESPACE::MathExc) +{ + int i, j, k; + Matrix33 s; + Matrix33 t (*this); + + // Forward elimination + + for (i = 0; i < 2 ; i++) + { + int pivot = i; + + T pivotsize = t[i][i]; + + if (pivotsize < 0) + pivotsize = -pivotsize; + + for (j = i + 1; j < 3; j++) + { + T tmp = t[j][i]; + + if (tmp < 0) + tmp = -tmp; + + if (tmp > pivotsize) + { + pivot = j; + pivotsize = tmp; + } + } + + if (pivotsize == 0) + { + if (singExc) + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); + + return Matrix33(); + } + + if (pivot != i) + { + for (j = 0; j < 3; j++) + { + T tmp; + + tmp = t[i][j]; + t[i][j] = t[pivot][j]; + t[pivot][j] = tmp; + + tmp = s[i][j]; + s[i][j] = s[pivot][j]; + s[pivot][j] = tmp; + } + } + + for (j = i + 1; j < 3; j++) + { + T f = t[j][i] / t[i][i]; + + for (k = 0; k < 3; k++) + { + t[j][k] -= f * t[i][k]; + s[j][k] -= f * s[i][k]; + } + } + } + + // Backward substitution + + for (i = 2; i >= 0; --i) + { + T f; + + if ((f = t[i][i]) == 0) + { + if (singExc) + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); + + return Matrix33(); + } + + for (j = 0; j < 3; j++) + { + t[i][j] /= f; + s[i][j] /= f; + } + + for (j = 0; j < i; j++) + { + f = t[j][i]; + + for (k = 0; k < 3; k++) + { + t[j][k] -= f * t[i][k]; + s[j][k] -= f * s[i][k]; + } + } + } + + return s; +} + +template +const Matrix33 & +Matrix33::invert (bool singExc) throw (IEX_NAMESPACE::MathExc) +{ + *this = inverse (singExc); + return *this; +} + +template +Matrix33 +Matrix33::inverse (bool singExc) const throw (IEX_NAMESPACE::MathExc) +{ + if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1) + { + Matrix33 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], + x[2][1] * x[0][2] - x[0][1] * x[2][2], + x[0][1] * x[1][2] - x[1][1] * x[0][2], + + x[2][0] * x[1][2] - x[1][0] * x[2][2], + x[0][0] * x[2][2] - x[2][0] * x[0][2], + x[1][0] * x[0][2] - x[0][0] * x[1][2], + + x[1][0] * x[2][1] - x[2][0] * x[1][1], + x[2][0] * x[0][1] - x[0][0] * x[2][1], + x[0][0] * x[1][1] - x[1][0] * x[0][1]); + + T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; + + if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) + { + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + s[i][j] /= r; + } + } + } + else + { + T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / limits::smallest(); + + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) + { + s[i][j] /= r; + } + else + { + if (singExc) + throw SingMatrixExc ("Cannot invert " + "singular matrix."); + return Matrix33(); + } + } + } + } + + return s; + } + else + { + Matrix33 s ( x[1][1], + -x[0][1], + 0, + + -x[1][0], + x[0][0], + 0, + + 0, + 0, + 1); + + T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; + + if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) + { + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < 2; ++j) + { + s[i][j] /= r; + } + } + } + else + { + T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / limits::smallest(); + + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < 2; ++j) + { + if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) + { + s[i][j] /= r; + } + else + { + if (singExc) + throw SingMatrixExc ("Cannot invert " + "singular matrix."); + return Matrix33(); + } + } + } + } + + s[2][0] = -x[2][0] * s[0][0] - x[2][1] * s[1][0]; + s[2][1] = -x[2][0] * s[0][1] - x[2][1] * s[1][1]; + + return s; + } +} + +template +inline T +Matrix33::minorOf (const int r, const int c) const +{ + int r0 = 0 + (r < 1 ? 1 : 0); + int r1 = 1 + (r < 2 ? 1 : 0); + int c0 = 0 + (c < 1 ? 1 : 0); + int c1 = 1 + (c < 2 ? 1 : 0); + + return x[r0][c0]*x[r1][c1] - x[r1][c0]*x[r0][c1]; +} + +template +inline T +Matrix33::fastMinor( const int r0, const int r1, + const int c0, const int c1) const +{ + return x[r0][c0]*x[r1][c1] - x[r0][c1]*x[r1][c0]; +} + +template +inline T +Matrix33::determinant () const +{ + return x[0][0]*(x[1][1]*x[2][2] - x[1][2]*x[2][1]) + + x[0][1]*(x[1][2]*x[2][0] - x[1][0]*x[2][2]) + + x[0][2]*(x[1][0]*x[2][1] - x[1][1]*x[2][0]); +} + +template +template +const Matrix33 & +Matrix33::setRotation (S r) +{ + S cos_r, sin_r; + + cos_r = Math::cos (r); + sin_r = Math::sin (r); + + x[0][0] = cos_r; + x[0][1] = sin_r; + x[0][2] = 0; + + x[1][0] = -sin_r; + x[1][1] = cos_r; + x[1][2] = 0; + + x[2][0] = 0; + x[2][1] = 0; + x[2][2] = 1; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::rotate (S r) +{ + *this *= Matrix33().setRotation (r); + return *this; +} + +template +const Matrix33 & +Matrix33::setScale (T s) +{ + memset (x, 0, sizeof (x)); + x[0][0] = s; + x[1][1] = s; + x[2][2] = 1; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::setScale (const Vec2 &s) +{ + memset (x, 0, sizeof (x)); + x[0][0] = s[0]; + x[1][1] = s[1]; + x[2][2] = 1; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::scale (const Vec2 &s) +{ + x[0][0] *= s[0]; + x[0][1] *= s[0]; + x[0][2] *= s[0]; + + x[1][0] *= s[1]; + x[1][1] *= s[1]; + x[1][2] *= s[1]; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::setTranslation (const Vec2 &t) +{ + x[0][0] = 1; + x[0][1] = 0; + x[0][2] = 0; + + x[1][0] = 0; + x[1][1] = 1; + x[1][2] = 0; + + x[2][0] = t[0]; + x[2][1] = t[1]; + x[2][2] = 1; + + return *this; +} + +template +inline Vec2 +Matrix33::translation () const +{ + return Vec2 (x[2][0], x[2][1]); +} + +template +template +const Matrix33 & +Matrix33::translate (const Vec2 &t) +{ + x[2][0] += t[0] * x[0][0] + t[1] * x[1][0]; + x[2][1] += t[0] * x[0][1] + t[1] * x[1][1]; + x[2][2] += t[0] * x[0][2] + t[1] * x[1][2]; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::setShear (const S &xy) +{ + x[0][0] = 1; + x[0][1] = 0; + x[0][2] = 0; + + x[1][0] = xy; + x[1][1] = 1; + x[1][2] = 0; + + x[2][0] = 0; + x[2][1] = 0; + x[2][2] = 1; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::setShear (const Vec2 &h) +{ + x[0][0] = 1; + x[0][1] = h[1]; + x[0][2] = 0; + + x[1][0] = h[0]; + x[1][1] = 1; + x[1][2] = 0; + + x[2][0] = 0; + x[2][1] = 0; + x[2][2] = 1; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::shear (const S &xy) +{ + // + // In this case, we don't need a temp. copy of the matrix + // because we never use a value on the RHS after we've + // changed it on the LHS. + // + + x[1][0] += xy * x[0][0]; + x[1][1] += xy * x[0][1]; + x[1][2] += xy * x[0][2]; + + return *this; +} + +template +template +const Matrix33 & +Matrix33::shear (const Vec2 &h) +{ + Matrix33 P (*this); + + x[0][0] = P[0][0] + h[1] * P[1][0]; + x[0][1] = P[0][1] + h[1] * P[1][1]; + x[0][2] = P[0][2] + h[1] * P[1][2]; + + x[1][0] = P[1][0] + h[0] * P[0][0]; + x[1][1] = P[1][1] + h[0] * P[0][1]; + x[1][2] = P[1][2] + h[0] * P[0][2]; + + return *this; +} + + +//--------------------------- +// Implementation of Matrix44 +//--------------------------- + +template +inline T * +Matrix44::operator [] (int i) +{ + return x[i]; +} + +template +inline const T * +Matrix44::operator [] (int i) const +{ + return x[i]; +} + +template +inline +Matrix44::Matrix44 () +{ + memset (x, 0, sizeof (x)); + x[0][0] = 1; + x[1][1] = 1; + x[2][2] = 1; + x[3][3] = 1; +} + +template +inline +Matrix44::Matrix44 (T a) +{ + x[0][0] = a; + x[0][1] = a; + x[0][2] = a; + x[0][3] = a; + x[1][0] = a; + x[1][1] = a; + x[1][2] = a; + x[1][3] = a; + x[2][0] = a; + x[2][1] = a; + x[2][2] = a; + x[2][3] = a; + x[3][0] = a; + x[3][1] = a; + x[3][2] = a; + x[3][3] = a; +} + +template +inline +Matrix44::Matrix44 (const T a[4][4]) +{ + memcpy (x, a, sizeof (x)); +} + +template +inline +Matrix44::Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h, + T i, T j, T k, T l, T m, T n, T o, T p) +{ + x[0][0] = a; + x[0][1] = b; + x[0][2] = c; + x[0][3] = d; + x[1][0] = e; + x[1][1] = f; + x[1][2] = g; + x[1][3] = h; + x[2][0] = i; + x[2][1] = j; + x[2][2] = k; + x[2][3] = l; + x[3][0] = m; + x[3][1] = n; + x[3][2] = o; + x[3][3] = p; +} + + +template +inline +Matrix44::Matrix44 (Matrix33 r, Vec3 t) +{ + x[0][0] = r[0][0]; + x[0][1] = r[0][1]; + x[0][2] = r[0][2]; + x[0][3] = 0; + x[1][0] = r[1][0]; + x[1][1] = r[1][1]; + x[1][2] = r[1][2]; + x[1][3] = 0; + x[2][0] = r[2][0]; + x[2][1] = r[2][1]; + x[2][2] = r[2][2]; + x[2][3] = 0; + x[3][0] = t[0]; + x[3][1] = t[1]; + x[3][2] = t[2]; + x[3][3] = 1; +} + +template +inline +Matrix44::Matrix44 (const Matrix44 &v) +{ + x[0][0] = v.x[0][0]; + x[0][1] = v.x[0][1]; + x[0][2] = v.x[0][2]; + x[0][3] = v.x[0][3]; + x[1][0] = v.x[1][0]; + x[1][1] = v.x[1][1]; + x[1][2] = v.x[1][2]; + x[1][3] = v.x[1][3]; + x[2][0] = v.x[2][0]; + x[2][1] = v.x[2][1]; + x[2][2] = v.x[2][2]; + x[2][3] = v.x[2][3]; + x[3][0] = v.x[3][0]; + x[3][1] = v.x[3][1]; + x[3][2] = v.x[3][2]; + x[3][3] = v.x[3][3]; +} + +template +template +inline +Matrix44::Matrix44 (const Matrix44 &v) +{ + x[0][0] = T (v.x[0][0]); + x[0][1] = T (v.x[0][1]); + x[0][2] = T (v.x[0][2]); + x[0][3] = T (v.x[0][3]); + x[1][0] = T (v.x[1][0]); + x[1][1] = T (v.x[1][1]); + x[1][2] = T (v.x[1][2]); + x[1][3] = T (v.x[1][3]); + x[2][0] = T (v.x[2][0]); + x[2][1] = T (v.x[2][1]); + x[2][2] = T (v.x[2][2]); + x[2][3] = T (v.x[2][3]); + x[3][0] = T (v.x[3][0]); + x[3][1] = T (v.x[3][1]); + x[3][2] = T (v.x[3][2]); + x[3][3] = T (v.x[3][3]); +} + +template +inline const Matrix44 & +Matrix44::operator = (const Matrix44 &v) +{ + x[0][0] = v.x[0][0]; + x[0][1] = v.x[0][1]; + x[0][2] = v.x[0][2]; + x[0][3] = v.x[0][3]; + x[1][0] = v.x[1][0]; + x[1][1] = v.x[1][1]; + x[1][2] = v.x[1][2]; + x[1][3] = v.x[1][3]; + x[2][0] = v.x[2][0]; + x[2][1] = v.x[2][1]; + x[2][2] = v.x[2][2]; + x[2][3] = v.x[2][3]; + x[3][0] = v.x[3][0]; + x[3][1] = v.x[3][1]; + x[3][2] = v.x[3][2]; + x[3][3] = v.x[3][3]; + return *this; +} + +template +inline const Matrix44 & +Matrix44::operator = (T a) +{ + x[0][0] = a; + x[0][1] = a; + x[0][2] = a; + x[0][3] = a; + x[1][0] = a; + x[1][1] = a; + x[1][2] = a; + x[1][3] = a; + x[2][0] = a; + x[2][1] = a; + x[2][2] = a; + x[2][3] = a; + x[3][0] = a; + x[3][1] = a; + x[3][2] = a; + x[3][3] = a; + return *this; +} + +template +inline T * +Matrix44::getValue () +{ + return (T *) &x[0][0]; +} + +template +inline const T * +Matrix44::getValue () const +{ + return (const T *) &x[0][0]; +} + +template +template +inline void +Matrix44::getValue (Matrix44 &v) const +{ + if (isSameType::value) + { + memcpy (v.x, x, sizeof (x)); + } + else + { + v.x[0][0] = x[0][0]; + v.x[0][1] = x[0][1]; + v.x[0][2] = x[0][2]; + v.x[0][3] = x[0][3]; + v.x[1][0] = x[1][0]; + v.x[1][1] = x[1][1]; + v.x[1][2] = x[1][2]; + v.x[1][3] = x[1][3]; + v.x[2][0] = x[2][0]; + v.x[2][1] = x[2][1]; + v.x[2][2] = x[2][2]; + v.x[2][3] = x[2][3]; + v.x[3][0] = x[3][0]; + v.x[3][1] = x[3][1]; + v.x[3][2] = x[3][2]; + v.x[3][3] = x[3][3]; + } +} + +template +template +inline Matrix44 & +Matrix44::setValue (const Matrix44 &v) +{ + if (isSameType::value) + { + memcpy (x, v.x, sizeof (x)); + } + else + { + x[0][0] = v.x[0][0]; + x[0][1] = v.x[0][1]; + x[0][2] = v.x[0][2]; + x[0][3] = v.x[0][3]; + x[1][0] = v.x[1][0]; + x[1][1] = v.x[1][1]; + x[1][2] = v.x[1][2]; + x[1][3] = v.x[1][3]; + x[2][0] = v.x[2][0]; + x[2][1] = v.x[2][1]; + x[2][2] = v.x[2][2]; + x[2][3] = v.x[2][3]; + x[3][0] = v.x[3][0]; + x[3][1] = v.x[3][1]; + x[3][2] = v.x[3][2]; + x[3][3] = v.x[3][3]; + } + + return *this; +} + +template +template +inline Matrix44 & +Matrix44::setTheMatrix (const Matrix44 &v) +{ + if (isSameType::value) + { + memcpy (x, v.x, sizeof (x)); + } + else + { + x[0][0] = v.x[0][0]; + x[0][1] = v.x[0][1]; + x[0][2] = v.x[0][2]; + x[0][3] = v.x[0][3]; + x[1][0] = v.x[1][0]; + x[1][1] = v.x[1][1]; + x[1][2] = v.x[1][2]; + x[1][3] = v.x[1][3]; + x[2][0] = v.x[2][0]; + x[2][1] = v.x[2][1]; + x[2][2] = v.x[2][2]; + x[2][3] = v.x[2][3]; + x[3][0] = v.x[3][0]; + x[3][1] = v.x[3][1]; + x[3][2] = v.x[3][2]; + x[3][3] = v.x[3][3]; + } + + return *this; +} + +template +inline void +Matrix44::makeIdentity() +{ + memset (x, 0, sizeof (x)); + x[0][0] = 1; + x[1][1] = 1; + x[2][2] = 1; + x[3][3] = 1; +} + +template +bool +Matrix44::operator == (const Matrix44 &v) const +{ + return x[0][0] == v.x[0][0] && + x[0][1] == v.x[0][1] && + x[0][2] == v.x[0][2] && + x[0][3] == v.x[0][3] && + x[1][0] == v.x[1][0] && + x[1][1] == v.x[1][1] && + x[1][2] == v.x[1][2] && + x[1][3] == v.x[1][3] && + x[2][0] == v.x[2][0] && + x[2][1] == v.x[2][1] && + x[2][2] == v.x[2][2] && + x[2][3] == v.x[2][3] && + x[3][0] == v.x[3][0] && + x[3][1] == v.x[3][1] && + x[3][2] == v.x[3][2] && + x[3][3] == v.x[3][3]; +} + +template +bool +Matrix44::operator != (const Matrix44 &v) const +{ + return x[0][0] != v.x[0][0] || + x[0][1] != v.x[0][1] || + x[0][2] != v.x[0][2] || + x[0][3] != v.x[0][3] || + x[1][0] != v.x[1][0] || + x[1][1] != v.x[1][1] || + x[1][2] != v.x[1][2] || + x[1][3] != v.x[1][3] || + x[2][0] != v.x[2][0] || + x[2][1] != v.x[2][1] || + x[2][2] != v.x[2][2] || + x[2][3] != v.x[2][3] || + x[3][0] != v.x[3][0] || + x[3][1] != v.x[3][1] || + x[3][2] != v.x[3][2] || + x[3][3] != v.x[3][3]; +} + +template +bool +Matrix44::equalWithAbsError (const Matrix44 &m, T e) const +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) + return false; + + return true; +} + +template +bool +Matrix44::equalWithRelError (const Matrix44 &m, T e) const +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) + return false; + + return true; +} + +template +const Matrix44 & +Matrix44::operator += (const Matrix44 &v) +{ + x[0][0] += v.x[0][0]; + x[0][1] += v.x[0][1]; + x[0][2] += v.x[0][2]; + x[0][3] += v.x[0][3]; + x[1][0] += v.x[1][0]; + x[1][1] += v.x[1][1]; + x[1][2] += v.x[1][2]; + x[1][3] += v.x[1][3]; + x[2][0] += v.x[2][0]; + x[2][1] += v.x[2][1]; + x[2][2] += v.x[2][2]; + x[2][3] += v.x[2][3]; + x[3][0] += v.x[3][0]; + x[3][1] += v.x[3][1]; + x[3][2] += v.x[3][2]; + x[3][3] += v.x[3][3]; + + return *this; +} + +template +const Matrix44 & +Matrix44::operator += (T a) +{ + x[0][0] += a; + x[0][1] += a; + x[0][2] += a; + x[0][3] += a; + x[1][0] += a; + x[1][1] += a; + x[1][2] += a; + x[1][3] += a; + x[2][0] += a; + x[2][1] += a; + x[2][2] += a; + x[2][3] += a; + x[3][0] += a; + x[3][1] += a; + x[3][2] += a; + x[3][3] += a; + + return *this; +} + +template +Matrix44 +Matrix44::operator + (const Matrix44 &v) const +{ + return Matrix44 (x[0][0] + v.x[0][0], + x[0][1] + v.x[0][1], + x[0][2] + v.x[0][2], + x[0][3] + v.x[0][3], + x[1][0] + v.x[1][0], + x[1][1] + v.x[1][1], + x[1][2] + v.x[1][2], + x[1][3] + v.x[1][3], + x[2][0] + v.x[2][0], + x[2][1] + v.x[2][1], + x[2][2] + v.x[2][2], + x[2][3] + v.x[2][3], + x[3][0] + v.x[3][0], + x[3][1] + v.x[3][1], + x[3][2] + v.x[3][2], + x[3][3] + v.x[3][3]); +} + +template +const Matrix44 & +Matrix44::operator -= (const Matrix44 &v) +{ + x[0][0] -= v.x[0][0]; + x[0][1] -= v.x[0][1]; + x[0][2] -= v.x[0][2]; + x[0][3] -= v.x[0][3]; + x[1][0] -= v.x[1][0]; + x[1][1] -= v.x[1][1]; + x[1][2] -= v.x[1][2]; + x[1][3] -= v.x[1][3]; + x[2][0] -= v.x[2][0]; + x[2][1] -= v.x[2][1]; + x[2][2] -= v.x[2][2]; + x[2][3] -= v.x[2][3]; + x[3][0] -= v.x[3][0]; + x[3][1] -= v.x[3][1]; + x[3][2] -= v.x[3][2]; + x[3][3] -= v.x[3][3]; + + return *this; +} + +template +const Matrix44 & +Matrix44::operator -= (T a) +{ + x[0][0] -= a; + x[0][1] -= a; + x[0][2] -= a; + x[0][3] -= a; + x[1][0] -= a; + x[1][1] -= a; + x[1][2] -= a; + x[1][3] -= a; + x[2][0] -= a; + x[2][1] -= a; + x[2][2] -= a; + x[2][3] -= a; + x[3][0] -= a; + x[3][1] -= a; + x[3][2] -= a; + x[3][3] -= a; + + return *this; +} + +template +Matrix44 +Matrix44::operator - (const Matrix44 &v) const +{ + return Matrix44 (x[0][0] - v.x[0][0], + x[0][1] - v.x[0][1], + x[0][2] - v.x[0][2], + x[0][3] - v.x[0][3], + x[1][0] - v.x[1][0], + x[1][1] - v.x[1][1], + x[1][2] - v.x[1][2], + x[1][3] - v.x[1][3], + x[2][0] - v.x[2][0], + x[2][1] - v.x[2][1], + x[2][2] - v.x[2][2], + x[2][3] - v.x[2][3], + x[3][0] - v.x[3][0], + x[3][1] - v.x[3][1], + x[3][2] - v.x[3][2], + x[3][3] - v.x[3][3]); +} + +template +Matrix44 +Matrix44::operator - () const +{ + return Matrix44 (-x[0][0], + -x[0][1], + -x[0][2], + -x[0][3], + -x[1][0], + -x[1][1], + -x[1][2], + -x[1][3], + -x[2][0], + -x[2][1], + -x[2][2], + -x[2][3], + -x[3][0], + -x[3][1], + -x[3][2], + -x[3][3]); +} + +template +const Matrix44 & +Matrix44::negate () +{ + x[0][0] = -x[0][0]; + x[0][1] = -x[0][1]; + x[0][2] = -x[0][2]; + x[0][3] = -x[0][3]; + x[1][0] = -x[1][0]; + x[1][1] = -x[1][1]; + x[1][2] = -x[1][2]; + x[1][3] = -x[1][3]; + x[2][0] = -x[2][0]; + x[2][1] = -x[2][1]; + x[2][2] = -x[2][2]; + x[2][3] = -x[2][3]; + x[3][0] = -x[3][0]; + x[3][1] = -x[3][1]; + x[3][2] = -x[3][2]; + x[3][3] = -x[3][3]; + + return *this; +} + +template +const Matrix44 & +Matrix44::operator *= (T a) +{ + x[0][0] *= a; + x[0][1] *= a; + x[0][2] *= a; + x[0][3] *= a; + x[1][0] *= a; + x[1][1] *= a; + x[1][2] *= a; + x[1][3] *= a; + x[2][0] *= a; + x[2][1] *= a; + x[2][2] *= a; + x[2][3] *= a; + x[3][0] *= a; + x[3][1] *= a; + x[3][2] *= a; + x[3][3] *= a; + + return *this; +} + +template +Matrix44 +Matrix44::operator * (T a) const +{ + return Matrix44 (x[0][0] * a, + x[0][1] * a, + x[0][2] * a, + x[0][3] * a, + x[1][0] * a, + x[1][1] * a, + x[1][2] * a, + x[1][3] * a, + x[2][0] * a, + x[2][1] * a, + x[2][2] * a, + x[2][3] * a, + x[3][0] * a, + x[3][1] * a, + x[3][2] * a, + x[3][3] * a); +} + +template +inline Matrix44 +operator * (T a, const Matrix44 &v) +{ + return v * a; +} + +template +inline const Matrix44 & +Matrix44::operator *= (const Matrix44 &v) +{ + Matrix44 tmp (T (0)); + + multiply (*this, v, tmp); + *this = tmp; + return *this; +} + +template +inline Matrix44 +Matrix44::operator * (const Matrix44 &v) const +{ + Matrix44 tmp (T (0)); + + multiply (*this, v, tmp); + return tmp; +} + +template +void +Matrix44::multiply (const Matrix44 &a, + const Matrix44 &b, + Matrix44 &c) +{ + register const T * IMATH_RESTRICT ap = &a.x[0][0]; + register const T * IMATH_RESTRICT bp = &b.x[0][0]; + register T * IMATH_RESTRICT cp = &c.x[0][0]; + + register T a0, a1, a2, a3; + + a0 = ap[0]; + a1 = ap[1]; + a2 = ap[2]; + a3 = ap[3]; + + cp[0] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12]; + cp[1] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13]; + cp[2] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14]; + cp[3] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15]; + + a0 = ap[4]; + a1 = ap[5]; + a2 = ap[6]; + a3 = ap[7]; + + cp[4] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12]; + cp[5] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13]; + cp[6] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14]; + cp[7] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15]; + + a0 = ap[8]; + a1 = ap[9]; + a2 = ap[10]; + a3 = ap[11]; + + cp[8] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12]; + cp[9] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13]; + cp[10] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14]; + cp[11] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15]; + + a0 = ap[12]; + a1 = ap[13]; + a2 = ap[14]; + a3 = ap[15]; + + cp[12] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12]; + cp[13] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13]; + cp[14] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14]; + cp[15] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15]; +} + +template template +void +Matrix44::multVecMatrix(const Vec3 &src, Vec3 &dst) const +{ + S a, b, c, w; + + a = src[0] * x[0][0] + src[1] * x[1][0] + src[2] * x[2][0] + x[3][0]; + b = src[0] * x[0][1] + src[1] * x[1][1] + src[2] * x[2][1] + x[3][1]; + c = src[0] * x[0][2] + src[1] * x[1][2] + src[2] * x[2][2] + x[3][2]; + w = src[0] * x[0][3] + src[1] * x[1][3] + src[2] * x[2][3] + x[3][3]; + + dst.x = a / w; + dst.y = b / w; + dst.z = c / w; +} + +template template +void +Matrix44::multDirMatrix(const Vec3 &src, Vec3 &dst) const +{ + S a, b, c; + + a = src[0] * x[0][0] + src[1] * x[1][0] + src[2] * x[2][0]; + b = src[0] * x[0][1] + src[1] * x[1][1] + src[2] * x[2][1]; + c = src[0] * x[0][2] + src[1] * x[1][2] + src[2] * x[2][2]; + + dst.x = a; + dst.y = b; + dst.z = c; +} + +template +const Matrix44 & +Matrix44::operator /= (T a) +{ + x[0][0] /= a; + x[0][1] /= a; + x[0][2] /= a; + x[0][3] /= a; + x[1][0] /= a; + x[1][1] /= a; + x[1][2] /= a; + x[1][3] /= a; + x[2][0] /= a; + x[2][1] /= a; + x[2][2] /= a; + x[2][3] /= a; + x[3][0] /= a; + x[3][1] /= a; + x[3][2] /= a; + x[3][3] /= a; + + return *this; +} + +template +Matrix44 +Matrix44::operator / (T a) const +{ + return Matrix44 (x[0][0] / a, + x[0][1] / a, + x[0][2] / a, + x[0][3] / a, + x[1][0] / a, + x[1][1] / a, + x[1][2] / a, + x[1][3] / a, + x[2][0] / a, + x[2][1] / a, + x[2][2] / a, + x[2][3] / a, + x[3][0] / a, + x[3][1] / a, + x[3][2] / a, + x[3][3] / a); +} + +template +const Matrix44 & +Matrix44::transpose () +{ + Matrix44 tmp (x[0][0], + x[1][0], + x[2][0], + x[3][0], + x[0][1], + x[1][1], + x[2][1], + x[3][1], + x[0][2], + x[1][2], + x[2][2], + x[3][2], + x[0][3], + x[1][3], + x[2][3], + x[3][3]); + *this = tmp; + return *this; +} + +template +Matrix44 +Matrix44::transposed () const +{ + return Matrix44 (x[0][0], + x[1][0], + x[2][0], + x[3][0], + x[0][1], + x[1][1], + x[2][1], + x[3][1], + x[0][2], + x[1][2], + x[2][2], + x[3][2], + x[0][3], + x[1][3], + x[2][3], + x[3][3]); +} + +template +const Matrix44 & +Matrix44::gjInvert (bool singExc) throw (IEX_NAMESPACE::MathExc) +{ + *this = gjInverse (singExc); + return *this; +} + +template +Matrix44 +Matrix44::gjInverse (bool singExc) const throw (IEX_NAMESPACE::MathExc) +{ + int i, j, k; + Matrix44 s; + Matrix44 t (*this); + + // Forward elimination + + for (i = 0; i < 3 ; i++) + { + int pivot = i; + + T pivotsize = t[i][i]; + + if (pivotsize < 0) + pivotsize = -pivotsize; + + for (j = i + 1; j < 4; j++) + { + T tmp = t[j][i]; + + if (tmp < 0) + tmp = -tmp; + + if (tmp > pivotsize) + { + pivot = j; + pivotsize = tmp; + } + } + + if (pivotsize == 0) + { + if (singExc) + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); + + return Matrix44(); + } + + if (pivot != i) + { + for (j = 0; j < 4; j++) + { + T tmp; + + tmp = t[i][j]; + t[i][j] = t[pivot][j]; + t[pivot][j] = tmp; + + tmp = s[i][j]; + s[i][j] = s[pivot][j]; + s[pivot][j] = tmp; + } + } + + for (j = i + 1; j < 4; j++) + { + T f = t[j][i] / t[i][i]; + + for (k = 0; k < 4; k++) + { + t[j][k] -= f * t[i][k]; + s[j][k] -= f * s[i][k]; + } + } + } + + // Backward substitution + + for (i = 3; i >= 0; --i) + { + T f; + + if ((f = t[i][i]) == 0) + { + if (singExc) + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); + + return Matrix44(); + } + + for (j = 0; j < 4; j++) + { + t[i][j] /= f; + s[i][j] /= f; + } + + for (j = 0; j < i; j++) + { + f = t[j][i]; + + for (k = 0; k < 4; k++) + { + t[j][k] -= f * t[i][k]; + s[j][k] -= f * s[i][k]; + } + } + } + + return s; +} + +template +const Matrix44 & +Matrix44::invert (bool singExc) throw (IEX_NAMESPACE::MathExc) +{ + *this = inverse (singExc); + return *this; +} + +template +Matrix44 +Matrix44::inverse (bool singExc) const throw (IEX_NAMESPACE::MathExc) +{ + if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1) + return gjInverse(singExc); + + Matrix44 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], + x[2][1] * x[0][2] - x[0][1] * x[2][2], + x[0][1] * x[1][2] - x[1][1] * x[0][2], + 0, + + x[2][0] * x[1][2] - x[1][0] * x[2][2], + x[0][0] * x[2][2] - x[2][0] * x[0][2], + x[1][0] * x[0][2] - x[0][0] * x[1][2], + 0, + + x[1][0] * x[2][1] - x[2][0] * x[1][1], + x[2][0] * x[0][1] - x[0][0] * x[2][1], + x[0][0] * x[1][1] - x[1][0] * x[0][1], + 0, + + 0, + 0, + 0, + 1); + + T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; + + if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) + { + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + s[i][j] /= r; + } + } + } + else + { + T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / limits::smallest(); + + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) + { + s[i][j] /= r; + } + else + { + if (singExc) + throw SingMatrixExc ("Cannot invert singular matrix."); + + return Matrix44(); + } + } + } + } + + s[3][0] = -x[3][0] * s[0][0] - x[3][1] * s[1][0] - x[3][2] * s[2][0]; + s[3][1] = -x[3][0] * s[0][1] - x[3][1] * s[1][1] - x[3][2] * s[2][1]; + s[3][2] = -x[3][0] * s[0][2] - x[3][1] * s[1][2] - x[3][2] * s[2][2]; + + return s; +} + +template +inline T +Matrix44::fastMinor( const int r0, const int r1, const int r2, + const int c0, const int c1, const int c2) const +{ + return x[r0][c0] * (x[r1][c1]*x[r2][c2] - x[r1][c2]*x[r2][c1]) + + x[r0][c1] * (x[r1][c2]*x[r2][c0] - x[r1][c0]*x[r2][c2]) + + x[r0][c2] * (x[r1][c0]*x[r2][c1] - x[r1][c1]*x[r2][c0]); +} + +template +inline T +Matrix44::minorOf (const int r, const int c) const +{ + int r0 = 0 + (r < 1 ? 1 : 0); + int r1 = 1 + (r < 2 ? 1 : 0); + int r2 = 2 + (r < 3 ? 1 : 0); + int c0 = 0 + (c < 1 ? 1 : 0); + int c1 = 1 + (c < 2 ? 1 : 0); + int c2 = 2 + (c < 3 ? 1 : 0); + + Matrix33 working (x[r0][c0],x[r1][c0],x[r2][c0], + x[r0][c1],x[r1][c1],x[r2][c1], + x[r0][c2],x[r1][c2],x[r2][c2]); + + return working.determinant(); +} + +template +inline T +Matrix44::determinant () const +{ + T sum = (T)0; + + if (x[0][3] != 0.) sum -= x[0][3] * fastMinor(1,2,3,0,1,2); + if (x[1][3] != 0.) sum += x[1][3] * fastMinor(0,2,3,0,1,2); + if (x[2][3] != 0.) sum -= x[2][3] * fastMinor(0,1,3,0,1,2); + if (x[3][3] != 0.) sum += x[3][3] * fastMinor(0,1,2,0,1,2); + + return sum; +} + +template +template +const Matrix44 & +Matrix44::setEulerAngles (const Vec3& r) +{ + S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; + + cos_rz = Math::cos (r[2]); + cos_ry = Math::cos (r[1]); + cos_rx = Math::cos (r[0]); + + sin_rz = Math::sin (r[2]); + sin_ry = Math::sin (r[1]); + sin_rx = Math::sin (r[0]); + + x[0][0] = cos_rz * cos_ry; + x[0][1] = sin_rz * cos_ry; + x[0][2] = -sin_ry; + x[0][3] = 0; + + x[1][0] = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; + x[1][1] = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; + x[1][2] = cos_ry * sin_rx; + x[1][3] = 0; + + x[2][0] = sin_rz * sin_rx + cos_rz * sin_ry * cos_rx; + x[2][1] = -cos_rz * sin_rx + sin_rz * sin_ry * cos_rx; + x[2][2] = cos_ry * cos_rx; + x[2][3] = 0; + + x[3][0] = 0; + x[3][1] = 0; + x[3][2] = 0; + x[3][3] = 1; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::setAxisAngle (const Vec3& axis, S angle) +{ + Vec3 unit (axis.normalized()); + S sine = Math::sin (angle); + S cosine = Math::cos (angle); + + x[0][0] = unit[0] * unit[0] * (1 - cosine) + cosine; + x[0][1] = unit[0] * unit[1] * (1 - cosine) + unit[2] * sine; + x[0][2] = unit[0] * unit[2] * (1 - cosine) - unit[1] * sine; + x[0][3] = 0; + + x[1][0] = unit[0] * unit[1] * (1 - cosine) - unit[2] * sine; + x[1][1] = unit[1] * unit[1] * (1 - cosine) + cosine; + x[1][2] = unit[1] * unit[2] * (1 - cosine) + unit[0] * sine; + x[1][3] = 0; + + x[2][0] = unit[0] * unit[2] * (1 - cosine) + unit[1] * sine; + x[2][1] = unit[1] * unit[2] * (1 - cosine) - unit[0] * sine; + x[2][2] = unit[2] * unit[2] * (1 - cosine) + cosine; + x[2][3] = 0; + + x[3][0] = 0; + x[3][1] = 0; + x[3][2] = 0; + x[3][3] = 1; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::rotate (const Vec3 &r) +{ + S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; + S m00, m01, m02; + S m10, m11, m12; + S m20, m21, m22; + + cos_rz = Math::cos (r[2]); + cos_ry = Math::cos (r[1]); + cos_rx = Math::cos (r[0]); + + sin_rz = Math::sin (r[2]); + sin_ry = Math::sin (r[1]); + sin_rx = Math::sin (r[0]); + + m00 = cos_rz * cos_ry; + m01 = sin_rz * cos_ry; + m02 = -sin_ry; + m10 = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; + m11 = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; + m12 = cos_ry * sin_rx; + m20 = -sin_rz * -sin_rx + cos_rz * sin_ry * cos_rx; + m21 = cos_rz * -sin_rx + sin_rz * sin_ry * cos_rx; + m22 = cos_ry * cos_rx; + + Matrix44 P (*this); + + x[0][0] = P[0][0] * m00 + P[1][0] * m01 + P[2][0] * m02; + x[0][1] = P[0][1] * m00 + P[1][1] * m01 + P[2][1] * m02; + x[0][2] = P[0][2] * m00 + P[1][2] * m01 + P[2][2] * m02; + x[0][3] = P[0][3] * m00 + P[1][3] * m01 + P[2][3] * m02; + + x[1][0] = P[0][0] * m10 + P[1][0] * m11 + P[2][0] * m12; + x[1][1] = P[0][1] * m10 + P[1][1] * m11 + P[2][1] * m12; + x[1][2] = P[0][2] * m10 + P[1][2] * m11 + P[2][2] * m12; + x[1][3] = P[0][3] * m10 + P[1][3] * m11 + P[2][3] * m12; + + x[2][0] = P[0][0] * m20 + P[1][0] * m21 + P[2][0] * m22; + x[2][1] = P[0][1] * m20 + P[1][1] * m21 + P[2][1] * m22; + x[2][2] = P[0][2] * m20 + P[1][2] * m21 + P[2][2] * m22; + x[2][3] = P[0][3] * m20 + P[1][3] * m21 + P[2][3] * m22; + + return *this; +} + +template +const Matrix44 & +Matrix44::setScale (T s) +{ + memset (x, 0, sizeof (x)); + x[0][0] = s; + x[1][1] = s; + x[2][2] = s; + x[3][3] = 1; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::setScale (const Vec3 &s) +{ + memset (x, 0, sizeof (x)); + x[0][0] = s[0]; + x[1][1] = s[1]; + x[2][2] = s[2]; + x[3][3] = 1; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::scale (const Vec3 &s) +{ + x[0][0] *= s[0]; + x[0][1] *= s[0]; + x[0][2] *= s[0]; + x[0][3] *= s[0]; + + x[1][0] *= s[1]; + x[1][1] *= s[1]; + x[1][2] *= s[1]; + x[1][3] *= s[1]; + + x[2][0] *= s[2]; + x[2][1] *= s[2]; + x[2][2] *= s[2]; + x[2][3] *= s[2]; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::setTranslation (const Vec3 &t) +{ + x[0][0] = 1; + x[0][1] = 0; + x[0][2] = 0; + x[0][3] = 0; + + x[1][0] = 0; + x[1][1] = 1; + x[1][2] = 0; + x[1][3] = 0; + + x[2][0] = 0; + x[2][1] = 0; + x[2][2] = 1; + x[2][3] = 0; + + x[3][0] = t[0]; + x[3][1] = t[1]; + x[3][2] = t[2]; + x[3][3] = 1; + + return *this; +} + +template +inline const Vec3 +Matrix44::translation () const +{ + return Vec3 (x[3][0], x[3][1], x[3][2]); +} + +template +template +const Matrix44 & +Matrix44::translate (const Vec3 &t) +{ + x[3][0] += t[0] * x[0][0] + t[1] * x[1][0] + t[2] * x[2][0]; + x[3][1] += t[0] * x[0][1] + t[1] * x[1][1] + t[2] * x[2][1]; + x[3][2] += t[0] * x[0][2] + t[1] * x[1][2] + t[2] * x[2][2]; + x[3][3] += t[0] * x[0][3] + t[1] * x[1][3] + t[2] * x[2][3]; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::setShear (const Vec3 &h) +{ + x[0][0] = 1; + x[0][1] = 0; + x[0][2] = 0; + x[0][3] = 0; + + x[1][0] = h[0]; + x[1][1] = 1; + x[1][2] = 0; + x[1][3] = 0; + + x[2][0] = h[1]; + x[2][1] = h[2]; + x[2][2] = 1; + x[2][3] = 0; + + x[3][0] = 0; + x[3][1] = 0; + x[3][2] = 0; + x[3][3] = 1; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::setShear (const Shear6 &h) +{ + x[0][0] = 1; + x[0][1] = h.yx; + x[0][2] = h.zx; + x[0][3] = 0; + + x[1][0] = h.xy; + x[1][1] = 1; + x[1][2] = h.zy; + x[1][3] = 0; + + x[2][0] = h.xz; + x[2][1] = h.yz; + x[2][2] = 1; + x[2][3] = 0; + + x[3][0] = 0; + x[3][1] = 0; + x[3][2] = 0; + x[3][3] = 1; + + return *this; +} + +template +template +const Matrix44 & +Matrix44::shear (const Vec3 &h) +{ + // + // In this case, we don't need a temp. copy of the matrix + // because we never use a value on the RHS after we've + // changed it on the LHS. + // + + for (int i=0; i < 4; i++) + { + x[2][i] += h[1] * x[0][i] + h[2] * x[1][i]; + x[1][i] += h[0] * x[0][i]; + } + + return *this; +} + +template +template +const Matrix44 & +Matrix44::shear (const Shear6 &h) +{ + Matrix44 P (*this); + + for (int i=0; i < 4; i++) + { + x[0][i] = P[0][i] + h.yx * P[1][i] + h.zx * P[2][i]; + x[1][i] = h.xy * P[0][i] + P[1][i] + h.zy * P[2][i]; + x[2][i] = h.xz * P[0][i] + h.yz * P[1][i] + P[2][i]; + } + + return *this; +} + + +//-------------------------------- +// Implementation of stream output +//-------------------------------- + +template +std::ostream & +operator << (std::ostream &s, const Matrix33 &m) +{ + std::ios_base::fmtflags oldFlags = s.flags(); + int width; + + if (s.flags() & std::ios_base::fixed) + { + s.setf (std::ios_base::showpoint); + width = s.precision() + 5; + } + else + { + s.setf (std::ios_base::scientific); + s.setf (std::ios_base::showpoint); + width = s.precision() + 8; + } + + s << "(" << std::setw (width) << m[0][0] << + " " << std::setw (width) << m[0][1] << + " " << std::setw (width) << m[0][2] << "\n" << + + " " << std::setw (width) << m[1][0] << + " " << std::setw (width) << m[1][1] << + " " << std::setw (width) << m[1][2] << "\n" << + + " " << std::setw (width) << m[2][0] << + " " << std::setw (width) << m[2][1] << + " " << std::setw (width) << m[2][2] << ")\n"; + + s.flags (oldFlags); + return s; +} + +template +std::ostream & +operator << (std::ostream &s, const Matrix44 &m) +{ + std::ios_base::fmtflags oldFlags = s.flags(); + int width; + + if (s.flags() & std::ios_base::fixed) + { + s.setf (std::ios_base::showpoint); + width = s.precision() + 5; + } + else + { + s.setf (std::ios_base::scientific); + s.setf (std::ios_base::showpoint); + width = s.precision() + 8; + } + + s << "(" << std::setw (width) << m[0][0] << + " " << std::setw (width) << m[0][1] << + " " << std::setw (width) << m[0][2] << + " " << std::setw (width) << m[0][3] << "\n" << + + " " << std::setw (width) << m[1][0] << + " " << std::setw (width) << m[1][1] << + " " << std::setw (width) << m[1][2] << + " " << std::setw (width) << m[1][3] << "\n" << + + " " << std::setw (width) << m[2][0] << + " " << std::setw (width) << m[2][1] << + " " << std::setw (width) << m[2][2] << + " " << std::setw (width) << m[2][3] << "\n" << + + " " << std::setw (width) << m[3][0] << + " " << std::setw (width) << m[3][1] << + " " << std::setw (width) << m[3][2] << + " " << std::setw (width) << m[3][3] << ")\n"; + + s.flags (oldFlags); + return s; +} + + +//--------------------------------------------------------------- +// Implementation of vector-times-matrix multiplication operators +//--------------------------------------------------------------- + +template +inline const Vec2 & +operator *= (Vec2 &v, const Matrix33 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + m[2][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + m[2][1]); + S w = S(v.x * m[0][2] + v.y * m[1][2] + m[2][2]); + + v.x = x / w; + v.y = y / w; + + return v; +} + +template +inline Vec2 +operator * (const Vec2 &v, const Matrix33 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + m[2][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + m[2][1]); + S w = S(v.x * m[0][2] + v.y * m[1][2] + m[2][2]); + + return Vec2 (x / w, y / w); +} + + +template +inline const Vec3 & +operator *= (Vec3 &v, const Matrix33 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1]); + S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]); + + v.x = x; + v.y = y; + v.z = z; + + return v; +} + +template +inline Vec3 +operator * (const Vec3 &v, const Matrix33 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1]); + S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]); + + return Vec3 (x, y, z); +} + + +template +inline const Vec3 & +operator *= (Vec3 &v, const Matrix44 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1]); + S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]); + S w = S(v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + m[3][3]); + + v.x = x / w; + v.y = y / w; + v.z = z / w; + + return v; +} + +template +inline Vec3 +operator * (const Vec3 &v, const Matrix44 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1]); + S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]); + S w = S(v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + m[3][3]); + + return Vec3 (x / w, y / w, z / w); +} + + +template +inline const Vec4 & +operator *= (Vec4 &v, const Matrix44 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + v.w * m[3][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + v.w * m[3][1]); + S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + v.w * m[3][2]); + S w = S(v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + v.w * m[3][3]); + + v.x = x; + v.y = y; + v.z = z; + v.w = w; + + return v; +} + +template +inline Vec4 +operator * (const Vec4 &v, const Matrix44 &m) +{ + S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + v.w * m[3][0]); + S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + v.w * m[3][1]); + S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + v.w * m[3][2]); + S w = S(v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + v.w * m[3][3]); + + return Vec4 (x, y, z, w); +} + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHMATRIX_H diff --git a/OpenEXR/include/OpenEXR/ImathMatrixAlgo.h b/OpenEXR/include/OpenEXR/ImathMatrixAlgo.h new file mode 100644 index 0000000..8e90b02 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathMatrixAlgo.h @@ -0,0 +1,1425 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHMATRIXALGO_H +#define INCLUDED_IMATHMATRIXALGO_H + +//------------------------------------------------------------------------- +// +// This file contains algorithms applied to or in conjunction with +// transformation matrices (Imath::Matrix33 and Imath::Matrix44). +// The assumption made is that these functions are called much less +// often than the basic point functions or these functions require +// more support classes. +// +// This file also defines a few predefined constant matrices. +// +//------------------------------------------------------------------------- + +#include "ImathExport.h" +#include "ImathMatrix.h" +#include "ImathQuat.h" +#include "ImathEuler.h" +#include "ImathExc.h" +#include "ImathVec.h" +#include "ImathLimits.h" +#include "ImathNamespace.h" +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +//------------------ +// Identity matrices +//------------------ + +IMATH_EXPORT_CONST M33f identity33f; +IMATH_EXPORT_CONST M44f identity44f; +IMATH_EXPORT_CONST M33d identity33d; +IMATH_EXPORT_CONST M44d identity44d; + +//---------------------------------------------------------------------- +// Extract scale, shear, rotation, and translation values from a matrix: +// +// Notes: +// +// This implementation follows the technique described in the paper by +// Spencer W. Thomas in the Graphics Gems II article: "Decomposing a +// Matrix into Simple Transformations", p. 320. +// +// - Some of the functions below have an optional exc parameter +// that determines the functions' behavior when the matrix' +// scaling is very close to zero: +// +// If exc is true, the functions throw an Imath::ZeroScale exception. +// +// If exc is false: +// +// extractScaling (m, s) returns false, s is invalid +// sansScaling (m) returns m +// removeScaling (m) returns false, m is unchanged +// sansScalingAndShear (m) returns m +// removeScalingAndShear (m) returns false, m is unchanged +// extractAndRemoveScalingAndShear (m, s, h) +// returns false, m is unchanged, +// (sh) are invalid +// checkForZeroScaleInRow () returns false +// extractSHRT (m, s, h, r, t) returns false, (shrt) are invalid +// +// - Functions extractEuler(), extractEulerXYZ() and extractEulerZYX() +// assume that the matrix does not include shear or non-uniform scaling, +// but they do not examine the matrix to verify this assumption. +// Matrices with shear or non-uniform scaling are likely to produce +// meaningless results. Therefore, you should use the +// removeScalingAndShear() routine, if necessary, prior to calling +// extractEuler...() . +// +// - All functions assume that the matrix does not include perspective +// transformation(s), but they do not examine the matrix to verify +// this assumption. Matrices with perspective transformations are +// likely to produce meaningless results. +// +//---------------------------------------------------------------------- + + +// +// Declarations for 4x4 matrix. +// + +template bool extractScaling + (const Matrix44 &mat, + Vec3 &scl, + bool exc = true); + +template Matrix44 sansScaling (const Matrix44 &mat, + bool exc = true); + +template bool removeScaling + (Matrix44 &mat, + bool exc = true); + +template bool extractScalingAndShear + (const Matrix44 &mat, + Vec3 &scl, + Vec3 &shr, + bool exc = true); + +template Matrix44 sansScalingAndShear + (const Matrix44 &mat, + bool exc = true); + +template void sansScalingAndShear + (Matrix44 &result, + const Matrix44 &mat, + bool exc = true); + +template bool removeScalingAndShear + (Matrix44 &mat, + bool exc = true); + +template bool extractAndRemoveScalingAndShear + (Matrix44 &mat, + Vec3 &scl, + Vec3 &shr, + bool exc = true); + +template void extractEulerXYZ + (const Matrix44 &mat, + Vec3 &rot); + +template void extractEulerZYX + (const Matrix44 &mat, + Vec3 &rot); + +template Quat extractQuat (const Matrix44 &mat); + +template bool extractSHRT + (const Matrix44 &mat, + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc /*= true*/, + typename Euler::Order rOrder); + +template bool extractSHRT + (const Matrix44 &mat, + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc = true); + +template bool extractSHRT + (const Matrix44 &mat, + Vec3 &s, + Vec3 &h, + Euler &r, + Vec3 &t, + bool exc = true); + +// +// Internal utility function. +// + +template bool checkForZeroScaleInRow + (const T &scl, + const Vec3 &row, + bool exc = true); + +template Matrix44 outerProduct + ( const Vec4 &a, + const Vec4 &b); + + +// +// Returns a matrix that rotates "fromDirection" vector to "toDirection" +// vector. +// + +template Matrix44 rotationMatrix (const Vec3 &fromDirection, + const Vec3 &toDirection); + + + +// +// Returns a matrix that rotates the "fromDir" vector +// so that it points towards "toDir". You may also +// specify that you want the up vector to be pointing +// in a certain direction "upDir". +// + +template Matrix44 rotationMatrixWithUpDir + (const Vec3 &fromDir, + const Vec3 &toDir, + const Vec3 &upDir); + + +// +// Constructs a matrix that rotates the z-axis so that it +// points towards "targetDir". You must also specify +// that you want the up vector to be pointing in a +// certain direction "upDir". +// +// Notes: The following degenerate cases are handled: +// (a) when the directions given by "toDir" and "upDir" +// are parallel or opposite; +// (the direction vectors must have a non-zero cross product) +// (b) when any of the given direction vectors have zero length +// + +template void alignZAxisWithTargetDir + (Matrix44 &result, + Vec3 targetDir, + Vec3 upDir); + + +// Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis +// If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis. +// Inputs are : +// -the position of the frame +// -the x axis direction of the frame +// -a normal to the y axis of the frame +// Return is the orthonormal frame +template Matrix44 computeLocalFrame( const Vec3& p, + const Vec3& xDir, + const Vec3& normal); + +// Add a translate/rotate/scale offset to an input frame +// and put it in another frame of reference +// Inputs are : +// - input frame +// - translate offset +// - rotate offset in degrees +// - scale offset +// - frame of reference +// Output is the offsetted frame +template Matrix44 addOffset( const Matrix44& inMat, + const Vec3& tOffset, + const Vec3& rOffset, + const Vec3& sOffset, + const Vec3& ref); + +// Compute Translate/Rotate/Scale matrix from matrix A with the Rotate/Scale of Matrix B +// Inputs are : +// -keepRotateA : if true keep rotate from matrix A, use B otherwise +// -keepScaleA : if true keep scale from matrix A, use B otherwise +// -Matrix A +// -Matrix B +// Return Matrix A with tweaked rotation/scale +template Matrix44 computeRSMatrix( bool keepRotateA, + bool keepScaleA, + const Matrix44& A, + const Matrix44& B); + + +//---------------------------------------------------------------------- + + +// +// Declarations for 3x3 matrix. +// + + +template bool extractScaling + (const Matrix33 &mat, + Vec2 &scl, + bool exc = true); + +template Matrix33 sansScaling (const Matrix33 &mat, + bool exc = true); + +template bool removeScaling + (Matrix33 &mat, + bool exc = true); + +template bool extractScalingAndShear + (const Matrix33 &mat, + Vec2 &scl, + T &h, + bool exc = true); + +template Matrix33 sansScalingAndShear + (const Matrix33 &mat, + bool exc = true); + +template bool removeScalingAndShear + (Matrix33 &mat, + bool exc = true); + +template bool extractAndRemoveScalingAndShear + (Matrix33 &mat, + Vec2 &scl, + T &shr, + bool exc = true); + +template void extractEuler + (const Matrix33 &mat, + T &rot); + +template bool extractSHRT (const Matrix33 &mat, + Vec2 &s, + T &h, + T &r, + Vec2 &t, + bool exc = true); + +template bool checkForZeroScaleInRow + (const T &scl, + const Vec2 &row, + bool exc = true); + +template Matrix33 outerProduct + ( const Vec3 &a, + const Vec3 &b); + + +//----------------------------------------------------------------------------- +// Implementation for 4x4 Matrix +//------------------------------ + + +template +bool +extractScaling (const Matrix44 &mat, Vec3 &scl, bool exc) +{ + Vec3 shr; + Matrix44 M (mat); + + if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) + return false; + + return true; +} + + +template +Matrix44 +sansScaling (const Matrix44 &mat, bool exc) +{ + Vec3 scl; + Vec3 shr; + Vec3 rot; + Vec3 tran; + + if (! extractSHRT (mat, scl, shr, rot, tran, exc)) + return mat; + + Matrix44 M; + + M.translate (tran); + M.rotate (rot); + M.shear (shr); + + return M; +} + + +template +bool +removeScaling (Matrix44 &mat, bool exc) +{ + Vec3 scl; + Vec3 shr; + Vec3 rot; + Vec3 tran; + + if (! extractSHRT (mat, scl, shr, rot, tran, exc)) + return false; + + mat.makeIdentity (); + mat.translate (tran); + mat.rotate (rot); + mat.shear (shr); + + return true; +} + + +template +bool +extractScalingAndShear (const Matrix44 &mat, + Vec3 &scl, Vec3 &shr, bool exc) +{ + Matrix44 M (mat); + + if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) + return false; + + return true; +} + + +template +Matrix44 +sansScalingAndShear (const Matrix44 &mat, bool exc) +{ + Vec3 scl; + Vec3 shr; + Matrix44 M (mat); + + if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) + return mat; + + return M; +} + + +template +void +sansScalingAndShear (Matrix44 &result, const Matrix44 &mat, bool exc) +{ + Vec3 scl; + Vec3 shr; + + if (! extractAndRemoveScalingAndShear (result, scl, shr, exc)) + result = mat; +} + + +template +bool +removeScalingAndShear (Matrix44 &mat, bool exc) +{ + Vec3 scl; + Vec3 shr; + + if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc)) + return false; + + return true; +} + + +template +bool +extractAndRemoveScalingAndShear (Matrix44 &mat, + Vec3 &scl, Vec3 &shr, bool exc) +{ + // + // This implementation follows the technique described in the paper by + // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a + // Matrix into Simple Transformations", p. 320. + // + + Vec3 row[3]; + + row[0] = Vec3 (mat[0][0], mat[0][1], mat[0][2]); + row[1] = Vec3 (mat[1][0], mat[1][1], mat[1][2]); + row[2] = Vec3 (mat[2][0], mat[2][1], mat[2][2]); + + T maxVal = 0; + for (int i=0; i < 3; i++) + for (int j=0; j < 3; j++) + if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal) + maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]); + + // + // We normalize the 3x3 matrix here. + // It was noticed that this can improve numerical stability significantly, + // especially when many of the upper 3x3 matrix's coefficients are very + // close to zero; we correct for this step at the end by multiplying the + // scaling factors by maxVal at the end (shear and rotation are not + // affected by the normalization). + + if (maxVal != 0) + { + for (int i=0; i < 3; i++) + if (! checkForZeroScaleInRow (maxVal, row[i], exc)) + return false; + else + row[i] /= maxVal; + } + + // Compute X scale factor. + scl.x = row[0].length (); + if (! checkForZeroScaleInRow (scl.x, row[0], exc)) + return false; + + // Normalize first row. + row[0] /= scl.x; + + // An XY shear factor will shear the X coord. as the Y coord. changes. + // There are 6 combinations (XY, XZ, YZ, YX, ZX, ZY), although we only + // extract the first 3 because we can effect the last 3 by shearing in + // XY, XZ, YZ combined rotations and scales. + // + // shear matrix < 1, YX, ZX, 0, + // XY, 1, ZY, 0, + // XZ, YZ, 1, 0, + // 0, 0, 0, 1 > + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + shr[0] = row[0].dot (row[1]); + row[1] -= shr[0] * row[0]; + + // Now, compute Y scale. + scl.y = row[1].length (); + if (! checkForZeroScaleInRow (scl.y, row[1], exc)) + return false; + + // Normalize 2nd row and correct the XY shear factor for Y scaling. + row[1] /= scl.y; + shr[0] /= scl.y; + + // Compute XZ and YZ shears, orthogonalize 3rd row. + shr[1] = row[0].dot (row[2]); + row[2] -= shr[1] * row[0]; + shr[2] = row[1].dot (row[2]); + row[2] -= shr[2] * row[1]; + + // Next, get Z scale. + scl.z = row[2].length (); + if (! checkForZeroScaleInRow (scl.z, row[2], exc)) + return false; + + // Normalize 3rd row and correct the XZ and YZ shear factors for Z scaling. + row[2] /= scl.z; + shr[1] /= scl.z; + shr[2] /= scl.z; + + // At this point, the upper 3x3 matrix in mat is orthonormal. + // Check for a coordinate system flip. If the determinant + // is less than zero, then negate the matrix and the scaling factors. + if (row[0].dot (row[1].cross (row[2])) < 0) + for (int i=0; i < 3; i++) + { + scl[i] *= -1; + row[i] *= -1; + } + + // Copy over the orthonormal rows into the returned matrix. + // The upper 3x3 matrix in mat is now a rotation matrix. + for (int i=0; i < 3; i++) + { + mat[i][0] = row[i][0]; + mat[i][1] = row[i][1]; + mat[i][2] = row[i][2]; + } + + // Correct the scaling factors for the normalization step that we + // performed above; shear and rotation are not affected by the + // normalization. + scl *= maxVal; + + return true; +} + + +template +void +extractEulerXYZ (const Matrix44 &mat, Vec3 &rot) +{ + // + // Normalize the local x, y and z axes to remove scaling. + // + + Vec3 i (mat[0][0], mat[0][1], mat[0][2]); + Vec3 j (mat[1][0], mat[1][1], mat[1][2]); + Vec3 k (mat[2][0], mat[2][1], mat[2][2]); + + i.normalize(); + j.normalize(); + k.normalize(); + + Matrix44 M (i[0], i[1], i[2], 0, + j[0], j[1], j[2], 0, + k[0], k[1], k[2], 0, + 0, 0, 0, 1); + + // + // Extract the first angle, rot.x. + // + + rot.x = Math::atan2 (M[1][2], M[2][2]); + + // + // Remove the rot.x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Matrix44 N; + N.rotate (Vec3 (-rot.x, 0, 0)); + N = N * M; + + // + // Extract the other two angles, rot.y and rot.z, from N. + // + + T cy = Math::sqrt (N[0][0]*N[0][0] + N[0][1]*N[0][1]); + rot.y = Math::atan2 (-N[0][2], cy); + rot.z = Math::atan2 (-N[1][0], N[1][1]); +} + + +template +void +extractEulerZYX (const Matrix44 &mat, Vec3 &rot) +{ + // + // Normalize the local x, y and z axes to remove scaling. + // + + Vec3 i (mat[0][0], mat[0][1], mat[0][2]); + Vec3 j (mat[1][0], mat[1][1], mat[1][2]); + Vec3 k (mat[2][0], mat[2][1], mat[2][2]); + + i.normalize(); + j.normalize(); + k.normalize(); + + Matrix44 M (i[0], i[1], i[2], 0, + j[0], j[1], j[2], 0, + k[0], k[1], k[2], 0, + 0, 0, 0, 1); + + // + // Extract the first angle, rot.x. + // + + rot.x = -Math::atan2 (M[1][0], M[0][0]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Matrix44 N; + N.rotate (Vec3 (0, 0, -rot.x)); + N = N * M; + + // + // Extract the other two angles, rot.y and rot.z, from N. + // + + T cy = Math::sqrt (N[2][2]*N[2][2] + N[2][1]*N[2][1]); + rot.y = -Math::atan2 (-N[2][0], cy); + rot.z = -Math::atan2 (-N[1][2], N[1][1]); +} + + +template +Quat +extractQuat (const Matrix44 &mat) +{ + Matrix44 rot; + + T tr, s; + T q[4]; + int i, j, k; + Quat quat; + + int nxt[3] = {1, 2, 0}; + tr = mat[0][0] + mat[1][1] + mat[2][2]; + + // check the diagonal + if (tr > 0.0) { + s = Math::sqrt (tr + T(1.0)); + quat.r = s / T(2.0); + s = T(0.5) / s; + + quat.v.x = (mat[1][2] - mat[2][1]) * s; + quat.v.y = (mat[2][0] - mat[0][2]) * s; + quat.v.z = (mat[0][1] - mat[1][0]) * s; + } + else { + // diagonal is negative + i = 0; + if (mat[1][1] > mat[0][0]) + i=1; + if (mat[2][2] > mat[i][i]) + i=2; + + j = nxt[i]; + k = nxt[j]; + s = Math::sqrt ((mat[i][i] - (mat[j][j] + mat[k][k])) + T(1.0)); + + q[i] = s * T(0.5); + if (s != T(0.0)) + s = T(0.5) / s; + + q[3] = (mat[j][k] - mat[k][j]) * s; + q[j] = (mat[i][j] + mat[j][i]) * s; + q[k] = (mat[i][k] + mat[k][i]) * s; + + quat.v.x = q[0]; + quat.v.y = q[1]; + quat.v.z = q[2]; + quat.r = q[3]; + } + + return quat; +} + +template +bool +extractSHRT (const Matrix44 &mat, + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc /* = true */ , + typename Euler::Order rOrder /* = Euler::XYZ */ ) +{ + Matrix44 rot; + + rot = mat; + if (! extractAndRemoveScalingAndShear (rot, s, h, exc)) + return false; + + extractEulerXYZ (rot, r); + + t.x = mat[3][0]; + t.y = mat[3][1]; + t.z = mat[3][2]; + + if (rOrder != Euler::XYZ) + { + IMATH_INTERNAL_NAMESPACE::Euler eXYZ (r, IMATH_INTERNAL_NAMESPACE::Euler::XYZ); + IMATH_INTERNAL_NAMESPACE::Euler e (eXYZ, rOrder); + r = e.toXYZVector (); + } + + return true; +} + +template +bool +extractSHRT (const Matrix44 &mat, + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc) +{ + return extractSHRT(mat, s, h, r, t, exc, IMATH_INTERNAL_NAMESPACE::Euler::XYZ); +} + +template +bool +extractSHRT (const Matrix44 &mat, + Vec3 &s, + Vec3 &h, + Euler &r, + Vec3 &t, + bool exc /* = true */) +{ + return extractSHRT (mat, s, h, r, t, exc, r.order ()); +} + + +template +bool +checkForZeroScaleInRow (const T& scl, + const Vec3 &row, + bool exc /* = true */ ) +{ + for (int i = 0; i < 3; i++) + { + if ((abs (scl) < 1 && abs (row[i]) >= limits::max() * abs (scl))) + { + if (exc) + throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ("Cannot remove zero scaling " + "from matrix."); + else + return false; + } + } + + return true; +} + +template +Matrix44 +outerProduct (const Vec4 &a, const Vec4 &b ) +{ + return Matrix44 (a.x*b.x, a.x*b.y, a.x*b.z, a.x*b.w, + a.y*b.x, a.y*b.y, a.y*b.z, a.x*b.w, + a.z*b.x, a.z*b.y, a.z*b.z, a.x*b.w, + a.w*b.x, a.w*b.y, a.w*b.z, a.w*b.w); +} + +template +Matrix44 +rotationMatrix (const Vec3 &from, const Vec3 &to) +{ + Quat q; + q.setRotation(from, to); + return q.toMatrix44(); +} + + +template +Matrix44 +rotationMatrixWithUpDir (const Vec3 &fromDir, + const Vec3 &toDir, + const Vec3 &upDir) +{ + // + // The goal is to obtain a rotation matrix that takes + // "fromDir" to "toDir". We do this in two steps and + // compose the resulting rotation matrices; + // (a) rotate "fromDir" into the z-axis + // (b) rotate the z-axis into "toDir" + // + + // The from direction must be non-zero; but we allow zero to and up dirs. + if (fromDir.length () == 0) + return Matrix44 (); + + else + { + Matrix44 zAxis2FromDir( IMATH_INTERNAL_NAMESPACE::UNINITIALIZED ); + alignZAxisWithTargetDir (zAxis2FromDir, fromDir, Vec3 (0, 1, 0)); + + Matrix44 fromDir2zAxis = zAxis2FromDir.transposed (); + + Matrix44 zAxis2ToDir( IMATH_INTERNAL_NAMESPACE::UNINITIALIZED ); + alignZAxisWithTargetDir (zAxis2ToDir, toDir, upDir); + + return fromDir2zAxis * zAxis2ToDir; + } +} + + +template +void +alignZAxisWithTargetDir (Matrix44 &result, Vec3 targetDir, Vec3 upDir) +{ + // + // Ensure that the target direction is non-zero. + // + + if ( targetDir.length () == 0 ) + targetDir = Vec3 (0, 0, 1); + + // + // Ensure that the up direction is non-zero. + // + + if ( upDir.length () == 0 ) + upDir = Vec3 (0, 1, 0); + + // + // Check for degeneracies. If the upDir and targetDir are parallel + // or opposite, then compute a new, arbitrary up direction that is + // not parallel or opposite to the targetDir. + // + + if (upDir.cross (targetDir).length () == 0) + { + upDir = targetDir.cross (Vec3 (1, 0, 0)); + if (upDir.length() == 0) + upDir = targetDir.cross(Vec3 (0, 0, 1)); + } + + // + // Compute the x-, y-, and z-axis vectors of the new coordinate system. + // + + Vec3 targetPerpDir = upDir.cross (targetDir); + Vec3 targetUpDir = targetDir.cross (targetPerpDir); + + // + // Rotate the x-axis into targetPerpDir (row 0), + // rotate the y-axis into targetUpDir (row 1), + // rotate the z-axis into targetDir (row 2). + // + + Vec3 row[3]; + row[0] = targetPerpDir.normalized (); + row[1] = targetUpDir .normalized (); + row[2] = targetDir .normalized (); + + result.x[0][0] = row[0][0]; + result.x[0][1] = row[0][1]; + result.x[0][2] = row[0][2]; + result.x[0][3] = (T)0; + + result.x[1][0] = row[1][0]; + result.x[1][1] = row[1][1]; + result.x[1][2] = row[1][2]; + result.x[1][3] = (T)0; + + result.x[2][0] = row[2][0]; + result.x[2][1] = row[2][1]; + result.x[2][2] = row[2][2]; + result.x[2][3] = (T)0; + + result.x[3][0] = (T)0; + result.x[3][1] = (T)0; + result.x[3][2] = (T)0; + result.x[3][3] = (T)1; +} + + +// Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis +// If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis. +// Inputs are : +// -the position of the frame +// -the x axis direction of the frame +// -a normal to the y axis of the frame +// Return is the orthonormal frame +template +Matrix44 +computeLocalFrame( const Vec3& p, + const Vec3& xDir, + const Vec3& normal) +{ + Vec3 _xDir(xDir); + Vec3 x = _xDir.normalize(); + Vec3 y = (normal % x).normalize(); + Vec3 z = (x % y).normalize(); + + Matrix44 L; + L[0][0] = x[0]; + L[0][1] = x[1]; + L[0][2] = x[2]; + L[0][3] = 0.0; + + L[1][0] = y[0]; + L[1][1] = y[1]; + L[1][2] = y[2]; + L[1][3] = 0.0; + + L[2][0] = z[0]; + L[2][1] = z[1]; + L[2][2] = z[2]; + L[2][3] = 0.0; + + L[3][0] = p[0]; + L[3][1] = p[1]; + L[3][2] = p[2]; + L[3][3] = 1.0; + + return L; +} + +// Add a translate/rotate/scale offset to an input frame +// and put it in another frame of reference +// Inputs are : +// - input frame +// - translate offset +// - rotate offset in degrees +// - scale offset +// - frame of reference +// Output is the offsetted frame +template +Matrix44 +addOffset( const Matrix44& inMat, + const Vec3& tOffset, + const Vec3& rOffset, + const Vec3& sOffset, + const Matrix44& ref) +{ + Matrix44 O; + + Vec3 _rOffset(rOffset); + _rOffset *= M_PI / 180.0; + O.rotate (_rOffset); + + O[3][0] = tOffset[0]; + O[3][1] = tOffset[1]; + O[3][2] = tOffset[2]; + + Matrix44 S; + S.scale (sOffset); + + Matrix44 X = S * O * inMat * ref; + + return X; +} + +// Compute Translate/Rotate/Scale matrix from matrix A with the Rotate/Scale of Matrix B +// Inputs are : +// -keepRotateA : if true keep rotate from matrix A, use B otherwise +// -keepScaleA : if true keep scale from matrix A, use B otherwise +// -Matrix A +// -Matrix B +// Return Matrix A with tweaked rotation/scale +template +Matrix44 +computeRSMatrix( bool keepRotateA, + bool keepScaleA, + const Matrix44& A, + const Matrix44& B) +{ + Vec3 as, ah, ar, at; + extractSHRT (A, as, ah, ar, at); + + Vec3 bs, bh, br, bt; + extractSHRT (B, bs, bh, br, bt); + + if (!keepRotateA) + ar = br; + + if (!keepScaleA) + as = bs; + + Matrix44 mat; + mat.makeIdentity(); + mat.translate (at); + mat.rotate (ar); + mat.scale (as); + + return mat; +} + + + +//----------------------------------------------------------------------------- +// Implementation for 3x3 Matrix +//------------------------------ + + +template +bool +extractScaling (const Matrix33 &mat, Vec2 &scl, bool exc) +{ + T shr; + Matrix33 M (mat); + + if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) + return false; + + return true; +} + + +template +Matrix33 +sansScaling (const Matrix33 &mat, bool exc) +{ + Vec2 scl; + T shr; + T rot; + Vec2 tran; + + if (! extractSHRT (mat, scl, shr, rot, tran, exc)) + return mat; + + Matrix33 M; + + M.translate (tran); + M.rotate (rot); + M.shear (shr); + + return M; +} + + +template +bool +removeScaling (Matrix33 &mat, bool exc) +{ + Vec2 scl; + T shr; + T rot; + Vec2 tran; + + if (! extractSHRT (mat, scl, shr, rot, tran, exc)) + return false; + + mat.makeIdentity (); + mat.translate (tran); + mat.rotate (rot); + mat.shear (shr); + + return true; +} + + +template +bool +extractScalingAndShear (const Matrix33 &mat, Vec2 &scl, T &shr, bool exc) +{ + Matrix33 M (mat); + + if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) + return false; + + return true; +} + + +template +Matrix33 +sansScalingAndShear (const Matrix33 &mat, bool exc) +{ + Vec2 scl; + T shr; + Matrix33 M (mat); + + if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) + return mat; + + return M; +} + + +template +bool +removeScalingAndShear (Matrix33 &mat, bool exc) +{ + Vec2 scl; + T shr; + + if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc)) + return false; + + return true; +} + +template +bool +extractAndRemoveScalingAndShear (Matrix33 &mat, + Vec2 &scl, T &shr, bool exc) +{ + Vec2 row[2]; + + row[0] = Vec2 (mat[0][0], mat[0][1]); + row[1] = Vec2 (mat[1][0], mat[1][1]); + + T maxVal = 0; + for (int i=0; i < 2; i++) + for (int j=0; j < 2; j++) + if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal) + maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]); + + // + // We normalize the 2x2 matrix here. + // It was noticed that this can improve numerical stability significantly, + // especially when many of the upper 2x2 matrix's coefficients are very + // close to zero; we correct for this step at the end by multiplying the + // scaling factors by maxVal at the end (shear and rotation are not + // affected by the normalization). + + if (maxVal != 0) + { + for (int i=0; i < 2; i++) + if (! checkForZeroScaleInRow (maxVal, row[i], exc)) + return false; + else + row[i] /= maxVal; + } + + // Compute X scale factor. + scl.x = row[0].length (); + if (! checkForZeroScaleInRow (scl.x, row[0], exc)) + return false; + + // Normalize first row. + row[0] /= scl.x; + + // An XY shear factor will shear the X coord. as the Y coord. changes. + // There are 2 combinations (XY, YX), although we only extract the XY + // shear factor because we can effect the an YX shear factor by + // shearing in XY combined with rotations and scales. + // + // shear matrix < 1, YX, 0, + // XY, 1, 0, + // 0, 0, 1 > + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + shr = row[0].dot (row[1]); + row[1] -= shr * row[0]; + + // Now, compute Y scale. + scl.y = row[1].length (); + if (! checkForZeroScaleInRow (scl.y, row[1], exc)) + return false; + + // Normalize 2nd row and correct the XY shear factor for Y scaling. + row[1] /= scl.y; + shr /= scl.y; + + // At this point, the upper 2x2 matrix in mat is orthonormal. + // Check for a coordinate system flip. If the determinant + // is -1, then flip the rotation matrix and adjust the scale(Y) + // and shear(XY) factors to compensate. + if (row[0][0] * row[1][1] - row[0][1] * row[1][0] < 0) + { + row[1][0] *= -1; + row[1][1] *= -1; + scl[1] *= -1; + shr *= -1; + } + + // Copy over the orthonormal rows into the returned matrix. + // The upper 2x2 matrix in mat is now a rotation matrix. + for (int i=0; i < 2; i++) + { + mat[i][0] = row[i][0]; + mat[i][1] = row[i][1]; + } + + scl *= maxVal; + + return true; +} + + +template +void +extractEuler (const Matrix33 &mat, T &rot) +{ + // + // Normalize the local x and y axes to remove scaling. + // + + Vec2 i (mat[0][0], mat[0][1]); + Vec2 j (mat[1][0], mat[1][1]); + + i.normalize(); + j.normalize(); + + // + // Extract the angle, rot. + // + + rot = - Math::atan2 (j[0], i[0]); +} + + +template +bool +extractSHRT (const Matrix33 &mat, + Vec2 &s, + T &h, + T &r, + Vec2 &t, + bool exc) +{ + Matrix33 rot; + + rot = mat; + if (! extractAndRemoveScalingAndShear (rot, s, h, exc)) + return false; + + extractEuler (rot, r); + + t.x = mat[2][0]; + t.y = mat[2][1]; + + return true; +} + + +template +bool +checkForZeroScaleInRow (const T& scl, + const Vec2 &row, + bool exc /* = true */ ) +{ + for (int i = 0; i < 2; i++) + { + if ((abs (scl) < 1 && abs (row[i]) >= limits::max() * abs (scl))) + { + if (exc) + throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ( + "Cannot remove zero scaling from matrix."); + else + return false; + } + } + + return true; +} + + +template +Matrix33 +outerProduct (const Vec3 &a, const Vec3 &b ) +{ + return Matrix33 (a.x*b.x, a.x*b.y, a.x*b.z, + a.y*b.x, a.y*b.y, a.y*b.z, + a.z*b.x, a.z*b.y, a.z*b.z ); +} + + +// Computes the translation and rotation that brings the 'from' points +// as close as possible to the 'to' points under the Frobenius norm. +// To be more specific, let x be the matrix of 'from' points and y be +// the matrix of 'to' points, we want to find the matrix A of the form +// [ R t ] +// [ 0 1 ] +// that minimizes +// || (A*x - y)^T * W * (A*x - y) ||_F +// If doScaling is true, then a uniform scale is allowed also. +template +IMATH_INTERNAL_NAMESPACE::M44d +procrustesRotationAndTranslation (const IMATH_INTERNAL_NAMESPACE::Vec3* A, // From these + const IMATH_INTERNAL_NAMESPACE::Vec3* B, // To these + const T* weights, + const size_t numPoints, + const bool doScaling = false); + +// Unweighted: +template +IMATH_INTERNAL_NAMESPACE::M44d +procrustesRotationAndTranslation (const IMATH_INTERNAL_NAMESPACE::Vec3* A, + const IMATH_INTERNAL_NAMESPACE::Vec3* B, + const size_t numPoints, + const bool doScaling = false); + +// Compute the SVD of a 3x3 matrix using Jacobi transformations. This method +// should be quite accurate (competitive with LAPACK) even for poorly +// conditioned matrices, and because it has been written specifically for the +// 3x3/4x4 case it is much faster than calling out to LAPACK. +// +// The SVD of a 3x3/4x4 matrix A is defined as follows: +// A = U * S * V^T +// where S is the diagonal matrix of singular values and both U and V are +// orthonormal. By convention, the entries S are all positive and sorted from +// the largest to the smallest. However, some uses of this function may +// require that the matrix U*V^T have positive determinant; in this case, we +// may make the smallest singular value negative to ensure that this is +// satisfied. +// +// Currently only available for single- and double-precision matrices. +template +void +jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix33& A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Vec3& S, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, + const T tol = IMATH_INTERNAL_NAMESPACE::limits::epsilon(), + const bool forcePositiveDeterminant = false); + +template +void +jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix44& A, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Vec4& S, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, + const T tol = IMATH_INTERNAL_NAMESPACE::limits::epsilon(), + const bool forcePositiveDeterminant = false); + +// Compute the eigenvalues (S) and the eigenvectors (V) of +// a real symmetric matrix using Jacobi transformation. +// +// Jacobi transformation of a 3x3/4x4 matrix A outputs S and V: +// A = V * S * V^T +// where V is orthonormal and S is the diagonal matrix of eigenvalues. +// Input matrix A must be symmetric. A is also modified during +// the computation so that upper diagonal entries of A become zero. +// +template +void +jacobiEigenSolver (Matrix33& A, + Vec3& S, + Matrix33& V, + const T tol); + +template +inline +void +jacobiEigenSolver (Matrix33& A, + Vec3& S, + Matrix33& V) +{ + jacobiEigenSolver(A,S,V,limits::epsilon()); +} + +template +void +jacobiEigenSolver (Matrix44& A, + Vec4& S, + Matrix44& V, + const T tol); + +template +inline +void +jacobiEigenSolver (Matrix44& A, + Vec4& S, + Matrix44& V) +{ + jacobiEigenSolver(A,S,V,limits::epsilon()); +} + +// Compute a eigenvector corresponding to the abs max/min eigenvalue +// of a real symmetric matrix using Jacobi transformation. +template +void +maxEigenVector (TM& A, TV& S); +template +void +minEigenVector (TM& A, TV& S); + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHMATRIXALGO_H diff --git a/OpenEXR/include/OpenEXR/ImathNamespace.h b/OpenEXR/include/OpenEXR/ImathNamespace.h new file mode 100644 index 0000000..c1fb993 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathNamespace.h @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHNAMESPACE_H +#define INCLUDED_IMATHNAMESPACE_H + +// +// The purpose of this file is to make it possible to specify an +// IMATH_INTERNAL_NAMESPACE as a preprocessor definition and have all of the +// Imath symbols defined within that namespace rather than the standard +// Imath namespace. Those symbols are made available to client code through +// the IMATH_NAMESPACE in addition to the IMATH_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the IMATH_NAMESPACE defaults to Imath +// and then "using namespace IMATH_INTERNAL_NAMESPACE;" brings all of the +// declarations from the IMATH_INTERNAL_NAMESPACE into the IMATH_NAMESPACE. +// This means that client code can continue to use syntax like Imath::V3f, +// but at link time it will resolve to a mangled symbol based on the +// IMATH_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of Imath and +// have it run alongside an older version in the same application, it is now +// possible to use an internal namespace to prevent collisions between the +// older versions of Imath symbols and the newer ones. To do this, the +// following could be defined at build time: +// +// IMATH_INTERNAL_NAMESPACE = Imath_v2 +// +// This means that declarations inside Imath headers look like this (after +// the preprocessor has done its work): +// +// namespace Imath_v2 { +// ... +// class declarations +// ... +// } +// +// namespace Imath { +// using namespace Imath_v2; +// } +// + +// +// Open Source version of this file pulls in the IlmBaseConfig.h file +// for the configure time options. +// +#include "IlmBaseConfig.h" + + +#ifndef IMATH_NAMESPACE +#define IMATH_NAMESPACE Imath +#endif + +#ifndef IMATH_INTERNAL_NAMESPACE +#define IMATH_INTERNAL_NAMESPACE IMATH_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// IMATH_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// IMATH_NAMESPACE and pulls the internal symbols into the public +// namespace. +// + +namespace IMATH_INTERNAL_NAMESPACE {} +namespace IMATH_NAMESPACE { + using namespace IMATH_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define IMATH_INTERNAL_NAMESPACE_HEADER_ENTER namespace IMATH_INTERNAL_NAMESPACE { +#define IMATH_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER namespace IMATH_INTERNAL_NAMESPACE { +#define IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT } + + +#endif /* INCLUDED_IMATHNAMESPACE_H */ diff --git a/OpenEXR/include/OpenEXR/ImathPlane.h b/OpenEXR/include/OpenEXR/ImathPlane.h new file mode 100644 index 0000000..7272d67 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathPlane.h @@ -0,0 +1,257 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHPLANE_H +#define INCLUDED_IMATHPLANE_H + +//---------------------------------------------------------------------- +// +// template class Plane3 +// +// The Imath::Plane3<> class represents a half space, so the +// normal may point either towards or away from origin. The +// plane P can be represented by Imath::Plane3 as either p or -p +// corresponding to the two half-spaces on either side of the +// plane. Any function which computes a distance will return +// either negative or positive values for the distance indicating +// which half-space the point is in. Note that reflection, and +// intersection functions will operate as expected. +// +//---------------------------------------------------------------------- + +#include "ImathVec.h" +#include "ImathLine.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +template +class Plane3 +{ + public: + + Vec3 normal; + T distance; + + Plane3() {} + Plane3(const Vec3 &normal, T distance); + Plane3(const Vec3 &point, const Vec3 &normal); + Plane3(const Vec3 &point1, + const Vec3 &point2, + const Vec3 &point3); + + //---------------------- + // Various set methods + //---------------------- + + void set(const Vec3 &normal, + T distance); + + void set(const Vec3 &point, + const Vec3 &normal); + + void set(const Vec3 &point1, + const Vec3 &point2, + const Vec3 &point3 ); + + //---------------------- + // Utilities + //---------------------- + + bool intersect(const Line3 &line, + Vec3 &intersection) const; + + bool intersectT(const Line3 &line, + T ¶meter) const; + + T distanceTo(const Vec3 &) const; + + Vec3 reflectPoint(const Vec3 &) const; + Vec3 reflectVector(const Vec3 &) const; +}; + + +//-------------------- +// Convenient typedefs +//-------------------- + +typedef Plane3 Plane3f; +typedef Plane3 Plane3d; + + +//--------------- +// Implementation +//--------------- + +template +inline Plane3::Plane3(const Vec3 &p0, + const Vec3 &p1, + const Vec3 &p2) +{ + set(p0,p1,p2); +} + +template +inline Plane3::Plane3(const Vec3 &n, T d) +{ + set(n, d); +} + +template +inline Plane3::Plane3(const Vec3 &p, const Vec3 &n) +{ + set(p, n); +} + +template +inline void Plane3::set(const Vec3& point1, + const Vec3& point2, + const Vec3& point3) +{ + normal = (point2 - point1) % (point3 - point1); + normal.normalize(); + distance = normal ^ point1; +} + +template +inline void Plane3::set(const Vec3& point, const Vec3& n) +{ + normal = n; + normal.normalize(); + distance = normal ^ point; +} + +template +inline void Plane3::set(const Vec3& n, T d) +{ + normal = n; + normal.normalize(); + distance = d; +} + +template +inline T Plane3::distanceTo(const Vec3 &point) const +{ + return (point ^ normal) - distance; +} + +template +inline Vec3 Plane3::reflectPoint(const Vec3 &point) const +{ + return normal * distanceTo(point) * -2.0 + point; +} + + +template +inline Vec3 Plane3::reflectVector(const Vec3 &v) const +{ + return normal * (normal ^ v) * 2.0 - v; +} + + +template +inline bool Plane3::intersect(const Line3& line, Vec3& point) const +{ + T d = normal ^ line.dir; + if ( d == 0.0 ) return false; + T t = - ((normal ^ line.pos) - distance) / d; + point = line(t); + return true; +} + +template +inline bool Plane3::intersectT(const Line3& line, T &t) const +{ + T d = normal ^ line.dir; + if ( d == 0.0 ) return false; + t = - ((normal ^ line.pos) - distance) / d; + return true; +} + +template +std::ostream &operator<< (std::ostream &o, const Plane3 &plane) +{ + return o << "(" << plane.normal << ", " << plane.distance + << ")"; +} + +template +Plane3 operator* (const Plane3 &plane, const Matrix44 &M) +{ + // T + // -1 + // Could also compute M but that would suck. + // + + Vec3 dir1 = Vec3 (1, 0, 0) % plane.normal; + T dir1Len = dir1 ^ dir1; + + Vec3 tmp = Vec3 (0, 1, 0) % plane.normal; + T tmpLen = tmp ^ tmp; + + if (tmpLen > dir1Len) + { + dir1 = tmp; + dir1Len = tmpLen; + } + + tmp = Vec3 (0, 0, 1) % plane.normal; + tmpLen = tmp ^ tmp; + + if (tmpLen > dir1Len) + { + dir1 = tmp; + } + + Vec3 dir2 = dir1 % plane.normal; + Vec3 point = plane.distance * plane.normal; + + return Plane3 ( point * M, + (point + dir2) * M, + (point + dir1) * M ); +} + +template +Plane3 operator- (const Plane3 &plane) +{ + return Plane3(-plane.normal,-plane.distance); +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHPLANE_H diff --git a/OpenEXR/include/OpenEXR/ImathPlatform.h b/OpenEXR/include/OpenEXR/ImathPlatform.h new file mode 100644 index 0000000..91e82cc --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathPlatform.h @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHPLATFORM_H +#define INCLUDED_IMATHPLATFORM_H + +//---------------------------------------------------------------------------- +// +// ImathPlatform.h +// +// This file contains functions and constants which aren't +// provided by the system libraries, compilers, or includes on +// certain platforms. +// +//---------------------------------------------------------------------------- + +#include + +#ifndef M_PI + #define M_PI 3.14159265358979323846 +#endif + +#ifndef M_PI_2 + #define M_PI_2 1.57079632679489661923 // pi/2 +#endif + + +//----------------------------------------------------------------------------- +// +// Some, but not all, C++ compilers support the C99 restrict +// keyword or some variant of it, for example, __restrict. +// +//----------------------------------------------------------------------------- + +#if defined __GNUC__ + + // + // supports __restrict + // + + #define IMATH_RESTRICT __restrict + +#elif defined (__INTEL_COMPILER) || \ + defined(__ICL) || \ + defined(__ICC) || \ + defined(__ECC) + + // + // supports restrict + // + + #define IMATH_RESTRICT restrict + +#elif defined __sgi + + // + // supports restrict + // + + #define IMATH_RESTRICT restrict + +#elif defined _MSC_VER + + // + // supports __restrict + // + +// #define IMATH_RESTRICT __restrict + #define IMATH_RESTRICT + +#else + + // + // restrict / __restrict not supported + // + + #define IMATH_RESTRICT + +#endif + +#endif // INCLUDED_IMATHPLATFORM_H diff --git a/OpenEXR/include/OpenEXR/ImathQuat.h b/OpenEXR/include/OpenEXR/ImathQuat.h new file mode 100644 index 0000000..e95e356 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathQuat.h @@ -0,0 +1,964 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHQUAT_H +#define INCLUDED_IMATHQUAT_H + +//---------------------------------------------------------------------- +// +// template class Quat +// +// "Quaternions came from Hamilton ... and have been an unmixed +// evil to those who have touched them in any way. Vector is a +// useless survival ... and has never been of the slightest use +// to any creature." +// +// - Lord Kelvin +// +// This class implements the quaternion numerical type -- you +// will probably want to use this class to represent orientations +// in R3 and to convert between various euler angle reps. You +// should probably use Imath::Euler<> for that. +// +//---------------------------------------------------------------------- + +#include "ImathExc.h" +#include "ImathMatrix.h" +#include "ImathNamespace.h" + +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +// Disable MS VC++ warnings about conversion from double to float +#pragma warning(disable:4244) +#endif + +template +class Quat +{ + public: + + T r; // real part + Vec3 v; // imaginary vector + + + //----------------------------------------------------- + // Constructors - default constructor is identity quat + //----------------------------------------------------- + + Quat (); + + template + Quat (const Quat &q); + + Quat (T s, T i, T j, T k); + + Quat (T s, Vec3 d); + + static Quat identity (); + + + //------------------------------------------------- + // Basic Algebra - Operators and Methods + // The operator return values are *NOT* normalized + // + // operator^ and euclideanInnnerProduct() both + // implement the 4D dot product + // + // operator/ uses the inverse() quaternion + // + // operator~ is conjugate -- if (S+V) is quat then + // the conjugate (S+V)* == (S-V) + // + // some operators (*,/,*=,/=) treat the quat as + // a 4D vector when one of the operands is scalar + //------------------------------------------------- + + const Quat & operator = (const Quat &q); + const Quat & operator *= (const Quat &q); + const Quat & operator *= (T t); + const Quat & operator /= (const Quat &q); + const Quat & operator /= (T t); + const Quat & operator += (const Quat &q); + const Quat & operator -= (const Quat &q); + T & operator [] (int index); // as 4D vector + T operator [] (int index) const; + + template bool operator == (const Quat &q) const; + template bool operator != (const Quat &q) const; + + Quat & invert (); // this -> 1 / this + Quat inverse () const; + Quat & normalize (); // returns this + Quat normalized () const; + T length () const; // in R4 + Vec3 rotateVector(const Vec3 &original) const; + T euclideanInnerProduct(const Quat &q) const; + + //----------------------- + // Rotation conversion + //----------------------- + + Quat & setAxisAngle (const Vec3 &axis, T radians); + + Quat & setRotation (const Vec3 &fromDirection, + const Vec3 &toDirection); + + T angle () const; + Vec3 axis () const; + + Matrix33 toMatrix33 () const; + Matrix44 toMatrix44 () const; + + Quat log () const; + Quat exp () const; + + + private: + + void setRotationInternal (const Vec3 &f0, + const Vec3 &t0, + Quat &q); +}; + + +template +Quat slerp (const Quat &q1, const Quat &q2, T t); + +template +Quat slerpShortestArc + (const Quat &q1, const Quat &q2, T t); + + +template +Quat squad (const Quat &q1, const Quat &q2, + const Quat &qa, const Quat &qb, T t); + +template +void intermediate (const Quat &q0, const Quat &q1, + const Quat &q2, const Quat &q3, + Quat &qa, Quat &qb); + +template +Matrix33 operator * (const Matrix33 &M, const Quat &q); + +template +Matrix33 operator * (const Quat &q, const Matrix33 &M); + +template +std::ostream & operator << (std::ostream &o, const Quat &q); + +template +Quat operator * (const Quat &q1, const Quat &q2); + +template +Quat operator / (const Quat &q1, const Quat &q2); + +template +Quat operator / (const Quat &q, T t); + +template +Quat operator * (const Quat &q, T t); + +template +Quat operator * (T t, const Quat &q); + +template +Quat operator + (const Quat &q1, const Quat &q2); + +template +Quat operator - (const Quat &q1, const Quat &q2); + +template +Quat operator ~ (const Quat &q); + +template +Quat operator - (const Quat &q); + +template +Vec3 operator * (const Vec3 &v, const Quat &q); + + +//-------------------- +// Convenient typedefs +//-------------------- + +typedef Quat Quatf; +typedef Quat Quatd; + + +//--------------- +// Implementation +//--------------- + +template +inline +Quat::Quat (): r (1), v (0, 0, 0) +{ + // empty +} + + +template +template +inline +Quat::Quat (const Quat &q): r (q.r), v (q.v) +{ + // empty +} + + +template +inline +Quat::Quat (T s, T i, T j, T k): r (s), v (i, j, k) +{ + // empty +} + + +template +inline +Quat::Quat (T s, Vec3 d): r (s), v (d) +{ + // empty +} + + +template +inline Quat +Quat::identity () +{ + return Quat(); +} + +template +inline const Quat & +Quat::operator = (const Quat &q) +{ + r = q.r; + v = q.v; + return *this; +} + + +template +inline const Quat & +Quat::operator *= (const Quat &q) +{ + T rtmp = r * q.r - (v ^ q.v); + v = r * q.v + v * q.r + v % q.v; + r = rtmp; + return *this; +} + + +template +inline const Quat & +Quat::operator *= (T t) +{ + r *= t; + v *= t; + return *this; +} + + +template +inline const Quat & +Quat::operator /= (const Quat &q) +{ + *this = *this * q.inverse(); + return *this; +} + + +template +inline const Quat & +Quat::operator /= (T t) +{ + r /= t; + v /= t; + return *this; +} + + +template +inline const Quat & +Quat::operator += (const Quat &q) +{ + r += q.r; + v += q.v; + return *this; +} + + +template +inline const Quat & +Quat::operator -= (const Quat &q) +{ + r -= q.r; + v -= q.v; + return *this; +} + + +template +inline T & +Quat::operator [] (int index) +{ + return index ? v[index - 1] : r; +} + + +template +inline T +Quat::operator [] (int index) const +{ + return index ? v[index - 1] : r; +} + + +template +template +inline bool +Quat::operator == (const Quat &q) const +{ + return r == q.r && v == q.v; +} + + +template +template +inline bool +Quat::operator != (const Quat &q) const +{ + return r != q.r || v != q.v; +} + + +template +inline T +operator ^ (const Quat& q1 ,const Quat& q2) +{ + return q1.r * q2.r + (q1.v ^ q2.v); +} + + +template +inline T +Quat::length () const +{ + return Math::sqrt (r * r + (v ^ v)); +} + + +template +inline Quat & +Quat::normalize () +{ + if (T l = length()) + { + r /= l; + v /= l; + } + else + { + r = 1; + v = Vec3 (0); + } + + return *this; +} + + +template +inline Quat +Quat::normalized () const +{ + if (T l = length()) + return Quat (r / l, v / l); + + return Quat(); +} + + +template +inline Quat +Quat::inverse () const +{ + // + // 1 Q* + // - = ---- where Q* is conjugate (operator~) + // Q Q* Q and (Q* Q) == Q ^ Q (4D dot) + // + + T qdot = *this ^ *this; + return Quat (r / qdot, -v / qdot); +} + + +template +inline Quat & +Quat::invert () +{ + T qdot = (*this) ^ (*this); + r /= qdot; + v = -v / qdot; + return *this; +} + + +template +inline Vec3 +Quat::rotateVector(const Vec3& original) const +{ + // + // Given a vector p and a quaternion q (aka this), + // calculate p' = qpq* + // + // Assumes unit quaternions (because non-unit + // quaternions cannot be used to rotate vectors + // anyway). + // + + Quat vec (0, original); // temporarily promote grade of original + Quat inv (*this); + inv.v *= -1; // unit multiplicative inverse + Quat result = *this * vec * inv; + return result.v; +} + + +template +inline T +Quat::euclideanInnerProduct (const Quat &q) const +{ + return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z; +} + + +template +T +angle4D (const Quat &q1, const Quat &q2) +{ + // + // Compute the angle between two quaternions, + // interpreting the quaternions as 4D vectors. + // + + Quat d = q1 - q2; + T lengthD = Math::sqrt (d ^ d); + + Quat s = q1 + q2; + T lengthS = Math::sqrt (s ^ s); + + return 2 * Math::atan2 (lengthD, lengthS); +} + + +template +Quat +slerp (const Quat &q1, const Quat &q2, T t) +{ + // + // Spherical linear interpolation. + // Assumes q1 and q2 are normalized and that q1 != -q2. + // + // This method does *not* interpolate along the shortest + // arc between q1 and q2. If you desire interpolation + // along the shortest arc, and q1^q2 is negative, then + // consider calling slerpShortestArc(), below, or flipping + // the second quaternion explicitly. + // + // The implementation of squad() depends on a slerp() + // that interpolates as is, without the automatic + // flipping. + // + // Don Hatch explains the method we use here on his + // web page, The Right Way to Calculate Stuff, at + // http://www.plunk.org/~hatch/rightway.php + // + + T a = angle4D (q1, q2); + T s = 1 - t; + + Quat q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 + + sinx_over_x (t * a) / sinx_over_x (a) * t * q2; + + return q.normalized(); +} + + +template +Quat +slerpShortestArc (const Quat &q1, const Quat &q2, T t) +{ + // + // Spherical linear interpolation along the shortest + // arc from q1 to either q2 or -q2, whichever is closer. + // Assumes q1 and q2 are unit quaternions. + // + + if ((q1 ^ q2) >= 0) + return slerp (q1, q2, t); + else + return slerp (q1, -q2, t); +} + + +template +Quat +spline (const Quat &q0, const Quat &q1, + const Quat &q2, const Quat &q3, + T t) +{ + // + // Spherical Cubic Spline Interpolation - + // from Advanced Animation and Rendering + // Techniques by Watt and Watt, Page 366: + // A spherical curve is constructed using three + // spherical linear interpolations of a quadrangle + // of unit quaternions: q1, qa, qb, q2. + // Given a set of quaternion keys: q0, q1, q2, q3, + // this routine does the interpolation between + // q1 and q2 by constructing two intermediate + // quaternions: qa and qb. The qa and qb are + // computed by the intermediate function to + // guarantee the continuity of tangents across + // adjacent cubic segments. The qa represents in-tangent + // for q1 and the qb represents the out-tangent for q2. + // + // The q1 q2 is the cubic segment being interpolated. + // The q0 is from the previous adjacent segment and q3 is + // from the next adjacent segment. The q0 and q3 are used + // in computing qa and qb. + // + + Quat qa = intermediate (q0, q1, q2); + Quat qb = intermediate (q1, q2, q3); + Quat result = squad (q1, qa, qb, q2, t); + + return result; +} + + +template +Quat +squad (const Quat &q1, const Quat &qa, + const Quat &qb, const Quat &q2, + T t) +{ + // + // Spherical Quadrangle Interpolation - + // from Advanced Animation and Rendering + // Techniques by Watt and Watt, Page 366: + // It constructs a spherical cubic interpolation as + // a series of three spherical linear interpolations + // of a quadrangle of unit quaternions. + // + + Quat r1 = slerp (q1, q2, t); + Quat r2 = slerp (qa, qb, t); + Quat result = slerp (r1, r2, 2 * t * (1 - t)); + + return result; +} + + +template +Quat +intermediate (const Quat &q0, const Quat &q1, const Quat &q2) +{ + // + // From advanced Animation and Rendering + // Techniques by Watt and Watt, Page 366: + // computing the inner quadrangle + // points (qa and qb) to guarantee tangent + // continuity. + // + + Quat q1inv = q1.inverse(); + Quat c1 = q1inv * q2; + Quat c2 = q1inv * q0; + Quat c3 = (T) (-0.25) * (c2.log() + c1.log()); + Quat qa = q1 * c3.exp(); + qa.normalize(); + return qa; +} + + +template +inline Quat +Quat::log () const +{ + // + // For unit quaternion, from Advanced Animation and + // Rendering Techniques by Watt and Watt, Page 366: + // + + T theta = Math::acos (std::min (r, (T) 1.0)); + + if (theta == 0) + return Quat (0, v); + + T sintheta = Math::sin (theta); + + T k; + if (abs (sintheta) < 1 && abs (theta) >= limits::max() * abs (sintheta)) + k = 1; + else + k = theta / sintheta; + + return Quat ((T) 0, v.x * k, v.y * k, v.z * k); +} + + +template +inline Quat +Quat::exp () const +{ + // + // For pure quaternion (zero scalar part): + // from Advanced Animation and Rendering + // Techniques by Watt and Watt, Page 366: + // + + T theta = v.length(); + T sintheta = Math::sin (theta); + + T k; + if (abs (theta) < 1 && abs (sintheta) >= limits::max() * abs (theta)) + k = 1; + else + k = sintheta / theta; + + T costheta = Math::cos (theta); + + return Quat (costheta, v.x * k, v.y * k, v.z * k); +} + + +template +inline T +Quat::angle () const +{ + return 2 * Math::atan2 (v.length(), r); +} + + +template +inline Vec3 +Quat::axis () const +{ + return v.normalized(); +} + + +template +inline Quat & +Quat::setAxisAngle (const Vec3 &axis, T radians) +{ + r = Math::cos (radians / 2); + v = axis.normalized() * Math::sin (radians / 2); + return *this; +} + + +template +Quat & +Quat::setRotation (const Vec3 &from, const Vec3 &to) +{ + // + // Create a quaternion that rotates vector from into vector to, + // such that the rotation is around an axis that is the cross + // product of from and to. + // + // This function calls function setRotationInternal(), which is + // numerically accurate only for rotation angles that are not much + // greater than pi/2. In order to achieve good accuracy for angles + // greater than pi/2, we split large angles in half, and rotate in + // two steps. + // + + // + // Normalize from and to, yielding f0 and t0. + // + + Vec3 f0 = from.normalized(); + Vec3 t0 = to.normalized(); + + if ((f0 ^ t0) >= 0) + { + // + // The rotation angle is less than or equal to pi/2. + // + + setRotationInternal (f0, t0, *this); + } + else + { + // + // The angle is greater than pi/2. After computing h0, + // which is halfway between f0 and t0, we rotate first + // from f0 to h0, then from h0 to t0. + // + + Vec3 h0 = (f0 + t0).normalized(); + + if ((h0 ^ h0) != 0) + { + setRotationInternal (f0, h0, *this); + + Quat q; + setRotationInternal (h0, t0, q); + + *this *= q; + } + else + { + // + // f0 and t0 point in exactly opposite directions. + // Pick an arbitrary axis that is orthogonal to f0, + // and rotate by pi. + // + + r = T (0); + + Vec3 f02 = f0 * f0; + + if (f02.x <= f02.y && f02.x <= f02.z) + v = (f0 % Vec3 (1, 0, 0)).normalized(); + else if (f02.y <= f02.z) + v = (f0 % Vec3 (0, 1, 0)).normalized(); + else + v = (f0 % Vec3 (0, 0, 1)).normalized(); + } + } + + return *this; +} + + +template +void +Quat::setRotationInternal (const Vec3 &f0, const Vec3 &t0, Quat &q) +{ + // + // The following is equivalent to setAxisAngle(n,2*phi), + // where the rotation axis, n, is orthogonal to the f0 and + // t0 vectors, and 2*phi is the angle between f0 and t0. + // + // This function is called by setRotation(), above; it assumes + // that f0 and t0 are normalized and that the angle between + // them is not much greater than pi/2. This function becomes + // numerically inaccurate if f0 and t0 point into nearly + // opposite directions. + // + + // + // Find a normalized vector, h0, that is halfway between f0 and t0. + // The angle between f0 and h0 is phi. + // + + Vec3 h0 = (f0 + t0).normalized(); + + // + // Store the rotation axis and rotation angle. + // + + q.r = f0 ^ h0; // f0 ^ h0 == cos (phi) + q.v = f0 % h0; // (f0 % h0).length() == sin (phi) +} + + +template +Matrix33 +Quat::toMatrix33() const +{ + return Matrix33 (1 - 2 * (v.y * v.y + v.z * v.z), + 2 * (v.x * v.y + v.z * r), + 2 * (v.z * v.x - v.y * r), + + 2 * (v.x * v.y - v.z * r), + 1 - 2 * (v.z * v.z + v.x * v.x), + 2 * (v.y * v.z + v.x * r), + + 2 * (v.z * v.x + v.y * r), + 2 * (v.y * v.z - v.x * r), + 1 - 2 * (v.y * v.y + v.x * v.x)); +} + +template +Matrix44 +Quat::toMatrix44() const +{ + return Matrix44 (1 - 2 * (v.y * v.y + v.z * v.z), + 2 * (v.x * v.y + v.z * r), + 2 * (v.z * v.x - v.y * r), + 0, + 2 * (v.x * v.y - v.z * r), + 1 - 2 * (v.z * v.z + v.x * v.x), + 2 * (v.y * v.z + v.x * r), + 0, + 2 * (v.z * v.x + v.y * r), + 2 * (v.y * v.z - v.x * r), + 1 - 2 * (v.y * v.y + v.x * v.x), + 0, + 0, + 0, + 0, + 1); +} + + +template +inline Matrix33 +operator * (const Matrix33 &M, const Quat &q) +{ + return M * q.toMatrix33(); +} + + +template +inline Matrix33 +operator * (const Quat &q, const Matrix33 &M) +{ + return q.toMatrix33() * M; +} + + +template +std::ostream & +operator << (std::ostream &o, const Quat &q) +{ + return o << "(" << q.r + << " " << q.v.x + << " " << q.v.y + << " " << q.v.z + << ")"; +} + + +template +inline Quat +operator * (const Quat &q1, const Quat &q2) +{ + return Quat (q1.r * q2.r - (q1.v ^ q2.v), + q1.r * q2.v + q1.v * q2.r + q1.v % q2.v); +} + + +template +inline Quat +operator / (const Quat &q1, const Quat &q2) +{ + return q1 * q2.inverse(); +} + + +template +inline Quat +operator / (const Quat &q, T t) +{ + return Quat (q.r / t, q.v / t); +} + + +template +inline Quat +operator * (const Quat &q, T t) +{ + return Quat (q.r * t, q.v * t); +} + + +template +inline Quat +operator * (T t, const Quat &q) +{ + return Quat (q.r * t, q.v * t); +} + + +template +inline Quat +operator + (const Quat &q1, const Quat &q2) +{ + return Quat (q1.r + q2.r, q1.v + q2.v); +} + + +template +inline Quat +operator - (const Quat &q1, const Quat &q2) +{ + return Quat (q1.r - q2.r, q1.v - q2.v); +} + + +template +inline Quat +operator ~ (const Quat &q) +{ + return Quat (q.r, -q.v); +} + + +template +inline Quat +operator - (const Quat &q) +{ + return Quat (-q.r, -q.v); +} + + +template +inline Vec3 +operator * (const Vec3 &v, const Quat &q) +{ + Vec3 a = q.v % v; + Vec3 b = q.v % a; + return v + T (2) * (q.r * a + b); +} + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +#pragma warning(default:4244) +#endif + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHQUAT_H diff --git a/OpenEXR/include/OpenEXR/ImathRandom.h b/OpenEXR/include/OpenEXR/ImathRandom.h new file mode 100644 index 0000000..4f0db13 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathRandom.h @@ -0,0 +1,401 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHRANDOM_H +#define INCLUDED_IMATHRANDOM_H + +//----------------------------------------------------------------------------- +// +// Generators for uniformly distributed pseudo-random numbers and +// functions that use those generators to generate numbers with +// non-uniform distributions: +// +// class Rand32 +// class Rand48 +// solidSphereRand() +// hollowSphereRand() +// gaussRand() +// gaussSphereRand() +// +// Note: class Rand48() calls erand48() and nrand48(), which are not +// available on all operating systems. For compatibility we include +// our own versions of erand48() and nrand48(). Our functions have +// been reverse-engineered from the corresponding Unix/Linux man page. +// +//----------------------------------------------------------------------------- + +#include "ImathNamespace.h" +#include "ImathExport.h" + +#include +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +//----------------------------------------------- +// Fast random-number generator that generates +// a uniformly distributed sequence with a period +// length of 2^32. +//----------------------------------------------- + +class IMATH_EXPORT Rand32 +{ + public: + + //------------ + // Constructor + //------------ + + Rand32 (unsigned long int seed = 0); + + + //-------------------------------- + // Re-initialize with a given seed + //-------------------------------- + + void init (unsigned long int seed); + + + //---------------------------------------------------------- + // Get the next value in the sequence (range: [false, true]) + //---------------------------------------------------------- + + bool nextb (); + + + //--------------------------------------------------------------- + // Get the next value in the sequence (range: [0 ... 0xffffffff]) + //--------------------------------------------------------------- + + unsigned long int nexti (); + + + //------------------------------------------------------ + // Get the next value in the sequence (range: [0 ... 1[) + //------------------------------------------------------ + + float nextf (); + + + //------------------------------------------------------------------- + // Get the next value in the sequence (range [rangeMin ... rangeMax[) + //------------------------------------------------------------------- + + float nextf (float rangeMin, float rangeMax); + + + private: + + void next (); + + unsigned long int _state; +}; + + +//-------------------------------------------------------- +// Random-number generator based on the C Standard Library +// functions erand48(), nrand48() & company; generates a +// uniformly distributed sequence. +//-------------------------------------------------------- + +class Rand48 +{ + public: + + //------------ + // Constructor + //------------ + + Rand48 (unsigned long int seed = 0); + + + //-------------------------------- + // Re-initialize with a given seed + //-------------------------------- + + void init (unsigned long int seed); + + + //---------------------------------------------------------- + // Get the next value in the sequence (range: [false, true]) + //---------------------------------------------------------- + + bool nextb (); + + + //--------------------------------------------------------------- + // Get the next value in the sequence (range: [0 ... 0x7fffffff]) + //--------------------------------------------------------------- + + long int nexti (); + + + //------------------------------------------------------ + // Get the next value in the sequence (range: [0 ... 1[) + //------------------------------------------------------ + + double nextf (); + + + //------------------------------------------------------------------- + // Get the next value in the sequence (range [rangeMin ... rangeMax[) + //------------------------------------------------------------------- + + double nextf (double rangeMin, double rangeMax); + + + private: + + unsigned short int _state[3]; +}; + + +//------------------------------------------------------------ +// Return random points uniformly distributed in a sphere with +// radius 1 around the origin (distance from origin <= 1). +//------------------------------------------------------------ + +template +Vec +solidSphereRand (Rand &rand); + + +//------------------------------------------------------------- +// Return random points uniformly distributed on the surface of +// a sphere with radius 1 around the origin. +//------------------------------------------------------------- + +template +Vec +hollowSphereRand (Rand &rand); + + +//----------------------------------------------- +// Return random numbers with a normal (Gaussian) +// distribution with zero mean and unit variance. +//----------------------------------------------- + +template +float +gaussRand (Rand &rand); + + +//---------------------------------------------------- +// Return random points whose distance from the origin +// has a normal (Gaussian) distribution with zero mean +// and unit variance. +//---------------------------------------------------- + +template +Vec +gaussSphereRand (Rand &rand); + + +//--------------------------------- +// erand48(), nrand48() and friends +//--------------------------------- + +IMATH_EXPORT double erand48 (unsigned short state[3]); +IMATH_EXPORT double drand48 (); +IMATH_EXPORT long int nrand48 (unsigned short state[3]); +IMATH_EXPORT long int lrand48 (); +IMATH_EXPORT void srand48 (long int seed); + + +//--------------- +// Implementation +//--------------- + + +inline void +Rand32::init (unsigned long int seed) +{ + _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL; +} + + +inline +Rand32::Rand32 (unsigned long int seed) +{ + init (seed); +} + + +inline void +Rand32::next () +{ + _state = 1664525L * _state + 1013904223L; +} + + +inline bool +Rand32::nextb () +{ + next (); + // Return the 31st (most significant) bit, by and-ing with 2 ^ 31. + return !!(_state & 2147483648UL); +} + + +inline unsigned long int +Rand32::nexti () +{ + next (); + return _state & 0xffffffff; +} + + +inline float +Rand32::nextf (float rangeMin, float rangeMax) +{ + float f = nextf(); + return rangeMin * (1 - f) + rangeMax * f; +} + + +inline void +Rand48::init (unsigned long int seed) +{ + seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL; + + _state[0] = (unsigned short int) (seed & 0xFFFF); + _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF); + _state[2] = (unsigned short int) (seed & 0xFFFF); +} + + +inline +Rand48::Rand48 (unsigned long int seed) +{ + init (seed); +} + + +inline bool +Rand48::nextb () +{ + return nrand48 (_state) & 1; +} + + +inline long int +Rand48::nexti () +{ + return nrand48 (_state); +} + + +inline double +Rand48::nextf () +{ + return erand48 (_state); +} + + +inline double +Rand48::nextf (double rangeMin, double rangeMax) +{ + double f = nextf(); + return rangeMin * (1 - f) + rangeMax * f; +} + + +template +Vec +solidSphereRand (Rand &rand) +{ + Vec v; + + do + { + for (unsigned int i = 0; i < Vec::dimensions(); i++) + v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); + } + while (v.length2() > 1); + + return v; +} + + +template +Vec +hollowSphereRand (Rand &rand) +{ + Vec v; + typename Vec::BaseType length; + + do + { + for (unsigned int i = 0; i < Vec::dimensions(); i++) + v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); + + length = v.length(); + } + while (length > 1 || length == 0); + + return v / length; +} + + +template +float +gaussRand (Rand &rand) +{ + float x; // Note: to avoid numerical problems with very small + float y; // numbers, we make these variables singe-precision + float length2; // floats, but later we call the double-precision log() + // and sqrt() functions instead of logf() and sqrtf(). + do + { + x = float (rand.nextf (-1, 1)); + y = float (rand.nextf (-1, 1)); + length2 = x * x + y * y; + } + while (length2 >= 1 || length2 == 0); + + return x * sqrt (-2 * log (double (length2)) / length2); +} + + +template +Vec +gaussSphereRand (Rand &rand) +{ + return hollowSphereRand (rand) * gaussRand (rand); +} + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHRANDOM_H diff --git a/OpenEXR/include/OpenEXR/ImathRoots.h b/OpenEXR/include/OpenEXR/ImathRoots.h new file mode 100644 index 0000000..036b7f7 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathRoots.h @@ -0,0 +1,219 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHROOTS_H +#define INCLUDED_IMATHROOTS_H + +//--------------------------------------------------------------------- +// +// Functions to solve linear, quadratic or cubic equations +// +//--------------------------------------------------------------------- + +#include "ImathMath.h" +#include "ImathNamespace.h" +#include + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +//-------------------------------------------------------------------------- +// Find the real solutions of a linear, quadratic or cubic equation: +// +// function equation solved +// +// solveLinear (a, b, x) a * x + b == 0 +// solveQuadratic (a, b, c, x) a * x*x + b * x + c == 0 +// solveNormalizedCubic (r, s, t, x) x*x*x + r * x*x + s * x + t == 0 +// solveCubic (a, b, c, d, x) a * x*x*x + b * x*x + c * x + d == 0 +// +// Return value: +// +// 3 three real solutions, stored in x[0], x[1] and x[2] +// 2 two real solutions, stored in x[0] and x[1] +// 1 one real solution, stored in x[1] +// 0 no real solutions +// -1 all real numbers are solutions +// +// Notes: +// +// * It is possible that an equation has real solutions, but that the +// solutions (or some intermediate result) are not representable. +// In this case, either some of the solutions returned are invalid +// (nan or infinity), or, if floating-point exceptions have been +// enabled with Iex::mathExcOn(), an Iex::MathExc exception is +// thrown. +// +// * Cubic equations are solved using Cardano's Formula; even though +// only real solutions are produced, some intermediate results are +// complex (std::complex). +// +//-------------------------------------------------------------------------- + +template int solveLinear (T a, T b, T &x); +template int solveQuadratic (T a, T b, T c, T x[2]); +template int solveNormalizedCubic (T r, T s, T t, T x[3]); +template int solveCubic (T a, T b, T c, T d, T x[3]); + + +//--------------- +// Implementation +//--------------- + +template +int +solveLinear (T a, T b, T &x) +{ + if (a != 0) + { + x = -b / a; + return 1; + } + else if (b != 0) + { + return 0; + } + else + { + return -1; + } +} + + +template +int +solveQuadratic (T a, T b, T c, T x[2]) +{ + if (a == 0) + { + return solveLinear (b, c, x[0]); + } + else + { + T D = b * b - 4 * a * c; + + if (D > 0) + { + T s = Math::sqrt (D); + T q = -(b + (b > 0 ? 1 : -1) * s) / T(2); + + x[0] = q / a; + x[1] = c / q; + return 2; + } + if (D == 0) + { + x[0] = -b / (2 * a); + return 1; + } + else + { + return 0; + } + } +} + + +template +int +solveNormalizedCubic (T r, T s, T t, T x[3]) +{ + T p = (3 * s - r * r) / 3; + T q = 2 * r * r * r / 27 - r * s / 3 + t; + T p3 = p / 3; + T q2 = q / 2; + T D = p3 * p3 * p3 + q2 * q2; + + if (D == 0 && p3 == 0) + { + x[0] = -r / 3; + x[1] = -r / 3; + x[2] = -r / 3; + return 1; + } + + std::complex u = std::pow (-q / 2 + std::sqrt (std::complex (D)), + T (1) / T (3)); + + std::complex v = -p / (T (3) * u); + + const T sqrt3 = T (1.73205080756887729352744634150587); // enough digits + // for long double + std::complex y0 (u + v); + + std::complex y1 (-(u + v) / T (2) + + (u - v) / T (2) * std::complex (0, sqrt3)); + + std::complex y2 (-(u + v) / T (2) - + (u - v) / T (2) * std::complex (0, sqrt3)); + + if (D > 0) + { + x[0] = y0.real() - r / 3; + return 1; + } + else if (D == 0) + { + x[0] = y0.real() - r / 3; + x[1] = y1.real() - r / 3; + return 2; + } + else + { + x[0] = y0.real() - r / 3; + x[1] = y1.real() - r / 3; + x[2] = y2.real() - r / 3; + return 3; + } +} + + +template +int +solveCubic (T a, T b, T c, T d, T x[3]) +{ + if (a == 0) + { + return solveQuadratic (b, c, d, x); + } + else + { + return solveNormalizedCubic (b / a, c / a, d / a, x); + } +} + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHROOTS_H diff --git a/OpenEXR/include/OpenEXR/ImathShear.h b/OpenEXR/include/OpenEXR/ImathShear.h new file mode 100644 index 0000000..b6f7b9a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathShear.h @@ -0,0 +1,656 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHSHEAR_H +#define INCLUDED_IMATHSHEAR_H + +//---------------------------------------------------- +// +// Shear6 class template. +// +//---------------------------------------------------- + +#include "ImathExc.h" +#include "ImathLimits.h" +#include "ImathMath.h" +#include "ImathVec.h" +#include "ImathNamespace.h" +#include + + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +template class Shear6 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T xy, xz, yz, yx, zx, zy; + + T & operator [] (int i); + const T & operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Shear6 (); // (0 0 0 0 0 0) + Shear6 (T XY, T XZ, T YZ); // (XY XZ YZ 0 0 0) + Shear6 (const Vec3 &v); // (v.x v.y v.z 0 0 0) + template // (v.x v.y v.z 0 0 0) + Shear6 (const Vec3 &v); + Shear6 (T XY, T XZ, T YZ, // (XY XZ YZ YX ZX ZY) + T YX, T ZX, T ZY); + + + //--------------------------------- + // Copy constructors and assignment + //--------------------------------- + + Shear6 (const Shear6 &h); + template Shear6 (const Shear6 &h); + + const Shear6 & operator = (const Shear6 &h); + template + const Shear6 & operator = (const Vec3 &v); + + + //---------------------- + // Compatibility with Sb + //---------------------- + + template + void setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY); + + template + void setValue (const Shear6 &h); + + template + void getValue (S &XY, S &XZ, S &YZ, + S &YX, S &ZX, S &ZY) const; + + template + void getValue (Shear6 &h) const; + + T * getValue(); + const T * getValue() const; + + + //--------- + // Equality + //--------- + + template + bool operator == (const Shear6 &h) const; + + template + bool operator != (const Shear6 &h) const; + + //----------------------------------------------------------------------- + // Compare two shears and test if they are "approximately equal": + // + // equalWithAbsError (h, e) + // + // Returns true if the coefficients of this and h are the same with + // an absolute error of no more than e, i.e., for all i + // + // abs (this[i] - h[i]) <= e + // + // equalWithRelError (h, e) + // + // Returns true if the coefficients of this and h are the same with + // a relative error of no more than e, i.e., for all i + // + // abs (this[i] - h[i]) <= e * abs (this[i]) + //----------------------------------------------------------------------- + + bool equalWithAbsError (const Shear6 &h, T e) const; + bool equalWithRelError (const Shear6 &h, T e) const; + + + //------------------------ + // Component-wise addition + //------------------------ + + const Shear6 & operator += (const Shear6 &h); + Shear6 operator + (const Shear6 &h) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Shear6 & operator -= (const Shear6 &h); + Shear6 operator - (const Shear6 &h) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Shear6 operator - () const; + const Shear6 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Shear6 & operator *= (const Shear6 &h); + const Shear6 & operator *= (T a); + Shear6 operator * (const Shear6 &h) const; + Shear6 operator * (T a) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Shear6 & operator /= (const Shear6 &h); + const Shear6 & operator /= (T a); + Shear6 operator / (const Shear6 &h) const; + Shear6 operator / (T a) const; + + + //---------------------------------------------------------- + // Number of dimensions, i.e. number of elements in a Shear6 + //---------------------------------------------------------- + + static unsigned int dimensions() {return 6;} + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + + //-------------------------------------------------------------- + // Base type -- in templates, which accept a parameter, V, which + // could be either a Vec2 or a Shear6, you can refer to T as + // V::BaseType + //-------------------------------------------------------------- + + typedef T BaseType; +}; + + +//-------------- +// Stream output +//-------------- + +template +std::ostream & operator << (std::ostream &s, const Shear6 &h); + + +//---------------------------------------------------- +// Reverse multiplication: scalar * Shear6 +//---------------------------------------------------- + +template Shear6 operator * (S a, const Shear6 &h); + + +//------------------------- +// Typedefs for convenience +//------------------------- + +typedef Vec3 Shear3f; +typedef Vec3 Shear3d; +typedef Shear6 Shear6f; +typedef Shear6 Shear6d; + + + + +//----------------------- +// Implementation of Shear6 +//----------------------- + +template +inline T & +Shear6::operator [] (int i) +{ + return (&xy)[i]; +} + +template +inline const T & +Shear6::operator [] (int i) const +{ + return (&xy)[i]; +} + +template +inline +Shear6::Shear6 () +{ + xy = xz = yz = yx = zx = zy = 0; +} + +template +inline +Shear6::Shear6 (T XY, T XZ, T YZ) +{ + xy = XY; + xz = XZ; + yz = YZ; + yx = 0; + zx = 0; + zy = 0; +} + +template +inline +Shear6::Shear6 (const Vec3 &v) +{ + xy = v.x; + xz = v.y; + yz = v.z; + yx = 0; + zx = 0; + zy = 0; +} + +template +template +inline +Shear6::Shear6 (const Vec3 &v) +{ + xy = T (v.x); + xz = T (v.y); + yz = T (v.z); + yx = 0; + zx = 0; + zy = 0; +} + +template +inline +Shear6::Shear6 (T XY, T XZ, T YZ, T YX, T ZX, T ZY) +{ + xy = XY; + xz = XZ; + yz = YZ; + yx = YX; + zx = ZX; + zy = ZY; +} + +template +inline +Shear6::Shear6 (const Shear6 &h) +{ + xy = h.xy; + xz = h.xz; + yz = h.yz; + yx = h.yx; + zx = h.zx; + zy = h.zy; +} + +template +template +inline +Shear6::Shear6 (const Shear6 &h) +{ + xy = T (h.xy); + xz = T (h.xz); + yz = T (h.yz); + yx = T (h.yx); + zx = T (h.zx); + zy = T (h.zy); +} + +template +inline const Shear6 & +Shear6::operator = (const Shear6 &h) +{ + xy = h.xy; + xz = h.xz; + yz = h.yz; + yx = h.yx; + zx = h.zx; + zy = h.zy; + return *this; +} + +template +template +inline const Shear6 & +Shear6::operator = (const Vec3 &v) +{ + xy = T (v.x); + xz = T (v.y); + yz = T (v.z); + yx = 0; + zx = 0; + zy = 0; + return *this; +} + +template +template +inline void +Shear6::setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY) +{ + xy = T (XY); + xz = T (XZ); + yz = T (YZ); + yx = T (YX); + zx = T (ZX); + zy = T (ZY); +} + +template +template +inline void +Shear6::setValue (const Shear6 &h) +{ + xy = T (h.xy); + xz = T (h.xz); + yz = T (h.yz); + yx = T (h.yx); + zx = T (h.zx); + zy = T (h.zy); +} + +template +template +inline void +Shear6::getValue (S &XY, S &XZ, S &YZ, S &YX, S &ZX, S &ZY) const +{ + XY = S (xy); + XZ = S (xz); + YZ = S (yz); + YX = S (yx); + ZX = S (zx); + ZY = S (zy); +} + +template +template +inline void +Shear6::getValue (Shear6 &h) const +{ + h.xy = S (xy); + h.xz = S (xz); + h.yz = S (yz); + h.yx = S (yx); + h.zx = S (zx); + h.zy = S (zy); +} + +template +inline T * +Shear6::getValue() +{ + return (T *) &xy; +} + +template +inline const T * +Shear6::getValue() const +{ + return (const T *) &xy; +} + +template +template +inline bool +Shear6::operator == (const Shear6 &h) const +{ + return xy == h.xy && xz == h.xz && yz == h.yz && + yx == h.yx && zx == h.zx && zy == h.zy; +} + +template +template +inline bool +Shear6::operator != (const Shear6 &h) const +{ + return xy != h.xy || xz != h.xz || yz != h.yz || + yx != h.yx || zx != h.zx || zy != h.zy; +} + +template +bool +Shear6::equalWithAbsError (const Shear6 &h, T e) const +{ + for (int i = 0; i < 6; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], h[i], e)) + return false; + + return true; +} + +template +bool +Shear6::equalWithRelError (const Shear6 &h, T e) const +{ + for (int i = 0; i < 6; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], h[i], e)) + return false; + + return true; +} + + +template +inline const Shear6 & +Shear6::operator += (const Shear6 &h) +{ + xy += h.xy; + xz += h.xz; + yz += h.yz; + yx += h.yx; + zx += h.zx; + zy += h.zy; + return *this; +} + +template +inline Shear6 +Shear6::operator + (const Shear6 &h) const +{ + return Shear6 (xy + h.xy, xz + h.xz, yz + h.yz, + yx + h.yx, zx + h.zx, zy + h.zy); +} + +template +inline const Shear6 & +Shear6::operator -= (const Shear6 &h) +{ + xy -= h.xy; + xz -= h.xz; + yz -= h.yz; + yx -= h.yx; + zx -= h.zx; + zy -= h.zy; + return *this; +} + +template +inline Shear6 +Shear6::operator - (const Shear6 &h) const +{ + return Shear6 (xy - h.xy, xz - h.xz, yz - h.yz, + yx - h.yx, zx - h.zx, zy - h.zy); +} + +template +inline Shear6 +Shear6::operator - () const +{ + return Shear6 (-xy, -xz, -yz, -yx, -zx, -zy); +} + +template +inline const Shear6 & +Shear6::negate () +{ + xy = -xy; + xz = -xz; + yz = -yz; + yx = -yx; + zx = -zx; + zy = -zy; + return *this; +} + +template +inline const Shear6 & +Shear6::operator *= (const Shear6 &h) +{ + xy *= h.xy; + xz *= h.xz; + yz *= h.yz; + yx *= h.yx; + zx *= h.zx; + zy *= h.zy; + return *this; +} + +template +inline const Shear6 & +Shear6::operator *= (T a) +{ + xy *= a; + xz *= a; + yz *= a; + yx *= a; + zx *= a; + zy *= a; + return *this; +} + +template +inline Shear6 +Shear6::operator * (const Shear6 &h) const +{ + return Shear6 (xy * h.xy, xz * h.xz, yz * h.yz, + yx * h.yx, zx * h.zx, zy * h.zy); +} + +template +inline Shear6 +Shear6::operator * (T a) const +{ + return Shear6 (xy * a, xz * a, yz * a, + yx * a, zx * a, zy * a); +} + +template +inline const Shear6 & +Shear6::operator /= (const Shear6 &h) +{ + xy /= h.xy; + xz /= h.xz; + yz /= h.yz; + yx /= h.yx; + zx /= h.zx; + zy /= h.zy; + return *this; +} + +template +inline const Shear6 & +Shear6::operator /= (T a) +{ + xy /= a; + xz /= a; + yz /= a; + yx /= a; + zx /= a; + zy /= a; + return *this; +} + +template +inline Shear6 +Shear6::operator / (const Shear6 &h) const +{ + return Shear6 (xy / h.xy, xz / h.xz, yz / h.yz, + yx / h.yx, zx / h.zx, zy / h.zy); +} + +template +inline Shear6 +Shear6::operator / (T a) const +{ + return Shear6 (xy / a, xz / a, yz / a, + yx / a, zx / a, zy / a); +} + + +//----------------------------- +// Stream output implementation +//----------------------------- + +template +std::ostream & +operator << (std::ostream &s, const Shear6 &h) +{ + return s << '(' + << h.xy << ' ' << h.xz << ' ' << h.yz + << h.yx << ' ' << h.zx << ' ' << h.zy + << ')'; +} + + +//----------------------------------------- +// Implementation of reverse multiplication +//----------------------------------------- + +template +inline Shear6 +operator * (S a, const Shear6 &h) +{ + return Shear6 (a * h.xy, a * h.xz, a * h.yz, + a * h.yx, a * h.zx, a * h.zy); +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHSHEAR_H diff --git a/OpenEXR/include/OpenEXR/ImathSphere.h b/OpenEXR/include/OpenEXR/ImathSphere.h new file mode 100644 index 0000000..e8f36df --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathSphere.h @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHSPHERE_H +#define INCLUDED_IMATHSPHERE_H + +//------------------------------------- +// +// A 3D sphere class template +// +//------------------------------------- + +#include "ImathVec.h" +#include "ImathBox.h" +#include "ImathLine.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +template +class Sphere3 +{ + public: + + Vec3 center; + T radius; + + //--------------- + // Constructors + //--------------- + + Sphere3() : center(0,0,0), radius(0) {} + Sphere3(const Vec3 &c, T r) : center(c), radius(r) {} + + //------------------------------------------------------------------- + // Utilities: + // + // s.circumscribe(b) sets center and radius of sphere s + // so that the s tightly encloses box b. + // + // s.intersectT (l, t) If sphere s and line l intersect, then + // intersectT() computes the smallest t, + // t >= 0, so that l(t) is a point on the + // sphere. intersectT() then returns true. + // + // If s and l do not intersect, intersectT() + // returns false. + // + // s.intersect (l, i) If sphere s and line l intersect, then + // intersect() calls s.intersectT(l,t) and + // computes i = l(t). + // + // If s and l do not intersect, intersect() + // returns false. + // + //------------------------------------------------------------------- + + void circumscribe(const Box > &box); + bool intersect(const Line3 &l, Vec3 &intersection) const; + bool intersectT(const Line3 &l, T &t) const; +}; + + +//-------------------- +// Convenient typedefs +//-------------------- + +typedef Sphere3 Sphere3f; +typedef Sphere3 Sphere3d; + + +//--------------- +// Implementation +//--------------- + +template +void Sphere3::circumscribe(const Box > &box) +{ + center = T(0.5) * (box.min + box.max); + radius = (box.max - center).length(); +} + + +template +bool Sphere3::intersectT(const Line3 &line, T &t) const +{ + bool doesIntersect = true; + + Vec3 v = line.pos - center; + T B = T(2.0) * (line.dir ^ v); + T C = (v ^ v) - (radius * radius); + + // compute discriminant + // if negative, there is no intersection + + T discr = B*B - T(4.0)*C; + + if (discr < 0.0) + { + // line and Sphere3 do not intersect + + doesIntersect = false; + } + else + { + // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1) + + T sqroot = Math::sqrt(discr); + t = (-B - sqroot) * T(0.5); + + if (t < 0.0) + { + // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1) + + t = (-B + sqroot) * T(0.5); + } + + if (t < 0.0) + doesIntersect = false; + } + + return doesIntersect; +} + + +template +bool Sphere3::intersect(const Line3 &line, Vec3 &intersection) const +{ + T t; + + if (intersectT (line, t)) + { + intersection = line(t); + return true; + } + else + { + return false; + } +} + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHSPHERE_H diff --git a/OpenEXR/include/OpenEXR/ImathVec.h b/OpenEXR/include/OpenEXR/ImathVec.h new file mode 100644 index 0000000..fb859eb --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathVec.h @@ -0,0 +1,2227 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHVEC_H +#define INCLUDED_IMATHVEC_H + +//---------------------------------------------------- +// +// 2D, 3D and 4D point/vector class templates +// +//---------------------------------------------------- + +#include "ImathExc.h" +#include "ImathLimits.h" +#include "ImathMath.h" +#include "ImathNamespace.h" + +#include + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +// suppress exception specification warnings +#pragma warning(push) +#pragma warning(disable:4290) +#endif + + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +template class Vec2; +template class Vec3; +template class Vec4; + +enum InfException {INF_EXCEPTION}; + + +template class Vec2 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T x, y; + + T & operator [] (int i); + const T & operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Vec2 (); // no initialization + explicit Vec2 (T a); // (a a) + Vec2 (T a, T b); // (a b) + + + //--------------------------------- + // Copy constructors and assignment + //--------------------------------- + + Vec2 (const Vec2 &v); + template Vec2 (const Vec2 &v); + + const Vec2 & operator = (const Vec2 &v); + + + //---------------------- + // Compatibility with Sb + //---------------------- + + template + void setValue (S a, S b); + + template + void setValue (const Vec2 &v); + + template + void getValue (S &a, S &b) const; + + template + void getValue (Vec2 &v) const; + + T * getValue (); + const T * getValue () const; + + + //--------- + // Equality + //--------- + + template + bool operator == (const Vec2 &v) const; + + template + bool operator != (const Vec2 &v) const; + + + //----------------------------------------------------------------------- + // Compare two vectors and test if they are "approximately equal": + // + // equalWithAbsError (v, e) + // + // Returns true if the coefficients of this and v are the same with + // an absolute error of no more than e, i.e., for all i + // + // abs (this[i] - v[i]) <= e + // + // equalWithRelError (v, e) + // + // Returns true if the coefficients of this and v are the same with + // a relative error of no more than e, i.e., for all i + // + // abs (this[i] - v[i]) <= e * abs (this[i]) + //----------------------------------------------------------------------- + + bool equalWithAbsError (const Vec2 &v, T e) const; + bool equalWithRelError (const Vec2 &v, T e) const; + + //------------ + // Dot product + //------------ + + T dot (const Vec2 &v) const; + T operator ^ (const Vec2 &v) const; + + + //------------------------------------------------ + // Right-handed cross product, i.e. z component of + // Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0) + //------------------------------------------------ + + T cross (const Vec2 &v) const; + T operator % (const Vec2 &v) const; + + + //------------------------ + // Component-wise addition + //------------------------ + + const Vec2 & operator += (const Vec2 &v); + Vec2 operator + (const Vec2 &v) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Vec2 & operator -= (const Vec2 &v); + Vec2 operator - (const Vec2 &v) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Vec2 operator - () const; + const Vec2 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Vec2 & operator *= (const Vec2 &v); + const Vec2 & operator *= (T a); + Vec2 operator * (const Vec2 &v) const; + Vec2 operator * (T a) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Vec2 & operator /= (const Vec2 &v); + const Vec2 & operator /= (T a); + Vec2 operator / (const Vec2 &v) const; + Vec2 operator / (T a) const; + + + //---------------------------------------------------------------- + // Length and normalization: If v.length() is 0.0, v.normalize() + // and v.normalized() produce a null vector; v.normalizeExc() and + // v.normalizedExc() throw a NullVecExc. + // v.normalizeNonNull() and v.normalizedNonNull() are slightly + // faster than the other normalization routines, but if v.length() + // is 0.0, the result is undefined. + //---------------------------------------------------------------- + + T length () const; + T length2 () const; + + const Vec2 & normalize (); // modifies *this + const Vec2 & normalizeExc () throw (IEX_NAMESPACE::MathExc); + const Vec2 & normalizeNonNull (); + + Vec2 normalized () const; // does not modify *this + Vec2 normalizedExc () const throw (IEX_NAMESPACE::MathExc); + Vec2 normalizedNonNull () const; + + + //-------------------------------------------------------- + // Number of dimensions, i.e. number of elements in a Vec2 + //-------------------------------------------------------- + + static unsigned int dimensions() {return 2;} + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + + //-------------------------------------------------------------- + // Base type -- in templates, which accept a parameter, V, which + // could be either a Vec2, a Vec3, or a Vec4 you can + // refer to T as V::BaseType + //-------------------------------------------------------------- + + typedef T BaseType; + + private: + + T lengthTiny () const; +}; + + +template class Vec3 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T x, y, z; + + T & operator [] (int i); + const T & operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Vec3 (); // no initialization + explicit Vec3 (T a); // (a a a) + Vec3 (T a, T b, T c); // (a b c) + + + //--------------------------------- + // Copy constructors and assignment + //--------------------------------- + + Vec3 (const Vec3 &v); + template Vec3 (const Vec3 &v); + + const Vec3 & operator = (const Vec3 &v); + + + //--------------------------------------------------------- + // Vec4 to Vec3 conversion, divides x, y and z by w: + // + // The one-argument conversion function divides by w even + // if w is zero. The result depends on how the environment + // handles floating-point exceptions. + // + // The two-argument version thows an InfPointExc exception + // if w is zero or if division by w would overflow. + //--------------------------------------------------------- + + template explicit Vec3 (const Vec4 &v); + template explicit Vec3 (const Vec4 &v, InfException); + + + //---------------------- + // Compatibility with Sb + //---------------------- + + template + void setValue (S a, S b, S c); + + template + void setValue (const Vec3 &v); + + template + void getValue (S &a, S &b, S &c) const; + + template + void getValue (Vec3 &v) const; + + T * getValue(); + const T * getValue() const; + + + //--------- + // Equality + //--------- + + template + bool operator == (const Vec3 &v) const; + + template + bool operator != (const Vec3 &v) const; + + //----------------------------------------------------------------------- + // Compare two vectors and test if they are "approximately equal": + // + // equalWithAbsError (v, e) + // + // Returns true if the coefficients of this and v are the same with + // an absolute error of no more than e, i.e., for all i + // + // abs (this[i] - v[i]) <= e + // + // equalWithRelError (v, e) + // + // Returns true if the coefficients of this and v are the same with + // a relative error of no more than e, i.e., for all i + // + // abs (this[i] - v[i]) <= e * abs (this[i]) + //----------------------------------------------------------------------- + + bool equalWithAbsError (const Vec3 &v, T e) const; + bool equalWithRelError (const Vec3 &v, T e) const; + + //------------ + // Dot product + //------------ + + T dot (const Vec3 &v) const; + T operator ^ (const Vec3 &v) const; + + + //--------------------------- + // Right-handed cross product + //--------------------------- + + Vec3 cross (const Vec3 &v) const; + const Vec3 & operator %= (const Vec3 &v); + Vec3 operator % (const Vec3 &v) const; + + + //------------------------ + // Component-wise addition + //------------------------ + + const Vec3 & operator += (const Vec3 &v); + Vec3 operator + (const Vec3 &v) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Vec3 & operator -= (const Vec3 &v); + Vec3 operator - (const Vec3 &v) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Vec3 operator - () const; + const Vec3 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Vec3 & operator *= (const Vec3 &v); + const Vec3 & operator *= (T a); + Vec3 operator * (const Vec3 &v) const; + Vec3 operator * (T a) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Vec3 & operator /= (const Vec3 &v); + const Vec3 & operator /= (T a); + Vec3 operator / (const Vec3 &v) const; + Vec3 operator / (T a) const; + + + //---------------------------------------------------------------- + // Length and normalization: If v.length() is 0.0, v.normalize() + // and v.normalized() produce a null vector; v.normalizeExc() and + // v.normalizedExc() throw a NullVecExc. + // v.normalizeNonNull() and v.normalizedNonNull() are slightly + // faster than the other normalization routines, but if v.length() + // is 0.0, the result is undefined. + //---------------------------------------------------------------- + + T length () const; + T length2 () const; + + const Vec3 & normalize (); // modifies *this + const Vec3 & normalizeExc () throw (IEX_NAMESPACE::MathExc); + const Vec3 & normalizeNonNull (); + + Vec3 normalized () const; // does not modify *this + Vec3 normalizedExc () const throw (IEX_NAMESPACE::MathExc); + Vec3 normalizedNonNull () const; + + + //-------------------------------------------------------- + // Number of dimensions, i.e. number of elements in a Vec3 + //-------------------------------------------------------- + + static unsigned int dimensions() {return 3;} + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + + //-------------------------------------------------------------- + // Base type -- in templates, which accept a parameter, V, which + // could be either a Vec2, a Vec3, or a Vec4 you can + // refer to T as V::BaseType + //-------------------------------------------------------------- + + typedef T BaseType; + + private: + + T lengthTiny () const; +}; + + + +template class Vec4 +{ + public: + + //------------------- + // Access to elements + //------------------- + + T x, y, z, w; + + T & operator [] (int i); + const T & operator [] (int i) const; + + + //------------- + // Constructors + //------------- + + Vec4 (); // no initialization + explicit Vec4 (T a); // (a a a a) + Vec4 (T a, T b, T c, T d); // (a b c d) + + + //--------------------------------- + // Copy constructors and assignment + //--------------------------------- + + Vec4 (const Vec4 &v); + template Vec4 (const Vec4 &v); + + const Vec4 & operator = (const Vec4 &v); + + + //------------------------------------- + // Vec3 to Vec4 conversion, sets w to 1 + //------------------------------------- + + template explicit Vec4 (const Vec3 &v); + + + //--------- + // Equality + //--------- + + template + bool operator == (const Vec4 &v) const; + + template + bool operator != (const Vec4 &v) const; + + + //----------------------------------------------------------------------- + // Compare two vectors and test if they are "approximately equal": + // + // equalWithAbsError (v, e) + // + // Returns true if the coefficients of this and v are the same with + // an absolute error of no more than e, i.e., for all i + // + // abs (this[i] - v[i]) <= e + // + // equalWithRelError (v, e) + // + // Returns true if the coefficients of this and v are the same with + // a relative error of no more than e, i.e., for all i + // + // abs (this[i] - v[i]) <= e * abs (this[i]) + //----------------------------------------------------------------------- + + bool equalWithAbsError (const Vec4 &v, T e) const; + bool equalWithRelError (const Vec4 &v, T e) const; + + + //------------ + // Dot product + //------------ + + T dot (const Vec4 &v) const; + T operator ^ (const Vec4 &v) const; + + + //----------------------------------- + // Cross product is not defined in 4D + //----------------------------------- + + //------------------------ + // Component-wise addition + //------------------------ + + const Vec4 & operator += (const Vec4 &v); + Vec4 operator + (const Vec4 &v) const; + + + //--------------------------- + // Component-wise subtraction + //--------------------------- + + const Vec4 & operator -= (const Vec4 &v); + Vec4 operator - (const Vec4 &v) const; + + + //------------------------------------ + // Component-wise multiplication by -1 + //------------------------------------ + + Vec4 operator - () const; + const Vec4 & negate (); + + + //------------------------------ + // Component-wise multiplication + //------------------------------ + + const Vec4 & operator *= (const Vec4 &v); + const Vec4 & operator *= (T a); + Vec4 operator * (const Vec4 &v) const; + Vec4 operator * (T a) const; + + + //------------------------ + // Component-wise division + //------------------------ + + const Vec4 & operator /= (const Vec4 &v); + const Vec4 & operator /= (T a); + Vec4 operator / (const Vec4 &v) const; + Vec4 operator / (T a) const; + + + //---------------------------------------------------------------- + // Length and normalization: If v.length() is 0.0, v.normalize() + // and v.normalized() produce a null vector; v.normalizeExc() and + // v.normalizedExc() throw a NullVecExc. + // v.normalizeNonNull() and v.normalizedNonNull() are slightly + // faster than the other normalization routines, but if v.length() + // is 0.0, the result is undefined. + //---------------------------------------------------------------- + + T length () const; + T length2 () const; + + const Vec4 & normalize (); // modifies *this + const Vec4 & normalizeExc () throw (IEX_NAMESPACE::MathExc); + const Vec4 & normalizeNonNull (); + + Vec4 normalized () const; // does not modify *this + Vec4 normalizedExc () const throw (IEX_NAMESPACE::MathExc); + Vec4 normalizedNonNull () const; + + + //-------------------------------------------------------- + // Number of dimensions, i.e. number of elements in a Vec4 + //-------------------------------------------------------- + + static unsigned int dimensions() {return 4;} + + + //------------------------------------------------- + // Limitations of type T (see also class limits) + //------------------------------------------------- + + static T baseTypeMin() {return limits::min();} + static T baseTypeMax() {return limits::max();} + static T baseTypeSmallest() {return limits::smallest();} + static T baseTypeEpsilon() {return limits::epsilon();} + + + //-------------------------------------------------------------- + // Base type -- in templates, which accept a parameter, V, which + // could be either a Vec2, a Vec3, or a Vec4 you can + // refer to T as V::BaseType + //-------------------------------------------------------------- + + typedef T BaseType; + + private: + + T lengthTiny () const; +}; + + +//-------------- +// Stream output +//-------------- + +template +std::ostream & operator << (std::ostream &s, const Vec2 &v); + +template +std::ostream & operator << (std::ostream &s, const Vec3 &v); + +template +std::ostream & operator << (std::ostream &s, const Vec4 &v); + +//---------------------------------------------------- +// Reverse multiplication: S * Vec2 and S * Vec3 +//---------------------------------------------------- + +template Vec2 operator * (T a, const Vec2 &v); +template Vec3 operator * (T a, const Vec3 &v); +template Vec4 operator * (T a, const Vec4 &v); + + +//------------------------- +// Typedefs for convenience +//------------------------- + +typedef Vec2 V2s; +typedef Vec2 V2i; +typedef Vec2 V2f; +typedef Vec2 V2d; +typedef Vec3 V3s; +typedef Vec3 V3i; +typedef Vec3 V3f; +typedef Vec3 V3d; +typedef Vec4 V4s; +typedef Vec4 V4i; +typedef Vec4 V4f; +typedef Vec4 V4d; + + +//------------------------------------------- +// Specializations for VecN, VecN +//------------------------------------------- + +// Vec2 + +template <> short +Vec2::length () const; + +template <> const Vec2 & +Vec2::normalize (); + +template <> const Vec2 & +Vec2::normalizeExc () throw (IEX_NAMESPACE::MathExc); + +template <> const Vec2 & +Vec2::normalizeNonNull (); + +template <> Vec2 +Vec2::normalized () const; + +template <> Vec2 +Vec2::normalizedExc () const throw (IEX_NAMESPACE::MathExc); + +template <> Vec2 +Vec2::normalizedNonNull () const; + + +// Vec2 + +template <> int +Vec2::length () const; + +template <> const Vec2 & +Vec2::normalize (); + +template <> const Vec2 & +Vec2::normalizeExc () throw (IEX_NAMESPACE::MathExc); + +template <> const Vec2 & +Vec2::normalizeNonNull (); + +template <> Vec2 +Vec2::normalized () const; + +template <> Vec2 +Vec2::normalizedExc () const throw (IEX_NAMESPACE::MathExc); + +template <> Vec2 +Vec2::normalizedNonNull () const; + + +// Vec3 + +template <> short +Vec3::length () const; + +template <> const Vec3 & +Vec3::normalize (); + +template <> const Vec3 & +Vec3::normalizeExc () throw (IEX_NAMESPACE::MathExc); + +template <> const Vec3 & +Vec3::normalizeNonNull (); + +template <> Vec3 +Vec3::normalized () const; + +template <> Vec3 +Vec3::normalizedExc () const throw (IEX_NAMESPACE::MathExc); + +template <> Vec3 +Vec3::normalizedNonNull () const; + + +// Vec3 + +template <> int +Vec3::length () const; + +template <> const Vec3 & +Vec3::normalize (); + +template <> const Vec3 & +Vec3::normalizeExc () throw (IEX_NAMESPACE::MathExc); + +template <> const Vec3 & +Vec3::normalizeNonNull (); + +template <> Vec3 +Vec3::normalized () const; + +template <> Vec3 +Vec3::normalizedExc () const throw (IEX_NAMESPACE::MathExc); + +template <> Vec3 +Vec3::normalizedNonNull () const; + +// Vec4 + +template <> short +Vec4::length () const; + +template <> const Vec4 & +Vec4::normalize (); + +template <> const Vec4 & +Vec4::normalizeExc () throw (IEX_NAMESPACE::MathExc); + +template <> const Vec4 & +Vec4::normalizeNonNull (); + +template <> Vec4 +Vec4::normalized () const; + +template <> Vec4 +Vec4::normalizedExc () const throw (IEX_NAMESPACE::MathExc); + +template <> Vec4 +Vec4::normalizedNonNull () const; + + +// Vec4 + +template <> int +Vec4::length () const; + +template <> const Vec4 & +Vec4::normalize (); + +template <> const Vec4 & +Vec4::normalizeExc () throw (IEX_NAMESPACE::MathExc); + +template <> const Vec4 & +Vec4::normalizeNonNull (); + +template <> Vec4 +Vec4::normalized () const; + +template <> Vec4 +Vec4::normalizedExc () const throw (IEX_NAMESPACE::MathExc); + +template <> Vec4 +Vec4::normalizedNonNull () const; + + +//------------------------ +// Implementation of Vec2: +//------------------------ + +template +inline T & +Vec2::operator [] (int i) +{ + return (&x)[i]; +} + +template +inline const T & +Vec2::operator [] (int i) const +{ + return (&x)[i]; +} + +template +inline +Vec2::Vec2 () +{ + // empty +} + +template +inline +Vec2::Vec2 (T a) +{ + x = y = a; +} + +template +inline +Vec2::Vec2 (T a, T b) +{ + x = a; + y = b; +} + +template +inline +Vec2::Vec2 (const Vec2 &v) +{ + x = v.x; + y = v.y; +} + +template +template +inline +Vec2::Vec2 (const Vec2 &v) +{ + x = T (v.x); + y = T (v.y); +} + +template +inline const Vec2 & +Vec2::operator = (const Vec2 &v) +{ + x = v.x; + y = v.y; + return *this; +} + +template +template +inline void +Vec2::setValue (S a, S b) +{ + x = T (a); + y = T (b); +} + +template +template +inline void +Vec2::setValue (const Vec2 &v) +{ + x = T (v.x); + y = T (v.y); +} + +template +template +inline void +Vec2::getValue (S &a, S &b) const +{ + a = S (x); + b = S (y); +} + +template +template +inline void +Vec2::getValue (Vec2 &v) const +{ + v.x = S (x); + v.y = S (y); +} + +template +inline T * +Vec2::getValue() +{ + return (T *) &x; +} + +template +inline const T * +Vec2::getValue() const +{ + return (const T *) &x; +} + +template +template +inline bool +Vec2::operator == (const Vec2 &v) const +{ + return x == v.x && y == v.y; +} + +template +template +inline bool +Vec2::operator != (const Vec2 &v) const +{ + return x != v.x || y != v.y; +} + +template +bool +Vec2::equalWithAbsError (const Vec2 &v, T e) const +{ + for (int i = 0; i < 2; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) + return false; + + return true; +} + +template +bool +Vec2::equalWithRelError (const Vec2 &v, T e) const +{ + for (int i = 0; i < 2; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) + return false; + + return true; +} + +template +inline T +Vec2::dot (const Vec2 &v) const +{ + return x * v.x + y * v.y; +} + +template +inline T +Vec2::operator ^ (const Vec2 &v) const +{ + return dot (v); +} + +template +inline T +Vec2::cross (const Vec2 &v) const +{ + return x * v.y - y * v.x; + +} + +template +inline T +Vec2::operator % (const Vec2 &v) const +{ + return x * v.y - y * v.x; +} + +template +inline const Vec2 & +Vec2::operator += (const Vec2 &v) +{ + x += v.x; + y += v.y; + return *this; +} + +template +inline Vec2 +Vec2::operator + (const Vec2 &v) const +{ + return Vec2 (x + v.x, y + v.y); +} + +template +inline const Vec2 & +Vec2::operator -= (const Vec2 &v) +{ + x -= v.x; + y -= v.y; + return *this; +} + +template +inline Vec2 +Vec2::operator - (const Vec2 &v) const +{ + return Vec2 (x - v.x, y - v.y); +} + +template +inline Vec2 +Vec2::operator - () const +{ + return Vec2 (-x, -y); +} + +template +inline const Vec2 & +Vec2::negate () +{ + x = -x; + y = -y; + return *this; +} + +template +inline const Vec2 & +Vec2::operator *= (const Vec2 &v) +{ + x *= v.x; + y *= v.y; + return *this; +} + +template +inline const Vec2 & +Vec2::operator *= (T a) +{ + x *= a; + y *= a; + return *this; +} + +template +inline Vec2 +Vec2::operator * (const Vec2 &v) const +{ + return Vec2 (x * v.x, y * v.y); +} + +template +inline Vec2 +Vec2::operator * (T a) const +{ + return Vec2 (x * a, y * a); +} + +template +inline const Vec2 & +Vec2::operator /= (const Vec2 &v) +{ + x /= v.x; + y /= v.y; + return *this; +} + +template +inline const Vec2 & +Vec2::operator /= (T a) +{ + x /= a; + y /= a; + return *this; +} + +template +inline Vec2 +Vec2::operator / (const Vec2 &v) const +{ + return Vec2 (x / v.x, y / v.y); +} + +template +inline Vec2 +Vec2::operator / (T a) const +{ + return Vec2 (x / a, y / a); +} + +template +T +Vec2::lengthTiny () const +{ + T absX = (x >= T (0))? x: -x; + T absY = (y >= T (0))? y: -y; + + T max = absX; + + if (max < absY) + max = absY; + + if (max == T (0)) + return T (0); + + // + // Do not replace the divisions by max with multiplications by 1/max. + // Computing 1/max can overflow but the divisions below will always + // produce results less than or equal to 1. + // + + absX /= max; + absY /= max; + + return max * Math::sqrt (absX * absX + absY * absY); +} + +template +inline T +Vec2::length () const +{ + T length2 = dot (*this); + + if (length2 < T (2) * limits::smallest()) + return lengthTiny(); + + return Math::sqrt (length2); +} + +template +inline T +Vec2::length2 () const +{ + return dot (*this); +} + +template +const Vec2 & +Vec2::normalize () +{ + T l = length(); + + if (l != T (0)) + { + // + // Do not replace the divisions by l with multiplications by 1/l. + // Computing 1/l can overflow but the divisions below will always + // produce results less than or equal to 1. + // + + x /= l; + y /= l; + } + + return *this; +} + +template +const Vec2 & +Vec2::normalizeExc () throw (IEX_NAMESPACE::MathExc) +{ + T l = length(); + + if (l == T (0)) + throw NullVecExc ("Cannot normalize null vector."); + + x /= l; + y /= l; + return *this; +} + +template +inline +const Vec2 & +Vec2::normalizeNonNull () +{ + T l = length(); + x /= l; + y /= l; + return *this; +} + +template +Vec2 +Vec2::normalized () const +{ + T l = length(); + + if (l == T (0)) + return Vec2 (T (0)); + + return Vec2 (x / l, y / l); +} + +template +Vec2 +Vec2::normalizedExc () const throw (IEX_NAMESPACE::MathExc) +{ + T l = length(); + + if (l == T (0)) + throw NullVecExc ("Cannot normalize null vector."); + + return Vec2 (x / l, y / l); +} + +template +inline +Vec2 +Vec2::normalizedNonNull () const +{ + T l = length(); + return Vec2 (x / l, y / l); +} + + +//----------------------- +// Implementation of Vec3 +//----------------------- + +template +inline T & +Vec3::operator [] (int i) +{ + return (&x)[i]; +} + +template +inline const T & +Vec3::operator [] (int i) const +{ + return (&x)[i]; +} + +template +inline +Vec3::Vec3 () +{ + // empty +} + +template +inline +Vec3::Vec3 (T a) +{ + x = y = z = a; +} + +template +inline +Vec3::Vec3 (T a, T b, T c) +{ + x = a; + y = b; + z = c; +} + +template +inline +Vec3::Vec3 (const Vec3 &v) +{ + x = v.x; + y = v.y; + z = v.z; +} + +template +template +inline +Vec3::Vec3 (const Vec3 &v) +{ + x = T (v.x); + y = T (v.y); + z = T (v.z); +} + +template +inline const Vec3 & +Vec3::operator = (const Vec3 &v) +{ + x = v.x; + y = v.y; + z = v.z; + return *this; +} + +template +template +inline +Vec3::Vec3 (const Vec4 &v) +{ + x = T (v.x / v.w); + y = T (v.y / v.w); + z = T (v.z / v.w); +} + +template +template +Vec3::Vec3 (const Vec4 &v, InfException) +{ + T vx = T (v.x); + T vy = T (v.y); + T vz = T (v.z); + T vw = T (v.w); + + T absW = (vw >= T (0))? vw: -vw; + + if (absW < 1) + { + T m = baseTypeMax() * absW; + + if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m) + throw InfPointExc ("Cannot normalize point at infinity."); + } + + x = vx / vw; + y = vy / vw; + z = vz / vw; +} + +template +template +inline void +Vec3::setValue (S a, S b, S c) +{ + x = T (a); + y = T (b); + z = T (c); +} + +template +template +inline void +Vec3::setValue (const Vec3 &v) +{ + x = T (v.x); + y = T (v.y); + z = T (v.z); +} + +template +template +inline void +Vec3::getValue (S &a, S &b, S &c) const +{ + a = S (x); + b = S (y); + c = S (z); +} + +template +template +inline void +Vec3::getValue (Vec3 &v) const +{ + v.x = S (x); + v.y = S (y); + v.z = S (z); +} + +template +inline T * +Vec3::getValue() +{ + return (T *) &x; +} + +template +inline const T * +Vec3::getValue() const +{ + return (const T *) &x; +} + +template +template +inline bool +Vec3::operator == (const Vec3 &v) const +{ + return x == v.x && y == v.y && z == v.z; +} + +template +template +inline bool +Vec3::operator != (const Vec3 &v) const +{ + return x != v.x || y != v.y || z != v.z; +} + +template +bool +Vec3::equalWithAbsError (const Vec3 &v, T e) const +{ + for (int i = 0; i < 3; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) + return false; + + return true; +} + +template +bool +Vec3::equalWithRelError (const Vec3 &v, T e) const +{ + for (int i = 0; i < 3; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) + return false; + + return true; +} + +template +inline T +Vec3::dot (const Vec3 &v) const +{ + return x * v.x + y * v.y + z * v.z; +} + +template +inline T +Vec3::operator ^ (const Vec3 &v) const +{ + return dot (v); +} + +template +inline Vec3 +Vec3::cross (const Vec3 &v) const +{ + return Vec3 (y * v.z - z * v.y, + z * v.x - x * v.z, + x * v.y - y * v.x); +} + +template +inline const Vec3 & +Vec3::operator %= (const Vec3 &v) +{ + T a = y * v.z - z * v.y; + T b = z * v.x - x * v.z; + T c = x * v.y - y * v.x; + x = a; + y = b; + z = c; + return *this; +} + +template +inline Vec3 +Vec3::operator % (const Vec3 &v) const +{ + return Vec3 (y * v.z - z * v.y, + z * v.x - x * v.z, + x * v.y - y * v.x); +} + +template +inline const Vec3 & +Vec3::operator += (const Vec3 &v) +{ + x += v.x; + y += v.y; + z += v.z; + return *this; +} + +template +inline Vec3 +Vec3::operator + (const Vec3 &v) const +{ + return Vec3 (x + v.x, y + v.y, z + v.z); +} + +template +inline const Vec3 & +Vec3::operator -= (const Vec3 &v) +{ + x -= v.x; + y -= v.y; + z -= v.z; + return *this; +} + +template +inline Vec3 +Vec3::operator - (const Vec3 &v) const +{ + return Vec3 (x - v.x, y - v.y, z - v.z); +} + +template +inline Vec3 +Vec3::operator - () const +{ + return Vec3 (-x, -y, -z); +} + +template +inline const Vec3 & +Vec3::negate () +{ + x = -x; + y = -y; + z = -z; + return *this; +} + +template +inline const Vec3 & +Vec3::operator *= (const Vec3 &v) +{ + x *= v.x; + y *= v.y; + z *= v.z; + return *this; +} + +template +inline const Vec3 & +Vec3::operator *= (T a) +{ + x *= a; + y *= a; + z *= a; + return *this; +} + +template +inline Vec3 +Vec3::operator * (const Vec3 &v) const +{ + return Vec3 (x * v.x, y * v.y, z * v.z); +} + +template +inline Vec3 +Vec3::operator * (T a) const +{ + return Vec3 (x * a, y * a, z * a); +} + +template +inline const Vec3 & +Vec3::operator /= (const Vec3 &v) +{ + x /= v.x; + y /= v.y; + z /= v.z; + return *this; +} + +template +inline const Vec3 & +Vec3::operator /= (T a) +{ + x /= a; + y /= a; + z /= a; + return *this; +} + +template +inline Vec3 +Vec3::operator / (const Vec3 &v) const +{ + return Vec3 (x / v.x, y / v.y, z / v.z); +} + +template +inline Vec3 +Vec3::operator / (T a) const +{ + return Vec3 (x / a, y / a, z / a); +} + +template +T +Vec3::lengthTiny () const +{ + T absX = (x >= T (0))? x: -x; + T absY = (y >= T (0))? y: -y; + T absZ = (z >= T (0))? z: -z; + + T max = absX; + + if (max < absY) + max = absY; + + if (max < absZ) + max = absZ; + + if (max == T (0)) + return T (0); + + // + // Do not replace the divisions by max with multiplications by 1/max. + // Computing 1/max can overflow but the divisions below will always + // produce results less than or equal to 1. + // + + absX /= max; + absY /= max; + absZ /= max; + + return max * Math::sqrt (absX * absX + absY * absY + absZ * absZ); +} + +template +inline T +Vec3::length () const +{ + T length2 = dot (*this); + + if (length2 < T (2) * limits::smallest()) + return lengthTiny(); + + return Math::sqrt (length2); +} + +template +inline T +Vec3::length2 () const +{ + return dot (*this); +} + +template +const Vec3 & +Vec3::normalize () +{ + T l = length(); + + if (l != T (0)) + { + // + // Do not replace the divisions by l with multiplications by 1/l. + // Computing 1/l can overflow but the divisions below will always + // produce results less than or equal to 1. + // + + x /= l; + y /= l; + z /= l; + } + + return *this; +} + +template +const Vec3 & +Vec3::normalizeExc () throw (IEX_NAMESPACE::MathExc) +{ + T l = length(); + + if (l == T (0)) + throw NullVecExc ("Cannot normalize null vector."); + + x /= l; + y /= l; + z /= l; + return *this; +} + +template +inline +const Vec3 & +Vec3::normalizeNonNull () +{ + T l = length(); + x /= l; + y /= l; + z /= l; + return *this; +} + +template +Vec3 +Vec3::normalized () const +{ + T l = length(); + + if (l == T (0)) + return Vec3 (T (0)); + + return Vec3 (x / l, y / l, z / l); +} + +template +Vec3 +Vec3::normalizedExc () const throw (IEX_NAMESPACE::MathExc) +{ + T l = length(); + + if (l == T (0)) + throw NullVecExc ("Cannot normalize null vector."); + + return Vec3 (x / l, y / l, z / l); +} + +template +inline +Vec3 +Vec3::normalizedNonNull () const +{ + T l = length(); + return Vec3 (x / l, y / l, z / l); +} + + +//----------------------- +// Implementation of Vec4 +//----------------------- + +template +inline T & +Vec4::operator [] (int i) +{ + return (&x)[i]; +} + +template +inline const T & +Vec4::operator [] (int i) const +{ + return (&x)[i]; +} + +template +inline +Vec4::Vec4 () +{ + // empty +} + +template +inline +Vec4::Vec4 (T a) +{ + x = y = z = w = a; +} + +template +inline +Vec4::Vec4 (T a, T b, T c, T d) +{ + x = a; + y = b; + z = c; + w = d; +} + +template +inline +Vec4::Vec4 (const Vec4 &v) +{ + x = v.x; + y = v.y; + z = v.z; + w = v.w; +} + +template +template +inline +Vec4::Vec4 (const Vec4 &v) +{ + x = T (v.x); + y = T (v.y); + z = T (v.z); + w = T (v.w); +} + +template +inline const Vec4 & +Vec4::operator = (const Vec4 &v) +{ + x = v.x; + y = v.y; + z = v.z; + w = v.w; + return *this; +} + +template +template +inline +Vec4::Vec4 (const Vec3 &v) +{ + x = T (v.x); + y = T (v.y); + z = T (v.z); + w = T (1); +} + +template +template +inline bool +Vec4::operator == (const Vec4 &v) const +{ + return x == v.x && y == v.y && z == v.z && w == v.w; +} + +template +template +inline bool +Vec4::operator != (const Vec4 &v) const +{ + return x != v.x || y != v.y || z != v.z || w != v.w; +} + +template +bool +Vec4::equalWithAbsError (const Vec4 &v, T e) const +{ + for (int i = 0; i < 4; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) + return false; + + return true; +} + +template +bool +Vec4::equalWithRelError (const Vec4 &v, T e) const +{ + for (int i = 0; i < 4; i++) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) + return false; + + return true; +} + +template +inline T +Vec4::dot (const Vec4 &v) const +{ + return x * v.x + y * v.y + z * v.z + w * v.w; +} + +template +inline T +Vec4::operator ^ (const Vec4 &v) const +{ + return dot (v); +} + + +template +inline const Vec4 & +Vec4::operator += (const Vec4 &v) +{ + x += v.x; + y += v.y; + z += v.z; + w += v.w; + return *this; +} + +template +inline Vec4 +Vec4::operator + (const Vec4 &v) const +{ + return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w); +} + +template +inline const Vec4 & +Vec4::operator -= (const Vec4 &v) +{ + x -= v.x; + y -= v.y; + z -= v.z; + w -= v.w; + return *this; +} + +template +inline Vec4 +Vec4::operator - (const Vec4 &v) const +{ + return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w); +} + +template +inline Vec4 +Vec4::operator - () const +{ + return Vec4 (-x, -y, -z, -w); +} + +template +inline const Vec4 & +Vec4::negate () +{ + x = -x; + y = -y; + z = -z; + w = -w; + return *this; +} + +template +inline const Vec4 & +Vec4::operator *= (const Vec4 &v) +{ + x *= v.x; + y *= v.y; + z *= v.z; + w *= v.w; + return *this; +} + +template +inline const Vec4 & +Vec4::operator *= (T a) +{ + x *= a; + y *= a; + z *= a; + w *= a; + return *this; +} + +template +inline Vec4 +Vec4::operator * (const Vec4 &v) const +{ + return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w); +} + +template +inline Vec4 +Vec4::operator * (T a) const +{ + return Vec4 (x * a, y * a, z * a, w * a); +} + +template +inline const Vec4 & +Vec4::operator /= (const Vec4 &v) +{ + x /= v.x; + y /= v.y; + z /= v.z; + w /= v.w; + return *this; +} + +template +inline const Vec4 & +Vec4::operator /= (T a) +{ + x /= a; + y /= a; + z /= a; + w /= a; + return *this; +} + +template +inline Vec4 +Vec4::operator / (const Vec4 &v) const +{ + return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w); +} + +template +inline Vec4 +Vec4::operator / (T a) const +{ + return Vec4 (x / a, y / a, z / a, w / a); +} + +template +T +Vec4::lengthTiny () const +{ + T absX = (x >= T (0))? x: -x; + T absY = (y >= T (0))? y: -y; + T absZ = (z >= T (0))? z: -z; + T absW = (w >= T (0))? w: -w; + + T max = absX; + + if (max < absY) + max = absY; + + if (max < absZ) + max = absZ; + + if (max < absW) + max = absW; + + if (max == T (0)) + return T (0); + + // + // Do not replace the divisions by max with multiplications by 1/max. + // Computing 1/max can overflow but the divisions below will always + // produce results less than or equal to 1. + // + + absX /= max; + absY /= max; + absZ /= max; + absW /= max; + + return max * + Math::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW); +} + +template +inline T +Vec4::length () const +{ + T length2 = dot (*this); + + if (length2 < T (2) * limits::smallest()) + return lengthTiny(); + + return Math::sqrt (length2); +} + +template +inline T +Vec4::length2 () const +{ + return dot (*this); +} + +template +const Vec4 & +Vec4::normalize () +{ + T l = length(); + + if (l != T (0)) + { + // + // Do not replace the divisions by l with multiplications by 1/l. + // Computing 1/l can overflow but the divisions below will always + // produce results less than or equal to 1. + // + + x /= l; + y /= l; + z /= l; + w /= l; + } + + return *this; +} + +template +const Vec4 & +Vec4::normalizeExc () throw (IEX_NAMESPACE::MathExc) +{ + T l = length(); + + if (l == T (0)) + throw NullVecExc ("Cannot normalize null vector."); + + x /= l; + y /= l; + z /= l; + w /= l; + return *this; +} + +template +inline +const Vec4 & +Vec4::normalizeNonNull () +{ + T l = length(); + x /= l; + y /= l; + z /= l; + w /= l; + return *this; +} + +template +Vec4 +Vec4::normalized () const +{ + T l = length(); + + if (l == T (0)) + return Vec4 (T (0)); + + return Vec4 (x / l, y / l, z / l, w / l); +} + +template +Vec4 +Vec4::normalizedExc () const throw (IEX_NAMESPACE::MathExc) +{ + T l = length(); + + if (l == T (0)) + throw NullVecExc ("Cannot normalize null vector."); + + return Vec4 (x / l, y / l, z / l, w / l); +} + +template +inline +Vec4 +Vec4::normalizedNonNull () const +{ + T l = length(); + return Vec4 (x / l, y / l, z / l, w / l); +} + +//----------------------------- +// Stream output implementation +//----------------------------- + +template +std::ostream & +operator << (std::ostream &s, const Vec2 &v) +{ + return s << '(' << v.x << ' ' << v.y << ')'; +} + +template +std::ostream & +operator << (std::ostream &s, const Vec3 &v) +{ + return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')'; +} + +template +std::ostream & +operator << (std::ostream &s, const Vec4 &v) +{ + return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')'; +} + + +//----------------------------------------- +// Implementation of reverse multiplication +//----------------------------------------- + +template +inline Vec2 +operator * (T a, const Vec2 &v) +{ + return Vec2 (a * v.x, a * v.y); +} + +template +inline Vec3 +operator * (T a, const Vec3 &v) +{ + return Vec3 (a * v.x, a * v.y, a * v.z); +} + +template +inline Vec4 +operator * (T a, const Vec4 &v) +{ + return Vec4 (a * v.x, a * v.y, a * v.z, a * v.w); +} + + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER +#pragma warning(pop) +#endif + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHVEC_H diff --git a/OpenEXR/include/OpenEXR/ImathVecAlgo.h b/OpenEXR/include/OpenEXR/ImathVecAlgo.h new file mode 100644 index 0000000..28bab6b --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImathVecAlgo.h @@ -0,0 +1,147 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMATHVECALGO_H +#define INCLUDED_IMATHVECALGO_H + +//------------------------------------------------------------------------- +// +// This file contains algorithms applied to or in conjunction +// with points (Imath::Vec2 and Imath::Vec3). +// The assumption made is that these functions are called much +// less often than the basic point functions or these functions +// require more support classes. +// +//------------------------------------------------------------------------- + +#include "ImathVec.h" +#include "ImathLimits.h" +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + + +//----------------------------------------------------------------- +// Find the projection of vector t onto vector s (Vec2, Vec3, Vec4) +//----------------------------------------------------------------- + +template Vec project (const Vec &s, const Vec &t); + + +//------------------------------------------------ +// Find a vector that is perpendicular to s and +// in the same plane as s and t (Vec2, Vec3, Vec4) +//------------------------------------------------ + +template Vec orthogonal (const Vec &s, const Vec &t); + + +//----------------------------------------------- +// Find the direction of a ray s after reflection +// off a plane with normal t (Vec2, Vec3, Vec4) +//----------------------------------------------- + +template Vec reflect (const Vec &s, const Vec &t); + + +//-------------------------------------------------------------------- +// Find the vertex of triangle (v0, v1, v2) that is closest to point p +// (Vec2, Vec3, Vec4) +//-------------------------------------------------------------------- + +template Vec closestVertex (const Vec &v0, + const Vec &v1, + const Vec &v2, + const Vec &p); + +//--------------- +// Implementation +//--------------- + +template +Vec +project (const Vec &s, const Vec &t) +{ + Vec sNormalized = s.normalized(); + return sNormalized * (sNormalized ^ t); +} + +template +Vec +orthogonal (const Vec &s, const Vec &t) +{ + return t - project (s, t); +} + +template +Vec +reflect (const Vec &s, const Vec &t) +{ + return s - typename Vec::BaseType(2) * (s - project(t, s)); +} + +template +Vec +closestVertex(const Vec &v0, + const Vec &v1, + const Vec &v2, + const Vec &p) +{ + Vec nearest = v0; + typename Vec::BaseType neardot = (v0 - p).length2(); + typename Vec::BaseType tmp = (v1 - p).length2(); + + if (tmp < neardot) + { + neardot = tmp; + nearest = v1; + } + + tmp = (v2 - p).length2(); + + if (tmp < neardot) + { + neardot = tmp; + nearest = v2; + } + + return nearest; +} + + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHVECALGO_H diff --git a/OpenEXR/include/OpenEXR/ImfAcesFile.h b/OpenEXR/include/OpenEXR/ImfAcesFile.h new file mode 100644 index 0000000..b801a86 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfAcesFile.h @@ -0,0 +1,324 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_ACES_FILE_H +#define INCLUDED_IMF_ACES_FILE_H + + +//----------------------------------------------------------------------------- +// +// ACES image file I/O. +// +// This header file declares two classes that directly support +// image file input and output according to the Academy Image +// Interchange Framework. +// +// The Academy Image Interchange file format is a subset of OpenEXR: +// +// - Images are stored as scanlines. Tiles are not allowed. +// +// - Images contain three color channels, either +// R, G, B (red, green, blue) or +// Y, RY, BY (luminance, sub-sampled chroma) +// +// - Images may optionally contain an alpha channel. +// +// - Only three compression types are allowed: +// - NO_COMPRESSION (file is not compressed) +// - PIZ_COMPRESSION (lossless) +// - B44A_COMPRESSION (lossy) +// +// - The "chromaticities" header attribute must specify +// the ACES RGB primaries and white point. +// +// class AcesOutputFile writes an OpenEXR file, enforcing the +// restrictions listed above. Pixel data supplied by application +// software must already be in the ACES RGB space. +// +// class AcesInputFile reads an OpenEXR file. Pixel data delivered +// to application software is guaranteed to be in the ACES RGB space. +// If the RGB space of the file is not the same as the ACES space, +// then the pixels are automatically converted: the pixels are +// converted to CIE XYZ, a color adaptation transform shifts the +// white point, and the result is converted to ACES RGB. +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfRgba.h" +#include "ImathVec.h" +#include "ImathBox.h" +#include "ImfThreading.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" + +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// ACES red, green, blue and white-point chromaticities. +// + +const Chromaticities & acesChromaticities (); + + +// +// ACES output file. +// + +class IMF_EXPORT AcesOutputFile +{ + public: + + //--------------------------------------------------- + // Constructor -- header is constructed by the caller + //--------------------------------------------------- + + AcesOutputFile (const std::string &name, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, + int numThreads = globalThreadCount()); + + + //---------------------------------------------------- + // Constructor -- header is constructed by the caller, + // file is opened by the caller, destructor will not + // automatically close the file. + //---------------------------------------------------- + + AcesOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, + int numThreads = globalThreadCount()); + + + //---------------------------------------------------------------- + // Constructor -- header data are explicitly specified as function + // call arguments (empty dataWindow means "same as displayWindow") + //---------------------------------------------------------------- + + AcesOutputFile (const std::string &name, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow = IMATH_NAMESPACE::Box2i(), + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, + int numThreads = globalThreadCount()); + + + //----------------------------------------------- + // Constructor -- like the previous one, but both + // the display window and the data window are + // Box2i (V2i (0, 0), V2i (width - 1, height -1)) + //----------------------------------------------- + + AcesOutputFile (const std::string &name, + int width, + int height, + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, + int numThreads = globalThreadCount()); + + + //----------- + // Destructor + //----------- + + virtual ~AcesOutputFile (); + + + //------------------------------------------------ + // Define a frame buffer as the pixel data source: + // Pixel (x, y) is at address + // + // base + x * xStride + y * yStride + // + //------------------------------------------------ + + void setFrameBuffer (const Rgba *base, + size_t xStride, + size_t yStride); + + + //------------------------------------------------- + // Write pixel data (see class Imf::OutputFile) + // The pixels are assumed to contain ACES RGB data. + //------------------------------------------------- + + void writePixels (int numScanLines = 1); + int currentScanLine () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + const IMATH_NAMESPACE::Box2i & displayWindow () const; + const IMATH_NAMESPACE::Box2i & dataWindow () const; + float pixelAspectRatio () const; + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + float screenWindowWidth () const; + LineOrder lineOrder () const; + Compression compression () const; + RgbaChannels channels () const; + + + // -------------------------------------------------------------------- + // Update the preview image (see Imf::OutputFile::updatePreviewImage()) + // -------------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba[]); + + + private: + + AcesOutputFile (const AcesOutputFile &); // not implemented + AcesOutputFile & operator = (const AcesOutputFile &); // not implemented + + class Data; + + Data * _data; +}; + + +// +// ACES input file +// + +class IMF_EXPORT AcesInputFile +{ + public: + + //------------------------------------------------------- + // Constructor -- opens the file with the specified name, + // destructor will automatically close the file. + //------------------------------------------------------- + + AcesInputFile (const std::string &name, + int numThreads = globalThreadCount()); + + + //----------------------------------------------------------- + // Constructor -- attaches the new AcesInputFile object to a + // file that has already been opened by the caller. + // Destroying the AcesInputFile object will not automatically + // close the file. + //----------------------------------------------------------- + + AcesInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int numThreads = globalThreadCount()); + + + //----------- + // Destructor + //----------- + + virtual ~AcesInputFile (); + + + //----------------------------------------------------- + // Define a frame buffer as the pixel data destination: + // Pixel (x, y) is at address + // + // base + x * xStride + y * yStride + // + //----------------------------------------------------- + + void setFrameBuffer (Rgba *base, + size_t xStride, + size_t yStride); + + + //-------------------------------------------- + // Read pixel data (see class Imf::InputFile) + // Pixels returned will contain ACES RGB data. + //-------------------------------------------- + + void readPixels (int scanLine1, int scanLine2); + void readPixels (int scanLine); + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + const IMATH_NAMESPACE::Box2i & displayWindow () const; + const IMATH_NAMESPACE::Box2i & dataWindow () const; + float pixelAspectRatio () const; + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + float screenWindowWidth () const; + LineOrder lineOrder () const; + Compression compression () const; + RgbaChannels channels () const; + const char * fileName () const; + bool isComplete () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + private: + + AcesInputFile (const AcesInputFile &); // not implemented + AcesInputFile & operator = (const AcesInputFile &); // not implemented + + class Data; + + Data * _data; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfArray.h b/OpenEXR/include/OpenEXR/ImfArray.h new file mode 100644 index 0000000..6a80d8f --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfArray.h @@ -0,0 +1,285 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_ARRAY_H +#define INCLUDED_IMF_ARRAY_H + +#include "ImfForward.h" + +//------------------------------------------------------------------------- +// +// class Array +// class Array2D +// +// "Arrays of T" whose sizes are not known at compile time. +// When an array goes out of scope, its elements are automatically +// deleted. +// +// Usage example: +// +// struct C +// { +// C () {std::cout << "C::C (" << this << ")\n";}; +// virtual ~C () {std::cout << "C::~C (" << this << ")\n";}; +// }; +// +// int +// main () +// { +// Array a(3); +// +// C &b = a[1]; +// const C &c = a[1]; +// C *d = a + 2; +// const C *e = a; +// +// return 0; +// } +// +//------------------------------------------------------------------------- + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +template +class Array +{ + public: + + //----------------------------- + // Constructors and destructors + //----------------------------- + + Array () {_data = 0; _size = 0;} + Array (long size) {_data = new T[size]; _size = size;} + ~Array () {delete [] _data;} + + + //----------------------------- + // Access to the array elements + //----------------------------- + + operator T * () {return _data;} + operator const T * () const {return _data;} + + + //------------------------------------------------------ + // Resize and clear the array (the contents of the array + // are not preserved across the resize operation). + // + // resizeEraseUnsafe() is more memory efficient than + // resizeErase() because it deletes the old memory block + // before allocating a new one, but if allocating the + // new block throws an exception, resizeEraseUnsafe() + // leaves the array in an unusable state. + // + //------------------------------------------------------ + + void resizeErase (long size); + void resizeEraseUnsafe (long size); + + + //------------------------------- + // Return the size of this array. + //------------------------------- + + long size() const {return _size;} + + + private: + + Array (const Array &); // Copying and assignment + Array & operator = (const Array &); // are not implemented + + long _size; + T * _data; +}; + + +template +class Array2D +{ + public: + + //----------------------------- + // Constructors and destructors + //----------------------------- + + Array2D (); // empty array, 0 by 0 elements + Array2D (long sizeX, long sizeY); // sizeX by sizeY elements + ~Array2D (); + + + //----------------------------- + // Access to the array elements + //----------------------------- + + T * operator [] (long x); + const T * operator [] (long x) const; + + + //------------------------------------------------------ + // Resize and clear the array (the contents of the array + // are not preserved across the resize operation). + // + // resizeEraseUnsafe() is more memory efficient than + // resizeErase() because it deletes the old memory block + // before allocating a new one, but if allocating the + // new block throws an exception, resizeEraseUnsafe() + // leaves the array in an unusable state. + // + //------------------------------------------------------ + + void resizeErase (long sizeX, long sizeY); + void resizeEraseUnsafe (long sizeX, long sizeY); + + + //------------------------------- + // Return the size of this array. + //------------------------------- + + long height() const {return _sizeX;} + long width() const {return _sizeY;} + + + private: + + Array2D (const Array2D &); // Copying and assignment + Array2D & operator = (const Array2D &); // are not implemented + + long _sizeX; + long _sizeY; + T * _data; +}; + + +//--------------- +// Implementation +//--------------- + +template +inline void +Array::resizeErase (long size) +{ + T *tmp = new T[size]; + delete [] _data; + _size = size; + _data = tmp; +} + + +template +inline void +Array::resizeEraseUnsafe (long size) +{ + delete [] _data; + _data = 0; + _size = 0; + _data = new T[size]; + _size = size; +} + + +template +inline +Array2D::Array2D (): + _sizeX(0), _sizeY (0), _data (0) +{ + // emtpy +} + + +template +inline +Array2D::Array2D (long sizeX, long sizeY): + _sizeX (sizeX), _sizeY (sizeY), _data (new T[sizeX * sizeY]) +{ + // emtpy +} + + +template +inline +Array2D::~Array2D () +{ + delete [] _data; +} + + +template +inline T * +Array2D::operator [] (long x) +{ + return _data + x * _sizeY; +} + + +template +inline const T * +Array2D::operator [] (long x) const +{ + return _data + x * _sizeY; +} + + +template +inline void +Array2D::resizeErase (long sizeX, long sizeY) +{ + T *tmp = new T[sizeX * sizeY]; + delete [] _data; + _sizeX = sizeX; + _sizeY = sizeY; + _data = tmp; +} + + +template +inline void +Array2D::resizeEraseUnsafe (long sizeX, long sizeY) +{ + delete [] _data; + _data = 0; + _sizeX = 0; + _sizeY = 0; + _data = new T[sizeX * sizeY]; + _sizeX = sizeX; + _sizeY = sizeY; +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfAttribute.h b/OpenEXR/include/OpenEXR/ImfAttribute.h new file mode 100644 index 0000000..86762ad --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfAttribute.h @@ -0,0 +1,407 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_ATTRIBUTE_H +#define INCLUDED_IMF_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class Attribute +// +//----------------------------------------------------------------------------- + +#include "IexBaseExc.h" +#include "ImfIO.h" +#include "ImfXdr.h" +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT Attribute +{ + public: + + //--------------------------- + // Constructor and destructor + //--------------------------- + + Attribute (); + virtual ~Attribute (); + + + //------------------------------- + // Get this attribute's type name + //------------------------------- + + virtual const char * typeName () const = 0; + + + //------------------------------ + // Make a copy of this attribute + //------------------------------ + + virtual Attribute * copy () const = 0; + + + //---------------------------------------- + // Type-specific attribute I/O and copying + //---------------------------------------- + + virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const = 0; + + virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version) = 0; + + virtual void copyValueFrom (const Attribute &other) = 0; + + + //------------------ + // Attribute factory + //------------------ + + static Attribute * newAttribute (const char typeName[]); + + + //----------------------------------------------------------- + // Test if a given attribute type has already been registered + //----------------------------------------------------------- + + static bool knownType (const char typeName[]); + + + protected: + + //-------------------------------------------------- + // Register an attribute type so that newAttribute() + // knows how to make objects of this type. + //-------------------------------------------------- + + static void registerAttributeType (const char typeName[], + Attribute *(*newAttribute)()); + + //------------------------------------------------------ + // Un-register an attribute type so that newAttribute() + // no longer knows how to make objects of this type (for + // debugging only). + //------------------------------------------------------ + + static void unRegisterAttributeType (const char typeName[]); +}; + + +//------------------------------------------------- +// Class template for attributes of a specific type +//------------------------------------------------- + +template +class TypedAttribute: public Attribute +{ + public: + + //---------------------------- + // Constructors and destructor + //------------_--------------- + + TypedAttribute (); + TypedAttribute (const T &value); + TypedAttribute (const TypedAttribute &other); + virtual ~TypedAttribute (); + + + //-------------------------------- + // Access to the attribute's value + //-------------------------------- + + T & value (); + const T & value () const; + + + //-------------------------------- + // Get this attribute's type name. + //-------------------------------- + + virtual const char * typeName () const; + + + //--------------------------------------------------------- + // Static version of typeName() + // This function must be specialized for each value type T. + //--------------------------------------------------------- + + static const char * staticTypeName (); + + + //--------------------- + // Make a new attribute + //--------------------- + + static Attribute * makeNewAttribute (); + + + //------------------------------ + // Make a copy of this attribute + //------------------------------ + + virtual Attribute * copy () const; + + + //----------------------------------------------------------------- + // Type-specific attribute I/O and copying. + // Depending on type T, these functions may have to be specialized. + //----------------------------------------------------------------- + + virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const; + + virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version); + + virtual void copyValueFrom (const Attribute &other); + + + //------------------------------------------------------------ + // Dynamic casts that throw exceptions instead of returning 0. + //------------------------------------------------------------ + + static TypedAttribute * cast (Attribute *attribute); + static const TypedAttribute * cast (const Attribute *attribute); + static TypedAttribute & cast (Attribute &attribute); + static const TypedAttribute & cast (const Attribute &attribute); + + + //--------------------------------------------------------------- + // Register this attribute type so that Attribute::newAttribute() + // knows how to make objects of this type. + // + // Note that this function is not thread-safe because it modifies + // a global variable in the IlmIlm library. A thread in a multi- + // threaded program may call registerAttributeType() only when no + // other thread is accessing any functions or classes in the + // IlmImf library. + // + //--------------------------------------------------------------- + + static void registerAttributeType (); + + + //----------------------------------------------------- + // Un-register this attribute type (for debugging only) + //----------------------------------------------------- + + static void unRegisterAttributeType (); + + + private: + + T _value; +}; + +//------------------------------------ +// Implementation of TypedAttribute +//------------------------------------ +template +TypedAttribute::TypedAttribute (): + Attribute (), + _value (T()) +{ + // empty +} + + +template +TypedAttribute::TypedAttribute (const T & value): + Attribute (), + _value (value) +{ + // empty +} + + +template +TypedAttribute::TypedAttribute (const TypedAttribute &other): + Attribute (other), + _value () +{ + copyValueFrom (other); +} + + +template +TypedAttribute::~TypedAttribute () +{ + // empty +} + + +template +inline T & +TypedAttribute::value () +{ + return _value; +} + + +template +inline const T & +TypedAttribute::value () const +{ + return _value; +} + + +template +const char * +TypedAttribute::typeName () const +{ + return staticTypeName(); +} + + +template +Attribute * +TypedAttribute::makeNewAttribute () +{ + return new TypedAttribute(); +} + + +template +Attribute * +TypedAttribute::copy () const +{ + Attribute * attribute = new TypedAttribute(); + attribute->copyValueFrom (*this); + return attribute; +} + + +template +void +TypedAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const +{ + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, _value); +} + + +template +void +TypedAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version) +{ + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, _value); +} + + +template +void +TypedAttribute::copyValueFrom (const Attribute &other) +{ + _value = cast(other)._value; +} + + +template +TypedAttribute * +TypedAttribute::cast (Attribute *attribute) +{ + TypedAttribute *t = + dynamic_cast *> (attribute); + + if (t == 0) + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); + + return t; +} + + +template +const TypedAttribute * +TypedAttribute::cast (const Attribute *attribute) +{ + const TypedAttribute *t = + dynamic_cast *> (attribute); + + if (t == 0) + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); + + return t; +} + + +template +inline TypedAttribute & +TypedAttribute::cast (Attribute &attribute) +{ + return *cast (&attribute); +} + + +template +inline const TypedAttribute & +TypedAttribute::cast (const Attribute &attribute) +{ + return *cast (&attribute); +} + + +template +inline void +TypedAttribute::registerAttributeType () +{ + Attribute::registerAttributeType (staticTypeName(), makeNewAttribute); +} + + +template +inline void +TypedAttribute::unRegisterAttributeType () +{ + Attribute::unRegisterAttributeType (staticTypeName()); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfB44Compressor.h b/OpenEXR/include/OpenEXR/ImfB44Compressor.h new file mode 100644 index 0000000..5c381c1 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfB44Compressor.h @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_B44_COMPRESSOR_H +#define INCLUDED_IMF_B44_COMPRESSOR_H + +//----------------------------------------------------------------------------- +// +// class B44Compressor -- lossy compression of 4x4 pixel blocks +// +//----------------------------------------------------------------------------- + +#include "ImfCompressor.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT B44Compressor: public Compressor +{ + public: + + B44Compressor (const Header &hdr, + size_t maxScanLineSize, + size_t numScanLines, + bool optFlatFields); + + virtual ~B44Compressor (); + + virtual int numScanLines () const; + + virtual Format format () const; + + virtual int compress (const char *inPtr, + int inSize, + int minY, + const char *&outPtr); + + virtual int compressTile (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + virtual int uncompress (const char *inPtr, + int inSize, + int minY, + const char *&outPtr); + + virtual int uncompressTile (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + private: + + struct ChannelData; + + int compress (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + int uncompress (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + int _maxScanLineSize; + bool _optFlatFields; + Format _format; + int _numScanLines; + unsigned short * _tmpBuffer; + char * _outBuffer; + int _numChans; + const ChannelList & _channels; + ChannelData * _channelData; + int _minX; + int _maxX; + int _maxY; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfBoxAttribute.h b/OpenEXR/include/OpenEXR/ImfBoxAttribute.h new file mode 100644 index 0000000..7bf2585 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfBoxAttribute.h @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_BOX_ATTRIBUTE_H +#define INCLUDED_IMF_BOX_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class Box2iAttribute +// class Box2fAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfAttribute.h" +#include "ImathBox.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute Box2iAttribute; + +template <> +IMF_EXPORT +const char *Box2iAttribute::staticTypeName (); +template <> +IMF_EXPORT +void Box2iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; +template <> +IMF_EXPORT +void Box2iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +typedef TypedAttribute Box2fAttribute; +template <> +IMF_EXPORT +const char *Box2fAttribute::staticTypeName (); +template <> +IMF_EXPORT +void Box2fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; +template <> +IMF_EXPORT +void Box2fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfCRgbaFile.h b/OpenEXR/include/OpenEXR/ImfCRgbaFile.h new file mode 100644 index 0000000..5ac2bf8 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfCRgbaFile.h @@ -0,0 +1,555 @@ +/* + +Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +Digital Ltd. LLC + +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 Industrial Light & Magic 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_IMF_C_RGBA_FILE_H +#define INCLUDED_IMF_C_RGBA_FILE_H + +#include "ImfExport.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Interpreting unsigned shorts as 16-bit floating point numbers +*/ + +typedef unsigned short ImfHalf; + +IMF_EXPORT +void ImfFloatToHalf (float f, + ImfHalf *h); + +IMF_EXPORT +void ImfFloatToHalfArray (int n, + const float f[/*n*/], + ImfHalf h[/*n*/]); + +IMF_EXPORT +float ImfHalfToFloat (ImfHalf h); + +IMF_EXPORT +void ImfHalfToFloatArray (int n, + const ImfHalf h[/*n*/], + float f[/*n*/]); + +/* +** RGBA pixel; memory layout must be the same as struct Imf::Rgba. +*/ + +struct ImfRgba +{ + ImfHalf r; + ImfHalf g; + ImfHalf b; + ImfHalf a; +}; + +typedef struct ImfRgba ImfRgba; + +/* +** Magic number; this must be the same as Imf::MAGIC +*/ + +#define IMF_MAGIC 20000630 + +/* +** Version number; this must be the same as Imf::EXR_VERSION +*/ + +#define IMF_VERSION_NUMBER 2 + +/* +** Line order; values must the the same as in Imf::LineOrder. +*/ + +#define IMF_INCREASING_Y 0 +#define IMF_DECREASING_Y 1 +#define IMF_RAMDOM_Y 2 + + +/* +** Compression types; values must be the same as in Imf::Compression. +*/ + +#define IMF_NO_COMPRESSION 0 +#define IMF_RLE_COMPRESSION 1 +#define IMF_ZIPS_COMPRESSION 2 +#define IMF_ZIP_COMPRESSION 3 +#define IMF_PIZ_COMPRESSION 4 +#define IMF_PXR24_COMPRESSION 5 +#define IMF_B44_COMPRESSION 6 +#define IMF_B44A_COMPRESSION 7 + + +/* +** Channels; values must be the same as in Imf::RgbaChannels. +*/ + +#define IMF_WRITE_R 0x01 +#define IMF_WRITE_G 0x02 +#define IMF_WRITE_B 0x04 +#define IMF_WRITE_A 0x08 +#define IMF_WRITE_Y 0x10 +#define IMF_WRITE_C 0x20 +#define IMF_WRITE_RGB 0x07 +#define IMF_WRITE_RGBA 0x0f +#define IMF_WRITE_YC 0x30 +#define IMF_WRITE_YA 0x18 +#define IMF_WRITE_YCA 0x38 + + +/* +** Level modes; values must be the same as in Imf::LevelMode +*/ + +#define IMF_ONE_LEVEL 0 +#define IMF_MIPMAP_LEVELS 1 +#define IMF_RIPMAP_LEVELS 2 + + +/* +** Level rounding modes; values must be the same as in Imf::LevelRoundingMode +*/ + +#define IMF_ROUND_DOWN 0 +#define IMF_ROUND_UP 1 + + +/* +** RGBA file header +*/ + +struct ImfHeader; +typedef struct ImfHeader ImfHeader; + +IMF_EXPORT +ImfHeader * ImfNewHeader (void); + +IMF_EXPORT +void ImfDeleteHeader (ImfHeader *hdr); + +IMF_EXPORT +ImfHeader * ImfCopyHeader (const ImfHeader *hdr); + +IMF_EXPORT +void ImfHeaderSetDisplayWindow (ImfHeader *hdr, + int xMin, int yMin, + int xMax, int yMax); + +IMF_EXPORT +void ImfHeaderDisplayWindow (const ImfHeader *hdr, + int *xMin, int *yMin, + int *xMax, int *yMax); + +IMF_EXPORT +void ImfHeaderSetDataWindow (ImfHeader *hdr, + int xMin, int yMin, + int xMax, int yMax); + +IMF_EXPORT +void ImfHeaderDataWindow (const ImfHeader *hdr, + int *xMin, int *yMin, + int *xMax, int *yMax); + +IMF_EXPORT +void ImfHeaderSetPixelAspectRatio (ImfHeader *hdr, + float pixelAspectRatio); + +IMF_EXPORT +float ImfHeaderPixelAspectRatio (const ImfHeader *hdr); + +IMF_EXPORT +void ImfHeaderSetScreenWindowCenter (ImfHeader *hdr, + float x, float y); + +IMF_EXPORT +void ImfHeaderScreenWindowCenter (const ImfHeader *hdr, + float *x, float *y); + +IMF_EXPORT +void ImfHeaderSetScreenWindowWidth (ImfHeader *hdr, + float width); + +IMF_EXPORT +float ImfHeaderScreenWindowWidth (const ImfHeader *hdr); + +IMF_EXPORT +void ImfHeaderSetLineOrder (ImfHeader *hdr, + int lineOrder); + +IMF_EXPORT +int ImfHeaderLineOrder (const ImfHeader *hdr); + +IMF_EXPORT +void ImfHeaderSetCompression (ImfHeader *hdr, + int compression); + +IMF_EXPORT +int ImfHeaderCompression (const ImfHeader *hdr); + +IMF_EXPORT +int ImfHeaderSetIntAttribute (ImfHeader *hdr, + const char name[], + int value); + +IMF_EXPORT +int ImfHeaderIntAttribute (const ImfHeader *hdr, + const char name[], + int *value); + +IMF_EXPORT +int ImfHeaderSetFloatAttribute (ImfHeader *hdr, + const char name[], + float value); + +IMF_EXPORT +int ImfHeaderSetDoubleAttribute (ImfHeader *hdr, + const char name[], + double value); + +IMF_EXPORT +int ImfHeaderFloatAttribute (const ImfHeader *hdr, + const char name[], + float *value); + +IMF_EXPORT +int ImfHeaderDoubleAttribute (const ImfHeader *hdr, + const char name[], + double *value); + +IMF_EXPORT +int ImfHeaderSetStringAttribute (ImfHeader *hdr, + const char name[], + const char value[]); + +IMF_EXPORT +int ImfHeaderStringAttribute (const ImfHeader *hdr, + const char name[], + const char **value); + +IMF_EXPORT +int ImfHeaderSetBox2iAttribute (ImfHeader *hdr, + const char name[], + int xMin, int yMin, + int xMax, int yMax); + +IMF_EXPORT +int ImfHeaderBox2iAttribute (const ImfHeader *hdr, + const char name[], + int *xMin, int *yMin, + int *xMax, int *yMax); + +IMF_EXPORT +int ImfHeaderSetBox2fAttribute (ImfHeader *hdr, + const char name[], + float xMin, float yMin, + float xMax, float yMax); + +IMF_EXPORT +int ImfHeaderBox2fAttribute (const ImfHeader *hdr, + const char name[], + float *xMin, float *yMin, + float *xMax, float *yMax); + +IMF_EXPORT +int ImfHeaderSetV2iAttribute (ImfHeader *hdr, + const char name[], + int x, int y); + +IMF_EXPORT +int ImfHeaderV2iAttribute (const ImfHeader *hdr, + const char name[], + int *x, int *y); + +IMF_EXPORT +int ImfHeaderSetV2fAttribute (ImfHeader *hdr, + const char name[], + float x, float y); + +IMF_EXPORT +int ImfHeaderV2fAttribute (const ImfHeader *hdr, + const char name[], + float *x, float *y); + +IMF_EXPORT +int ImfHeaderSetV3iAttribute (ImfHeader *hdr, + const char name[], + int x, int y, int z); + +IMF_EXPORT +int ImfHeaderV3iAttribute (const ImfHeader *hdr, + const char name[], + int *x, int *y, int *z); + +IMF_EXPORT +int ImfHeaderSetV3fAttribute (ImfHeader *hdr, + const char name[], + float x, float y, float z); + +IMF_EXPORT +int ImfHeaderV3fAttribute (const ImfHeader *hdr, + const char name[], + float *x, float *y, float *z); + +IMF_EXPORT +int ImfHeaderSetM33fAttribute (ImfHeader *hdr, + const char name[], + const float m[3][3]); + +IMF_EXPORT +int ImfHeaderM33fAttribute (const ImfHeader *hdr, + const char name[], + float m[3][3]); + +IMF_EXPORT +int ImfHeaderSetM44fAttribute (ImfHeader *hdr, + const char name[], + const float m[4][4]); + +IMF_EXPORT +int ImfHeaderM44fAttribute (const ImfHeader *hdr, + const char name[], + float m[4][4]); + +/* +** RGBA output file +*/ + +struct ImfOutputFile; +typedef struct ImfOutputFile ImfOutputFile; + +IMF_EXPORT +ImfOutputFile * ImfOpenOutputFile (const char name[], + const ImfHeader *hdr, + int channels); + +IMF_EXPORT +int ImfCloseOutputFile (ImfOutputFile *out); + +IMF_EXPORT +int ImfOutputSetFrameBuffer (ImfOutputFile *out, + const ImfRgba *base, + size_t xStride, + size_t yStride); + +IMF_EXPORT +int ImfOutputWritePixels (ImfOutputFile *out, + int numScanLines); + +IMF_EXPORT +int ImfOutputCurrentScanLine (const ImfOutputFile *out); + +IMF_EXPORT +const ImfHeader * ImfOutputHeader (const ImfOutputFile *out); + +IMF_EXPORT +int ImfOutputChannels (const ImfOutputFile *out); + + +/* +** Tiled RGBA output file +*/ + +struct ImfTiledOutputFile; +typedef struct ImfTiledOutputFile ImfTiledOutputFile; + +IMF_EXPORT +ImfTiledOutputFile * ImfOpenTiledOutputFile (const char name[], + const ImfHeader *hdr, + int channels, + int xSize, int ySize, + int mode, int rmode); + +IMF_EXPORT +int ImfCloseTiledOutputFile (ImfTiledOutputFile *out); + +IMF_EXPORT +int ImfTiledOutputSetFrameBuffer (ImfTiledOutputFile *out, + const ImfRgba *base, + size_t xStride, + size_t yStride); + +IMF_EXPORT +int ImfTiledOutputWriteTile (ImfTiledOutputFile *out, + int dx, int dy, + int lx, int ly); + +IMF_EXPORT +int ImfTiledOutputWriteTiles (ImfTiledOutputFile *out, + int dxMin, int dxMax, + int dyMin, int dyMax, + int lx, int ly); + +IMF_EXPORT +const ImfHeader * ImfTiledOutputHeader (const ImfTiledOutputFile *out); + +IMF_EXPORT +int ImfTiledOutputChannels (const ImfTiledOutputFile *out); + +IMF_EXPORT +int ImfTiledOutputTileXSize (const ImfTiledOutputFile *out); + +IMF_EXPORT +int ImfTiledOutputTileYSize (const ImfTiledOutputFile *out); + +IMF_EXPORT +int ImfTiledOutputLevelMode (const ImfTiledOutputFile *out); + +IMF_EXPORT +int ImfTiledOutputLevelRoundingMode + (const ImfTiledOutputFile *out); + + +/* +** RGBA input file +*/ + +struct ImfInputFile; +typedef struct ImfInputFile ImfInputFile; + +ImfInputFile * ImfOpenInputFile (const char name[]); + +IMF_EXPORT +int ImfCloseInputFile (ImfInputFile *in); + +IMF_EXPORT +int ImfInputSetFrameBuffer (ImfInputFile *in, + ImfRgba *base, + size_t xStride, + size_t yStride); + +IMF_EXPORT +int ImfInputReadPixels (ImfInputFile *in, + int scanLine1, + int scanLine2); + +IMF_EXPORT +const ImfHeader * ImfInputHeader (const ImfInputFile *in); + +IMF_EXPORT +int ImfInputChannels (const ImfInputFile *in); + +IMF_EXPORT +const char * ImfInputFileName (const ImfInputFile *in); + + +/* +** Tiled RGBA input file +*/ + +struct ImfTiledInputFile; +typedef struct ImfTiledInputFile ImfTiledInputFile; + +IMF_EXPORT +ImfTiledInputFile * ImfOpenTiledInputFile (const char name[]); + +IMF_EXPORT +int ImfCloseTiledInputFile (ImfTiledInputFile *in); + +IMF_EXPORT +int ImfTiledInputSetFrameBuffer (ImfTiledInputFile *in, + ImfRgba *base, + size_t xStride, + size_t yStride); + +IMF_EXPORT +int ImfTiledInputReadTile (ImfTiledInputFile *in, + int dx, int dy, + int lx, int ly); + +IMF_EXPORT +int ImfTiledInputReadTiles (ImfTiledInputFile *in, + int dxMin, int dxMax, + int dyMin, int dyMax, + int lx, int ly); + +IMF_EXPORT +const ImfHeader * ImfTiledInputHeader (const ImfTiledInputFile *in); + +IMF_EXPORT +int ImfTiledInputChannels (const ImfTiledInputFile *in); + +IMF_EXPORT +const char * ImfTiledInputFileName (const ImfTiledInputFile *in); + +IMF_EXPORT +int ImfTiledInputTileXSize (const ImfTiledInputFile *in); + +IMF_EXPORT +int ImfTiledInputTileYSize (const ImfTiledInputFile *in); + +IMF_EXPORT +int ImfTiledInputLevelMode (const ImfTiledInputFile *in); + +IMF_EXPORT +int ImfTiledInputLevelRoundingMode + (const ImfTiledInputFile *in); + +/* +** Lookup tables +*/ + +struct ImfLut; +typedef struct ImfLut ImfLut; + +IMF_EXPORT +ImfLut * ImfNewRound12logLut (int channels); + +IMF_EXPORT +ImfLut * ImfNewRoundNBitLut (unsigned int n, int channels); + +IMF_EXPORT +void ImfDeleteLut (ImfLut *lut); + +IMF_EXPORT +void ImfApplyLut (ImfLut *lut, + ImfRgba *data, + int nData, + int stride); +/* +** Most recent error message +*/ + +IMF_EXPORT +const char * ImfErrorMessage (void); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfChannelList.h b/OpenEXR/include/OpenEXR/ImfChannelList.h new file mode 100644 index 0000000..fc31a15 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfChannelList.h @@ -0,0 +1,436 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_CHANNEL_LIST_H +#define INCLUDED_IMF_CHANNEL_LIST_H + +//----------------------------------------------------------------------------- +// +// class Channel +// class ChannelList +// +//----------------------------------------------------------------------------- + +#include "ImfName.h" +#include "ImfPixelType.h" + +#include "ImfNamespace.h" +#include "ImfExport.h" + +#include +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct IMF_EXPORT Channel +{ + //------------------------------ + // Data type; see ImfPixelType.h + //------------------------------ + + PixelType type; + + + //-------------------------------------------- + // Subsampling: pixel (x, y) is present in the + // channel only if + // + // x % xSampling == 0 && y % ySampling == 0 + // + //-------------------------------------------- + + int xSampling; + int ySampling; + + + //-------------------------------------------------------------- + // Hint to lossy compression methods that indicates whether + // human perception of the quantity represented by this channel + // is closer to linear or closer to logarithmic. Compression + // methods may optimize image quality by adjusting pixel data + // quantization acording to this hint. + // For example, perception of red, green, blue and luminance is + // approximately logarithmic; the difference between 0.1 and 0.2 + // is perceived to be roughly the same as the difference between + // 1.0 and 2.0. Perception of chroma coordinates tends to be + // closer to linear than logarithmic; the difference between 0.1 + // and 0.2 is perceived to be roughly the same as the difference + // between 1.0 and 1.1. + //-------------------------------------------------------------- + + bool pLinear; + + + //------------ + // Constructor + //------------ + + Channel (PixelType type = HALF, + int xSampling = 1, + int ySampling = 1, + bool pLinear = false); + + + //------------ + // Operator == + //------------ + + bool operator == (const Channel &other) const; +}; + + +class IMF_EXPORT ChannelList +{ + public: + + //-------------- + // Add a channel + //-------------- + + void insert (const char name[], + const Channel &channel); + + void insert (const std::string &name, + const Channel &channel); + + //------------------------------------------------------------------ + // Access to existing channels: + // + // [n] Returns a reference to the channel with name n. + // If no channel with name n exists, an IEX_NAMESPACE::ArgExc + // is thrown. + // + // findChannel(n) Returns a pointer to the channel with name n, + // or 0 if no channel with name n exists. + // + //------------------------------------------------------------------ + + Channel & operator [] (const char name[]); + const Channel & operator [] (const char name[]) const; + + Channel & operator [] (const std::string &name); + const Channel & operator [] (const std::string &name) const; + + Channel * findChannel (const char name[]); + const Channel * findChannel (const char name[]) const; + + Channel * findChannel (const std::string &name); + const Channel * findChannel (const std::string &name) const; + + + //------------------------------------------- + // Iterator-style access to existing channels + //------------------------------------------- + + typedef std::map ChannelMap; + + class Iterator; + class ConstIterator; + + Iterator begin (); + ConstIterator begin () const; + + Iterator end (); + ConstIterator end () const; + + Iterator find (const char name[]); + ConstIterator find (const char name[]) const; + + Iterator find (const std::string &name); + ConstIterator find (const std::string &name) const; + + + //----------------------------------------------------------------- + // Support for image layers: + // + // In an image file with many channels it is sometimes useful to + // group the channels into "layers", that is, into sets of channels + // that logically belong together. Grouping channels into layers + // is done using a naming convention: channel C in layer L is + // called "L.C". + // + // For example, a computer graphic image may contain separate + // R, G and B channels for light that originated at each of + // several different virtual light sources. The channels in + // this image might be called "light1.R", "light1.G", "light1.B", + // "light2.R", "light2.G", "light2.B", etc. + // + // Note that this naming convention allows layers to be nested; + // for example, "light1.specular.R" identifies the "R" channel + // in the "specular" sub-layer of layer "light1". + // + // Channel names that don't contain a "." or that contain a + // "." only at the beginning or at the end are not considered + // to be part of any layer. + // + // layers(lns) sorts the channels in this ChannelList + // into layers and stores the names of + // all layers, sorted alphabetically, + // into string set lns. + // + // channelsInLayer(ln,f,l) stores a pair of iterators in f and l + // such that the loop + // + // for (ConstIterator i = f; i != l; ++i) + // ... + // + // iterates over all channels in layer ln. + // channelsInLayer (ln, l, p) calls + // channelsWithPrefix (ln + ".", l, p). + // + //----------------------------------------------------------------- + + void layers (std::set &layerNames) const; + + void channelsInLayer (const std::string &layerName, + Iterator &first, + Iterator &last); + + void channelsInLayer (const std::string &layerName, + ConstIterator &first, + ConstIterator &last) const; + + + //------------------------------------------------------------------- + // Find all channels whose name begins with a given prefix: + // + // channelsWithPrefix(p,f,l) stores a pair of iterators in f and l + // such that the following loop iterates over all channels whose name + // begins with string p: + // + // for (ConstIterator i = f; i != l; ++i) + // ... + // + //------------------------------------------------------------------- + + void channelsWithPrefix (const char prefix[], + Iterator &first, + Iterator &last); + + void channelsWithPrefix (const char prefix[], + ConstIterator &first, + ConstIterator &last) const; + + void channelsWithPrefix (const std::string &prefix, + Iterator &first, + Iterator &last); + + void channelsWithPrefix (const std::string &prefix, + ConstIterator &first, + ConstIterator &last) const; + + //------------ + // Operator == + //------------ + + bool operator == (const ChannelList &other) const; + + private: + + ChannelMap _map; +}; + + +//---------- +// Iterators +//---------- + +class ChannelList::Iterator +{ + public: + + Iterator (); + Iterator (const ChannelList::ChannelMap::iterator &i); + + Iterator & operator ++ (); + Iterator operator ++ (int); + + const char * name () const; + Channel & channel () const; + + private: + + friend class ChannelList::ConstIterator; + + ChannelList::ChannelMap::iterator _i; +}; + + +class ChannelList::ConstIterator +{ + public: + + ConstIterator (); + ConstIterator (const ChannelList::ChannelMap::const_iterator &i); + ConstIterator (const ChannelList::Iterator &other); + + ConstIterator & operator ++ (); + ConstIterator operator ++ (int); + + const char * name () const; + const Channel & channel () const; + + private: + + friend bool operator == (const ConstIterator &, const ConstIterator &); + friend bool operator != (const ConstIterator &, const ConstIterator &); + + ChannelList::ChannelMap::const_iterator _i; +}; + + +//----------------- +// Inline Functions +//----------------- + +inline +ChannelList::Iterator::Iterator (): _i() +{ + // empty +} + + +inline +ChannelList::Iterator::Iterator (const ChannelList::ChannelMap::iterator &i): + _i (i) +{ + // empty +} + + +inline ChannelList::Iterator & +ChannelList::Iterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline ChannelList::Iterator +ChannelList::Iterator::operator ++ (int) +{ + Iterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +ChannelList::Iterator::name () const +{ + return *_i->first; +} + + +inline Channel & +ChannelList::Iterator::channel () const +{ + return _i->second; +} + + +inline +ChannelList::ConstIterator::ConstIterator (): _i() +{ + // empty +} + +inline +ChannelList::ConstIterator::ConstIterator + (const ChannelList::ChannelMap::const_iterator &i): _i (i) +{ + // empty +} + + +inline +ChannelList::ConstIterator::ConstIterator (const ChannelList::Iterator &other): + _i (other._i) +{ + // empty +} + +inline ChannelList::ConstIterator & +ChannelList::ConstIterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline ChannelList::ConstIterator +ChannelList::ConstIterator::operator ++ (int) +{ + ConstIterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +ChannelList::ConstIterator::name () const +{ + return *_i->first; +} + +inline const Channel & +ChannelList::ConstIterator::channel () const +{ + return _i->second; +} + + +inline bool +operator == (const ChannelList::ConstIterator &x, + const ChannelList::ConstIterator &y) +{ + return x._i == y._i; +} + + +inline bool +operator != (const ChannelList::ConstIterator &x, + const ChannelList::ConstIterator &y) +{ + return !(x == y); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfChannelListAttribute.h b/OpenEXR/include/OpenEXR/ImfChannelListAttribute.h new file mode 100644 index 0000000..60d8907 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfChannelListAttribute.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_CHANNEL_LIST_ATTRIBUTE_H +#define INCLUDED_IMF_CHANNEL_LIST_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class ChannelListAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfChannelList.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute ChannelListAttribute; + +template <> +IMF_EXPORT +const char *ChannelListAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void ChannelListAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void ChannelListAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif + diff --git a/OpenEXR/include/OpenEXR/ImfChromaticities.h b/OpenEXR/include/OpenEXR/ImfChromaticities.h new file mode 100644 index 0000000..9af4769 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfChromaticities.h @@ -0,0 +1,131 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_CHROMATICITIES_H +#define INCLUDED_IMF_CHROMATICITIES_H + +//----------------------------------------------------------------------------- +// +// CIE (x,y) chromaticities, and conversions between +// RGB tiples and CIE XYZ tristimulus values. +// +//----------------------------------------------------------------------------- + +#include "ImathVec.h" +#include "ImathMatrix.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct IMF_EXPORT Chromaticities +{ + //----------------------------------------------- + // The CIE x and y coordinates of the RGB triples + // (1,0,0), (0,1,0), (0,0,1) and (1,1,1). + //----------------------------------------------- + + IMATH_NAMESPACE::V2f red; + IMATH_NAMESPACE::V2f green; + IMATH_NAMESPACE::V2f blue; + IMATH_NAMESPACE::V2f white; + + //-------------------------------------------- + // Default constructor produces chromaticities + // according to Rec. ITU-R BT.709-3 + //-------------------------------------------- + + Chromaticities (const IMATH_NAMESPACE::V2f &red = IMATH_NAMESPACE::V2f (0.6400f, 0.3300f), + const IMATH_NAMESPACE::V2f &green = IMATH_NAMESPACE::V2f (0.3000f, 0.6000f), + const IMATH_NAMESPACE::V2f &blue = IMATH_NAMESPACE::V2f (0.1500f, 0.0600f), + const IMATH_NAMESPACE::V2f &white = IMATH_NAMESPACE::V2f (0.3127f, 0.3290f)); + + + //--------- + // Equality + //--------- + + bool operator == (const Chromaticities &v) const; + bool operator != (const Chromaticities &v) const; +}; + + +// +// Conversions between RGB and CIE XYZ +// +// RGB to XYZ: +// +// Given a set of chromaticities, c, and the luminance, Y, of the RGB +// triple (1,1,1), or "white", RGBtoXYZ(c,Y) computes a matrix, M, so +// that multiplying an RGB value, v, with M produces an equivalent +// XYZ value, w. (w == v * M) +// +// If we define that +// +// (Xr, Yr, Zr) == (1, 0, 0) * M +// (Xg, Yg, Zg) == (0, 1, 0) * M +// (Xb, Yb, Zb) == (0, 0, 1) * M +// (Xw, Yw, Zw) == (1, 1, 1) * M, +// +// then the following statements are true: +// +// Xr / (Xr + Yr + Zr) == c.red.x +// Yr / (Xr + Yr + Zr) == c.red.y +// +// Xg / (Xg + Yg + Zg) == c.red.x +// Yg / (Xg + Yg + Zg) == c.red.y +// +// Xb / (Xb + Yb + Zb) == c.red.x +// Yb / (Xb + Yb + Zb) == c.red.y +// +// Xw / (Xw + Yw + Zw) == c.red.x +// Yw / (Xw + Yw + Zw) == c.red.y +// +// Yw == Y. +// +// XYZ to RGB: +// +// YYZtoRGB(c,Y) returns RGBtoXYZ(c,Y).inverse(). +// + +IMF_EXPORT IMATH_NAMESPACE::M44f RGBtoXYZ (const Chromaticities chroma, float Y); +IMF_EXPORT IMATH_NAMESPACE::M44f XYZtoRGB (const Chromaticities chroma, float Y); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfChromaticitiesAttribute.h b/OpenEXR/include/OpenEXR/ImfChromaticitiesAttribute.h new file mode 100644 index 0000000..6c0c35a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfChromaticitiesAttribute.h @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_CHROMATICITIES_ATTRIBUTE_H +#define INCLUDED_IMF_CHROMATICITIES_ATTRIBUTE_H + + +//----------------------------------------------------------------------------- +// +// class ChromaticitiesAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfChromaticities.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute ChromaticitiesAttribute; + +template <> +IMF_EXPORT +const char *ChromaticitiesAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void ChromaticitiesAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void ChromaticitiesAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, + int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfCompositeDeepScanLine.h b/OpenEXR/include/OpenEXR/ImfCompositeDeepScanLine.h new file mode 100644 index 0000000..2dc23e5 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfCompositeDeepScanLine.h @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// 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 Weta Digital 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_IMF_COMPOSITEDEEPSCANLINE_H +#define INCLUDED_IMF_COMPOSITEDEEPSCANLINE_H + +//----------------------------------------------------------------------------- +// +// Class to composite deep samples into a frame buffer +// Initialise with a deep input part or deep inputfile +// (also supports multiple files and parts, and will +// composite them together, as long as their sizes and channelmaps agree) +// +// Then call setFrameBuffer, and readPixels, exactly as for reading +// regular scanline images. +// +// Restrictions - source file(s) must contain at least Z and alpha channels +// - if multiple files/parts are provided, sizes must match +// - all requested channels will be composited as premultiplied +// - only half and float channels can be requested +// +// This object should not be considered threadsafe +// +// The default compositing engine will give spurious results with overlapping +// volumetric samples - you may derive from DeepCompositing class, override the +// sort_pixel() and composite_pixel() functions, and pass an instance to +// setCompositing(). +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT CompositeDeepScanLine +{ + public: + CompositeDeepScanLine(); + virtual ~CompositeDeepScanLine(); + + /// set the source data as a part + ///@note all parts must remain valid until after last interaction with DeepComp + void addSource(DeepScanLineInputPart * part); + + /// set the source data as a file + ///@note all file must remain valid until after last interaction with DeepComp + void addSource(DeepScanLineInputFile * file); + + + ///////////////////////////////////////// + // + // set the frame buffer for output values + // the buffers specified must be large enough + // to handle the dataWindow() + // + ///////////////////////////////////////// + void setFrameBuffer(const FrameBuffer & fr); + + + + ///////////////////////////////////////// + // + // retrieve frameBuffer + // + //////////////////////////////////////// + const FrameBuffer & frameBuffer() const; + + + ////////////////////////////////////////////////// + // + // read scanlines start to end from the source(s) + // storing the result in the frame buffer provided + // + ////////////////////////////////////////////////// + + void readPixels(int start,int end); + + int sources() const; // return number of sources + + ///////////////////////////////////////////////// + // + // retrieve the datawindow + // If multiple parts are specified, this will + // be the union of the dataWindow of all parts + // + //////////////////////////////////////////////// + + const IMATH_NAMESPACE::Box2i & dataWindow() const; + + + // + // override default sorting/compositing operation + // (otherwise an instance of the base class will be used) + // + + void setCompositing(DeepCompositing *); + + struct Data; + private : + struct Data *_Data; + + CompositeDeepScanLine(const CompositeDeepScanLine &); // not implemented + const CompositeDeepScanLine & operator=(const CompositeDeepScanLine &); // not implemented +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfCompression.h b/OpenEXR/include/OpenEXR/ImfCompression.h new file mode 100644 index 0000000..c066d34 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfCompression.h @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_COMPRESSION_H +#define INCLUDED_IMF_COMPRESSION_H + +//----------------------------------------------------------------------------- +// +// enum Compression +// +//----------------------------------------------------------------------------- +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +enum Compression +{ + NO_COMPRESSION = 0, // no compression + + RLE_COMPRESSION = 1, // run length encoding + + ZIPS_COMPRESSION = 2, // zlib compression, one scan line at a time + + ZIP_COMPRESSION = 3, // zlib compression, in blocks of 16 scan lines + + PIZ_COMPRESSION = 4, // piz-based wavelet compression + + PXR24_COMPRESSION = 5, // lossy 24-bit float compression + + B44_COMPRESSION = 6, // lossy 4-by-4 pixel block compression, + // fixed compression rate + + B44A_COMPRESSION = 7, // lossy 4-by-4 pixel block compression, + // flat fields are compressed more + + DWAA_COMPRESSION = 8, // lossy DCT based compression, in blocks + // of 32 scanlines. More efficient for partial + // buffer access. + + DWAB_COMPRESSION = 9, // lossy DCT based compression, in blocks + // of 256 scanlines. More efficient space + // wise and faster to decode full frames + // than DWAA_COMPRESSION. + + NUM_COMPRESSION_METHODS // number of different compression methods +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfCompressionAttribute.h b/OpenEXR/include/OpenEXR/ImfCompressionAttribute.h new file mode 100644 index 0000000..bfc72de --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfCompressionAttribute.h @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_COMPRESSION_ATTRIBUTE_H +#define INCLUDED_IMF_COMPRESSION_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class CompressionAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfCompression.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute CompressionAttribute; +template <> const char *CompressionAttribute::staticTypeName (); +template <> void CompressionAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; +template <> void CompressionAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, + int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfConvert.h b/OpenEXR/include/OpenEXR/ImfConvert.h new file mode 100644 index 0000000..b0a7f47 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfConvert.h @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_CONVERT_H +#define INCLUDED_IMF_CONVERT_H + +//----------------------------------------------------------------------------- +// +// Routines for converting between pixel data types, +// with well-defined behavior for exceptional cases, +// without depending on how hardware and operating +// system handle integer overflows and floating-point +// exceptions. +// +//----------------------------------------------------------------------------- + +#include "half.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +//--------------------------------------------------------- +// Conversion from half or float to unsigned int: +// +// input result +// --------------------------------------------------- +// +// finite, >= 0 input, cast to unsigned int +// (rounds towards zero) +// +// finite, < 0 0 +// +// NaN 0 +// +// +infinity UINT_MAX +// +// -infinity 0 +// +//--------------------------------------------------------- + +IMF_EXPORT unsigned int halfToUint (half h); +IMF_EXPORT unsigned int floatToUint (float f); + + +//--------------------------------------------------------- +// Conversion from unsigned int or float to half: +// +// input result +// --------------------------------------------------- +// +// finite, closest possible half +// magnitude <= HALF_MAX +// +// finite, > HALF_MAX +infinity +// +// finite, < -HALF_MAX -infinity +// +// NaN NaN +// +// +infinity +infinity +// +// -infinity -infinity +// +//--------------------------------------------------------- + +IMF_EXPORT half uintToHalf (unsigned int ui); +IMF_EXPORT half floatToHalf (float f); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepCompositing.h b/OpenEXR/include/OpenEXR/ImfDeepCompositing.h new file mode 100644 index 0000000..b400efc --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepCompositing.h @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// 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 Weta Digital 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_IMF_DEEPCOMPOSITING_H +#define INCLUDED_IMF_DEEPCOMPOSITING_H + +//----------------------------------------------------------------------------- +// +// Class to sort and composite deep samples into a frame buffer +// You may derive from this class to change the way that CompositeDeepScanLine +// and CompositeDeepTile combine samples together - pass an instance of your derived +// class to the compositing engine +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT DeepCompositing +{ + public: + DeepCompositing(); + virtual ~DeepCompositing(); + + + ////////////////////////////////////////////// + /// + /// composite together the given channels + /// + /// @param outputs - return array of pixel values - + /// @param inputs - arrays of input sample + /// @param channel_names - array of channel names for corresponding channels + /// @param num_channels - number of active channels (3 or greater) + /// @param num_samples - number of values in all input arrays + /// @param sources - number of different sources + /// + /// each array input has num_channels entries: outputs[n] should be the composited + /// values in array inputs[n], whose name will be given by channel_names[n] + /// + /// The channel ordering shall be as follows: + /// Position Channel + /// 0 Z + /// 1 ZBack (if no ZBack, then inputs[1]==inputs[0] and channel_names[1]==channel_names[0]) + /// 2 A (alpha channel) + /// 3-n other channels - only channels in the frame buffer will appear here + /// + /// since a Z and Alpha channel is required, and channel[1] is ZBack or another copy of Z + /// there will always be 3 or more channels. + /// + /// The default implementation calls sort() if and only if more than one source is active, + /// composites all samples together using the Over operator from front to back, + /// stopping as soon as a sample with alpha=1 is found + /// It also blanks all outputs if num_samples==0 + /// + /// note - multiple threads may call composite_pixel simultaneously for different pixels + /// + /// + ////////////////////////////////////////////// + virtual void composite_pixel(float outputs[], + const float * inputs[], + const char * channel_names[], + int num_channels, + int num_samples, + int sources + ); + + + + //////////////////////////////////////////////////////////////// + /// + /// find the depth order for samples with given channel values + /// does not sort the values in-place. Instead it populates + /// array 'order' with the desired sorting order + /// + /// the default operation sorts samples from front to back according to their Z channel + /// + /// @param order - required output order. order[n] shall be the nth closest sample + /// @param inputs - arrays of input samples, one array per channel_name + /// @param channel_names - array of channel names for corresponding channels + /// @param num_channels - number of channels (3 or greater) + /// @param num_samples - number of samples in each array + /// @param sources - number of different sources the data arises from + /// + /// the channel layout is identical to composite_pixel() + /// + /////////////////////////////////////////////////////////////// + + virtual void sort(int order[], + const float * inputs[], + const char * channel_names[], + int num_channels, + int num_samples, + int sources); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepFrameBuffer.h b/OpenEXR/include/OpenEXR/ImfDeepFrameBuffer.h new file mode 100644 index 0000000..8eec6ff --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepFrameBuffer.h @@ -0,0 +1,339 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFDEEPFRAMEBUFFER_H_ +#define IMFDEEPFRAMEBUFFER_H_ + +#include "ImfFrameBuffer.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//-------------------------------------------------------- +// Description of a single deep slice of the frame buffer: +//-------------------------------------------------------- + +struct IMF_EXPORT DeepSlice : public Slice +{ + //--------------------------------------------------------------------- + // The stride for each sample in this slice. + // + // Memory layout: The address of sample i in pixel (x, y) is + // + // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride + // + i * sampleStride + // + // where xp and yp are computed as follows: + // + // * If we are reading or writing a scanline-based file: + // + // xp = x + // yp = y + // + // * If we are reading a tile whose upper left coorner is at (xt, yt): + // + // if xTileCoords is true then xp = x - xt, else xp = x + // if yTileCoords is true then yp = y - yt, else yp = y + // + //--------------------------------------------------------------------- + + int sampleStride; + + //------------ + // Constructor + //------------ + DeepSlice (PixelType type = HALF, + char * base = 0, + size_t xStride = 0, + size_t yStride = 0, + size_t sampleStride = 0, + int xSampling = 1, + int ySampling = 1, + double fillValue = 0.0, + bool xTileCoords = false, + bool yTileCoords = false); +}; + +//----------------- +// DeepFrameBuffer. +//----------------- + +class IMF_EXPORT DeepFrameBuffer +{ + public: + + + //------------ + // Add a slice + //------------ + + void insert (const char name[], + const DeepSlice &slice); + + void insert (const std::string &name, + const DeepSlice &slice); + + //---------------------------------------------------------------- + // Access to existing slices: + // + // [n] Returns a reference to the slice with name n. + // If no slice with name n exists, an IEX_NAMESPACE::ArgExc + // is thrown. + // + // findSlice(n) Returns a pointer to the slice with name n, + // or 0 if no slice with name n exists. + // + //---------------------------------------------------------------- + + DeepSlice & operator [] (const char name[]); + const DeepSlice & operator [] (const char name[]) const; + + DeepSlice & operator [] (const std::string &name); + const DeepSlice & operator [] (const std::string &name) const; + + DeepSlice * findSlice (const char name[]); + const DeepSlice * findSlice (const char name[]) const; + + DeepSlice * findSlice (const std::string &name); + const DeepSlice * findSlice (const std::string &name) const; + + + //----------------------------------------- + // Iterator-style access to existing slices + //----------------------------------------- + + typedef std::map SliceMap; + + class Iterator; + class ConstIterator; + + Iterator begin (); + ConstIterator begin () const; + + Iterator end (); + ConstIterator end () const; + + Iterator find (const char name[]); + ConstIterator find (const char name[]) const; + + Iterator find (const std::string &name); + ConstIterator find (const std::string &name) const; + + //---------------------------------------------------- + // Public function for accessing a sample count slice. + //---------------------------------------------------- + + void insertSampleCountSlice(const Slice & slice); + const Slice & getSampleCountSlice() const; + + private: + + SliceMap _map; + Slice _sampleCounts; +}; + +//---------- +// Iterators +//---------- + +class DeepFrameBuffer::Iterator +{ + public: + + Iterator (); + Iterator (const DeepFrameBuffer::SliceMap::iterator &i); + + Iterator & operator ++ (); + Iterator operator ++ (int); + + const char * name () const; + DeepSlice & slice () const; + + private: + + friend class DeepFrameBuffer::ConstIterator; + + DeepFrameBuffer::SliceMap::iterator _i; +}; + + +class DeepFrameBuffer::ConstIterator +{ + public: + + ConstIterator (); + ConstIterator (const DeepFrameBuffer::SliceMap::const_iterator &i); + ConstIterator (const DeepFrameBuffer::Iterator &other); + + ConstIterator & operator ++ (); + ConstIterator operator ++ (int); + + const char * name () const; + const DeepSlice & slice () const; + + private: + + friend bool operator == (const ConstIterator &, const ConstIterator &); + friend bool operator != (const ConstIterator &, const ConstIterator &); + + DeepFrameBuffer::SliceMap::const_iterator _i; +}; + + +//----------------- +// Inline Functions +//----------------- + +inline +DeepFrameBuffer::Iterator::Iterator (): _i() +{ + // empty +} + + +inline +DeepFrameBuffer::Iterator::Iterator (const DeepFrameBuffer::SliceMap::iterator &i): + _i (i) +{ + // empty +} + + +inline DeepFrameBuffer::Iterator & +DeepFrameBuffer::Iterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline DeepFrameBuffer::Iterator +DeepFrameBuffer::Iterator::operator ++ (int) +{ + Iterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +DeepFrameBuffer::Iterator::name () const +{ + return *_i->first; +} + + +inline DeepSlice & +DeepFrameBuffer::Iterator::slice () const +{ + return _i->second; +} + + +inline +DeepFrameBuffer::ConstIterator::ConstIterator (): _i() +{ + // empty +} + +inline +DeepFrameBuffer::ConstIterator::ConstIterator + (const DeepFrameBuffer::SliceMap::const_iterator &i): _i (i) +{ + // empty +} + + +inline +DeepFrameBuffer::ConstIterator::ConstIterator (const DeepFrameBuffer::Iterator &other): + _i (other._i) +{ + // empty +} + +inline DeepFrameBuffer::ConstIterator & +DeepFrameBuffer::ConstIterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline DeepFrameBuffer::ConstIterator +DeepFrameBuffer::ConstIterator::operator ++ (int) +{ + ConstIterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +DeepFrameBuffer::ConstIterator::name () const +{ + return *_i->first; +} + +inline const DeepSlice & +DeepFrameBuffer::ConstIterator::slice () const +{ + return _i->second; +} + + +inline bool +operator == (const DeepFrameBuffer::ConstIterator &x, + const DeepFrameBuffer::ConstIterator &y) +{ + return x._i == y._i; +} + + +inline bool +operator != (const DeepFrameBuffer::ConstIterator &x, + const DeepFrameBuffer::ConstIterator &y) +{ + return !(x == y); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + + +#endif /* IMFDEEPFRAMEBUFFER_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfDeepImageState.h b/OpenEXR/include/OpenEXR/ImfDeepImageState.h new file mode 100644 index 0000000..a3941c4 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepImageState.h @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2013, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DEEPIMAGESTATE_H +#define INCLUDED_IMF_DEEPIMAGESTATE_H + +//----------------------------------------------------------------------------- +// +// enum DeepImageState -- describes how orderly the pixel data +// in a deep image are +// +// The samples in a deep image pixel may be sorted according to +// depth, and the sample depths or depth ranges may or may not +// overlap each other. A pixel is +// +// - SORTED if for every i and j with i < j +// +// (Z[i] < Z[j]) || (Z[i] == Z[j] && ZBack[i] < ZBack[j]), +// +// - NON_OVERLAPPING if for every i and j with i != j +// +// (Z[i] < Z[j] && ZBack[i] <= Z[j]) || +// (Z[j] < Z[i] && ZBack[j] <= Z[i]) || +// (Z[i] == Z[j] && ZBack[i] <= Z[i] & ZBack[j] > Z[j]) || +// (Z[i] == Z[j] && ZBack[j] <= Z[j] & ZBack[i] > Z[i]), +// +// - TIDY if it is SORTED and NON_OVERLAPPING, +// +// - MESSY if it is neither SORTED nor NON_OVERLAPPING. +// +// A deep image is +// +// - MESSY if at least one of its pixels is MESSY, +// - SORTED if all of its pixels are SORTED, +// - NON_OVERLAPPING if all of its pixels are NON_OVERLAPPING, +// - TIDY if all of its pixels are TIDY. +// +// Note: the rather complicated definition of NON_OVERLAPPING prohibits +// overlapping volume samples, coincident point samples and point samples +// in the middle of a volume sample, but it does allow point samples at +// the front or back of a volume sample. +// +//----------------------------------------------------------------------------- + +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +enum DeepImageState +{ + DIS_MESSY = 0, + DIS_SORTED = 1, + DIS_NON_OVERLAPPING = 2, + DIS_TIDY = 3, + + DIS_NUMSTATES // Number of different image states +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepImageStateAttribute.h b/OpenEXR/include/OpenEXR/ImfDeepImageStateAttribute.h new file mode 100644 index 0000000..6174e94 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepImageStateAttribute.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2013, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DEEPIMAGESTATE_ATTRIBUTE_H +#define INCLUDED_IMF_DEEPIMAGESTATE_ATTRIBUTE_H + + +//----------------------------------------------------------------------------- +// +// class DeepImageStateAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfDeepImageState.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute + DeepImageStateAttribute; + +template <> IMF_EXPORT const char *DeepImageStateAttribute::staticTypeName (); + +template <> IMF_EXPORT +void DeepImageStateAttribute::writeValueTo + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; + +template <> IMF_EXPORT +void DeepImageStateAttribute::readValueFrom + (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepScanLineInputFile.h b/OpenEXR/include/OpenEXR/ImfDeepScanLineInputFile.h new file mode 100644 index 0000000..87a4065 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepScanLineInputFile.h @@ -0,0 +1,276 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DEEP_SCAN_LINE_INPUT_FILE_H +#define INCLUDED_IMF_DEEP_SCAN_LINE_INPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepScanLineInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfDeepScanLineOutputFile.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT DeepScanLineInputFile : public GenericInputFile +{ + public: + + //------------ + // Constructor + //------------ + + DeepScanLineInputFile (const char fileName[], + int numThreads = globalThreadCount()); + + DeepScanLineInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, + int version, /*version field from file*/ + int numThreads = globalThreadCount()); + + + //----------------------------------------- + // Destructor -- deallocates internal data + // structures, but does not close the file. + //----------------------------------------- + + virtual ~DeepScanLineInputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the InputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readPixels() is called. + // The current frame buffer can be changed after each call + // to readPixels(). + //----------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //--------------------------------------------------------------- + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window are + // present in the input file, or false if any pixels are missing. + // (Another program may still be busy writing the file, or file + // writing may have been aborted prematurely.) + //--------------------------------------------------------------- + + bool isComplete () const; + + + //--------------------------------------------------------------- + // Read pixel data: + // + // readPixels(s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the file, + // and stores them in the current frame buffer. + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // The scan lines can be read from the file in random order, and + // individual scan lines may be skipped or read multiple times. + // For maximum efficiency, the scan lines should be read in the + // order in which they were written to the file. + // + // readPixels(s) calls readPixels(s,s). + // + // If threading is enabled, readPixels (s1, s2) tries to perform + // decopmression of multiple scanlines in parallel. + // + //--------------------------------------------------------------- + + void readPixels (int scanLine1, int scanLine2); + void readPixels (int scanLine); + + + + //--------------------------------------------------------------- + // Extract pixel data from pre-read block + // + // readPixels(rawPixelData,frameBuffer,s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the data provided and + // stores them in the provided frameBuffer. + // the data can be obtained from a call to rawPixelData() + // + // + // Both s1 and s2 must be within the data specified + // + // you must provide a frameBuffer with a samplecountslice, which must have been read + // and the data valid - readPixels uses your sample count buffer to compute + // offsets to the data it needs + // + // This call does not block, and is thread safe for clients with an existing + // threading model. The InputFile's frameBuffer is not used in this call. + // + // This call is only provided for clients which have an existing threading model in place + // and unpredictable access patterns to the data. + // The fastest way to read an entire image is to enable threading,use setFrameBuffer then + // readPixels(header().dataWindow().min.y, header.dataWindow().max.y) + // + //--------------------------------------------------------------- + + void readPixels (const char * rawPixelData, + const DeepFrameBuffer & frameBuffer, + int scanLine1, + int scanLine2) const; + + //---------------------------------------------- + // Read a block of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement OutputFile::copyPixels()). + // note: returns the entire payload of the relevant chunk of data, not including part number + // including compressed and uncompressed sizes + // on entry, if pixelDataSize is insufficiently large, no bytes are read (pixelData can safely be NULL) + // on exit, pixelDataSize is the number of bytes required to read the chunk + // + //---------------------------------------------- + + void rawPixelData (int firstScanLine, + char * pixelData, + Int64 &pixelDataSize); + + + //------------------------------------------------- + // firstScanLineInChunk() returns the row number of the first row that's stored in the + // same chunk as scanline y. Depending on the compression mode, this may not be the same as y + // + // lastScanLineInChunk() returns the row number of the last row that's stored in the same + // chunk as scanline y. Depending on the compression mode, this may not be the same as y. + // The last chunk in the file may be smaller than all the others + // + //------------------------------------------------ + int firstScanLineInChunk(int y) const; + int lastScanLineInChunk (int y) const; + + //----------------------------------------------------------- + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCounts(s1, s2) reads all the counts of + // pixel samples with y coordinates in the interval + // [min (s1, s2), max (s1, s2)] from the file, and stores + // them in the slice naming "sample count". + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // readPixelSampleCounts(s) calls readPixelSampleCounts(s,s). + // + //----------------------------------------------------------- + + void readPixelSampleCounts (int scanline1, + int scanline2); + void readPixelSampleCounts (int scanline); + + + //---------------------------------------------------------- + // Read pixel sample counts into the provided frameBuffer + // using a block read of data read by rawPixelData + // for multi-scanline compression schemes, you must decode the entire block + // so scanline1=firstScanLineInChunk(y) and scanline2=lastScanLineInChunk(y) + // + // This call does not block, and is thread safe for clients with an existing + // threading model. The InputFile's frameBuffer is not used in this call. + // + // The fastest way to read an entire image is to enable threading in OpenEXR, use setFrameBuffer then + // readPixelSampleCounts(header().dataWindow().min.y, header.dataWindow().max.y) + // + //---------------------------------------------------------- + void readPixelSampleCounts (const char * rawdata , + const DeepFrameBuffer & frameBuffer, + int scanLine1 , + int scanLine2) const; + + struct Data; + + private: + + Data * _data; + + DeepScanLineInputFile (InputPartData* part); + + void initialize(const Header& header); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream & is); + void multiPartInitialize(InputPartData* part); + + friend class InputFile; + friend class MultiPartInputFile; + friend void DeepScanLineOutputFile::copyPixels(DeepScanLineInputFile &); +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepScanLineInputPart.h b/OpenEXR/include/OpenEXR/ImfDeepScanLineInputPart.h new file mode 100644 index 0000000..c21786b --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepScanLineInputPart.h @@ -0,0 +1,181 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFDEEPSCANLINEINPUTPART_H_ +#define IMFDEEPSCANLINEINPUTPART_H_ + +#include "ImfMultiPartInputFile.h" +#include "ImfDeepScanLineInputFile.h" +#include "ImfDeepScanLineOutputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT DeepScanLineInputPart +{ + public: + + DeepScanLineInputPart(MultiPartInputFile& file, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the InputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readPixels() is called. + // The current frame buffer can be changed after each call + // to readPixels(). + //----------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //--------------------------------------------------------------- + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window are + // present in the input file, or false if any pixels are missing. + // (Another program may still be busy writing the file, or file + // writing may have been aborted prematurely.) + //--------------------------------------------------------------- + + bool isComplete () const; + + + //--------------------------------------------------------------- + // Read pixel data: + // + // readPixels(s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the file, + // and stores them in the current frame buffer. + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // The scan lines can be read from the file in random order, and + // individual scan lines may be skipped or read multiple times. + // For maximum efficiency, the scan lines should be read in the + // order in which they were written to the file. + // + // readPixels(s) calls readPixels(s,s). + // + // If threading is enabled, readPixels (s1, s2) tries to perform + // decopmression of multiple scanlines in parallel. + // + //--------------------------------------------------------------- + + void readPixels (int scanLine1, int scanLine2); + void readPixels (int scanLine); + void readPixels (const char * rawPixelData,const DeepFrameBuffer & frameBuffer, + int scanLine1,int scanLine2) const; + + //---------------------------------------------- + // Read a block of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement OutputFile::copyPixels()). + //---------------------------------------------- + + void rawPixelData (int firstScanLine, + char * pixelData, + Int64 &pixelDataSize); + + + //----------------------------------------------------------- + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCounts(s1, s2) reads all the counts of + // pixel samples with y coordinates in the interval + // [min (s1, s2), max (s1, s2)] from the file, and stores + // them in the slice naming "sample count". + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // readPixelSampleCounts(s) calls readPixelSampleCounts(s,s). + //----------------------------------------------------------- + + void readPixelSampleCounts(int scanline1, + int scanline2); + void readPixelSampleCounts(int scanline); + + void readPixelSampleCounts( const char * rawdata , const DeepFrameBuffer & frameBuffer, + int scanLine1 , int scanLine2) const; + + int firstScanLineInChunk(int y) const; + int lastScanLineInChunk (int y) const; + private: + DeepScanLineInputFile *file; + + // needed for copyPixels + friend void DeepScanLineOutputFile::copyPixels(DeepScanLineInputPart &); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFDEEPSCANLINEINPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfDeepScanLineOutputFile.h b/OpenEXR/include/OpenEXR/ImfDeepScanLineOutputFile.h new file mode 100644 index 0000000..c823d7f --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepScanLineOutputFile.h @@ -0,0 +1,244 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DEEP_SCAN_LINE_OUTPUT_FILE_H +#define INCLUDED_IMF_DEEP_SCAN_LINE_OUTPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepScanLineOutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct PreviewRgba; + +class IMF_EXPORT DeepScanLineOutputFile : public GenericOutputFile +{ + public: + + //----------------------------------------------------------- + // Constructor -- opens the file and writes the file header. + // The file header is also copied into the DeepScanLineOutputFile + // object, and can later be accessed via the header() method. + // Destroying this DeepScanLineOutputFile object automatically closes + // the file. + // + // numThreads determines the number of threads that will be + // used to write the file (see ImfThreading.h). + //----------------------------------------------------------- + + DeepScanLineOutputFile (const char fileName[], const Header &header, + int numThreads = globalThreadCount()); + + + //------------------------------------------------------------ + // Constructor -- attaches the new DeepScanLineOutputFile object + // to a file that has already been opened, and writes the file header. + // The file header is also copied into the DeepScanLineOutputFile + // object, and can later be accessed via the header() method. + // Destroying this DeepScanLineOutputFile object does not automatically + // close the file. + // + // numThreads determines the number of threads that will be + // used to write the file (see ImfThreading.h). + //------------------------------------------------------------ + + DeepScanLineOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, + int numThreads = globalThreadCount()); + + + //------------------------------------------------- + // Destructor + // + // Destroying the DeepScanLineOutputFile object + // before writing all scan lines within the data + // window results in an incomplete file. + //------------------------------------------------- + + virtual ~DeepScanLineOutputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the OutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writePixels() is + // called. The current frame buffer can be changed + // after each call to writePixels. + //------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------------- + // Write pixel data: + // + // writePixels(n) retrieves the next n scan lines worth of data from + // the current frame buffer, starting with the scan line indicated by + // currentScanLine(), and stores the data in the output file, and + // progressing in the direction indicated by header.lineOrder(). + // + // To produce a complete and correct file, exactly m scan lines must + // be written, where m is equal to + // header().dataWindow().max.y - header().dataWindow().min.y + 1. + //------------------------------------------------------------------- + + void writePixels (int numScanLines = 1); + + + //------------------------------------------------------------------ + // Access to the current scan line: + // + // currentScanLine() returns the y coordinate of the first scan line + // that will be read from the current frame buffer during the next + // call to writePixels(). + // + // If header.lineOrder() == INCREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().min.y. After writing each scan line, + // the current scan line is incremented by 1. + // + // If header.lineOrder() == DECREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().max.y. After writing each scan line, + // the current scan line is decremented by 1. + // + //------------------------------------------------------------------ + + int currentScanLine () const; + + + //-------------------------------------------------------------- + // Shortcut to copy all pixels from an InputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the InputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder" and "channels" attributes must be the same. + //-------------------------------------------------------------- + + void copyPixels (DeepScanLineInputFile &in); + + // -------------------------------------------------------------- + // Shortcut to copy pixels from a given part of a multipart file + // -------------------------------------------------------------- + void copyPixels (DeepScanLineInputPart &in); + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few scan lines at a + // time, while the image is being generated. Since the preview + // image is an attribute in the file's header, it gets stored in + // the file as soon as the file is opened, but we may not know + // what the preview image should look like until we have written + // the last scan line of the main image. + // + //-------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba newPixels[]); + + + struct Data; + + private: + + //------------------------------------------------------------ + // Constructor -- attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + //------------------------------------------------------------ + DeepScanLineOutputFile (const OutputPartData* part); + + DeepScanLineOutputFile (const DeepScanLineOutputFile &); // not implemented + DeepScanLineOutputFile & operator = (const DeepScanLineOutputFile &); // not implemented + + void initialize (const Header &header); + void initializeLineBuffer(); + + Data * _data; + + + + friend class MultiPartOutputFile; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepScanLineOutputPart.h b/OpenEXR/include/OpenEXR/ImfDeepScanLineOutputPart.h new file mode 100644 index 0000000..05410f3 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepScanLineOutputPart.h @@ -0,0 +1,168 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFDEEPSCANLINEOUTPUTPART_H_ +#define IMFDEEPSCANLINEOUTPUTPART_H_ + +#include "ImfDeepScanLineOutputFile.h" +#include "ImfMultiPartOutputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT DeepScanLineOutputPart +{ + public: + + DeepScanLineOutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the OutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writePixels() is + // called. The current frame buffer can be changed + // after each call to writePixels. + //------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------------- + // Write pixel data: + // + // writePixels(n) retrieves the next n scan lines worth of data from + // the current frame buffer, starting with the scan line indicated by + // currentScanLine(), and stores the data in the output file, and + // progressing in the direction indicated by header.lineOrder(). + // + // To produce a complete and correct file, exactly m scan lines must + // be written, where m is equal to + // header().dataWindow().max.y - header().dataWindow().min.y + 1. + //------------------------------------------------------------------- + + void writePixels (int numScanLines = 1); + + + //------------------------------------------------------------------ + // Access to the current scan line: + // + // currentScanLine() returns the y coordinate of the first scan line + // that will be read from the current frame buffer during the next + // call to writePixels(). + // + // If header.lineOrder() == INCREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().min.y. After writing each scan line, + // the current scan line is incremented by 1. + // + // If header.lineOrder() == DECREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().max.y. After writing each scan line, + // the current scan line is decremented by 1. + // + //------------------------------------------------------------------ + + int currentScanLine () const; + + + //-------------------------------------------------------------- + // Shortcut to copy all pixels from an InputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the InputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder" and "channels" attributes must be the same. + //-------------------------------------------------------------- + + void copyPixels (DeepScanLineInputFile &in); + void copyPixels (DeepScanLineInputPart &in); + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few scan lines at a + // time, while the image is being generated. Since the preview + // image is an attribute in the file's header, it gets stored in + // the file as soon as the file is opened, but we may not know + // what the preview image should look like until we have written + // the last scan line of the main image. + // + //-------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba newPixels[]); + + private: + DeepScanLineOutputFile* file; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFDEEPSCANLINEOUTPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfDeepTiledInputFile.h b/OpenEXR/include/OpenEXR/ImfDeepTiledInputFile.h new file mode 100644 index 0000000..87294b5 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepTiledInputFile.h @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DEEP_TILED_INPUT_FILE_H +#define INCLUDED_IMF_DEEP_TILED_INPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepTiledInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "ImfTileDescription.h" +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfDeepFrameBuffer.h" +#include "ImfDeepTiledOutputFile.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT DeepTiledInputFile : public GenericInputFile +{ + public: + + //-------------------------------------------------------------------- + // A constructor that opens the file with the specified name, and + // reads the file header. The constructor throws an IEX_NAMESPACE::ArgExc + // exception if the file is not tiled. + // The numThreads parameter specifies how many worker threads this + // file will try to keep busy when decompressing individual tiles. + // Destroying TiledInputFile objects constructed with this constructor + // automatically closes the corresponding files. + //-------------------------------------------------------------------- + + DeepTiledInputFile (const char fileName[], + int numThreads = globalThreadCount ()); + + + // ---------------------------------------------------------- + // A constructor that attaches the new TiledInputFile object + // to a file that has already been opened. + // Destroying TiledInputFile objects constructed with this + // constructor does not automatically close the corresponding + // files. + // ---------------------------------------------------------- + + DeepTiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount ()); + + + //----------- + // Destructor + //----------- + + virtual ~DeepTiledInputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledInputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readTile() is called. + // The current frame buffer can be changed after each call + // to readTile(). + //----------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------ + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window + // (in all levels) are present in the input file, or false if + // any pixels are missing. (Another program may still be busy + // writing the file, or file writing may have been aborted + // prematurely.) + //------------------------------------------------------------ + + bool isComplete () const; + + + //-------------------------------------------------- + // Utility functions: + //-------------------------------------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with + // MIPMAP_LEVELS files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + // totalTiles() returns the total number of tiles in the image + // + //-------------------------------------------------------------------- + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + size_t totalTiles() const; + + //---------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //---------------------------------------------------------- + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + + //-------------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //-------------------------------------------------------------- + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional region of + // valid pixel coordinates for a level with level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------ + // Read pixel data: + // + // readTile(dx, dy, lx, ly) reads the tile with tile + // coordinates (dx, dy), and level number (lx, ly), + // and stores it in the current frame buffer. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readTile(dx, dy, level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It calls + // readTile(dx, dy, level, level). + // + // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow + // reading multiple tiles at once. If multi-threading is used + // the multiple tiles are read concurrently. + // + // Pixels that are outside the pixel coordinate range for the + // tile's level, are never accessed by readTile(). + // + // Attempting to access a tile that is not present in the file + // throws an InputExc exception. + // + //------------------------------------------------------------ + + void readTile (int dx, int dy, int l = 0); + void readTile (int dx, int dy, int lx, int ly); + + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //-------------------------------------------------- + // Read a tile of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement TiledOutputFile::copyPixels()). + //-------------------------------------------------- + + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + char *pixelData, + Int64 &dataSize) const; + + //------------------------------------------------------------------ + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCount(dx, dy, lx, ly) reads the sample counts + // for tile (dx, dy) in level (lx, ly). + // + // readPixelSampleCount(dx, dy, l) calls + // readPixelSampleCount(dx, dy, lx = l, ly = l) + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx, ly) reads all + // the sample counts for tiles within range + // [(min(dx1, dx2), min(dy1, dy2))...(max(dx1, dx2), max(dy1, dy2)], + // and on level (lx, ly) + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, l) calls + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx = l, ly = l). + //------------------------------------------------------------------ + + void readPixelSampleCount (int dx, int dy, int l = 0); + void readPixelSampleCount (int dx, int dy, int lx, int ly); + + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int lx, int ly); + + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int l = 0); + + struct Data; + + + + private: + + friend class InputFile; + friend class MultiPartInputFile; + + DeepTiledInputFile (InputPartData* part); + + DeepTiledInputFile (const DeepTiledInputFile &); // not implemented + DeepTiledInputFile & operator = (const DeepTiledInputFile &); // not implemented + + DeepTiledInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, int version, + int numThreads); + + void initialize (); + void multiPartInitialize(InputPartData* part); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is); + + bool isValidTile (int dx, int dy, + int lx, int ly) const; + + size_t bytesPerLineForTile (int dx, int dy, + int lx, int ly) const; + + + void getTileOrder(int dx[],int dy[],int lx[],int ly[]) const; + + + Data * _data; + + + // needed for copyPixels + friend void DeepTiledOutputFile::copyPixels(DeepTiledInputFile &); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepTiledInputPart.h b/OpenEXR/include/OpenEXR/ImfDeepTiledInputPart.h new file mode 100644 index 0000000..8663639 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepTiledInputPart.h @@ -0,0 +1,362 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFDEEPTILEDINPUTPART_H_ +#define IMFDEEPTILEDINPUTPART_H_ + +#include "ImfDeepTiledInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT DeepTiledInputPart +{ + public: + + DeepTiledInputPart(MultiPartInputFile& multiPartFile, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledInputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readTile() is called. + // The current frame buffer can be changed after each call + // to readTile(). + //----------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------ + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window + // (in all levels) are present in the input file, or false if + // any pixels are missing. (Another program may still be busy + // writing the file, or file writing may have been aborted + // prematurely.) + //------------------------------------------------------------ + + bool isComplete () const; + + + //-------------------------------------------------- + // Utility functions: + //-------------------------------------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with + // MIPMAP_LEVELS files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + + //---------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //---------------------------------------------------------- + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + + //-------------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //-------------------------------------------------------------- + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional region of + // valid pixel coordinates for a level with level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------ + // Read pixel data: + // + // readTile(dx, dy, lx, ly) reads the tile with tile + // coordinates (dx, dy), and level number (lx, ly), + // and stores it in the current frame buffer. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readTile(dx, dy, level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It calls + // readTile(dx, dy, level, level). + // + // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow + // reading multiple tiles at once. If multi-threading is used + // the multiple tiles are read concurrently. + // + // Pixels that are outside the pixel coordinate range for the + // tile's level, are never accessed by readTile(). + // + // Attempting to access a tile that is not present in the file + // throws an InputExc exception. + // + //------------------------------------------------------------ + + void readTile (int dx, int dy, int l = 0); + void readTile (int dx, int dy, int lx, int ly); + + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //-------------------------------------------------- + // Read a tile of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement TiledOutputFile::copyPixels()). + //-------------------------------------------------- + + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + char *data, + Int64 &dataSize + ) const; + + //------------------------------------------------------------------ + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCount(dx, dy, lx, ly) reads the sample counts + // for tile (dx, dy) in level (lx, ly). + // + // readPixelSampleCount(dx, dy, l) calls + // readPixelSampleCount(dx, dy, lx = l, ly = l) + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx, ly) reads all + // the sample counts for tiles within range + // [(min(dx1, dx2), min(dy1, dy2))...(max(dx1, dx2), max(dy1, dy2)], + // and on level (lx, ly) + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, l) calls + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx = l, ly = l). + //------------------------------------------------------------------ + + void readPixelSampleCount (int dx, int dy, int l = 0); + void readPixelSampleCount (int dx, int dy, int lx, int ly); + + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int lx, int ly); + + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int l = 0); + + private: + DeepTiledInputFile* file; + + friend void DeepTiledOutputFile::copyPixels(DeepTiledInputPart &); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif /* IMFDEEPTILEDINPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfDeepTiledOutputFile.h b/OpenEXR/include/OpenEXR/ImfDeepTiledOutputFile.h new file mode 100644 index 0000000..e12dda1 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepTiledOutputFile.h @@ -0,0 +1,475 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DEEP_TILED_OUTPUT_FILE_H +#define INCLUDED_IMF_DEEP_TILED_OUTPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepTiledOutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT DeepTiledOutputFile : public GenericOutputFile +{ + public: + + //------------------------------------------------------------------- + // A constructor that opens the file with the specified name, and + // writes the file header. The file header is also copied into the + // TiledOutputFile object, and can later be accessed via the header() + // method. + // + // Destroying TiledOutputFile constructed with this constructor + // automatically closes the corresponding files. + // + // The header must contain a TileDescriptionAttribute called "tiles". + // + // The x and y subsampling factors for all image channels must be 1; + // subsampling is not supported. + // + // Tiles can be written to the file in arbitrary order. The line + // order attribute can be used to cause the tiles to be sorted in + // the file. When the file is read later, reading the tiles in the + // same order as they are in the file tends to be significantly + // faster than reading the tiles in random order (see writeTile, + // below). + //------------------------------------------------------------------- + + DeepTiledOutputFile (const char fileName[], + const Header &header, + int numThreads = globalThreadCount ()); + + + // ---------------------------------------------------------------- + // A constructor that attaches the new TiledOutputFile object to + // a file that has already been opened. Destroying TiledOutputFile + // objects constructed with this constructor does not automatically + // close the corresponding files. + // ---------------------------------------------------------------- + + DeepTiledOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + int numThreads = globalThreadCount ()); + + + //----------------------------------------------------- + // Destructor + // + // Destroying a TiledOutputFile object before all tiles + // have been written results in an incomplete file. + //----------------------------------------------------- + + virtual ~DeepTiledOutputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledOutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writeTile() is + // called. The current frame buffer can be changed + // after each call to writeTile(). + //------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //------------------- + // Utility functions: + //------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with MIPMAP_LEVELS + // files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + + //--------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //--------------------------------------------------------- + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + + //---------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //---------------------------------------------------------- + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a level with + // level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------------ + // Write pixel data: + // + // writeTile(dx, dy, lx, ly) writes the tile with tile + // coordinates (dx, dy), and level number (lx, ly) to + // the file. + // + // dx must lie in the interval [0, numXTiles(lx) - 1] + // dy must lie in the interval [0, numYTiles(ly) - 1] + // + // lx must lie in the interval [0, numXLevels() - 1] + // ly must lie in the inverval [0, numYLevels() - 1] + // + // writeTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls + // writeTile(dx, dy, level, level). + // + // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow + // writing multiple tiles at once. If multi-threading is used + // multiple tiles are written concurrently. The tile coordinates, + // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile + // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the + // tiles are always written in the order specified by the line + // order attribute. Hence, it is not possible to specify an + // "invalid" or empty tile range. + // + // Pixels that are outside the pixel coordinate range for the tile's + // level, are never accessed by writeTile(). + // + // Each tile in the file must be written exactly once. + // + // The file's line order attribute determines the order of the tiles + // in the file: + // + // INCREASING_Y In the file, the tiles for each level are stored + // in a contiguous block. The levels are ordered + // like this: + // + // (0, 0) (1, 0) ... (nx-1, 0) + // (0, 1) (1, 1) ... (nx-1, 1) + // ... + // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) + // + // where nx = numXLevels(), and ny = numYLevels(). + // In an individual level, (lx, ly), the tiles + // are stored in the following order: + // + // (0, 0) (1, 0) ... (tx-1, 0) + // (0, 1) (1, 1) ... (tx-1, 1) + // ... + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // + // where tx = numXTiles(lx), + // and ty = numYTiles(ly). + // + // DECREASING_Y As for INCREASING_Y, the tiles for each level + // are stored in a contiguous block. The levels + // are ordered the same way as for INCREASING_Y, + // but within an individual level, the tiles + // are stored in this order: + // + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // ... + // (0, 1) (1, 1) ... (tx-1, 1) + // (0, 0) (1, 0) ... (tx-1, 0) + // + // + // RANDOM_Y The order of the calls to writeTile() determines + // the order of the tiles in the file. + // + //------------------------------------------------------------------ + + void writeTile (int dx, int dy, int l = 0); + void writeTile (int dx, int dy, int lx, int ly); + + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //------------------------------------------------------------------ + // Shortcut to copy all pixels from a TiledInputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the TiledInputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder", "channels", and "tiles" attributes must be the same. + //------------------------------------------------------------------ + + void copyPixels (DeepTiledInputFile &in); + void copyPixels (DeepTiledInputPart &in); + + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few tiles at a time, + // while the image is being generated. Since the preview image + // is an attribute in the file's header, it gets stored in the + // file as soon as the file is opened, but we may not know what + // the preview image should look like until we have written the + // last tile of the main image. + // + //-------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba newPixels[]); + + + //------------------------------------------------------------- + // Break a tile -- for testing and debugging only: + // + // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the + // output file by writing n copies of character c, starting + // p bytes from the beginning of the tile with tile coordinates + // (dx, dy) and level number (lx, ly). + // + // Warning: Calling this function usually results in a broken + // image file. The file or parts of it may not be readable, + // or the file may contain bad data. + // + //------------------------------------------------------------- + + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + struct Data; + + private: + + // ---------------------------------------------------------------- + // A constructor attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + // ---------------------------------------------------------------- + DeepTiledOutputFile (const OutputPartData* part); + + DeepTiledOutputFile (const DeepTiledOutputFile &); // not implemented + DeepTiledOutputFile & operator = (const DeepTiledOutputFile &); // not implemented + + void initialize (const Header &header); + + bool isValidTile (int dx, int dy, + int lx, int ly) const; + + size_t bytesPerLineForTile (int dx, int dy, + int lx, int ly) const; + + Data * _data; + + + friend class MultiPartOutputFile; + +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfDeepTiledOutputPart.h b/OpenEXR/include/OpenEXR/ImfDeepTiledOutputPart.h new file mode 100644 index 0000000..c88da12 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDeepTiledOutputPart.h @@ -0,0 +1,394 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFDEEPTILEDOUTPUTPART_H_ +#define IMFDEEPTILEDOUTPUTPART_H_ + +#include "ImfForward.h" +#include "ImfDeepTiledInputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT DeepTiledOutputPart +{ + public: + + DeepTiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledOutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writeTile() is + // called. The current frame buffer can be changed + // after each call to writeTile(). + //------------------------------------------------------- + + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const DeepFrameBuffer & frameBuffer () const; + + + //------------------- + // Utility functions: + //------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with MIPMAP_LEVELS + // files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + + //--------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //--------------------------------------------------------- + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + + //---------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //---------------------------------------------------------- + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a level with + // level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------------ + // Write pixel data: + // + // writeTile(dx, dy, lx, ly) writes the tile with tile + // coordinates (dx, dy), and level number (lx, ly) to + // the file. + // + // dx must lie in the interval [0, numXTiles(lx) - 1] + // dy must lie in the interval [0, numYTiles(ly) - 1] + // + // lx must lie in the interval [0, numXLevels() - 1] + // ly must lie in the inverval [0, numYLevels() - 1] + // + // writeTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls + // writeTile(dx, dy, level, level). + // + // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow + // writing multiple tiles at once. If multi-threading is used + // multiple tiles are written concurrently. The tile coordinates, + // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile + // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the + // tiles are always written in the order specified by the line + // order attribute. Hence, it is not possible to specify an + // "invalid" or empty tile range. + // + // Pixels that are outside the pixel coordinate range for the tile's + // level, are never accessed by writeTile(). + // + // Each tile in the file must be written exactly once. + // + // The file's line order attribute determines the order of the tiles + // in the file: + // + // INCREASING_Y In the file, the tiles for each level are stored + // in a contiguous block. The levels are ordered + // like this: + // + // (0, 0) (1, 0) ... (nx-1, 0) + // (0, 1) (1, 1) ... (nx-1, 1) + // ... + // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) + // + // where nx = numXLevels(), and ny = numYLevels(). + // In an individual level, (lx, ly), the tiles + // are stored in the following order: + // + // (0, 0) (1, 0) ... (tx-1, 0) + // (0, 1) (1, 1) ... (tx-1, 1) + // ... + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // + // where tx = numXTiles(lx), + // and ty = numYTiles(ly). + // + // DECREASING_Y As for INCREASING_Y, the tiles for each level + // are stored in a contiguous block. The levels + // are ordered the same way as for INCREASING_Y, + // but within an individual level, the tiles + // are stored in this order: + // + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // ... + // (0, 1) (1, 1) ... (tx-1, 1) + // (0, 0) (1, 0) ... (tx-1, 0) + // + // + // RANDOM_Y The order of the calls to writeTile() determines + // the order of the tiles in the file. + // + //------------------------------------------------------------------ + + void writeTile (int dx, int dy, int l = 0); + void writeTile (int dx, int dy, int lx, int ly); + + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //------------------------------------------------------------------ + // Shortcut to copy all pixels from a TiledInputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the TiledInputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder", "channels", and "tiles" attributes must be the same. + //------------------------------------------------------------------ + + void copyPixels (DeepTiledInputFile &in); + void copyPixels (DeepTiledInputPart &in); + + + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few tiles at a time, + // while the image is being generated. Since the preview image + // is an attribute in the file's header, it gets stored in the + // file as soon as the file is opened, but we may not know what + // the preview image should look like until we have written the + // last tile of the main image. + // + //-------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba newPixels[]); + + + //------------------------------------------------------------- + // Break a tile -- for testing and debugging only: + // + // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the + // output file by writing n copies of character c, starting + // p bytes from the beginning of the tile with tile coordinates + // (dx, dy) and level number (lx, ly). + // + // Warning: Calling this function usually results in a broken + // image file. The file or parts of it may not be readable, + // or the file may contain bad data. + // + //------------------------------------------------------------- + + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + + private: + DeepTiledOutputFile* file; + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFDEEPTILEDOUTPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfDoubleAttribute.h b/OpenEXR/include/OpenEXR/ImfDoubleAttribute.h new file mode 100644 index 0000000..d9a88a8 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfDoubleAttribute.h @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_DOUBLE_ATTRIBUTE_H +#define INCLUDED_IMF_DOUBLE_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class DoubleAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute DoubleAttribute; +template <> IMF_EXPORT const char *DoubleAttribute::staticTypeName (); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfEnvmap.h b/OpenEXR/include/OpenEXR/ImfEnvmap.h new file mode 100644 index 0000000..16e4ee3 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfEnvmap.h @@ -0,0 +1,336 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_ENVMAP_H +#define INCLUDED_IMF_ENVMAP_H + +//----------------------------------------------------------------------------- +// +// Environment maps +// +// Environment maps define a mapping from 3D directions to 2D +// pixel space locations. Environment maps are typically used +// in 3D rendering, for effects such as quickly approximating +// how shiny surfaces reflect their environment. +// +// Environment maps can be stored in scanline-based or in tiled +// OpenEXR files. The fact that an image is an environment map +// is indicated by the presence of an EnvmapAttribute whose name +// is "envmap". (Convenience functions to access this attribute +// are defined in header file ImfStandardAttributes.h.) +// The attribute's value defines the mapping from 3D directions +// to 2D pixel space locations. +// +// This header file defines the set of possible EnvmapAttribute +// values. +// +// For each possible EnvmapAttribute value, this header file also +// defines a set of convienience functions to convert between 3D +// directions and 2D pixel locations. +// +// Most of the convenience functions defined below require a +// dataWindow parameter. For scanline-based images, and for +// tiled images with level mode ONE_LEVEL, the dataWindow +// parameter should be set to the image's data window, as +// defined in the image header. For tiled images with level +// mode MIPMAP_LEVELS or RIPMAP_LEVELS, the data window of the +// image level that is being accessed should be used instead. +// (See the dataWindowForLevel() methods in ImfTiledInputFile.h +// and ImfTiledOutputFile.h.) +// +//----------------------------------------------------------------------------- + +#include "ImathBox.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//-------------------------------- +// Supported environment map types +//-------------------------------- + +enum Envmap +{ + ENVMAP_LATLONG = 0, // Latitude-longitude environment map + ENVMAP_CUBE = 1, // Cube map + + NUM_ENVMAPTYPES // Number of different environment map types +}; + + +//------------------------------------------------------------------------- +// Latitude-Longitude Map: +// +// The environment is projected onto the image using polar coordinates +// (latitude and longitude). A pixel's x coordinate corresponds to +// its longitude, and the y coordinate corresponds to its latitude. +// Pixel (dataWindow.min.x, dataWindow.min.y) has latitude +pi/2 and +// longitude +pi; pixel (dataWindow.max.x, dataWindow.max.y) has +// latitude -pi/2 and longitude -pi. +// +// In 3D space, latitudes -pi/2 and +pi/2 correspond to the negative and +// positive y direction. Latitude 0, longitude 0 points into positive +// z direction; and latitude 0, longitude pi/2 points into positive x +// direction. +// +// The size of the data window should be 2*N by N pixels (width by height), +// where N can be any integer greater than 0. +//------------------------------------------------------------------------- + +namespace LatLongMap +{ + //---------------------------------------------------- + // Convert a 3D direction to a 2D vector whose x and y + // components represent the corresponding latitude + // and longitude. + //---------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V2f latLong (const IMATH_NAMESPACE::V3f &direction); + + + //-------------------------------------------------------- + // Convert the position of a pixel to a 2D vector whose + // x and y components represent the corresponding latitude + // and longitude. + //-------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V2f latLong (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &pixelPosition); + + + //------------------------------------------------------------- + // Convert a 2D vector, whose x and y components represent + // longitude and latitude, into a corresponding pixel position. + //------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V2f pixelPosition (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &latLong); + + + //----------------------------------------------------- + // Convert a 3D direction vector into a corresponding + // pixel position. pixelPosition(dw,dir) is equivalent + // to pixelPosition(dw,latLong(dw,dir)). + //----------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V2f pixelPosition (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V3f &direction); + + + //-------------------------------------------------------- + // Convert the position of a pixel in a latitude-longitude + // map into a corresponding 3D direction. + //-------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V3f direction (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &pixelPosition); +} + + +//-------------------------------------------------------------- +// Cube Map: +// +// The environment is projected onto the six faces of an +// axis-aligned cube. The cube's faces are then arranged +// in a 2D image as shown below. +// +// 2-----------3 +// / /| +// / / | Y +// / / | | +// 6-----------7 | | +// | | | | +// | | | | +// | 0 | 1 *------- X +// | | / / +// | | / / +// | |/ / +// 4-----------5 Z +// +// dataWindow.min +// / +// / +// +-----------+ +// |3 Y 7| +// | | | +// | | | +// | ---+---Z | +X face +// | | | +// | | | +// |1 5| +// +-----------+ +// |6 Y 2| +// | | | +// | | | +// | Z---+--- | -X face +// | | | +// | | | +// |4 0| +// +-----------+ +// |6 Z 7| +// | | | +// | | | +// | ---+---X | +Y face +// | | | +// | | | +// |2 3| +// +-----------+ +// |0 1| +// | | | +// | | | +// | ---+---X | -Y face +// | | | +// | | | +// |4 Z 5| +// +-----------+ +// |7 Y 6| +// | | | +// | | | +// | X---+--- | +Z face +// | | | +// | | | +// |5 4| +// +-----------+ +// |2 Y 3| +// | | | +// | | | +// | ---+---X | -Z face +// | | | +// | | | +// |0 1| +// +-----------+ +// / +// / +// dataWindow.max +// +// The size of the data window should be N by 6*N pixels +// (width by height), where N can be any integer greater +// than 0. +// +//-------------------------------------------------------------- + +//------------------------------------ +// Names for the six faces of the cube +//------------------------------------ + +enum CubeMapFace +{ + CUBEFACE_POS_X, // +X face + CUBEFACE_NEG_X, // -X face + CUBEFACE_POS_Y, // +Y face + CUBEFACE_NEG_Y, // -Y face + CUBEFACE_POS_Z, // +Z face + CUBEFACE_NEG_Z // -Z face +}; + +namespace CubeMap +{ + //--------------------------------------------- + // Width and height of a cube's face, in pixels + //--------------------------------------------- + + IMF_EXPORT + int sizeOfFace (const IMATH_NAMESPACE::Box2i &dataWindow); + + + //------------------------------------------ + // Compute the region in the environment map + // that is covered by the specified face. + //------------------------------------------ + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForFace (CubeMapFace face, + const IMATH_NAMESPACE::Box2i &dataWindow); + + + //---------------------------------------------------- + // Convert the coordinates of a pixel within a face + // [in the range from (0,0) to (s-1,s-1), where + // s == sizeOfFace(dataWindow)] to pixel coordinates + // in the environment map. + //---------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V2f pixelPosition (CubeMapFace face, + const IMATH_NAMESPACE::Box2i &dataWindow, + IMATH_NAMESPACE::V2f positionInFace); + + + //-------------------------------------------------------------- + // Convert a 3D direction into a cube face, and a pixel position + // within that face. + // + // If you have a 3D direction, dir, the following code fragment + // finds the position, pos, of the corresponding pixel in an + // environment map with data window dw: + // + // CubeMapFace f; + // V2f pif, pos; + // + // faceAndPixelPosition (dir, dw, f, pif); + // pos = pixelPosition (f, dw, pif); + // + //-------------------------------------------------------------- + + IMF_EXPORT + void faceAndPixelPosition (const IMATH_NAMESPACE::V3f &direction, + const IMATH_NAMESPACE::Box2i &dataWindow, + CubeMapFace &face, + IMATH_NAMESPACE::V2f &positionInFace); + + + // -------------------------------------------------------- + // Given a cube face and a pixel position within that face, + // compute the corresponding 3D direction. + // -------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::V3f direction (CubeMapFace face, + const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &positionInFace); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfEnvmapAttribute.h b/OpenEXR/include/OpenEXR/ImfEnvmapAttribute.h new file mode 100644 index 0000000..0d0129b --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfEnvmapAttribute.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_ENVMAP_ATTRIBUTE_H +#define INCLUDED_IMF_ENVMAP_ATTRIBUTE_H + + +//----------------------------------------------------------------------------- +// +// class EnvmapAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfEnvmap.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute EnvmapAttribute; + +template <> IMF_EXPORT const char *EnvmapAttribute::staticTypeName (); + +template <> IMF_EXPORT +void EnvmapAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> IMF_EXPORT +void EnvmapAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, + int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfExport.h b/OpenEXR/include/OpenEXR/ImfExport.h new file mode 100644 index 0000000..6563fd5 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfExport.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(ILMIMF_EXPORTS) + #define IMF_EXPORT __declspec(dllexport) + #define IMF_EXPORT_CONST extern __declspec(dllexport) + #else + #define IMF_EXPORT __declspec(dllimport) + #define IMF_EXPORT_CONST extern __declspec(dllimport) + #endif +#else + #define IMF_EXPORT + #define IMF_EXPORT_CONST extern const +#endif diff --git a/OpenEXR/include/OpenEXR/ImfFloatAttribute.h b/OpenEXR/include/OpenEXR/ImfFloatAttribute.h new file mode 100644 index 0000000..7370721 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfFloatAttribute.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_FLOAT_ATTRIBUTE_H +#define INCLUDED_IMF_FLOAT_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class FloatAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute FloatAttribute; +template <> IMF_EXPORT const char *FloatAttribute::staticTypeName (); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfForward.h b/OpenEXR/include/OpenEXR/ImfForward.h new file mode 100644 index 0000000..ea51c24 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfForward.h @@ -0,0 +1,127 @@ + + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// Portions (c) 2012 Weta Digital Ltd +// +// 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 Industrial Light & Magic 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_IMF_FORWARD_H +#define INCLUDED_IMF_FORWARD_H + +//////////////////////////////////////////////////////////////////// +// +// Forward declarations for OpenEXR - correctly declares namespace +// +//////////////////////////////////////////////////////////////////// + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// classes for basic types; +template class Array; +template class Array2D; +struct Channel; +class ChannelList; +struct Chromaticities; + +// attributes used in headers are TypedAttributes +class Attribute; + +class Header; + +// file handling classes +class OutputFile; +class TiledInputFile; +class ScanLineInputFile; +class InputFile; +class TiledOutputFile; +class DeepScanLineInputFile; +class DeepScanLineOutputFile; +class DeepTiledInputFile; +class DeepTiledOutputFile; +class AcesInputFile; +class AcesOutputFile; +class TiledInputPart; +class TiledInputFile; +class TileOffsets; + +// multipart file handling +class GenericInputFile; +class GenericOutputFile; +class MultiPartInputFile; +class MultiPartOutputFile; + +class InputPart; +class TiledInputPart; +class DeepScanLineInputPart; +class DeepTiledInputPart; + +class OutputPart; +class ScanLineOutputPart; +class TiledOutputPart; +class DeepScanLineOutputPart; +class DeepTiledOutputPart; + + +// internal use only +struct InputPartData; +struct OutputStreamMutex; +struct OutputPartData; +struct InputStreamMutex; + +// frame buffers + +class FrameBuffer; +class DeepFrameBuffer; +struct DeepSlice; + +// compositing +class DeepCompositing; +class CompositeDeepScanLine; + +// preview image +class PreviewImage; +struct PreviewRgba; + +// streams +class OStream; +class IStream; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif // include guard diff --git a/OpenEXR/include/OpenEXR/ImfFrameBuffer.h b/OpenEXR/include/OpenEXR/ImfFrameBuffer.h new file mode 100644 index 0000000..a810cfa --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfFrameBuffer.h @@ -0,0 +1,386 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_FRAME_BUFFER_H +#define INCLUDED_IMF_FRAME_BUFFER_H + +//----------------------------------------------------------------------------- +// +// class Slice +// class FrameBuffer +// +//----------------------------------------------------------------------------- + +#include "ImfName.h" +#include "ImfPixelType.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + +#include +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +//------------------------------------------------------- +// Description of a single slice of the frame buffer: +// +// Note -- terminology: as part of a file, a component of +// an image (e.g. red, green, blue, depth etc.) is called +// a "channel". As part of a frame buffer, an image +// component is called a "slice". +//------------------------------------------------------- + +struct IMF_EXPORT Slice +{ + //------------------------------ + // Data type; see ImfPixelType.h + //------------------------------ + + PixelType type; + + + //--------------------------------------------------------------------- + // Memory layout: The address of pixel (x, y) is + // + // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride + // + // where xp and yp are computed as follows: + // + // * If we are reading or writing a scanline-based file: + // + // xp = x + // yp = y + // + // * If we are reading a tile whose upper left coorner is at (xt, yt): + // + // if xTileCoords is true then xp = x - xt, else xp = x + // if yTileCoords is true then yp = y - yt, else yp = y + // + //--------------------------------------------------------------------- + + char * base; + size_t xStride; + size_t yStride; + + + //-------------------------------------------- + // Subsampling: pixel (x, y) is present in the + // slice only if + // + // x % xSampling == 0 && y % ySampling == 0 + // + //-------------------------------------------- + + int xSampling; + int ySampling; + + + //---------------------------------------------------------- + // Default value, used to fill the slice when a file without + // a channel that corresponds to this slice is read. + //---------------------------------------------------------- + + double fillValue; + + + //------------------------------------------------------- + // For tiled files, the xTileCoords and yTileCoords flags + // determine whether pixel addressing is performed using + // absolute coordinates or coordinates relative to a + // tile's upper left corner. (See the comment on base, + // xStride and yStride, above.) + // + // For scanline-based files these flags have no effect; + // pixel addressing is always done using absolute + // coordinates. + //------------------------------------------------------- + + bool xTileCoords; + bool yTileCoords; + + + //------------ + // Constructor + //------------ + + Slice (PixelType type = HALF, + char * base = 0, + size_t xStride = 0, + size_t yStride = 0, + int xSampling = 1, + int ySampling = 1, + double fillValue = 0.0, + bool xTileCoords = false, + bool yTileCoords = false); +}; + + +class IMF_EXPORT FrameBuffer +{ + public: + + //------------ + // Add a slice + //------------ + + void insert (const char name[], + const Slice &slice); + + void insert (const std::string &name, + const Slice &slice); + + //---------------------------------------------------------------- + // Access to existing slices: + // + // [n] Returns a reference to the slice with name n. + // If no slice with name n exists, an IEX_NAMESPACE::ArgExc + // is thrown. + // + // findSlice(n) Returns a pointer to the slice with name n, + // or 0 if no slice with name n exists. + // + //---------------------------------------------------------------- + + Slice & operator [] (const char name[]); + const Slice & operator [] (const char name[]) const; + + Slice & operator [] (const std::string &name); + const Slice & operator [] (const std::string &name) const; + + Slice * findSlice (const char name[]); + const Slice * findSlice (const char name[]) const; + + Slice * findSlice (const std::string &name); + const Slice * findSlice (const std::string &name) const; + + + //----------------------------------------- + // Iterator-style access to existing slices + //----------------------------------------- + + typedef std::map SliceMap; + + class Iterator; + class ConstIterator; + + Iterator begin (); + ConstIterator begin () const; + + Iterator end (); + ConstIterator end () const; + + Iterator find (const char name[]); + ConstIterator find (const char name[]) const; + + Iterator find (const std::string &name); + ConstIterator find (const std::string &name) const; + + private: + + SliceMap _map; +}; + + +//---------- +// Iterators +//---------- + +class FrameBuffer::Iterator +{ + public: + + Iterator (); + Iterator (const FrameBuffer::SliceMap::iterator &i); + + Iterator & operator ++ (); + Iterator operator ++ (int); + + const char * name () const; + Slice & slice () const; + + private: + + friend class FrameBuffer::ConstIterator; + + FrameBuffer::SliceMap::iterator _i; +}; + + +class FrameBuffer::ConstIterator +{ + public: + + ConstIterator (); + ConstIterator (const FrameBuffer::SliceMap::const_iterator &i); + ConstIterator (const FrameBuffer::Iterator &other); + + ConstIterator & operator ++ (); + ConstIterator operator ++ (int); + + const char * name () const; + const Slice & slice () const; + + private: + + friend bool operator == (const ConstIterator &, const ConstIterator &); + friend bool operator != (const ConstIterator &, const ConstIterator &); + + FrameBuffer::SliceMap::const_iterator _i; +}; + + +//----------------- +// Inline Functions +//----------------- + +inline +FrameBuffer::Iterator::Iterator (): _i() +{ + // empty +} + + +inline +FrameBuffer::Iterator::Iterator (const FrameBuffer::SliceMap::iterator &i): + _i (i) +{ + // empty +} + + +inline FrameBuffer::Iterator & +FrameBuffer::Iterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline FrameBuffer::Iterator +FrameBuffer::Iterator::operator ++ (int) +{ + Iterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +FrameBuffer::Iterator::name () const +{ + return *_i->first; +} + + +inline Slice & +FrameBuffer::Iterator::slice () const +{ + return _i->second; +} + + +inline +FrameBuffer::ConstIterator::ConstIterator (): _i() +{ + // empty +} + +inline +FrameBuffer::ConstIterator::ConstIterator + (const FrameBuffer::SliceMap::const_iterator &i): _i (i) +{ + // empty +} + + +inline +FrameBuffer::ConstIterator::ConstIterator (const FrameBuffer::Iterator &other): + _i (other._i) +{ + // empty +} + +inline FrameBuffer::ConstIterator & +FrameBuffer::ConstIterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline FrameBuffer::ConstIterator +FrameBuffer::ConstIterator::operator ++ (int) +{ + ConstIterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +FrameBuffer::ConstIterator::name () const +{ + return *_i->first; +} + +inline const Slice & +FrameBuffer::ConstIterator::slice () const +{ + return _i->second; +} + + +inline bool +operator == (const FrameBuffer::ConstIterator &x, + const FrameBuffer::ConstIterator &y) +{ + return x._i == y._i; +} + + +inline bool +operator != (const FrameBuffer::ConstIterator &x, + const FrameBuffer::ConstIterator &y) +{ + return !(x == y); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfFramesPerSecond.h b/OpenEXR/include/OpenEXR/ImfFramesPerSecond.h new file mode 100644 index 0000000..59ab4cb --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfFramesPerSecond.h @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_FRAMES_PER_SECOND_H +#define INCLUDED_IMF_FRAMES_PER_SECOND_H + +//----------------------------------------------------------------------------- +// +// Convenience functions related to the framesPerSecond attribute +// +// Functions that return the exact values for commonly used frame rates: +// +// name frames per second +// +// fps_23_976() 23.976023... +// fps_24() 24.0 35mm film frames +// fps_25() 25.0 PAL video frames +// fps_29_97() 29.970029... NTSC video frames +// fps_30() 30.0 60Hz HDTV frames +// fps_47_952() 47.952047... +// fps_48() 48.0 +// fps_50() 50.0 PAL video fields +// fps_59_94() 59.940059... NTSC video fields +// fps_60() 60.0 60Hz HDTV fields +// +// Functions that try to convert inexact frame rates into exact ones: +// +// Given a frame rate, fps, that is close to one of the pre-defined +// frame rates fps_23_976(), fps_29_97(), fps_47_952() or fps_59_94(), +// guessExactFps(fps) returns the corresponding pre-defined frame +// rate. If fps is not close to one of the pre-defined frame rates, +// then guessExactFps(fps) returns Rational(fps). +// +//----------------------------------------------------------------------------- + +#include "ImfRational.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +inline Rational fps_23_976 () {return Rational (24000, 1001);} +inline Rational fps_24 () {return Rational (24, 1);} +inline Rational fps_25 () {return Rational (25, 1);} +inline Rational fps_29_97 () {return Rational (30000, 1001);} +inline Rational fps_30 () {return Rational (30, 1);} +inline Rational fps_47_952 () {return Rational (48000, 1001);} +inline Rational fps_48 () {return Rational (48, 1);} +inline Rational fps_50 () {return Rational (50, 1);} +inline Rational fps_59_94 () {return Rational (60000, 1001);} +inline Rational fps_60 () {return Rational (60, 1);} + +IMF_EXPORT Rational guessExactFps (double fps); +IMF_EXPORT Rational guessExactFps (const Rational &fps); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfGenericInputFile.h b/OpenEXR/include/OpenEXR/ImfGenericInputFile.h new file mode 100644 index 0000000..78b32ba --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfGenericInputFile.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFGENERICINPUTFILE_H_ +#define IMFGENERICINPUTFILE_H_ + +#include "ImfIO.h" +#include "ImfHeader.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class IMF_EXPORT GenericInputFile +{ + public: + virtual ~GenericInputFile() {} + + protected: + GenericInputFile() {} + void readMagicNumberAndVersionField(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int& version); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif /* IMFGENERICINPUTFILE_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfGenericOutputFile.h b/OpenEXR/include/OpenEXR/ImfGenericOutputFile.h new file mode 100644 index 0000000..6b37f2a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfGenericOutputFile.h @@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFGENERICOUTPUTFILE_H_ +#define IMFGENERICOUTPUTFILE_H_ + +#include "ImfVersion.h" +#include "ImfIO.h" +#include "ImfXdr.h" +#include "ImfHeader.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT GenericOutputFile +{ + public: + virtual ~GenericOutputFile() {} + + protected: + GenericOutputFile() {} + void writeMagicNumberAndVersionField (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, const Header& header); + void writeMagicNumberAndVersionField (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, const Header * headers, int parts); + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* GENERICOUTPUTFILE_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfHeader.h b/OpenEXR/include/OpenEXR/ImfHeader.h new file mode 100644 index 0000000..756a62e --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfHeader.h @@ -0,0 +1,699 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_HEADER_H +#define INCLUDED_IMF_HEADER_H + +//----------------------------------------------------------------------------- +// +// class Header +// +//----------------------------------------------------------------------------- + +#include "ImfLineOrder.h" +#include "ImfCompression.h" +#include "ImfName.h" +#include "ImfTileDescription.h" +#include "ImfInt64.h" +#include "ImathVec.h" +#include "ImathBox.h" +#include "IexBaseExc.h" + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +#include +#include +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +using std::string; + + +class IMF_EXPORT Header +{ + public: + + //---------------------------------------------------------------- + // Default constructor -- the display window and the data window + // are both set to Box2i (V2i (0, 0), V2i (width-1, height-1). + //---------------------------------------------------------------- + + Header (int width = 64, + int height = 64, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression = ZIP_COMPRESSION); + + + //-------------------------------------------------------------------- + // Constructor -- the data window is specified explicitly; the display + // window is set to Box2i (V2i (0, 0), V2i (width-1, height-1). + //-------------------------------------------------------------------- + + Header (int width, + int height, + const IMATH_NAMESPACE::Box2i &dataWindow, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression = ZIP_COMPRESSION); + + + //---------------------------------------------------------- + // Constructor -- the display window and the data window are + // both specified explicitly. + //---------------------------------------------------------- + + Header (const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression = ZIP_COMPRESSION); + + + //----------------- + // Copy constructor + //----------------- + + Header (const Header &other); + + + //----------- + // Destructor + //----------- + + ~Header (); + + + //----------- + // Assignment + //----------- + + Header & operator = (const Header &other); + + + //--------------------------------------------------------------- + // Add an attribute: + // + // insert(n,attr) If no attribute with name n exists, a new + // attribute with name n, and the same type as + // attr, is added, and the value of attr is + // copied into the new attribute. + // + // If an attribute with name n exists, and its + // type is the same as attr, the value of attr + // is copied into this attribute. + // + // If an attribute with name n exists, and its + // type is different from attr, an IEX_NAMESPACE::TypeExc + // is thrown. + // + //--------------------------------------------------------------- + + void insert (const char name[], + const Attribute &attribute); + + void insert (const std::string &name, + const Attribute &attribute); + + //--------------------------------------------------------------- + // Remove an attribute: + // + // remove(n) If an attribute with name n exists, then it + // is removed from the map of present attributes. + // + // If no attribute with name n exists, then this + // functions becomes a 'no-op' + // + //--------------------------------------------------------------- + void erase (const char name[]); + void erase (const std::string &name); + + + + //------------------------------------------------------------------ + // Access to existing attributes: + // + // [n] Returns a reference to the attribute + // with name n. If no attribute with + // name n exists, an IEX_NAMESPACE::ArgExc is thrown. + // + // typedAttribute(n) Returns a reference to the attribute + // with name n and type T. If no attribute + // with name n exists, an IEX_NAMESPACE::ArgExc is + // thrown. If an attribute with name n + // exists, but its type is not T, an + // IEX_NAMESPACE::TypeExc is thrown. + // + // findTypedAttribute(n) Returns a pointer to the attribute with + // name n and type T, or 0 if no attribute + // with name n and type T exists. + // + //------------------------------------------------------------------ + + Attribute & operator [] (const char name[]); + const Attribute & operator [] (const char name[]) const; + + Attribute & operator [] (const std::string &name); + const Attribute & operator [] (const std::string &name) const; + + template T& typedAttribute (const char name[]); + template const T& typedAttribute (const char name[]) const; + + template T& typedAttribute (const std::string &name); + template const T& typedAttribute (const std::string &name) const; + + template T* findTypedAttribute (const char name[]); + template const T* findTypedAttribute (const char name[]) const; + + template T* findTypedAttribute (const std::string &name); + template const T* findTypedAttribute (const std::string &name) + const; + + //--------------------------------------------- + // Iterator-style access to existing attributes + //--------------------------------------------- + + typedef std::map AttributeMap; + + class Iterator; + class ConstIterator; + + Iterator begin (); + ConstIterator begin () const; + + Iterator end (); + ConstIterator end () const; + + Iterator find (const char name[]); + ConstIterator find (const char name[]) const; + + Iterator find (const std::string &name); + ConstIterator find (const std::string &name) const; + + + //-------------------------------- + // Access to predefined attributes + //-------------------------------- + + IMATH_NAMESPACE::Box2i & displayWindow (); + const IMATH_NAMESPACE::Box2i & displayWindow () const; + + IMATH_NAMESPACE::Box2i & dataWindow (); + const IMATH_NAMESPACE::Box2i & dataWindow () const; + + float & pixelAspectRatio (); + const float & pixelAspectRatio () const; + + IMATH_NAMESPACE::V2f & screenWindowCenter (); + const IMATH_NAMESPACE::V2f & screenWindowCenter () const; + + float & screenWindowWidth (); + const float & screenWindowWidth () const; + + ChannelList & channels (); + const ChannelList & channels () const; + + LineOrder & lineOrder (); + const LineOrder & lineOrder () const; + + Compression & compression (); + const Compression & compression () const; + + + //----------------------------------------------------- + // Access to required attributes for multipart files + // They are optional to non-multipart files and mandatory + // for multipart files. + //----------------------------------------------------- + void setName (const string& name); + + string& name(); + const string& name() const; + + bool hasName() const; + + void setType (const string& Type); + + string& type(); + const string& type() const; + + bool hasType() const; + + void setVersion (const int version); + + int& version(); + const int& version() const; + + bool hasVersion() const; + + // + // the chunkCount attribute is set automatically when a file is written. + // There is no need to set it manually + // + void setChunkCount(int chunks); + bool hasChunkCount() const; + const int & chunkCount() const; + int & chunkCount(); + + + // + // for multipart files, return whether the file has a view string attribute + // (for the deprecated single part multiview format EXR, see ImfMultiView.h) + // + void setView(const string & view); + bool hasView() const; + string & view(); + const string & view() const; + + + //---------------------------------------------------------------------- + // Tile Description: + // + // The tile description is a TileDescriptionAttribute whose name + // is "tiles". The "tiles" attribute must be present in any tiled + // image file. When present, it describes various properties of the + // tiles that make up the file. + // + // Convenience functions: + // + // setTileDescription(td) + // calls insert ("tiles", TileDescriptionAttribute (td)) + // + // tileDescription() + // returns typedAttribute("tiles").value() + // + // hasTileDescription() + // return findTypedAttribute("tiles") != 0 + // + //---------------------------------------------------------------------- + + void setTileDescription (const TileDescription & td); + + TileDescription & tileDescription (); + const TileDescription & tileDescription () const; + + bool hasTileDescription() const; + + + //---------------------------------------------------------------------- + // Preview image: + // + // The preview image is a PreviewImageAttribute whose name is "preview". + // This attribute is special -- while an image file is being written, + // the pixels of the preview image can be changed repeatedly by calling + // OutputFile::updatePreviewImage(). + // + // Convenience functions: + // + // setPreviewImage(p) + // calls insert ("preview", PreviewImageAttribute (p)) + // + // previewImage() + // returns typedAttribute("preview").value() + // + // hasPreviewImage() + // return findTypedAttribute("preview") != 0 + // + //---------------------------------------------------------------------- + + void setPreviewImage (const PreviewImage &p); + + PreviewImage & previewImage (); + const PreviewImage & previewImage () const; + + bool hasPreviewImage () const; + + + //------------------------------------------------------------- + // Sanity check -- examines the header, and throws an exception + // if it finds something wrong (empty display window, negative + // pixel aspect ratio, unknown compression sceme etc.) + // + // set isTiled to true if you are checking a tiled/multi-res + // header + //------------------------------------------------------------- + + void sanityCheck (bool isTiled = false, + bool isMultipartFile = false) const; + + + //---------------------------------------------------------------- + // Maximum image size and maximim tile size: + // + // sanityCheck() will throw an exception if the width or height of + // the data window exceeds the maximum image width or height, or + // if the size of a tile exceeds the maximum tile width or height. + // + // At program startup the maximum image and tile width and height + // are set to zero, meaning that width and height are unlimited. + // + // Limiting image and tile width and height limits how much memory + // will be allocated when a file is opened. This can help protect + // applications from running out of memory while trying to read + // a damaged image file. + //---------------------------------------------------------------- + + static void setMaxImageSize (int maxWidth, int maxHeight); + static void setMaxTileSize (int maxWidth, int maxHeight); + + // + // Check if the header reads nothing. + // + bool readsNothing(); + + + //------------------------------------------------------------------ + // Input and output: + // + // If the header contains a preview image attribute, then writeTo() + // returns the position of that attribute in the output stream; this + // information is used by OutputFile::updatePreviewImage(). + // If the header contains no preview image attribute, then writeTo() + // returns 0. + //------------------------------------------------------------------ + + + Int64 writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + bool isTiled = false) const; + + void readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int &version); + + + private: + + AttributeMap _map; + + bool _readsNothing; +}; + + +//---------- +// Iterators +//---------- + +class Header::Iterator +{ + public: + + Iterator (); + Iterator (const Header::AttributeMap::iterator &i); + + Iterator & operator ++ (); + Iterator operator ++ (int); + + const char * name () const; + Attribute & attribute () const; + + private: + + friend class Header::ConstIterator; + + Header::AttributeMap::iterator _i; +}; + + +class Header::ConstIterator +{ + public: + + ConstIterator (); + ConstIterator (const Header::AttributeMap::const_iterator &i); + ConstIterator (const Header::Iterator &other); + + ConstIterator & operator ++ (); + ConstIterator operator ++ (int); + + const char * name () const; + const Attribute & attribute () const; + + private: + + friend bool operator == (const ConstIterator &, const ConstIterator &); + friend bool operator != (const ConstIterator &, const ConstIterator &); + + Header::AttributeMap::const_iterator _i; +}; + + +//------------------------------------------------------------------------ +// Library initialization: +// +// In a multithreaded program, staticInitialize() must be called once +// during startup, before the program accesses any other functions or +// classes in the IlmImf library. Calling staticInitialize() in this +// way avoids races during initialization of the library's global +// variables. +// +// Single-threaded programs are not required to call staticInitialize(); +// initialization of the library's global variables happens automatically. +// +//------------------------------------------------------------------------ + +void staticInitialize (); + + +//----------------- +// Inline Functions +//----------------- + + +inline +Header::Iterator::Iterator (): _i() +{ + // empty +} + + +inline +Header::Iterator::Iterator (const Header::AttributeMap::iterator &i): _i (i) +{ + // empty +} + + +inline Header::Iterator & +Header::Iterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline Header::Iterator +Header::Iterator::operator ++ (int) +{ + Iterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +Header::Iterator::name () const +{ + return *_i->first; +} + + +inline Attribute & +Header::Iterator::attribute () const +{ + return *_i->second; +} + + +inline +Header::ConstIterator::ConstIterator (): _i() +{ + // empty +} + +inline +Header::ConstIterator::ConstIterator + (const Header::AttributeMap::const_iterator &i): _i (i) +{ + // empty +} + + +inline +Header::ConstIterator::ConstIterator (const Header::Iterator &other): + _i (other._i) +{ + // empty +} + +inline Header::ConstIterator & +Header::ConstIterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline Header::ConstIterator +Header::ConstIterator::operator ++ (int) +{ + ConstIterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +Header::ConstIterator::name () const +{ + return *_i->first; +} + + +inline const Attribute & +Header::ConstIterator::attribute () const +{ + return *_i->second; +} + + +inline bool +operator == (const Header::ConstIterator &x, const Header::ConstIterator &y) +{ + return x._i == y._i; +} + + +inline bool +operator != (const Header::ConstIterator &x, const Header::ConstIterator &y) +{ + return !(x == y); +} + + +//--------------------- +// Template definitions +//--------------------- + +template +T & +Header::typedAttribute (const char name[]) +{ + Attribute *attr = &(*this)[name]; + T *tattr = dynamic_cast (attr); + + if (tattr == 0) + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); + + return *tattr; +} + + +template +const T & +Header::typedAttribute (const char name[]) const +{ + const Attribute *attr = &(*this)[name]; + const T *tattr = dynamic_cast (attr); + + if (tattr == 0) + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); + + return *tattr; +} + + +template +T & +Header::typedAttribute (const std::string &name) +{ + return typedAttribute (name.c_str()); +} + + +template +const T & +Header::typedAttribute (const std::string &name) const +{ + return typedAttribute (name.c_str()); +} + + +template +T * +Header::findTypedAttribute (const char name[]) +{ + AttributeMap::iterator i = _map.find (name); + return (i == _map.end())? 0: dynamic_cast (i->second); +} + + +template +const T * +Header::findTypedAttribute (const char name[]) const +{ + AttributeMap::const_iterator i = _map.find (name); + return (i == _map.end())? 0: dynamic_cast (i->second); +} + + +template +T * +Header::findTypedAttribute (const std::string &name) +{ + return findTypedAttribute (name.c_str()); +} + + +template +const T * +Header::findTypedAttribute (const std::string &name) const +{ + return findTypedAttribute (name.c_str()); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfHuf.h b/OpenEXR/include/OpenEXR/ImfHuf.h new file mode 100644 index 0000000..fa89604 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfHuf.h @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_HUF_H +#define INCLUDED_IMF_HUF_H + +#include "ImfExport.h" +#include "ImfNamespace.h" + +//----------------------------------------------------------------------------- +// +// 16-bit Huffman compression and decompression: +// +// hufCompress (r, nr, c) +// +// Compresses the contents of array r (of length nr), +// stores the compressed data in array c, and returns +// the size of the compressed data (in bytes). +// +// To avoid buffer overflows, the size of array c should +// be at least 2 * nr + 65536. +// +// hufUncompress (c, nc, r, nr) +// +// Uncompresses the data in array c (with length nc), +// and stores the results in array r (with length nr). +// +//----------------------------------------------------------------------------- + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +IMF_EXPORT +int +hufCompress (const unsigned short raw[/*nRaw*/], + int nRaw, + char compressed[/*2 * nRaw + 65536*/]); + +IMF_EXPORT +void +hufUncompress (const char compressed[/*nCompressed*/], + int nCompressed, + unsigned short raw[/*nRaw*/], + int nRaw); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfIO.h b/OpenEXR/include/OpenEXR/ImfIO.h new file mode 100644 index 0000000..4416d17 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfIO.h @@ -0,0 +1,255 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_IO_H +#define INCLUDED_IMF_IO_H + +//----------------------------------------------------------------------------- +// +// Low-level file input and output for OpenEXR. +// +//----------------------------------------------------------------------------- + +#include "ImfInt64.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//----------------------------------------------------------- +// class IStream -- an abstract base class for input streams. +//----------------------------------------------------------- + +class IMF_EXPORT IStream +{ + public: + + //----------- + // Destructor + //----------- + + virtual ~IStream (); + + + //------------------------------------------------- + // Does this input stream support memory-mapped IO? + // + // Memory-mapped streams can avoid an extra copy; + // memory-mapped read operations return a pointer + // to an internal buffer instead of copying data + // into a buffer supplied by the caller. + //------------------------------------------------- + + virtual bool isMemoryMapped () const; + + + //------------------------------------------------------ + // Read from the stream: + // + // read(c,n) reads n bytes from the stream, and stores + // them in array c. If the stream contains less than n + // bytes, or if an I/O error occurs, read(c,n) throws + // an exception. If read(c,n) reads the last byte from + // the file it returns false, otherwise it returns true. + //------------------------------------------------------ + + virtual bool read (char c[/*n*/], int n) = 0; + + + //--------------------------------------------------- + // Read from a memory-mapped stream: + // + // readMemoryMapped(n) reads n bytes from the stream + // and returns a pointer to the first byte. The + // returned pointer remains valid until the stream + // is closed. If there are less than n byte left to + // read in the stream or if the stream is not memory- + // mapped, readMemoryMapped(n) throws an exception. + //--------------------------------------------------- + + virtual char * readMemoryMapped (int n); + + + //-------------------------------------------------------- + // Get the current reading position, in bytes from the + // beginning of the file. If the next call to read() will + // read the first byte in the file, tellg() returns 0. + //-------------------------------------------------------- + + virtual Int64 tellg () = 0; + + + //------------------------------------------- + // Set the current reading position. + // After calling seekg(i), tellg() returns i. + //------------------------------------------- + + virtual void seekg (Int64 pos) = 0; + + + //------------------------------------------------------ + // Clear error conditions after an operation has failed. + //------------------------------------------------------ + + virtual void clear (); + + + //------------------------------------------------------ + // Get the name of the file associated with this stream. + //------------------------------------------------------ + + const char * fileName () const; + + protected: + + IStream (const char fileName[]); + + private: + + IStream (const IStream &); // not implemented + IStream & operator = (const IStream &); // not implemented + + std::string _fileName; +}; + + +//----------------------------------------------------------- +// class OStream -- an abstract base class for output streams +//----------------------------------------------------------- + +class IMF_EXPORT OStream +{ + public: + + //----------- + // Destructor + //----------- + + virtual ~OStream (); + + + //---------------------------------------------------------- + // Write to the stream: + // + // write(c,n) takes n bytes from array c, and stores them + // in the stream. If an I/O error occurs, write(c,n) throws + // an exception. + //---------------------------------------------------------- + + virtual void write (const char c[/*n*/], int n) = 0; + + + //--------------------------------------------------------- + // Get the current writing position, in bytes from the + // beginning of the file. If the next call to write() will + // start writing at the beginning of the file, tellp() + // returns 0. + //--------------------------------------------------------- + + virtual Int64 tellp () = 0; + + + //------------------------------------------- + // Set the current writing position. + // After calling seekp(i), tellp() returns i. + //------------------------------------------- + + virtual void seekp (Int64 pos) = 0; + + + //------------------------------------------------------ + // Get the name of the file associated with this stream. + //------------------------------------------------------ + + const char * fileName () const; + + protected: + + OStream (const char fileName[]); + + private: + + OStream (const OStream &); // not implemented + OStream & operator = (const OStream &); // not implemented + + std::string _fileName; +}; + + +//----------------------- +// Helper classes for Xdr +//----------------------- + +struct StreamIO +{ + static void + writeChars (OStream &os, const char c[/*n*/], int n) + { + os.write (c, n); + } + + static bool + readChars (IStream &is, char c[/*n*/], int n) + { + return is.read (c, n); + } +}; + + +struct CharPtrIO +{ + static void + writeChars (char *&op, const char c[/*n*/], int n) + { + while (n--) + *op++ = *c++; + } + + static bool + readChars (const char *&ip, char c[/*n*/], int n) + { + while (n--) + *c++ = *ip++; + + return true; + } +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfInputFile.h b/OpenEXR/include/OpenEXR/ImfInputFile.h new file mode 100644 index 0000000..42c6352 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfInputFile.h @@ -0,0 +1,240 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_INPUT_FILE_H +#define INCLUDED_IMF_INPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class InputFile -- a scanline-based interface that can be used +// to read both scanline-based and tiled OpenEXR image files. +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfTiledOutputFile.h" +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT InputFile : public GenericInputFile +{ + public: + + //----------------------------------------------------------- + // A constructor that opens the file with the specified name. + // Destroying the InputFile object will close the file. + // + // numThreads determines the number of threads that will be + // used to read the file (see ImfThreading.h). + //----------------------------------------------------------- + + InputFile (const char fileName[], int numThreads = globalThreadCount()); + + + //------------------------------------------------------------- + // A constructor that attaches the new InputFile object to a + // file that has already been opened. Destroying the InputFile + // object will not close the file. + // + // numThreads determines the number of threads that will be + // used to read the file (see ImfThreading.h). + //------------------------------------------------------------- + + InputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount()); + + + //----------- + // Destructor + //----------- + + virtual ~InputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the InputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readPixels() is called. + // The current frame buffer can be changed after each call + // to readPixels(). + //----------------------------------------------------------- + + void setFrameBuffer (const FrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const FrameBuffer & frameBuffer () const; + + + //--------------------------------------------------------------- + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window are + // present in the input file, or false if any pixels are missing. + // (Another program may still be busy writing the file, or file + // writing may have been aborted prematurely.) + //--------------------------------------------------------------- + + bool isComplete () const; + + + //--------------------------------------------------------------- + // Check if SSE optimization is enabled + // + // Call after setFrameBuffer() to query whether optimized file decoding + // is available - decode times will be faster if returns true + // + // Optimization depends on: + // the file type (only scanline data is supported), + // the framebuffer channels (RGB/RGBA mono or stereo) + // the framebuffer channel types (all channels half-float format only) + // the file channels (RGB/RGBA mono or stereo) + // the file channel types (all channel half-float format only) + // whether SSE2 instruction support was detected at compile time + // + // Calling isOptimizationEnabled before setFrameBuffer will throw an exception + // + //--------------------------------------------------------------- + + bool isOptimizationEnabled () const; + + + + + //--------------------------------------------------------------- + // Read pixel data: + // + // readPixels(s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the file, + // and stores them in the current frame buffer. + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header().dataWindow().max.y] + // + // The scan lines can be read from the file in random order, and + // individual scan lines may be skipped or read multiple times. + // For maximum efficiency, the scan lines should be read in the + // order in which they were written to the file. + // + // readPixels(s) calls readPixels(s,s). + // + //--------------------------------------------------------------- + + void readPixels (int scanLine1, int scanLine2); + void readPixels (int scanLine); + + + //---------------------------------------------- + // Read a block of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement OutputFile::copyPixels()). + //---------------------------------------------- + + void rawPixelData (int firstScanLine, + const char *&pixelData, + int &pixelDataSize); + + //-------------------------------------------------- + // Read a tile of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement TiledOutputFile::copyPixels()). + //-------------------------------------------------- + + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); + + struct Data; + + private: + + InputFile (InputPartData* part); + InputFile (const InputFile &); // not implemented + InputFile & operator = (const InputFile &); // not implemented + + void initialize (); + void multiPartInitialize(InputPartData* part); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is); + TiledInputFile * tFile (); + + friend void TiledOutputFile::copyPixels (InputFile &); + + Data * _data; + + + friend class MultiPartInputFile; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfInputPart.h b/OpenEXR/include/OpenEXR/ImfInputPart.h new file mode 100644 index 0000000..bfc30e3 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfInputPart.h @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFINPUTPART_H_ +#define IMFINPUTPART_H_ + +#include "ImfInputFile.h" +#include "ImfOutputPart.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//------------------------------------------------------------------- +// class InputPart: +// +// Same interface as InputFile. Please refer to InputFile. +//------------------------------------------------------------------- + +class IMF_EXPORT InputPart +{ + public: + InputPart(MultiPartInputFile& multiPartFile, int partNumber); + + const char * fileName () const; + const Header & header () const; + int version () const; + void setFrameBuffer (const FrameBuffer &frameBuffer); + const FrameBuffer & frameBuffer () const; + bool isComplete () const; + bool isOptimizationEnabled () const; + void readPixels (int scanLine1, int scanLine2); + void readPixels (int scanLine); + void rawPixelData (int firstScanLine, + const char *&pixelData, + int &pixelDataSize); + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); + + private: + InputFile* file; + // for internal use - give OutputFile and TiledOutputFile access to file for copyPixels + friend void OutputFile::copyPixels(InputPart&); + friend void TiledOutputFile::copyPixels(InputPart&); + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFINPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfInt64.h b/OpenEXR/include/OpenEXR/ImfInt64.h new file mode 100644 index 0000000..761557d --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfInt64.h @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_INT64_H +#define INCLUDED_IMF_INT64_H + +//---------------------------------------------------------------------------- +// +// Int64 -- unsigned 64-bit integers, imported from namespace Imath +// +//---------------------------------------------------------------------------- + +#include "ImathInt64.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +using IMATH_NAMESPACE::Int64; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + +#endif // INCLUDED_IMF_INT64_H diff --git a/OpenEXR/include/OpenEXR/ImfIntAttribute.h b/OpenEXR/include/OpenEXR/ImfIntAttribute.h new file mode 100644 index 0000000..3d271ca --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfIntAttribute.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_INT_ATTRIBUTE_H +#define INCLUDED_IMF_INT_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class IntAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute IntAttribute; +template <> IMF_EXPORT const char *IntAttribute::staticTypeName (); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfKeyCode.h b/OpenEXR/include/OpenEXR/ImfKeyCode.h new file mode 100644 index 0000000..2146101 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfKeyCode.h @@ -0,0 +1,167 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_KEY_CODE_H +#define INCLUDED_IMF_KEY_CODE_H + +//----------------------------------------------------------------------------- +// +// class KeyCode +// +// A KeyCode object uniquely identifies a motion picture film frame. +// The following fields specifiy film manufacturer, film type, film +// roll and the frame's position within the roll: +// +// filmMfcCode film manufacturer code +// range: 0 - 99 +// +// filmType film type code +// range: 0 - 99 +// +// prefix prefix to identify film roll +// range: 0 - 999999 +// +// count count, increments once every perfsPerCount +// perforations (see below) +// range: 0 - 9999 +// +// perfOffset offset of frame, in perforations from +// zero-frame reference mark +// range: 0 - 119 +// +// perfsPerFrame number of perforations per frame +// range: 1 - 15 +// +// typical values: +// +// 1 for 16mm film +// 3, 4, or 8 for 35mm film +// 5, 8 or 15 for 65mm film +// +// perfsPerCount number of perforations per count +// range: 20 - 120 +// +// typical values: +// +// 20 for 16mm film +// 64 for 35mm film +// 80 or 120 for 65mm film +// +// For more information about the interpretation of those fields see +// the following standards and recommended practice publications: +// +// SMPTE 254 Motion-Picture Film (35-mm) - Manufacturer-Printed +// Latent Image Identification Information +// +// SMPTE 268M File Format for Digital Moving-Picture Exchange (DPX) +// (section 6.1) +// +// SMPTE 270 Motion-Picture Film (65-mm) - Manufacturer- Printed +// Latent Image Identification Information +// +// SMPTE 271 Motion-Picture Film (16-mm) - Manufacturer- Printed +// Latent Image Identification Information +// +//----------------------------------------------------------------------------- +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT KeyCode +{ + public: + + //------------------------------------- + // Constructors and assignment operator + //------------------------------------- + + KeyCode (int filmMfcCode = 0, + int filmType = 0, + int prefix = 0, + int count = 0, + int perfOffset = 0, + int perfsPerFrame = 4, + int perfsPerCount = 64); + + KeyCode (const KeyCode &other); + KeyCode & operator = (const KeyCode &other); + + + //---------------------------- + // Access to individual fields + //---------------------------- + + int filmMfcCode () const; + void setFilmMfcCode (int filmMfcCode); + + int filmType () const; + void setFilmType (int filmType); + + int prefix () const; + void setPrefix (int prefix); + + int count () const; + void setCount (int count); + + int perfOffset () const; + void setPerfOffset (int perfOffset); + + int perfsPerFrame () const; + void setPerfsPerFrame (int perfsPerFrame); + + int perfsPerCount () const; + void setPerfsPerCount (int perfsPerCount); + + private: + + int _filmMfcCode; + int _filmType; + int _prefix; + int _count; + int _perfOffset; + int _perfsPerFrame; + int _perfsPerCount; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfKeyCodeAttribute.h b/OpenEXR/include/OpenEXR/ImfKeyCodeAttribute.h new file mode 100644 index 0000000..00d4ece --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfKeyCodeAttribute.h @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_KEY_CODE_ATTRIBUTE_H +#define INCLUDED_IMF_KEY_CODE_ATTRIBUTE_H + + +//----------------------------------------------------------------------------- +// +// class KeyCodeAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfKeyCode.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute KeyCodeAttribute; + +template <> +IMF_EXPORT +const char *KeyCodeAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void KeyCodeAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void KeyCodeAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfLineOrder.h b/OpenEXR/include/OpenEXR/ImfLineOrder.h new file mode 100644 index 0000000..8f30bed --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfLineOrder.h @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_LINE_ORDER_H +#define INCLUDED_IMF_LINE_ORDER_H + +//----------------------------------------------------------------------------- +// +// enum LineOrder +// +//----------------------------------------------------------------------------- +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +enum LineOrder +{ + INCREASING_Y = 0, // first scan line has lowest y coordinate + + DECREASING_Y = 1, // first scan line has highest y coordinate + + RANDOM_Y = 2, // only for tiled files; tiles are written + // in random order + + NUM_LINEORDERS // number of different line orders +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfLineOrderAttribute.h b/OpenEXR/include/OpenEXR/ImfLineOrderAttribute.h new file mode 100644 index 0000000..342c3d0 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfLineOrderAttribute.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_LINE_ORDER_ATTRIBUTE_H +#define INCLUDED_IMF_LINE_ORDER_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class LineOrderAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfLineOrder.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute LineOrderAttribute; + +template <> +IMF_EXPORT +const char *LineOrderAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void LineOrderAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void LineOrderAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfLut.h b/OpenEXR/include/OpenEXR/ImfLut.h new file mode 100644 index 0000000..b9ccc4c --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfLut.h @@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_LUT_H +#define INCLUDED_IMF_LUT_H + +//----------------------------------------------------------------------------- +// +// Lookup tables for efficient application +// of half --> half functions to pixel data, +// and some commonly applied functions. +// +//----------------------------------------------------------------------------- + +#include "ImfRgbaFile.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "halfFunction.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Lookup table for individual half channels. +// + +class IMF_EXPORT HalfLut +{ + public: + + //------------ + // Constructor + //------------ + + template + HalfLut (Function f); + + + //---------------------------------------------------------------------- + // Apply the table to data[0], data[stride] ... data[(nData-1) * stride] + //---------------------------------------------------------------------- + + void apply (half *data, + int nData, + int stride = 1) const; + + + //--------------------------------------------------------------- + // Apply the table to a frame buffer slice (see ImfFrameBuffer.h) + //--------------------------------------------------------------- + + void apply (const Slice &data, + const IMATH_NAMESPACE::Box2i &dataWindow) const; + + private: + + halfFunction _lut; +}; + + +// +// Lookup table for combined RGBA data. +// + +class IMF_EXPORT RgbaLut +{ + public: + + //------------ + // Constructor + //------------ + + template + RgbaLut (Function f, RgbaChannels chn = WRITE_RGB); + + + //---------------------------------------------------------------------- + // Apply the table to data[0], data[stride] ... data[(nData-1) * stride] + //---------------------------------------------------------------------- + + void apply (Rgba *data, + int nData, + int stride = 1) const; + + + //----------------------------------------------------------------------- + // Apply the table to a frame buffer (see RgbaOutpuFile.setFrameBuffer()) + //----------------------------------------------------------------------- + + void apply (Rgba *base, + int xStride, + int yStride, + const IMATH_NAMESPACE::Box2i &dataWindow) const; + + private: + + halfFunction _lut; + RgbaChannels _chn; +}; + + +// +// 12bit log rounding reduces data to 20 stops with 200 steps per stop. +// That makes 4000 numbers. An extra 96 just come along for the ride. +// Zero explicitly remains zero. The first non-zero half will map to 1 +// in the 0-4095 12log space. A nice power of two number is placed at +// the center [2000] and that number is near 0.18. +// + +IMF_EXPORT +half round12log (half x); + + +// +// Round to n-bit precision (n should be between 0 and 10). +// After rounding, the significand's 10-n least significant +// bits will be zero. +// + +struct roundNBit +{ + roundNBit (int n): n(n) {} + half operator () (half x) {return x.round(n);} + int n; +}; + + +// +// Template definitions +// + + +template +HalfLut::HalfLut (Function f): + _lut(f, -HALF_MAX, HALF_MAX, half (0), + half::posInf(), half::negInf(), half::qNan()) +{ + // empty +} + + +template +RgbaLut::RgbaLut (Function f, RgbaChannels chn): + _lut(f, -HALF_MAX, HALF_MAX, half (0), + half::posInf(), half::negInf(), half::qNan()), + _chn(chn) +{ + // empty +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfMatrixAttribute.h b/OpenEXR/include/OpenEXR/ImfMatrixAttribute.h new file mode 100644 index 0000000..31f1466 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfMatrixAttribute.h @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_MATRIX_ATTRIBUTE_H +#define INCLUDED_IMF_MATRIX_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class M33fAttribute +// class M33dAttribute +// class M44fAttribute +// class M44dAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImathMatrix.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute M33fAttribute; +template <> IMF_EXPORT const char *M33fAttribute::staticTypeName (); +template <> IMF_EXPORT void M33fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M33fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute M33dAttribute; +template <> IMF_EXPORT const char *M33dAttribute::staticTypeName (); +template <> IMF_EXPORT void M33dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M33dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute M44fAttribute; +template <> IMF_EXPORT const char *M44fAttribute::staticTypeName (); +template <> IMF_EXPORT void M44fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M44fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute M44dAttribute; +template <> IMF_EXPORT const char *M44dAttribute::staticTypeName (); +template <> IMF_EXPORT void M44dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M44dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfMisc.h b/OpenEXR/include/OpenEXR/ImfMisc.h new file mode 100644 index 0000000..cc697e2 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfMisc.h @@ -0,0 +1,466 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_MISC_H +#define INCLUDED_IMF_MISC_H + +//----------------------------------------------------------------------------- +// +// Miscellaneous helper functions for OpenEXR image file I/O +// +//----------------------------------------------------------------------------- + +#include "ImfPixelType.h" +#include "ImfCompressor.h" +#include "ImfArray.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" + +#include +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// Return the size of a single value of the indicated type, +// in the machine's native format. +// + +IMF_EXPORT +int pixelTypeSize (PixelType type); + + +// +// Return the number of samples a channel with subsampling rate +// s has in the interval [a, b]. For example, a channel with +// subsampling rate 2 (and samples at 0, 2, 4, 6, 8, etc.) has +// 2 samples in the interval [1, 5] and three samples in the +// interval [2, 6]. +// + +IMF_EXPORT +int numSamples (int s, int a, int b); + + +// +// Build a table that lists, for each scanline in a file's +// data window, how many bytes are required to store all +// pixels in all channels in that scanline (assuming that +// the pixel data are tightly packed). +// + +IMF_EXPORT +size_t bytesPerLineTable (const Header &header, + std::vector &bytesPerLine); + + +// +// Get the sample count for pixel (x, y) using the array base +// pointer, xStride and yStride. +// + +IMF_EXPORT +int& +sampleCount(char* base, int xStride, int yStride, int x, int y); + + +IMF_EXPORT +const int& +sampleCount(const char* base, int xStride, int yStride, int x, int y); + +// +// Build a table that lists, for each scanline in a DEEP file's +// data window, how many bytes are required to store all +// pixels in all channels in scanlines ranged in [minY, maxY] +// (assuming that the pixel data are tightly packed). +// + +IMF_EXPORT +size_t bytesPerDeepLineTable (const Header &header, + int minY, int maxY, + const char* base, + int xStride, + int yStride, + std::vector &bytesPerLine); + + +// +// Build a table that lists, for each scanline in a DEEP file's +// data window, how many bytes are required to store all +// pixels in all channels in every scanline (assuming that +// the pixel data are tightly packed). +// + +IMF_EXPORT +size_t bytesPerDeepLineTable (const Header &header, + char* base, + int xStride, + int yStride, + std::vector &bytesPerLine); + + +// +// For scanline-based files, pixels are read or written in +// in multi-scanline blocks. Internally, class OutputFile +// and class ScanLineInputFile store a block of scan lines +// in a "line buffer". Function offsetInLineBufferTable() +// builds a table that lists, scanlines within range +// [scanline1, scanline2], the location of the pixel data +// for the scanline relative to the beginning of the line buffer, +// where scanline1 = 0 represents the first line in the DATA WINDOW. +// The one without specifying the range will make scanline1 = 0 +// and scanline2 = bytesPerLine.size(). +// + +IMF_EXPORT +void offsetInLineBufferTable (const std::vector &bytesPerLine, + int scanline1, int scanline2, + int linesInLineBuffer, + std::vector &offsetInLineBuffer); + +IMF_EXPORT +void offsetInLineBufferTable (const std::vector &bytesPerLine, + int linesInLineBuffer, + std::vector &offsetInLineBuffer); + +// +// For a scanline-based file, compute the range of scanlines +// that occupy the same line buffer as a given scanline, y. +// (minY is the minimum y coordinate of the file's data window.) +// + +IMF_EXPORT int lineBufferMinY (int y, int minY, int linesInLineBuffer); +IMF_EXPORT int lineBufferMaxY (int y, int minY, int linesInLineBuffer); + + +// +// Return a compressor's data format (Compressor::NATIVE or Compressor::XDR). +// If compressor is 0, return Compressor::XDR. +// + +IMF_EXPORT +Compressor::Format defaultFormat (Compressor *compressor); + + +// +// Return the number of scan lines a compressor wants to compress +// or uncompress at once. If compressor is 0, return 1. +// + +IMF_EXPORT +int numLinesInBuffer (Compressor *compressor); + + +// +// Copy a single channel of a horizontal row of pixels from an +// input file's internal line buffer or tile buffer into a +// frame buffer slice. If necessary, perform on-the-fly data +// type conversion. +// +// readPtr initially points to the beginning of the +// data in the line or tile buffer. readPtr +// is advanced as the pixel data are copied; +// when copyIntoFrameBuffer() returns, +// readPtr points just past the end of the +// copied data. +// +// writePtr, endPtr point to the lefmost and rightmost pixels +// in the frame buffer slice +// +// xStride the xStride for the frame buffer slice +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// typeInFrameBuffer the pixel data type of the frame buffer slice +// +// typeInFile the pixel data type in the input file's channel +// + +IMF_EXPORT +void copyIntoFrameBuffer (const char *&readPtr, + char *writePtr, + char *endPtr, + size_t xStride, + bool fill, + double fillValue, + Compressor::Format format, + PixelType typeInFrameBuffer, + PixelType typeInFile); + + +// +// Copy a single channel of a horizontal row of pixels from an +// input file's internal line buffer or tile buffer into a +// frame buffer slice. If necessary, perform on-the-fly data +// type conversion. +// +// readPtr initially points to the beginning of the +// data in the line or tile buffer. readPtr +// is advanced as the pixel data are copied; +// when copyIntoFrameBuffer() returns, +// readPtr points just past the end of the +// copied data. +// +// base point to each pixel in the framebuffer +// +// sampleCountBase, provide the number of samples in each pixel +// sampleCountXStride, +// sampleCountYStride +// +// y the scanline to copy. The coordinate is +// relative to the datawindow.min.y. +// +// minX, maxX used to indicate which pixels in the scanline +// will be copied. +// +// xOffsetForSampleCount, used to offset the sample count array +// yOffsetForSampleCount, and the base array. +// xOffsetForData, +// yOffsetForData +// +// xStride the xStride for the frame buffer slice +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// typeInFrameBuffer the pixel data type of the frame buffer slice +// +// typeInFile the pixel data type in the input file's channel +// + +IMF_EXPORT +void copyIntoDeepFrameBuffer (const char *& readPtr, + char * base, + const char* sampleCountBase, + ptrdiff_t sampleCountXStride, + ptrdiff_t sampleCountYStride, + int y, int minX, int maxX, + int xOffsetForSampleCount, + int yOffsetForSampleCount, + int xOffsetForData, + int yOffsetForData, + ptrdiff_t xStride, + ptrdiff_t xPointerStride, + ptrdiff_t yPointerStride, + bool fill, + double fillValue, + Compressor::Format format, + PixelType typeInFrameBuffer, + PixelType typeInFile); + + +// +// Given a pointer into a an input file's line buffer or tile buffer, +// skip over the data for xSize pixels of type typeInFile. +// readPtr initially points to the beginning of the data to be skipped; +// when skipChannel() returns, readPtr points just past the end of the +// skipped data. +// + +IMF_EXPORT +void skipChannel (const char *&readPtr, + PixelType typeInFile, + size_t xSize); + +// +// Convert an array of pixel data from the machine's native +// representation to XDR format. +// +// toPtr, fromPtr initially point to the beginning of the input +// and output pixel data arrays; when convertInPlace() +// returns, toPtr and fromPtr point just past the +// end of the input and output arrays. +// If the native representation of the data has the +// same size as the XDR data, then the conversion +// can take in place, without an intermediate +// temporary buffer (toPtr and fromPtr can point +// to the same location). +// +// type the pixel data type +// +// numPixels number of pixels in the input and output arrays +// + +IMF_EXPORT +void convertInPlace (char *&toPtr, + const char *&fromPtr, + PixelType type, + size_t numPixels); + +// +// Copy a single channel of a horizontal row of pixels from a +// a frame buffer into an output file's internal line buffer or +// tile buffer. +// +// writePtr initially points to the beginning of the +// data in the line or tile buffer. writePtr +// is advanced as the pixel data are copied; +// when copyFromFrameBuffer() returns, +// writePtr points just past the end of the +// copied data. +// +// readPtr, endPtr point to the lefmost and rightmost pixels +// in the frame buffer slice +// +// xStride the xStride for the frame buffer slice +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// type the pixel data type in the frame buffer +// and in the output file's channel (function +// copyFromFrameBuffer() doesn't do on-the-fly +// data type conversion) +// + +IMF_EXPORT +void copyFromFrameBuffer (char *&writePtr, + const char *&readPtr, + const char *endPtr, + size_t xStride, + Compressor::Format format, + PixelType type); + +// +// Copy a single channel of a horizontal row of pixels from a +// a frame buffer in a deep data file into an output file's +// internal line buffer or tile buffer. +// +// writePtr initially points to the beginning of the +// data in the line or tile buffer. writePtr +// is advanced as the pixel data are copied; +// when copyFromDeepFrameBuffer() returns, +// writePtr points just past the end of the +// copied data. +// +// base the start pointer of each pixel in this channel. +// It points to the real data in FrameBuffer. +// It is different for different channels. +// dataWindowMinX and dataWindowMinY are involved in +// locating for base. +// +// sampleCountBase, used to locate the position to get +// sampleCountXStride, the number of samples for each pixel. +// sampleCountYStride Used to determine how far we should +// read based on the pointer provided by base. +// +// y the scanline to copy. If we are dealing +// with a tiled deep file, then probably a portion +// of the scanline is copied. +// +// xMin, xMax used to indicate which pixels in the scanline +// will be copied. +// +// xOffsetForSampleCount, used to offset the sample count array +// yOffsetForSampleCount, and the base array. +// xOffsetForData, +// yOffsetForData +// +// xStride the xStride for the frame buffer slice +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// type the pixel data type in the frame buffer +// and in the output file's channel (function +// copyFromFrameBuffer() doesn't do on-the-fly +// data type conversion) +// + +IMF_EXPORT +void copyFromDeepFrameBuffer (char *& writePtr, + const char * base, + char* sampleCountBase, + ptrdiff_t sampleCountXStride, + ptrdiff_t sampleCountYStride, + int y, int xMin, int xMax, + int xOffsetForSampleCount, + int yOffsetForSampleCount, + int xOffsetForData, + int yOffsetForData, + ptrdiff_t sampleStride, + ptrdiff_t xStrideForData, + ptrdiff_t yStrideForData, + Compressor::Format format, + PixelType type); + +// +// Fill part of an output file's line buffer or tile buffer with +// zeroes. This routine is called when an output file contains +// a channel for which the frame buffer contains no corresponding +// slice. +// +// writePtr initially points to the beginning of the +// data in the line or tile buffer. When +// fillChannelWithZeroes() returns, writePtr +// points just past the end of the zeroed +// data. +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// type the pixel data type in the line or frame buffer. +// +// xSize number of pixels to be filled with zeroes. +// + +IMF_EXPORT +void fillChannelWithZeroes (char *&writePtr, + Compressor::Format format, + PixelType type, + size_t xSize); + +IMF_EXPORT +bool usesLongNames (const Header &header); + + +// +// compute size of chunk offset table - if ignore_attribute set to true +// will compute from the image size and layout, rather than the attribute +// The default behaviour is to read the attribute +// + +IMF_EXPORT +int getChunkOffsetTableSize(const Header& header,bool ignore_attribute=false); + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfMultiPartInputFile.h b/OpenEXR/include/OpenEXR/ImfMultiPartInputFile.h new file mode 100644 index 0000000..51ef9d3 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfMultiPartInputFile.h @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFMULTIPARTINPUTFILE_H_ +#define IMFMULTIPARTINPUTFILE_H_ + +#include "ImfGenericInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfThreading.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT MultiPartInputFile : public GenericInputFile +{ + public: + MultiPartInputFile(const char fileName[], + int numThreads = globalThreadCount(), + bool reconstructChunkOffsetTable = true); + + MultiPartInputFile(IStream& is, + int numThreads = globalThreadCount(), + bool reconstructChunkOffsetTable = true); + + virtual ~MultiPartInputFile(); + + // ---------------------- + // Count of number of parts in file + // --------------------- + int parts() const; + + + //---------------------- + // Access to the headers + //---------------------- + + const Header & header(int n) const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + // =---------------------------------------- + // Check whether the entire chunk offset + // table for the part is written correctly + // ----------------------------------------- + bool partComplete(int part) const; + + + + struct Data; + + + private: + Data* _data; + + MultiPartInputFile(const MultiPartInputFile &); // not implemented + + + // + // used internally by 'Part' types to access individual parts of the multipart file + // + template T* getInputPart(int partNumber); + InputPartData* getPart(int); + + void initialize(); + + + + + friend class InputPart; + friend class ScanLineInputPart; + friend class TiledInputPart; + friend class DeepScanLineInputPart; + friend class DeepTiledInputPart; + + // + // For backward compatibility. + // + + friend class InputFile; + friend class TiledInputFile; + friend class ScanLineInputFile; + friend class DeepScanLineInputFile; + friend class DeepTiledInputFile; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFMULTIPARTINPUTFILE_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfMultiPartOutputFile.h b/OpenEXR/include/OpenEXR/ImfMultiPartOutputFile.h new file mode 100644 index 0000000..d5d6bfc --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfMultiPartOutputFile.h @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// Portions (c) 2012 Weta Digital Ltd +// +// 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 Industrial Light & Magic 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 MULTIPARTOUTPUTFILE_H_ +#define MULTIPARTOUTPUTFILE_H_ + +#include "ImfHeader.h" +#include "ImfGenericOutputFile.h" +#include "ImfForward.h" +#include "ImfThreading.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// Class responsible for handling the writing of multipart images. +// +// Note: Certain attributes are 'common' to all parts. Notably: +// * Display Window +// * Pixel Aspect Ratio +// * Time Code +// * Chromaticities +// The first header forms the basis for the set of attributes that are shared +// across the constituent parts. +// +// Parameters +// headers - pointer to array of headers; one for each part of the image file +// parts - count of number of parts +// overrideSharedAttributes - toggle for the handling of shared attributes. +// set false to check for inconsistencies, true +// to copy the values over from the first header. +// numThreads - number of threads that should be used in encoding the data. +// + +class IMF_EXPORT MultiPartOutputFile : public GenericOutputFile +{ + public: + MultiPartOutputFile(const char fileName[], + const Header * headers, + int parts, + bool overrideSharedAttributes = false, + int numThreads = globalThreadCount()); + + MultiPartOutputFile(OStream & os, + const Header * headers, + int parts, + bool overrideSharedAttributes = false, + int numThreads = globalThreadCount()); + + // + // return number of parts in file + // + int parts() const ; + + + // + // return header for part n + // (note: may have additional attributes compared to that passed to constructor) + // + const Header & header(int n) const; + + ~MultiPartOutputFile(); + + struct Data; + + private: + Data* _data; + + MultiPartOutputFile(const MultiPartOutputFile &); // not implemented + + template T* getOutputPart(int partNumber); + + + friend class OutputPart; + friend class TiledOutputPart; + friend class DeepScanLineOutputPart; + friend class DeepTiledOutputPart; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* MULTIPARTOUTPUTFILE_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfMultiView.h b/OpenEXR/include/OpenEXR/ImfMultiView.h new file mode 100644 index 0000000..127f97d --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfMultiView.h @@ -0,0 +1,187 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007, Weta Digital Ltd +// +// 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 Weta Digital 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_IMF_MULTIVIEW_H +#define INCLUDED_IMF_MULTIVIEW_H + +#include "ImfChannelList.h" +#include "ImfStringVectorAttribute.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + +//----------------------------------------------------------------------------- +// +// Functions related to accessing channels and views in multi-view +// OpenEXR files. +// +// A multi-view image file contains two or more views of the same +// scene, as seen from different viewpoints, for example, a left-eye +// and a right-eye view for stereo displays. Each view has its own +// set of image channels. A naming convention identifies the channels +// that belong to a given view. +// +// A "multiView" attribute in the file header lists the names of the +// views in an image (see ImfStandardAttributes.h), and channel names +// of the form +// +// layer.view.channel +// +// allow channels to be matched with views. +// +// For compatibility with singe-view images, the first view listed in +// the multiView attribute is the "default view", and channels that +// have no periods in their names are considered part of the default +// view. +// +// For example, if a file's multiView attribute lists the views +// "left" and "right", in that order, then "left" is the default +// view. Channels +// +// "R", "left.Z", "diffuse.left.R" +// +// are part of the "left" view; channels +// +// "right.R", "right.Z", "diffuse.right.R" +// +// are part of the "right" view; and channels +// +// "tmp.R", "right.diffuse.R", "diffuse.tmp.R" +// +// belong to no view at all. +// +//----------------------------------------------------------------------------- + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Return the name of the default view given a multi-view string vector, +// that is, return the first element of the string vector. If the string +// vector is empty, return "". +// + +IMF_EXPORT +std::string defaultViewName (const StringVector &multiView); + + +// +// Given the name of a channel, return the name of the view to +// which it belongs. Returns the empty string ("") if the channel +// is not a member of any named view. +// + +IMF_EXPORT +std::string viewFromChannelName (const std::string &channel, + const StringVector &multiView); + + +// +// Return whether channel1 and channel2 are the same channel but +// viewed in different views. (Return false if either channel +// belongs to no view or if both channels belong to the same view.) +// + +IMF_EXPORT +bool areCounterparts (const std::string &channel1, + const std::string &channel2, + const StringVector &multiView); + +// +// Return a list of all channels belonging to view viewName. +// + +IMF_EXPORT +ChannelList channelsInView (const std::string &viewName, + const ChannelList &channelList, + const StringVector &multiView); + +// +// Return a list of channels not associated with any view. +// + +IMF_EXPORT +ChannelList channelsInNoView (const ChannelList &channelList, + const StringVector &multiView); + +// +// Given the name of a channel, return a list of the same channel +// in all views (for example, given X.left.Y return X.left.Y, +// X.right.Y, X.centre.Y, etc.). +// + +IMF_EXPORT +ChannelList channelInAllViews (const std::string &channame, + const ChannelList &channelList, + const StringVector &multiView); + +// +// Given the name of a channel in one view, return the corresponding +// channel name for view otherViewName. Return "" if no corresponding +// channel exists in view otherViewName, or if view otherViewName doesn't +// exist. +// + +IMF_EXPORT +std::string channelInOtherView (const std::string &channel, + const ChannelList &channelList, + const StringVector &multiView, + const std::string &otherViewName); + +// +// Given a channel name that does not include a view name, insert +// multiView[i] into the channel name at the appropriate location. +// If i is zero and the channel name contains no periods, then do +// not insert the view name. +// + +IMF_EXPORT +std::string insertViewName (const std::string &channel, + const StringVector &multiView, + int i); + +// +// Given a channel name that does may include a view name, return +// string without the view name. If the string does not contain +// the view name, return the string unaltered. +// (Will only remove the viewname if it is in the correct position +// in the string) +// + +IMF_EXPORT +std::string removeViewName (const std::string &channel, + const std::string &view); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfName.h b/OpenEXR/include/OpenEXR/ImfName.h new file mode 100644 index 0000000..4d4f25a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfName.h @@ -0,0 +1,150 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_NAME_H +#define INCLUDED_IMF_NAME_H + +//----------------------------------------------------------------------------- +// +// class ImfName -- a zero-terminated string +// with a fixed, small maximum length +// +//----------------------------------------------------------------------------- + +#include +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class Name +{ + public: + + //------------- + // Constructors + //------------- + + Name (); + Name (const char text[]); + + + //-------------------- + // Assignment operator + //-------------------- + + Name & operator = (const char text[]); + + + //--------------------- + // Access to the string + //--------------------- + + const char * text () const {return _text;} + const char * operator * () const {return _text;} + + //--------------- + // Maximum length + //--------------- + + static const int SIZE = 256; + static const int MAX_LENGTH = SIZE - 1; + + private: + + char _text[SIZE]; +}; + + +bool operator == (const Name &x, const Name &y); +bool operator != (const Name &x, const Name &y); +bool operator < (const Name &x, const Name &y); + + +//----------------- +// Inline functions +//----------------- + +inline Name & +Name::operator = (const char text[]) +{ + strncpy (_text, text, MAX_LENGTH); + return *this; +} + + +inline +Name::Name () +{ + _text[0] = 0; +} + + +inline +Name::Name (const char text[]) +{ + *this = text; + _text [MAX_LENGTH] = 0; +} + + +inline bool +operator == (const Name &x, const Name &y) +{ + return strcmp (*x, *y) == 0; +} + + +inline bool +operator != (const Name &x, const Name &y) +{ + return !(x == y); +} + + +inline bool +operator < (const Name &x, const Name &y) +{ + return strcmp (*x, *y) < 0; +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfNamespace.h b/OpenEXR/include/OpenEXR/ImfNamespace.h new file mode 100644 index 0000000..c36a31e --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfNamespace.h @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMFNAMESPACE_H +#define INCLUDED_IMFNAMESPACE_H + +// +// The purpose of this file is to have all of the Imath symbols defined within +// the OPENEXR_IMF_INTERNAL_NAMESPACE namespace rather than the standard Imath +// namespace. Those symbols are made available to client code through the +// OPENEXR_IMF_NAMESPACE in addition to the OPENEXR_IMF_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the OPENEXR_IMF_NAMESPACE defaults to +// Imath and then "using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;" brings all +// of the declarations from the OPENEXR_IMF_INTERNAL_NAMESPACE into the +// OPENEXR_IMF_NAMESPACE. +// This means that client code can continue to use syntax like +// Imf::Header, but at link time it will resolve to a +// mangled symbol based on the OPENEXR_IMF_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of Imath and +// have it run alongside an older version in the same application, it is now +// possible to use an internal namespace to prevent collisions between the +// older versions of Imath symbols and the newer ones. To do this, the +// following could be defined at build time: +// +// OPENEXR_IMF_INTERNAL_NAMESPACE = Imf_v2 +// +// This means that declarations inside Imath headers look like this (after +// the preprocessor has done its work): +// +// namespace Imf_v2 { +// ... +// class declarations +// ... +// } +// +// namespace Imf { +// using namespace IMF_NAMESPACE_v2; +// } +// + +// +// Open Source version of this file pulls in the OpenEXRConfig.h file +// for the configure time options. +// +#include "OpenEXRConfig.h" + + +#ifndef OPENEXR_IMF_NAMESPACE +#define OPENEXR_IMF_NAMESPACE Imf +#endif + +#ifndef OPENEXR_IMF_INTERNAL_NAMESPACE +#define OPENEXR_IMF_INTERNAL_NAMESPACE OPENEXR_IMF_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// OPENEXR_IMF_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// OPENEXR_IMF_NAMESPACE and pulls the internal symbols into the public +// namespace. +// + +namespace OPENEXR_IMF_INTERNAL_NAMESPACE {} +namespace OPENEXR_IMF_NAMESPACE { + using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER namespace OPENEXR_IMF_INTERNAL_NAMESPACE { +#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER namespace OPENEXR_IMF_INTERNAL_NAMESPACE { +#define OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT } + + +#endif /* INCLUDED_IMFNAMESPACE_H */ diff --git a/OpenEXR/include/OpenEXR/ImfOpaqueAttribute.h b/OpenEXR/include/OpenEXR/ImfOpaqueAttribute.h new file mode 100644 index 0000000..1682bfd --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfOpaqueAttribute.h @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_OPAQUE_ATTRIBUTE_H +#define INCLUDED_IMF_OPAQUE_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class OpaqueAttribute +// +// When an image file is read, OpqaqueAttribute objects are used +// to hold the values of attributes whose types are not recognized +// by the reading program. OpaqueAttribute objects can be read +// from an image file, copied, and written back to to another image +// file, but their values are inaccessible. +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfArray.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT OpaqueAttribute: public Attribute +{ + public: + + //---------------------------- + // Constructors and destructor + //---------------------------- + + OpaqueAttribute (const char typeName[]); + OpaqueAttribute (const OpaqueAttribute &other); + virtual ~OpaqueAttribute (); + + + //------------------------------- + // Get this attribute's type name + //------------------------------- + + virtual const char * typeName () const; + + + //------------------------------ + // Make a copy of this attribute + //------------------------------ + + virtual Attribute * copy () const; + + + //---------------- + // I/O and copying + //---------------- + + virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const; + + virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version); + + virtual void copyValueFrom (const Attribute &other); + + + private: + + Array _typeName; + long _dataSize; + Array _data; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfOutputFile.h b/OpenEXR/include/OpenEXR/ImfOutputFile.h new file mode 100644 index 0000000..00f9f80 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfOutputFile.h @@ -0,0 +1,263 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_OUTPUT_FILE_H +#define INCLUDED_IMF_OUTPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class OutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT OutputFile : public GenericOutputFile +{ + public: + + //----------------------------------------------------------- + // Constructor -- opens the file and writes the file header. + // The file header is also copied into the OutputFile object, + // and can later be accessed via the header() method. + // Destroying this OutputFile object automatically closes + // the file. + // + // numThreads determines the number of threads that will be + // used to write the file (see ImfThreading.h). + //----------------------------------------------------------- + + OutputFile (const char fileName[], const Header &header, + int numThreads = globalThreadCount()); + + + //------------------------------------------------------------ + // Constructor -- attaches the new OutputFile object to a file + // that has already been opened, and writes the file header. + // The file header is also copied into the OutputFile object, + // and can later be accessed via the header() method. + // Destroying this OutputFile object does not automatically + // close the file. + // + // numThreads determines the number of threads that will be + // used to write the file (see ImfThreading.h). + //------------------------------------------------------------ + + OutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, + int numThreads = globalThreadCount()); + + + //------------------------------------------------- + // Destructor + // + // Destroying the OutputFile object before writing + // all scan lines within the data window results in + // an incomplete file. + //------------------------------------------------- + + virtual ~OutputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the OutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writePixels() is + // called. The current frame buffer can be changed + // after each call to writePixels. + //------------------------------------------------------- + + void setFrameBuffer (const FrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const FrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------------- + // Write pixel data: + // + // writePixels(n) retrieves the next n scan lines worth of data from + // the current frame buffer, starting with the scan line indicated by + // currentScanLine(), and stores the data in the output file, and + // progressing in the direction indicated by header.lineOrder(). + // + // To produce a complete and correct file, exactly m scan lines must + // be written, where m is equal to + // header().dataWindow().max.y - header().dataWindow().min.y + 1. + //------------------------------------------------------------------- + + void writePixels (int numScanLines = 1); + + + //------------------------------------------------------------------ + // Access to the current scan line: + // + // currentScanLine() returns the y coordinate of the first scan line + // that will be read from the current frame buffer during the next + // call to writePixels(). + // + // If header.lineOrder() == INCREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().min.y. After writing each scan line, + // the current scan line is incremented by 1. + // + // If header.lineOrder() == DECREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().max.y. After writing each scan line, + // the current scan line is decremented by 1. + // + //------------------------------------------------------------------ + + int currentScanLine () const; + + + //-------------------------------------------------------------- + // Shortcut to copy all pixels from an InputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the InputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder" and "channels" attributes must be the same. + //-------------------------------------------------------------- + + void copyPixels (InputFile &in); + + //------------------------------------------------------------- + // Shortcut to copy all pixels from an InputPart into this file + // - equivalent to copyPixel(InputFile &in) but for multipart files + //--------------------------------------------------------------- + + void copyPixels (InputPart &in); + + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few scan lines at a + // time, while the image is being generated. Since the preview + // image is an attribute in the file's header, it gets stored in + // the file as soon as the file is opened, but we may not know + // what the preview image should look like until we have written + // the last scan line of the main image. + // + //-------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba newPixels[]); + + + //--------------------------------------------------------- + // Break a scan line -- for testing and debugging only: + // + // breakScanLine(y,p,n,c) introduces an error into the + // output file by writing n copies of character c, starting + // p bytes from the beginning of the pixel data block that + // contains scan line y. + // + // Warning: Calling this function usually results in a + // broken image file. The file or parts of it may not + // be readable, or the file may contain bad data. + // + //--------------------------------------------------------- + + void breakScanLine (int y, int offset, int length, char c); + + + struct Data; + + private: + + //------------------------------------------------------------ + // Constructor -- attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + //------------------------------------------------------------ + OutputFile (const OutputPartData* part); + + OutputFile (const OutputFile &); // not implemented + OutputFile & operator = (const OutputFile &); // not implemented + + void initialize (const Header &header); + + Data * _data; + + + friend class MultiPartOutputFile; + +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfOutputPart.h b/OpenEXR/include/OpenEXR/ImfOutputPart.h new file mode 100644 index 0000000..41f3cf3 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfOutputPart.h @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFOUTPUTPART_H_ +#define IMFOUTPUTPART_H_ + +#include "ImfMultiPartOutputFile.h" +#include "ImfOutputFile.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +//--------------------------------------------------------------------- +// class OutputPart: +// +// Same interface as OutputFile. Please refer to OutputFile. +//--------------------------------------------------------------------- + +class IMF_EXPORT OutputPart +{ + public: + OutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + const char * fileName () const; + const Header & header () const; + void setFrameBuffer (const FrameBuffer &frameBuffer); + const FrameBuffer & frameBuffer () const; + void writePixels (int numScanLines = 1); + int currentScanLine () const; + void copyPixels (InputFile &in); + void copyPixels (InputPart &in); + + void updatePreviewImage (const PreviewRgba newPixels[]); + void breakScanLine (int y, int offset, int length, char c); + + private: + OutputFile* file; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFOUTPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfPartHelper.h b/OpenEXR/include/OpenEXR/ImfPartHelper.h new file mode 100644 index 0000000..d55cc7b --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfPartHelper.h @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// 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 Weta Digital 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_IMF_PARTHELPER_H +#define INCLUDED_IMF_PARTHELPER_H + +//----------------------------------------------------------------------------- +// +// Functions to help split channels into separate parts: provide a list of +// channels, with desired views. call SplitChannels to assign a part to each +// layer, or correct the name of the channel. +// Also can enumerate the parts in a file and list which parts channels are in +// +// This is a good way to offer a 'create Multipart file' checkbox to the user in a +// write dialog box: Populate a list of MultiViewChannelName objects, +// call SplitChannels with whether single or multipart files are required. +// Then write the number of parts it specifies, using internal_name for the channel +// names in the ChannelList and FrameBuffer objects. There should be no need +// for different codepaths for single part and multipart files +// +// Similarly, on reading a file as a MultiPartInputFile, use GetChannelsInMultiPartFile to +// enumerate all channels in the file, using internal_name in FrameBuffer objects +// to read the channel +// +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfMultiPartInputFile.h" +#include "ImfChannelList.h" +#include "ImfStringVectorAttribute.h" +#include "ImfStandardAttributes.h" +#include "ImfMultiView.h" + +#include +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +struct MultiViewChannelName{ + +public: + std::string name; ///< name of channel + std::string view; ///< view for channel + + int part_number; ///< part number: updated by SplitChannels + std::string internal_name;///< name used in headers: in singlepart mode, may contain viewname + + virtual ~MultiViewChannelName() {} + + //return layer for this channel, or "" if no layer + std::string getLayer() const + { + std::size_t q=name.rfind('.'); + if( q==name.npos ) + { + return ""; + } + return name.substr(0,q); + + } + + std::string getSuffix() const + { + std::size_t q=name.rfind('.'); + if( q==name.npos ) + { + return name; + } + return name.substr(q+1); + + } + +}; + + + +// +///\brief assigns individual channels to different parts based on their layer and view name +/// input is an array, list, vector etc of MultiViewChannelName objects +/// on entry, each MultiViewChannelName name/view must be set (view can be empty if not multiview) +/// +/// if singlepart set, then on exit part_number will be zero, and internal_name will have view name inserted +/// otherwise, each channel will be assigned to a different part based on its layer name and view name +/// +/// @param begin pointer to first MultiViewChannelName item +/// @param end pointer to end of MultiViewChannelName item array +/// @return total number of parts required +// + +template int +SplitChannels(const T & begin,const T & end,bool multipart=true,const std::string & heroView="") +{ + if(!multipart) + { + for(T i=begin;i!=end;i++) + { + i->part_number=0; + + //does this have a view name set? + if(i->view=="") + { + i->internal_name=i->name; + }else{ + + std::string lname = i->getLayer(); + + // no layer, only non-hero views get view name in layer name + + + if(lname=="") + { + if(i->view==heroView) + { + i->internal_name = i->name; + }else{ + i->internal_name = i->view+"."+i->name; + } + }else{ + i->internal_name = lname+"."+i->view+"."+i->getSuffix(); + } + } + } + // single part created + return 1; + }else{ + // step 1: extract individual layers and parts + // for each layer, enumerate which views are active + + std::map< std::string , std::set< std::string > > viewsInLayers; + for(T i=begin;i!=end;i++) + { + viewsInLayers[i->getLayer()].insert(i->view); + } + + // step 2: assign a part number to each layer/view + + std::map< std::pair , int > layerToPart; + + int partCount=0; + + for(std::map< std::string , std::set< std::string > >::const_iterator layer=viewsInLayers.begin(); + layer!=viewsInLayers.end();layer++) + { + // if this layer has a heroView, insert that first + bool layer_has_hero = layer->second.find(heroView)!=layer->second.end(); + if( layer_has_hero ) + { + layerToPart[ std::make_pair(layer->first,heroView) ] = partCount++; + } + + + // insert other layers which aren't the hero view + for(std::set< std::string >::const_iterator view=layer->second.begin(); + view!=layer->second.end();view++) + { + if(*view!=heroView) + { + layerToPart[ std::make_pair(layer->first,*view) ] = partCount++; + } + } + + } + + // step 3: update part number of each provided channel + + for( T i=begin;i!=end;i++) + { + i->internal_name=i->name; + i->part_number = layerToPart[ std::make_pair(i->getLayer(),i->view) ]; + } + + + // return number of parts created + return partCount; + } +} + +// +// populate the chans vector with a list of channels in the file +// and their corresponding part number +// +template void +GetChannelsInMultiPartFile(const MultiPartInputFile & file,T & chans) +{ + bool has_multiview=false; + StringVector mview; + if(file.parts()==1) + { + if(hasMultiView(file.header(0))) + { + mview=multiView(file.header(0)); + has_multiview=true; + } + } + + for(int p=0;p +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +const std::string SCANLINEIMAGE = "scanlineimage"; +const std::string TILEDIMAGE = "tiledimage"; +const std::string DEEPSCANLINE = "deepscanline"; +const std::string DEEPTILE = "deeptile"; + +IMF_EXPORT bool isImage(const std::string& name); + +IMF_EXPORT bool isTiled(const std::string& name); + +IMF_EXPORT bool isDeepData(const std::string& name); + +IMF_EXPORT bool isSupportedType(const std::string& name); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif /* IMFPARTTYPE_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfPixelType.h b/OpenEXR/include/OpenEXR/ImfPixelType.h new file mode 100644 index 0000000..4b8005e --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfPixelType.h @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_PIXEL_TYPE_H +#define INCLUDED_IMF_PIXEL_TYPE_H + +//----------------------------------------------------------------------------- +// +// enum PixelType +// +//----------------------------------------------------------------------------- + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +enum PixelType +{ + UINT = 0, // unsigned int (32 bit) + HALF = 1, // half (16 bit floating point) + FLOAT = 2, // float (32 bit floating point) + + NUM_PIXELTYPES // number of different pixel types +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfPreviewImage.h b/OpenEXR/include/OpenEXR/ImfPreviewImage.h new file mode 100644 index 0000000..dcd2ebe --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfPreviewImage.h @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_PREVIEW_IMAGE_H +#define INCLUDED_IMF_PREVIEW_IMAGE_H + +#include "ImfNamespace.h" +#include "ImfExport.h" + +//----------------------------------------------------------------------------- +// +// class PreviewImage -- a usually small, low-dynamic range image, +// that is intended to be stored in an image file's header. +// +// struct PreviewRgba -- holds the value of a PreviewImage pixel. +// +//----------------------------------------------------------------------------- + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct IMF_EXPORT PreviewRgba +{ + unsigned char r; // Red, green and blue components of + unsigned char g; // the pixel's color; intensity is + unsigned char b; // proportional to pow (x/255, 2.2), + // where x is r, g, or b. + + unsigned char a; // The pixel's alpha; 0 == transparent, + // 255 == opaque. + + PreviewRgba (unsigned char r = 0, + unsigned char g = 0, + unsigned char b = 0, + unsigned char a = 255) + : r(r), g(g), b(b), a(a) {} +}; + + +class IMF_EXPORT PreviewImage +{ + public: + + //-------------------------------------------------------------------- + // Constructor: + // + // PreviewImage(w,h,p) constructs a preview image with w by h pixels + // whose initial values are specified in pixel array p. The x and y + // coordinates of the pixels in p go from 0 to w-1, and from 0 to h-1. + // The pixel with coordinates (x, y) is at address p + y*w + x. + // Pixel (0, 0) is in the upper left corner of the preview image. + // If p is zero, the pixels in the preview image are initialized with + // (r = 0, b = 0, g = 0, a = 255). + // + //-------------------------------------------------------------------- + + PreviewImage (unsigned int width = 0, + unsigned int height = 0, + const PreviewRgba pixels[] = 0); + + //----------------------------------------------------- + // Copy constructor, destructor and assignment operator + //----------------------------------------------------- + + PreviewImage (const PreviewImage &other); + ~PreviewImage (); + + PreviewImage & operator = (const PreviewImage &other); + + + //----------------------------------------------- + // Access to width, height and to the pixel array + //----------------------------------------------- + + unsigned int width () const {return _width;} + unsigned int height () const {return _height;} + + PreviewRgba * pixels () {return _pixels;} + const PreviewRgba * pixels () const {return _pixels;} + + + //---------------------------- + // Access to individual pixels + //---------------------------- + + PreviewRgba & pixel (unsigned int x, unsigned int y) + {return _pixels[y * _width + x];} + + const PreviewRgba & pixel (unsigned int x, unsigned int y) const + {return _pixels[y * _width + x];} + + private: + + unsigned int _width; + unsigned int _height; + PreviewRgba * _pixels; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfPreviewImageAttribute.h b/OpenEXR/include/OpenEXR/ImfPreviewImageAttribute.h new file mode 100644 index 0000000..160e409 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfPreviewImageAttribute.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_PREVIEW_IMAGE_ATTRIBUTE_H +#define INCLUDED_IMF_PREVIEW_IMAGE_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class PreviewImageAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfPreviewImage.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute PreviewImageAttribute; + +template <> +IMF_EXPORT +const char *PreviewImageAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void PreviewImageAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void PreviewImageAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfRational.h b/OpenEXR/include/OpenEXR/ImfRational.h new file mode 100644 index 0000000..ba62b6b --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfRational.h @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_RATIONAL_H +#define INCLUDED_IMF_RATIONAL_H + +#include "ImfExport.h" +#include "ImfNamespace.h" + +//----------------------------------------------------------------------------- +// +// Rational numbers +// +// A rational number is represented as pair of integers, n and d. +// The value of of the rational number is +// +// n/d for d > 0 +// positive infinity for n > 0, d == 0 +// negative infinity for n < 0, d == 0 +// not a number (NaN) for n == 0, d == 0 +// +//----------------------------------------------------------------------------- + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT Rational +{ + public: + + int n; // numerator + unsigned int d; // denominator + + + //---------------------------------------- + // Default constructor, sets value to zero + //---------------------------------------- + + Rational (): n (0), d (1) {} + + + //------------------------------------- + // Constructor, explicitly sets n and d + //------------------------------------- + + Rational (int n, int d): n (n), d (d) {} + + + //---------------------------- + // Constructor, approximates x + //---------------------------- + + explicit Rational (double x); + + + //--------------------------------- + // Approximate conversion to double + //--------------------------------- + + operator double () const {return double (n) / double (d);} +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfRationalAttribute.h b/OpenEXR/include/OpenEXR/ImfRationalAttribute.h new file mode 100644 index 0000000..988fe01 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfRationalAttribute.h @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_RATIONAL_ATTRIBUTE_H +#define INCLUDED_IMF_RATIONAL_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class RationalAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfRational.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute RationalAttribute; + +template <> +IMF_EXPORT +const char *RationalAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void RationalAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void RationalAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfRgba.h b/OpenEXR/include/OpenEXR/ImfRgba.h new file mode 100644 index 0000000..dccba9f --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfRgba.h @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_RGBA_H +#define INCLUDED_IMF_RGBA_H + +//----------------------------------------------------------------------------- +// +// class Rgba +// +//----------------------------------------------------------------------------- + +#include "half.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// RGBA pixel +// + +struct Rgba +{ + half r; + half g; + half b; + half a; + + Rgba () {} + Rgba (half r, half g, half b, half a = 1.f): r (r), g (g), b (b), a (a) {} + + Rgba & operator = (const Rgba &other) + { + r = other.r; + g = other.g; + b = other.b; + a = other.a; + + return *this; + } +}; + + +// +// Channels in an RGBA file +// + +enum RgbaChannels +{ + WRITE_R = 0x01, // Red + WRITE_G = 0x02, // Green + WRITE_B = 0x04, // Blue + WRITE_A = 0x08, // Alpha + + WRITE_Y = 0x10, // Luminance, for black-and-white images, + // or in combination with chroma + + WRITE_C = 0x20, // Chroma (two subsampled channels, RY and BY, + // supported only for scanline-based files) + + WRITE_RGB = 0x07, // Red, green, blue + WRITE_RGBA = 0x0f, // Red, green, blue, alpha + + WRITE_YC = 0x30, // Luminance, chroma + WRITE_YA = 0x18, // Luminance, alpha + WRITE_YCA = 0x38 // Luminance, chroma, alpha +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfRgbaFile.h b/OpenEXR/include/OpenEXR/ImfRgbaFile.h new file mode 100644 index 0000000..10a74a0 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfRgbaFile.h @@ -0,0 +1,346 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_RGBA_FILE_H +#define INCLUDED_IMF_RGBA_FILE_H + + +//----------------------------------------------------------------------------- +// +// Simplified RGBA image I/O +// +// class RgbaOutputFile +// class RgbaInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfRgba.h" +#include "ImathVec.h" +#include "ImathBox.h" +#include "half.h" +#include "ImfThreading.h" +#include +#include "ImfNamespace.h" +#include "ImfForward.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// RGBA output file. +// + +class IMF_EXPORT RgbaOutputFile +{ + public: + + //--------------------------------------------------- + // Constructor -- header is constructed by the caller + //--------------------------------------------------- + + RgbaOutputFile (const char name[], + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, + int numThreads = globalThreadCount()); + + + //---------------------------------------------------- + // Constructor -- header is constructed by the caller, + // file is opened by the caller, destructor will not + // automatically close the file. + //---------------------------------------------------- + + RgbaOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, + int numThreads = globalThreadCount()); + + + //---------------------------------------------------------------- + // Constructor -- header data are explicitly specified as function + // call arguments (empty dataWindow means "same as displayWindow") + //---------------------------------------------------------------- + + RgbaOutputFile (const char name[], + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow = IMATH_NAMESPACE::Box2i(), + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, + int numThreads = globalThreadCount()); + + + //----------------------------------------------- + // Constructor -- like the previous one, but both + // the display window and the data window are + // Box2i (V2i (0, 0), V2i (width - 1, height -1)) + //----------------------------------------------- + + RgbaOutputFile (const char name[], + int width, + int height, + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, + int numThreads = globalThreadCount()); + + + //----------- + // Destructor + //----------- + + virtual ~RgbaOutputFile (); + + + //------------------------------------------------ + // Define a frame buffer as the pixel data source: + // Pixel (x, y) is at address + // + // base + x * xStride + y * yStride + // + //------------------------------------------------ + + void setFrameBuffer (const Rgba *base, + size_t xStride, + size_t yStride); + + + //--------------------------------------------- + // Write pixel data (see class Imf::OutputFile) + //--------------------------------------------- + + void writePixels (int numScanLines = 1); + int currentScanLine () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + const FrameBuffer & frameBuffer () const; + const IMATH_NAMESPACE::Box2i & displayWindow () const; + const IMATH_NAMESPACE::Box2i & dataWindow () const; + float pixelAspectRatio () const; + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + float screenWindowWidth () const; + LineOrder lineOrder () const; + Compression compression () const; + RgbaChannels channels () const; + + + // -------------------------------------------------------------------- + // Update the preview image (see Imf::OutputFile::updatePreviewImage()) + // -------------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba[]); + + + //----------------------------------------------------------------------- + // Rounding control for luminance/chroma images: + // + // If the output file contains luminance and chroma channels (WRITE_YC + // or WRITE_YCA), then the the significands of the luminance and + // chroma values are rounded to roundY and roundC bits respectively (see + // function half::round()). Rounding improves compression with minimal + // image degradation, usually much less than the degradation caused by + // chroma subsampling. By default, roundY is 7, and roundC is 5. + // + // If the output file contains RGB channels or a luminance channel, + // without chroma, then no rounding is performed. + //----------------------------------------------------------------------- + + void setYCRounding (unsigned int roundY, + unsigned int roundC); + + + //---------------------------------------------------- + // Break a scan line -- for testing and debugging only + // (see Imf::OutputFile::updatePreviewImage() + // + // Warning: Calling this function usually results in a + // broken image file. The file or parts of it may not + // be readable, or the file may contain bad data. + // + //---------------------------------------------------- + + void breakScanLine (int y, + int offset, + int length, + char c); + private: + + RgbaOutputFile (const RgbaOutputFile &); // not implemented + RgbaOutputFile & operator = (const RgbaOutputFile &); // not implemented + + class ToYca; + + OutputFile * _outputFile; + ToYca * _toYca; +}; + + +// +// RGBA input file +// + +class IMF_EXPORT RgbaInputFile +{ + public: + + //------------------------------------------------------- + // Constructor -- opens the file with the specified name, + // destructor will automatically close the file. + //------------------------------------------------------- + + RgbaInputFile (const char name[], int numThreads = globalThreadCount()); + + + //----------------------------------------------------------- + // Constructor -- attaches the new RgbaInputFile object to a + // file that has already been opened by the caller. + // Destroying the RgbaInputFile object will not automatically + // close the file. + //----------------------------------------------------------- + + RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount()); + + + //-------------------------------------------------------------- + // Constructors -- the same as the previous two, but the names + // of the red, green, blue, alpha, luminance and chroma channels + // are expected to be layerName.R, layerName.G, etc. + //-------------------------------------------------------------- + + RgbaInputFile (const char name[], + const std::string &layerName, + int numThreads = globalThreadCount()); + + RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + const std::string &layerName, + int numThreads = globalThreadCount()); + + + //----------- + // Destructor + //----------- + + virtual ~RgbaInputFile (); + + + //----------------------------------------------------- + // Define a frame buffer as the pixel data destination: + // Pixel (x, y) is at address + // + // base + x * xStride + y * yStride + // + //----------------------------------------------------- + + void setFrameBuffer (Rgba *base, + size_t xStride, + size_t yStride); + + + //---------------------------------------------------------------- + // Switch to a different layer -- subsequent calls to readPixels() + // will read channels layerName.R, layerName.G, etc. + // After each call to setLayerName(), setFrameBuffer() must be + // called at least once before the next call to readPixels(). + //---------------------------------------------------------------- + + void setLayerName (const std::string &layerName); + + + //------------------------------------------- + // Read pixel data (see class Imf::InputFile) + //------------------------------------------- + + void readPixels (int scanLine1, int scanLine2); + void readPixels (int scanLine); + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + const FrameBuffer & frameBuffer () const; + const IMATH_NAMESPACE::Box2i & displayWindow () const; + const IMATH_NAMESPACE::Box2i & dataWindow () const; + float pixelAspectRatio () const; + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + float screenWindowWidth () const; + LineOrder lineOrder () const; + Compression compression () const; + RgbaChannels channels () const; + const char * fileName () const; + bool isComplete () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + private: + + RgbaInputFile (const RgbaInputFile &); // not implemented + RgbaInputFile & operator = (const RgbaInputFile &); // not implemented + + class FromYca; + + InputFile * _inputFile; + FromYca * _fromYca; + std::string _channelNamePrefix; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfRgbaYca.h b/OpenEXR/include/OpenEXR/ImfRgbaYca.h new file mode 100644 index 0000000..c4c6775 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfRgbaYca.h @@ -0,0 +1,259 @@ +#ifndef INCLUDED_IMF_RGBA_YCA_H +#define INCLUDED_IMF_RGBA_YCA_H + +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm +// Entertainment Company Ltd. Portions contributed and copyright held by +// others as indicated. 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 Industrial Light & Magic 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. +// +////////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------- +// +// Conversion between RGBA (red, green, blue alpha) +// and YCA (luminance, subsampled chroma, alpha) data: +// +// Luminance, Y, is computed as a weighted sum of R, G, and B: +// +// Y = yw.x * R + yw.y * G + yw.z * B +// +// Function computeYw() computes a set of RGB-to-Y weights, yw, +// from a set of primary and white point chromaticities. +// +// Chroma, C, consists of two components, RY and BY: +// +// RY = (R - Y) / Y +// BY = (B - Y) / Y +// +// For efficiency, the x and y subsampling rates for chroma are +// hardwired to 2, and the chroma subsampling and reconstruction +// filters are fixed 27-pixel wide windowed sinc functions. +// +// Starting with an image that has RGBA data for all pixels, +// +// RGBA RGBA RGBA RGBA ... RGBA RGBA +// RGBA RGBA RGBA RGBA ... RGBA RGBA +// RGBA RGBA RGBA RGBA ... RGBA RGBA +// RGBA RGBA RGBA RGBA ... RGBA RGBA +// ... +// RGBA RGBA RGBA RGBA ... RGBA RGBA +// RGBA RGBA RGBA RGBA ... RGBA RGBA +// +// function RGBAtoYCA() converts the pixels to YCA format: +// +// YCA YCA YCA YCA ... YCA YCA +// YCA YCA YCA YCA ... YCA YCA +// YCA YCA YCA YCA ... YCA YCA +// YCA YCA YCA YCA ... YCA YCA +// ... +// YCA YCA YCA YCA ... YCA YCA +// YCA YCA YCA YCA ... YCA YCA +// +// Next, decimateChomaHoriz() eliminates the chroma values from +// the odd-numbered pixels in every scan line: +// +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// ... +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// +// decimateChromaVert() eliminates all chroma values from the +// odd-numbered scan lines: +// +// YCA YA YCA YA ... YCA YA +// YA YA YA YA ... YA YA +// YCA YA YCA YA ... YCA YA +// YA YA YA YA ... YA YA +// ... +// YCA YA YCA YA ... YCA YA +// YA YA YA YA ... YA YA +// +// Finally, roundYCA() reduces the precision of the luminance +// and chroma values so that the pixel data shrink more when +// they are saved in a compressed file. +// +// The output of roundYCA() can be converted back to a set +// of RGBA pixel data that is visually very similar to the +// original RGBA image, by calling reconstructChromaHoriz(), +// reconstructChromaVert(), YCAtoRGBA(), and finally +// fixSaturation(). +// +//----------------------------------------------------------------------------- + +#include "ImfRgba.h" +#include "ImfChromaticities.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +namespace RgbaYca { + + +// +// Width of the chroma subsampling and reconstruction filters +// + +static const int N = 27; +static const int N2 = N / 2; + + +// +// Convert a set of primary chromaticities into a set of weighting +// factors for computing a pixels's luminance, Y, from R, G and B +// + +IMF_EXPORT +IMATH_NAMESPACE::V3f computeYw (const Chromaticities &cr); + + +// +// Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha): +// +// ycaOut[i].g = Y (rgbaIn[i]); +// ycaOut[i].r = RY (rgbaIn[i]); +// ycaOut[i].b = BY (rgbaIn[i]); +// ycaOut[i].a = aIsValid? rgbaIn[i].a: 1 +// +// yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). +// + +IMF_EXPORT +void RGBAtoYCA (const IMATH_NAMESPACE::V3f &yw, + int n, + bool aIsValid, + const Rgba rgbaIn[/*n*/], + Rgba ycaOut[/*n*/]); + +// +// Perform horizontal low-pass filtering and subsampling of +// the chroma channels of an array of n pixels. In order +// to avoid indexing off the ends of the input array during +// low-pass filtering, ycaIn must have N2 extra pixels at +// both ends. Before calling decimateChromaHoriz(), the extra +// pixels should be filled with copies of the first and last +// "real" input pixel. +// + +IMF_EXPORT +void decimateChromaHoriz (int n, + const Rgba ycaIn[/*n+N-1*/], + Rgba ycaOut[/*n*/]); + +// +// Perform vertical chroma channel low-pass filtering and subsampling. +// N scan lines of input pixels are combined into a single scan line +// of output pixels. +// + +IMF_EXPORT +void decimateChromaVert (int n, + const Rgba * const ycaIn[N], + Rgba ycaOut[/*n*/]); + +// +// Round the luminance and chroma channels of an array of YCA +// pixels that has already been filtered and subsampled. +// The signifcands of the pixels' luminance and chroma values +// are rounded to roundY and roundC bits respectively. +// + +IMF_EXPORT +void roundYCA (int n, + unsigned int roundY, + unsigned int roundC, + const Rgba ycaIn[/*n*/], + Rgba ycaOut[/*n*/]); + +// +// For a scan line that has valid chroma data only for every other pixel, +// reconstruct the missing chroma values. +// + +IMF_EXPORT +void reconstructChromaHoriz (int n, + const Rgba ycaIn[/*n+N-1*/], + Rgba ycaOut[/*n*/]); + +// +// For a scan line that has only luminance and no valid chroma data, +// reconstruct chroma from the surronding N scan lines. +// + +IMF_EXPORT +void reconstructChromaVert (int n, + const Rgba * const ycaIn[N], + Rgba ycaOut[/*n*/]); + +// +// Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA. +// This function is the inverse of RGBAtoYCA(). +// yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). +// + +IMF_EXPORT +void YCAtoRGBA (const IMATH_NAMESPACE::V3f &yw, + int n, + const Rgba ycaIn[/*n*/], + Rgba rgbaOut[/*n*/]); + +// +// Eliminate super-saturated pixels: +// +// Converting an image from RGBA to YCA, low-pass filtering chroma, +// and converting the result back to RGBA can produce pixels with +// super-saturated colors, where one or two of the RGB components +// become zero or negative. (The low-pass and reconstruction filters +// introduce some amount of ringing into the chroma components. +// This can lead to negative RGB values near high-contrast edges.) +// +// The fixSaturation() function finds super-saturated pixels and +// corrects them by desaturating their colors while maintaining +// their luminance. fixSaturation() takes three adjacent input +// scan lines, rgbaIn[0], rgbaIn[1], rgbaIn[2], adjusts the +// saturation of rgbaIn[1], and stores the result in rgbaOut. +// + +IMF_EXPORT +void fixSaturation (const IMATH_NAMESPACE::V3f &yw, + int n, + const Rgba * const rgbaIn[3], + Rgba rgbaOut[/*n*/]); + +} // namespace RgbaYca +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfStandardAttributes.h b/OpenEXR/include/OpenEXR/ImfStandardAttributes.h new file mode 100644 index 0000000..4280ac4 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfStandardAttributes.h @@ -0,0 +1,382 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_STANDARD_ATTRIBUTES_H +#define INCLUDED_IMF_STANDARD_ATTRIBUTES_H + +//----------------------------------------------------------------------------- +// +// Optional Standard Attributes -- these attributes are "optional" +// because not every image file header has them, but they define a +// "standard" way to represent commonly used data in the file header. +// +// For each attribute, with name "foo", and type "T", the following +// functions are automatically generated via macros: +// +// void addFoo (Header &header, const T &value); +// bool hasFoo (const Header &header); +// const TypedAttribute & fooAttribute (const Header &header); +// TypedAttribute & fooAttribute (Header &header); +// const T & foo (const Header &Header); +// T & foo (Header &Header); +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfBoxAttribute.h" +#include "ImfChromaticitiesAttribute.h" +#include "ImfEnvmapAttribute.h" +#include "ImfDeepImageStateAttribute.h" +#include "ImfFloatAttribute.h" +#include "ImfKeyCodeAttribute.h" +#include "ImfMatrixAttribute.h" +#include "ImfRationalAttribute.h" +#include "ImfStringAttribute.h" +#include "ImfStringVectorAttribute.h" +#include "ImfTimeCodeAttribute.h" +#include "ImfVecAttribute.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +#define IMF_STD_ATTRIBUTE_DEF(name,suffix,object) \ + \ + OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER \ + IMF_EXPORT void add##suffix (Header &header, const object &v); \ + IMF_EXPORT bool has##suffix (const Header &header); \ + IMF_EXPORT const TypedAttribute & \ + name##Attribute (const Header &header); \ + IMF_EXPORT TypedAttribute & \ + name##Attribute (Header &header); \ + IMF_EXPORT const object & \ + name (const Header &header); \ + IMF_EXPORT object & name (Header &header); \ + OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT \ + +// +// chromaticities -- for RGB images, specifies the CIE (x,y) +// chromaticities of the primaries and the white point +// + +IMF_STD_ATTRIBUTE_DEF (chromaticities, Chromaticities, Chromaticities) + + +// +// whiteLuminance -- for RGB images, defines the luminance, in Nits +// (candelas per square meter) of the RGB value (1.0, 1.0, 1.0). +// +// If the chromaticities and the whiteLuminance of an RGB image are +// known, then it is possible to convert the image's pixels from RGB +// to CIE XYZ tristimulus values (see function RGBtoXYZ() in header +// file ImfChromaticities.h). +// +// + +IMF_STD_ATTRIBUTE_DEF (whiteLuminance, WhiteLuminance, float) + + +// +// adoptedNeutral -- specifies the CIE (x,y) coordinates that should +// be considered neutral during color rendering. Pixels in the image +// file whose (x,y) coordinates match the adoptedNeutral value should +// be mapped to neutral values on the display. +// + +IMF_STD_ATTRIBUTE_DEF (adoptedNeutral, AdoptedNeutral, IMATH_NAMESPACE::V2f) + + +// +// renderingTransform, lookModTransform -- specify the names of the +// CTL functions that implements the intended color rendering and look +// modification transforms for this image. +// + +IMF_STD_ATTRIBUTE_DEF (renderingTransform, RenderingTransform, std::string) +IMF_STD_ATTRIBUTE_DEF (lookModTransform, LookModTransform, std::string) + + +// +// xDensity -- horizontal output density, in pixels per inch. +// The image's vertical output density is xDensity * pixelAspectRatio. +// + +IMF_STD_ATTRIBUTE_DEF (xDensity, XDensity, float) + + +// +// owner -- name of the owner of the image +// + +IMF_STD_ATTRIBUTE_DEF (owner, Owner, std::string) + + +// +// comments -- additional image information in human-readable +// form, for example a verbal description of the image +// + +IMF_STD_ATTRIBUTE_DEF (comments, Comments, std::string) + + +// +// capDate -- the date when the image was created or captured, +// in local time, and formatted as +// +// YYYY:MM:DD hh:mm:ss +// +// where YYYY is the year (4 digits, e.g. 2003), MM is the month +// (2 digits, 01, 02, ... 12), DD is the day of the month (2 digits, +// 01, 02, ... 31), hh is the hour (2 digits, 00, 01, ... 23), mm +// is the minute, and ss is the second (2 digits, 00, 01, ... 59). +// +// + +IMF_STD_ATTRIBUTE_DEF (capDate, CapDate, std::string) + + +// +// utcOffset -- offset of local time at capDate from +// Universal Coordinated Time (UTC), in seconds: +// +// UTC == local time + utcOffset +// + +IMF_STD_ATTRIBUTE_DEF (utcOffset, UtcOffset, float) + + +// +// longitude, latitude, altitude -- for images of real objects, the +// location where the image was recorded. Longitude and latitude are +// in degrees east of Greenwich and north of the equator. Altitude +// is in meters above sea level. For example, Kathmandu, Nepal is +// at longitude 85.317, latitude 27.717, altitude 1305. +// + +IMF_STD_ATTRIBUTE_DEF (longitude, Longitude, float) +IMF_STD_ATTRIBUTE_DEF (latitude, Latitude, float) +IMF_STD_ATTRIBUTE_DEF (altitude, Altitude, float) + + +// +// focus -- the camera's focus distance, in meters +// + +IMF_STD_ATTRIBUTE_DEF (focus, Focus, float) + + +// +// exposure -- exposure time, in seconds +// + +IMF_STD_ATTRIBUTE_DEF (expTime, ExpTime, float) + + +// +// aperture -- the camera's lens aperture, in f-stops (focal length +// of the lens divided by the diameter of the iris opening) +// + +IMF_STD_ATTRIBUTE_DEF (aperture, Aperture, float) + + +// +// isoSpeed -- the ISO speed of the film or image sensor +// that was used to record the image +// + +IMF_STD_ATTRIBUTE_DEF (isoSpeed, IsoSpeed, float) + + +// +// envmap -- if this attribute is present, the image represents +// an environment map. The attribute's value defines how 3D +// directions are mapped to 2D pixel locations. For details +// see header file ImfEnvmap.h +// + +IMF_STD_ATTRIBUTE_DEF (envmap, Envmap, Envmap) + + +// +// keyCode -- for motion picture film frames. Identifies film +// manufacturer, film type, film roll and frame position within +// the roll. +// + +IMF_STD_ATTRIBUTE_DEF (keyCode, KeyCode, KeyCode) + + +// +// timeCode -- time and control code +// + +IMF_STD_ATTRIBUTE_DEF (timeCode, TimeCode, TimeCode) + + +// +// wrapmodes -- determines how texture map images are extrapolated. +// If an OpenEXR file is used as a texture map for 3D rendering, +// texture coordinates (0.0, 0.0) and (1.0, 1.0) correspond to +// the upper left and lower right corners of the data window. +// If the image is mapped onto a surface with texture coordinates +// outside the zero-to-one range, then the image must be extrapolated. +// This attribute tells the renderer how to do this extrapolation. +// The attribute contains either a pair of comma-separated keywords, +// to specify separate extrapolation modes for the horizontal and +// vertical directions; or a single keyword, to specify extrapolation +// in both directions (e.g. "clamp,periodic" or "clamp"). Extra white +// space surrounding the keywords is allowed, but should be ignored +// by the renderer ("clamp, black " is equivalent to "clamp,black"). +// The keywords listed below are predefined; some renderers may support +// additional extrapolation modes: +// +// black pixels outside the zero-to-one range are black +// +// clamp texture coordinates less than 0.0 and greater +// than 1.0 are clamped to 0.0 and 1.0 respectively +// +// periodic the texture image repeats periodically +// +// mirror the texture image repeats periodically, but +// every other instance is mirrored +// + +IMF_STD_ATTRIBUTE_DEF (wrapmodes, Wrapmodes, std::string) + + +// +// framesPerSecond -- defines the nominal playback frame rate for image +// sequences, in frames per second. Every image in a sequence should +// have a framesPerSecond attribute, and the attribute value should be +// the same for all images in the sequence. If an image sequence has +// no framesPerSecond attribute, playback software should assume that +// the frame rate for the sequence is 24 frames per second. +// +// In order to allow exact representation of NTSC frame and field rates, +// framesPerSecond is stored as a rational number. A rational number is +// a pair of integers, n and d, that represents the value n/d. +// +// For the exact values of commonly used frame rates, please see header +// file ImfFramesPerSecond.h. +// + +IMF_STD_ATTRIBUTE_DEF (framesPerSecond, FramesPerSecond, Rational) + + +// +// multiView -- defines the view names for multi-view image files. +// A multi-view image contains two or more views of the same scene, +// as seen from different viewpoints, for example a left-eye and +// a right-eye view for stereo displays. The multiView attribute +// lists the names of the views in an image, and a naming convention +// identifies the channels that belong to each view. +// +// For details, please see header file ImfMultiView.h +// + +IMF_STD_ATTRIBUTE_DEF (multiView , MultiView, StringVector) + + +// +// worldToCamera -- for images generated by 3D computer graphics rendering, +// a matrix that transforms 3D points from the world to the camera coordinate +// space of the renderer. +// +// The camera coordinate space is left-handed. Its origin indicates the +// location of the camera. The positive x and y axes correspond to the +// "right" and "up" directions in the rendered image. The positive z +// axis indicates the camera's viewing direction. (Objects in front of +// the camera have positive z coordinates.) +// +// Camera coordinate space in OpenEXR is the same as in Pixar's Renderman. +// + +IMF_STD_ATTRIBUTE_DEF (worldToCamera, WorldToCamera, IMATH_NAMESPACE::M44f) + + +// +// worldToNDC -- for images generated by 3D computer graphics rendering, a +// matrix that transforms 3D points from the world to the Normalized Device +// Coordinate (NDC) space of the renderer. +// +// NDC is a 2D coordinate space that corresponds to the image plane, with +// positive x and pointing to the right and y positive pointing down. The +// coordinates (0, 0) and (1, 1) correspond to the upper left and lower right +// corners of the OpenEXR display window. +// +// To transform a 3D point in word space into a 2D point in NDC space, +// multiply the 3D point by the worldToNDC matrix and discard the z +// coordinate. +// +// NDC space in OpenEXR is the same as in Pixar's Renderman. +// + +IMF_STD_ATTRIBUTE_DEF (worldToNDC, WorldToNDC, IMATH_NAMESPACE::M44f) + + +// +// deepImageState -- specifies whether the pixels in a deep image are +// sorted and non-overlapping. +// +// Note: this attribute can be set by application code that writes a file +// in order to tell applications that read the file whether the pixel data +// must be cleaned up prior to image processing operations such as flattening. +// The IlmImf library does not verify that the attribute is consistent with +// the actual state of the pixels. Application software may assume that the +// attribute is valid, as long as the software will not crash or lock up if +// any pixels are inconsistent with the deepImageState attribute. +// + +IMF_STD_ATTRIBUTE_DEF (deepImageState, DeepImageState, DeepImageState) + + +// +// originalDataWindow -- if application software crops an image, then it +// should save the data window of the original, un-cropped image in the +// originalDataWindow attribute. +// + +IMF_STD_ATTRIBUTE_DEF + (originalDataWindow, OriginalDataWindow, IMATH_NAMESPACE::Box2i) + + +// +// dwaCompressionLevel -- sets the quality level for images compressed +// with the DWAA or DWAB method. +// + +IMF_STD_ATTRIBUTE_DEF (dwaCompressionLevel, DwaCompressionLevel, float) + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfStringAttribute.h b/OpenEXR/include/OpenEXR/ImfStringAttribute.h new file mode 100644 index 0000000..f5d62d7 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfStringAttribute.h @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_STRING_ATTRIBUTE_H +#define INCLUDED_IMF_STRING_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class StringAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute StringAttribute; + +template <> +IMF_EXPORT +const char *StringAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void StringAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void StringAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfStringVectorAttribute.h b/OpenEXR/include/OpenEXR/ImfStringVectorAttribute.h new file mode 100644 index 0000000..d13ef96 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfStringVectorAttribute.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007, Weta Digital Ltd +// +// 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 Weta Digital 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_IMF_STRINGVECTOR_ATTRIBUTE_H +#define INCLUDED_IMF_STRINGVECTOR_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class StringVectorAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfNamespace.h" + +#include +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +typedef std::vector StringVector; +typedef TypedAttribute StringVectorAttribute; + +template <> +IMF_EXPORT +const char *StringVectorAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void StringVectorAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void StringVectorAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTestFile.h b/OpenEXR/include/OpenEXR/ImfTestFile.h new file mode 100644 index 0000000..d02d3bc --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTestFile.h @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TEST_FILE_H +#define INCLUDED_IMF_TEST_FILE_H + +//----------------------------------------------------------------------------- +// +// Utility routines to test quickly if a given +// file is an OpenEXR file, and whether the +// file is scanline-based or tiled. +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +IMF_EXPORT bool isOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isOpenExrFile (const char fileName[], + bool &isTiled); + +IMF_EXPORT bool isOpenExrFile (const char fileName[], + bool &isTiled, + bool &isDeep); + +IMF_EXPORT bool isOpenExrFile (const char fileName[], + bool &isTiled, + bool &isDeep, + bool &isMultiPart); + +IMF_EXPORT bool isTiledOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isDeepOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isMultiPartOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isOpenExrFile (IStream &is); + +IMF_EXPORT bool isOpenExrFile (IStream &is, + bool &isTiled); + +IMF_EXPORT bool isOpenExrFile (IStream &is, + bool &isTiled, + bool &isDeep); + +IMF_EXPORT bool isOpenExrFile (IStream &is, + bool &isTiled, + bool &isDeep, + bool &isMultiPart); + +IMF_EXPORT bool isTiledOpenExrFile (IStream &is); + +IMF_EXPORT bool isDeepOpenExrFile (IStream &is); + +IMF_EXPORT bool isMultiPartOpenExrFile (IStream &is); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfThreading.h b/OpenEXR/include/OpenEXR/ImfThreading.h new file mode 100644 index 0000000..4d1db04 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfThreading.h @@ -0,0 +1,95 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_THREADING_H +#define INCLUDED_IMF_THREADING_H + +#include "ImfExport.h" +#include "ImfNamespace.h" + +//----------------------------------------------------------------------------- +// +// Threading support for the IlmImf library +// +// The IlmImf library uses threads to perform reading and writing +// of OpenEXR files in parallel. The thread that calls the library +// always performs the actual file IO (this is usually the main +// application thread) whereas a several worker threads perform +// data compression and decompression. The number of worker +// threads can be any non-negative value (a value of zero reverts +// to single-threaded operation). As long as there is at least +// one worker thread, file IO and compression can potentially be +// done concurrently through pinelining. If there are two or more +// worker threads, then pipelining as well as concurrent compression +// of multiple blocks can be performed. +// +// Threading in the Imf library is controllable at two granularities: +// +// * The functions in this file query and control the total number +// of worker threads, which will be created globally for the whole +// library. Regardless of how many input or output files are +// opened simultaneously, the library will use at most this number +// of worker threads to perform all work. The default number of +// global worker threads is zero (i.e. single-threaded operation; +// everything happens in the thread that calls the library). +// +// * Furthermore, it is possible to set the number of threads that +// each input or output file should keep busy. This number can +// be explicitly set for each file. The default behavior is for +// each file to try to occupy all worker threads in the library's +// thread pool. +// +//----------------------------------------------------------------------------- + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +//----------------------------------------------------------------------------- +// Return the number of Imf-global worker threads used for parallel +// compression and decompression of OpenEXR files. +//----------------------------------------------------------------------------- + +IMF_EXPORT int globalThreadCount (); + + +//----------------------------------------------------------------------------- +// Change the number of Imf-global worker threads +//----------------------------------------------------------------------------- + +IMF_EXPORT void setGlobalThreadCount (int count); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTileDescription.h b/OpenEXR/include/OpenEXR/ImfTileDescription.h new file mode 100644 index 0000000..7b219c8 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTileDescription.h @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TILE_DESCRIPTION_H +#define INCLUDED_IMF_TILE_DESCRIPTION_H + +//----------------------------------------------------------------------------- +// +// class TileDescription and enum LevelMode +// +//----------------------------------------------------------------------------- +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +enum LevelMode +{ + ONE_LEVEL = 0, + MIPMAP_LEVELS = 1, + RIPMAP_LEVELS = 2, + + NUM_LEVELMODES // number of different level modes +}; + + +enum LevelRoundingMode +{ + ROUND_DOWN = 0, + ROUND_UP = 1, + + NUM_ROUNDINGMODES // number of different rounding modes +}; + + +class TileDescription +{ + public: + + unsigned int xSize; // size of a tile in the x dimension + unsigned int ySize; // size of a tile in the y dimension + LevelMode mode; + LevelRoundingMode roundingMode; + + TileDescription (unsigned int xs = 32, + unsigned int ys = 32, + LevelMode m = ONE_LEVEL, + LevelRoundingMode r = ROUND_DOWN) + : + xSize (xs), + ySize (ys), + mode (m), + roundingMode (r) + { + // empty + } + + bool + operator == (const TileDescription &other) const + { + return xSize == other.xSize && + ySize == other.ySize && + mode == other.mode && + roundingMode == other.roundingMode; + } +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTileDescriptionAttribute.h b/OpenEXR/include/OpenEXR/ImfTileDescriptionAttribute.h new file mode 100644 index 0000000..a8b69b9 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTileDescriptionAttribute.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TILE_DESCRIPTION_ATTRIBUTE_H +#define INCLUDED_IMF_TILE_DESCRIPTION_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class TileDescriptionAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfTileDescription.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +typedef TypedAttribute TileDescriptionAttribute; + +template <> +IMF_EXPORT +const char * +TileDescriptionAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void +TileDescriptionAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void +TileDescriptionAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTiledInputFile.h b/OpenEXR/include/OpenEXR/ImfTiledInputFile.h new file mode 100644 index 0000000..108ec7a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTiledInputFile.h @@ -0,0 +1,401 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TILED_INPUT_FILE_H +#define INCLUDED_IMF_TILED_INPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class TiledInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "ImfTileDescription.h" +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfTiledOutputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT TiledInputFile : public GenericInputFile +{ + public: + + //-------------------------------------------------------------------- + // A constructor that opens the file with the specified name, and + // reads the file header. The constructor throws an IEX_NAMESPACE::ArgExc + // exception if the file is not tiled. + // The numThreads parameter specifies how many worker threads this + // file will try to keep busy when decompressing individual tiles. + // Destroying TiledInputFile objects constructed with this constructor + // automatically closes the corresponding files. + //-------------------------------------------------------------------- + + TiledInputFile (const char fileName[], + int numThreads = globalThreadCount ()); + + + // ---------------------------------------------------------- + // A constructor that attaches the new TiledInputFile object + // to a file that has already been opened. + // Destroying TiledInputFile objects constructed with this + // constructor does not automatically close the corresponding + // files. + // ---------------------------------------------------------- + + TiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount ()); + + + //----------- + // Destructor + //----------- + + virtual ~TiledInputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledInputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readTile() is called. + // The current frame buffer can be changed after each call + // to readTile(). + //----------------------------------------------------------- + + void setFrameBuffer (const FrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const FrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------ + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window + // (in all levels) are present in the input file, or false if + // any pixels are missing. (Another program may still be busy + // writing the file, or file writing may have been aborted + // prematurely.) + //------------------------------------------------------------ + + bool isComplete () const; + + + //-------------------------------------------------- + // Utility functions: + //-------------------------------------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with + // MIPMAP_LEVELS files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + + //---------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //---------------------------------------------------------- + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + + //-------------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //-------------------------------------------------------------- + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional region of + // valid pixel coordinates for a level with level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------ + // Read pixel data: + // + // readTile(dx, dy, lx, ly) reads the tile with tile + // coordinates (dx, dy), and level number (lx, ly), + // and stores it in the current frame buffer. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readTile(dx, dy, level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It calls + // readTile(dx, dy, level, level). + // + // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow + // reading multiple tiles at once. If multi-threading is used + // the multiple tiles are read concurrently. + // + // Pixels that are outside the pixel coordinate range for the + // tile's level, are never accessed by readTile(). + // + // Attempting to access a tile that is not present in the file + // throws an InputExc exception. + // + //------------------------------------------------------------ + + void readTile (int dx, int dy, int l = 0); + void readTile (int dx, int dy, int lx, int ly); + + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //-------------------------------------------------- + // Read a tile of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement TiledOutputFile::copyPixels()). + // + // for single part files, reads the next tile in the file + // for multipart files, reads the tile specified by dx,dy,lx,ly + // + //-------------------------------------------------- + + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); + + struct Data; + + private: + + friend class InputFile; + friend class MultiPartInputFile; + + TiledInputFile (InputPartData* part); + + TiledInputFile (const TiledInputFile &); // not implemented + TiledInputFile & operator = (const TiledInputFile &); // not implemented + + TiledInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, int version, + int numThreads); + + void initialize (); + void multiPartInitialize(InputPartData* part); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is); + + bool isValidTile (int dx, int dy, + int lx, int ly) const; + + size_t bytesPerLineForTile (int dx, int dy, + int lx, int ly) const; + + void tileOrder(int dx[],int dy[],int lx[],int ly[]) const; + Data * _data; + + friend void TiledOutputFile::copyPixels(TiledInputFile &); +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTiledInputPart.h b/OpenEXR/include/OpenEXR/ImfTiledInputPart.h new file mode 100644 index 0000000..ea44c02 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTiledInputPart.h @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFTILEDINPUTPART_H_ +#define IMFTILEDINPUTPART_H_ + +#include "ImfMultiPartInputFile.h" +#include "ImfTiledInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//----------------------------------------------------------------------------- +// class TiledInputPart: +// +// Same interface as TiledInputFile. Please have a reference to TiledInputFile. +//----------------------------------------------------------------------------- + +class IMF_EXPORT TiledInputPart +{ + public: + TiledInputPart(MultiPartInputFile& multiPartFile, int partNumber); + + const char * fileName () const; + const Header & header () const; + int version () const; + void setFrameBuffer (const FrameBuffer &frameBuffer); + const FrameBuffer & frameBuffer () const; + bool isComplete () const; + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + int levelWidth (int lx) const; + int levelHeight (int ly) const; + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + void readTile (int dx, int dy, int l = 0); + void readTile (int dx, int dy, int lx, int ly); + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); + + private: + TiledInputFile* file; + // for internal use - allow TiledOutputFile access to file for copyPixels + friend class TiledOutputFile; + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFTILEDINPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfTiledOutputFile.h b/OpenEXR/include/OpenEXR/ImfTiledOutputFile.h new file mode 100644 index 0000000..bfd6bea --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTiledOutputFile.h @@ -0,0 +1,495 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TILED_OUTPUT_FILE_H +#define INCLUDED_IMF_TILED_OUTPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class TiledOutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "ImfTileDescription.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct PreviewRgba; + + +class IMF_EXPORT TiledOutputFile : public GenericOutputFile +{ + public: + + //------------------------------------------------------------------- + // A constructor that opens the file with the specified name, and + // writes the file header. The file header is also copied into the + // TiledOutputFile object, and can later be accessed via the header() + // method. + // + // Destroying TiledOutputFile constructed with this constructor + // automatically closes the corresponding files. + // + // The header must contain a TileDescriptionAttribute called "tiles". + // + // The x and y subsampling factors for all image channels must be 1; + // subsampling is not supported. + // + // Tiles can be written to the file in arbitrary order. The line + // order attribute can be used to cause the tiles to be sorted in + // the file. When the file is read later, reading the tiles in the + // same order as they are in the file tends to be significantly + // faster than reading the tiles in random order (see writeTile, + // below). + //------------------------------------------------------------------- + + TiledOutputFile (const char fileName[], + const Header &header, + int numThreads = globalThreadCount ()); + + + // ---------------------------------------------------------------- + // A constructor that attaches the new TiledOutputFile object to + // a file that has already been opened. Destroying TiledOutputFile + // objects constructed with this constructor does not automatically + // close the corresponding files. + // ---------------------------------------------------------------- + + TiledOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + int numThreads = globalThreadCount ()); + + + //----------------------------------------------------- + // Destructor + // + // Destroying a TiledOutputFile object before all tiles + // have been written results in an incomplete file. + //----------------------------------------------------- + + virtual ~TiledOutputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledOutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writeTile() is + // called. The current frame buffer can be changed + // after each call to writeTile(). + //------------------------------------------------------- + + void setFrameBuffer (const FrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + const FrameBuffer & frameBuffer () const; + + + //------------------- + // Utility functions: + //------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with MIPMAP_LEVELS + // files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + + //--------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //--------------------------------------------------------- + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + + //---------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //---------------------------------------------------------- + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a level with + // level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------------ + // Write pixel data: + // + // writeTile(dx, dy, lx, ly) writes the tile with tile + // coordinates (dx, dy), and level number (lx, ly) to + // the file. + // + // dx must lie in the interval [0, numXTiles(lx) - 1] + // dy must lie in the interval [0, numYTiles(ly) - 1] + // + // lx must lie in the interval [0, numXLevels() - 1] + // ly must lie in the inverval [0, numYLevels() - 1] + // + // writeTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls + // writeTile(dx, dy, level, level). + // + // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow + // writing multiple tiles at once. If multi-threading is used + // multiple tiles are written concurrently. The tile coordinates, + // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile + // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the + // tiles are always written in the order specified by the line + // order attribute. Hence, it is not possible to specify an + // "invalid" or empty tile range. + // + // Pixels that are outside the pixel coordinate range for the tile's + // level, are never accessed by writeTile(). + // + // Each tile in the file must be written exactly once. + // + // The file's line order attribute determines the order of the tiles + // in the file: + // + // INCREASING_Y In the file, the tiles for each level are stored + // in a contiguous block. The levels are ordered + // like this: + // + // (0, 0) (1, 0) ... (nx-1, 0) + // (0, 1) (1, 1) ... (nx-1, 1) + // ... + // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) + // + // where nx = numXLevels(), and ny = numYLevels(). + // In an individual level, (lx, ly), the tiles + // are stored in the following order: + // + // (0, 0) (1, 0) ... (tx-1, 0) + // (0, 1) (1, 1) ... (tx-1, 1) + // ... + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // + // where tx = numXTiles(lx), + // and ty = numYTiles(ly). + // + // DECREASING_Y As for INCREASING_Y, the tiles for each level + // are stored in a contiguous block. The levels + // are ordered the same way as for INCREASING_Y, + // but within an individual level, the tiles + // are stored in this order: + // + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // ... + // (0, 1) (1, 1) ... (tx-1, 1) + // (0, 0) (1, 0) ... (tx-1, 0) + // + // + // RANDOM_Y The order of the calls to writeTile() determines + // the order of the tiles in the file. + // + //------------------------------------------------------------------ + + void writeTile (int dx, int dy, int l = 0); + void writeTile (int dx, int dy, int lx, int ly); + + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //------------------------------------------------------------------ + // Shortcut to copy all pixels from a TiledInputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the TiledInputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder", "channels", and "tiles" attributes must be the same. + //------------------------------------------------------------------ + + void copyPixels (TiledInputFile &in); + void copyPixels (TiledInputPart &in); + + + //------------------------------------------------------------------ + // Shortcut to copy all pixels from an InputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the InputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder", "channels", and "tiles" attributes must be the same. + // + // To use this function, the InputFile must be tiled. + //------------------------------------------------------------------ + + void copyPixels (InputFile &in); + void copyPixels (InputPart &in); + + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few tiles at a time, + // while the image is being generated. Since the preview image + // is an attribute in the file's header, it gets stored in the + // file as soon as the file is opened, but we may not know what + // the preview image should look like until we have written the + // last tile of the main image. + // + //-------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba newPixels[]); + + + //------------------------------------------------------------- + // Break a tile -- for testing and debugging only: + // + // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the + // output file by writing n copies of character c, starting + // p bytes from the beginning of the tile with tile coordinates + // (dx, dy) and level number (lx, ly). + // + // Warning: Calling this function usually results in a broken + // image file. The file or parts of it may not be readable, + // or the file may contain bad data. + // + //------------------------------------------------------------- + + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + struct Data; + + private: + + // ---------------------------------------------------------------- + // A constructor attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + // ---------------------------------------------------------------- + TiledOutputFile (const OutputPartData* part); + + TiledOutputFile (const TiledOutputFile &); // not implemented + TiledOutputFile & operator = (const TiledOutputFile &); // not implemented + + void initialize (const Header &header); + + bool isValidTile (int dx, int dy, + int lx, int ly) const; + + size_t bytesPerLineForTile (int dx, int dy, + int lx, int ly) const; + + Data * _data; + + OutputStreamMutex* _streamData; + bool _deleteStream; + + friend class MultiPartOutputFile; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTiledOutputPart.h b/OpenEXR/include/OpenEXR/ImfTiledOutputPart.h new file mode 100644 index 0000000..1af84be --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTiledOutputPart.h @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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 IMFTILEDOUTPUTPART_H_ +#define IMFTILEDOUTPUTPART_H_ + +#include "ImfMultiPartOutputFile.h" +#include "ImfTiledOutputFile.h" +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//------------------------------------------------------------------------------- +// class TiledOutputPart: +// +// Same interface as TiledOutputFile. Please have a reference to TiledOutputFile. +//------------------------------------------------------------------------------- + +class IMF_EXPORT TiledOutputPart +{ + public: + TiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + const char * fileName () const; + const Header & header () const; + void setFrameBuffer (const FrameBuffer &frameBuffer); + const FrameBuffer & frameBuffer () const; + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + int levelWidth (int lx) const; + int levelHeight (int ly) const; + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + void writeTile (int dx, int dy, int l = 0); + void writeTile (int dx, int dy, int lx, int ly); + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + void copyPixels (TiledInputFile &in); + void copyPixels (InputFile &in); + void copyPixels (TiledInputPart &in); + void copyPixels (InputPart &in); + + + void updatePreviewImage (const PreviewRgba newPixels[]); + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + + private: + TiledOutputFile* file; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFTILEDOUTPUTPART_H_ */ diff --git a/OpenEXR/include/OpenEXR/ImfTiledRgbaFile.h b/OpenEXR/include/OpenEXR/ImfTiledRgbaFile.h new file mode 100644 index 0000000..978ba36 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTiledRgbaFile.h @@ -0,0 +1,482 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TILED_RGBA_FILE_H +#define INCLUDED_IMF_TILED_RGBA_FILE_H + +//----------------------------------------------------------------------------- +// +// Simplified RGBA image I/O for tiled files +// +// class TiledRgbaOutputFile +// class TiledRgbaInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathVec.h" +#include "ImathBox.h" +#include "half.h" +#include "ImfTileDescription.h" +#include "ImfRgba.h" +#include "ImfThreading.h" +#include +#include "ImfNamespace.h" +#include "ImfForward.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// Tiled RGBA output file. +// + +class IMF_EXPORT TiledRgbaOutputFile +{ + public: + + //--------------------------------------------------- + // Constructor -- rgbaChannels, tileXSize, tileYSize, + // levelMode, and levelRoundingMode overwrite the + // channel list and tile description attribute in the + // header that is passed as an argument to the + // constructor. + //--------------------------------------------------- + + TiledRgbaOutputFile (const char name[], + const Header &header, + RgbaChannels rgbaChannels, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode = ROUND_DOWN, + int numThreads = globalThreadCount ()); + + + //--------------------------------------------------- + // Constructor -- like the previous one, but the new + // TiledRgbaOutputFile is attached to a file that has + // already been opened by the caller. Destroying + // TiledRgbaOutputFileObjects constructed with this + // constructor does not automatically close the + // corresponding files. + //--------------------------------------------------- + + TiledRgbaOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode = ROUND_DOWN, + int numThreads = globalThreadCount ()); + + + //------------------------------------------------------ + // Constructor -- header data are explicitly specified + // as function call arguments (an empty dataWindow means + // "same as displayWindow") + //------------------------------------------------------ + + TiledRgbaOutputFile (const char name[], + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow = IMATH_NAMESPACE::Box2i(), + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = + IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = ZIP_COMPRESSION, + int numThreads = globalThreadCount ()); + + + //----------------------------------------------- + // Constructor -- like the previous one, but both + // the display window and the data window are + // Box2i (V2i (0, 0), V2i (width - 1, height -1)) + //----------------------------------------------- + + TiledRgbaOutputFile (const char name[], + int width, + int height, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode = ROUND_DOWN, + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = + IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = ZIP_COMPRESSION, + int numThreads = globalThreadCount ()); + + + virtual ~TiledRgbaOutputFile (); + + + //------------------------------------------------ + // Define a frame buffer as the pixel data source: + // Pixel (x, y) is at address + // + // base + x * xStride + y * yStride + // + //------------------------------------------------ + + void setFrameBuffer (const Rgba *base, + size_t xStride, + size_t yStride); + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + const FrameBuffer & frameBuffer () const; + const IMATH_NAMESPACE::Box2i & displayWindow () const; + const IMATH_NAMESPACE::Box2i & dataWindow () const; + float pixelAspectRatio () const; + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + float screenWindowWidth () const; + LineOrder lineOrder () const; + Compression compression () const; + RgbaChannels channels () const; + + + //---------------------------------------------------- + // Utility functions (same as in Imf::TiledOutputFile) + //---------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------------ + // Write pixel data: + // + // writeTile(dx, dy, lx, ly) writes the tile with tile + // coordinates (dx, dy), and level number (lx, ly) to + // the file. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // writeTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls + // writeTile(dx, dy, level, level). + // + // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow + // writing multiple tiles at once. If multi-threading is used + // multiple tiles are written concurrently. + // + // Pixels that are outside the pixel coordinate range for the tile's + // level, are never accessed by writeTile(). + // + // Each tile in the file must be written exactly once. + // + //------------------------------------------------------------------ + + void writeTile (int dx, int dy, int l = 0); + void writeTile (int dx, int dy, int lx, int ly); + + void writeTiles (int dxMin, int dxMax, int dyMin, int dyMax, + int lx, int ly); + + void writeTiles (int dxMin, int dxMax, int dyMin, int dyMax, + int l = 0); + + + // ------------------------------------------------------------------------- + // Update the preview image (see Imf::TiledOutputFile::updatePreviewImage()) + // ------------------------------------------------------------------------- + + void updatePreviewImage (const PreviewRgba[]); + + + //------------------------------------------------ + // Break a tile -- for testing and debugging only + // (see Imf::TiledOutputFile::breakTile()) + // + // Warning: Calling this function usually results + // in a broken image file. The file or parts of + // it may not be readable, or the file may contain + // bad data. + // + //------------------------------------------------ + + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + private: + + // + // Copy constructor and assignment are not implemented + // + + TiledRgbaOutputFile (const TiledRgbaOutputFile &); + TiledRgbaOutputFile & operator = (const TiledRgbaOutputFile &); + + class ToYa; + + TiledOutputFile * _outputFile; + ToYa * _toYa; +}; + + + +// +// Tiled RGBA input file +// + +class IMF_EXPORT TiledRgbaInputFile +{ + public: + + //-------------------------------------------------------- + // Constructor -- opens the file with the specified name. + // Destroying TiledRgbaInputFile objects constructed with + // this constructor automatically closes the corresponding + // files. + //-------------------------------------------------------- + + TiledRgbaInputFile (const char name[], + int numThreads = globalThreadCount ()); + + + //------------------------------------------------------- + // Constructor -- attaches the new TiledRgbaInputFile + // object to a file that has already been opened by the + // caller. + // Destroying TiledRgbaInputFile objects constructed with + // this constructor does not automatically close the + // corresponding files. + //------------------------------------------------------- + + TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount ()); + + + //------------------------------------------------------------ + // Constructors -- the same as the previous two, but the names + // of the red, green, blue, alpha, and luminance channels are + // expected to be layerName.R, layerName.G, etc. + //------------------------------------------------------------ + + TiledRgbaInputFile (const char name[], + const std::string &layerName, + int numThreads = globalThreadCount()); + + TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + const std::string &layerName, + int numThreads = globalThreadCount()); + + //----------- + // Destructor + //----------- + + virtual ~TiledRgbaInputFile (); + + + //----------------------------------------------------- + // Define a frame buffer as the pixel data destination: + // Pixel (x, y) is at address + // + // base + x * xStride + y * yStride + // + //----------------------------------------------------- + + void setFrameBuffer (Rgba *base, + size_t xStride, + size_t yStride); + + //------------------------------------------------------------------- + // Switch to a different layer -- subsequent calls to readTile() + // and readTiles() will read channels layerName.R, layerName.G, etc. + // After each call to setLayerName(), setFrameBuffer() must be called + // at least once before the next call to readTile() or readTiles(). + //------------------------------------------------------------------- + + void setLayerName (const std::string &layerName); + + + //-------------------------- + // Access to the file header + //-------------------------- + + const Header & header () const; + const FrameBuffer & frameBuffer () const; + const IMATH_NAMESPACE::Box2i & displayWindow () const; + const IMATH_NAMESPACE::Box2i & dataWindow () const; + float pixelAspectRatio () const; + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + float screenWindowWidth () const; + LineOrder lineOrder () const; + Compression compression () const; + RgbaChannels channels () const; + const char * fileName () const; + bool isComplete () const; + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + int version () const; + + + //--------------------------------------------------- + // Utility functions (same as in Imf::TiledInputFile) + //--------------------------------------------------- + + unsigned int tileXSize () const; + unsigned int tileYSize () const; + LevelMode levelMode () const; + LevelRoundingMode levelRoundingMode () const; + + int numLevels () const; + int numXLevels () const; + int numYLevels () const; + bool isValidLevel (int lx, int ly) const; + + int levelWidth (int lx) const; + int levelHeight (int ly) const; + + int numXTiles (int lx = 0) const; + int numYTiles (int ly = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + + //---------------------------------------------------------------- + // Read pixel data: + // + // readTile(dx, dy, lx, ly) reads the tile with tile + // coordinates (dx, dy), and level number (lx, ly), + // and stores it in the current frame buffer. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readTile(dx, dy, level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It calls + // readTile(dx, dy, level, level). + // + // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow + // reading multiple tiles at once. If multi-threading is used + // multiple tiles are read concurrently. + // + // Pixels that are outside the pixel coordinate range for the + // tile's level, are never accessed by readTile(). + // + // Attempting to access a tile that is not present in the file + // throws an InputExc exception. + // + //---------------------------------------------------------------- + + void readTile (int dx, int dy, int l = 0); + void readTile (int dx, int dy, int lx, int ly); + + void readTiles (int dxMin, int dxMax, + int dyMin, int dyMax, int lx, int ly); + + void readTiles (int dxMin, int dxMax, + int dyMin, int dyMax, int l = 0); + + private: + + // + // Copy constructor and assignment are not implemented + // + + TiledRgbaInputFile (const TiledRgbaInputFile &); + TiledRgbaInputFile & operator = (const TiledRgbaInputFile &); + + class FromYa; + + TiledInputFile * _inputFile; + FromYa * _fromYa; + std::string _channelNamePrefix; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTimeCode.h b/OpenEXR/include/OpenEXR/ImfTimeCode.h new file mode 100644 index 0000000..751c416 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTimeCode.h @@ -0,0 +1,242 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TIME_CODE_H +#define INCLUDED_IMF_TIME_CODE_H + +#include "ImfExport.h" +#include "ImfNamespace.h" + +//----------------------------------------------------------------------------- +// +// class TimeCode +// +// A TimeCode object stores time and control codes as described +// in SMPTE standard 12M-1999. A TimeCode object contains the +// following fields: +// +// Time Address: +// +// hours integer, range 0 - 23 +// minutes integer, range 0 - 59 +// seconds integer, range 0 - 59 +// frame integer, range 0 - 29 +// +// Flags: +// +// drop frame flag boolean +// color frame flag boolean +// field/phase flag boolean +// bgf0 boolean +// bgf1 boolean +// bgf2 boolean +// +// Binary groups for user-defined data and control codes: +// +// binary group 1 integer, range 0 - 15 +// binary group 2 integer, range 0 - 15 +// ... +// binary group 8 integer, range 0 - 15 +// +// Class TimeCode contains methods to convert between the fields +// listed above and a more compact representation where the fields +// are packed into two unsigned 32-bit integers. In the packed +// integer representations, bit 0 is the least significant bit, +// and bit 31 is the most significant bit of the integer value. +// +// The time address and flags fields can be packed in three +// different ways: +// +// bits packing for packing for packing for +// 24-frame 60-field 50-field +// film television television +// +// 0 - 3 frame units frame units frame units +// 4 - 5 frame tens frame tens frame tens +// 6 unused, set to 0 drop frame flag unused, set to 0 +// 7 unused, set to 0 color frame flag color frame flag +// 8 - 11 seconds units seconds units seconds units +// 12 - 14 seconds tens seconds tens seconds tens +// 15 phase flag field/phase flag bgf0 +// 16 - 19 minutes units minutes units minutes units +// 20 - 22 minutes tens minutes tens minutes tens +// 23 bgf0 bgf0 bgf2 +// 24 - 27 hours units hours units hours units +// 28 - 29 hours tens hours tens hours tens +// 30 bgf1 bgf1 bgf1 +// 31 bgf2 bgf2 field/phase flag +// +// User-defined data and control codes are packed as follows: +// +// bits field +// +// 0 - 3 binary group 1 +// 4 - 7 binary group 2 +// 8 - 11 binary group 3 +// 12 - 15 binary group 4 +// 16 - 19 binary group 5 +// 20 - 23 binary group 6 +// 24 - 27 binary group 7 +// 28 - 31 binary group 8 +// +//----------------------------------------------------------------------------- + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class IMF_EXPORT TimeCode +{ + public: + + //--------------------- + // Bit packing variants + //--------------------- + + enum Packing + { + TV60_PACKING, // packing for 60-field television + TV50_PACKING, // packing for 50-field television + FILM24_PACKING // packing for 24-frame film + }; + + + //------------------------------------- + // Constructors and assignment operator + //------------------------------------- + + TimeCode (); // all fields set to 0 or false + + TimeCode (int hours, + int minutes, + int seconds, + int frame, + bool dropFrame = false, + bool colorFrame = false, + bool fieldPhase = false, + bool bgf0 = false, + bool bgf1 = false, + bool bgf2 = false, + int binaryGroup1 = 0, + int binaryGroup2 = 0, + int binaryGroup3 = 0, + int binaryGroup4 = 0, + int binaryGroup5 = 0, + int binaryGroup6 = 0, + int binaryGroup7 = 0, + int binaryGroup8 = 0); + + TimeCode (unsigned int timeAndFlags, + unsigned int userData = 0, + Packing packing = TV60_PACKING); + + TimeCode (const TimeCode &other); + + TimeCode & operator = (const TimeCode &other); + + + //---------------------------- + // Access to individual fields + //---------------------------- + + int hours () const; + void setHours (int value); + + int minutes () const; + void setMinutes (int value); + + int seconds () const; + void setSeconds (int value); + + int frame () const; + void setFrame (int value); + + bool dropFrame () const; + void setDropFrame (bool value); + + bool colorFrame () const; + void setColorFrame (bool value); + + bool fieldPhase () const; + void setFieldPhase (bool value); + + bool bgf0 () const; + void setBgf0 (bool value); + + bool bgf1 () const; + void setBgf1 (bool value); + + bool bgf2 () const; + void setBgf2 (bool value); + + int binaryGroup (int group) const; // group must be between 1 and 8 + void setBinaryGroup (int group, int value); + + + //--------------------------------- + // Access to packed representations + //--------------------------------- + + unsigned int timeAndFlags (Packing packing = TV60_PACKING) const; + + void setTimeAndFlags (unsigned int value, + Packing packing = TV60_PACKING); + + unsigned int userData () const; + + void setUserData (unsigned int value); + + + //--------- + // Equality + //--------- + + bool operator == (const TimeCode &v) const; + bool operator != (const TimeCode &v) const; + + private: + + unsigned int _time; + unsigned int _user; +}; + + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfTimeCodeAttribute.h b/OpenEXR/include/OpenEXR/ImfTimeCodeAttribute.h new file mode 100644 index 0000000..ccd893a --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfTimeCodeAttribute.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_TIME_CODE_ATTRIBUTE_H +#define INCLUDED_IMF_TIME_CODE_ATTRIBUTE_H + + +//----------------------------------------------------------------------------- +// +// class TimeCodeAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfTimeCode.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute TimeCodeAttribute; + +template <> +IMF_EXPORT +const char *TimeCodeAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void TimeCodeAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; + +template <> +IMF_EXPORT +void TimeCodeAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfVecAttribute.h b/OpenEXR/include/OpenEXR/ImfVecAttribute.h new file mode 100644 index 0000000..8480fe6 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfVecAttribute.h @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_VEC_ATTRIBUTE_H +#define INCLUDED_IMF_VEC_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class V2iAttribute +// class V2fAttribute +// class V2dAttribute +// class V3iAttribute +// class V3fAttribute +// class V3dAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImathVec.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +typedef TypedAttribute V2iAttribute; +template <> IMF_EXPORT const char *V2iAttribute::staticTypeName (); +template <> IMF_EXPORT void V2iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V2iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute V2fAttribute; +template <> IMF_EXPORT const char *V2fAttribute::staticTypeName (); +template <> IMF_EXPORT void V2fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V2fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute V2dAttribute; +template <> IMF_EXPORT const char *V2dAttribute::staticTypeName (); +template <> IMF_EXPORT void V2dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V2dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute V3iAttribute; +template <> IMF_EXPORT const char *V3iAttribute::staticTypeName (); +template <> IMF_EXPORT void V3iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V3iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute V3fAttribute; +template <> IMF_EXPORT const char *V3fAttribute::staticTypeName (); +template <> IMF_EXPORT void V3fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V3fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +typedef TypedAttribute V3dAttribute; +template <> IMF_EXPORT const char *V3dAttribute::staticTypeName (); +template <> IMF_EXPORT void V3dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V3dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#if defined (OPENEXR_IMF_INTERNAL_NAMESPACE_AUTO_EXPOSE) +namespace Imf { using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; } + +#endif + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfVersion.h b/OpenEXR/include/OpenEXR/ImfVersion.h new file mode 100644 index 0000000..de2577f --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfVersion.h @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_VERSION_H +#define INCLUDED_IMF_VERSION_H + +//----------------------------------------------------------------------------- +// +// Magic and version number. +// +//----------------------------------------------------------------------------- + +#include "ImfExport.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// The MAGIC number is stored in the first four bytes of every +// OpenEXR image file. This can be used to quickly test whether +// a given file is an OpenEXR image file (see isImfMagic(), below). +// + +const int MAGIC = 20000630; + + +// +// The second item in each OpenEXR image file, right after the +// magic number, is a four-byte file version identifier. Depending +// on a file's version identifier, a file reader can enable various +// backwards-compatibility switches, or it can quickly reject files +// that it cannot read. +// +// The version identifier is split into an 8-bit version number, +// and a 24-bit flags field. +// + +const int VERSION_NUMBER_FIELD = 0x000000ff; +const int VERSION_FLAGS_FIELD = 0xffffff00; + + +// +// Value that goes into VERSION_NUMBER_FIELD. +// + +const int EXR_VERSION = 2; + + +// +// Flags that can go into VERSION_FLAGS_FIELD. +// Flags can only occupy the 1 bits in VERSION_FLAGS_FIELD. +// + +const int TILED_FLAG = 0x00000200; // File is tiled + +const int LONG_NAMES_FLAG = 0x00000400; // File contains long + // attribute or channel + // names + +const int NON_IMAGE_FLAG = 0x00000800; // File has at least one part + // which is not a regular + // scanline image or regular tiled image + // (that is, it is a deep format) + +const int MULTI_PART_FILE_FLAG = 0x00001000; // File has multiple parts + +// +// Bitwise OR of all known flags. +// + +const int ALL_FLAGS = TILED_FLAG | LONG_NAMES_FLAG | + NON_IMAGE_FLAG | MULTI_PART_FILE_FLAG; + + +// +// Utility functions +// + +inline bool isTiled (int version) {return !!(version & TILED_FLAG);} +inline bool isMultiPart (int version) {return version & MULTI_PART_FILE_FLAG; } +inline bool isNonImage(int version) {return version & NON_IMAGE_FLAG; } +inline int makeTiled (int version) {return version | TILED_FLAG;} +inline int makeNotTiled (int version) {return version & ~TILED_FLAG;} +inline int getVersion (int version) {return version & VERSION_NUMBER_FIELD;} +inline int getFlags (int version) {return version & VERSION_FLAGS_FIELD;} +inline bool supportsFlags (int flags) {return !(flags & ~ALL_FLAGS);} + + +// +// Given the first four bytes of a file, returns true if the +// file is probably an OpenEXR image file, false if not. +// + +IMF_EXPORT +bool isImfMagic (const char bytes[4]); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfWav.h b/OpenEXR/include/OpenEXR/ImfWav.h new file mode 100644 index 0000000..9751433 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfWav.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_WAV_H +#define INCLUDED_IMF_WAV_H + +//----------------------------------------------------------------------------- +// +// 16-bit Haar Wavelet encoding and decoding +// +//----------------------------------------------------------------------------- +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +IMF_EXPORT +void +wav2Encode + (unsigned short *in, // io: values in[y][x] are transformed in place + int nx, // i : x size + int ox, // i : x offset + int ny, // i : y size + int oy, // i : y offset + unsigned short mx); // i : maximum in[x][y] value + +IMF_EXPORT +void +wav2Decode + (unsigned short *in, // io: values in[y][x] are transformed in place + int nx, // i : x size + int ox, // i : x offset + int ny, // i : y size + int oy, // i : y offset + unsigned short mx); // i : maximum in[x][y] value + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif diff --git a/OpenEXR/include/OpenEXR/ImfXdr.h b/OpenEXR/include/OpenEXR/ImfXdr.h new file mode 100644 index 0000000..0af6f67 --- /dev/null +++ b/OpenEXR/include/OpenEXR/ImfXdr.h @@ -0,0 +1,927 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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_IMF_XDR_H +#define INCLUDED_IMF_XDR_H + + +//---------------------------------------------------------------------------- +// +// Xdr -- routines to convert data between the machine's native +// format and a machine-independent external data representation: +// +// write (T &o, S v); converts a value, v, of type S +// into a machine-independent +// representation and stores the +// result in an output buffer, o. +// +// read (T &i, S &v); reads the machine-independent +// representation of a value of type +// S from input buffer i, converts +// the value into the machine's native +// representation, and stores the result +// in v. +// +// size(); returns the size, in bytes, of the +// machine-independent representation +// of an object of type S. +// +// The write() and read() routines are templates; data can be written +// to and read from any output or input buffer type T for which a helper +// class, R, exits. Class R must define a method to store a char array +// in a T, and a method to read a char array from a T: +// +// struct R +// { +// static void +// writeChars (T &o, const char c[/*n*/], int n) +// { +// ... // Write c[0], c[1] ... c[n-1] to output buffer o. +// } +// +// static void +// readChars (T &i, char c[/*n*/], int n) +// { +// ... // Read n characters from input buffer i +// // and copy them to c[0], c[1] ... c[n-1]. +// } +// }; +// +// Example - writing to and reading from iostreams: +// +// struct CharStreamIO +// { +// static void +// writeChars (ostream &os, const char c[], int n) +// { +// os.write (c, n); +// } +// +// static void +// readChars (istream &is, char c[], int n) +// { +// is.read (c, n); +// } +// }; +// +// ... +// +// Xdr::write (os, 3); +// Xdr::write (os, 5.0); +// +//---------------------------------------------------------------------------- + +#include "ImfInt64.h" +#include "IexMathExc.h" +#include "half.h" +#include + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +namespace Xdr { + + +//------------------------------- +// Write data to an output stream +//------------------------------- + +template +void +write (T &out, bool v); + +template +void +write (T &out, char v); + +template +void +write (T &out, signed char v); + +template +void +write (T &out, unsigned char v); + +template +void +write (T &out, signed short v); + +template +void +write (T &out, unsigned short v); + +template +void +write (T &out, signed int v); + +template +void +write (T &out, unsigned int v); + +template +void +write (T &out, signed long v); + +template +void +write (T &out, unsigned long v); + +#if ULONG_MAX != 18446744073709551615LU + + template + void + write (T &out, Int64 v); + +#endif + +template +void +write (T &out, float v); + +template +void +write (T &out, double v); + +template +void +write (T &out, half v); + +template +void +write (T &out, const char v[/*n*/], int n); // fixed-size char array + +template +void +write (T &out, const char v[]); // zero-terminated string + + +//----------------------------------------- +// Append padding bytes to an output stream +//----------------------------------------- + +template +void +pad (T &out, int n); // write n padding bytes + + + +//------------------------------- +// Read data from an input stream +//------------------------------- + +template +void +read (T &in, bool &v); + +template +void +read (T &in, char &v); + +template +void +read (T &in, signed char &v); + +template +void +read (T &in, unsigned char &v); + +template +void +read (T &in, signed short &v); + +template +void +read (T &in, unsigned short &v); + +template +void +read (T &in, signed int &v); + +template +void +read (T &in, unsigned int &v); + +template +void +read (T &in, signed long &v); + +template +void +read (T &in, unsigned long &v); + +#if ULONG_MAX != 18446744073709551615LU + + template + void + read (T &in, Int64 &v); + +#endif + +template +void +read (T &in, float &v); + +template +void +read (T &in, double &v); + +template +void +read (T &in, half &v); + +template +void +read (T &in, char v[/*n*/], int n); // fixed-size char array + +template +void +read (T &in, int n, char v[/*n*/]); // zero-terminated string + + +//------------------------------------------- +// Skip over padding bytes in an input stream +//------------------------------------------- + +template +void +skip (T &in, int n); // skip n padding bytes + + + +//-------------------------------------- +// Size of the machine-independent +// representation of an object of type S +//-------------------------------------- + +template +int +size (); + + +//--------------- +// Implementation +//--------------- + +template +inline void +writeSignedChars (T &out, const signed char c[], int n) +{ + S::writeChars (out, (const char *) c, n); +} + + +template +inline void +writeUnsignedChars (T &out, const unsigned char c[], int n) +{ + S::writeChars (out, (const char *) c, n); +} + + +template +inline void +readSignedChars (T &in, signed char c[], int n) +{ + S::readChars (in, (char *) c, n); +} + + +template +inline void +readUnsignedChars (T &in, unsigned char c[], int n) +{ + S::readChars (in, (char *) c, n); +} + + +template +inline void +write (T &out, bool v) +{ + char c = !!v; + S::writeChars (out, &c, 1); +} + + +template +inline void +write (T &out, char v) +{ + S::writeChars (out, &v, 1); +} + + +template +inline void +write (T &out, signed char v) +{ + writeSignedChars (out, &v, 1); +} + + +template +inline void +write (T &out, unsigned char v) +{ + writeUnsignedChars (out, &v, 1); +} + + +template +void +write (T &out, signed short v) +{ + signed char b[2]; + + b[0] = (signed char) (v); + b[1] = (signed char) (v >> 8); + + writeSignedChars (out, b, 2); +} + + +template +void +write (T &out, unsigned short v) +{ + unsigned char b[2]; + + b[0] = (unsigned char) (v); + b[1] = (unsigned char) (v >> 8); + + writeUnsignedChars (out, b, 2); +} + + +template +void +write (T &out, signed int v) +{ + signed char b[4]; + + b[0] = (signed char) (v); + b[1] = (signed char) (v >> 8); + b[2] = (signed char) (v >> 16); + b[3] = (signed char) (v >> 24); + + writeSignedChars (out, b, 4); +} + + +template +void +write (T &out, unsigned int v) +{ + unsigned char b[4]; + + b[0] = (unsigned char) (v); + b[1] = (unsigned char) (v >> 8); + b[2] = (unsigned char) (v >> 16); + b[3] = (unsigned char) (v >> 24); + + writeUnsignedChars (out, b, 4); +} + + +template +void +write (T &out, signed long v) +{ + signed char b[8]; + + b[0] = (signed char) (v); + b[1] = (signed char) (v >> 8); + b[2] = (signed char) (v >> 16); + b[3] = (signed char) (v >> 24); + + #if LONG_MAX == 2147483647 + + if (v >= 0) + { + b[4] = 0; + b[5] = 0; + b[6] = 0; + b[7] = 0; + } + else + { + b[4] = ~0; + b[5] = ~0; + b[6] = ~0; + b[7] = ~0; + } + + #elif LONG_MAX == 9223372036854775807L + + b[4] = (signed char) (v >> 32); + b[5] = (signed char) (v >> 40); + b[6] = (signed char) (v >> 48); + b[7] = (signed char) (v >> 56); + + #else + + #error write (T &out, signed long v) not implemented + + #endif + + writeSignedChars (out, b, 8); +} + + +template +void +write (T &out, unsigned long v) +{ + unsigned char b[8]; + + b[0] = (unsigned char) (v); + b[1] = (unsigned char) (v >> 8); + b[2] = (unsigned char) (v >> 16); + b[3] = (unsigned char) (v >> 24); + + #if ULONG_MAX == 4294967295U + + b[4] = 0; + b[5] = 0; + b[6] = 0; + b[7] = 0; + + #elif ULONG_MAX == 18446744073709551615LU + + b[4] = (unsigned char) (v >> 32); + b[5] = (unsigned char) (v >> 40); + b[6] = (unsigned char) (v >> 48); + b[7] = (unsigned char) (v >> 56); + + #else + + #error write (T &out, unsigned long v) not implemented + + #endif + + writeUnsignedChars (out, b, 8); +} + + +#if ULONG_MAX != 18446744073709551615LU + + template + void + write (T &out, Int64 v) + { + unsigned char b[8]; + + b[0] = (unsigned char) (v); + b[1] = (unsigned char) (v >> 8); + b[2] = (unsigned char) (v >> 16); + b[3] = (unsigned char) (v >> 24); + b[4] = (unsigned char) (v >> 32); + b[5] = (unsigned char) (v >> 40); + b[6] = (unsigned char) (v >> 48); + b[7] = (unsigned char) (v >> 56); + + writeUnsignedChars (out, b, 8); + } + +#endif + + +template +void +write (T &out, float v) +{ + union {unsigned int i; float f;} u; + u.f = v; + + unsigned char b[4]; + + b[0] = (unsigned char) (u.i); + b[1] = (unsigned char) (u.i >> 8); + b[2] = (unsigned char) (u.i >> 16); + b[3] = (unsigned char) (u.i >> 24); + + writeUnsignedChars (out, b, 4); +} + + +template +void +write (T &out, double v) +{ + union {Int64 i; double d;} u; + u.d = v; + + unsigned char b[8]; + + b[0] = (unsigned char) (u.i); + b[1] = (unsigned char) (u.i >> 8); + b[2] = (unsigned char) (u.i >> 16); + b[3] = (unsigned char) (u.i >> 24); + b[4] = (unsigned char) (u.i >> 32); + b[5] = (unsigned char) (u.i >> 40); + b[6] = (unsigned char) (u.i >> 48); + b[7] = (unsigned char) (u.i >> 56); + + writeUnsignedChars (out, b, 8); +} + + +template +inline void +write (T &out, half v) +{ + unsigned char b[2]; + + b[0] = (unsigned char) (v.bits()); + b[1] = (unsigned char) (v.bits() >> 8); + + writeUnsignedChars (out, b, 2); +} + + +template +inline void +write (T &out, const char v[], int n) // fixed-size char array +{ + S::writeChars (out, v, n); +} + + +template +void +write (T &out, const char v[]) // zero-terminated string +{ + while (*v) + { + S::writeChars (out, v, 1); + ++v; + } + + S::writeChars (out, v, 1); +} + + +template +void +pad (T &out, int n) // add n padding bytes +{ + for (int i = 0; i < n; i++) + { + const char c = 0; + S::writeChars (out, &c, 1); + } +} + + +template +inline void +read (T &in, bool &v) +{ + char c; + + S::readChars (in, &c, 1); + v = !!c; +} + + +template +inline void +read (T &in, char &v) +{ + S::readChars (in, &v, 1); +} + + +template +inline void +read (T &in, signed char &v) +{ + readSignedChars (in, &v, 1); +} + + +template +inline void +read (T &in, unsigned char &v) +{ + readUnsignedChars (in, &v, 1); +} + + +template +void +read (T &in, signed short &v) +{ + signed char b[2]; + + readSignedChars (in, b, 2); + + v = (b[0] & 0x00ff) | + (b[1] << 8); +} + + +template +void +read (T &in, unsigned short &v) +{ + unsigned char b[2]; + + readUnsignedChars (in, b, 2); + + v = (b[0] & 0x00ff) | + (b[1] << 8); +} + + +template +void +read (T &in, signed int &v) +{ + signed char b[4]; + + readSignedChars (in, b, 4); + + v = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); +} + + +template +void +read (T &in, unsigned int &v) +{ + unsigned char b[4]; + + readUnsignedChars (in, b, 4); + + v = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); +} + + +template +void +read (T &in, signed long &v) +{ + signed char b[8]; + + readSignedChars (in, b, 8); + + #if LONG_MAX == 2147483647 + + v = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); + + if (( b[4] || b[5] || b[6] || b[7]) && + (~b[4] || ~b[5] || ~b[6] || ~b[7])) + { + throw IEX_NAMESPACE::OverflowExc ("Long int overflow - read a large " + "64-bit integer in a 32-bit process."); + } + + #elif LONG_MAX == 9223372036854775807L + + v = ((long) b[0] & 0x00000000000000ff) | + (((long) b[1] << 8) & 0x000000000000ff00) | + (((long) b[2] << 16) & 0x0000000000ff0000) | + (((long) b[3] << 24) & 0x00000000ff000000) | + (((long) b[4] << 32) & 0x000000ff00000000) | + (((long) b[5] << 40) & 0x0000ff0000000000) | + (((long) b[6] << 48) & 0x00ff000000000000) | + ((long) b[7] << 56); + + #else + + #error read (T &in, signed long &v) not implemented + + #endif +} + + +template +void +read (T &in, unsigned long &v) +{ + unsigned char b[8]; + + readUnsignedChars (in, b, 8); + + #if ULONG_MAX == 4294967295U + + v = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); + + if (b[4] || b[5] || b[6] || b[7]) + { + throw IEX_NAMESPACE::OverflowExc ("Long int overflow - read a large " + "64-bit integer in a 32-bit process."); + } + + #elif ULONG_MAX == 18446744073709551615LU + + v = ((unsigned long) b[0] & 0x00000000000000ff) | + (((unsigned long) b[1] << 8) & 0x000000000000ff00) | + (((unsigned long) b[2] << 16) & 0x0000000000ff0000) | + (((unsigned long) b[3] << 24) & 0x00000000ff000000) | + (((unsigned long) b[4] << 32) & 0x000000ff00000000) | + (((unsigned long) b[5] << 40) & 0x0000ff0000000000) | + (((unsigned long) b[6] << 48) & 0x00ff000000000000) | + ((unsigned long) b[7] << 56); + + #else + + #error read (T &in, unsigned long &v) not implemented + + #endif +} + + +#if ULONG_MAX != 18446744073709551615LU + + template + void + read (T &in, Int64 &v) + { + unsigned char b[8]; + + readUnsignedChars (in, b, 8); + + v = ((Int64) b[0] & 0x00000000000000ffLL) | + (((Int64) b[1] << 8) & 0x000000000000ff00LL) | + (((Int64) b[2] << 16) & 0x0000000000ff0000LL) | + (((Int64) b[3] << 24) & 0x00000000ff000000LL) | + (((Int64) b[4] << 32) & 0x000000ff00000000LL) | + (((Int64) b[5] << 40) & 0x0000ff0000000000LL) | + (((Int64) b[6] << 48) & 0x00ff000000000000LL) | + ((Int64) b[7] << 56); + } + +#endif + + +template +void +read (T &in, float &v) +{ + unsigned char b[4]; + + readUnsignedChars (in, b, 4); + + union {unsigned int i; float f;} u; + + u.i = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); + + v = u.f; +} + + +template +void +read (T &in, double &v) +{ + unsigned char b[8]; + + readUnsignedChars (in, b, 8); + + union {Int64 i; double d;} u; + + u.i = ((Int64) b[0] & 0x00000000000000ffULL) | + (((Int64) b[1] << 8) & 0x000000000000ff00ULL) | + (((Int64) b[2] << 16) & 0x0000000000ff0000ULL) | + (((Int64) b[3] << 24) & 0x00000000ff000000ULL) | + (((Int64) b[4] << 32) & 0x000000ff00000000ULL) | + (((Int64) b[5] << 40) & 0x0000ff0000000000ULL) | + (((Int64) b[6] << 48) & 0x00ff000000000000ULL) | + ((Int64) b[7] << 56); + + v = u.d; +} + + +template +inline void +read (T &in, half &v) +{ + unsigned char b[2]; + + readUnsignedChars (in, b, 2); + + v.setBits ((b[0] & 0x00ff) | (b[1] << 8)); +} + + +template +inline void +read (T &in, char v[], int n) // fixed-size char array +{ + S::readChars (in, v, n); +} + + +template +void +read (T &in, int n, char v[]) // zero-terminated string +{ + while (n >= 0) + { + S::readChars (in, v, 1); + + if (*v == 0) + break; + + --n; + ++v; + } +} + + +template +void +skip (T &in, int n) // skip n padding bytes +{ + char c[1024]; + + while (n >= (int) sizeof (c)) + { + if (!S::readChars (in, c, sizeof (c))) + return; + + n -= sizeof (c); + } + + if (n >= 1) + S::readChars (in, c, n); +} + + +template <> inline int size () {return 1;} +template <> inline int size () {return 1;} +template <> inline int size () {return 1;} +template <> inline int size () {return 1;} +template <> inline int size () {return 2;} +template <> inline int size () {return 2;} +template <> inline int size () {return 4;} +template <> inline int size () {return 4;} +template <> inline int size () {return 8;} +template <> inline int size () {return 8;} +template <> inline int size () {return 8;} +template <> inline int size () {return 4;} +template <> inline int size () {return 8;} +template <> inline int size () {return 2;} + + +} // namespace Xdr +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#if defined (OPENEXR_IMF_INTERNAL_NAMESPACE_AUTO_EXPOSE) +namespace Imf{using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;} +#endif + + +#endif diff --git a/OpenEXR/include/OpenEXR/OpenEXRConfig.h b/OpenEXR/include/OpenEXR/OpenEXRConfig.h new file mode 100644 index 0000000..a92067d --- /dev/null +++ b/OpenEXR/include/OpenEXR/OpenEXRConfig.h @@ -0,0 +1,73 @@ +/* config/OpenEXRConfig.h. Generated from OpenEXRConfig.h.in by configure. */ +// +// Define and set to 1 if the target system supports a proc filesystem +// compatible with the Linux kernel's proc filesystem. Note that this +// is only used by a program in the IlmImfTest test suite, it's not +// used by any OpenEXR library or application code. +// + +#define OPENEXR_IMF_HAVE_LINUX_PROCFS 1 + +// +// Define and set to 1 if the target system is a Darwin-based system +// (e.g., OS X). +// + +/* #undef OPENEXR_IMF_HAVE_DARWIN */ + +// +// Define and set to 1 if the target system has a complete +// implementation, specifically if it supports the std::right +// formatter. +// + +#define OPENEXR_IMF_HAVE_COMPLETE_IOMANIP 1 + +// +// Define and set to 1 if the target system has support for large +// stack sizes. +// + +#define OPENEXR_IMF_HAVE_LARGE_STACK 1 + +// +// Define if we can support GCC style inline asm with AVX instructions +// + +#define OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX 1 + +// +// Define if we can use sysconf(_SC_NPROCESSORS_ONLN) to get CPU count +// + +#define OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN 1 + +// +// Current internal library namepace name +// +#define OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM 1 +#define OPENEXR_IMF_INTERNAL_NAMESPACE Imf_2_2 + +// +// Current public user namepace name +// + +/* #undef OPENEXR_IMF_NAMESPACE_CUSTOM */ +#define OPENEXR_IMF_NAMESPACE Imf + +// +// Version string for runtime access +// + +#define OPENEXR_VERSION_STRING "2.2.0" +#define OPENEXR_PACKAGE_STRING "OpenEXR 2.2.0" + +#define OPENEXR_VERSION_MAJOR 2 +#define OPENEXR_VERSION_MINOR 2 +#define OPENEXR_VERSION_PATCH 0 + +// Version as a single hex number, e.g. 0x01000300 == 1.0.3 +#define OPENEXR_VERSION_HEX ((OPENEXR_VERSION_MAJOR << 24) | \ + (OPENEXR_VERSION_MINOR << 16) | \ + (OPENEXR_VERSION_PATCH << 8)) + diff --git a/OpenEXR/include/OpenEXR/half.h b/OpenEXR/include/OpenEXR/half.h new file mode 100644 index 0000000..f78e4f6 --- /dev/null +++ b/OpenEXR/include/OpenEXR/half.h @@ -0,0 +1,757 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + +// Primary authors: +// Florian Kainz +// Rod Bogart + +//--------------------------------------------------------------------------- +// +// half -- a 16-bit floating point number class: +// +// Type half can represent positive and negative numbers whose +// magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative +// error of 9.8e-4; numbers smaller than 6.1e-5 can be represented +// with an absolute error of 6.0e-8. All integers from -2048 to +// +2048 can be represented exactly. +// +// Type half behaves (almost) like the built-in C++ floating point +// types. In arithmetic expressions, half, float and double can be +// mixed freely. Here are a few examples: +// +// half a (3.5); +// float b (a + sqrt (a)); +// a += b; +// b += a; +// b = a + 7; +// +// Conversions from half to float are lossless; all half numbers +// are exactly representable as floats. +// +// Conversions from float to half may not preserve a float's value +// exactly. If a float is not representable as a half, then the +// float value is rounded to the nearest representable half. If a +// float value is exactly in the middle between the two closest +// representable half values, then the float value is rounded to +// the closest half whose least significant bit is zero. +// +// Overflows during float-to-half conversions cause arithmetic +// exceptions. An overflow occurs when the float value to be +// converted is too large to be represented as a half, or if the +// float value is an infinity or a NAN. +// +// The implementation of type half makes the following assumptions +// about the implementation of the built-in C++ types: +// +// float is an IEEE 754 single-precision number +// sizeof (float) == 4 +// sizeof (unsigned int) == sizeof (float) +// alignof (unsigned int) == alignof (float) +// sizeof (unsigned short) == 2 +// +//--------------------------------------------------------------------------- + +#ifndef _HALF_H_ +#define _HALF_H_ + +#include "halfExport.h" // for definition of HALF_EXPORT +#include + +class half +{ + public: + + //------------- + // Constructors + //------------- + + half (); // no initialization + half (float f); + + + //-------------------- + // Conversion to float + //-------------------- + + operator float () const; + + + //------------ + // Unary minus + //------------ + + half operator - () const; + + + //----------- + // Assignment + //----------- + + half & operator = (half h); + half & operator = (float f); + + half & operator += (half h); + half & operator += (float f); + + half & operator -= (half h); + half & operator -= (float f); + + half & operator *= (half h); + half & operator *= (float f); + + half & operator /= (half h); + half & operator /= (float f); + + + //--------------------------------------------------------- + // Round to n-bit precision (n should be between 0 and 10). + // After rounding, the significand's 10-n least significant + // bits will be zero. + //--------------------------------------------------------- + + half round (unsigned int n) const; + + + //-------------------------------------------------------------------- + // Classification: + // + // h.isFinite() returns true if h is a normalized number, + // a denormalized number or zero + // + // h.isNormalized() returns true if h is a normalized number + // + // h.isDenormalized() returns true if h is a denormalized number + // + // h.isZero() returns true if h is zero + // + // h.isNan() returns true if h is a NAN + // + // h.isInfinity() returns true if h is a positive + // or a negative infinity + // + // h.isNegative() returns true if the sign bit of h + // is set (negative) + //-------------------------------------------------------------------- + + bool isFinite () const; + bool isNormalized () const; + bool isDenormalized () const; + bool isZero () const; + bool isNan () const; + bool isInfinity () const; + bool isNegative () const; + + + //-------------------------------------------- + // Special values + // + // posInf() returns +infinity + // + // negInf() returns -infinity + // + // qNan() returns a NAN with the bit + // pattern 0111111111111111 + // + // sNan() returns a NAN with the bit + // pattern 0111110111111111 + //-------------------------------------------- + + static half posInf (); + static half negInf (); + static half qNan (); + static half sNan (); + + + //-------------------------------------- + // Access to the internal representation + //-------------------------------------- + + HALF_EXPORT unsigned short bits () const; + HALF_EXPORT void setBits (unsigned short bits); + + + public: + + union uif + { + unsigned int i; + float f; + }; + + private: + + HALF_EXPORT static short convert (int i); + HALF_EXPORT static float overflow (); + + unsigned short _h; + + HALF_EXPORT static const uif _toFloat[1 << 16]; + HALF_EXPORT static const unsigned short _eLut[1 << 9]; +}; + + + +//----------- +// Stream I/O +//----------- + +HALF_EXPORT std::ostream & operator << (std::ostream &os, half h); +HALF_EXPORT std::istream & operator >> (std::istream &is, half &h); + + +//---------- +// Debugging +//---------- + +HALF_EXPORT void printBits (std::ostream &os, half h); +HALF_EXPORT void printBits (std::ostream &os, float f); +HALF_EXPORT void printBits (char c[19], half h); +HALF_EXPORT void printBits (char c[35], float f); + + +//------------------------------------------------------------------------- +// Limits +// +// Visual C++ will complain if HALF_MIN, HALF_NRM_MIN etc. are not float +// constants, but at least one other compiler (gcc 2.96) produces incorrect +// results if they are. +//------------------------------------------------------------------------- + +#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER + + #define HALF_MIN 5.96046448e-08f // Smallest positive half + + #define HALF_NRM_MIN 6.10351562e-05f // Smallest positive normalized half + + #define HALF_MAX 65504.0f // Largest positive half + + #define HALF_EPSILON 0.00097656f // Smallest positive e for which + // half (1.0 + e) != half (1.0) +#else + + #define HALF_MIN 5.96046448e-08 // Smallest positive half + + #define HALF_NRM_MIN 6.10351562e-05 // Smallest positive normalized half + + #define HALF_MAX 65504.0 // Largest positive half + + #define HALF_EPSILON 0.00097656 // Smallest positive e for which + // half (1.0 + e) != half (1.0) +#endif + + +#define HALF_MANT_DIG 11 // Number of digits in mantissa + // (significand + hidden leading 1) + +#define HALF_DIG 2 // Number of base 10 digits that + // can be represented without change + +#define HALF_RADIX 2 // Base of the exponent + +#define HALF_MIN_EXP -13 // Minimum negative integer such that + // HALF_RADIX raised to the power of + // one less than that integer is a + // normalized half + +#define HALF_MAX_EXP 16 // Maximum positive integer such that + // HALF_RADIX raised to the power of + // one less than that integer is a + // normalized half + +#define HALF_MIN_10_EXP -4 // Minimum positive integer such + // that 10 raised to that power is + // a normalized half + +#define HALF_MAX_10_EXP 4 // Maximum positive integer such + // that 10 raised to that power is + // a normalized half + + +//--------------------------------------------------------------------------- +// +// Implementation -- +// +// Representation of a float: +// +// We assume that a float, f, is an IEEE 754 single-precision +// floating point number, whose bits are arranged as follows: +// +// 31 (msb) +// | +// | 30 23 +// | | | +// | | | 22 0 (lsb) +// | | | | | +// X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX +// +// s e m +// +// S is the sign-bit, e is the exponent and m is the significand. +// +// If e is between 1 and 254, f is a normalized number: +// +// s e-127 +// f = (-1) * 2 * 1.m +// +// If e is 0, and m is not zero, f is a denormalized number: +// +// s -126 +// f = (-1) * 2 * 0.m +// +// If e and m are both zero, f is zero: +// +// f = 0.0 +// +// If e is 255, f is an "infinity" or "not a number" (NAN), +// depending on whether m is zero or not. +// +// Examples: +// +// 0 00000000 00000000000000000000000 = 0.0 +// 0 01111110 00000000000000000000000 = 0.5 +// 0 01111111 00000000000000000000000 = 1.0 +// 0 10000000 00000000000000000000000 = 2.0 +// 0 10000000 10000000000000000000000 = 3.0 +// 1 10000101 11110000010000000000000 = -124.0625 +// 0 11111111 00000000000000000000000 = +infinity +// 1 11111111 00000000000000000000000 = -infinity +// 0 11111111 10000000000000000000000 = NAN +// 1 11111111 11111111111111111111111 = NAN +// +// Representation of a half: +// +// Here is the bit-layout for a half number, h: +// +// 15 (msb) +// | +// | 14 10 +// | | | +// | | | 9 0 (lsb) +// | | | | | +// X XXXXX XXXXXXXXXX +// +// s e m +// +// S is the sign-bit, e is the exponent and m is the significand. +// +// If e is between 1 and 30, h is a normalized number: +// +// s e-15 +// h = (-1) * 2 * 1.m +// +// If e is 0, and m is not zero, h is a denormalized number: +// +// S -14 +// h = (-1) * 2 * 0.m +// +// If e and m are both zero, h is zero: +// +// h = 0.0 +// +// If e is 31, h is an "infinity" or "not a number" (NAN), +// depending on whether m is zero or not. +// +// Examples: +// +// 0 00000 0000000000 = 0.0 +// 0 01110 0000000000 = 0.5 +// 0 01111 0000000000 = 1.0 +// 0 10000 0000000000 = 2.0 +// 0 10000 1000000000 = 3.0 +// 1 10101 1111000001 = -124.0625 +// 0 11111 0000000000 = +infinity +// 1 11111 0000000000 = -infinity +// 0 11111 1000000000 = NAN +// 1 11111 1111111111 = NAN +// +// Conversion: +// +// Converting from a float to a half requires some non-trivial bit +// manipulations. In some cases, this makes conversion relatively +// slow, but the most common case is accelerated via table lookups. +// +// Converting back from a half to a float is easier because we don't +// have to do any rounding. In addition, there are only 65536 +// different half numbers; we can convert each of those numbers once +// and store the results in a table. Later, all conversions can be +// done using only simple table lookups. +// +//--------------------------------------------------------------------------- + + +//-------------------- +// Simple constructors +//-------------------- + +inline +half::half () +{ + // no initialization +} + + +//---------------------------- +// Half-from-float constructor +//---------------------------- + +inline +half::half (float f) +{ + uif x; + + x.f = f; + + if (f == 0) + { + // + // Common special case - zero. + // Preserve the zero's sign bit. + // + + _h = (x.i >> 16); + } + else + { + // + // We extract the combined sign and exponent, e, from our + // floating-point number, f. Then we convert e to the sign + // and exponent of the half number via a table lookup. + // + // For the most common case, where a normalized half is produced, + // the table lookup returns a non-zero value; in this case, all + // we have to do is round f's significand to 10 bits and combine + // the result with e. + // + // For all other cases (overflow, zeroes, denormalized numbers + // resulting from underflow, infinities and NANs), the table + // lookup returns zero, and we call a longer, non-inline function + // to do the float-to-half conversion. + // + + register int e = (x.i >> 23) & 0x000001ff; + + e = _eLut[e]; + + if (e) + { + // + // Simple case - round the significand, m, to 10 + // bits and combine it with the sign and exponent. + // + + register int m = x.i & 0x007fffff; + _h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13); + } + else + { + // + // Difficult case - call a function. + // + + _h = convert (x.i); + } + } +} + + +//------------------------------------------ +// Half-to-float conversion via table lookup +//------------------------------------------ + +inline +half::operator float () const +{ + return _toFloat[_h].f; +} + + +//------------------------- +// Round to n-bit precision +//------------------------- + +inline half +half::round (unsigned int n) const +{ + // + // Parameter check. + // + + if (n >= 10) + return *this; + + // + // Disassemble h into the sign, s, + // and the combined exponent and significand, e. + // + + unsigned short s = _h & 0x8000; + unsigned short e = _h & 0x7fff; + + // + // Round the exponent and significand to the nearest value + // where ones occur only in the (10-n) most significant bits. + // Note that the exponent adjusts automatically if rounding + // up causes the significand to overflow. + // + + e >>= 9 - n; + e += e & 1; + e <<= 9 - n; + + // + // Check for exponent overflow. + // + + if (e >= 0x7c00) + { + // + // Overflow occurred -- truncate instead of rounding. + // + + e = _h; + e >>= 10 - n; + e <<= 10 - n; + } + + // + // Put the original sign bit back. + // + + half h; + h._h = s | e; + + return h; +} + + +//----------------------- +// Other inline functions +//----------------------- + +inline half +half::operator - () const +{ + half h; + h._h = _h ^ 0x8000; + return h; +} + + +inline half & +half::operator = (half h) +{ + _h = h._h; + return *this; +} + + +inline half & +half::operator = (float f) +{ + *this = half (f); + return *this; +} + + +inline half & +half::operator += (half h) +{ + *this = half (float (*this) + float (h)); + return *this; +} + + +inline half & +half::operator += (float f) +{ + *this = half (float (*this) + f); + return *this; +} + + +inline half & +half::operator -= (half h) +{ + *this = half (float (*this) - float (h)); + return *this; +} + + +inline half & +half::operator -= (float f) +{ + *this = half (float (*this) - f); + return *this; +} + + +inline half & +half::operator *= (half h) +{ + *this = half (float (*this) * float (h)); + return *this; +} + + +inline half & +half::operator *= (float f) +{ + *this = half (float (*this) * f); + return *this; +} + + +inline half & +half::operator /= (half h) +{ + *this = half (float (*this) / float (h)); + return *this; +} + + +inline half & +half::operator /= (float f) +{ + *this = half (float (*this) / f); + return *this; +} + + +inline bool +half::isFinite () const +{ + unsigned short e = (_h >> 10) & 0x001f; + return e < 31; +} + + +inline bool +half::isNormalized () const +{ + unsigned short e = (_h >> 10) & 0x001f; + return e > 0 && e < 31; +} + + +inline bool +half::isDenormalized () const +{ + unsigned short e = (_h >> 10) & 0x001f; + unsigned short m = _h & 0x3ff; + return e == 0 && m != 0; +} + + +inline bool +half::isZero () const +{ + return (_h & 0x7fff) == 0; +} + + +inline bool +half::isNan () const +{ + unsigned short e = (_h >> 10) & 0x001f; + unsigned short m = _h & 0x3ff; + return e == 31 && m != 0; +} + + +inline bool +half::isInfinity () const +{ + unsigned short e = (_h >> 10) & 0x001f; + unsigned short m = _h & 0x3ff; + return e == 31 && m == 0; +} + + +inline bool +half::isNegative () const +{ + return (_h & 0x8000) != 0; +} + + +inline half +half::posInf () +{ + half h; + h._h = 0x7c00; + return h; +} + + +inline half +half::negInf () +{ + half h; + h._h = 0xfc00; + return h; +} + + +inline half +half::qNan () +{ + half h; + h._h = 0x7fff; + return h; +} + + +inline half +half::sNan () +{ + half h; + h._h = 0x7dff; + return h; +} + + +inline unsigned short +half::bits () const +{ + return _h; +} + + +inline void +half::setBits (unsigned short bits) +{ + _h = bits; +} + +#endif diff --git a/OpenEXR/include/OpenEXR/halfExport.h b/OpenEXR/include/OpenEXR/halfExport.h new file mode 100644 index 0000000..3a0c86a --- /dev/null +++ b/OpenEXR/include/OpenEXR/halfExport.h @@ -0,0 +1,27 @@ +#ifndef HALFEXPORT_H +#define HALFEXPORT_H + +// +// Copyright (c) 2008 Lucasfilm Entertainment Company Ltd. +// All rights reserved. Used under authorization. +// This material contains the confidential and proprietary +// information of Lucasfilm Entertainment Company and +// may not be copied in whole or in part without the express +// written permission of Lucasfilm Entertainment Company. +// This copyright notice does not imply publication. +// + +#if defined(OPENEXR_DLL) + #if defined(HALF_EXPORTS) + #define HALF_EXPORT __declspec(dllexport) + #else + #define HALF_EXPORT __declspec(dllimport) + #endif + #define HALF_EXPORT_CONST +#else + #define HALF_EXPORT + #define HALF_EXPORT_CONST const +#endif + +#endif // #ifndef HALFEXPORT_H + diff --git a/OpenEXR/include/OpenEXR/halfFunction.h b/OpenEXR/include/OpenEXR/halfFunction.h new file mode 100644 index 0000000..98c1d17 --- /dev/null +++ b/OpenEXR/include/OpenEXR/halfFunction.h @@ -0,0 +1,179 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + +// Primary authors: +// Florian Kainz +// Rod Bogart + + +//--------------------------------------------------------------------------- +// +// halfFunction -- a class for fast evaluation +// of half --> T functions +// +// The constructor for a halfFunction object, +// +// halfFunction (function, +// domainMin, domainMax, +// defaultValue, +// posInfValue, negInfValue, +// nanValue); +// +// evaluates the function for all finite half values in the interval +// [domainMin, domainMax], and stores the results in a lookup table. +// For finite half values that are not in [domainMin, domainMax], the +// constructor stores defaultValue in the table. For positive infinity, +// negative infinity and NANs, posInfValue, negInfValue and nanValue +// are stored in the table. +// +// The tabulated function can then be evaluated quickly for arbitrary +// half values by calling the the halfFunction object's operator() +// method. +// +// Example: +// +// #include +// #include +// +// halfFunction hsin (sin); +// +// halfFunction hsqrt (sqrt, // function +// 0, HALF_MAX, // domain +// half::qNan(), // sqrt(x) for x < 0 +// half::posInf(), // sqrt(+inf) +// half::qNan(), // sqrt(-inf) +// half::qNan()); // sqrt(nan) +// +// half x = hsin (1); +// half y = hsqrt (3.5); +// +//--------------------------------------------------------------------------- + +#ifndef _HALF_FUNCTION_H_ +#define _HALF_FUNCTION_H_ + +#include "half.h" + +#include "IlmBaseConfig.h" +#ifndef ILMBASE_HAVE_LARGE_STACK +#include // need this for memset +#else +#endif + +#include + + +template +class halfFunction +{ + public: + + //------------ + // Constructor + //------------ + + template + halfFunction (Function f, + half domainMin = -HALF_MAX, + half domainMax = HALF_MAX, + T defaultValue = 0, + T posInfValue = 0, + T negInfValue = 0, + T nanValue = 0); + +#ifndef ILMBASE_HAVE_LARGE_STACK + ~halfFunction () { delete [] _lut; } +#endif + + //----------- + // Evaluation + //----------- + + T operator () (half x) const; + + private: + +#ifdef ILMBASE_HAVE_LARGE_STACK + T _lut[1 << 16]; +#else + T * _lut; +#endif +}; + + +//--------------- +// Implementation +//--------------- + +template +template +halfFunction::halfFunction (Function f, + half domainMin, + half domainMax, + T defaultValue, + T posInfValue, + T negInfValue, + T nanValue) +{ +#ifndef ILMBASE_HAVE_LARGE_STACK + _lut = new T[1<<16]; + memset (_lut, 0 , (1<<16) * sizeof(T)); +#endif + + for (int i = 0; i < (1 << 16); i++) + { + half x; + x.setBits (i); + + if (x.isNan()) + _lut[i] = nanValue; + else if (x.isInfinity()) + _lut[i] = x.isNegative()? negInfValue: posInfValue; + else if (x < domainMin || x > domainMax) + _lut[i] = defaultValue; + else + _lut[i] = f (x); + } +} + + +template +inline T +halfFunction::operator () (half x) const +{ + return _lut[x.bits()]; +} + + +#endif diff --git a/OpenEXR/include/OpenEXR/halfLimits.h b/OpenEXR/include/OpenEXR/halfLimits.h new file mode 100644 index 0000000..404f589 --- /dev/null +++ b/OpenEXR/include/OpenEXR/halfLimits.h @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// 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 Industrial Light & Magic 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. +// +/////////////////////////////////////////////////////////////////////////// + + +// Primary authors: +// Florian Kainz +// Rod Bogart + + +#ifndef INCLUDED_HALF_LIMITS_H +#define INCLUDED_HALF_LIMITS_H + + +//------------------------------------------------------------------------ +// +// C++ standard library-style numeric_limits for class half +// +//------------------------------------------------------------------------ + +#include +#include "half.h" + +namespace std { + +template <> +class numeric_limits +{ + public: + + static const bool is_specialized = true; + + static half min () throw () {return HALF_NRM_MIN;} + static half max () throw () {return HALF_MAX;} + + static const int digits = HALF_MANT_DIG; + static const int digits10 = HALF_DIG; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const int radix = HALF_RADIX; + static half epsilon () throw () {return HALF_EPSILON;} + static half round_error () throw () {return HALF_EPSILON / 2;} + + static const int min_exponent = HALF_MIN_EXP; + static const int min_exponent10 = HALF_MIN_10_EXP; + static const int max_exponent = HALF_MAX_EXP; + static const int max_exponent10 = HALF_MAX_10_EXP; + + static const bool has_infinity = true; + static const bool has_quiet_NaN = true; + static const bool has_signaling_NaN = true; + static const float_denorm_style has_denorm = denorm_present; + static const bool has_denorm_loss = false; + static half infinity () throw () {return half::posInf();} + static half quiet_NaN () throw () {return half::qNan();} + static half signaling_NaN () throw () {return half::sNan();} + static half denorm_min () throw () {return HALF_MIN;} + + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + + static const bool traps = true; + static const bool tinyness_before = false; + static const float_round_style round_style = round_to_nearest; +}; + + +} // namespace std + +#endif diff --git a/OpenEXR/lib/Half.lib b/OpenEXR/lib/Half.lib new file mode 100644 index 0000000000000000000000000000000000000000..9972429f9b0a5d39d47cf2cb6e2dd8ce98451f96 GIT binary patch literal 5192 zcmcIoPj3@P6#v-?`QxOClk`&5szypndkJ1+Cq}BWyN*K=VFwZ%8j#T1v7N?}!$!74 zZ}i5gCq6WND^@c}B)_jYHz{xe%_v#j(yv+uo`_nVpb-n{jt z?@EpG$$I2UtozZDYuZ{el}N31^W)-G(^6O6ZZQJjGhq4&F!KzUeGSaNA$kNvi!Lp_ z1el^PTv}KMnC4yyN>fX;m~(02DanbJXgt&6TPDle$=|xUU$C;9w>S28ZWV6sTid1j zF)VBMAeZZx;wKin!ov2!?hPwz7EDsFot{~`)v~YG?NZA)Atl3z?_~<-wPQmwGHs1& z?z}_1m4SX#Yc<7yz0Hidb$CxID-LWV*@l_-a4BWFzG~bx%}w);zI;?_*2pYCgQ_+JDhAgFEU*dnvqtTKdzystaOkb;gBI9)ABrsR zo#O{$;+cBT>}{Ia_bk0zMKRtNAdh6>2-#~@KoY2eum@Ol<_LySj6#VGJ{ z33x&6`U3E34oDN_7J;YqUL@ID>Qm~&3?i7o6sGYBW-*UBOd^D^!@q#>KG_%oboHQO zS(V$=xk#OFdQNWW2vK;?&~tdM)`Ld6ih|uS#wQ~WfANSbCir|7Xxg^=?ze%jM#XI> z#wu?pAyeK(LKZ;o31%kGAC&V+Px2M^jrZ{?b#W5ml4Ye*ugi+;eU(@;oe(uyF;aOv zhJR*%`+gz>%0}+9QmG!D|FC>pyn@Ou{48HYYap6gsZ~m?(sDwIKBdm@M1Kp$7_|oC z&xPKqU{mG;{w0!n%r_8w9;SAlG9o`ya#5GD6rCi-9}b&}K5C=)7xT4p!*1Hgt=KpF z-^Ow~yElZqtD)o!M!^Kis@$XGj0;Xrnjq_C`}B-pM(>A0@7{IllOh;b7;?1+;2=Gb z9A{mw6`_-49U6qTPRipj{|o*R56=#?H;4LRP*F=oVlcIZplqBxWuA+0Ie`M`h(PXR3m; zzVRUIAqfq#Gia=6aZQPFk1&QP-vm`?Nn9A(Gm~inFvefq-Y$Ml2*Z>I_5K^ZZA^9s z-3{-{zuVSVWNXZ^<^TOGZH=(PYw8tpgpczXC<>3!t)=9F_w47FWR2@~b@}^o>`kye zWq~xhy=yZ0_pC2Z>zibI0Tf-MqtoKzFQguHT&he3fX*w#M#q?v#Z?c+7-5|5$0&=# nwn5n$IO=>N{A;ooQQK22b7-sbAbM7LiLB1BRi6@8+Ck($^1vp5 literal 0 HcmV?d00001 diff --git a/OpenEXR/lib/Iex-2_2.lib b/OpenEXR/lib/Iex-2_2.lib new file mode 100644 index 0000000000000000000000000000000000000000..2d86cddc603eb26edffb6cc8981623cc060b1db9 GIT binary patch literal 36992 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 S-F@4gKYJN+2~I2<)B)B9h?te9t-j0 zLNczzl;mZ5RH}=K7gG8d1aKGd?E(H%AaG9Vra31CV9YM9T~*EI*NUaGx{_XhTgtAL zizPK%JI+`1`fN;%K~)PIx!hF{zSvMErkvR*tg0)iatg~W+MhnI7TbbgDjg)mhtyU^ zY}0{_*1qZjSl+Ga?EcF3%vNu=8)Ug&X=}||@kl?^Nourr>7?4e-srRs#ejp~rBkV` z{?TLZ9=TS@eysvjtUVua>IcqA*`&&eNuW!UMEDWF1U&Fc$p_aQjhg_MnvBg7S#7s^ zNywOaA4(@zp4vD(r!|}N!#YffF7-N0JMrP))c5z(9_k~i5|25p_UULhvTkZXnuM>G zB3FUXo4JNo(JPUd_39xBzi9rI1|kClqGuA9kY%JwCiE~$-@^6?Kjh%kfmc%F#fxov zj!j)x;shO6AIhAV61OqOYcS`B5hRB?m^qsHs`s=pXVEe;bG})MT$wqy#)zBL_%Q`? z?T2IJ%q`h7XZGA5a$pvGaOPZkPO*~3J-?%W+-*AIISe!T)tsDzN|n literal 0 HcmV?d00001 diff --git a/OpenEXR/lib/IlmImf-2_2.lib b/OpenEXR/lib/IlmImf-2_2.lib new file mode 100644 index 0000000000000000000000000000000000000000..1e5211c2362ab4adad3b287ed8f66a679f2c2221 GIT binary patch literal 627250 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

{VOHB;PodJ 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 RV4kMS6U#pkmLsiW`F}+rAr}Au literal 0 HcmV?d00001 diff --git a/OpenEXR/lib/IlmThread-2_2.lib b/OpenEXR/lib/IlmThread-2_2.lib new file mode 100644 index 0000000000000000000000000000000000000000..e78e26564a90a3007a10cd218cb1e4a15dd35b0e GIT binary patch literal 14870 zcmc&*&2tn*6n_Z>Fnkz5AtK;HzJYw~X0yAo)R{#BL_>^8K%`2SO?D+I7B}v0{JL1h z!IMXe@?de|rvHFd6#5rfR(Y}XLX`(O;Eg-JH{J8K)7{g(S<0z;*`1wVcmMkJ>(~8W zPfom6tgWuS(LJ6BU&(YfnN3fnGRg4o6a02EH<4jquXh8$BEa#x0EveHCyxU3-DWa; z1%PDYMI3MnWQ<}c69MPcw&2**&%7cbAhT{xFt&Vyx5%vD!! z+8(Nawb}N&Gx@xopE-Nw(q^Olxt+8N^Y%4tWc}7g!KjF3C8hOW^=njutm5h?o9nf* zEvxCOUy}~hs+B9{VqL2~9jH}74VFt%dWCtPpAOWr3g?%~w~8BURqV82WCH!wf#QHM zOIfH^E28@B+2G)6U~yFCsLNzKevfsa*2kONnCrH@;&*4x<}dmc82KXf`D=k+a`9)G7R_>Q@-J)qZn&;}K!V^6n zOPZmvcv|3t7m@EirS}_O=O#6Lgyp*h{vt zi0h#eg}oC#kC>to<*eSe5Q2lA4@^N?yVXEz^W%6BSGWPxDrANHxGI%kV59qe&A`upZcI)V_Exw%XvPOTU1%QLXFq)dO3f7Au=&l@dbR8Z$JS zhE%(bdDJ&IHmbEoolV(#^V0BsKBy=?F!?Aa@@THiS!Y5HN(m$HBm_k4ObxT@jbg3A z_gf-P0TVNTqH4wMl3vXt~n_7z5*{jn8hM!B`W^+#A5UMgTe|u`GUnf@Ly;04t{eda<4( zV*m#*2L1!vxPzE4a{z~s#JBj{H7xhdG{EC5){AX-;`clFYz6P{V;zsMjz6*O@30OG z=V3b>gOhL=UVxY26zqp?=z`Ct!cN!= zXJ7;dAOSkdPO%fs2*Fb4JP+<1vgw7SpyGmzqZh8hbdcB#l`fLUXgAm2NW6PiU=rmgb6X zutU<>x9V`oLbWw5swwD6rn;&x9B64t40${ zQ5lLO7G`xLomM!GXv?=j4F*w+)$3M_)1A+?j3%GsG=s zYdP~9ruj2oPCKiibH2grG|J!eGI|j=2kV^OaHw&X-z{eld71>``s*<#qO&SF2|iCCv)!k^7U>nMM&qIW2H(3#@*v)4vMR7Dw*ZT>)oZVx52-AetPe4 z2Vh*vuCY>iW%EY=62FBD_yvz`LzfLbXUEn{#YV9oBXD-TfFHl3{KN0J;inA~zi=Ez z&FsQsW9Y*6TpaysL*kcC{OrZ3mahGgZVti0o}Ksv54fFcAO7w6;J~Hz)mpV){iu-` zUK~lx&Cb8gpNBs7;2qH+p`e|<_2Azw=Ub#Luve?MHjsDE2OS+xp9afe0Sweh-0s@| z4)rzn7pJ4FHI7LW1`C0Qneu<3-!Ze`T~s@O<=s1#Pu?WRf;t@w z`WY!Q>iBkmz=BGF4$;?u1z`?`U1UK&xHtThEQsoTMwX#7(#NoQ=?ewMx|?<k&bor+lMsbJf@+K%T4+o6M&|0 z>1*U}6((&tV|l z+d3>L*%hT>t_jz5pzjE30+X=llpP+T&2v+H6(wS-kDNpwdE~J@hKIWoWg(H1os1GP z*GyVGLbRTA`HYltSd@mTUb5c1Y~k@CC%uES5QZ*tQ#IB^E+y8)8^~d2kb@{RYP+Rm z6&AZoi;Z~dn2t?tLgd5b1k6W5p@+Rbga6T2?BgtizM`F)koa+0*Pah@5c!HW@=*D#9*2j1 zCTr{SB(OTN^lJBx?yCC*v71(}Bo!h?_U{o*9W%;GsF5So79}6Sh6=XC>=81t*6>?TaRB zn>Z-^#bIY=XuNIQ21`)wDtbAOn1m?4S`sBu6bGu8TY%wcAldEYvxtRyEu zDU{>HDL$(oC1Gsms`>Vc%OdW-C)&UxC$SwHwUHnmM&}VxLZ)*pE7=|33s`W1_~@N= zM2WO@giaC@or9D%@KDX6KH_0~N)shzJW7hyv)|#QaRL;jVLnC*YZ-8OXdN%Lfk{rX zt9%{pc959ppIx@;6RtqcFUV`G+6H_YY-#Wm%TRUzUESZ{It&`*!!~?wNac z{Ze(9ow=v`{LZh>>3eU#IBH>ErGIGAjFaZd|8j-4Tw7s&OKY?Id-OHeT4-(yF0G#d zFlB#$?Qa5n3jnTc2e|!cEN2_cV=ng%05G|2HkTjo24HgQ>s)?x832=e)^oYF3x7xX#ZE3ieF`9u zR{TV{v%=+$BLJA(i{+Ty@e!8?9sywT^FM^L0zXmiLYqu}wusBUA7VL_yY}VsU?%{R zAO0hhA^b$S<#sMVKuk>T{v(%L&>trE{hiB0Xyd`R0e<-|z(eTU!^`pS9_08=E{|>p zVDjWtE>B$v5XdzAM0s)tmnZOdCJ!9X<$ko!HxCemAZ_y7XPh%ZS_Wp^>3oQUlUb=KuY+Da`nwzcKsFgP_9Q? zOs;#3%eR*UFxh=Dm+#yMz-0FaTy8*IOn&_#z;8ar&$akDQZ6s;UU6pcs&d!jm8bSD zU9sxS-tyATebu28Tgoj^F88cnzFbv-D{4AiW7X-adzO{EI#zW+vDn?n>?*m{6{^zpbu8{&Q*7GMH$L279mzaRu`N4hx#hzYNcBs@WX z2KzQ=gVaW5U+ zxMFO0v}#Kni=L&XWa?10#koUir4iJ%ULk8k7Is)$${j(&=|g*zmO0EHgCQk>EP7Uk zl3`8;Zk!dELk7!q68RKD>?}{u+S+H$B8#4-reqdTwZ&OPX{DM)SsSvjlR*~I9;KK? z217~~S@f(7DOqHwFnDf~vWQTmZ$*Z*PzoXTmG}tM-G@&?+iZ6utERQKWG>M)#@R&c zrJ7IKo3gT$K~CAcN-?X9rj)$0YC15bYvB~_y5mV#d~^x>Sr%Gk>OzL7y& zg4q;pbtTh_tS`e*LgOWY&u8-h@44zSL9V1IsPqptWZy(#ol0BV(0< zza4G4BKp#T=sf-LEJa$;;tJo=C_CD6#qq8E{Tt=B5qlNW<>Hpg-~dt1bUCn>h=raW zA(9Y|?s8yHcOi6~+0$Jvjtq`&st%QcU~4HY5j{O?ac9R8A^z=}#nI@&+fX5!D(PI4 zYZ0aaeTu~OvsY$4X3B(Hsn|--*eH9jsKb(b$=KR}!A@rf_6B;+9Eu3_o86~OIF%Bt z(5_RKoJ%I6_Vi@bo^Fa-t!9ipYJh|q6;cjG;`#+DJxsWjimfDQ^swY!GPYI=!Gs;E zp$()7MTGjz?hE>1H&^RS2AoO>R%q8LOU@;wsLea~wFb=?J7-f-vqvpiB(A?kC8?im z0k=}I6^TYKOYS9OYhlzXcBqCn@GKM&>NmSD=qEXgqm}|DSfO2~EIF4TMqiR%{{fY492fLp29N`giYOYS9OYqh9N*r6KQz_U<9sNd|qpr7PS zj9N1=!3ymmnHX-v9&O2 z6+2Wz8+aCq2=$xY7xa^y#ZgNE6Rgm#Q&$+={)*tDfG)?e8= zUL73o9jo?LhsQ=cMh8~mu-N!W@C`?ogoVKC*b8m3iLWjxu%V~s5>AE1BVNs==JK+# zFzk_`1sC+)9_YK#8GrQkT5v({%{{h7Pxkx^R$RRBW(e!=_V%I?E9k`qef?t_hF7lX zDkUmf%V%$S$mjETxfz!Wl0+l=u0x(@7sVsiC?8P9@DoI%33 zpuGeixNj^DNZ<6$?BZM61_|G=0i^JX+O3E7Ehr}4(OB5I_?EUo!nYujHSK2cEhr}V z#(Q%Y-_kb7d>bB};C!1PgM@Eshky7wY9=#ngM@EshriXgv<(uzr5*lO-!d{dJTN#~ z9j;!I&r9?AdHH6Ci#4LPYf*th!B8LwFinAcUYe?xECkCzR11az0Ts+bJ!cB!qca6? zV>G7#GQlLCGM@aH|av-viF5AFe2i+|6#A9rx$&gBxy<=+FCcQgKe zH^9gEIe&Q0epzp_Qk(D9|ZWv4*`ZyZpYo`T|WT$BifsdfBzlrt-u}OZ==q; zzeJn(_wt7UdhqW%5&!l_0j55QCnP)tFb!n~`}+xi z?RgJ>{}sRjlv()q_IGhd_4@$R@$(S;yaDytcKT^gqpiJI&+}OBC4g10;)w@upbfls z177K$`@!CCj?PI*Q=0!Yp z0I&TEubuxE+I}3M@GN5g9rA_O7QTYJ!e0mY8(!Om*Y@JI*@)xP-{bChymlzV@isv9 zy8!>Z5lbpb{+cmZGeM! z<7o)r!M4ZG>J8|}uMyvGu)Xnf1V8tm0`LvE0xpN`a0z@JE``hBn;1Yl;7Yg(u7;g( z4Qzvp;9}ScpMqI%0L+B_;dnR!j)P<282Ai)7UsY~FdO!RPr|ec zIrsv65srqVU@ja8UxtHWIvfs7@M$;^4uKi45WWIO!k6F_D8eG>f>U8WEQ4NH2kT)I zj6w%2fL1se+Mx}W!%8>@`d|pgpc_`fxv&9-VGH!YYWOPj!v%05oC#~-JQ#qlK?PR8 z*>FA#!U&ARS+Ew$un{&x6-sahoDNH1F?7OGI1Q%2)c*hmPJ%o%!#v1Ai@?Tpa4lR9 zyC#8^eQ;T9I7}kGwo$KIc(00H_mi)w-gO0CuJjbgst#V;v~@{O!RlLz=>^rhuArlq zaMfPeYIUVCtmIsoK$JK}C5^F2m8ndz0o~ewSHzT98GFg74JbKRCQv0-CXKFOWfS#E zN}G~cY4k0MFcmbH=B1|Imr>f3#w$j@?Y%dO0bxi2-=CPN$$z_;*au>%yW?R||G)u3 zV2~@CuxOyItW!ObZd}?->klUZTQUBKc6M+)70s5|GZ+fCADP-l?6wu# zVMnu3B|<^()ArcW7cV>H3n5#Q>r(ZrN4c`nTC{Sa*(hbD{b*&Unrq82m0;CZF6jH! z??_9ner4Z<1&<>+wfdDn*VivC9(Cj>QO1cUsf;66i8B6n966KhIPw;*I#w7H7V5@X zR#Q&6Kq)I6(aIh*E38m8D|G0UYhmX|h@kI;yr%C+i=gjUzau%d`W^X^Ld=n)L>VVP zq%w|NCCd2QapX+0L-VG+8RL@{JDvV`uri8wfdojf4T`r}a>Y;7cQ zVnJOeeb<&-sB0|~BfSnw_%d1_NnlKjxF#`5Qxfd4wXqeZ!rYWF$)Q`bn#N>a!fjiX z!5k5vW0WV(*eJYt*|f@_-^88*({L{0M5d>{-;PBl8!XEhi!reWvQHIvEPb zaGi8DeZULdt5 zpiL!Pfz}oqf|_W_f@6z4g<`9IY7CQ>k_3~=0>8Ft&M4SXkLvKFDaM+*q4(12sp+Vw z8RJFKG&!DB^qLBd+`>W>3);!QT3G`n_ChK@bQyi$rI{kFK_g4Vi^ppE#^#`bnc9Xd z<#>`b-7>A6;?dNGmQa;c=4Blt53-ucZ%NC3im&k$-LPHAGkQZE>I7QtNvaOzkR|r= zEY2KXY-f|p>;W-a&KU2bQ2*LxtVGQMs&EJ!nYZ#d*tnM&ky z+F_H3I5i{nhB`Il^CHfQVYWQ9X_+$@v|JB6H%^X=hy0R9hsXCorbf-BNANsm)J;Va zjV;c>>We6??o!0tiV_EQD@s66MQYPy%2bzQDG!fow!EklO4Vb_i@=&KFAk;YGA|wz zB|ZF;N_z2`C|R#fFJ2{^Ufk9u^YC7RRyzKpdB5){YettHuBM7TCttJpIONSV&>j)l@i2n`vj9{LL{a?iA z4UCMOGe;_}1A`m3 zZfaV|zX9&)#+~lbm+-R$vpVMu5A;?0np&bubMOz`3=jVk{;&^zmY{iWsMi|)jJwbQ zrl7q@kNsYPxqGML=N#OF&i)-BIdu#iG;2Tn6}Qs||5y#P&YRsm++P_RAKO@+du;D< zbC)meSr%TGK4#)K289W3{}29}h5!9T@RwuJ*p`s>C|;<6qeCN3;Kg|5#ms+v($fQ*kpq;DktB%SqCVn3nl1 zLc~lBA_k9f2nba11)0h+P5f7aQj}?h=y#UU{}p`+Kbc+z{JL;^ zBtjs<(wE&_E@l^irR%^>)|Z_VcsecB^A99!-f=)7oq}Bw?wIvk^c5^<5SBs+hvH?2 zbgBtyViw(X=~s40_o)Y|e(^=Hq^wb-@%>he({nLSr-?{y>&k@lIm8uP{M3$cU6~Bk z``I9uGh<~Z!_*?xhE<4A5vz2pMTS`SO=4AJ)NgTJhFJIW!74&R^@AT8@f~4w^jcMox3- zo5MR?uBEm1?khgMU4ZC6ofZ0UnW=5yK&N3^@BPS(Lvy z*v}R8{pjUr|8tRj+ghy@*AF)4O}n8*7oj(YdU&Hx5eb_UxB5HmHbnDzFEr^UimxAS zQOB9c6E-M*n6n?+bV;@MJKPzIk~ZEra`}i9xff=4lOs3|!|FJ;NH4R5@%Dqdn;hxl zhdx!jaZq=Yxo$YpO%iVpsJqEgb`P}a;hU+{-Q;LH1|=oli1|og+3*GQRMQ`%}nNU3!?a<6N+>b!WVyAG+dduYp`j?FIn+x z)4@9@Tlo?G*qkzlCn1JotQeGZ@V9S>q!ZBovD|*Id4r6^cpXo6Q3J@nv+?5NxNYOI z>rB(po5eOmE1ry=9Pj3dJ|(@8VZE8xf>hNsb z7Cjm#GLtP^Inf1$lAOK>a)k(j+?MR=d>%(&+Ha6)dieU$7QMhFm~2NsPIB@?pB%n8 za`~vUlliP5j%G(3>86IS2W`=SMuJJUz$542fi^L`^RqR2u}GlEA&M3U6iQJ zqFE53p)!Nrxs0OQL{o1wK9 zAeK`&7X8z|W{at0+rLL8o)H!~Ac?oGHio0!aEC1-BSntG*rPZ!kbks9uh@xbVdKRm zj>pu$IKYv(a>%6C=;b1T=0rr(feWLHMRE_XWX`{Dp~kN|Yu2gGrM0spN2dI(K?Y6@ zF&H`%)wp*wv_=oG3I5sJdY52b?L1WDQe(JyZg|IKBNdB7+s4#T&HMXq=pp8z{UxD& zQ!1$Dy}c)xKP|{Z>fmq5nt#k0?ik0S=chB<#_i$_+9iBm%IuQc&>OSeZm?ZKpU+^n zy|=eFh==Hhm)Y=OIh_*$Ni5!muvqSs)GCC&p*aiR{y7 zjK~1I?~qgQs~l{ioLEoEO;lIBq3FEaz*nBsv1|6q5|Glr>nC zTf+olS+B)1IlS~~uqd~S3F2jg7E5-#P%8)fB`mcwDwHQGGc{5$J3Q4;Xa-DZoXJTO z&7dBQM>?g6W}^wsq;RuIkH#aV(&T2ygeE&~49`ZL_;fNXp^?rf$uh49L>EwqCWWJ~ znGt1~Uj#=Z6rxGtXtNnnmU%{SG)f`Lj3eqfa7;qva7dTb?bI=oV0bHF>&3U|u_SmA z&c4bJ%Y`~DN@h(AmWm$Br0_DX!=hx<#PCwpW66vc>d9-XjK%yQXrx98<_4bwFEXNW zB_~ZZ7aP#Hr&F3}wi(e(1~-=&(72~mn%rD!M3Wge#NG1iG8+0pFulAY5M4$hnhcJ< zK_JR7zX*;lClO5sM^_MtGR!lAqwOT3tT>|9FnlvWq#Xyx)hz62N2#BYzd78k<{O^- zj=|@?9n7}r$Vl0&_ZTc?_gj%&X)Z84zOg~O)GYdy%&zw#mogyfn*;yUv&&UBJgLv3 pw;EPX9*5Delc6ym$|*VS|NcS6!_|Rh!~Z)pL%Y{Rb{*pI{{XH9@>l=> literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..5eb0129 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +This is an experiment to: + +- Allow applying color changes to single objects in a deep EXR render with clean +edge antialiasing, to avoid the artifacts caused by masks. +- Allow it to be done using simple tools like Photoshop, instead of heavy compositing +packages like Nuke. + +This works with image editing software without additional plugins, and requires no +extra renderer support beyond standard deep EXR rendering and object IDs. This +idea is based on . + +This tool separates objects in a deep EXR file by object ID, and generates a layer +for each file that can be edited separately and blended together. The only trick +is that the layers are blended together with additive blending rather than normal +blending. + +Instructions +------------ + +- Render a deep EXR file with object ID samples. This is tested with Arnold renders +out of Maya. The EXR channel names should be "R", "G", "B", "A", "Z", "ZBack" and +"id". +- Run the tool: + +``` +exrflatten input.exr "output .exr" +``` + +``""`` in the output will be substituted with the object ID, giving filenames like +"output #1.exr". Be sure to include quotes around the output file. + +- In Photoshop, add all output EXRs to a document. Be sure they're aligned identically. +(The easiest way to do this is to zoom out so the whole document is visible, and then +drag each EXR into the document. For some reason, zooming out first convinces Photoshop +to align the image correctly.) Set all layer blending modes to "Linear dodge (add)". +- Add a layer to the bottom, and fill with black. This is needed for the layers to +combine correctly. + +The image should now look like the original render, and you can make color adjustments +to individual object layers. + +Limitations +----------- + +This is an experiment, and hasn't been used on very complex scenes. + +This doesn't currently perform "tidying" of images, which means it will probably give +incorrect results if the EXR file contains volumes (samples with nonzero depth). + +The names of input channels are fixed. The basic names are standardized, but they +can be different if EXR layers are used. + +Transparency in the input file won't work if it shows through to the background and not +onto another object. To apply the original contribution of a sample in a way that will +give the same input in additive blending, the final contribution is used as the alpha +channel. For this to work, the background needs to be solid black. This can be worked +around by using the original image's alpha channel as a mask on the final output. + +Algorithm +--------- + +By reorganizing samples from over blending to additive blending, layer compositing +becomes independent of order: you can add layers together in any order you want and +get the same result. From this we can combine all samples for each object ID and +output a layer for each. + +Layers (or samples for deep EXR images) are normally composited with "over" blending: + +bottom = (top\*alpha) + (bottom\*(1-alpha)) + +Each layer's contribution is added based on its alpha, and the contribution of all +layers underneath it is reduced proportionally. + +Instead of destructively reducing the contribution of lower layers by accumulating +them into a single output buffer, we track the contribution fo each layer individually. +When we add a layer, we reduce the contribution of each layer underneath it, but +remember each layer separately. + +This gives us a list of the (top\*alpha) terms in the above formula, with their future +(\*(1-alpha)) adjustments already applied into their alpha value. (Adding all of these +together would be the same as the original compositing.) We can then combine samples +with the same object ID and save them separately. + diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..5570e4a --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1 @@ +exrflatten.* diff --git a/bin/Half.dll b/bin/Half.dll new file mode 100644 index 0000000000000000000000000000000000000000..df9eff1fa4380358aed9aa622ee2a46da8d67c3f GIT binary patch literal 276480 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

y@o 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 literal 0 HcmV?d00001 diff --git a/bin/Iex-2_2.dll b/bin/Iex-2_2.dll new file mode 100644 index 0000000000000000000000000000000000000000..07ab16574f4c55fa5bf140552bc819c1fa1aa163 GIT binary patch literal 77824 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 S9f8E2?#b#u#{Bns;Qs=HWvS)> literal 0 HcmV?d00001 diff --git a/bin/IlmImf-2_2.dll b/bin/IlmImf-2_2.dll new file mode 100644 index 0000000000000000000000000000000000000000..4489c43640dbc2c264988e466a2607147a8bab5d GIT binary patch literal 2961408 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

4{3i-C}cO*d?&n+9pngOdOqjX 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�X_t=N72ghgrkM)>W11?5`jz6$|a-K@Uxwe@Rz;&7w2F;uYDwqF&g zXh&V^wEE_3IvCHI7c{i2AYxj@=4tMt08;n9j2!PWm*iMze_oGI+p*?rpVzmb8K_Il zx$9$kdf+U0T5dAmJuT@844xHfZhP>(ibF^IM^LYZ&_)LQ#4D*;01 zG!(m+p>*c%ppoUt?1{uzmH1zG&+CtQM2G%~mRqN}XKu?zWSbqyQjyu)GJ86y^T&l= zsBeL|!9D-in0rvPZ1?T=B2<6=!t+l~%W%(YOe_3b_JX7?p;h6lW+} zTE!|Ebp!uK8`F#tS@ke|K&UC;2oxmINRyoN?38t=Vly7U)IN`nZ9!y}-Q^BD!Y(5+ z8<$Xgn+v~173*NgW!8=G2||}i^*tH2V`*pwt28T8uz9qR6VvKH$|%80yUib!6ugQn zs1hURq6GgN)I*1U<6aj0Ml&MWncEocL9{27*^Gke)$g$SoMJs{qyfY^^9bRb+|1p? zg^=bh~=~!zGL7KSg-{6TtHyNM_|hW>B13WA7UqRs=l| z_YQep2>J{BftyI%v?=Ls97Fup2? z%|~Aq)?0&Hc7XZm3H#Sq_ro_nXZ5dBOj0YDq}Jp;=fSxtd(O2XXU|#ioOE$6f8Y=3 zrj$MBS2!wJ^b3zI?EOZLHwhvJI?sa!`-?Z-BtO2OZo<(hdG@9P49#4&(Ra)s~>N)&>*&c=#IYBVCLr^+a-G(=(c0^$f9{u|g`z(hmO@OTlsBP?V!(qLvpFNF)O z+_dWB*93FZ*Nn(bXDvJsXN98c%(P?NYx7(-!@oI(!OVj4n+iXb;ji&0@3C1aye zKg>@Dv!Rt1yC}QsaQW=VV>&H1fJUTHK9&K)l#-vV?%U!;=qJoJq5jyR{IT1hWhm4S zgO<|9McLK;V96FAN}d3ZEj#@<&{$!J1R$W8g=6=0;d#;k4YqW@f3zboa|9lL4m?^o*9!_nIm`joE)1*- z)6SvdnI;^mqj{P71`kfUM2y(c3c9TV=z6is3)Gi?uwM|IXt@wCh2?^FUYNpi0pK|k zHQtt6607i)=%BAqVWtalt^StmG`^3;jXPizi4`{kVOPM*a&URN`7Kx$2zNTk7-;%g zQGcK6nxG!RmRNe4e_d_R-B^qiD5&QLhXu21&msz*#V?4t8&8(BU>1xzl6j_WK}f)W4>>Sko^D8#o?AXff0NmI3of zIGzxZt^Ql}KtDdJuZN7rst1p=WgI-;M(Ue=5Kfsb%T@6fqK4j9HwSmDFnM%^rweSu zaU$ICK~~|B!##9)>W~i^w?RlD->SasI)ef-nc5@mbl@12G=X521oKmrU=5l(v|V)^ z;+U7skThPUu>sXb$+XWXs(z%#Va^0&$(i7ih{FFPCa2u`)QL|eAhE_J7}v{Y=Q1^} zKS_7r;kc?t^5L%x1oBvnK;((lh2+=lSk-^JFkHA7L1+0`9&#BBgrk*DRi7{duLnPh z8pUXbn}#`CnyMPX+P`xY9&{PAVg6;0jG_xJOV@J<4_Wb3lIIVT%gj6=U}t~XERul$ zgZl#jQ3LMsu;-%-GxH<*ZG|Oz1#(&Yz9aXu*TZ+47KG^s3=q2`9*&zR*i$HiqnGnMLEFvv#JYV+9NwSY(#$TiT-uf$1sGmuRbCVDD&^fGbgjznQs_H;yQ5~1fXfB(9 ztZoFCOzk1zvztrwi#=U^(9072aMjUUCcl|cS&`WPF67gnE42o5XGuN{gJAB8}*S1-1~=c~>J_=XkxYQYCkaeHwkw%6Ek z=qT4|*J=BX%o!FG%~OX(o}rBFLOCCgPRI5hNIV_|l33?K9^Hj$pmG(g4*?&xML~Fj zvbZON_0k+QJ|MwqLH{e5HjD=8!y@^$r{V+AAR=fG!8l5@Ftb16yfKHb7F*l)68(^_ ztP&Uvl{%}QhWh~Gm6oHACmw{V^Yvn&K_I(!7=Us#L)BhT)+~Jtu^_KHTQ3F@q}3h; zSO5+R95h=*u>kp&D_SWeEu*=Y0N?Rr+#A72)|>~Wi4Va1@yRt=Eb#;P=lH^dS(St2oFjVNn}n zdX2a9^{FP*{?F^9=wn}-Y5)>ubvqvhB)M~VrK-en=Wrp->C*byt#}L;_x}0`aB=4K zn_zSzh8-V|-i+atvjPKY0j;klzC7A!ORC*GrXC2IejB!G@W-|xDMgAj9afgKYbbF5R;GzVc8OoMxMgXD;%-VASeDo1YN73!!7_i#H`pVOg&aAS8I4urmZG{68aBAMfX*WS z_#B4}b@TC3I~se6w+8s(;R-)1)K9zm=}2iQfVK&E|&nvFN zAv-y#Q1ZHHIER)VXu2_%78+LdR~8!fj7RbM^ADY1S!nnO@o0*LhN%9Nf8k?^zNW;# zx5Pc7jY~X-h<-+$ve1C<%9Ktv^XyWVbZ~9qEn%COI?9jY-hcdA4z$bpL&Zq;*6_}) z;K5eqF;~ywNpVyWjgmZ@iwx%VKPR;(nL?}m^-BP;cJnFlZ(=WSCSE*@Dr_1FHfAd^ z``4!v0%NlEQK!X}No1PGp+T$IT_)f!)^hZ5KCs~dS)NdSWj7#17;uvkA`s5l@e22A zKSXW~1*v2K&;2;S(wG&#yTY3KH5|~B0R}_et!x_-?a(lW=-LFziy2Vky8mZMzmv;2;;Pv09zh{L-ck^P>!J)yl4TOW%Xp3%TDBlkY;U|SkY2EWybCDuzhw2O@yBZ zj7zeZ4v(^Qhy{Bk2}J^Vk-Xk~<@+l~9|QIcOhW!+(f=7>0YMq33v(BlZjPQND%oQz z%>YAD5m)Cc>+1Ue=PR^ZZQxQrsDGyEcc|Uy4%vEaOIq+SBKMRD`HxE1hnwi8 zyI~0_59u9X3oB8!zlQ}hdXIN|xQRjViU2x{ZLG(06OL|&K~9Bm+^;RY&}*zE)0$nk^eW&|QQdgtnIo}qHi7m(8= z7OyYSSF$^{CyD3SMf`*RuT}KFunMFDFx{`ih(AbL!ePYy5?64f!-zX1ZaIv&MP+U` zmsS8|(b$XZ1%8MI_z{*%zXOXrO>>N+h0HRnnw@8eN)dWH#*^IrjO6YoT;Pe%h_P%GFyF7wh_j@7y3_sR zrH6^`50G@L`&p8xx?iZe@0d=D>LW=JK@R17DaPp@KM~9~42~C?8O+TSmg43}UT_fO z2~+MLujoAf*I&nb`O{0{M?pRf*I&<;4NPQk?gp`+hy$YVa(JCk2o~zq-(jQ-V-HT= zHPCX8?6vwmCIJgld?6tSxl22ACnLzY&4&KM38GlYwm!|C=|TSAxw+-wX@>u)qB%7zNwxyk&|H^*QU!URjxa zJD(7|w_FPBCo5bEoIA!CJXvdbKP!@n%@K{q`3w7t9d*?ae4<+izz<4t$}ct8;dM z3r^#LOPrzhV^2CDPp5!wOU_iQP1#e&cKDAaBqJ~}?LD8NRD0^Ds+Mr?NYx9w5y8(C zp@m`vS71zJ1p_#>RD)(d{(Dv(1LeTw0hSPC2w<^r`C)~550y^&N-u-*!XG8^F8X#= ze;MnC`OBmxBGLrJ5x99VaCv~5A-+}(;dUb_3Y0?s<(%B>Jd=D+Mm}k}I>VU%DkJmR z&F0E`*=N7^w*s{9v(NtJL;sid*-r%CT3q{q?Xxe3vy=tN_StP~nv^?n)qkP2?8PeG zsI_!nsAYam71onTxkQ6ivZOGc)L;e5U3zp{+88727w~tSrDftK6ZA7BiqjByohi`p z0SW7M#*sU(07yEnzAO^lS8WRI^q~hWFW76MCqrS0;t^~{n0|? z9r7mTz7SL%9fh`G6EHsRz4Re@BNxEVLtUem8Y-*!!jR2FqvUn-r*)*g;=QWz8q|Sz zkiU{c)NjCK3gTeNJ!FL|A##EZkUJg$?x0_6lc!bgt2Nwruo!P=8b!P1ntBj=kt&;0 z?tHXgnV1F<5Z4Nd9zvR+_m;rQp3W>=!vnTbOjKowPOXeb`Bgo&X{16?W3Aac{ko z^zLa$3aKO-=No1P4e!wyp?NB!fI~Sz1Tai~kR5T=@<*(1crUt`@{*ErbMf`UalqhW ztPH1h{Him&RL>~m!oTdl0MtW)vM;0v+%XPD9zn4 zoZa{Oe~AtouA$tBW8pdk&r(5PK}l}hdor^{mntMT0Cl8tVpg=vN-O2;MWSt&Xp43#XReV(_&!=hrK^Og;-Uxz`X1qf>c2r zNHANVN~~JE7E^tpodm3^aFS**DNiL4-y%**1yc^SQef=lOef``eBe~~i}KtNV>cEE zOpaU3NpuDHgJ(zhhL#U6CHhDXbJ7f8P_TZMmQj7W-q-}FgTTW^G~TcS+W8b5LUS#w zua-9e;L~6mw)0L*Eth^dRmiX65gK`Clo%_!0ojNS=7A~*&2m#R4A&$6Ew%a8#}2zO zzxH_lmTE5o)gJw#yrBQ}THK+BhFyvKkSK3RaUVjG!-7?9QGat4Zo;(F{M&1PT#ek7 z`L##;w^tvo6%T8Hg^8Y3N3*k&M808D-(D#lE^L8sJsm*(AQ1^b`&^C zVJ3b2f|MfO3~*8knDUC10=(HJctJG08V#B&m|`rF@z|&{<$eOt`>&D&vYY}z?1G4~ zl06=FGp_TGW8jJ$cjFNVgod5$ZtN$4o3q@FnFu8?iVyDsB8}b;T2+D9#|izWv$*te zYmKbb_PXg9NH#opci1=ab(5L%Oa>r<{V3u;&fTE&LB+-maUCJO7iEyozVWO=i|0TYj?9%*Al9Ccaei6EP@G z#szm^7$yFKy=lYUESG@r%E?^0XgmHBN#o^Ehbf~*3p^0bz=0FAq+DG52?a{Hf-9+j zQ5wvo01ygnnyyopK+h5dI)w{(|0UMXla5?f6TweVpP`-^#uzyPEpsiW6_z8Ri<<@P zk3!q5b~qkxsOsPiQPrkARzQ=Ma>v9WF6v)(({io;6TBI?4U@|^CYS(mNXULe53Q8^ zd+_q)3#cUd<~nnknEUSl6N!wFqh5%f*#{?^f1|FNj}XxhHRtro@7_=TWVLQEd<%Ht zJ@?~EfFJjOrhO^V%((74_DA+ETn?2|%XH>+v=$!nf!KjjEMLjeP}9}RVOQ}!aD3tA z=~0;CCz6l*5qYL=(HD6BYw^r*bq*`uXb!aE6RmjOm%MT45&1ZRx_cN1h6z_X`narN z8VJNcC7eA>!}kse=M2+8OI9Py3jhAJQ^8URcBncg9FnL*ld!5|IK!iIhK)cSg$T2b zc#BiVe-M-k8k7;?oO?*$TrP5Dv2Ztn87fHn+XOhry`2ly)(`;fERF#idr3Fm6*2|f zLAS**JOe%exY@7U{^sljAA@7Sae%MMjFRlQ_i8DLcBMo(I~u#XG8DVI#un9>wclD@ z-ek7?iYuKQ>X~A7q$JJk|BO&~a*df*(D2>}<22@fp0-l9nw?hA@U}7K4MvTL7^0De zNsoIES%BW^u2cDg{RiLB#5bda&@*NRl+<&hIqpvm{6YvS_>qBv{g=B@8unkvfy5fQ z^CR{T72^g$C`!iP0f)H320S(t7pcuo9{t6=zhXMJQK>?0u+ycQhJNxXkzxULVZV>1 zHMM6d&>E~V?(Hje8LmGHvn&~+u}3SB7K%Mu!(LeuG1L2v1Ln&fw87jC8x@2SGMc}C z%7OGRt)SuUiwx#ncFI#T8v3~&;wF-|0i$D~ zxc5Y+6Y2ztg8CO^7r@rYr$kBu>db01X0sX_>eALdSV}x9W?uf0+>EpW(1i7 z39zbk7K(c}GM!*$6$-4sl4<}}eoCYyz$&dZ%6Z8KtF(2V)CK#8WMyNLfnY@%!OB)` zuxh&rRuCU0?lp@f4ouo)&U(NGbC(!>F*qEv?Fk3WFIYjtdnz)Rf3Z`xn!j~YrgH-B zvr}F-o1Bz0m~soFKzkX8H32^nheloRMDoy)vY%lLkWL( zEpBTe->%Uz0`7%t0!>wUAvrz=8g}A+*&3~)hYAQrNr!pYn~*xG$O>~-BGP15IuQyR ze##iE2X{pESu0RY)l{-|m0VlCs9w?p4Nl=$VTaE=0^0Y4TM#ypW0qGt#`?zQW)bgs z>#k31(lcUng}5RvPo#oyEHpO0#60%f{1kI)2N8b+v8mj)3EXwW$;XT^n@5njSTK0gK2 z5W#+xlC_;6Oc^!%rkkJs4lk8Z2wA}ysxo|V9AH`emf{!ud^8XKQAD4Ox*cOY<~g_v zuB*)prB#K4@c0$-@0fKZfignRIx_*UWN_iR!G#H65%QXzRb&ARdKLhnp#TlchH)A5 zee7TSEJqSa3C34z^=)u9`YAZV55Q@0A~~UI9;pTwg;aqTWw;EduvUaj527~UN4SY6 zfn4NRoSdVi$-IRbXq}CT?Ii_mEG~xHN>-RtRN^O+xTB=tC6)M^px%X2wb)yFGM1Ir zc_f~cfeaQME~iSh``^|iq%kLuAdRIseZbTG?mLAFet}IC^hTMwbA7C0X;PDcvY>Ju zxW%o1v$@=PuTAx?+rTjy?7q1f%EmlIgLztG1r6^|WH6txQ?{Cq zJ1Lhjdwhf1EA-g$ok!Ov6zO*VTVw2E+AR)$?xl74k?GgV720 zs|i1GZ{1xMJV8Nic&c<3ihFCAPN=a8wX1}s8o-mE5-ACIN^6a% z`Cq^j9|=$V5T49#!}E(T9C)64j}6a9VJCy|L`HM&;|@H3VFeBE2Na23W2bC2r#LCM z4}z$ngi*j#x@W=jmPXX6yB_3^1J4=fC*ZmKQi12C%wV`KRz2@#Ukz7O#nOQJgeQLD z-a?L1s54M0AY$c3*(w7|#l0sB5CAsTp#b`y1#BGv<)=hS0-(}dqf}!fs5Ew8lLF`v zsX#IiphzP?*{TiD-+b->^xt>e03CXSTARpd7XH}*=!sU)@ZPr$06oG^*=ioIeLA?blU%=USzl~HFCg3Sr|h1^vug~L;fdy{#tj9WQ8{qis(44$k5 z0&(wkx64#t&L6&t!$+PM&*NOHJmyW4WU>GYo}Q4-@syHjI4lMxhaJtyZ!O1N~ir|i6`10B5|wzlT>D> z{jvMDj|st@8zz9d^YRG5Cvq{Wi%0!X6G?Z8uBI>BZ%|ZqekOEGNM$!IBH%CTFolzZ`IPO4;k_aCEI0uAUmQ`&yKGhLfaT5 z^l*2;6AWVIGK$+Nc8chigPyE6r#*vn&=^>|Sk|J&>YD*5>0c1WE|$$@REy2sfuE@U zEfe5(w1XcD=E}6$x}jg<+q0GUW1i~g29FB}Wrl+%kLrj%8wEF+qZh%@mp&>F8bzA^ zKr^!I+2&IlAnA==n;k2_Ur+4XTxdD?pxBv@WK3FdA%E8t7jb$6n8aL)rZIsYt-eMn ze5S3z2V+dRSgMJ8qqD#!b%9>K6@g`VxLsmTN5=+3Pae^VsC8JReMq`S85l*Q*jLx0RtUwT83Or-d@h&KH?5;X?RXJ&GVlbgh_F_UU@f~+V zD-$gRN179|6&x?Uibq9&!qRWFbik7I8zcVLxm(uMacez*R^wzQg0rxdGRH8^lO(K2 zaNqSyx~0{4h9oMj#><8QtTL}4F4uy%;Kl}>fi78$w@=h2fI>^`Of7Z;KHY!}@Vx}> zA$P+A90ahoM$;GO)gfZeuOR7~mq$2o^QjSq%>xeTkDvz!9MD}%Od8Owj3*7~=aOy> zXsRTt0mX{cyA9G4Xtw7c(Dy5MKyYj);0~$=x{UPvm~Z)i?e7OacSy(|D0e)++WRH_ zzmAzQ>s)enXIsu+$CuAKnatk_cO|G>rWc_ch|7@38mSES<79Ht@? z!|h_QQZn#uX*d?lvgCkVDU<^ag&YtjW_n;^W;s4}wy_?gI6WAHN66q5_q+%30dW+C zZJ%IH=Uqt|RKA?9TToMV)qeU_djX zoV#q6Pya&L_CNB+@YbC{b{z>qhs>7IV2bhiPl^0@sQfpp{H3Y+?_qxXpUmHK9s_Xa zk}ubPu>ZEpnaCwf>h1qDAJSKvv4j89YWB$W>0JD9zeD&VD_lxWW*Y_r|EITrn4^9l z$|!*au2ngLK-{~YX_SBkG@P7(|#SR?U z|EVSGj=sl3H808T`nJD7vD7qw<(#A6vVw-!-xsIljg0aponr~eh`+8vOSE}QycnxugCQ{#aWO0osS2;I?#N8hJaNA zwu2nG#rbJqIz4Nu*|~&$HC&|@a4-s2)Cwof&RGzP9cXq=XPPq+DE|!zDFA(Nv-8KB zS=w-oQiZ;McK*7%*GucJW$w(>YbvT>$8tuP{RTK`-Cf77e4u755hfhi*1m`^i8w470m&MGGs{Q$`hO}DHU zQz0zB6WlPmvtR!e=zFsNiu_JmDvo3cJBe#Wa+q630Cyn&X9mM{i&WiMhdmXsnJPx^0oik< z!b{kRlzlfP3e8Kw23R{#0x#K>fGRS4q-Su}ccR|9v1P*}qTcybJw)B3a*{s2~ zJ*=1t7QVd6;Im8#9R z|6%S#0cV&fbkM`>{17wsU7jJn(<6k;zl|xPs108b2~5FNl3+?G_R!K~1OdX3A$Jf6 z2txsiMP9xKVd}Z_95ljAWbOkX%yS8Zfp--PVJP=;APF=)FeFjNMi|OJVH{{gN9Rj? zMnJq?#xJUy2b^Ykm3x3`-f!m$k~{aE)4adVrJ(ef^$tpda45V6F2f(XtZL;pg==3S zw5)uhG|XZbl1>!~)sV;H7ejMinV-Y!a%DRGJh`y8t^J=Sd8uD78|*Q1e*pRLFwhu1uNAROzXcL|!iw?zP2Br? zD^?}3`x%Sqv+!1=tuW$`S52n)C`o4+?JIrZS0TTb=hhp|&Xd6ZS=z!ol!7o=BS@X_ z6@LRBYD168h94GOFNo0uybFJR4+M54bT+V5FdDZUX7@{?F$3Z2{+$gZ*$8l)4LtrY zvTrz=mSaDj&W*&_!6k$v-0^3yUlyx1cQskCeQ!P0`N8L$A2i6X!LN0YuwW++$O&77 z*OfT9xmJE?@oSK@GmF@#;7sIOW?1mPfzd*05EaF}E_4ZOTM3oTrfyI>Rg_o z>dKK%NlEsVcg_^4qCr)Kvp6>Rc@n`pr=KbQ-~t{8&^>7lX5$H3{Fp3hUwc3H3Neo- z^s>KjO!LG-idj5Qu?Nt`D6)cvw?A^2r!b1!6E$WG0f3Bq$6t-Yx+{lpAwURS!~4*2 z>g2(w*#yZZ=GxnFKWeF%#Ads>q+qNI7dhF{idBuT%sxgd*qvlAQ_pfkE@ecrBK2l^ z_2*FX0%N0L9V<&H;B1tjffg~ulFY>czNL=p{bk00?T{H`<}XH(jluXu2s$-b%h zg>ml*>^UR|f)_x)-xesbB~b}tOI*0k1bhB|;_0dg6>uMV0RQ1XB?Rh!kpJ*A_boya z1Tk+_9?-HjFL$DIHqk#u(-_o^xZ&HbwFQevn!{oxl1~L1chamIUV&SH>JI7Gl}3!Q zH6i`#GO^qWYu8uN-0W6U)6mmcVX$uY;Iyit@Wt!_eprr^;W}4e)zXvQ6uy+do~DUq zEqijC!k3}qriqimPnYp&8a-Jf2ydsMrdegkuZp7-KCze-2)4v?kv=)8gx=aTH6_2^ z>SS;EI=5+Ra^@gR;5J>Ck{zF%{K1xQQT=tPC00XKzE_FWNhQ8PiL0eV#nkB>0*Asr zBt~HOh`$&)NNPIzY>k12t93Z2CYW*BD25Z^HK3M73Yeh7@Q8sZ_Z?&sb0)P=BE*H8 zP0M=eZz%urv`)oq+rAE8L7QJu*hc$XONc!-O=>Q|5@9l-XhUW&bG%q_XP{1Bc=4 zh~7leaHOC~_63L4-G|Q=pTZaXK~Ws8Inc=~g@l~NACM4Ph=w=gNJT;zHN!v2gwx>4 zDQ@E=90=%D_*ndgp+o961~Np4!-pY26%T#j@{s>MxA8TG5^ns!-Sh@!cw16p*DomRUPt`enbN3Pzb*oenFZ0 ze8{shJdL1`8N9=Bt2zy{jO2RiP(fUAGEzjjw>|D1qmo|uH%cNY2T5|ZE`6Do=fk-K z``Z;P=(>bIm|1>Ab@_wT%ra_TI|Q3U$p8Lq*s5I}(%%P;LcHwX18>i5aKz9N(&NC! z5cYHeoU@>%SG!><8$t^CO3_2X*7zz|_bylsE9}cUkTL=P1Hj1+g_G_0p`keJ@a2?k z2juORe{;lL(yY@paDbaZCG_(#ozQLG8PxxYIX2!#xo3U&W7Zu*rlg0`JY2frJ>x_8 z%6C!lxC8X(cYu8YmN?B6yo~|#oc{W!fKCh#<&YYU(e`TZ9%&U&wh-fW5p~O|iSatv zMXRUrx|OI1Ql~mJM*p}C_(ff%fMt^kMiHEcAT9`DyRIRx4q=+F>%s|euk>X!s))Dx zvG94obI;EMyh53^@Nhf`A-tR>sDk=8sCRH3IVd;|#`fjtal4Gr*`o}{f5zqr_q=7sQ@E22*X`6%(2nrKrCOSs{3 zG1@o5-#u%*nt=Gxm;e+b^sCN9QQr0!;kT4*oA{6gaYLmW*?DU!+RcT_XjzO0P4?{q zt6Fp~5MRZC$JMdJN=C%r%47+8btIs$9sii7S|5K2|_{=Bp5C$vFk z;KEAQ&}CC(4gH-zm~4K;8d~jDYlu^YZ!99{jpltJEW#`YxvROq*c+F4Xd<&L@?vNiU@jHAP3tgJ zoFLyaT|6Pfg5zW8IM>2sUvMqJjML?X)V{dB6#ud7t~c+YeK&D#iV0W$K{$ookaVNRGwIj1ZJqaQGQ_;I@cVC zAuRP&o&0PK7P5J$-4ffuwdN(@xR9Tih|WpPTVNYg@TFf zZQgQRgFw|J*Sve(9u64~Y9AH3WV>lpT0DpJE3N8Eq5V zoK%b!Rz`wwCpz)nr=AaK=XOUe>a~C^%E zb}v%qb0y^*-!-4|9=bGzwqQxm;5!_;GNR#U3x}WhM5Yo?jbpa}Id8!xEA*ns+%{Tl zfNe1U(JC{>1&BSv?8Z}8@KM|S7lsJt2DeCCZ_ z1>16t>L@yCTY}8wDzM+lnz{DRYRy0iwKy9_lsr|Zsx^I1a?!&>BvA^-BP6+GF>dpy z#+t?vsDkaFrW`vC5;R^@dPVEO!{=V^0kQP`z-L7S@QLa#*>Ks$r@H?gT&Dg-!R69{ z-v^h!9|$hTCKpYH%URr~lHpQ0_P}tlZ~UQ8OWIeN3Uh``P>r7cJj#wb?26iG@YGpx73=N@!wcbNAQ>j+g_&lLQHIV)R0 zyF^vVDwe8X6v5>xSc>2Z6_mGE8nK|v%zzhiqTJrY30gHh4%T%eKd}y5oM7F=$C9va zCyo(F_f(y&FzpAvyIZTVL!S;)0MB@5B?)j@ykXvFhZ>xJB-KTkXjJox2vosoQ)dIvp&)v4SHE#Ue=F z4^vq*MMfbDfDjZay?A#%UNLC9&HgZ3)h8004F)X&1`YqqTDmgp-cJuUT@Jdo$sBo` zka_d%C&;P=V`GPN(qbcV)B>}XFR2!@cJvG~YeDj9rN}agSH{R04eKL^2lYt-$fQcm zrw8C*4u%c?r{h0xOc*wc+SMmn>7x9+^FoiKQ6>7$KCm#YJi3CJp%z<2jH?|A-dkz6 zVmpPD5Z1$zKEX;_A#^c4Hz9F+F4+?>-6Wx2h$(4t-2_6X>r^-qM2&tsvGT-TUlEZqr$3l? zvDfz_?b`7@c=oUg2ca=NrrRy&12NXuiXyhLK9(W}{viumJ57L_OmFRogXz!kWH*jCG%DEdxf-bs_Z*TWyco6Q@p`1!eDhKSpo(O} z=wqPs*e4P%uT(}GA1=*hCi5?w)WTVGwfy3(qs(~ciQuB8faFi&cXZdGn=JVqj;2I# z-f9TXjQ}T(_Y?URr@a&R2qbg)VxJ0A30C{Tn^lu1SWS|NF`t5|e|pS7U9t!U0{MAZ z7xpIK{6zyqKVUebXcC9N2e>7J-N1`3Kn^<}M)LkfRqgs|AOTEOI|d+EKtcA0r60TYyUQOSog#>GIhRJVxkZ?hoPOBvAna+D{xCmi5wV5& zDY+<@a*6)i<(&K}_3v!A`)TJpxcWccryRS`ISLMBtO_K4Nw4^>4XNo5RKv2Z`iK2` zB0XCeOS2*M!A;o??)5;Wa%=O(#$D-ytnR*-EwmE{ys(xpRyi$Ua2Xv@;GIR45||a4 zKf!$bOw3H`o~ z?`-wC8|u)XxVPUJBC@N`B@|Kc)jjOLNSNwGG}Q9(SZr44b{VoOwOJq7BXNG3rp*LCplU33L`!7-!_Ftq(xC!1jy5Xk-G|Ri{UC<>M zq%%*s5o3ii1#BuFYXuGO1f-g7MzOxo-4b*pFdFUZt}FQy3*)2roD9lXN-E7+$ATo1 z)SQ9U>r2}QMB#625Iuv-G7hZBJS&GF$~aJw!<`~cPLaKbu}Ic|ioEl+-O8m-k@Zp} z`#?n=cZ!_q6j_WSjD zQrmlGb87tL%Twcnw)BekO7Gh%{mv^=^I!97YW(J2>6awZ_pvXTugHpAXJCD5LRNHF zsNE(f&0Mf_W2`KiTBb~gU0UvL>_HOj;*BE4yAB0A%9UA8I$(vluzK*`6)TF1ztCCy z3A3bKOyfc?w^sji7fU@kAjsB7XZ6b)uNpQ|O7yG2`j^sJ|Eds9*^XJ#LbKx{QgPmt z|KUEhC@amu*IC41i#fmw8s0Ba+RR`SD3AWrPUw)4D5AS2@JHDRJ!P*4<18sRD~|#( z&>sq5G!$I}Wed%Puuq3bJ_Xu1L%|~28f*QGD>S!4ZWDqaAP_2;fft_fm!cI{#qMXa+NZ^` zHX{&f&zKeqZO)Kj7K2$5?89ImxOt7lTebKaX>#@>umTdH6kh;Cc(~_(1e^qEAtI8r zJbM@@&D_<**d)=mMOG5>l|sQ}%t<-rPdGinrKwz|b}KmouSapjDB_8$2vj`)R9+Jn z^^rh2XAy5WF^fE(!y?LR+R7H12RppTMFTKk)~=HWTfN<;Le67t-|9Rd{NX|N=fdRv zoMZO~=h`|9ADExot<#gbHGth3n3Pj``1MZ-yaVmE)H?9=i> zvMo#zH=1*~R@>x*k`9RdXpR7Hoq3U6t}X$u;=5FQoj#-)!wO&(aX#D)85A4gdnGt@ ztneWrnUb1xy|EHA?(cTry#;Lr^*EPWDCGazefI_=SpFgL;uCKsZ!1r8H>|?fkp2`I z6p9G|xRo^s!@x496{e2H6q;{ciIs^&wQlJu8-iRAfl^65ZnRprWn8zV*1DZABwkYS z7148w`|i_GVTt}t)EFO7{_E80cwjPrhahNZ>6TzZ>d_pWpi%c&-!h1FDss))-MjyWjIz>;>k5mOn7()$`Z|N#?Z@0 zVEwL}HX@eQf>3B(27;lM3<+mRI7`BPB%Hd2%Vz&d)^J$=d=2JA>vR*Fynn-;7WS0KqC$zW2wi_v!6l%^`El<( zz!2^(q{kL(xfCf2;@-QN0`>F-*4A=`lneE9zS%oVzj@#*mvUp7j*?5k&q_(d^%wHB zvG7u=)P+5&SnphJavBe52td<7eXAj`vJ>?^V5XfRlcQIjnG zwvUiSF2sGwqD_u$e~dHoa!C+adm0}MON^{AK68})GfRp zsp?A>k8g#y5mbfdHG4DCV%NjSFt#?_4^gUJOqbk%=m07<&1ND4zS5iGQlIjV3Pdz)ToO*DJ?D|u3J$Xs> z^z8lap)F3-11nmtNOC>@9Gn2ra;c~1fFLTBdg2_HCrMiHvn)=lQdXeUAaOYdtVuoJ zKm4K+B0POB<%qoREynD(#*`l`ZhDS9VWyRJJ+eZiYfBt(p0)ju$x)##ptg)8dj-IZ zH7hO5Xb{5*5!kcf)DuObaE$K3Jj168hj~y+i9x^ZbxFW6P-ONaRa|RdyEuCCIIvzfJ!3%>Tn_Z zD$Ub>BsWx)3rWK(b46OM#PcGlp_o$B7fRby4xo72Tyql+a)#>x*g8t?ntOj;>yzl( z7jBPh2!?a;{WA_v?cXs6*T0j{KWiHV``Uhu=m`UyiSu8%8t=DaIh!CKzb6B)GHx!% z6L;`hH&<%VbU1VzC$xfDOWN9`k3o zqXzLUc>wk%k+X9QDCk&Y_)BOOze6|hSLpu(*aIG6MspIaM8(1nU=G{vAho(A7vDcK z#~vxT#TlcRFOcTGWG5yIvX|b-B%VRxhdHXR5n%#~KV!b*Nz4{nsXRiEDco1dy#TTM<`$$mYK#)V#7W$`e~_M*fsEgqt8JXu$w<1 ziXhAI)((P^@B{X`nD|FQj}MGXzd>m#hga1-54l6Nb4Q_bMYH z9Gs37S%Vc>R>>7x7WaNs1RQ?^1Z}j1AgD z2B*41oazo!)ukZQ{uc0ls`EM3y?DDl*cU*6NlDAdIGJPBiwi*1#+c;G=H)OsMPVB5 zZ@&UD1;Hd5B<^o#!sJr^%QXp)(u~lAzK_72_+TpIst#=a^vLxNA;qJ_X zHh`o!%r?U=IH60!tI@oGS$P)ClXr+JP+tBwNJGbk7TLU4KxN!@Ejx}HW{YLO0ZFzuvZAU^33cU=jfD?amI zzgL*(BP@N=*4a3^iBuBg-1Z??$o}}uYs8i}Lo3-FKw8cfSobv}7J%wkSMroD^2Td= z$=~}PnUNxoJooz4_^4j_Kb+yn-~KoG!^oc;NdE9DV1Z2vqKddTAGs{~!|9NGe#hzF zy8rvHPO zy6Z20w~)HA8!c0)0CVr5yegcxYiNceT!+s#Z}=^OaqmrMb1k~Ay#PNk90d*6bQN3z zT8-o5#pm$&80K*+_4IfV6OvAk$4jyAJU!N+N}L`yVS?Du4d+XnOToR!Dr*bpO80n% z{PJr$O5hptPqW!UoFVJVxQuX7vBj*mf`<1Jv}#UcH2Dm<=q!}cT~G4|o@h8`!`sxE zI8narqKr}=x&lZLZ(udRs-)cM*y4@AU&T5wv}kvPaFjZjne7lEl#7f4R+~E_nOm?r%YKmjPlE|6 z3j9DNXFp=s1TYkXn;+Po@`2(@K6CfsilVqE2x0)PZcNBLaVU0ERme-bMh zR_AbTqM#?`0(=CfO8|?h+?=;W5f(K9s8a9RM&XRz_L$*3AfT#Jd|w=e7gFG18tl^@ z)Q$+4%jOl5^MX3+f8EF4!sga;-r0!fn6d8C{tZTk=PAD4q^T46Cw*-EXcGFM4`@q9+Z^BHRoycrBr z^O`_A2*lndjo-^fexXWu2VrsSu1xy1X(eH`3NpoK_BYKHebgh zSn3OvWAiVBz7Vd?W(Gu8D0q2rYH&(IzDzd6wyFt>XSnj-&B-jXpM$N319Iv-oF`wg zYNC05l@@Gy7Xq90p~KplK8#T-Tx5kqFi%htyqx3lh*S#i0MYuMpxzvUB)G7}L~J`k zXF(c-kGL4g#oY)#oDFLj99<#v4N-%`<1T$nj(pWyn$QIlx1PA62E7F(TRL-9;l4;8 zLVc3bY!H=!QmA=HR#2o#hw}B|CS=4Q`pO$J$1bVj*U?`fn*H8SGqNUa+DiFR+u%o2V||sc|W?v zg9RR4??ElKtE!J519O~ozJsUy>&+6QERKAw%(uRW`C4IHv^cK)lF!CB!<5~Zvqq^4 z9J_suj(d!Om>st^?9iE~xIGzm!|`^jO*pq?1*%LXo)0c8R4?AGBNzZ?H|V9GSj zJ$o}nFnC<;o>>qrfOLAjSi;+i*EPBDUyY>%0Oa{NaA?;I=!=5mJYDB${xK$0+0B_J z+2e)eDd--6gP=$Ae1VYWA%|OU=HlJ0Pqw=jG@@gaMh$4 z!)4N^EpU5AVg$c1Bk^_UGw(7!%K%_Xblmo}0q%Jb|JSp|CG2Uit_XI?h#qY>Iiog8 z!Ma>l2c|X>B_FPE3d7B62NXQf4jFc|9ca~B`#k4Wod`O$zWB^#1+ab(!w_L)Q2fp%638+S=HsfL?9FbUeL zrrK8KM%ICBbikBm5B%@C?^d^e1QI5sh*MLDS+OnlK_O2YmNC=k_N2Q#hXZ7n!O}$r zej{8rqY)W^-%Ek18IfUWGef|4bc~(wlzGq!F=Mp!Nkd*#FyJ!el{)b*D}BFpIm8P1 z5EzdazCy2p?x(j$_4lwVCXgdqu(kwFn|5`A@UDlwj3k?sFsPC5p8qES*$6mPrU?C) z#0stcJ-p(t1@2|8qNJisgZI?N%h5pURgQx)uJ_K4SmkI&wMPc{Tn=$#&MFJdBt*Gd` z0hE0J;&ab`p8%mdjlNhds9+s;&q9&bZ8a|hVdP~4uwYFT97&-pvBeS!n?rAgfR>UXx}h;_rZTZkEUL{(QI)hHtxo z9@ywNK%S!rMInmg)f^i}-40!FY{ewih&lJ+uAc?#_hi5n;*hl%;wq^S{;Bq;3IY2W zoCQ2m1f=ooiN(N1fChqe6>Qq4qf*)NsLVM%C)En&V@@=BnDmiMWY>M%z&L-o_8kp& zTldq@GF+vtv_Tpzz}3%7kzFQ*O}!B~!#z)Im}2HDVZp+ro4FcX>qd6H9sCE6I?;mN z*f%0Z4(^0r!b%(Gp-tt&|3}@sz*kkBdH=aWkib4D(b#&4nrdh)je-_>w4Ngg>;oqf z6x!egX|YtTZ6hRzh#E)`PPa#y8K>1=UYXX8_A=G!bVO~d2?&Xz5WJ$cime@Yj8+uO z#oKwmzqR&0ISEi|+jst-KOb`TUTd%Gv!3;==Xut%o<$Et-fNu55GEWHoU{HaoSIjm zMS`9u@WeyuKU|C9dP06NJrDmS`w;fek9(6cL& z>mA0@xL|}E-MXMea$j`Ef!IrELO(%xLF=k#4km!7wT;=fi^680{oTMVj+) z817Rf>m{j^9#s3$1*at`YGML%)3&Z$naC|SDXfgSbdY7w(m_47&M9Hng0;!$=0)|1 zbOLaWN_vMSqE9Rso8;$ouB|1-b1DjwdKja?(mbk=ry;3$5ei6ZqOF(HuD#sR_|}34 zD6Zu)3U=Dx(ztWkXeA_;w)7W3*feIE=&m8TG>5ejyjG*M0P}=EI}vDhWHuG$^MpD( zqY_!-+^eIVrs`-{%LQs|GP~%~YbSG-A{RL`PzNg0=r(t?FG# z9a<&qBB5m zB@>&BPhfP15y}YdFR%!}@yb6rOpe?3T7JtbxvcO>M&CcY=Q zwwnhR2PAgzw*$uiw#i&!Uky5}JkaY^Ln06L1gYU(GhWo8sPi&TyuSuFo$2xWX>n?53vS z?*{^p8U_P!tXhWqx9ZSk{zAx%IfLd3IRTsDWL@pQhVt^V*E^W3YG}-$@Ag5dfPc$xy&)4dX|G)cWx677drtGC-jFziM4>R=XvOAuUj!PSk zuf2^@HqQAi3>Q#539oz{qS(9EE8-L3OPrgAP-Y^#m|=f2?v41wD=LeeoBo^T5RRkV zD8lZgaD#iRcu>y4_Phc@(iJhL}P<19$5>3BPAxxkAv zWvn7g`m}gqr_qhZrg}x4Fb_l}=5?YhwGrqISkpZ23?7Xy9(+%vi?(SfRELJ5_hpoY z%N~{z+xqps!xDfB{BeBD5P&Uuq|5Gl!p{8)5rYc97bPS7>r9CrtcT~xD}WKjVxnlq z+|rngJm-H#CWSh++-@oz*MUBVy-I|i;1KU{zjm)tYwF&=;q}P#jO#-o56u0=h5>%p z?aaWVa(|qER-$l^(BTw@3g2k{(}m&zIPFvoGuIUm2H4pwN*pGXxcdhMKmq@Z=~A2y zk=l@R^UlIQj?sxpFKQe$80-*#{#W$x3q~&bi~V~A<{94jZ|>hFZ3P~ze_Q_TBlpkj zmoXO4CpBx>%+5mHT+h>0?@cYK&rY%&ubR;(owhbmroNi(Ova}-aesCZ9U!Mj`m4qg zdi_EztnW|P!g|b6^1D}k2=emB*xk_SeZ*08ES-B1*E;2a(=F`Q+g3kW-JOhb)Ai^Q zB*=tw_LInkJXmnhVD>K6TC2B!#rxmx&&j4g=Y0Gh)t?&&^#}S<1z*`R6s|>Dmw~Jb z_hM{fZsJ|P^jvL}xXbqDvG6aL;HKjzA<|q$f}fZKm=FH>X>AI0qYG;xx=%v@!+(<7 zwtYLw_&uh0zekBk@z0sEM@))=`URscGt=CgQQkj8-Rc>v%nagdxF{Jcs53Yn&P$(oXB>7#0xyZfx@PWw{wPV>&FnVue96XeI4PP)`&$8>rk zD;_s++dE>KtGS3IS=c$Qquwhq@>-(pjLy78*Cp^ViJ^P-BgoeHGm^CT#{{Sy$Mn5= zOPz>FNHzL#ToR6XkkA43y~3)>s-(v;Udz_sli&A; zfS#EBRyX~#%0?{5*=NOvH-l0<>stZoUm?dd=x(IQslnlNxzq}R?yvf(;d&|BPXX9y z3-)MnNm>CJYn0IGt)uERjx5nzpT8~Jbzt@cPf!X#sk57GO7V< zb5&p1rK{Xniq}h_FjufkRF~{$Y<@#qX`eLQq5hHb5^z0C*I<0%9F2A+Ss>P=z(8MS z=6F>X|Hm!`lv$TMv8FV}+B3~%Nf>Lk6J}<&P;f&S2_nZ2h}6c(=}J4H)_HJgO&;Tm;IheS z*S)uKV-u`u7qcxy61_GBv4SI;O*1R6ROJhtdzV&T&DCKMR{-h!eaY}1#V;hP+`cyR zT47&Xc&)Opi+HWEuUGLp!M--x#}Z;97P8myT5eyL@>*eEujRGMzFx;`jeWhI*9rD@ z@$fxuT_uI@F3aSBf6k4!Gr@ECU3F|3pQvsss(l8dhfgoEpAK4CyzFSKRyms()YYSjS+1L)S@=oZzy zmd{CDi-*WM?_p+3h4J&Y*}r9|xsbd4QIhacUq}#q9J))~3Wi2*3T)x(I5=rpi;1gd zx|I$U?W()|1VM9`Q#?%DIw^bcQ)wpe{wHmc{h{Sw zFolS2K-}UP*5`8|-|Ly-_~QtaZ2?`;Lfiu(be2CM{Tkw?p&sni8fxNM0wbefQ4{u@ z4gG?v{Fi49S1I}iKb1Xn7&|Zb!hmJ3`@l!+qCHOQasO$S2kzlh!t0erf!oPy(K^$y z7|V-VA?3MPvfCV1z7sdrYs_0fh6*fv^QVM`mSYw ziZ+yL3=22(=V#wD;f+27A8*gYbi7lWioKu0I%aNB0yIp=z{U=j;Yk!SK}b3C5Q-js zh@e=9X>IiR1rPRjkaK)=?jU^t#)4-pE3_`S&Vo)Cu?%3*Ir=~%KFV)0}yz47Aj$5TZUy!;dv z>|iYymK(L;tKLYhioXJ0ZN2%;*Xd_s+g==JY7h~=uDR1nWt>oPM;NJWs~*gYCcb{T z%Zg@A{&`4qkI@tka*>hdL=x41>W9CVf7|Zs@GCNUZ1{%!pD3?SFQOfN`7JN?n$2V7 zU#GF#H$TlMZyb+wx%po0)$Lgzs3w$hw-a>R-YZ&gAs$QKXIk6_K71d-lW_|-B%?d7 zDt4ofFFXq!S=)A4fG6GR9>ED!bdmV3-DuSd-Oks*s^4?OK^g@n)d%A`cK%ec#!2I& zJAax)tT>uo(;MhyqI%o>)wQY0F}11VR>kYao_BMr+)o8dsFgMnv%=fkrPSV|XOU*~m z7qZ;-s2Fj)hN@MN%1fUxq*A1?-z?`MtEw2ZzxV%7{=4OWga4N2qXY2YI7SNjZ?oU_ z`NX_!-rGpL+=1t;`o5^-JhrvD+}K%lGa)HSSMuayJ!jQ*yr6qZnJw0(mF1eIx)OsK z>a;)1n3-8xM@(Yg~-g1#WXrWNpR^!Tg8z}=-v-gj#z%v{bbaZ7RCev)}iP#&Q0Iv zn?#g|z(sEavx+(E>!MSOoOCN6)$VJTsLlP2HBH}7Gx7C%-E?|EO|b;-N@-hn@5M}U z;M#IJ;A}bNuPdl|SUuT$r9?H2lPuNWI4fDvN@OVflbwe{j+w~CjmS+$rvi2X_CTBe zsjqIs$jt15iz!Gv&@VNutHV2!w+)$TuUlOo(d0+Ats1xnIPE`S#5hu*J(5IfVMTpv zVNZSP8kTnvG$Subz6lr5gtrd)bwbJXbm@dd^{{;?iqn1=<<)z`#yt}3AF?n?JhGw| z`qqgoa78Q|rJ)S#wBJKLkIQ*KHRm1n(&Se9n&92#P#IvTha1hdQc|{QDd@SJbIqB4_zGl3 zAH0sshNpQmCzMR99z6jWbs&6Yp0wN?S@!B#>o;g5fFW>$NgkNgaH?su7BfuZf-A%y z$E1&UwFz=7V3HxgY`7zFKMmZLdo=6vjg@Qo!V4VTQyX=*?s0z>ta@MJ#zK%D6K)aR zosU6u+a7Mjm@go;MnbpzskMdmk^51&EgRnPImio2jL1O-vZSWwPZK?-g?5859{m*~^%|ksp_Hi%t^QW1q=~9|M zgStnVjDs-9X=<3`_gmR~JkX~Rf6Oy|+#^K6d?HQbH9<}8=(Ndisu zkGO6fx%QTh_$t)%BT;2L?J4?Y&J0x}Q|u{pA0Vy%9Sc_~7GmNs%Zymfmt{uI*wtxx zk)zEwHgBcbBJBthuEsWDui-^LC{fn^Ng4${K*=H znJV3n82&_L$?_+hPz^UyjDCE8;y*YCqZ0?ROM%|Lh2_f*bXrMouS`X~N6lT{dxSSN z*l|~Au5Km`6W~c*(zXrYtnNdt%uR4w2Vlg(2$UQ4g*{frP31!gnwY~@Y42v{R!Lva zR>Xn#e`TM`ZSW;#iy^=Ns$&eA%oYQD<^Tu;| z78AGnc{RlFqWM$c0QO@g`M=fw+W*pp+JpOl-QU*#-7o&*`k%YMZtc-;HN-n*+-zdH zVZ3$yu{Fy#G;j-{Imu@+6D5q#6=9i{&zpVueLct3remLi+8s6t%9l=ZO1_r^nXAof zrmPGV)#?Kt0H1#PyO~@WK3Au^&uF8J)LuQKJHW?w6KMX{vVDqidDYYngGAh}JTr0EH7Xul#8J+n-|r4^Yhc4J6_M#;pl zzgb)b_c^rsufcrWXRzqOeSE4t1t3$|$Fr>O)*Q+GB79r8 zoGtel08H-S9csHjZ7%D>kZyuAwi~1KC1ov#A^uMQMDyievlAl4)-%e22}rVD@mU`f z=5_WSQHzrg7a5~@%(CBSGS_3B(Ya?t+xGnQH#4A}_P^G5?j12dUWg~3;DkT4vuqf- z=VOmThfT4;&Vqde?O8jDCQ;Ml?~DI=Zl^Q5bTw_m6EBTCSo7A9>2Gh|<>WqK^SH0v zxrqyIY1G5In@1bQ%U)llg@y^rIdbM_IZFYH!(!OImy@YWx5a;x$0ks%GbVOd9lhek zz4dJjiASvY@<>HDtO{KV?GHi<~j&RV{x6FMG`UN$y8} zuQ1P9+oLt8Vt)LD4fEsC4GRx()~>5_K3&whsEj*dbT~x+yj#p`=W7vX?b6EQowZ%L z8M^k9!Jb&@e3J~x%1UQ#XKseh{bab&*3e6aw<&)owr)lD=(n`h8QZy}re!RJ#GSFF ztxGCfj_1VH`o7F{s4cel z4vLvplimlt|FqW>T6&)f8&u9nQw~s>tzya#P)uPRTTa8BwY8Ne&QDD$=)>P`@fu3a zCT~3}3yR!1@z=m$F6CGl6u=x}F!%=QylWVvTBizmf#0NdkE$@LbE?2lrwWu!qFQfd z6kJs5-R5b}LCKm{92k}wnl6SByYQm*nos5$EXZ5xQnS2?`+@grWWRi`GiLF&M7ps+ zljc4oW6h8ew;YDsi|Rc(%kF%E#*B$|yYt?*^TSy?2~-;KuX_w&M=x{6KD%UW%gIC+ zFmOeLyOtc&a+I^S5bt5fGPXR6jtznZyD6SQLo z%c)uiVXDjH+w6^u;11z3G4-J5g>Nx@Ek#R)w+w?CFBVQ}+hego$jt7Kj*w51hrw{h z?w+4Y9t-wysC@DMi(m6M6yI!%uLVByQ>Dk!B@C<&P=4%hD1WpqUu`b{rgGzUEE-N> z)t|sBB{>sp<0H_Z%tMum&B6yG zoSQPNCyCSr82?~DKV~84cg`P8{ij{A8gaF41IRe$8k!L~a~=_O&X`Hv!p7o@Y-rkj z3XS-J4V`zFLS-{-=z?1nI(nK7&0D3=ClZ91G;9zk_^Hp?AkLgvop#B+va?sY?`HEny{QUU5ykL6;{{wJrg;wRc$}ZNf|c2 z?bl(-u#2WFXZB`Q#JU3zM%_}`L8@Tg(QCNw=-o{7@^?P^G=F_(Ky#DFzRn0dZi16` z(07dhh}S;=k=y~m?fswu;QoSvU7f@bj6 zR=OM}3yW&gJP1n*YiwJSlQP7NHmwU`%Ip|)gem{7F}UUJk3I&MlE*D z6t(&jujlLK?f%7Zvo@kdnJV~YLh*ZvSrRX-Y~YN@3GPp;*h>`)685K6xlM|FI5#b^H)u%o0n{E)$PET}2j`&l8`cCl23K%{ z!C`U?XpidX2y%e!{Y_F)J;8?oy)7I76ap|7hSddhu)4|w!Gwls}`O3NKkzWjY7`s5oQeMIjh zj~&tEF&d3aGhIk>C1|owKH&S1FC+}1 z7eGgfmP??HBk}&Tvo>EbrOT7fl;6cI3(t4w)13)t$|k-hyhoH^{Boyiqf^BKej!qu zVb@_|SQed&ANAk-6UVmJPAhP#IFVO8gBFpPucfQ70VrS`xAbSbxZCeA$?KJfi4(D%vkyG_H&p9Pd6+~+G_+?HNjh4(Z zTg(P9sj$4p!c7fA?^$ynA@>alJlv$!}^z&U3j3Rr-Plc_+XXxGEik7MY!DQLatT z%gFAuRq&{0<;Jl3O<9Z?8UYJkTv%MBg_WIX!*0LQJ~C@hnw~5T$8-Gsp6WSS zUG;1{`tY^KC%hr~2=T}A>{)(X;*SxmAQV<;lK9i3aR*6^ z@D++bCK-gmBn!nKlk$-;Wgz~Tl#m3QG7x_tilTTFNh45)7+wTK8~d~oe}w)4?a*sT zJM?a7$C0moblUO8|JaoaHG#yR%_jK2DE`dd2i#4A!5s=a10lYeUK=Pe3|WY;F_Cs` zvJe-1!jxHvcZ4Yq4)McUMxk>EATE8%j=nFW;>&{l2Y(z0_R7Dg?X(3{O67Sa8I9Oe zOOc0y<})Sjyv|FbUJfD(J!RPkW(~9c5+e#-Xhb0_3=JKaYp6$)B%oG$D}PP`nj|1m zVM#!1cyf@gLaLuY0+Rgm^nO3A2|nyol<;YPHLvUlJ`8T?%AVlEz`kcFB`qjfZ6D| zgW+bQ_Zc!1z27mjU-ma>_RE?8)VZT(zwB?=?3a!pPwu$cFZ&xfzWjY7_iZ+_T$ytYQ4SK&(~MKm7bc3x4nPJf+1|4=Jh4{WxH_grunre;N)oSlk-pD z(DCE*pL~rE>*mMVOr2j_$jg)4@7E^c{93vB@Gv%6yPim2ALiE$?=+RouS*r7d2x#* z*9|F(?^=gmrju5-We!;|lmcTPnhF~~yr0cl7^MN#9=z5~gKMS2+94liOE2h~K_!g^ z_nV$my6I5u36GfS=-J;|MShWwXMhHR^MrXV7%75(Fz zl_9(NO58BTjcyACOq0<=2t~?#&iQoDq7$u9SGNHuH1=)R`6O;WI<78x+i5Ib zws<67tY#Nq#?!C*1*gs*!EwomFA!V#`kYW-{FASR`p+`}n(84f*t z8fCZb`R<|`OiP+hv8E+8nX-$1C#k;pLDNWfTlo6+x2>67jeqHX%G5vIc!^5*!jITI zQR9(NrrCGXiD-eY3P_z(gFQv+objGp%1!aIO@av$WVG?}>JQDvi(r^z+GP|D!TI}i z@vp|xC|NpU&yXnhU;i#yylEBwAI!@pV~Wsw4nVbfitsmvnnL5VT~&F-U%MzfETXhB zS%boV?Now~?J+G41)UDXHcsPf)Zri=L*6Zjy zX2m0mhv6BcdSj-$ucWOzQ>}OVF}{0St#fy09W}1lKvvHa0P4IAalCtd{TCl(yq$`L!zxo+ES3n)6-c|8Td{qO!iSXRBt?w(QG+>Qbb7Wr2 z4CX_m^=jUZ#;mk;F)t%92JFW5f&$I&i11YOeG=!kCFbkLb^bNl7->1wn4!ok6_@>* zw7!YyN57|kDc7z6`mIGe*~Xv&UW(ZtO(!eI8wX}O;&_GuQ7!Dn1pix{O@sou ztXJfZbGnK=5Cb9pc##jD6GR+LZUSeR0!<12>}+OQGOk0X4Ep~;x^6XHFaAYimUOi$ zCS4Xexy1AgM;ZV9thnUj7xhS&y}H_V5D2j%`5iy)?)llS&0I5JXrYC4KD2P6p@maM<42lvAyXoR@;kS4Oq*Ct>UCh7pTe!FBSb9><=N6J7$ro?HbZ=B zC_gW^{MRYgl>cue+xLDj3Ld8FY_-&;ItsVWH#HO_bVTpBeV0+Z>%FMrEp0mr+BUvC zw;HVyRCC?uY(W>~JNFJ(xs<0)496$w1*#4fk>OUi1T1`<_EVkFOe{x8ZuL%j@hb zZT$mpM^%pNSoYzfPoI(xbJtg357;${iC7FEjMI|9&3QQ9uK#-^s}M^4ND+QF_~iP( z8JsBmejs?qjN2&ILLq?!ID1W}S3GG(u-vlnoBO2z3POUeT;~J^7(Btx8~b5qbuM@n ztA%}n4#z!sP;ebMYZ6Gm96(wWUPE=9q4j#J;G7-YEYMvwR4)K`)sW8K($<#&?Z{>C zS-3)3)W{3ykaO>P3uH`LM1!t^*$Ve_26&q?^uf%pzZc$iJcM-<{3?7sftV|Gt5R{Q$SH#vuTiG9FKS^g7+ zd5_g|`YT-;;fPx?hZl6pO`f2()kmM7njRf7{-2^-UFU4h!agFb>@9pn67)U<%lLyD z=nJyJx`BkvEODbf3on;vx#*);eaWrHH~OSV%Lsen5pwjWX{Ouu>UOsIiJ(?^! z)Au)*J4fZZZIenMEo=sB?uL%Af+-3M>D=T%pj~s3z1;}*UT0d)#ATebA)p5AX78vI_yX{&*nugEysPFN2ez+Il)%&hDYkS`?3M(G>gbGgA_270Ozs2FSTf}uH)%9#Fisbdd zpantph{4YF(IiWO@aaIpq$N7uxbK!10Bb4Z~ z{~c!6YSy3YCckSmABK<2CtyS3r?e9oM#GZ}C^yuT>tzCy8u z;Pw`S+g|azQ$w6S0(*zx7-Co5o5D#BV=^EzeHjR zS;`t#y%ct!GgB;I>+RD)c~>}Zt|(~xFn`g}Zu*=LIf-5D7D^I)#&14C>K~GvptLw7 zT6Bz?o*pEjY^7-k(`0BfZd1uZQntU~tY{PT=|W2xtt@EaaHJTYwsoL+ z{mp$ijLw)(9~QJ+$ke^revw`T_r$wf+=TaAK+=3hGQH?SeD17HL|<$!w`CN<+0@_c z;t=-L|9DRe(#N%r(bk1Z?!|?}`=0iDY;@6o<+Ix2RFG0ds81KGN%gP}{)iuQgP~Wq z(v+CQEurw*jLo<=-p!yq+38$QV!BEaDkJ+RxGN7YaI?Pc_uOSN->!CN^MV_DUMK6l z>&bA0rrm8fnblor7#iZ__&*wWfAB2;+E-(I&;%igaJ_Pozl|Fdo4_~-37yLD+Hwf1|7v;8+6q5Mg0!BLi!op|8_-XFZkH4?swIFJHW^L>Oy=(AA9R?_6#{mT>WPr`fujml_L9 zjUQ0s?%Wz*vNbMNX6tIe&Y8KUG{eX^ZAk^f8s+rH)_9UhgMH^RQ{(OcP;YLmdr39s zH(y8}Ib~M&Y;KJY*&4?vb8d~JOld)l9|$wU8hf*|)M|jb{d1^Mi%_4w2U1pwMZy$^8<4XIuoCmz!JR7>uK4#g+IrcGy2T5W!G|@gzwU281sMI5i zmWi$@Mj%O~u8PDr4%JM8Mz?K-tZ!^RGbWt#KVvQA@&iEk2Jq=@(^_kbD!CRL^hCQe>rRooW4>!h-&(yNuXhj9S9hnOe4j%In-8aM=$&Dx+|;#( zp$h0-*M8{Tv%Xhj;2|<6mTb5G8dj_DZgpDKA`1cnp_#-IchBI-b8GJ8X;&beJWUFi zCGKLArrRHNotdr!n#QgGMD%*-C8GKf;s8t|Sna^178dUhB{bp48+2(I3I_)eTD!tPd0Yg>8j>ehDeosdyn6Ra43(0ht2?w5zhSr@lxLfXT1eyb+xIltxcxJBvY4_@E3t~1IzM~6EBZAH#ERTC)%!y zIJiju!Q=UK6EQDI_AEr6`AH(+<6f35fZ&AQ}*Ox7DydFV?R*uD8zjY_7z_Np*ipO}t)XNCdn%8V0LcC;Jv#o2q^ znX*FKtHM+$V(_afC(N+1$f)Ynh?X1r>Lsnax!+rt=4UEePQz|3lZZazEdL<@M4}#0 z#@QQ-*wC{*X+9*Zsqa3as8*$4^~xvAW>gxPmeH1Ubg(_>@2rAu?9qUvC+8b_nVz-V z|G@nK48l?E4yS!NA1yRzB)pL*%F2b`W}U7Ty~t&9wJ)7zivsCJ zB(L{4_-3@3N3-5#$};y`{`c2r?VM;Ir`kugeN^&b?L69s4z~}-K1%E(p9e|a{go+Y zr+vI`AAhuu7kR9%XM}`V3q~6MaNHoY+5i6Qdo%mOy0G3mJ-%@WWc^_<$0&X7SSki1 zyC7@I?{`5CXF);sNS;N-Yb#Z+! z>*AZXYfjMUp&RRVqv(WUEaQVwQ?W88(^usuqi?lv^KU6Yf7UPg4mV=cYBW4?xA2*; zTrG1)e?ycQ&8z7YKBly>w5R!F@%v~bY9 zJm?y=TQIo%H+IE@*#$R(71Jz*{`J6|F&WrB4~{TcRbUin-R<9Yi){(CWo`eea;M+9 zZNRGXr6p!nSwlZ^Ru#K#gI5}D*)&nveRdU*H?t;8wRafSX;*EkxbJm|1>|uj%`4v!=HuX0qnR|;t34l9;=GZz?Wy&?S+%1ng7qNF4;ViEPrCm2#!k5#VK*meN=ZvU8nF`(}N^gaEc@9-x-Ye26PluewV1VI+oBse!Y zr+;H4;A&(2(&OMe<>tzw{ZixPPUksP>Omnt6SxUORHNQX*^ZJghfAC z@b7&^URPfs+Ei_o%#|_srJ;kwoDKc`?1#GQM}zv&h`pxkVI#elZJ`Czv5HCM-`_;5 z{rkTGaw0Uu*!Y2S_`I89%TPF|BSqRiY^+$-ST*hue7c{^A7;8P_IYkCe@Xsk@^>MB zmvqHWM&o=|S1e{9GwtJ2Jq&;DrlyqKKS5Pa4y#m!qiQAKKdrT5>TRM9NOe=F9_UUl z@xRTf0=ZE(dqi}+K^<@0&u%FDMPD%TP}Wjhn_0R2_qFF``+rVu|G)mf-~X^m_5b6p zS>(Zx({Xxdrck$EVd&%lNTi1y1QN2x{yZRP=(n{11dC-(-3rv>9{2R_FxPeo2jfR8&>;khbRi6Lh!UmHBpz!4O3O7hJ+qa;D~)X{s5J7-k2+`y1Ov%^YsflhdW3kLwTS*39G-MCeLtjJhrE}e`Shyh$R$FIU92{U3HUN1GfYc{* z0CL9_0*G}?vJXrqmr$LQX5QoetMt|zI&n(L(o%0q(ZngGON($xUT{x-JLewiGCCOJ zwO4kKm?_2ys)+S-#tAQ!YI1IOkD4u+op0Z(yo(U*ywSyAjNtqKCLo_%oCUJ$Km8~` zjwvPpvg@DQ9Rm6FuhMR>J8Zf@{VB^tim{f~c&nSPSjS4vvpz)7E(COc!sSngjk% zs2enMUwoX5__Nvn;s%3{mjeaijlqWxZWpLd!Xhh+k3RwV{4&L4@$sat5LBI)2cXh5 z3&5$$HOesN;aR{*T%Ls!R_ijSgL(OBNS^i&qW2%n;^xbD7!ZkS?H@O_1RV@NnXp)D z7%$Yq&;Ll|0H{cf5AhSps-u}XJ3(`{E5X&caH|GCH~CZOJyhT$BO#iA!NUD*}h2FPvj1Sgb)@#ajO=9J;w4N1wsu%!teYh zi-gzzP@3$&h=k$&lC!a5D8Ak`(9=a8mE1!pUg8imgvK5y6L~-@Asiv}qvC?zzDsGp z-a<^a48wr(j{VE!iK=GH`|bhC+jqT+X{k2L)N{Mm6*Oa6H{x_OE|^>Gc_2cO{uy6E zJkz=R=EJ$o65fs*G}_kD!D)N^GpL3sI%!YeG&+3K6x(6%>Jsb^n$dSU>NFONVW(FI zz24%#n=N&usYbl<|0qt1KyWywMOP*o15A+iv)=Bf{TpFw``f>C{(;-S)YKTZ|G~)z zZ@-1|7XP#RY5$1_Z@=`XvFu{$jri%z6Z5|8dPSdT1k?{OaTvnVZm;N&iN)KepO}ZY zDMh76JW0U+CM!hSnO(eQoE1Of1N6Ii28}kPy@Ak(DK?a>#C2Pw_*3CG{D?(Hj0?YA zXe<+04dyEPsZKd(#FOhK%5q4UKheo<)_FA(ntnV8NV*L3W60|)W8-(4WM~M>F*xuUjzh~{4gYYF`ID1}V z`ALBs+g{m9&)fD6z3TY;{)so|husTVJ8m@5GMKnji~h2QZ{-`?9A)`*K{SP96?6Vw z?0xZcJo`p@SyNhgTk*23K#vK zf$;bxrLT}tBW^XZq%)~iKyjKV zlcq@tZnhy)UZi+M_{|{JH^OgJ0P4*(nB`x)O8Tx%{)Rt%ppEQ#dY}EQaR_N~d;;aV z9EB#!8N9|yOx-cXmYUdF#YRl5t5`fYk~S%y1F>>`>6hlo;-iRPS~;_C1OcAz2%J`GN`H6?FZQWXn_&aGkLaFFC8_OcO{tV>c{0wWY=c8aUR!P7Z!eXeOb~C5NMQ zR4nd!3GZDp#A&}5-7l!}%gPF~*lyze*Od|8H%_U__osD>>q$+o5I8((|Gg;_SsEc&(rPMr#(yr24>9GSsf^F9)<=g;fQTYNP;uh^8$swMUSq! z$ISOyr}4D!65&)8zdu~`e$GX$eB7pwJh$uFRrk6ca<{wN8B@1|M3354Yx%#9L=#h z&B zVcG`C=%$%-d2RAvq(x-o6EIG95b{6H;YuEi$2EGM_+5XQ&rc2PZm4( zc(D`G88zi(zVz@sgXeahNuE1+Vm_2M6rDA%86HPY7qk)}AEC*+rUGPHxPzZ-wi|C= z{7mcM=e&Cmn!-KZaQ(dlF~hDec0C>(e(Lkt^F~zw>q!2-h;uYNTg^Vysd|jZ)C%G* zE0rTKf&0oLId&U!MkSxlCZdrEh+D_mXV>t))nrlBdgkt^h;aZn`)o#R_PG%3*;C1t z%`kpIhKegwH9&HP9j3+5Rj2j8dH~XkYr7+z%yF92M=#HsiV0YBzC8j6p)8*>U0(Iwo z{yyOELzSrIE%HT;$kmnm?+z72t^~9Gs_sph9oq&_uaCtfPkccYN;RH+{^sS%2tseCNBhOsoX`4k-{e3lrNW#?!3NmKUOyO^OnF3aQmEhcDd`^y@9_i zZeh1E3P~T;9bHoC+?+?@I_KefBX0XnAzow(8KcT&IIqG#qUOl#xJC`fia5H{`bx}Y zuIKn>cOQJE%ezJmB)-t*{*VW9k-yx1FzVR~Stu$VvR9_T^ ziXiL>Qq7)e%4#6$9VMP|A#Z#6gC@**S}|A8g*_75G+ucLE5OXkCcZGe=KMME@!ll= zYH}gpgZ=h*KnJ!^k!sCEP`l$8sC?w~mA_*p34Q9N_qyCaxW)RAFl++Z6>0qr; zP8$n4B-mig>%eE^W3WrBkU`{W7f_Hf4Kk{ceZF6FyRL0`U+kZ50{{Hf(e`OfubpL%**(0KE|DHkuQ)zR<(6|@qOGW>gv2fcbduD7^xwa+X zoU8>j416EPn^lw!y>rPZLY?W>H zFOljiJb=c&$!7oeGqUPNSAz%%+RrA5Zdm!{aH2YFbGm#nnGS zK_UL=6w+4r{+YAPKS1`pws27+pxW@iFbf4jdPL-hG8$ONJmQ$bg=_$E&0Fg1lKK=y zdIia7cMIn!bS*|fG6lm`(067ZjocN?yFi_z0CwJs^oYdLOXygYy7+2y#*p-0?l$2${9@9~me zS)&-ULM~340VF#y&ts2_w?m9^Vv(ETgrZWXxR{!6(RfMA5H~fWqz_q_=xBZm3f)oI z=cLG=!owEFrud**Z7sPq&Y+##Lq_>2?zj#NAeEIoln=~J9WzQ=MkJ{?k!pzazHcV{ zRH~Z6xk#cTCi;&=CsX<6{W+oQ!8?1eN}|D>f-_c>T8=c@Q>`K9U+C*$wy&6DtM3ui z*Qrr%iYq7%+S{`kIRQ_P5Tg6`c8Gc_h^m{Tu;WkV_c841Y9tBzsCqN>?Gb3CL7tCW z=&m<_hMMGHd~Dy%wYl|Ru5Q13j&0tOyp~UBN2gWrU_w=y377PS#qY`Y9T~rP>wC2r zL)4PM>$JERtB6m`chc*GF8k!H#}~*wIA`AEKViF%Bme#4kXWQ2G zovx8REeLShr+@4#>b*yey$y%7H4GKB-WA58e>W=ixmstKB zFgM}pn#CTLnxx0*Ov1_YCTcd280#HQC+gatXdX7P0WtIY9eqQidih?5C?M1{48uo~V`(msHrv9DS_TE^nBfW7Z-WM#6&-7vn2u;?4@k>d zYH)U(RWdei7cB2-Q+|S~mA#YmH53inIy%ec@~Bk+LjPDqC!nv(18#^zuyj>!+I}?( zRCH?(#Q2PuAbs6UE7(MHGg~aJV)h%6Jn8#h7F|gnoNamEeB9Te21BQFCp%_Qo`89Dy#kE6Vx*~l;l3MYG z>0@(mGTNaD)=+V6A(;rZeB*wzmldnmfCam+$GGz-PAmc?#B?vAtO0I&QqyKnU%|Kx zM?@Br*focfUGD<+yl`;B#@Aeb;cm8=U|S5>gIQ<4{21!jca0_K+e}-J$Z4hNY0yeH zx~;i5dS1n~2{%nm;ohp$@l8pFRl|iwto3AVU`(Iu-@PlRP8qb)nkMt*X@j70CE{HJ zMqmVyDcgDzm?Wh9p1~eaa_+^Dfxiy^Hw3?7yqH~ zZygij|IVB`2f+VnX2xLnZ}t8T_}@t8e=z(jn9Y8NdrT@U;lcHKgjXd8&=I}OkH=Oo1QaQOVOons@hF`6*|s-p{(~(u=QVW;t#6& zb3;dE@F(U*1_k{tANu_>$#KxkczCl#gScZYwpy_3WVE%zC?wuuExwCy`bWdA6=}ez zQOmRc3clX79Msf$cT~!NSSB(fxhPiNo4WmcN?MIe)snn1DHOu8^CgY23^f;E2ChiyaZ)`{E)+*cfW`4`>oqKUKuZqyW_@fThS)^Tw z-%yYK9h>OC`dPJj?qavvZPL}zyL-9Vyg+O;cfE5Rd@}mB)Ammkbbm}8`8XX(Vqd4e zs1G$RT0bmJ7op-~VJhm5W47zu-obgxs@l{g@crKAg!ia_^GRxoSvj?0l1*1-Ok-J8 zLD5d9?GB1hdXr)%hGp4V`On0-X%cgTBv!+PSeP^*`EtO6)|oR{g`6uGk@+B z)=6}t6@|Be5%04TnJGI4RO3`eKKEdo8{1LIZN>1=q{J6c(YPlN^9r{nqFeFwgF}vK zG5?3gvhh4z?>rG+l}@v~(mjZ?eM`eud}UB8zM#hMzabm{6Sf_*efF}m#!;WL*WAK&h#%LbAZ}~gTj{*30HhV?@Bym=E~nQTi!VPptI%u{@HRxcD8)c4A=kb z+0vCeTQ)zS*|Ot?{o<%ed4So{Vk~a|zS%OMCAFp{^FMk^`ih0*|A5)D{J5Oia@w)k zK+Iot^nqu~KKjS!l3qR%dOcz*+<46I8)Y&N_YaNBmW|bBz#P+Jg(wCV7}ay@)s0$4 zCV#?A8x+yasHYMT-2s+@$UiRYVfB=l_dAZLKqQ(`JA>PwSPF8ntD5gZmF285Kx9vGeCEaX3dgzwA{a>9WqVkO<{#e@YR%>YDTmc_1 zBHfaP7z@80Vt_6GT;EfAZ+c81#oOnU2KRw*#)r#Gbe$^sq$;7g8z?b6adrkL&YJl) z(tPVbB>LeBr3DDM-BN4+WWvEA(U(ntrbcX2V>A_(NYml_3$LIt@%n;)v7^AV!Xw06n&D_qhZmB zlEdn#Cgk!HVJzCJimb1g!;IhP0g90~OaW|mL>uSgqKb17gDO-vYCztrnaXYo4>{Tf zp)-lrurqY&ud~-2!jSaaYd(f|mIK+FK6a*NmFzW-_N7d*>G~~5?=au3x(gWZV?nC< zXW^^urM>1#u zm%y`*7BJ$sZJYpfQ%r6Y>!2QU79|(T^59*275Q?EIw5y=1A9mDNjbzTcdrc+USa zEp{jT9LS3J?obrX{!_6!$1=O%w4*Lh4$ z7wvNKTmTjLkSB~ee7A%PdKaAV*uT7xYtoBfEg{ywTq2aFMb@l;oS5Yb{E!$wYG0s% zj=%bKb7<}=0>=Uqw|Z0JH$SyB^pj#+(>aNz?u2 z9D2<}jkwj0%`YxrUcF6bz;T4&y|=J{V`D{^;16@7o0=Zs{rcdYgW;c{v#|p+h-N<1 z54ImrmL($YLt%@J`mL*;ZIAlu&ctqipoEc#KIydSv~GPhCh%Q}-MxwXv+KnGStNlP zuXly~(Sm)ay7x zfNy>jcK^vlw8!}O6h0ZAnjU61Y=uM-?Xgt29w!0c5`gCf!V5<1(U+P>2|HFS3_<)- z%bQ4Bk(?#5dZcO0=E1-|+`qX%lM2}eCmE7nCF)HE{W%(;Hb@hndw$o`nalc1?O222*E&i;ZFrC}}fM-)M*{&4x`gf+U3=Sl+ zF<`x!vfs3!SlfvU}YRKsI9Y7{5=7VgT~iodG}^IeNSgK(OT7mWXyA2q3jT{<{H^ zuOdDIKt>tS=zst@{^xr$e!5jcP>%rfgPV+N0e?vt^_YLNqE@g|vqTVJCXC{w4QMc} z#4ozq7)4(K2KlaXyn~{(C;3CtnCc2&vZY0{rR7sv@JWTAJFqd6XbcYSEApBTO?b1U z75l8bblq6W4%=Kz=8WUdDx*TA1=L~FXm6)V2@Bcl#38{{4H>Nb3(eI!QBx(?Yc;Cw zzh=sN6$;2?^?Kt~RL)n)>py=h%`*4FmaCV`KgkgG9%=@3g?LzS7d0Rk<^HCXx7tQeO26xGr^G!mDe-NkX@O!_RZ9do*F2{KB!o(tAlPH0?1iW_KGu zwQ?}~14<6|w^@qQWg|_|>D5I0pM3$$#V66O!zH|^um=BI*a{8w9Mt6h07prhWS8dB z?go?mDz*@qy_c#h$<(!TH`X=eCA}4Q5j2SpH*SXhRn>t%rq)_zLCS6G;`I89&T_af zykt#YAQE1D7VLvqLrO1>2JdsJ$mN=W z!q(-coGg=c@%nlc$L-fLJfe?r86cp-ZaL3dML{=@4Go;^{UNZWc6*ikkxJ^m?42P#jQ8?lPwoz&16ng`GE@Jus~kvk7|BLwgwG-pkiP$W5*{J++Sr{ z7kp~=mCwvz4=3-q`!?JBh@;m<`T)gbYc2$Txwmgb!do0kMmIVuen^*Eua{ssr=$go zu#1rhhPV@(jMdxX5*!py9M^)yTT~Wr*Ptgp+?{x8%gM?j8zlGr&c@{*R75^U8C3}cXZtDC9(J~Gr{$qw^+PV?l2@RnGoBd7rWmh3wI8=^Uu_|6p)1)tB zJU1($f7#{vdA)M!XnHWq_F%Z}04B@q6o$5Ef1wAc57YxLS5uFS)gb-Ez z1<}qE3{2Eu+e{GkJ!3v1aId%(uB$JWO`=>(;@nQ%dznlih7ax&c6qi-&usoMvvG>L zIhpOzITc!~PH=aV%`_BWXMrt9&EICtl&gEtqJxh;tS^4n;&I8ZJ!z$;2@#oRMExbc* zg@hE(^qS26C93`bYnibk5#T&lnE#uRt3rud766{RJhXe>VPtt_H0a z8N;hT;YUVQHm{LdyCxZZqxn3T5AbpUWrx=>n0j#uau%LflF?oDfos=NNuxzUJ;Z10 zNkn&i&FOU#!9yURH_nJsj|GHU9Sx*Genn z^vni*leR z`4Sewd@<5rjSaYm!(6eOl|A*M^*Y#3K$oa3fi1Lf*SDCg@x{o<>9W^&*P6v}FFtUjc34%+=-rq%tCt!4qWy68z&$_IVJr^Fz zDK=EM_5g5mYfsg_xAt89ZB18}Dm2~@*;jRa4@}3vyLV>hB>H$(d&SOkSKN?F?y&Zo zj zrv!XmY=Ih@o0p`9?qH5#U|ro)>)hKd4`VVvIrQoNYzH2R9=G~=wae@Y=4*8jgULLG z2&%7b(zItsOZrji{SBizH@oE`Q`R-i0f_Due+-DOq%`Ad3)wgBp`*ppzPiBdcuH3^ z&agN!vJ8Dswd&cAv@s8I_**7i;1Vy_BPcaTG`C>|3`JXB=*MsG4rs?rL#v*2g0(S9T&|*AT zUMi97spF+O9>Ret##b%mLb!<5_EfwapTgH+*^EP0^@oo%*QFQ&`SJTCL5Kpn=F%J8 z?D*HIjK0c<0tehJp_l?%_k0t3Em5wE; zR&be79n7CyllFoZ8-GH3$6@+@c1g0jAo1&d41Rc@tpcZgJ(XaakxYN;|8n;(;89gq z-*`e22m(&1jHZe>YSidxje;5s>I}@l8JI}C$5*Rq<0V#XQ4)<6F(HX$+#HA&E4E&! zw^FZYy#OjET#|4R;-wn3Dqd<&8m)MP0P1|d-`eM#nMnfD_Ur$9pMRcba?ZYaN`J(}SY zqqf#ud-`)(0Q z09dz8)*Gv&i`K01a&zLK=LZ0bxT)A=T_D+(;Upu?6Ml;^gNsDSn(0~Iy_Z^rWw#KQ zGZEtoal|!Ne~<^T8}(I9Cj*UJcIF~qk=-}+nf7yX3IqJnvpbdif$~iQH9)`0!rWGZ zv)O?zRj^A2Y*5@g5G%kupjzotkk6!e=s?{mkkE`)SYrI9)d6DGOQ|6@a2Rv z5GigFUA9N?!nU$;P6AY%~#FN>;4|kScJ!qTF?L1z&jA)h{&ku8bt#{b=`_s8T{y zDJ4wH98_`55%v0?IFH4G7gTRWC@%fN3Y-Pk9-y1CiTS*Su(WX^My54((b0Ofjm-ke zP+dU=%0|0>?@v->z$q>;;8iNQNH{3Bfb`2r_A`eCP=lW=M2|iu1&n$7ZtW z*_Q@jvMnse6c-Uf-}`NG6e{`L9Vj#~KxmTX19~hH<6w^s<|eprjt;l_i4h7lVq+sl z94RN&I9QYkrVUEj=&@o{RnGgetRt`(h_(kdHrUal7qEiFUB0=E6LLj>;tB60E8@d? z580;ldpKEzd8Bf&jHGC6cmR+bCSEOxln-#v2c=soLj6bfY^Sxdo&Tmi+W@=pzhTeT zwnl&Vf3rQ?p>`WT25pBP6ph4k?5O{p_H5Uz7NBZ-woC26|G(_n=C5KGLAd_6*|Tk3 z*{flWJ=;%n!RGDOo{j3#^}w;ESpVeyncHgc5`>GaVzY*?p5fzb5Hy-R!zVZ4C9nuF zix{&6F-sWJjF@J|z^lz<_&Ul7z^%>r&5VIxo5@=YT(DmCAcClD0Aq6yo5OrQxu_#B8D zY;&9cyW>;h-TnByASMfXd^Ydl_$=Oq>0gC43o7mZo$4T9gCgUTjt$@*&7bUK5G9#LRaoy~X8m`@XLXM~K1F?O z1e3<+dofe%Gd@S0^Pi5-yJ!EG#wQ1w1-qkfGxOZ>xq4#4Zf&>ptzs9ZgB8}Pz~BGQ z_~dP~$LIHbYzULa=OQs<>oY!c&f4Yp*sL~`c6k<>x`{Qkc#+C~I4BEdTQ_OTG_cE9 zm2A6dwx`Lq&rdmN)kIX}gFjp~s)t7ItChvZQgGe;JBV8NyafI2Mru%g3k2C(xg58s^Vg|J}s{dCyjJO z1xr302gki9oJmW*2rT*V!|_MfNYJrJY+$hQq7Y(mB=pM?{7QqdS!Kb-YoU{RQ3bbL z`APPC^mm0uBU^Pu+w$Sjh^A9GiJc@i9QZJ|7`BdX(()twU#*HvndRFY2`bcMFus&( z2Srr|kGgpZ$c+zl7ja{N=panV_T)?e=P@bAlQRX3$5bD};5#N2e2EB*A0!`NBHET@ zIO7FDCzB%pz!rH9Xm1#i0KJNFM3KKqNJ_ zp9W9|tFWCD>C4`+AO1o+4hIW@s|~SP#AuHqRfIVhnG9>qFklr}9v_by;Dz+rjbR7j z9uh|-JvfC2=rIhj=>Qt^zkFI=K!p>2RiAmJIDP-m+Bb_-!D-)N$?e<6Zl5+)8;JIG z14E#hGQqx1V%yN9-t2APps?Z*oMq4r8~ac#eK_EU`;d&U+CLF&ipUO%L5q5e_AFyy z8%OakcKR1|J%?}Gg*fSQ?fK}dxjqCwEoR17~F##dT67j>ZCIYHDAaHn&rrHT{&%v zQPWXzZzc#DBf5rTEU98NC2aEkZz+P#!j(cfiQ0(l>`Fu1Qw`E0u2kH zBcdpspqH+_)8}6Sag*(xD*oTtJ5}t~-sw)*cVSD<{=nWT`FvH*64zB8Z0##jP_8XT zOqLgj1;s1{UrA61eowDw z&e`R<%6+YeAkq}B0wf28i* zyf8?#BgGzU2}+K4r-kn1JZNM{Mf zMS@(y@?{;fezg#4I(4fnlKPmy2W?+=A$H8#zDzdS5P}ati@1_tV)Pl^e(k>s&;+Xy zFyKcWWo782mEWuWk^g4>yRt89&tk7TlDn`BRG^9M=f7fK)=&M? z{))c!pa1XFpOBjO%j81#jbo0ttZ%rq^lxu=-(>05580b#Ox!bjv${|7qj2XJRckRJ zpjNjs;>RgGSG|=pE~YlX^UmsxBYJp8SjBXtk@bInCRzXV2&iqbe>iNsaw07|c&3SJ z#8RrWxae(I*XM|RRM9I2oFhckTA*}(*H=6fz)KQtbN*t!KwJIQszG3w6MrHWNc1fCKj@ab807zGI6^(SSE71ai7)Grt#R#f}Q zYx{p{MRnHJias2S9%GbUy(30V}HSXZ*(id7f4L3jkR^Ww!wNYc=eXCQTum z-$A{#3(x0kr!~fj+F(T(MV*sboB=6TR4XRP$#4a&s0Oe^UlS#0@T%7CA4PES9_7)n zbQoVVF4>Z5-BY4?qAjV85o3#fEvb%YOHVn`ZRz+kbW4wNqBdB^G76iqS*fjDc$jXb z6+fZhCSq5C3w&+;!+2}WxL&qY`N=I*Z(~vJ-`1))12=ufIXW(iIq zjJBFm5G&al%N>H#eNYTKtHq`T^?7iDfFm*NE@5c_TP7nm*S-L4fk?ljj_h86m01@r z@fnC9bB!y+gX*tP(#VeZJ@h>TM%q*VAyN|d^f;6^)VNNbZl7@lkNKo_Qh|;MY8<4gc&De1oI&@q5W=^0f&YbUJ`F2!-23EdlsaYI z#|K)(NaUHZ&Ew{=o`v*u1HV#*uTX2w^sch&=tQN~<9`(4QU@#LG8y+S(3KY3l`;~A zM%k4zX#EV8Leb{iC_MW>&EPz=bwBZ{gGv^%){4(iYp(?P+!OP^X97T$=pZLTI==#c z&n!*9&&+J=qY{4RP{0pznUX@oUs52S%Gkkk5wQR5*6(l;7@yZ@0D1-DBS5oXwvL7A zsu9b4ultN>Ebl!@7}{ywc^(RsXV+~XeBGJo+y19+kE^-2w7)zs&B$06{~*|wc@JUP zJ(6!eG^P7Te9PfmHs6q#)_0g@pMix|bU+tbdYGD#G49>#R2in7r|4l~B)+=g8$C=6 zS{?{du@*e7{qRw#r5M-L0=(EEL4O0vd7ip!2I3S=Z3wDxpv4-xIKA=|uto_z7clng zp#kPu5zQOj@&T0kLwUy!X}8~wbKeSvw0q{}psI+1b`b zbQ)TjSJd)}6gzpy7W-|i`&Kw)OG>eEx>(4wqB8Hapq>5H(2y<8`zcB9;j2oSAa&~S3yxXo}o3%-6jMw=t{@OF+EoqCqx@*8Zk=+z3> zgsL|utD&2%eU2ADy^UNDq$!+RZ#K+>k1!NAZq8t3JCeNFeIdM(iK!) ztUKj;JVZI^e1>7WlA_FZHX{2`X8ViBQBLZu%!c{aa3paM>Xaqmb{vJk1@`qm(3XO& z#9etuka7xy>hligJ78l6A^lAb=A{M?O$|a%F*)+_CD4IZ5u^rr@)pO{?s$kd>G6E&M>6J| zYzjHp6wRAt&#;N^3=6w&p&>1G%_F3)F8KNZ^56hhX3T|oQ*7Lu?BZU;ev9TAL!f~5 zvh^yoaQ&s3YSo>@7LvsA+s6F?!`FBcDl1llrU32W$s0uR3?Yg|D?R2&ey6;BipoS% z0AjK+?X2tC-)oe5<3mBIPw)_wYGt@LO0^)eAC#I6@u${z>kp+4?iZyB1bz-mvE2?1 zLD@1HElx-cLbWbAb#!X*_|zb*H^U6qFh%KJ?%39^V(0q6t)*YNOKWE&>(1Z&9KW?$zjs;*!@TK!wCI zfU6c;GmQ+`l8}O6w~VVtxfJBX2AGBnrQlLH*DJcP;fRAeRom3*?XNXGtG1dTGo_op znIJl=?bw;tuMykSoh!xf(rN%8dSH-V$g4pW4hfTGs`rA9B@Y?CpvB)d7^Lqlj1e_L zu=rbJO&Tu=&#@F0S%dSwj~A=etOy;Lo7ap;_LGUx*rRzhct-p$N0ud&f?FtvRlU{P zq0dp_so#$5#p*9$0DzUJp)l%;?K63yh<9^==6v=;=~BtU#Owb)kC);1(Q`~GnkII$RWg=@o|)ggKf7we5GHr zRxZ+Rfk7?X1uH>1b4hiGVifJTW;P8j%V@Myk<|NmGY=KZB6TZa;JwB(`^Vrr2(KD6 z*HEXzIkcz#8F`;dFFd&11%aqZVc&VV)&U27kK7DQ_0dh&u5F4^9Cmr;6ba*!BDFq_ z-nu*u`y<5`S$paRB4Ep_J+r^Wmtm28glEnNY=f3m|M=^4jO*pFQoJ0dHkbRB=SyQZ zS=mS^ZurboKTjI0FC{kA0>KE9v5QCX1bMDpBMXe!^S0l|FQiJ`4-0NxgSOWq1!nGW zGqz^N)lt8NyVA3-`5FEnaoyQbW$~+5d_{bP#v|^<;Bi|iW*p=N2^JPEP^NV43*lni zn{_f|5OMGKW96|;Kep&cmwtSxAMfbL>-zDsezfx8PzjmF1u~_z7LuOVP0n&au|3Q( z>hmo2&JQm)Jp+v8wzTIo$apAwuap|iOe&x{RtAm`zf^xM$decPSTiIHoUpx?6-w9^ z;`?>xcI$t>OeeFd85p+VTDD=a+lCCc4LD+!Hf(`M@?9Myye?^pgM`%*PPE}^3EOS> zqt4uJz3~NyWUlPoXnpY8?LaB>uDlWdhrxmud~iOcLz*k3RFe5nx3huhXOIJ8Mna~2Nm+@I~{ssT&1)$7XgxT z1|a8yjyB&4_*TNVd{G=GD~-#Y<=X7&)@9dzA74hYU@iF^BaK`YltY}Lry=HGKHpFr z%FMhpoF5AT3;7*-faiX2z;LqFo$%-Rj%2p}#Hu)tt$XEd6)~m;C2(x)gQ;9TF$M=v zDH2UNPf0c6_X!?A$vfFU!D>u@nX1`x3XBE8cH;E^%0I#Vm+z5(f<5iuCI8#{x9YMz z>z`{s{PQQk>yC!Dg4V=@_9pCy;lC|dV)%n{P+Zh;ZjO7W93%a! zehx-egm#4!sPs7oG!euD;(`+2uSIg-si3|LN z&M4U$E=U)!jKC#|(sXbsx~#aMQPT z>=IsY!9=(pc&&tZQGa0RRTMNPAm*umgNHQ&%fIH)Y0w4Ig0iffwh$epp(#ek&AA=Ht!qggd}k308L> zjeJ$d!lz8O3I zE_x1%KOH8SIOT4uZ+41SWjXy@zgZrqFS7k3T9d_{9NzwAtk z6OWQfaReWFQhfV?Jt-!9pH61St6p<557wD?9O-7>VnMog|6 zYoAAnQV>dq5eHFC?>4(ezQp9-n+H!l9X?^4S=11B0Iob0fcI+^W51X)`W^0r4DkmrGY@_oaKp}sylxyJz8+PM$3AQ~;S!(?j;0)I{lV7x z-=&M70FkyKrGk&1@3l(+?1Zk(p-g0Y_mHT9H%+`b&H;WS4P~36MO)|~;9OsC2LaNM z%wm<7hf|Pf(f9bOw&0AY4c6vw^@kDfT5v`nJH4&Bq4|1<;Zd*JLe!u@wIN2VCCQaT zf57Aq<-MH*l*&k4{{~kYn6TM9>Jsq(Ah%Ez=shO8o<)Yj(87uS?3tK}ppb?;d?aVx zmuq&$92$Yt28#e(Zta8CXo>x;w0t*<7g=dd;PK!&t3piSv4Jl3Sr-l@ap7*7#QKdR z1TWk8(0I9FvyGRJ;37F>q@Mv`*E5^p4vT{i2Qc~xSV$1tGGHK@8(bQYc?P<;$qJwJ zEolztTw@IZ=O^I$B3`uULr>jY5Df9F27gM9r?XOGVg)Gxmb&VwnK_7_&LCv#up%Fd z`EqyY+$&@Yu?u4^$w;%TiVxW)C_o(z*w^tNaA z^%y2r;(7LrOROIQoeWi6#*N-%-Fl-(7AV=hm|SI@wBvJqjFGW|s~Ajl1A>_r&$9ue z7k@>@D}mFyoWiz?h=l%*X4$w6pnr(4?H}S4`iI~(6{+qY&Uug2{H$#1VB;tQWOFD; z`(ES<@Of9$r&pA)?5R6>_pHVY%i(@l<#jzVYF<*fwhV201jGk{f2u8HLN3KX1 z+GW(W6j;Ce3SJgRZ^eZqo_Ulkag|6u?+nYZ=iBEB@T34h6`-Di$>zu{*gA<^Ka}?q zP*Ylq9!qIHB(OZOIwtA;=%jal()&?K??)!R=iBc_YzW;R&c(4lIS9aHsMQ)Y(xJ+X zD^%bXfl(vSsPP4|zSR|`K@A>~9SB$>MVn^+vwKkRXB7(|6yTb)vY$f zT;Ii0XNN$nQh|Vrqu7sQe8IymF2tw7{4c@6PR3DNvL(*5>+Z7$UYv93i)t}UA*@qA zSj30TiSSU!!MD!|XXYJhpVb}Wp4A=fzWL@YL@s1s?X1sAb)M zGz(C%&CI&jelG!W?TmXH^PouuQ23CaN_fIwcZG9K(g)uW=J!gEFjjGZQfy=#&kfrw?N3tYPf53m(r~3Gj473fZ)+B@L+L zsox-#HnNPFRV$4Qqpqx3`W5goJ0;7d>owC?IKz(>b9 z;28$+giARDfKG8~-1`CgLg3VD?ia9mrWv(|V$ZbWf&MRCCreq0b#Iv6JSWl1ePv9& zCv_(JwGaDcD02}p0@Gvt-!z3Mo@>F3*5|+IVwo$um5-U;XWB6f>P}gMha7M{$S^L3 z#7(H$6WL%xov;Xz;?UteH~?8i2Oxv32O!ndr(5s2yrWU{mGF+0KSiew&^7y=nukdE zCSB`ksCBPCwL&ho$(pjeiZhRI?jC^KEwKUs?%*gv7*hQm{6K#%ZIk|1;UWD!hvDA+ zEkR`O{yq&EJo(OAurIh~M zi4D#!`vX?Rh=Cxw_5<1!lKl&GU5wpxKmF@$NJO)LJ-x!YH>ajoFGz%)_JLl!ZT$)f zy}-Oj=>-_>GC3O=jAhbi{n4!_^>Qb)UF)YKe}$VrpQWYTy?x8EKTALO&h55@?@Y8` z#`B)kaA&V@?!Bq$y~EjmNKLQ4Z}(yA{?zo|;nIgv)3cYPhAW;*4L9}*FMK*ReQ8qI z8IPp-aem8g@o8|EaYq6l39r&#;cTe7IcUZ7{9fV3y~5SdI84b8<;vZK7bm6n)Bdq^ zwy~@E?c^8yd}-wF@pD({z43FlhpKuqf^66dxyuSrg!!VFT^zo$^Bm%O${&ZNpnwu z2(QIS>CX5j;WI5Zc8L!xZ^4=?<$JlQ;r3qP&IPIXS>a2~-#c7-NNW1xV|E`l3VNlF z*?qY2q}25MXd>JXJi6+B03M5fktk32^i=IW+%_zs&>Cy5)W<*7^4N7|;t%jf^ z8ylm6+@ICWJT51#3itO#k1Js^Ja2ET92och*2`UEB8z7MuaPR?#TDF=L8y6LzJW_K zZps`@`{ej06*?~Wux4<%!4)`gNUQ4!RGtLO-G-Z(8}gB(?Akofo_!o7u+ifT*azVw zaD5r{gx<4Tjf%S0+Bsp+4+*hk>>SZMW5YXD`K3s+zm5a90tILWDOca zAq)5#=^8+I9F+l_uHpa#TUqY8XQ7TJ_@~5!n)USc=lwO~sOt^5O;*vdN$|`8JjEqI zH8?4KiPeRD&igTb|B*k1TX5!y`wI7g&WrWWbsBYH)@kgNRE+4_;ghq)qGLdU`w7-y`%%4xfK3?k6GcE|p*do^Gs6ABhUfHk zMmex@leI65@zl#=t!3L~Kxi;Zpt~N~^p97jrFuJo2nl+OL4|vlw}_P_w(?nz!Pw93-RkwacV+C| zFdY9(XZLpC21aymQueX{n{qERsZJuSs*AZy-dDSc?Sb>JNTdUz|ijoQ($iO2-0PV6aWlq|pCNdu=z*{m@fR`@S;`)MF z1^5-R^fp1B*b)biG={;%`33o&zD;?Uv;g#jpWj;m1^>hq#F!o@C)G2cZ{XnA;awnN z#HS#XFlfwzStfSrSK%C~scWu)QDd*T$-r_5uK6C@&Kl8C33E}pymu#t}W?~^Xyt5Vd1aM<%5SKJW{$DHUxHuaHVTjFzWQd}ApLRYwB}cUF%CbGnk~(}IW5uL$`fq=B@(&ZkQ!kf zR;R1PfcGhcn~^&VHBYE|uP%iOS8%ba+z;u*k3L;i^A;i6I!tO;^QsxhwF4Cl46y^H z415oF@EGiQ0!r6_87fIOP?r8d+ zE@4~CHmEa0pN6f7#$=(!!-r4eAzxPW(%68c2Icf=&~}iOT{Y-kNlP^7WeF!5^rD3A z29Z7i8tvBmYjlJ7ZL}m?Kjh15o-iIs4HDKvw4!lzClIQTdisY@RDUDr=t7T^aH2s+ zOW1DEK{|80b-LXkej5$iq95{QHLrssmDHfk45u{cO_|gEH|Tji-`xg1BH=`XelKCW zLGyIxcI(B}8bbUw8q}#D@?|w|2^)~qpk{_s8Z=Sr>Ayio>2J6V+F!zn2JIzbyFuT{ zhkRMhDlybeAnNbahj3NCJs)wuAvw?2=5X29Hvs<~K6&xJQ!Y4s z7ryFCwB8DzpyCpQ-pVYjv?#eua)a@;KL1Wk$~S7g4y?ju++ygZnEvVEYUYJ3@aai^ zHa#`7_6cB71Wk=W7#Ym2S=tO_ORL=9P&G@5>Bya^Qn4uXSquONy`J^!a~*2}OpNqJUbyPjQ~!7L5Z8>+ zX+Lf{#om*OcLN=p3f$!I3T<_Zarr~k-yT8RBSo)VcT^M@r(O}pE-mvGjECCa5RnMA0=@X4I*1F}glDqE2N^Fp9m|IpPma=@a@O+Mmm#@KC7zxwH$KY_g7T;b>wcT`i9!bnDmOjnsrSx92HYbAb~$ z)@s3$d2xmiLbUDO0eItg_I9mj)&WC-PV%7un<#$M_t0NS_ysa#TZF3?RocY;*k59X zpxz(yS8^7*JNaL^AA7g{Q=Xv=tpE1>e9zjm3JA0Z?dj+I3cQAZh@PU9egr9q-qOg%)!aFTOTc958AQySSxcm))K!$}|xM(O?JoaEu!xZ!^2=4$mkd2sXF)~HWGxF4cvDi>YUs1;gRow%K468GI zA>0t7T0{Qka8buihegWQMN}PEE~;LK{VRi}k#3X^FmSE8c_ujbuJo!cxZx{bU*Q^x zJ)I{jEl3^~k#rc3#B*R@Sd0tKgDS>vz(^}MqyqR(i~oyIQR_{|N6OnHs@C~N(7(kz zJzW%-9D6=v?EZ#l(*EuTKaZH$&Rw?O4wxuT%E1<<05{vHY-@G#POz3!bB$OqpP#{k zAbjp=#@Ond8Dr5N=s7V%jLJ{ks80qOVdn%DoRFG~-}oHf3_$E+n@|IS7q6|0*vSU(>xm0(l7dg7KH_{M=r!W5J?# zJ@xmZv|8n#Lzuvb)KGKCu;|Z>=rA&d8?goAKO(HY=0}i$yp`df!|!sn3PM#EZuIIR z3@aV2#%u|xiDMexsm3)QcLulh0NY1}8=9*J2UW9wRlL1B8%|1se!T0{ZEpoVPqY`k z^BRlA-OQcM|L?Ij`i3Xxx#iFGJvZOgu

&EXxXWt*jF7soQ63LdPq*l) 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%0D8#+AlZ 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

rVxrIDJ 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⪼#fr1t6T-(cY?DN|0JD@IFi<@7=DH#ifEQYhnG({v#6}=SkB_%9V!{pY)j-wVbOyT$il9pkh zv`d7;=1!A^#m`otGrYSmQ=FBL1!!}L=oCyNX>%DD zS37qm3ex)mWFao9-HRO|N`%VjnewF&p^lI(B2yo!D@4ytZ1#nS!&s{o31O`!Rrr6QwH7`;kBfqc)+6I)2ZIKCi` z(sw28u6y2zMy{}848hUL20og~vXwsvnE6YNJ95So8GRyH$DWY)We$_1th1`5qdvXN zId45IX_{G|?r2^)Ue4OAG1jxz5bFsO)|l3?9)7LuNyBNwZjAi7$YJpeo9!Agg1p~q zxSb7c*Mtw-Y=_?nr7YMCNBy$g`8vW(Dz(gJ<(UcR%(CL&3{iz8VIeS+m4`#ts8x|7!@t$y9a+f)nq<%RBcr*V3)9aDp5W+Ee#))2t|D zIA;DDYF}XCgxs$V3fxQG_cc)C3-$JRHT(h6I-F(qePW;yP<;gX81E#Z}kZj`;da`6*M}1qT z{5W35!@RvIB{WxZ=059?S4RPP!@Zp&U!KBey@cjmkWyl6qqrj|wl?3$Mvson_UmA# zPm|?pGLv?bY&UF4sxPo+CKS3!atX(#lNS?=9oN#nG{}q9a_8HY3*53PsTNPFR2RqU zYISMs%zTz8$XqT2$wf6Zu}6oYWL1!H*|tx{A-PqPmL(gGQ`AGu-qp^si$-TdM>5&w z>^7T}Y@;ZLPu23(N10`Ir#WjVC6{tT7=`UaD2`LePL5)f$!Fmmu!)_X(BXTrhLMbh z$1u^;3dQQ>b1P9f=W2n7ljip3m7vFDVuXnfiIShK_GW|F)R|2_`RYXEcL@Kej17t6 z+gv&KT~%2qTC}}nKcg}7RBdN6dECQQh0Cr5>$}=d>)g+%7(voHv4UmY-xB1XWH{t3NID zdrA0;Gd@eEXUKa&?Qb(iB}6(#NvAs8+ASl^PkB@&FdQPehsv1>lpi+E?Iq2Xd+l7^ zAe2hko1-J?B5r>P7&hd4mrx9sF*#uoaTX(>iX@CYkD;KooxecWjcM$Vt=2(?(c7k7 zdt}Xs`}O_Yh#^5hgv_?!1a)ri+5Jsv^;|+kfyXzP#Z#evSK3{#Zw~mMO-0hPt^dG}N@ENd_eMQY0Rd?|u@6tbeMk%z8c24MY zQYdFPO|5T8CMI<)N%C2b;B=Dx?eUn0{p|cWt~uo{0|nX0-34;GDf^UzJ67b=4fehy zuhT5E*Pn#9r_S*n`BgYL%ya@dZ)J<4e&wFI!owu@riD%xBbpne$Jlj4-ew8823d$V`$8VLo<8YGGvoMQCj8Ce-6c!y}8(7N?PdtiDHu$x?`evM#GV`5|){U zm@CVR*auORO@@Bn;lyO$QPGSkVHmWUOB+UYiHh$0pQa*6ViD7%3!QH+s>Tw%|3KUdj;v7KeU z@Yv36$2pepeVZYU+__*Mj+7nLH1ZbN<5@YA8x~7up#6R2F!J051(^oxtjN)>s8@;T%M4Wpzl$Ul=mxs!)^3C)nk z;~G=rcvWjV0G>AyNUd2ZEAEnJZ0xp1 z&E4C-QEDUUO&&z-_OmZpu;&iCn%mOz+NagGG-bLgi)CZ&>;ST7j=I|BB#YY?CtH@T zwg&gxj$wCK%2wOi`P2N-Ade)#uBCCyZPttBX1C76qga4dDO#1TjKiT69m4w`#n?As zklc>i5ZRQHCR>}KBrIy}#O=OybtXIIH!9_veBgkh_pNq!vBbI3xhvh^UVi5Hb?k0f z{#PPHC>0+x@hRhXxs>0DEW}6A!%}`Iayg%glvkvOZeVg(Gd#LrEfLa9wr`mWrO$N? z1%EsL<1)_>7vQW~2csFz(l(#Q?#X4*#8J$qDWFfR%lbSs%F+-=aO9Sc98+g3ms{pT z2@532FSwDa^2v!c*CAi7<~~dva>-quM{#Fl?S;KS-B9Ypm>i#RnX3%^yN~#*gi!>s zhjR|wxoCDp{qk{>S*y?fe6HN*c(~l-f4J<^OPVPR8zO0zaW~40F21i*-^P+~z>t*7 z{7QC31i7N7%_c9gx{bvwZk@Zr{vKXd7tT++KRvgiy`!aZUi&24sgC*_+mNfyvSjY! zA9l+=?i0a9Y8%ESXV9I+CB7v?1*m2W;>b`KI9i4}9kV7+D%GHQEQ+@#EY_?k!v&OV z$Bz0`D@8l210{X0q`E5KdDUX1_9aw_d6Qr(JTXOOM+q7z-M@em>MSc&iQMwhL4_P~ zl!D61x#w<$PpDiyk%P_vVc|>pR3j<>R=(Npfem@{ps%pACCk=h*w`~4<<*|t0B5&i zGM)CVdd}5fDm~>~qO-r!*2bj{_LEDAmD}S|$%@b4p^U>ba`=_8jqLGdE_w=A#Mwe+ z8z_F1Xfdi(6cD41k|W0M#KuoaLGp0+YIS_SvketsuO?TqkIuYYBiSMfMadQun0$}2 zRF0(Bu?h$aF~ksK-Z*DZ-*7oI4^V$=68!2P#RFq$|vTvQrsFTq@ zlrjB`SW6k1&g8JjiLrxm$Z`tpW-Og?$WF8p8RrgkhQZ|i*k`ykj@tb=WHUtVge;Be z8c2TV4#`q94c#qS8q?uUekomYe->cKNh)SXWvN0+8-@{kIA^Bv?v)x+g!0xX*f3ChtPl!_A{&!-G@+2u&WCT~xzau%87ugOXIji=n-uJ|b(9qk=6 z*#f~gNhI;qmiBsge^1WO%8riuRq~nK`!lcICd~PnA>p$9WCz{aaZSF>ZCd|%v*Nk8 z8-ta?46!_>=G@K`c-GvRYN=n9_qe@lNlQ|}*w$6?yt*x|ci4>A>q{eF)3J&jBh5)(MyE+fuLuE<2=hkcCG zzCO&Ye!OS1s+!a8quHrsTXyXypX675{?i=dt~7ONFgecqNnIV>%Z5kP+aJZ0+Bq*W z3Oc{@Q{g;cn3<)OkuwSfWo4eqy4bT{=4nP)=9&FP-I*+OWV5v&d*@#BUrYN-9@&w+ zr*@`fMC7L_^G^O{Z|KkFBp=%wmi@=B9hcR&wIy3J0&=Zrb9Nr)r!4SXnKb8ph`P?p ze0?*|RSMhrCL`q}#DCr?geYHF&i|c%M;|Ny9w810JgaLe7o&MrzBohoHqV4ULi8-k zJiD^FT&&bah{0nr&z|SmOKXh~>l~GN_U7_(F-Y9i-^x6jv$9-VZjKP29-VnMctW`t zuttdf0KZMXQ!eg<-`N4W2|PhEKcUU)^xSIyb%> z9^rcx(6j5`mpb%y_>}y&ryG8`%=!JH z^hy4Wa_RPS!=v5sWH)@k4L5Y-O>o1b-0(Cvyu}TlcSD;w|Lb$*TQt@Gdv(cSG}dhrYrM z&v3(++;B{X^S;9kA92I4-LTx#qtl^#&kZM}o!>of_!l>v)8#xr-wj`M!*SF<^55BR zxY`Y0bN%USH!T0QLwArH9_@ygyWt<)aP#9Fx?|n&5;y#V8;)pk-cNJG^WE@MH=NMw zyidE~J#J{WInU>~;pJ}lk{cf4rr%Bs{~JjiD*vrs;e=1P;h>wof4aY~cEgL^u-grn zyWu#O&zEkzI`{d8ZdmSy6>fNh8{XuGwi5jBC#xJi9&$tPc{%mE{P&nE=Pozg(0#7E zp-2Ck8~>kf_=ZdW2lw~WZul4X`9Iz8S~vW}4TVSNhBvs+@9^Hc0-tu}zvzZk zc#|8R>xOM^IKvIcx#4Ix{KS>l=*k)6{$9roy>u>ffA8&v3*7JqH@wmfd))90H$1@& zJKS)F8`im@$Nv&n{vX`%+?;gZ=lcB}Zuo0A^x|7$A{R=sUoxF=&bv&ioGRCN3^B1b z?Tm@t7ZpcV&FgAzVi!i0(0R)iG%pUX4zChIj-&T(Y-te!t`jS&xPx%Y%7#RBa;5X> z54q$oKZBSv1In%0@*9hj=T98du&lnLHr-L*%vYHwJD1*PO?XbuoCrTkhy`L|GrSv< zOSyg(3e?#0^Il5@#72_8J+6roFhTOqr}6}dBWwxz z1X9G>QbJfBm$=yo2b3Ndl8dehg$Sh>J}28#%E&YEaC`DRF|oe0vw3M-LTON$9Bxw@ zzEqXVRLy8#+T5V>j^Qex@^CeG;jdsyuB|;w5ara_ty{{n4?Z$VrlUHWx0^S98Qvl? ztsdFFP>s#uUsD$DLKz2Ji*&a z4y?y6%d%~5`j25(@v{1KzGunFZYhYWY^JSc9xGeV(cw~DHFuO0v)Zd$Q!SC2901)| z1)Z0kS+*7m0$Y!xqr8bUjF4L7yIPJp#!DUYsXP@#wXH)wfmC5LDIq5-efA}7u9WrN zNSnKyH&+|6Q~?`C@*l1;Ph-E=xY}`cH(+-uaV}Gi&Yl4~S*`xXQoiM!23hP6_1I8q zFN3B)Rl9#Ene8d|?Nz=Oc5h&2S30>eQOzyJ%jj%02Kpne=ZsZScv2~8E$!U9uOy-- zv%4K)U73Ozk}gD$*phm_vC+MlvcB`UgriPPdwWZ694=k7@AHsU_O4A+T63QKsp9U@ zI#*)bT^zB#)JGM=OP145lN3%g6=UqPfyXD3iasH^ooua7Eo<-KSc1aV@+`GjPjU;T z^HkeSo`q;mCqfCO`^e6o*j`NJbFpzKsma>9Tn}LTne7QG)64x-^6V1zT4yrNXR#g9 z=qTUY1)zI8_f4yLwM)M$B6?(<}^8zbp9J5PH1Uf;`F+= zwd9fW`mUwR(zVHz4arnm9#ONG_~k)8WSpl@tX;GO|F`!Lc(0@xzbD_cB-@tqoxY@8 zLi1mGZPA62qP;6!+ul^mM^~06^C;n+@!7^ZOHVWJ?#CCXdpKKRX=ShQgut2x+0(BP5@bf~jb3XAq+v)HrGP^#2vo zlWBSJVbWKiU}W3>r`fv$WjXilUNE9(@yX=p?9Qf@zDNpD)IiM9*(-L-jEPMxU7gE{ zkL`A5$@5Kf^o}V$A?v#MS?$z?-8nfELzb64Vpl9>SL^YG+J#OskY(!>;?Hlh8;~J# z_{5mlOj*jfhm%zWOV>=Pf$V7`yq+!Rc0(e5Zu^^zT%_IeGTfsZO~YUwZ^IEbD6%C+_EETI}*FOB|gn`!3frgXJI=2d^0X zmzYDAEvJ-3t1Rz!Nupu5ONgvZ685_rrC#~($eFRExvIG_;kvLN&%UQdynvk!Po|wV z*Ch#3PO=?VGHz~7$t#KBc#S@>zGX%Is?OTBb~*W#kmoHMmZxiJJ=|8!-cl`F%+D!# zGA~_{#N^5IYiBO8>*{pE{Vt>3U%<%0H?mC_%QG2D=NNDQZGUr0j5jCJjt(!=U1Zze zxvaTqXnZSOWo-rTbZpwdpfNh(bJ=!I;z;9yCT=HAdwC?QhpGh=oZ6<(m`J%IPl_#? z(ySZ}c5~CtxsTDTn$KVr%gR0!MQ+}tPi$yO)_3^v3$~VlW>)MZ{kQ1SS9Eh_x9RJZ zRMKT6P_`UB$a~(ao~GkY5WbI_)keTI(kI=!swfaoeJ`tcmh= z!XfasPmQbClFy8@GC9TP4CD1{hL%&O%bLrxOe|Smje3DOQ4U6Zv&M>?l|fz`e65p1 zONY!VB8LnohlapADu-^TBu{N_XCsW$5-gVW^!(c9cG)eF)d%;7%QoXl>R)N0sQP!@ zf(pNqs1!5jE|^p^c0z?SCfZNbrn>mFCIcSEbG5ZJAGLfEPad96C&i(nHQ6e^SIH>S zdFPLtY8%*dD8vqV&pE%F?r2}dDnsq0l`9$BF~R8#wuIOadLG-`hNjiGHMS%>#tU(X zl+z&jmGgeiyveKD>RX!|Ce?SQ#liNw)|3#3$-fv02Zs*1zYlo$Bup?X%RdA96Q&~mgx2R1rc}R z(cEmWCp%{6cyq1IBol>wkBprgRwZloO^(y$fEsQhyPn>x1#y=5qaV zb^h`1so&*KeYKkUt?`{Zerrqp&4$MNUHHGJzl?SLH&=J+ukQNy)LXOP^|zhBr~dru ze@UNhu9K;+lmARj`oCSNUmO0>l~Q+2mHK+x_KwEKLh4K4jz3(k)LWAJcUS7oH$H*< zmio|aOT8tXskbEc7X9h!cD4P@_-0p^>)%~%>92-dt{zug>WRO({v&;+KIyssS67?y z#i^^$)t35aYb5`@>$jBL`ES23S?oIIYD<5XcDV*zDZDqe!}WipzSd6oU=cfKVEcLCW9g9+LWwARQxXRpr?&<1o zbN#DJe$1ynqKuyn9XtQM-Bs?g-i4`;%k(?f^*_3P`*UZzvB3C;X8d7Z>LWJwi=?*S z|26f~=(p70x|aHQ|E;y_U-!CP|JisSratD2!Pkn2e%e9y^{^;1* z^LzJi-L0u_YBhdN{MKdtNA-TQNL%W+FN_ae<7eH@o}GV7{idBj=0ow+T~Z(Osh_&3 zLB@OMZ)xF5{VX?bV!V;5-$w-f+fG+&=kI^{`=5XL_uo7Il6vwlU8%onE%hIE{LAiz ze_8k!^HT(Cr2bi_e#a6Q_zdH>Fr9e&&el#Rp8Co3`yaT#ZeaYw{_{Ule+Td1aVhn2 zl>W|Y^OK6}Ke_*Ed=Rpq^Dfu_>0P(8bua&1;Bxuh=66l=2mW8*Kkw}R>)!M~t;@cR zJ5wKnmb;VnUsJyUx8{#7<2PGVe}(Y&U8&D2sZT1mT&q$)8@hLl=^no zKX&|M_fGR}sqB)GHFf>*w-q~f82>rC)b|beHg@k`)!Lc*xxaJOAE~SNbf>-!O=au; z_~YOH(YeO@C!czwx>BDd?-*qB?_J&hXx;rU9jSkKJ6x_^-hcXYwed&2sZU#}|0Bnr z#+6TH{Y!`WDRBpU4o-caV(J~^a&62?y=AtzGd0b)VEVt6wiakOZsmaOf3(p6aHz3D}qw<_XJa+>;Ey* ze@_4NHvYdEEB;Kq0Xq$q`q`WM{$=AQi&tOSz-aoHP zeIho#5!3Zw{E;&m-@O{qWUH0H>2gKIrJ*JLrXv5~kfcmm&vowyyA6KA_C^{+_uOuOaexr-&8 zuGB9o(obNu$CdhJ49q#`>P$O)b}30WBvSRbQvWhd&B0IhSjpkkuP97rsC`JwbU#X| zK9C|tPy9Fp>PT9duYIngkoTpPcs+((zw3C~$@66DS8if*zr_sS?>a@?Y0HUoz;y=k z!PKvOjHmEwl3~|XE5Yiz>l&If z>KaZveBMx!n~+E~lKOY5aZ~x^J=chpP<30I-huRii|V^+l6rBEre5Uhec~QkPMl+| zM}&`APM(ihGVXd}C0IRkJtcF-p_3A+8;!f3E6EE;q?&NOgw%X;(lucvRK3!qZ(Xk; z<@$|9Qit2^o=iJ@zEhI-kVrL^`idp>KQdto60AOI(rMQxNU8qf`V1r`((|XS#OucD zt2X_HQmkiO-w{d4)MR7c3`(i~0VLZkiJ^ZI!rd=}rsj(u9#FotGG7C3KjeY560f<) z1>N~+C(n?(5S|NK%-9rkhlz_=PMlG9DdGutH0|(N!IGpqW+ha`)2XpDVR2K}5I4ti z;;ePgCA`*h@|?$#I`@1l!D^v<0h-g`u1h<7E>e=kkVsYUUIM9c{|5I8cfFNRwN#rf zgLIXf>g8!-&cv@PttZTEwdKUw=w3s3qvhnemL*N@bykAa2KRb0rwKad-X`}(CD{at zRL$)XPY8Dh(loWf{GtS24;eYQ zBbF0qpZh4`eU_8wF_!eZk6Q^=C*3E=oPOw-+xy+8l;kudQVqDzKx#fY=pL{Vs?KWC z3+{7}a(&(+Vk$o`!jpnrf<&qz_hm>$ZwL~su4vL>_f<%#zV5yT#GE_o9<~yyZfMh+ zD8+ijeG3sW`JQ_OQm${?k~@ezaC3LpqQ(xlXEg2bd0$B$LL$|e`w^sK(ikLIJ=Ub- z?kA8^{mlIoh?qML30BXw=?j!%J>hmUovwnC$`O?aK4S4*J2hvKs<{}sL&cuZ=$Lz(JR6l{6C_eKdp1LAKH1`Fwi2qgXwp{C zR!F(tW)Wj*ucsyL@VQ+{c0eLkyQd9OF{vFAtafSAPS0*gsovx10AkKP=;^c)s=Bmk zH%hVY@$5xJPVRy9u!rh>wq!pc+#N_$a|3=oWIbhOM=U4KKF?9Y`z$BVV=U?S9Jdmz zPI^v|IsMQv_x5{EDamO_q#E#?fz*6*&@*5qRGrnN7d+=6<@&ru#8iG>geL{L1c_8b zp39Jm-Vh{MUD2e&o~w{jecf{nh&gxEGi)VP-O#2tQHu45=N2Mj@;%Q8q+H*&C3g^c z;NkABMU5RU?`YcL^S+WighZ+_&m&01q%laadaOyuJx?H|`kCh`5HWWg60DwU(-$bk zdcyM(5ixnvGXW{ruWZO$&uc_f_XeoB#qFK65~|*5)AuOFddl+w5jlAZrBr{kA=92u zh;aAC^BGaOXBtwkm+G&!&3L{ODmEF@X9(f$2cp?tObz#wQPux48^#~|c~e{A z)kB=ma^ehl{e%ZBC(m4#1ikrIf>p>{Nah5gW8Nj`4J%0m5~-rzQb^4w6W*wmP*tHx zlinDlT*oaUrt-4}o)lybBvRFS=RzuawUA&nPm|Vp=R->MLhk|~=G+Evot03vNSiK3 zDc1GgC5VX0E4=lPa=p}+EJI|Km%HT_6+8I35}p=hH6&6sde=ZIdX11^wN{fhdDlTo z^#<>HAYyJ4Bv@_KrkhZTb+dOfB4Tojw;58dx7d(Y?^Z-qw+*PdrPteHB~)$KraMrI zb-T9>5jnXXrBv^-A)Vgch;X;Z+kvRqbI{ufDc4=Lq?-`xdc1oH#hZE%IqcPwp_J+?He}d)6%p>P zd#@oX_KbRmA?5mpExAbubtB$egvw3#yd#LH?zSVnL+Asq>hD5B?lhIxH)=6M-A7vT zhbYB*%=-ut*&jnG)sJn+xc3Pn+&%L?MO5w?M=90MZOIElsGIPpYL zt@kydI{yYW@K!th4*J=?Nuu97xGC=kLdA4r#uOpkeRQDH-cN+8{)_iBY2dxngmCxO zk$z*8`x)4uwORP{eHHhwA%UGmFlncwv1Gfq$X)lj~)GG7BeKjeY560f<) z1%3HxC(n?t5S|NK%$ObYg^7z;PMlF+DdGuVH0|(N!IGpeW+ha`)2XpDVR2K}5I4ti z;;i+}CA`*h@|?$#I^TRN!D^vz0h-g`t4lk4E>e=kkVsYUTLP(Z{|4U*U%i!3wN#rf zgLIXT>g8!-&cv@PttZTEwdKUw=vza0qvhnemL*NTbykAa2H$!zrwKad-X`BhCD{at zRL#E4keW}n_?oSRsx6wd)wdN=uD4mlnA+=WNjrRQSCSo&NY(CZgH%jvhXku#nzYlm z8&azG_&R`?a}WADt%RyBZQ6}etb2TW5s{O7AU*7(dY>)XPY8Dh($w65Uk_PNnb{G` ziL=jll<+>w$@3UX`hCZ(1gn$26J$<5bj-c|zEeta8WO1nd}kmvpB(fJSP4~UHR%Q4 zIY_xaZxJz-pBLdtK`uce)sXKpq@p(j307A$>9FrAq*Pz`T?1my9rX=c2~{_==}nYk zJ>t8Ch?soOHv%cww{6KCL>~CKyK7NnhbwC|?eKYDNghHX)tK)Qq+-$-Bv?Jxq~pFP zkW&53_Y{bjI}Qm}&$a0blwv*Mdx?mcJn5T&lDBC2}>)ZF6EnzRzC-f7eK zD8+ip_W=<(c?zXef3zXfzE6m7_r>=aQMqRtQg0U3Uv0@ZLa3YZeJ50GGN#WE!rc!< zv$HTY+)qYT|I2KoKl;tB=BpKxeZx$RzlSxZMqnxSl4GQK}1YmkyQ^V*Gp~5GDKEoakt!}Vh2B0!qbAR zhD55ytTm8|ULzz}t<|JWS?eIBdPCNFAYyJ4Bv@_KrkhZTb#vBcM8xEltY%2L-eN;q zv$i6lx@|zsExlPSRzlTwZMp-cShr`jAtEQYqm=4hHl#CaHzM5a$?8B<>^Yd#2`SfI zwxpX7>Uy&F5{ftVAaXd1yM2yyKclKYU^UVk{k^6`=OHCI0*O?8Sw|rillmaR>X;_& z&pHk%)hDw~01syh!KYR zl8qk9x{QdNH-u8Euh@{`tgDD{cRlMGqGHcz)-a@8->@Y&388Kz>lUGM)4i+_L{xX% zk=`NnL6++8Lc`qY_K#W#Rrj^&LzH4Ymh}h`Ie84FR6n*M<5^D-;qF=1Q$*#SagHc+BBt`Q2A&jT4kS|5`sYF_dbN;XHBXb)`R7AQ^+Nvw zAm-c#f1Q<3wMd&TMk&_y{w0Wr$t(QzkaE4$mMlYLm7lxi78N`Axe}fhWHlsGHTu^; zDte8OV6|40Hu={$7vLT)R-H33v$KQdd*mKa|2`SfIwxpX7>U#Wp z3B{Xw5IOAUZl5FFATSPij}pNC+AAV(mPs?UEEQqk*!1gm43wBLUmQmRk-PXG~f z`ys*Vlr}w$QmhC3XAlvS2mJ$(a(&i@T=1VmM0MwZ$}Ku|5qg72U9!zBSc|$0r z`ic!1_FqMWyX*dIh>AU<{$WVDzF|vl5<=aG{}!Qg(>?zPBC5OXNbeB(z_0qd&@gwp zvPZ3is{7jXAxg0x^FKmFP98%k)sJn+xc>pYLt^YNlI{yYW#8!9qB&1xwvnB5dp>E3mfl$0@iV*HTI?!qVCqh;K#s8T! z@ZM=eyxH7+b)?@I<$lKhoi*fUW7iC$s{cV6+1a#V_@7Ecm;4ef^DBUC;~wsS3r-Ix zL41%%70C8ODtZA(u*%h>!R&lUsSafq0ughAkYE+orV*549nCI9L`+U(MJ2wjz}`sL7&J9TO$^cs*_ZKE5r*B~P2HKLU2wKk+FdmSR& zZOC4asNBKj*;@(K`E95nw)SSXK+5%YTe5=? z>e{p02*sP)3E^&+1MSS-O{nVkWOtB;+grw* zebgT%`k{jx%YFnjJ0PDk^cW%BJ$9hu*-r>n{j=<+q#@oaWA8X2+&y=sFBs*1BKsw4 z;LVfS6NKvgs|<~|*{@kcpS&S0dJ8A_jyyNX-1`iED*FR#&|OoEs{Uh!#&q^4*3czi zvOl9%Q2@UkhMQ(o^9b!()A-uY`r!fP zODpp=5b#4DNGtK0i(D{}pLX&L1q$K0pv8<$!9bX}h~>l?4U{6D2t?BkpA{@g24Yr1 zRXm*Eho=;EU633w-T%t1{R<>4S~9}!{;I;SqzC(^?@aj z8uxDqtO(Rw2~|tA=`u)H1*l%0Cgx21y3%^W%vM`YoQ;7sgg07Fo@-gs6j)~^SZxTb zCv%#hWA1GVY*dm>kVw@W*bJ%pWJ{pgN~qeRNm~P3A?13TMU1JvftIwx=XNF80f|)Y zfi_6Rq;^QK+NDW51G^!mdQYGOh&lIQpwmjI>e8m&D8;%buon?Ixd+n20jl@elKq5m zcOXs84fyqt^^}<%v79*j0!In&vz$DSv7|q6+)A)I88|`a^h3wo+aEZkB&Q*fY9Me1 zQuE2dz<`xdbykyJ2%LkI>+=>7Q~7xjo)qK~BvK6pE<-AMLy%x~MUxH(u0l%n^}sbC z=G@W1u$54CLz~`2Db^!_TZo9s_W~o3a(&yD+(G0)fV;aEHFmgiM$-hAh{=?Qb^4w6FE^Up{hcYCUattavisbn99!@cv6r#kVsXV zGZ#|PtAzxsd788?XFjAOYXP8%X}ayv??-ep5Nb9N)b z-JYBdM8%$iIh~Ml-DOL<38AhhXD^|6Qx77CbGX~*NcS_U`U6%Yy)n1fbm%;!Bu5~T zsxRj#q+(JZBv>8Or2RR^A*K3c&Iur5Za*YgozkYKQHu3I&KX3++%Ttigs8O<4nlp&iO>B>c8ZCCJnrInh@^3BAT6xso}mc%Kc2vch-=b zjpt_=RsD~Qjh{+Gm;5qY#;^Z#%{!Q{9^!nK6K5dTPk6v`^2}vPFgM>yunOfCk~u-> zn70V#hLt1&iB!?tQb^4w6S+|OYXZW|(Uayv??-ep5Nb9W=c-JaYIM8%$i zxt)-5-DOL<38AhhcQ2uMQx77CbGh5+NcS_U`U6%&Y~<%5m>|dzNTlk^JqoGl^+AHw zF-_W^dmK`#Pv)KgBIfo(g4HQ)dK#rz59FRfL`)vc9e|YUvo_>H?m0wMcOIzRqEi>4 zH;B|F8$FbJ84)>e2&GhCu_42`R}tavdhRtu#h%gJVMw{YVM}fjLfuI2Ekfm{d$}Ws zsP48Sy+i1OT-D!&hPl&~H)|{n&<#=RQG%yJxvi5tVz! zQA+i5Tk?Vs>Lzku5-K-M=1w4@x>pYLZSHGAb^Z-%h^_9tNl3YVXG`7_LfusE2SV|t zDMGmW=s>4)KM|_>FS(yd1Mi(i#GA+6S4aAdQSN7Qzq5wiZ0wq0RP{edBRh{a4F6MU z=#pQeWqbvY@5)Qx1Dzfv@j)V0AkPn}m=J&jt6WVQ%*%(A>QG)G5HU9h307fk8bK-6 z(Y#Vb#NfHg7H>a$YS;sh(#;>hk6z!rj8W z1&E404S98ta=plwEGC4y`n)BC%1tZs>Jd@hQb)Rs&{cV=Uk(kqQ>Ru!uK}smHo7ry z4I*-0BTA`WYeSmy)*-^(hP?HN$~{derFx?+*+d9+&3T&%m77}fnh{am76;mzx0O(x z--a4uYj0i)q+D;eB|8YAu05}fP`s&~5bkz4(9XQwgsOf|UI%H&y$AC;5m8;2Bkg9C z`<}eLtU)*T5PCRI_4_h5_A3otasXQL2Bvc7_gc(Qhme;12uiW;%R7pQ?DwIR>SH#f zKkqmq+?~ujfvDWmk5Z~n*^<+QP&bfwhETa_FmC`6)tz;q7xK;#s`KYj18=p{7g2wZ z=t~Z6DDN_%c=`|_++A^?!+BQ;RsHq6YosCfj^+&`qPiQ7^d_U+kL2BA4ZQhY-Uy*O ze>-F24r@Hf(H zRW!d8QuE0~e$+~+s?em#{1~KM$1NhJ^0Nk>6l4x0Qq|_qg;exvA;D^%Caue#4=L3P z^A`Xy=QiZmSqW8(wCQ4$VqKrV1Q9WLMSeY`TragH%Me+W&)ss1iXHr12~P{M8WO1* z^VdKsdX11^wN{fh<*$R3>J9npfrzb3zjxAf+>SP50zwdoF&V%?tKhKQWpj#8?3*^tis-H33vC%*$xvFBiZC!}0=*^+KT zsO!n!ODNvdgUI20?)Ev-{fw&qfYlHi`FRK?2yz4xsrvGdLMnQFkYII8llJEyhm`7* z`6qygx&4q}bxNC_Mk&?<`DYLjlLzw$Am#e34Y`ni4iVLz2P(Jd)J5nGB6Z0|59MD* zM9v#RDb-hO$Z-BuM7X=2e+^NwXEc8pQm${?9R?sOH5S_xJ6wdq5YVm+4s2oX7X45d^*wjtyBPY~hmS^iT*<(_erQvKYPydZ?S ziTsy@%1x8`6Nsqpl>>d7|C&&pe}fugtGi$lQm)_GlJ|sAHaH0zaf;LI4u1ay4nNARkhyLj{FE#M~exScSD|1f^I<3rZ0YlM@9| zNV%@CA<2RmBC3l6m0NVG26_pk=Gf@kg1Lyud9^5|dY%obE0~W6cMA&^AS(7W6x2b= z^&(rcm=Nmf3ziTnH?1hBM?`f?9qBScR~4v!IW*)>omvUK2BcQo=*EIIh{$=3D5ZL> z4QVP^hX{8Y3f3bk_cWoD>W#K!6Cu>z}?_JTG-@uqe{xZCAGI}3Ibs`@=fiAg= zTH+4w!cj=MzHdt&5<=Zr!6QQPrZGaed+b2R3!V_F`ey}CNdxa4CxpA_j`Rhi+)os| zWDUG|vS5Nxoqv^~@wVVKYv_|Vq(yHbowslj^$hopdD?x?DECtZA6SDvKgFo(KW1o5 z7kpw3UGk;iGi%X%Of#zbucVP(NE?R#rZm)Krr^8M!Z$JI%qR_A@?%!5pPH6F`z4y@ z*L{V?t=vHuoE}hu_#lxgQ0RwL^a7Azm8(gEh53+D9V#pYBIX7m!78jxBPhi>T3CvR zn4Bn#Ldtc84M`Tp5K&zmsNAAcHPA~SHOEHR7S2UP&Z|W!)$?pfUEzF0xLa7b08z20 zp|B28t{2&o#e`5-U$}%&xoJgVJtC@G>PVLnx~fq1%b_86>eNc;H6XRxMmH9&K}61L zL@Cv4ZAeq$Iz+hJP`DmZxu*%GRByB;n+Tz>v%f_h4ZsBC6|hq}_~i-&44k zHR$FZLJt?JeqYAMex;#H4nRxZK&K8tuNSE!HoC9yC?axRA4;h{W<&Z5k0Zj}$-)ze z%02xkrTUaDIZX(41BGV@m74|&2M|%+SqFNd@EoB!e;zgPRy%zW^#_T*eqyWvQ0GRpl(;Vss{o9`8l5UTUHGdAw9#)Cp# zau>D49b84DkaB(BmOLbcy0OAXgyKzOgmCxRfsPkGAyoCx3ZIe&-aAeRch4Q^3r4x0 zD16Bpc=Kf81fe?rDnsLK;cM2=CvQkg-ojlpiHPdnInwuxaz9o0fi>vnDMnTQF+*dz z@Dpq3k}rjyS&QCdnow_%>c3`ed{Y`~GE?|nY2lj~n`e}UF8RS)*+sl%BtJDRefCQ> z#aDhs@@7(btkfHHA?35tfg(R5<`m<}07|LOwIRWxd_=el6%`^X_XJT&b=a0f2%#=o zR7$AalqiZKqPhwPnkvBs(*U9udt@Ez>*O4M&4dbNXV zELuY-p590ZcWWJJQ_(s?RllKVJ!#;*O@wf_(UERql>6qQ&8&epw-hxKs`FbiG+K+c zvW7m{Mq2U~y+tjEsBXI>-N7jL?L}>@K{vNEs`_0S8l6SESwolXDe7P?e2;@gorLOq zSH?!S(omD0qP33AGpvC(4;Bp&s`Fimt2jhjkC zO-71tDJ^=FdqpFxp-*nls&z+cJt)#=cS)1p$;sU(&y6zoFoPc}dc+!Z*BGO!f1IH) zUi5@Dbjh=#r>IpF#BYb;#u-)p^NfubN<&R1ie4%$`5rNDGFddi8v5kbELv}iUMnrT z>dj^}Eq(T5*3F;Vrd|5WXd8d_YyI$m@}-se8VLF!52TfN%|$L4%uhRc zhJuCgT+m|1reH8kT*PwXj0Q^)PXwcBhtCR@B!e+4p(>tEjhzXLo4SU$IhGS=ZE!B( zwU(3TJeJf2=UWL@3xf;LoQ7as+TnANk}QTqs`}s(NR9h91Xl#>t%Rzj+H@JDtAbQ7 zPZM({eqCujVP>l>C(g#;8p0bbC(pGkX$r2h609}^*ONI-&@uNm1ve_mCP<`e4sM3j ze6l6jY$a4}(WI@xt&noP%_7Fs-e61G;d8r^?0`h7_Fx;NVp2OKSnblJox$CZQoSeG z0mPhpFxY7&RCQ_7Zj@r(6Woi4oZJKH;ULxfY{`B?xI2)h<_7$F$a>1mj#y5deZixI z_gPM!$5_%IJZ>deoeZ8JbNZoU?(GkrQj*hf|nr`y&*`jx}r&kgI6J?`g-sh5OeNmaM((yx}i;Pq7>_q;4MVN zTXU zqpJU9Hqsyc=2r976T;4CIdKL;e!>HmlV>hVf}wmX!73CgBy)n$F}DXpVI_$`B2_e0 z3aR;IA{4a}swy;TG8BW9>$pY4RDRaLlY-2FM5@}*Tu4Q)780!HY0|pTd`PKY7+L_t zoZAqpvl6NnY173h#kxMU1Q9WLMW`N9u9w=9Wr(Z_akt!}Vh2B0!qbARhD55y&>BcZ zuMrZg)@stG&^kz|-Vj<3M9gi11gnkObQ4OkZVqimL`-f8HABkv78}wU+KPzkwgEM_ z^oCljgsSb@bO%bYZV$B~A}6<_lXbG;jZ&-!LT3;WlLtcskaB(2hFl1pLqv7wfyym9brE`lNL{kgL!rxv$azC3 zrTU5u84g`VguCmZYlwNaz-!a?`!g2qLPx?MUws`XHqGyU;Lq zy2GPZLe+h3`Vgg9kA)r~A}5cblLao+2vujH8t5=eFbpA=FKTUJ@!d zO@<~AQQa#C`Zn~MP@R8+8hESF-tZ(e4E>Hc+2;uId1Dy_iB2@KX zLZ3+k@0})uyRV35hcPwWH%7Ui34Lb`x!HJrhEdi3$k_O)G<3-?vt|7HKWyH?eDx6L zvz#~sVL#yk%gHmBCBbmMm0%SL7m_(a=$N+%hQmq{fkdikxD-t(quRW zDc5m}h^hRnfhPr-1Bq0%;kl5CUM(b8&C{fH;rWnKy)e80h&i_*TxTUzEz+ioQHpha zcnKn6@``Xhq+BnxCCd<573OZaMa2$&u7sxrSq+I)jo~$rie4imSgqBhP2qKrQoSL( z9*CIR1PN9fwdp35V%;3xjEI=r5^jc+>n%2I)x*RP_2F!RnYM?GGP^lb^F8h*GS_!jBM< zlgCg>^L$W336+~B!xM<8?v(?58-7iw&c8to zvDIBX2`Sg_Y{`2VJ?%b}?-j{-@H=CBH<=_zEE6Do)=6ogO9eK_XS4*bk|g5P$@$TumA* z&WDuhP;ns;F*gVaR$*-#K`GYJ;!;G!AT8#dVN!y~vgj$(P8Od)RPO0VDb=TJ$!S8U8z??QsN6JIJb;Mm z&N|Qw#pejs`SYlOx7z88s6R;bB?mWDe3?)@eTWe5t~k));;V$J{(A8>(vW*ci-!?W z-3>>2lTq$Rif^$7-h8ikgixKoow0F;H69e}lDnvd?_j6zL*E-2CHkR*8!LW9sF-fd z7$bzc#}0J7_z9t^e^&gIH1OVWLb!YGNMA6@{Y3Fg*1(%5izf)x`BxblZ;M~EhCX>i zTJ#o9?j3nVhvsLrT8;z$+y|K$26m=|C+J! zO=+mfO!0T6#cwjBG<3<2S+#y@TKepl*)+fUL$98Qc|Y^jXE|{OB7VXHmXl{LOM;Pn zE5RxhDI{}(&@uN0BVi?pKq6H%QVOa0WFiu^5~?aRX)+Rnl|W^fkdj> z$XrN8uND%l=4sNp$b3ktUKm*b#GKm@sk0KQ7HQMPD8;%yvIG$^c}1iiQm&WUl4Xdj zig35wqGAU>SHjbRtcFCY#>g5-MXwPOtk!DMrpP)-sooG-4@Asuf&{CL+H@02v2KoR zMnp_*i8MpX^%fh_8rh17>b3zjxAaC@tc0rV+H?m>v2KsFAtEQYqm=4hHl#DM8xijI zL^==^dk#iAA?3QumUI(BT~A~$p?FgdB8MZ~?Q^928CCrOt06Y>^AJoBk*kPscRg|qQL$$yM#6j z|5It`l3$`_{@TAp+(VomCGkNbRiMNVsdzE~30Aq9G+2@kDb=BpLLg#p5E87y+BAYv ztfM8Rh=|FFk|?BHSJ;qbNemIy#evE#I#mO`1X6QsbZyC8MC80$lu|vwl++`lx}}bE8KJ96RKFY=a;HwMgkA$ut8H{+ z$r?oDyhfB#z1D^_m8?UAyA37l5tVzIP)hYiTe67|>Y7V76Dl{glr$rvx-Aa0wPY)y zI=>Ay#Ma)D7D&0?ZcBC$LS1`F8=-hpJ0aZda-f|hy9rhOo{|pIkb4i7bRwdsXk>(P7^}iK*2K7pyMS^2vz;FlBcAB_l^_7 z-E&9!f>G`#N?x)C-aJ_{L8#8Z%FuXQ@|rdD$s5w5w~)?TI*EFQd&fNOzGsyCsge(@ zL7$&uRP`S-G^R^Fv4$@BQu3L#=sl(xRsC1e$S$P~!+%p6YBE#uU1{N)7;|QnhA#Or ztJY6VOP~D`P2=mosH-%6D|C94#0QB~fl@!DVnP5Cta3GJurwc1szarPK*Zc2Bv^&D zX#}NMM@vf)5t9?8QAoM2up!CP7$T~R1C?8Jss?%qq~_S@+S0j*$a%FWrFxzXsVkk2 z2zLuh7a%J3G?dms%Jm{!vX~I+>PwdpDmSettw%(4OC9MlLRXclemOMcPMul_y#}OK z+vvv9HHgT0jVPshtqo}^U55yF8%ozBD)%&@l z=~hB@ej93tt-Yl!kaE4r5&Up_Z}?mL_~F6 zjq9Bk$81P{ z>2XB3J6U=HQMsodrBt7?C8r6YZlLrGp>oq;=>Q_CJL^C%l%6A0=g*@C-fE{WqW&P! zmmJ(s>19Ik^dUmHyW&8HORo~D`s=0FNJH)&EgeQgbvGR8O-8vNDZRxSc=Nr|5khtT zcE-jX)_72=OYWkUxPz-~6jHA5+meTbP&Zckh)}#~j1cY~JJ9jcCxoj0S?N>KzO~CJ|BHJ4gDSQSPToKd=Vf zJjJN$KW1o5mwsXmUGk;$Gi%X%OcUxYQ~lSBjc-arO=e2JD=mBzWAlvC&?P@uE4z%h zjO3@LrO$rJruYi5%)FU9>O#tcwB$aNVjU>+BO?0&lv15*LxN@bh;SDwD@0W838Iwh zuq}xYLS3}1lu)@TQ5Ho+brlXYSr#Ky=i{h>x7z6%)K3sS$HCQ>%_S61uO)=Lc@DI$ zY(Al?Us$$)H00ifvN}Xmx5$w$W|aH-vL&p6H?JtGCsgN`W^62Dja6m3WI1Z#JJ{)! zsNX>JY6sU?wuVqVy^#>^);iFpvUP;2enZ)M(!hJ02;pv{Bi+O(_swOSSp#owDQhNF z=eJ~Nw3cmU4SlkWwB#*%%UTdo-F8R1gHi6=%i36jZf<8(^}8}OI?HymhA!Dt*1=l% z9tX=h3Dx8j8|@|fh=c1Z zJ4&dSZp`Q-gu7!7w7={)p{hSwc7inU-hM*3JLO1EGs^uy*%{Wrn+MAV2-W$s85$SL z&as9*IZs;j7EbOWd2W!oOBwu7*=5$CyM`E5{gn)j;j*i&p-ZlpU1KeLkI}MWLUsN| z#>P#hp(Z0`x0DvW$-S}>*3c)nXVto+v>ue{v%928@8sm}ljla6dzitGl|4d@>?nTT zaAS`U2a(kzP7x6km? zN<)`?omK0brlref%D!uw_&sLcY(~@4XFq1${Hbl)rN7L!`L#cK^+e6vny)^~i8B!O z6CSXfJabtRjOJSjR-tGinG=MLxi=UMD@g6l4x0Qq@N1LMnQ-kYF`Wlh#G&LrV3+=mH?-+=ghKl~A=vn=VEv*7eaPh=|E6 zqVJL~Av5}vL zV1gh=Ad#vsdK6O8>w^TVW16%-dK^-!PexAw5p(+?!RnMYJ&jVV2cl;X5t9d_1CVlk z)`nb&oS8h{$or`=m;XJyX{Et5c(jh`n%9Dce=_)t%R!k+Vmkxu^x*)LPSm;Ln+md zZOC}^2_oD*i#|nE?ioiZ)z59o3qq)yh`uCLZkmivAfmcg4)ksGHK98H1~tT1cljiw zT)(p=?+Kx9D*Ay?ylILM?mjxu>F6gyRsSXWnKba;X+*r`+UlP#u6#Zs+$}6$fT-BhP+kWq*Nbe)VnV2^FJD5a+_a*+9ud_ob)?G(T~)67<tDO+-y5b6fX&k!m%4VDieqPnvV^g{VLLUsN; zYT&JQ`XcHN5`D?R4V7Oe6i*)_gu5#abh!K~p{l=LevLHb-qG@5L{xXfk=|sK`;qcn ztbsS*D<2_L=Wl0h++mFe<+|i9YKc3zD@GyZ`o1lBNCYtTAB@MiHoDlAwJJJ`7az9c2k~Q$=$?^$8b^cX`#@q7Otf5cdkQTj#bl!?d)HB>W z=4tmmqufuGe_##z{1l_A|CpgMUH*wRbjg?U&#Xo7G0mvzzmi6F1#KAqo6=B|ney*S z3*W?;Gov(g$&XpJerj6!?3ZYoU;kBzTZz-7BtA%_3RL(Z6;B2r!75ji1}pL*r8-nm z2t>>cLV{ITn?_KIb+n=s5ivPY5rvfN3LBEFh#{i7I8eDor)r>=Kx&SSuC17hh@4l8 zQmW_Kkh+Tbh;X;CVgaIJPeVl=q+BnuC5s86uD)Ukp>orTih4v;x73j?BXm`T>X$=9 z?$oK3&}%?ywT*79Sc8b1*N9T8*V>S#igk!^x1nM^qH<3YN~zvxOEwWgU30}|Lgl8G zie^Mqx5a_BR%|6y=eMDT*xFms0x8$qZOINosB5oiBNT6HCxp9Q4z#mkH=(NEQ_(>h za__;4PDE7KvQ2oA)jr~ePmmGkWyn#*~f?h9DM{IOo#Zg4$ zygrmteawdRR~$!#yOR|s5S4rSQA+hGTXLEZ>IN##5GpqfRtzAby0Z@SLd7{kb^bhR z;H`H0BI*wkeaXQMRa_<%Pah(LyDJWKxZ*0Is=r=wjWp!m(TZV2RCmLX-ei>fk&0Wa zfj8f)7$H>WZ)a@WVT}hBy5ufui95I|Mj|jz^#t7l=u>&2ictWV^ zpH)014ZL@p5bmBk(ie{#Ay?+ltq$p-q1R z8RdSe;sa~Y%~Oo3{$qy5bj2su&?R3gKC>3R$26hdO4WbO*!ZS2)MTdOyVAlpF*eUA z4PEkswX!RD%Se7|TKeplY?@yI#$1)w&4}`7Qy)sP4pjOPk@Es5r8?J!1S|6q;Vx8J zh^X8XL@Cu_TM{9Jx@cu7p>k8AGKz@mDjaCCGDfJ*$58`swbM1IpCEdUgR8BaODLXR zO9*%K9B5tTd_q;fuyO%u$h{4fb%>~Lkt1EqDEIZ1OIQPMUQt<3sLn6V*jUCIt15NL za@4|iu+uA1zk%r04z96s4WW2?BO%j+i-hRXG%f%i5M!rewkx`|Qln=3c7 z2HxCK*-WU;Z^_VTt=!5Q`eYkv$y@YRwjiRq?T&N@qujSwwy_4?+|H=#cV%dFR_T^cdQp0 zhCW0bZXF?ny1vSzgyQG=2;uIS1MROoPN?cnR-PaYytkha?oK(<(~NRIP-=&m6~RevQzW4Q7vYv_{emDgAc z-($3Lm{6U+k+E@8X{gCa(xs{V0?#(3ou*3c!-Dxb0zy~jACs(+rb@j_{+$wcK#rA2QtSvkQP z`sCFtT5l^~D=oY14QujSW%BRX^OK5yKZ|6l@&jpQ$LJixPbm#u@^Kce>B>(^OP_tI z{H!$bd&Iccw9?QeUuV_&rfKQ2nab~)rh2m(O-rBsn051~wrQ9C5^eF-KRZ1!acgn< zAdxB%^Fu0n0Z6dQ)uh2#KBQEKVue7&+#n=ag|%q}rC3K}rHF{hiC7d;t}ARvG8RKb zb#b6_i%!)*FM-q?8(kZli-??8i&CoR*^s)}d_=fg7+Zj-*wYZJgOuwWVcOiK13&)72=&x-qr}5jn3BrBtuAAx*J$ zh;X+dwjNQrrwOH0Z?q+w2%)YywwX}5sU_Boi0ZaD(AL;iLUn!{YKX19u@*?V-fl~F z5JFvhtc_5-shtq+b~(__*lt2qzbDo~8glQ!SSKQ?>vE*sjB?)-+shhsa}S}1W2)bm zv9Vui=#m4_k~h$)L(uC*>WGc*iycKo&g(-d)yHf|f9yCS+?|Y_KveGOM=8~(Y{_Xt zs2hl#AyjS}j13^7y0Z@SLhKx&I)5HD@K!s05%mX&zU1JBVwVZU(}xJ*?ur8)j$I{G z_19z9NJH)&jSVBBx*Lx4CZpVs#BQ+$-h3}MLa5H)&e*ua8V_Q+G`#VlP<(Z=Q@z5UTU9 zGBn=CUbBWic|%(A7VfG^L{#_Ak-le?`>EIm)}WiG7*+kp42|j7C)Usp+zs5jih_QmS)pNU$m&5$-}&g^0>ML6lM*wj~ilsEbyW5-K+(s-lRfuEK#P zt73%ed>l3KRy$pT`U#@vIJnxXxrE~BwS;gt&wU;N8hCFLA>3_rq?;J!zPV~MYv9c-Rn3Iz{FV%j)~c(e<6u=Mp*r7{vC*wG)TF0suhQZ- z>0yn-Rk~!~tXlguEq!(XHQ`3_UYRm|$d()-gu1?}qlDs3eS~m#%z^e-9Vb-vC#z17 z2Hx9G2zRF(>1jr}AE-LR8hGOwoLe)9e&?o0fi{8S?T_n#9GIuG1AF8^{ z8g$nXqpH7>p)p)_l{Iw9^{Q*Eh3_$1HB6|^-^kdwsWjANr0SN^qBpr$HNqPD<5f>sLzg_Oddgb#9^;Iv z{&~j63#FkZ6ICyj7QM-2)dXwklUK87y{&q!wCu7stjTYMy*EBd+J=9pB>ai@N<&Si zsy-+!K4(g4=#r1KXiZmrQd;`#OVwwk$?r9-G<3;V*2<3amXUnZv~<}_)pt#k-prUc zqiN~0AG2=$)HdzXU$QN}>W|BNO69RqZ^DI?&qfF0eniYE#*+b*Qk`oD*g6KI8t~NfGP&~bs z5bowV(7O11LRG&ozJN63-iCM`BC1>DNEb88eSLfhYv9c*;`M~;{L+k#WvsC(u1l7q z7QTa>UWxh*M6Y&mjqx>v;^~cqaJSZhHpSNws`?G_^`wFKHW9+zMn}4dQSO`Ln^^;I zZizP&s`FbiG+N_ZSwo*}BQ1H0-gpZls@v{JcQDF*d%TS`=;n4tRlh4kqcgsnHFU|I zcn53YdmM~+5~}lE85`Y7Lrr?(dzBWyNe^orj_Zimt2 zjhjkCO-ACkloq|oz4!=g=#$&CYTZ#<590dlE@{d;xvEDIQQdt<`jAoX$KsDzgKi#U zRP~QDG{)mkSVNaQi$7&8dXI5NRsTF=3|N=duRfRm-UA=VfTrRnKP)U9zxx0c+uVG*s6Ss`HC7 zHWn)lHL0&&qO|BuR#exshCW$3tJX55wW?a5EhkNSCnvX(JlDY7>I}ZIdJSvPU5$*Y zer<+EQ}sI5&?OtH*RvMAM-!u}-=r#>Q!-p(X>>XOxzFj~F)@tR7$ueR6gdtqaxX zl$Kp~o;CTcGWm<_`9Z~Bnnf~HeOYPo%|l8Jg=7m))Lq^NyzZpxQ3I%i8>onf!hB{HWp|&LSDBex$Vc z<}szAOCHanHD3KhY3Z|P)lZcszt_0Z&?V1j)q0_6>9UFHmzpNO*<|&E(z455&9eEn z`n9HMpS~gO>ID7xF#M#_&?WC?)q1aK>9VQn51J-^|Cu+N(zNv1$5}R~t3PR)cIlVu z&ziP+&uL9dpM9Nm^P9G*PiLyXYumb;&S;x<>5u@k_gvCu=L);w8iL*8_m+)H4$#Wh{>Jsy<1gnLK1!zt~qAu<5xkyPCLn2juVhNIH#OT;Z_aycr;)2ONkRDD@ zz0a2HCxp8LY3fREz^{j_r_Ah#<;2;SI7)b*<>YycCH;xxR)W>Z#0fH|A3Cn|jrtR( zl;kudQVk@|Kx#fYm>94Us?KWC3yE`(a(&(+uJnBdp(p%BCAkENR6~i&kcuaVAi?U2 zCLK;(g_P>+iEBVy=^KtFhOLCE8`|_HO0gbE+(N`{Hft2gpw&V^X4-(wnwWuq# z!<8IOJAB?(l82B;HI{e;smq!)1_@S=HR*Wb38Yj%OFRYQvgVFMg4J_v`U0g`Pb6L< z;<6@BCMF=|`jriNn|O_g>fQi#rMI|~lU732J8k+NrC3iTJ|NTXUqpJU9Hq!fC=+%?N z&SyDs29kcl1D2C#E=z*Rd@I2!lq@83g3vLy2a{nXi9jM%G+7F%`D7v)wGyf-G-)y! zgOuyIMZ{Eo*1(g3%z;Fz+T>hFMXweTtmbLby5xLFsa}{|0K}ZzkgT&3supR}#VEzP zKDh)DF?mI@9#XEC+LC36tV(jX+@fL!KUc!jf~b9RNJXy^60Fv0(x&7(NU7eC zTn|LdZGr@=joNe*O0jNEZbn2*Zb>#n%Jmi-(wf|gi0ZZhHMjI8Tdaht?b>t)O0jNF zwjm-Xx1*HmT{fgMxf>Dg_9QzH6?+aQJ0az|%a(K#LS0XCFQIr-4w4HfATn_RG&dpg|TXgCo^ahc-WTS_Yml2WkhEPiN6&o^~yov~S*OS)} z6?;aL!;o@)!&xIcf{e=dqSw2N`4>|KQ~1PcOM<-bn+9Ss{fMwOd5FaG$Gu5MKrqx zQ^S2@l>3?Fch-=bjpt_=RsD~Qjh{+Gm;5qY#;^Qq%sZH`9^!nK6K9~tPk6v`^2}vP zuqNM1unN@_k~u->n70Vlgq0)$iB!>=Qb^4w6E#sQp{hcYCTn7lavisbn99!@cv6r# zkVsWqGZ#|PtAzxsd78AYWd*1!XiQy5)vC3;R@K01jnK9guT?Fc*B7r-#Co?)HE`M> zwi`hU=l0@FfLJeg6t}CE&YKNnTk#e^c-pGy%$Aai!K&?GTin~-x=Y2-99}%3oiw__QH+2JYteB>Qw)7C8JRi;))<*h! zRJ~x4aEMsf!coQ8|aKBA9{d48abnVoqhBiRN|kHq!~XyH6s{1g!V z@+fHW{LDbcik|~Q)63!)fa*PCpvChmBYBMoPUFRI5Y?L|ipK%r>8%a@Q2Y*2DZdAX zwRKj>glg&h(MUcag41O2XGGzqNknM+Vne5jzaq->_u_BJfP1F^nNvd34_o?^P@1QU ze-T4(&g_~dl;_{bm|ud8O#Z_RsrhSJnZE(J@=E^Q0e)w*X0B@VlwUGWwbl#ys)5r2 zp)Dv`s9HQPE?K0A^=^S`;Iu?+mx30~g(b@Xv0g4JDO4?;mmA2ck`;jPv{F&MMVgA0 zR|F=PVfK``0nzVyK#OOufdoo?fY1~y@dIk@Nt6UsOXrZ0)F6UWq$G@}-jpnf0K!w$ zmc|fmF5x+@482pDQp!t!DQ%crOI8D--)jXep4S*iTgh5LXj)&g4p6_il9>O_R5T{g6< zWH+Kb?=9Jb488YANf#hI?X#u(38lHa)yex&?4t`Rgpu}PyPPZ70V z&%7~;2u;sy=vc{fM0tK$@&Xxf?-(L9y|SgR38i_w+D z9$EMbyYvx#H$l=Thdf#G85r|j@cT@fB$Veb4#rf;S7J!b_mXeK(*MkvJEjQb`G=$N zlNr33F8ReQddW01q~>={)*r!=yT3E$%-{aNpR-*v_s#q{H=C^AeAhh0^Rr3+E+9>T zYhkv5(_+^m^iF|tX7(1imat~2YV=g-TBh2WFN<7-*#=L`g?5!|g=*=%GE1yi>2I<6 z(jqR^=*i=9tJd;7s)3VNXag>vYVjO&`4yRYH{l9o8$5-?wg$9tj<~{rST84C5!KQ; zY9uj0nq4%-v((x_e^csfi=T-+UA1)HY#`fQTL9r{tD-YodR!gZ22b0?b_ZzT-09j0h<>>fw0PcS zAYHEAfY7wpwFgjZ&k3*046x-=pdU ziyT*to_bv;RBL&?s)5rQZ1g(xK1l#z1yc6IGq*SbD)KDzw108*2@E~e$~?X zf`MFiT?B-uON#0((sV_617Nypmx$4P?l50}z^Sxo!e#?HO?msg};S zjpPm@I1Rh*BC0n%bPWT-(>+^yAJNAyo*yVp37ay>z_*RPPxBEuLQ)$!kP#8h5=xRBxJajRV5dTO0bp^$t-fzXyi3byn$w zYU%vZNIoHg)1>P&qHxnBA~b!mp;NA}i1Pg1^$i(t?-U?&N@@CGOMend^R(+1G4$rl zu4zJf{*8?JrP#>iKg^Jtzm_%gzx_+CJFMT?teLACJ>{3qQ?2!7zG~pKKxhj}7pfM| zi%S=j8^ns&oY)JgrnzZ;_^AX#*{uHyFuAL~v>^-Gr## z)KS_F2v3`B=(f@=h)Q`YFs!XTr5&oJ^L8WIfe22Wr8^OYn>rDpX_pP{D&37J&wESv zAVcpxQrZOwPy1}?enM&PE;v$7;}YRBVrf7S6q; zCjike_ktGBCk>>p^b{a8ohdyHsNT~DT0EaMl5>dQ)L(iYQN3xPv>yr=7*)jh)VgMqj8@Yk4vTI0kEtaX1PaHOXo*M@&pl_MoXU}3O9`+Len!FI#&7| zQJ!CxzCZ@tJBA2NuWadSLTMf^eM1bmd7^Y2Q7ON5Fg}#NBZl0(M;5+9r#bEk;APTB zlCk@VP?{%8KNACgKS?OhUmT37(yzpjn(w9Gh=uQ%B9!MJ$e8cOMkfDc25+WIe=!SQ zl6hyE8B+5*C+m-3$=zSe%>4b&ljr_-75JUanz^dcQ@(qiYONRYRRgC5LR;Wos9HQP zb}v%IdbdC|a9Sd^OF;|gLiaL2te1=2g{r0VasyfAUI7SCD;3pSq^VeWMPPCnW{=wq zhM+EPa7A9aUZrn2sCfUiS$=^n1Oa z#q&u6>2sd~gr+m@(}3zdeW1njStB`z2u}U(^N8wA1MYr6c)DOiFS{=yD&}HWy=uNn~KT`0pV%64P8~X0#PZi1P0t{nu~#7gl3mb@|3v|g|B-Mp~-7Q z17$u$c@CEOk)ih{$^wA!6tbl?gwh--3ljrwPL@Rwm2%Y4h!LZ?Olso5f;X7v6z~&h zPTQo`vek&f*IN;xX^jnSD_e^w&+E(9Ap`DhLxiRcwsa$*G`E*+A_m;tQPz&Als7vV z+sd{OLvFSrOJC7b)&U4l+imF%LTT$=( zLuy`@y&#tUXU^O)Mkvp(9F5n^;LUj18)o54Cd$T%AvbSxus)Q%W0t9VPfU81Q~pT4 zpJ4e@4$WlQXJ*mOlgyBsFF9CKWnY;kci+ptA@lz{_@6J6r!3qHh5Ytw5vQTR7>ZTSz^6Pe~Z1rPdDmn^Ip}B&`}fwR%>o*790a1E)1Y+vZuTT0F1!tW(5#w@o#0+90+YK?~=0 z&n7^umpeS|s-^R01KH-;0tioA6`k4AGJFb zgr>coJ%Cz!j(ECMOXqz?vL6wgx;+OFg`2toIp(41pe;Q_D9?wphP9FY9#t<`8#kE11+5UJ?8)Jus}Tv&tt_OXrV9 z@(B@~COw}Kg_|Z3q3Meao$`D|l;`iBZ^(dqrvRB#PSX!t`jb$ar#-)jp*LrCO%uxV zZ)D6b$3`aqVTRQFwXB){?O$%)Vg1f#&0N*!DZhN4YOOExRRgC5LR(P2P_=koT)s#V z>)is?z-futE(I-|3(J=QV!d2cUZ`3+FE@}?E0uLw*o!|W+{1ESya zfELeQ0|}J-0HG;Z?g!M`lPC|Umd+s~sX+v%NO>4hy(w890feWhEsY`CT+VY`8G5HQ zrIeQdQ`#`Mmahgxzt;*{Jg+g3w(_-r(6qjM9iVzo8))&o!ALeDf>V3>CPek7j`DUu zc-m}3x0P=}RLWa{VQuXx?@%qBw;Rb0L~!aX--#&P)QJd9yKHDz`EEpc-dny08G7%L z@-9Gl+Gk7m6H0S;`2k|!&E1F|E9d#3qj88CQgc{Y*$ccqR)eOaVtX94aPBQX0f>IN z7qoajX&`;&rvRbpO!;X*^`1V^;`ywRoI?bs{_^vP>P-XX{ebXv!G>Ngzlf-mF98E? zHO*ImKY-?|HfgZ@8lv#^K}2Y}ZbOI4Zy?I^t@4}5(0fP9hXCQ}wk^FwD9yv=cZmTv zKP(?cRLb`pjr+uSTrM>afMwk<%R8c4IzKX!Cy3xQTK*JKxM>s-nx5IvvGV7L^8B*= z1v22?F+^y3WlLWZO7nR68)CrC6XoNGO8KpW@uB=3G34ewvhWo;&GAkEFOxo!jNMO! z(mYxInHc!{NkV!4;$TdbeYQ;Y}U+Gjh^zo^HghnnXei+EfCrQ??Tn$d9inqBG$VF zs)5rIv0VyUI2U@C0b;#eA*wfZc-sNtX|oO8 z=G}s*l(z!I+S=poP%WLe8_5ntaO(8#L=*w}0)(f1 zwsb$CG-0HWXP1udRW8c3h_ z6d*L6@ty`$@96_Ap3fS|IYe;k_nt>oZyNCS1H#h<8+zG$5m6~$0tVb_ny&zV0L@oz z(xCSmqVV-WL}b=B@MhZki&^lJ%;srkNX>6z&99(VruidSa`#u8 zGk*j0kb;VZfY7wKViBNvPXTE0yu?VBB7#$4 z#WFrfdRLg=3?L%q1k1VJQZ$4;p-kmX!6?7K!p!co`V&B zWazz#iU1%yg=}dJp)^M-!o+}^lNAv}r5trMV#H{!keWEK;0>lZ1^fh>(>AHKVl|@h z^;Se^T4O`oD%K*(^ZJT)$bfs>5TR*1<;@Ppwu&vpkejW@ z(pU6UbO6HBc3ZlGP?|d{b`k?`?j)4wT@FT9#cpCq&EASV#DaGmspvvf%KIFR{mkG^ zcf|o_(M!6CajZgW4(4PX5-hnp3`}^DHP7<(C?hi;MG0ER5y7dq;sm1byIw?SI%z}u zDo!EF^O=g%$bftM5TWU;Ej>pl&HWYUi2*kcRP-Y%z%Pf4!!-`>I z$j!Z+tozJ*Tp@Q4kcn@yOOL>Jb9^HtJ#omR6;FwwcV%81C6wo94#rr;b7Dx%%ZeAo z!gq`j%JVBn<25sQGhXqAS@@EPig9Ad&D$KT4;Am2W$NA&lV0VNKa%e!SpJklGgP<;s1Q4F0wls!lvybPvGW1SqN+~Y^rnF&h z^{oa(zt;*{Jg+g3Hs4x6Xj<=E2dLiD23kCCFp`ak;MDHhgs9%s;cEwkr_DBWn{NxE zQr-#-Yip0ML$!3?ZX`Pp!Ku@?6H&OS6A_wr+0ZWEZbW(B>)V42z4wT(3lN_6+0y-l z(%kJkKn%RO8_{Dvo)0=2hnOKXhn1x-kfx)`>jBeo!`$mT0f>ID7qoajX&`;RQ-IKP z#&;S}y{8Yfcs^?+=McfE-*+BSy=lPL4+u{eZ0Kd*MMR~12^eszX}$vd0W@E=NrS#? zh{D$g5uxe24IT2`K$PcOzMII<)(v@;BdVqIBO`f&2u`EEr-;H$qlnP-%!ZEno+HZhOWzA*z`bLL(Dcfdz9y9B zao-zaz|9lBaYUv3*1`DTdq)hpd5fbbNur8R`o9H|Tw18z=MMi7;9)X|6$qq$OQ;=qD8nC2Al6KGD`q}IySh{D%f z5us^~4Q;Djizv_QE7u_d?rlSarVX}qBcU|6S8gH(+}u&wj;NG3I~dz4w-7^awjxVk z(Noz02v6H>=?+3^?yTHN47|CMP@Z==7+saSi6J$6EB6o!-f^U|3sEWWb2RodgE!rk z2be`K=_bapN~t-RlXXb2hW1sSLX_t- zm8X#b_x2$|(^*@3j!>HWE6)=HZXT%YM^wre9E{7A7l|P^mym_8uuE6acLO9{b;yI2 z*NB044HC-pbq8ap@&+-a=2qoRV!=B`Du)o2@@+@s4l{T&TzQvS_>zZ}!^DuAdpTM6 znf16*?j9gh-!#iV0tio!Z0Qq1X&$Y7N({Vtlu(|ZIT&M=&xs*5FDqXV3*RwDD9^7P zjn~ZJ&3NS-X5mXFD#wW-H*a&WK2*MAmZ^JBOnMc}bNmy?&g74*pAH#E_eN zIa&9a_1G_W50I&E%Bvaygr`Tg^a-IfkNTey18*KBl;>v-#+d&(F{I|D{{^w|9b<&@ z{L0aI%?#d*``<7NUoznzCx+a-&B6NMf5$9S_nw&Ws##SNh)VgRqw$FuyqWZWW){6< zk{MF-B?oKD|CL#C_uc=Ene?tHV$7+Mnjbk?KLtzbrv1MJ6JM6OV_LA}?l&{%S8+4b z{Si%5`xn~({tLjrzxP+cTj4xgkvV}pG|#n3`Bn1}wO-7;k&g&X3v6gX)j~vhUR<>Z z8E|g_A~Y?rrArB=xv**(G2rH+szOAiyxhT9RkeZ`aoqeRc>P7 zT^>St_Bt4WDjzYVCRpVs7Q7=-6+l$VAxEQz8N7*9g_(sfNmfOOAve*StQfPJtK=?@ zOnj4FN}=x(B&8j4Yt?FE;9aeR^1Q~uXscRF45?XPwT@W$jy6Jh-r#6#WCm~At2QwU zU(!+4P7Jx(oP)KkY74VW-Bx14t9q(B5S8+FM`H&wc+*+6lUekVPG(5Wt{kkcs@=?z zyS-I=n2GN?Qq@Hax!ISKwO_ELuDj}hVDihlnRTp6?hfW`9uiGcdl=dHLc4Sneb+LrxtlMY5-)hS{~&6%px#M1xFnLGLj<@v0magG_h>90D^EPTm8 zRX;K0=0XnE<*JL!GIf`TNw0FsSIGAREMLu`8LYa-EV_A+8B%jS2WzP62D9YuR@F^r z;=4wwhKM0Iw{x=Y2$s|hSKSp%dfCIOVP=`SdpVo;1@m#0seM3fdZSZ*M7|$k`AH7V zXw_3@(aodGkeX*XSYuVsnI(5Gt6m`U{{r}*FO$cZAvLdZvR(_8)QwlY5lr}REOXgJ z)i|?E-P;_^4^{63)7-viHor2L<|BJ<Ena*iBY_7EFG}q+rS2mmJNhs;`1+YQI-~ z6KsCxlwir-kDSe)qA9o2Rlh`Ax^!AJP3`ahWdAYP=Kk-@7c>8VKfs@}12ebJ{5dz9 ztl#{=JjC;}N&hY&O+jE`wt>^)z#{ZcfpTW{76g{CW~plQR2W#M+LAW&atXJu8vHH>?F4gGC6L726@;s`6lUHa10iSB|91QpsnRz!62xJ>Pg~YZ7 zv~Z3D!hl#WCj$}H(m84*F+iFFG{v*j+ChI)>T8RnRimfYz-rZ6UaM;0v_@##0&7)^ z=k!=N1$D`blz+r+X7nv;c2U)Gh2EB9oYs?+r@SV zXyM!$*a?V!xf8T_-en+Nf!%=6v^TH^P;1YTK$mLiyw6DXBZ5II7&SB;)}11D5#dA+KE(@CN23!G9dp3ekMD`LIdry4k&729*5 zg>!%4JRsJ~1A%_k()ogcTn=0Wgr`f2>MhcAMR@~Yx@wpQ1J?l2?+t<$&({rPC~yN1 znr;Pd0&49U2@I*0&bN)^4k9=W2ks)OH$4mt1H#iiTY4YS#{r%nC}U=4UT`Ga;OUXr zJ^?M9M*~j*(JzmJ7SGQNWGwI;5Sm^FUI421jDZ%9R$h~P9C_>3srG>HgJUu@`9;47j$e-C^^2HZOZ$ebWe zKWynwLTR23{33?loY^%^D9^uzwW86einMZrSV(s{XotO~9Ggr}8? z>Mhb#th^#HxeT)>=mtc;=K(FAy#^8p`T(IR81w^b?MVa!s-<(tNNNzlDH04Lsy8Kr z5kPo~+R_-J%|V{y%FsKdDW$vwn9_#1HMklO{a!0*@w~=B+Jb8Vp=o_^9iVzo8))&o z!ALeDf>V2N6QX)kN3b0bo;KUiZNV*wN_i_VtgSu44%O0myOHcb1gFm6PDJ6RPDE(h zWkb7yyAkDiZ*UJX^xh-EE4ju zpy{aC9tSO)dxIwc(J%Lc7SAUQq%U|15Sq>ePXns=^nn)7XN}|>A~^L2&m*cg4FvlE z;pu`6y&SxVsFW`O18z0VSAai&=BqYoFnA47`1&9sG+no$L%|z}@_Z|J6B&B%NN@-c zo^IRHJA~3a9K1^mxcOml7*Q$Tb2RP~<8e@G9stX_VOD5FwRC=DBu@~*X*Bp0QMhRo z5t^Ra(6QiiM0tK0e1QzOcMK7lUfI&ugwi}7d_xSlc_KKDsFdG27$1V~h#@!ck%h0& zX-;SYc$xH(WbA$-l;+9cXJX**Ckf^Gi-R#0{7MX|`5yd6EPTflp*;UU#{3XAGWjPn zcrzXR#VmM9=ACI~NX_q@tUrP!cYiH&=I?(Y>niJaHf!dpMo;;nd8)O(%vTMZ76@%Y zXrXHHyg0N-5$oLo)xc?q*e(SvoC`zC0I^;!3KgoB&dUvCRcHkuJgrnzZ;_^A>y(t-r0K!w$mc|fm z4)GjUhTbVnDdi==ls3$*q1Axs_gX=V=QRe>7Fr7kP3uGJ0M&ciK#S)MMzRqRoZ3U1 z5Y?MHLhXR?wAqGk3vEGE%3Fb9ZS4tlsFu##jbsNRICX}0A__NkB0|$H8`>4xjVRB1 zLwk^+_Z|s#0m9QhTe_c6n!7^>h=DhEBYG^v^Fc@B5HqCau(I?8(sWdLJzzR+n0rGf z0MYODf)>vw4Wuu03J{vkgiZsh_w<1l&u5L~93nXNht4CaHw}dP0paO_4ZR$?h^Uk= z0RwI|%~yawfaa?LUjH%F9Vo1&R&^Kb?JEjnwQ_b@aN8=|mcrzXP#VmM9X7e;Nq~kb>%kfY7wKdJ&*{ zPXTE0yu?VBB7#$4^)f{DrlRUXKzLeiLswO=Kvc>rfdRLg=3?L%q1k1VJk@SQ;p-km zX!6?7K(!B1o`cnXWazz#>Hr`-g=}dJp)^OT!^D7_lhqMKr5trMV#H{!mYO)Q;0>lZ z1^fh>(>AHKdNrc(^;Se^T4O`os@EdQ^ZM#_$bfs>5TR*4r%heZ& zAvc$hg|DznSI~C@BwcmLgVooFfp-lO%JX#xW2pKDF{I{J^-W^IJ4UL95S8+6N8=7N zcr#pmms$9dhtg{TH*a&WK2*PBmZ^JBOnQ}5 z{z$%`VEI!H&1CgwWX-R^?_}~MGo%ga{{oE8XeLCr$d z;(2k+B1Nos3seKAC1Sf2v~Vu0Sq6ypa#2m8YU#Y(KvvbP0EDNNis~)WRII!rFu4q~ zr^XG4e$NA1JbMi!P~!uHreKX9P-{=3CZJk6hm52K5u745VMO(&WK9GRo}#uihG=sQ z&v9kwozj$2UII*M!`xc48W8OF0s#q$Ou*@y^E?KPVa z)tfqM+5zEdvkl!=vjtHpZv}?6wWp>-wRGNYBs&nnsk3G$qHt3uA~fx?p-g0O4t$E!|Hj&D}Kzh=DhEBYLcc=Yx*MA!bO;VP)wHr0J;gdcbttF!$D+ z07Spn3tBv%G?2cUQ-IKPrsg!DdQTr{@qE@u&LM(Rf6aMB^`?QEen5D-U_&q0TtrmL zmw*Acn&vCOA3*a}n>1K+4N>^|AR;tfx1mEdHxT9dR?SUh=)EH~LxAvf+m_xTl;+`@ zyTpK-AJz;bD&>2Q#(iQuu92Dtz_M=0s~u4-ogW#=6GU(tt$B(l+%$>^P0wuTSj}@p zd45^*0vT}c7$P*ivZb#HrFp#O4Kd*6iJEalrTo^x_)znX7;^I-S^A1uwG)8w^wE}n zB9!LIn$N_*nmQ;5!~<@txB@sk<6nXdW8EO<#~^E5N0 z<~OnC*HSCf{1Gg<`>RdsZ+^A~#$y4h_6u$03 zgeI>I4b=J&;s0{$ZQ^=Oq5K42THcSk-IawP)RLW6DBSwtoTB(Tx3*KOw zQ@~H4Ic<|#YgZ!*UvEW(rZqOSt#&PwKs_c?-;2aLR8AP9gRE8;LULD zU1s4+9@Y*MLvHTnWZh@h<660UfJ}YUtndgRJUz0dPY9)XwDu`6@a9oMd4A?#jMY9T zhSa>QeL*aI#~7hJzj8EQGlMtdwQrb(FPW$vCx+a-&B6Lm`;J+r?maQ-RWQ#9Par#! zKeC2?@rfC{nXLWHEc(tQGoEV=ugv-w9fP3>Q8&;0#Ak{8b2iKf|NI~TNY&JWK6M8B60T0Ac>kb>|+ zKxkSVUIeJ#Qvg~#FENs(h~QKhUWTaNR1_`*gs0^;bX9l-qEcQ747k-a7X!Zt%`Thd z3A+)6uX_-o$!kLcVIQJA2g813=)H+>01%!+wzP&&nj_&bG2rH8ID)8@qmD+57|mg+ zi31DXV473FPoOz%lUl>85rwa}B0|#|8`>6Lizv_Q!|RX%_qHKI(*|3*kx-i3!<&c! zH+O{F5tZ_02V+}!3o+zoE3)(zJ>d>Oc-n4DcMwW*XLu(u@a9fJdEVt6<%FDL6hvmS@#?g29OO?h=AfbjIlmOder=F#v|V&KiAg!25%!59la zCx+C#48I^2zGI9~o?kf{ubIJ{@$egF;Y%jMelJ!ta=6>fRF*UNx(30#PY{ zbTmFOgEy1m&&;BiOfo}izT{v{g}*XO?!Je=F_YdkMT|LhQu8Ax>!)Bz-E{buVB*U% zcT5YG-2G(*J3JT%Wn30iXz!70CP9-{EOd_-tkU_%S) z79z^?;<`o1fO`uNp=pUNT}mj;g>}n_0XG-b6(TC-sAv3?`kEK=QR#STise>NX`1Xb;QDVv=Pel21jEf zGkDWpw~1N!l8(A|V#v+r9IS11TbO0)wh|Lw)l=7jsFb%m8atT5o6fqO%%YccGDB*1 z#qj8QIyy>qy z&n$e&KwUpE>V}9RH@9=L?g*CD4cFZjOnTYFx?yISx_ddB_XYEDovD35Y zVfjf8&1l_IWX+G@cQSdD8B+5s2WzbEIkV*MW!(#A!ha)~yT+IyHLr5AUJI7gjn};q zOnTWw-8i#M-P;_^4|VSZ)7-viHor2L<|BJ<Ena*iF`b7EFG}q+rS2mmJNhy03z1 zYQNWgBliDA=s$O+nG!6y`;oKxQ#9pvy6%@~^}zE-2b({u>RW* z`JElH{u!*_xvJ4qeq^3%EiYd+a9SX=1(AiS#q;9GB1Nos3seKAC1Sf2v~VtrECa-P zxhPVoS~@Q`kX4Ztfbg_ZQN2Z)ij`LcCYNFMMBISr_dKA*v)4cZ5g#Bl1tWeytv!iI zK(%xZ8A%NyI7K31MD?a*BmxLeQCk{Av^m0aTp4<&G^Lc608`p9w?WH)h!qa9Ox-GH=Q7LZ)hPAaP(xF;9 zZ#R-1h~U&2*@-CJ)QJd9yKHDzWH+Kb?~Uw1hTeN5(gg@l`)uicLTT=f93TeX+>Pk5 z2+s!{jYG_kn#0P{7f91l<@JE+xMA*%oB%|>*9%%apEQuZ$SFW*Iukh!sNT~DT0EaM zl5>dQ)E_yIsNOUX=?8?T3pVs}{-G&ZD zZXn9@t;kJe=)EJ6AwYP#ZA ze(PX-h`b|)+`LDYzG7DW1Ry+pw56X2rFk;)nHYHUB%wTiaWJMLUx^_#-y`3Mh3}X` zbWT0bKOBvp%;3#*vC z_45GHujGRk&kGEspnf4BG%c=Q1gPFq09rgRF_NW-;8a+@3{kzQsJ;*oo|fCtRrMVZTUtXX&5`;r zG2rH8eFRY{M;(nAF`Db8CJrokgK16yKY`}7O=_)QjVOG*6%m@&*wD86wTSY(zJ47t z;NCVwXxd;)Hxf#7d;KP2z|9@??TAWwvxBj%ehV?=W-GGv6+QJGfbg{4mhK>w=Fa+^ z#K4<73FUd0gV9yLn;25Fw|)Q(YA8(Jh&e8p&})aO$l;fhgS6iwI38ZD?QpDMWcbQ-2y6aBm+XG@Z4j=Ln^_ zzy3Ti;O2q)enh2w!NIs(e~}n+a|v1a3cGX#eK$bTRfjxSe~lP;*C3%hUw1Hu>TeK3 zYHrovBo@45q<#odDc^Q9?l6Nl!}WKWg)eznKTHg{xtEi5pIMLVqGrJW|_M8#H3fjJSRGV>`ea18v4a2X7FaR{xh@aJCn?inlCw6Q}th&C3oNJ zzcG{EHN_06`9ZAtQEFwHpMoWI)Ahdu6JM5jZ(6YA?sv}SAJH_mf3{XeSj)YELS zoeNqx=SSxOqF>1eEuI$`NI`TVAT%wGE&^2VDF7{=ml(-XL~tsME<;prDvA~Y!qaja zx+=N?Q7Nwk2Ha|zi-BK+W|vL!MBRwO*FA{PVZTUtXX z&5>xB7;tkk8bMUbQAZ<2jOM7+#DN8GFwH68C(xX>Nv+Y(WIh)Q|0gRw2Tg&1rx4}&O!PD|;NCt&XgX_4&k;&< zfAl;t;O2p7KcZ5;;9y*iUL=OxTtXJU!Y*Aw-wlv-)gcc?uMq?98YGnG>kh_H^ae4c z=2rA3vEUse(IG^oeB05u!wlXGNAEHVU-B?IObofXmy>m$S&yS~_W+stro4s`KzMp& zOP>%*^Jw%bG4SS5LV14XV2nkd6GLiVMqdyM-!Vog&#xSf*UaF}c=Qdk@Ff$`abn2L z+Z?P9(Ra);b?=D@ubR~`fvA)}IvSst!JEnGXJ*k$CYd2MUvjXfqF){TF~(UW2-o%(IPT zE+RPPH_Ss6zMhW=O$%&jLBm2sd0yPG2pMp10U|Ulv8781rMa+S88P7IqJ~05rM%q1 zSk``S@;UORE)kWBFW{DJq>PR;9VX{BY_>MM0dEVe?Y-9#++8Z`83t!UF&`u1w*_?y5tziqZOx;#u!mD~3IuMoe zc1L3eGkDY4u#;Kzl1^qw&8{4*u7=&rlDoYPdzgvuI?~WZ47u5tleJ&4q^`T+fMD{= zx|wyXLGBLbY#tI#Q+pWM_(Gj##d?63Nk>V>?r}nC?rk_h4E%jBp*){-F!~x!5kqRu zG@K?DzN3#&p3gcO=a|8p{)Y3+!j}v*^b$hqMHYqAvM=?u!b6LFiY-kHQZz-zH6jmh!}EnJ16UoU`gF@!(G9ompyD4W|pbD zm$P|aFdsLV+6Tm@H#+4<==(Xb5tg6i(2O=bWft6=d3Tf}Hv1N$rO+~RnKzLeiLs!LCAS&gRz<^s#b20FX(Co5Fo|qd^ z___xXn!GkN5c46*b1>#dhTfZq1pwhGWJ_xZr8yD{69aBe#v+JHIqGP{h|wIAnmDlF z4VigXBJ=;o68{WqPN4*?G$J^)##SQ=ziUN=rZqOSEw&a>p4Z3LAp`DhLxiRcwsa$* zG`Gh#5d&`Sh_xds<;@Ppw%8V8$jw${=_`6-9f0t(-Inekl;+OZPGaEAorLnd%faZ1 z?IwoQ?2YXq7QEv~tP4>o?{hTvGlMtXu>;Jamvj^3SWIdT=42fbEV(-jOn8xLJ_`IE zG#|G~y|ELB!qv75w#cZ|e_5S8+6 zN8=7NcrzTk%Pf4!!`Lt}+8vWa^vp8b<)(>5(mcLMY9nv8Tkqn@0)d z`I&<;7JE(%sd*WDK`ea77@<7Bax`8ugE!-`H_XD9OvJ{CAvbSxus+1zG0W7wCnmgV zR^tSsQvT>@d}0P~CS#wOMK76ThSYq?!J3MFWtQB1k9}h%y=#gXa~h@QM^4sH!IHY^ z*e}7vmu2pl7A(2@&CL0Y+{|=;MAOv%g|_-TM_wbm70$D>WKJS4W?3`yTtslnZ=8qd z%!@PMux+CnEbMCW*uvk zyMsBKheXrV9!55}Fx~?ROGj<#aYAYCZ9G8?yt$W9o=-X$eT}DxAvI?jPZJB@(MKrH zXB~}m%-~Ib<9TM`O9mSIi6J)^aC3m+PZ!#0#HPSdl47s_TlXXY1q;9zJu3*y39ySg$%hcV=*}N~9j~h+x z17gD)XT?VlmGUD;;|Vi(Gurr+S@e=oW=PGm9IUa%=ggA3myIu&N$(nChSa>u$$BkV zQa9fCMlk7R6OH4{GIeirG(R-H6HIgap4t3L+{}qjkZ&^0N1@~2eG)9Gn{50nnEbs- z!IHZ#Ihs?AUj@_DesBCH*!<2Z!IHZl%$y(RW~TconsPhc_)E0urI~l9Mbp&&{!jKF zgKh5r!Y}^)_n&|NRVEHEhx2SBnTrTc`SE#*&QIi_Io~!du%QLJv|=Aw8ZqEcS&V62L-AcowmL>9inE)}Eiib!%fWKY~p47|%j zD9>I8BM|oyLu!I?Ke6B)iFg1}DTf@58fNe&5)U&AUy_VRh#@!8oU9nLn&Wa8M<%|> zE~U_S36jzdxi!9;7zuz zJ2B*Da}L(F_!efFx~;^7SM|g@5S8+FM`H&wc+(l*$t-$FCo`mGR}NNJd^fY?Zf|@K zGx1$V;$6g$n|(Q1`vptty5k1~lV8@&tYdMxJD9V1NHk6DVPxYA?b1>7T@Oje9dd8{ z1TpZgUP5_3>0tE5PZ2|E&csg>3*XU4D9>jdjdRT4O@I76v+yMY@qS{+&4nDS%khiM zGIf`TNw0FsSIGAREMLu`8H`_J7Tr9^45_)EgEbVt!7RDE6~D<$eAh^Ph!}EnJ16Uo zU`gF@{H|cq%O1vunPuwkL%l#1(RPkDOhs%B}a2A{#7td?f3XM!RB{PF>6kf-2KSe{3)7p zJ01Te+Vs-QRnwwrYJUs%{3glHw0{h?x&Mp5$o?0gfB%i9315%XY+E{)P@40b<`DzG zo=+&x3mlAsriH|in#E0vfc1ZgJdz3=^Abm6DKmIe*tCpU`rkqG;P)=5j zU`bu1DJ+=uvSd?)S*9+Uvl$c2<|b1cCpNv&DW}Ny36|42G_6gmnMF6ZGDB+Cu73cmZ{sEqq(hVi(s1Dt<1((_B3@6 zLvFU`WbF_vsq1XoDVY4SPQjA9T{)UvO}hot)b4HCBiQuLBTZe*GIjfMHusCB+;%q| z5N+wwZoxd(WNHuoC;O1WHus0g7xZGMe3X3O!}9SQn%<@p%%YonnISbNbFliFPBBaF z&NQ87CcUeV8B%jLC+nPGNnL-_dBLQY4K(#L%hX-S(Y)MrQ83NzC1n4<1pdDtnLNM@ zskxGqbycvWZm{W^V8VZYGnWktmfT&>(Hv^JA(*E2R?|(vrgx4s4Kd5q-Oky(BbstM z+;ms8`K1q=h6U5y-uqAXebIj0WbPlZFZj*5G>_OjBSP~e$8NOgsbKOuMg>dmp5%g<$hL#{^66Ugd1Q7EQSwZ+auz{L+c0altgVZ~ue+q3NAy+x72-FQlt; z?LG?cO^Ds6|Iki0eHLx$s!7o_wO{^&J=OG8w9WnZrf=dG(%n;{X=;D`C;O+tHucj@ zzYJf1H33v_%FfV<)m4aSdne;wDMn@_rIM*Sw1rt zqvXma>(`TTBksv2{p%%7AmPh4a0({;;GIMw@GrsN5Nm2wqo+tBtlGT){j($z$wVaE z;3+D$G1WFF@Erd~^8URE|4jYs6WKr0Ni$^Lnq{PreJAl{oz`u8Mh`VyzI4V=y-PNR4Fl#}=GqQ1mg z)|^v~p86B#RXg+LK%zg};OT9w%se zkfnM5+mV+X`Iq4DBi1}ojh;pmPgR?jeQ8uRaC#=RV~OXg#q-O=3q|s>?~bVkPOrrF zHE7{Ho_GUDUiRgQ#JFnd{MJA|B;EnS(|bkp{%x6+oX9qK`Y5)aKnv%|#AiVA)XS5g z#q$>fnM!;Ggr@I_Z-C~hJyWWklf?56Bl(F4PSc5Bh~{NCWnP~~gr?ts&QC&`Nq-3C z`R|PJZ(knxb9NG@x!Gj><|pSNo}W$ncL8Y%k_)p9oE9e+p?3REy_e z(yz$OyNP5V+u$iAwl$!Ib0irC#CkcIjHs5*Q6q@~(ww9zo~70f`kPW;TO_R-J+&rR ztJd;bRRgCrLfe*Ht6Ds-Pp(tMdbdqAaM~cY8$k=__T(l&td~2I?W(2oW&_!l+yV$s zTNRzz(v$4SHh9`DwmU!z=g#C#K=jLZ5MzS9f zoVt?-5QUq%0XdeW>7Xq=L@3XPv&O%Tsh*hxevh)|xN7v&n>?Xf>!n`R!0DvW_9aiL z7SCsrrxmf@?Nbe$&Wi0h(89Stc^(k!<$+|sYUzBzKrSaQ0>aZJMfDbGx}v-RFkLmw zgUM@v==TOei|6YGGL*al2u-(=HvzTwj3kFtOXu50at9HdhLd*@)teqBhXLW~o-MtP z=;I{M50o*pb5?33+u-Su*ggR*oJW&S0nsmyf)>xu3}h_%91xmbCSL%m_l$uS&##Q+ zH6l2TC*L5dH%%nR0paPb4gHXOhp3d_0|Rcg<~gYeWn|`$C_(EJA~;PZKO+jin?!`B zFE(^4`4v%~zbC&T1MZzdgr*;W&QC#_Nk0jtc{=%v7AW&atXJu8vHH>?F4gGClX9!p@;s`6lUHa1DW7Wb98CEY znRz#n3S=8Rg~YZ7v~Z53!hl#WCsPsC(m84*F+iGAG{v*j+ChI)>T8RnRimfY)N0jQ zUaM;0v_@##QfpO<=k=*|idgTqsRm9P#C9WS;oP3u1c>!=N2*=5blz+r+frKq;c2U) zGh2F69oYs?+r@SVXyM$M+6jn$xf8T_-en+Nsoj9kv^TW}P;1YTRF`V$yw6DXBZ5Hwl}Q#T;TQZya3rH2UR`Eb^-Hqzgt>II7&SB;)}QzukwdA+KE(@CN2OPx|Jp3kIC zD`LIdry4k&729*5g>!%EJRsJ~1F3%1()ogcTuxmCgr`f2>MhcAMR@~Yx@wpQQ`Z2| z?+t<$&({rPD0Kr6nr@|T0&49UNe!u%&bN)^4k9=Wr|u%EH$6-Z1H#iiTY4YS$0?p4 zC}U=4Uh_z{!P6tLeF9oIkEWgiqF){bEuNnl$XMz*AT+&9y#Q4283QezUm3}3L~t5U zy+KrOnn;ZU!qZzD`XTiWQ7OL%hP8E8^Mq>Y{Lx50A%fFn>NBEn(K8He=FF~XLV5m;jQP#j$mBoFkea`im6w;uOXoHJ zy94~rX3bpH=qbN>o@%WZ@>K(;1wvcUyim1xUfjG$5$oLo)xc?q*e(SvoC}+m0b;#e z)Lf`qIxjbnRn02^;c2C!dW$p_E3XJlF2n3;b_1f{^MDr5UIPg<`v9RS*z5GZ^M8DSxT0E~Y zkhbQvfY7wQc^#m7PaA0QyunB|B7#$U^Cm>~rjF)zKzQ10L$@_=K~&0Hfnja!Y3@)h zowpmw4n%P3Y~G0|+|-E(O}lJpSMzQ}dEVQ+2N`)Nyc-m)6_Y+EUck=;a;LY8L z9&6_Lprdh!8B%jtS^9#RX;!)?%QDkZFl&Asv~cciJ^_gKdqIomlLpe)dTf=esNOWt+z$v(7i{R|=8K3*`4TYTR?~b1_ycIZYLf<=uOSLw zA4G(v>o#<#`39mq-)g>z483=xc?b}mZrjp3gwj0Re3uw-^TXz0M5TPs(YQ~H$IVjn z09fz_)BH&JbJ8PdeqxhGo1Y?Ty`Fhv6cL)9+0e1(=ZNzBviSuv;NCGrXnJK!UlU66 zc=H=#z|9lQ(lELvEFS{4V*TJ?MBeTxjnrJ5bNcRbh~QlyxBmurMCdW(^f@iw)CVs zvJIZLi|r23!nrfO6A=A!Cus4!%Rsu)y8)qTZ+Z`))}ABjF4fX`pONfG1gGxw0Yu@Z zZa|KuX*y_24-v}q;jCe8q`ybi3l=%98a?%?k)i4jHuK}Xp8w4$$ zuN%lv`UW60-AdmC)Y>zW9#SoxZyU)SL~t5T-$hh!dYB#tgr|G9^gg1G(>y;=#>~#V zmXU0Or$=J@1hjA-O+N)hzdQzvsp7& zHG0Z#nWtLo%Y4O7qt|smd?u! zWL3)wKzLfIsNNz?#mXxJlgluBTHJu>_dKA*v)4cZEj~bK3byzGwe}=h0;;8R$Vh4s z!70)bMpSP~wnPBoDQZh&h&H$I99M?kDNQNmCBT$6%&je}0nzWZf)>wf45Y1PEg&?l zZ&?SZ-qQwJJZ~_PjfmjX-m(c%y{V(69T1*2+t6(-TM(7_LX!d!(fc5T5qg(*1$+aA{a&j$4~}upIHNLubulLX-#2Dx&5!^0 zomqIt1fw$l1Y>R?8matC7_yoCf4_xAFG;;KDGaUo$fkDx7b%I4>+*V3G8@Syn@*MQXd4v~oRK4l<1g{KMO>1^Q{LhU_0q{aE1 zk(>vDskiU~POo&v!%T=)zq-82k@r{@lIr0@k$nO_yY1cUA!0m9R3NBV|Qo<|GcGJ|d&D;x!? z<##T|$HMo_(3=ln*;mXc8Y4uePmc66qdboneqjb~9%oeMuP(+!;WuVz&5y$G%)&b+ zfX*tC`KPP#OBk}5Ec`7jdP!>Yq%gGR53}YLaVypQRV=;xXPfEY0E?zBo8ikK(@Zkk zd^Tz6oLMx75ZlirEza`{B&%pXAv`TCT0p41CyTT=FEWzFKrm$&Edgq8$|=ewM5d(< zbVboJpjuu|47$}cuOxmB%&QzyZqaI>^z~dIJgsq{c|~i1%Dld49T@iBf}%V^WZK|J zH!{j|e$ggo(9PS5@_}l3v#YU%89R!!W-GDi4W@ZJ@e5$y>5zOyg+S@+J|H}mIM85` zAE?Zsq5v3lZx9Gi6^=B_D9@3iYG%;Qv7!i2E!Vji%|%gW=uIP7_7z=4F+yaDJJJNB zJSU6Vn1P#~xPi?rsD zC+o0c>D>`x(u+*w@`&L+UO%2{iqB>Wyw7Je_i&Jw>O1%6zuy3>b884-lTt zInwit^4wc=ff;mjUr{emEnjpot`uEjhTdET3$JiWSK+%pmae(v{-W#5z+L@}%6!Ac z7$~~Q46V6cbcWpGw1w%KY5L7%6(e46S)p^paWjpE-5M2%|E;b~WAzLpGyD zZ-s@Ij1`SCLvP-Bus#;O7nZ5}z)XIXTmHnp9~1erhi1I!i?I0Sabal9R}a=i(Klh~ z-H)R0VE&&E|9q)DAq=hg>B;(~SXwt(^jk6M-`Lb;lZvHxe>|IiRnye|o3f{V_b30I z>6^NC>c6w6Q~GD7Zw~Ox>16+$$C@nP{ON{H3w;aVoh-|l+MDHDB$~xmV^7(>C00B2 zWsWaMwv>G~9sBM_EbdLC{2}!>k^F^$d&vgdU?28g2 zQ=>(vwsiSo(+y5>wM~$g&PiVzA@<8j(&D_^KstPT2;pg;Z!e+gJx6^VR?Fx8MsffM zrcU2Mpmb9wA;*0@9de|H8I}3Sw2|J(e;%`5NRty*V^7__lUAGdx~+yzr6&5g z_gyE%ey^XjINvak0pCqRc)IPoMQD1@kZ-_h`FzJn?gGIy=(`8h-t@>fNQg}L9q9w0 zPkb^zw2Y~p8O1}>4Ni~M_9~X>opTAS1pPgz)sr_mWV1&j@L8er+Ug zfM6Q+y#;D-8uN`3BGWqu`qB3usFptvBfWJ-@tD=}`IC`+27+na_XQ~3G!BHPuMTv= z_YJ7bKYZW8pnE3>nN`fwPe=NTQJyD#znNigPVJgxROUZm%q>PEmH!GuYyPFJssG)- zIDJR@=SV$#w%yLbs9 z>6degv#plTOATa2@iIbWT5eH$i#Dyayc{yEGR(Qfs|m5+%Ox$&YYZf>cr773tuJ0j zXnIdUah}!kd4rK`1cE8QcoR^2)3)M#LS)+PNVfppQ7rRT%dmH9({{@%Ak$96>?gR^K0h{+r$8_b7e50^Hw^>f>A3?PDSiP|=2yip!JvCbfbjI%k-lM+=h5P~ z%%GdcibsKJ`JIdLvG_eR^yULtc!iy2m5dQDl|HeI?q^1M9xwjF4E%naQJKHG7!$?c zn4vX4ioY`p@0egz=AU59EkPrde+ff2lf}P6~4%gpl;h zIVIUv%jcyAvZ7=eAu=tusJ%s-R$5*TnN}I*+>+IV*ze_%7Uwkvl2@{p5T4eTtRpnN zr=TRyYWcjuNHzk&lwYz5sJ&@hNj@PmZFZzvfbJ-fd8=jEJGE)M; z=OZo7B?b~K@e{&Rs3btBy(dUooGXkZ3mt($!`xkRk`Vj7Zqnj>%0PNbP7}h@*^)Da+IxCP zi}N`nIS&L=Z^;Fq_NKm)UP5HL=s>TOTmq`)%fz5tP4iXa_rZM4A@!GB2TEV>2g1`0 z2Rcx46R6C$OKyQ-?;R=`AVj7+j`S|0JP(%KV+P&)sALeRmhZb7518?!L~9-rD}6&o z>5$d(`LU5a1%hd~^K+lGNr&VQ9@CX3Z_-R;u}{SbF!*Hm80A^kDeg!U zjPjf;ZDR&*PBJR&olg8mXVr|L88_PAeg#KPXeXibpzq)lmqQ4Jq=Xmv!!RipnH3O z@N~|Ro@bQj-qH)qpqu+jdx2{CqKk2*^b#}l<}z4#g;Tl;-}SL{%_aAjUS|gG>St8u z8!pB`=}l&6&F#`#%%XP;l@0*a@*P*>t}tXXSb9%bc*&#EL1yU9eNWZ{VLd6;yN6)n zO-|`C`EHhfh^414dARf$GwfZd*M=FD`MHZRQu=}!TJx&(CA0935k_Tx?P|OchHOSl z-wF#a87m!ShTgpMV0|ooFDz5{ftma&xBQ8HKPK{L56yV#7qI5~@tss27lzh+^=V6-)2_csBp4rm6jxw$s1;v!65l z>8sN}XIqUuW%}n>ZQ9GU8amBW+ARNktHpVte}P5P?`ByIoffI>V$#w%+rNa6^vgN^ zY^&w-QUh7xUq*;b%Pnee(WaG_mqVsihB?>2nh^WFT+-sa#z6A?YYE|Ly?-5{={*Jh zJgepN1|!)B1XI3$6Ht58Hh(@LGHrIGTY&EH%e>Vx?48=Q-SP^^w9_#A{Dp+r@A*iJ zbBTcj{eD7t3i$(s+Ixbe#ks;r!ay)Z{MA71O)-Cj5Si*6XtO^GRLhOTNN?@($E=pm zaU)3p!Ibp30i~OgKzQ2iKs)?) zGT-*!0>j=r?G$S51KT0TEE zlBYm04f~$~rJII<@buh)j`&{ymHCzbB^Y$?2oRoLJJL6d@;vH)%M7}C%s&cL%kNx_ zkN)?}(3=ln*;mXc8zV%fPmc66qdbrMzc2$gk25OsR~KW#|BV@1^TYq0S$M|;&{<_N z|8zBe2}3rM{@=o)m!vjN3PWrDFl%lZw^Get#nQWfwwe0PFPP!aDEsd+HqBJq*`%d& zX4xD}v^k!h&|T~W3S zsFs%#gKjm=D~X>2^D2jwTecb~eLWWlPiq`#UfEipGOsUN2Zp`3pe&CNnKn4mjg0b~ zU$%)Ebn~{de4tw1>}qUb#*Q+r*-9*WgK6GQ`~sMFIwW6NAyE3d4+u{s4m4Qi2P$)@ zEC2@G8wA2rg(D3!%5$Wwni+I+tSkal%XKbBb6J!bdeaD&eMMJUj1ZaPjx@n2&&jej zX5i)|qcZPyF*?fjFhgthmF;B~z2j(E2T(2VcQp14+7GOan}$vUi9 zdUu4F)KxIB#b_NW(w+9GM=N##IMtSZn zyTA;(xv#7jsFp9f7+1s%DxMe z-!&l&t@+8UxdCpanqP{gb(3Yk6%#K@y*H^?diTe(`Bybf?LXU2|NbACx^qS_gG@8Y zZ1dTqrE_Lr4k5OmNm`ue8Aw)OJ|R3U3@jkj-jhXIoEI6%Vj!5Z151F~n{oo#gvhki zfvyNF1FGfa#GqSE^Gf39z`V*K}qUb#*Tp2Y$X=G!8C6tegVuo9g;6l2$a6=1Hw~@0}TfJ zKxGaE0$|X+K_EO;IMOhqJVyf6%%GcNfe277*SQ$YfhaTdrV%XrimpJ65SikRG{Gp( z$v_)3aC4GTnRmMw9f3W}(3*XLz09I_91U~;)$)E<WxewJk4{US>^MA%Dk|A0T^^|77(5mInu?9@|<11gc)>mPI)#^ zEiZL3R+KMehTbd(3$JiWE8)8wmR7ms-161Tz+JhF%Dl$K$SYsV46RvTzK&V+j)L+$ zpjzJGYHSpSZ1T%D2@5aTR-Vrcz1i%^+9IqS<$AXjOuWe{ZHMm)Sla25edUGBz+FB@ zWiD|sg5`c@Xica*z%0BY$f(Q}u0~iGvWb*e3kxral}DJNH+3GY=JKepOkE>0=~Z3j zF`!zGyBY~$$R=6dCMoBf`w1B#_}o#h7= zQ(o37tmEZ+cgVAOST#-U5wP(>r*sUy>tgAIOYSZ|NsPHc`h6;OGb-~b7o(^AG&8j3 zZ21{x*?;EL9X*W7e9qN4FAUlAmR}GSUeZ_I%M87_=)t;Deo0uS?lLp^Rc`qz`@T=) zYaW{Z^6SFloBM^KH8(t11LZe`rFXZ>ZwV9c8Y&-PhTh!qWZhLPts5-AreUldc`F|Js8_tm30QT|OaP3@2J?}{z&oKP&i`{~*IrJ8y>S^itKwM!>e)71X? zpX|Q|+uZ+~`eN$;_JjO)W^n5EssGNNPU)YS!8yP)r<4729&56K^QRj+EetMzcd{&J zYHwC>k!TiMjXh-tmssu8mpQ@g=?15zO1mPs%xd|(e43nQXV7}Gzd9#shA!J98 zr>)a8y@UVUZhf65JFUi^e8EDiO?y78p;L*{27`X9#W@rVSS0;!&}!&Zp|)Yt(m4{W zCM5lGEEus`KGzvYb1+JXOpO+u+R_z_O*c5j)iyy|Iwyl|gxD`9NsIGt1L+9vA%v%W z!M%j0_Z$s&SS_FT8_5A6m^y<8fznN#gd7j@bjXn&W>n@Q(?)tD|9Q-MAx%zLjXiY- zPg-r->$Vy?ol@GK;AyMH`E2lvMbhu~SPh-dsqJ~v(z!QyfspjeeZgL<nHA#crz8EvD9@9@-^{Q#r*=&;D)S#O z=7!Kn<-fwvnty3)>VNkSrSC}poGF^wR%1_@p*dEY{xZ{Q=rm7hvqJN&7UzYb1r|xa zn`Je0TBNp%NlWMK&=Nw@FXx1^t(MPA4P-@V86h$)x2U~En^sz04w+UN=G@R~LhSc) zNsIFu1IY`mC4{H-p>>3&_Y{Qktd`FkjASDaO!=WrK;Blx|7_;c2%6?Fj7wD)YY3UNG#vM?)Qi z$h6;)9$=K`&d@<-;O0)C$3rq7ay1SMLu-y$*7OAxUFim2g1`02RabC2~_6Wp<7_sdxt^;gvfNqk=|vL=fTiDX3))#LW4lH zeBaf0z>Fs$t$9eS^bIpAhOCy)kB#Ih5KP0NXF%zuVIVv`cc3Go7eHlx6?zE<-8%w= zr`L}34Wm4dhTbxRZXOGb0@d<67vp2-Ju~#?16X*4on}>x5igZKv5f9#MtL3&ePITE zKhCJkUtNre&^Kmi&5zJ`X5k$ZjLQ5IjJXwPr1CFe$YwJ1TUhjx)H{>H(3(G4>8sK|XNqRF)!0*J#T=_mf0=1DbegBMSrzlG7UzW(3oMd;H_K}1v`B3i zla|ie6-x+7znoK%ZMA$}Y9K2rmJuS;a*Ntqv}vW~<&bHWVa}~sO^E$oE@^RIV<34I zYYE|LeZ@LL(|Zak@~oE68;oQl5KQ?Mn}FJzwpHX4BGYC^x&`Qt3YoWBhP_jpwp(5S znRXgxUqvAy_Ip0k;#^`N!3sYiJcTL(gxY(8q{X?yNWwrcMJlR++M8k(5kh3DbD+%? zQJ`9GBu08`S4GTf`5ZTr1Q1NgiZ-BhQxXVIyB%mp#U7wC@2l7ghQ0S_MF$}=?RTUH z80ERM;vh3{b0^T_6*3=kH4Y0yYmQi!eStO|v%D@coiNPZ6(pEc=QXm1Bg+^vRKaW|ZggiZ9H-&Et&9{ME&n zsQAVVt@%;$omqIt1khQPGXHcnehEW1lNG;(MK4Kho)m`G{9)GIN^Yf^zlx=I|7>&W zH^6X4<@9AR%~adjq@{Ca;aJr@X1YaD1^X`?qwFe<7j0EP%ZCwH4X?vHl39R zg~c!FWXADItvTe$I;>cFcZ8VqqVzl?++`W5`4}W>odANVyYeJZ`dv2=o=!Q?p32ie zWj7^hSuD!yu~bf$57<}P%YnaHSP*SHiMP-goT$psvKm7-rVXL^mpE1MUm3nQMQJJ5+7$cQ0n4vYVDqk`S?-*fJ z=GU&q8)3+1wDPU6@RG60QD*4PI}g^!%J;%Dbsw0?uX4+u*!N>1fA-LfSAGF&ZW!N5 z<#AzX%~ucBMCCVO>D`aY@4}>iBdNP4grPM*Jz2jLOY0^pe=DZEY*MlG?vH2luWFjw ze`!1Y+dum`Gn~FU{d2a}*i&YBj@72UOsk>OJf+PF&$n8f7ls#DB>ird)zE2?+Abz7 zowLJB2uZ)36VA3;J})(p72#!s$h6#|_7-hgX?ZzhT4k7X!>b9g-^(Q}&T9-LFT9oz zp4Nxg5t`mp5YDq&K5sCRjX*Hvhc^MWH*E{&6C%@QN4f>*jeM+lLr&Ve?Eqd>LX zNR0H>u5iq1`5ZTr1Q1Nga2rs%DG7w9-43)Pya%Yv`@(y{u=gGfcMu}een)zMQJy=) z2bqDJJAob#%Y4YyI4lgUIbvD%1=@7X^18@$!Z3G-PZDCk*G*cSPZ>y0_%tCroeiHM z)ZWuWTAa@r$$21{dczlh+MD{qy@beg(ScqGUjnM-%fz5tP4iXa_rZM4A@zr^1EsI` z1L5h0104w81S<3G@GUUxy+h#vLS(w*NbfSr^I-TMGw9|=;X$BUzVB*0V8)ZM);uIu z`i6|EA*9r$$!zjJl^b<}z4#g;Tl;-}SL{%_a9&U1tXF>St8u8!pB` z)lFt-&F!jN%%XP;RSf{u@*P*>t}tXXSanZWc*&!xL1yU9eNWZ{VLhqRyN6)fH_fOX zB1ERgj`S&`JP%hrV+L*>W>n_qF2+dJ3ub7|tE!jG!aGJ7mHD-+@kSW38LfINEWBi_ zYLppz^Uj0yvFg3BOx*`&@~dc`RXqlFDt{6U|KhVSWHVm%MOgfuabal9R}a=i)i+`3 z-H)p8!sK^N2t#XrGHY%%w^Ge7#nQUTs^5xbk3}vLx}xeCTVe=XCPVC^9kW;Vf6w+?LAqf#d(pDECzxpyLt&wds9wz zHX$-Cb)YM%mjTuCa$?Y}rgm3smOy)$72p_ZC#= z5hBwDN4k+wp7X0WF@tX2R-F%2%bQ(|EzHtNlP_4pj%hpnHQrc&c!uVMck5R97>DZjMz)fNHtU#b~aMGDB|~!LqODs*VvN zQ{0gz809%x-Np>uoMcqy-7ZE)^&Vzu&A#fr%%XQ3t?mG-<^8V40b$6dv-+U0_$8gp zI9{zahdfz_6-)1q5R+bHnvW5`3+59Jsk{0lQ2Kf|5S~ss(4OkkKxIB#eFhA=w+9GM z=N##IMtSb7zQ7E+xv#nxsFp9f7+0zsFpvu8lQzBoAK%|!s3^V3qxzZdax#{zX?n4 zepG)KCckTf8MA7%=BFp?mttw%Wc6>w#LH55Oe&V%{SoHe8fm7wzp80!|54li7l4}d zturDSFwcZUt=T{@W!B6AO25kl!qYqlnpHC&sLTs%7JxzbW&z=8kt1EqD9_n7OPE17 z=hS2a)$&poV@1s}X6Vgwu<#0}v=Y9{VQH01&aGL^4BVB=sLX3zjJ%q)%+Q+kHS3r~ z?uEs`T$R@vLld$lTZ8iDK(3{PktS!RYQKNTT!Ni-K(suZ+fTf)-*;iA@ z4BX{oROS*FBUs~ShSr2?0?fiYf{e;s;cA41A)81|wXpD#SWSc(dQ<1YYOaY2%hWY8 zlU~(T69cN{xT}#6hHR2GZNlQ0B!!_hyFFMPHG71mcl&Dg3KQ=-TGPP{z1i={I-pou z*I9E=G38~Q!a81~cZWQihgH+m9swIKbV|p_ce5g0ES+%4-8CnfVed-4*3GEQr(BGl zn$yhCnzJ=$n1y%rFe>voSL3`eWYb%7L0EW6UrjGF^yZ=m>q^ZfVVSzi%;Zie3yW{=7lzi{@L&zp+!U7H-LAPMOuTETW`G%bbH|f)SFyBiu;!j(^2;98 z3<}HC-S=!hP|PParuHGT`HgP*G5dZ<7TQ$#-1`GbF4P)Wm*lL<|%DfWWLqn zyfCuBBI$RttcFgD)OImx>6{%|LP+}MoJh9S@_DI&tcWZlM5g5ywYO-~O3TY3(<;N9 z8(B?={a!9m1!UT3n0=8#LhSc^q{X?!K!OoJAv}d50YdFPLDJ$}VI*N7m?DvC zp!TL%BtnQxbq=&S5(TQ|Mq;G5c12=V%jdX}B!FN_M%sYVO-Ud;?RKCYkv%|V-WS;m zhQ0S_q=OKd_B+x8jPl$WImis$+zIq}MCL=T#$jP-%@ND8FVLoAme)n56Nb4va*`1H zy>8Ote9Az2BBu%A>1^Z-q4u60(&Bv1NX`Sn)El_~)ZWw==_N#_iw^Wk(?;VN^5F*nZM|zi0o(CiMm_au` ziVOnP@_kq10W+RNwB{kP(l=z(4p}Xq9~;S2Aee?D&w$cR!$5d??m$N(FM!JYD)JHx zx_1N!Pp=*68%B8^jl5+B-8>c<1*+wDF2={mduHg(2e9lbX4H-mBGV^F`k7Il$0J{u zft$w}mHDfSF%kL346XSQ`OYl7V*==`TA6>k8oz`go5{#;VbM!cn6}?RhYOfc2E(5CN<;0*{P4i0P=fJ$mA?4Pt21;Mg1;W!B2bx#A z7O2eYYuABc?=7g!BSfYRj&viVJm=SLVg}v3tu`O1mN&Z^TbQwcBD@k<$1XF88dM6FrzX*cQHn4Uob;!Ue&&27Tz(! zsLZcjjW@!O&1mggVc{iXwWG|?n|B_pkG1cGW$HdKlV3&ithzC{l{Li}O4K$*P-A2u};^77%Lh$s#Sz zi;QG35KP&1OMu#&a_X`Pk!h&|T~W6TsFs%#gKjm=D~X>2^D2jwTeli0eLWWlPiq`# zUfo)tGOw>&2Zp`3pe~OPnKn4mjg0b~U$==Fbn~{le4tw1>}qUb#*R9z*-9*WgK6GQ z`~sMFIwW6RAyE3d4+u{s4m4Qj2P$)@E&vAI8wA2rg(D3!%5$Wyni+I+tS$mn%XKbB zb6u1fdeaD&eMMJYj1ZaPjx@n2&&j$rX5i)|qcZPyF*@q@Fhgth)$L^#z2j(I2T(2V zcQp14+7I;}b6$vUi9dUu4F^di%IjQCwJpKwUsbti$+*Smr6bjpGD z)SU(@^VzyHV9>oiKzKUmNY69Mb8p=RX3))jb-h5fe9^_YQg?|NdUF{pyuvA6h41=U zy5^Gm>#j2ccl9$W^9>hcpzbC!wB~l*EoRX>hUx}@YWa?D@yx?VB>{hX|4Bu_JxTD9^)n&zOOmhZ&Xmxr;GU_ktN(^Q!J8v+#}) zMrD5OYP=DKY)0$e3JWh8s~cs8-n{c*eXM&gEK~P^ne?g|^bgN0W(rIqkq4oj_hTd%UWNi`Fj(WY@3MSs< zl(xfn1uX4!$-eqRX5cO#qcWGc7{Pi!GqfgDA7B>V5oA>63Rfd64B15LtA&M^#Ofo= z(3?6BR&#w+Sf;L#ne?iz`WR3x$6bwtFl3XgZxa^3Bq@|dQxDB>{WD?F&8c^X zg`qXiJy;|4FNCFcuj*e4lixKW46S+X$$Fz$S~pt%Rx$ZyWA&rLGIj4fnjh=mE2g>q zAZ&T1m*$grXH026d+f&Rzc6!dl)sm1#uZENzIrq#>c1(bsr^y^U9s`+D|P3DV(Hya z&*m@H)Z5AW->R)$I;onb_Rs%h|25d={-6DY{jWdDG&5@dS?p;xY3ZC9okNK2XOb4@ zc?Oadolgi)3!@7NwfAI^7UxAqvKR=a?C27p_NJU@HX$-Cb)YMv%YbTmIWg!~)4Y=S zIWVtsNV(C~Kom zAUst#(lDbuN21ltpqpdS2v9B8xfspSC^Ph?5iI+Pu4s%9nc|K#!6?tkXd5$dbCOY+ zce@xJ(LK!2ntjo|%%XQ3jdlRl@_tw2fG}j!89gX0en}@Yjz_iTkSFV~V(HxxV$zFD z^D*Lg!F<9Ybw^JErLT7b;pvnE?TMZSD)ZUs88GPH9w0oObEM}P<+(R{ff;mjU$hsf zmM^*(SE84gp*NSo!YiE8Rrs!trE4y^KYE=RxT~L0nQyol1JRqz(3;!PTg;+&3`GZk zYWa?-#Yx$nt(Agm`*y?Y3zeN#rm5Fs)>cBD@k<#{;zj2XCj zm{FOZyBH(U7tGL_SJ9Wu!aGJ7mHD-+@kSW38I8Ub7G5$I9c6~zyz^jvjJ_9^sr$f8 zdew}EF`!!h8UxdXk85f4ueDz>WM8643?|wwT3zOe9!HiiATJzJB^-Hm| zZZi5?G4Zn09g~WscYlOAw?Uez?yqW^+JDqe{oeoI?;IHoQ@75DWkhkFX(Y3OV9IQm z1C+j=352J44m7J_K2Vt#HY@;x?#%+i(;`Q@m{Fdy8+Mni;q&mrl@ZFi{4StkOx%D8(fWz!jMgV z!zN+jCEFVEnV~nEJy~0XwWC4rwt|T_Ii>CJT>(owU9zvCkQunk$EeIDE=I7y&kU^z zH3XQ2cLW)gxx&>53qv-MhH7EqC9#GGGxVm;gVo#+6_%-MWG20;t04wd%W+pDAq?3h z8`^}$FG&hRYj%6EIvVx}OYinI>=h>7b+n;_8G5tdlXXC`w63$^pkm6)I)!z-LGKQE zHV><&sXYQVxv;T|5|NHM(i4pG+}&`J8MwKdQJGJ<7(ETAnV~gj8_qBb@91Gv=5wyb zd11(=x8Z`Y@RGiUUS{acMGw}MhD*XSb(fjRuX4**+4p@SU-QuPH(VDM-`p<@t-0aB z8fdsFEWNwka7&nY*HFU%GxX+;C+n_aY29GMJ;mggJ!%*fmZ`h%*?gdwPZ~_^LuS(( zXEY80)$(Ik}t&8)^T_D!n!q;>&x)mW;|*UFQ@%H@SbF!> zqdC#=O)*XFkB0AxE$^IAEWP_F%(;!yOm)9hQ*S35eycXWH1+PJYMR69`Z99B5YKe4sKfY+L{a-J1o3 zr$vr*F{3At*6j9Rbu{h~mfr1a+$&7H z>u6&KGxTP^C+mP>Xu(%0C_486JN!Mf6TNm!=t zGBf#AZuu(vzE9+99-98f>%!uj`-P!3H#}GajW>m*cefjF2@~%cY8+sO-rVtI-Bm2D z8*IF%nEbLwjf286b@x4+4;1rBqp5w!YDm0HntD6g z_*=F4rKzhXRnye|QS7-*nw@I@8foLuAq_Y|2IkRaFG3LhT zu2jloROWduMpn~&W@ydArUlHh|CFgavKW)_Ab;n$`+S@76c16DHnO(3Hmvz1iT& z+NfAsm*2EWG5KZNn(~EZ>Na~ew>silukEJ(?X&dlb{u?rYks*!<3;O&!8Ab^AS=2UJsUJDU!w zwsvW!VjgcYwTJ#E`>??__ea@y*@B(3(>ote&RR!qU65 zO=rOTzZm}cQn^PMT64~mbzZTwuD9ueV$#2{)Mb55y}~ke7d@I+nl34(xxFlGd8L=; zs(7bQX|8$f`kSsRro5wHvGneSM{}U*red1f+fBC=o8LLqG$1TfcgM4NS2gu^u<4#^ z%S#_M4JxL&z5hSi4^;a}levE=zK}P2X&#GrhLq;1$8NaknPSR2h80Wio_jP$nqDZT zseRS-QnBToBZ{SWuRWV@R8wz9o8GFnymYK-R58u%yZ^!d*z{hto%#>#i~ldi|K}>z zj477hee!I6R!zMfZ~CIz`1d9}f|+OPkEJ<;?{waxvHrtj((+T9bXX=;D|Pxdc^ zZR#hRejC2fFP}8n=KjzB{Ka467f$5g)K^pgpMT`PGhMSBhqp)!0*RY_-*fokcSKyRaaZH{Ia0L2WmZ zmd^RHO@w4jzq~D$Z?$~hY$RI<*%9Mu>om=n-obxvx4ur3omOK{zF48vrahn4(5Xae zgE7C=;v9+vERr#OVbE&mRH3$E($YB+t0p94`sG+GVzqp(Gmz$3ln|L3Et>J)mabTA zy1^-~wh7YGIT>psB*S_+Nm`tD8%RfN4ROHalT<71F@Tg@N_$Ni_nbeJwveptL5_@Be@F%(_ri#&p-+WAA}#`2#UBrnk;$9m1R=AUdHU%{e=*AQWb8LHGOW$1U6YK;{0EG=&1j_Z zUtws?zqB>IKZE_8+02{SR%1_@&2y|a?PppIo#rWRR`YzT#d%@#0*j>I&9WLgEmGUX zq@{Cq^AbYRFXuF8TP>fL8pw*~WrWDI+@kgtZCYu0Ib>R8m~)#~6Jo!YOIn=Q7)W08 zT0(eQ-@J~{^qzv|JgepN1|!)B1XF(VCZP7FZO!?F$h6s!ZUMTZS>~;lVeizY?Uq+S zrk#e_*IY=5{hp7sIF}emu-Q)tPod@jq4u62X>qPFk}wcVk>+Zk_NG{KgbL%&c*oH{GJ(l^8qZp!cMc|W5i3PPb{PRnNgm{o4+svzaM8* z=C3ZsMDsUhXw8r2@65tGCK#3ZCm3_%Xr%HlVaR5(`M0p>C8>8Ng`qWnJXwDgOYi=r z&8gq};_0i>KWB<&w$<2EW_*s-roYUz8amBW+N}6|tHpU?e1S#M?`ByIoffI>V$#w% zJHCXF^vgN%Y^&w-QUh5LUq*;b%Pnee(WaG_mqVsihB-IBnh^WFT+-sa#z6AoYYE|L zeS96E={*JUJgepN1|!)B1XF%|6Ht58ws<}vGHrIGTY&C}%e>Vx?48=Q-SP^^w9_#A z;)R6R@A*iJbBTcj<9r6T;Kk_!&a& zJw2qw`J9oQ2ZE_LegUYxsW0A3h)fq9=#}^-pjy6647$}cUnPDY%-0-JfBZU7`g%VQ zo^CkMf%r|JGT)Bh0>j=r6dxc&raO-GE~7jT#_utMZhjOW1ghoxuEqmqJc(<~Lt>?G z$Y>d|T0TEElBYm04ac7WrJII<@buh)j>KO8mHActB^Y$?2oRoLJJL6d@;n-U%M7}C zEItZU%kNx_kMZ}+(3=ln*;mYH86!ldPmc66qdbqtzc2$gk25OsR~KU<{*4)0^CSM9 zS$M|;&{-`q|8zBe2}3rM@!!Itm!vjN3PWrDFl%lLw^Get#nQWfwmJ11U?QVs`ZAbi zs_ksj(mAtb4k7k?nWV*eo`Gbw%qN7Wg)IvRwfAI^7UxAqvKR=a?3N`!?M*o?*@Vcn z)Pb&OSq46miN0F2ZSM;&X$A1;+J$X<9LhK z9P(rxRxG_cLQHy5dY+N!vW(Px3=*|Y0KwGVauO*0t{VtXryOWc%W0r8pKUn<2Ho2O zgr{?k^gN?H_qJSM2Ho7((hF3}7hQ}iEti;~HW=Q$ym!MGxX-22kT?YdtsTn56t9Ox#dsn`!SI}duYa6zJN71f$ya9xG=Qls|RbM z<(shd?nldaVbZ^m)Lj$8(3+o~tY36;oa|saSgV$FuoYHBIfmw4MI#pZ%Pf zNMD`)IooRNDKjz0YSUh()zE34(q<**TP@BD6ALVoemBc%=(I>}7n7FG*@-2Dq+iZS zWLqttmm0{5#4l5n;P46j4 z7OCe9FQ@97~e&gYEe zJP=I1i3>pOO?`=8LS(w=K(8b&0oC$lV$iLo`6}`IV7}&%`V-fI(%1We@N~n04kT^@ zmHBq!78v&4p~L_oGTm{ccNyh*FmaC=bn~OcAW$vecQqa`<4Hnm9ug~kLq_Y6)$;kV zkvs*0X*lr=DBUy+gs0~YbR_WtsLZbtFTtRDM}YA3+L69tl;_dJTV~MBV~J6qT7KtZ zd`!G&hTePt%f4bp>lh(2eR8Cq8RdCA@r4<5zP_g+S@+J|H}mIM86LAE?Zs)&LlE zZx9Gi6^=B_D9@4BYG%;QvDOGsE!Vji&8<;p=uIP7_7z>NF+yaDJJJNBJSSV*n1P#< zjLN**#pr0=!wjw2*SeQk^p2yg9YD3b-_~xPTeaqpC+o0c>D>`x zS{Jo-*)5xo8OaGCn7Ug}0;QX}f$((7f%deX1}gK})-zzxy*)s9I_F5wGs<&s>jh@e z&3&!CK(&0)#kkUXi5Yrx87#cQDP4u{`dGT=lKWe)GXr<^Gb-~97h|CHCNs3=cIz!> z(L07(2Y_n%j;nE37_u2`y(cWZ`jkq}UNY7?$_%}E=fV2e z`d(P3?gKOVRW#3P8v{F)KZ%Ba@mUzM8E^d}EdI{8Ftp~Y2Wz7Bo3QlmN9%WC^1CL4 zp*265HMfmhspgkrY29S&Z^gvRQtwSFmfrpGZ2nbEQ~S@hr+)uWX0%P;3DZoqolROg zXSU5D#C|W6v^dW*kgT@(gz&VmZ2_V7o-EShyvRrv1HqKtwgjlXDW@%)5Sf-b&=qaV zfNFU;G3Zv)yps4iFt2h*xoxX~(${l=@U+H(=C!Q_D)aibbzsPo8U)x@0(L0W|bpX}!eplmwFl5u&c2HRSl1^qEZ_}DXo~*-) zrFTb&NiQuo58kw!oo`)wGA>uZ|-}t9ti76o8CPH)4nOAeTWd59y`*f zjPg9(_KX?0d6-d|pSu_%Z7-OiHLu!UG7Ik*VN~YVuErZ-$Y!+dt+4Qtv9?iW=*>G1 z*2lK@!ZLLqm`Sgi(LM%L%b#40&%%(+c-t3Y@k_>qp*3GUSQBmEgr#>s+P({u-!;LE zS?yZ$)06c}v9xZo?YCm$WvM$R6-)2_2y>fX`TbkYM&2O=7sGGz@U4xfbg`)kuGMG=j`?+%%Gcd+OvUbd8v!B zqJ0@N^kz9&c!g713E$O{BeASa?aSJ;DsVsqKd6zuj*=#0o8Kc z)kp|KHp%ujVew0n!qA%C9;}Y`J;KtveeHXNiFX}s?_h@B?Du3HP%N$MY(J=&^0H20 z9dFmWL!QmUs%dJEfQ=VArDNo~S;;PzPPpXm_LI!8ccotIW>n@=E=EuLX=Z56+4eKc z!aI5xmHC{jab6g*>21FtEWD(zy_Xq!bJ2r!rTvnyOx@~hnPRrY`!lfSCh?tA9u|hyJojLYw7(FR-o0vnDNOn|lDca| z7+Uk%ll4Ziv~INhtzz=a#@a`PW$NB}G(Wb#S4?yJLD=$2FU=?M&Y04C_SlWLe^E?% z$GBqY-B*w1MEf_zG_^n4zcc&)lKjt|Y9i$uGTUnTywpHeB$p8)({hX2TeNAV<>ioRm0`|Jt|r8OFPF49 zuQ8Ck_TAy4;XnIdUGS6!HyunB|0>PA@+yvC#v@MxWh)kOu=@y_nk}_|#411?G zZMVDvGVL_XzGNXG_Ip0k;#^`N!K9xMoqPFk}wcVkz_Scds8eKAw;G+ z2ilyB0@ZROG16PRk}<30bKFQ0KrkhfZ9wU!BoLlmt($!`z)bNr?SkH)(M`WgtDt z(}eJJHhG3ndruE(aXx1x=Ye4AOjy~`-igUNf$pqn2h2Z3t&zN_(o z8Bda0^N?8S8!~ncSuLL*8_823n1++jfYMFFKzMrYKu3}eD)X6Vfaul>>49PrcaLaGow6@C%-TQH;*$a^H&#R zBKeIOTJt0MomqIt1khQ#Wd7-D{1S$2CX>H~MK4Kho)m`G{9)GIUEE4Fe-%sb{@G^w zH@{u>W%e{vZD*5~&Y8RB5MsZQNm`ue8A#Ty`GoMaaMuDt?LAqf#d(pDECzxpd)E@6 z_NJU&*@Vcn)Pb(pwG611mlK0-HO(uDp9AwMhm^Z(HBkC`E)bs9IMBRZYk|tVe%CrM z?7aoM@(7V>gCpI@D9`!3HZg;4-nJ_rsFpXo8e5pLW0%%!B^JHGG;b$<0n9rcl5bZb zQ2M$L2u~#rG`PzTROZmG02p*{5C~5djx@|D&yii#%%GcNyCOifT<2mm?}{=*ZyLd} zujtwpBSfaSBTX>Mb8=T3GjMZ~QJHtU7#+LzFhgth?b^#MddJaS9YD3b-_o~*-)rFTb&X=5)l>=5)t-7NJLmfNJLmfNJLmfNJRU0P0p-!yq#;EK6m@a z-Z%S?XM23VpU*na!*TLb@8^UiJxM6d-M^nA2E4iF_ijX`eA>o1_xl-Q$jw<~;VrDv zdGuTlNf&H#@9!6hf$!=il;=w}M&Iw3i6J#tf4@R3xW~ZneTYi=nyqo28NBKL{RXq} zCU<`CCx+bI)Us|d>)!8jcN>}JPE#BMfbewJlHMnj=E2_|5Ch*lNGQ(_ZH%Gc9}z=p zp8WopSa^>iLV12_Ydm8HZ-#$=&Mdsi$nV3%kee48*6ZJ2GE3FHA|~Am=4p-*WM}dl z*3c*3GJ`jxzrSM^J!g~|QuAKJ8vFeNv*hm6?;n{-_Znk{)O;q^Ob4|x%@@Ivy7Aw? z3MSqxbKbaM$=x??^SfxO+8?H!`~BZx?rBa_#dbPq;hgW70f>1@K4|egOF;@8vjL%L zu44|M<~;?V#q&HRnU4rgg^mS?nl}|W3IXA1p#@#yScIsQ7Xt&{s+yMqzX;9CEK;#! zIim3NVnk?KVL?kAD-q>+wPO`B%zMimC4lg>#*(fjl;%>$I%2?^H#tfXmGXL9V*@d^ zIHYDHu;31=c{A|K(7e?ml{>Z}3QsRbgr@Blw8F6iQJ!}>b|M4bTY(5oyDjM+LTRpa z>?H=gxyn(AsFe5F7zZ8ui6J)!kY#QWa#R7r(;-WGm{6Ll9Y=_PZ>}bkXNQg9b~uS4 zH6DkHSa6T9!;Pqvy|#vr8N3NN{LG@81c(uJNKH`7Ix1LlcMOkh#@y; zk%hOgO6SpYJtSSQ$-Rz?#K3p;63X)>8>7#0nHW-Y)p3PbaE}2;AEHveW@}t$25(2aLTWlfhasZ9}${nS2`2a&ub4I#+XsS*q?VG3i!z`8;{Phvf?zO>fObX3?8_nIScoG_1aw%gmCyt2I}c ziT4_)=_7{RT+_0y3zpRN*W3_Hy4jtYerBn3YNbM7EBq~@W9HB|G6S#tNJ<}owrUPH`~nx|UUGr^L&;hN`yNjDp*8D^HM zd!cE*u6Ze#>h=}0`Ib7(8+Oi!(7e^`Mr+;?bEcD?muW@?OYYulnqxH|1XI<1s`)6` z`1Q){IVMJ>{tNS136XsukglVeN{9MdwI%wgX z@0F0wM&$ASyz&RTbn&vv^0BYV-09riHQk+TpGo)%irCC){N zN_jCb;H|28De#NXyv!mMJC`F0PcKGn#JLhto>x0pA;Y}4%vk~mPirjcT0&_q zb*>`@ym^ze6j3R!w>35pV~bO2HUbOopqe)WzYNV=EmFC28=~;^aztp_Zb2)YI}qi0 zmvbjF;Jp=y(6rl-4iiIeUT9da zoiCZC>Ru5OZZ)NL1W_r!u{GW@gEynjcg&)jj50%N-fLK6&JWCzyHC!K%%ppb5o21d z)O^;mz6h4ojXS>zCf+Qw$GBk0-8W{=tmS5=`!1TQ_6M{le(!hZIrD0>yRvzzl1xVg zr~KL(h{DtJ5us_81udwZjVRA^Yv&*X-dlhOP4g`2d_rk1tX)71cym#0A)-=VXk#p? zT|^AIS&S^ag;iRLo+~10nN2RPT}}*qS23YHudp#nYF83NYF5{-A{N}EthNMEDX+0L z)-r=PrM2srg*Vw$TS^SMS+8YnVAhsex!Z_LypvVhjGikaX{${xuiZurd{;T4Ja4x# zDr$ESLuz)_?j#o8qk>SLciS3!n8BOM+P%!en^e_S5<_nGX;=qq_cKe?9Uvy$DpXsA zsFV-c8i$#|o9fyl%%YoAGec?|8kW1($t=0^)Vi37_X^j#i6J*$Ez2iZQWvQ83nt$z zz^rJk+y%AGqoS#5k0Bdu=n6r?QpA$R2&Fku8z%<7IYB7TNgJc9Hbo4nIbNG47T%+a zP@YfN8Yh{-o9^0E%)*=W)OHg?Zcb}h=W5R|OVynvCf&*|pC`}vuzW$I>8-uUEP8V< zGoS9eZ-KPYg*QI!IHZE+8csNH@j2Y&n#7UQ`@{HnD=T` z?QLSi9jCYk5S8*>TjM@6cr#f0fLU~tL1swJLk(-F_7St>?n&)qX41Wem?1S!wXA1? zC3VBK&jpiiHc~sxELHbH(|ld~QZUu+D`xX8aWl;|LY~PqZ-kCN_g1i^ZnXBDVDj@u z1xxPUYno%V9|Tj?eyaT_*nH11!IHbr%$(`sW~TchnsPf{`&G2*rkQicMN`#&o0R=s zVXONe@CozpKd#*7Q`~uIo{AE*rXzw=zH0`e@VR_MXqsg~3tY1i<$11a4l>}q1&Giz z&yvn3l;%R$0%E|Mi(G|>N_nA;vBb5A7;>{1S$GSpv=lv8MA9;wTW0&%14nJ(J`L-jYd^D8-2r04twOFUM5TPl);P=z-c-AeFpF+d%?zn=XjpESlUZ`-ak-d@ z_X@k*#E=`WmgN&HsSCLLg2^`vFe~bkyP&ptR5VrXF=XQntx^O%7a}QUlM}8uG4Ndp zLU~Tw7+tOuF{I|WD@`oCM;D4Gt5$TXNgI- zvdibm^F1tI&}e#H7nwzG?q!D5T+*=mT$h<8cUN6kn2GlqaP<*GZmwxr*9A-J`dv2! zlWum$)z2(dcT?NEC7AbIs`fUq;f{HA1BgobuB~yO8N3;EJzy5yWRMwB^H9SYay?>} z+&ytUW+vThh#6AzRLgoMSW-9adM=oBvk})YvsB#+P4l(urC_StSIov+PN^FqhTOc- zvfc`o)Q!5{2`1lcRIudky{0+l`XHF9_LJ+QVDml4m^H0V?mlaqUqn-G$6a4Vn{Jxf zYFso`?Ki=mStr?<_PfGX_doCx*}nk&{HsqL-X5o^fKGGgku=>V=hw|3hIxACw0uH& zo@HYc)XgS_)Xc4$LoB>U0iit4vo+>3gExhB3z&sBDXJ?ZhTJUFu$I&Pm^-K&BbQnOpj+9Oy}S6R1LFzIGhb(PFgb^A2UgLV4_Q{5h5Hr_H+S49lDIizJB z7A&c&t~(-_e6wo7k~@c{>8^7MrmFSSxdfZ;8Lo3POVxR`O`mAWZJ^FC+R~;0!Hm|a z+Tf(@qY7KyA0toDjqP%TJRf2?rqLwo;>eom#^+>mf*Dei)UdkhQp}RO<8^6f!dE1- zR~Iv+=7g4YQm~}1yY7@=(#?A6x|yZwPHURy>dpwJx;@KmzNJoco}JSpG#50x-nxr| z$@l0LEV;X+Y4+7!7ED!pweE^w(>(|3`k1Bau4$XsMN@A3>u!iP-}FvhzhJ7{o0GC{ ziT1rZb$^>Z!FSea?y_?Rgyz0xH(2*TF!>&Xf+cqkHO-;AM}nzppVU1j_J7>;^UgFw zf+crPwasUuDYwIQ&qW)*qM1!c>V^eV-M*NF{kra@Xj}EKgeRn}b-Ophc_U)?b`tGq z-8<2iwi*>pRr`Jt_E_Bq(N_1L>OP83NPCZormFosDf^4UR`ug`UlmWtn~y7Ob^mSB zPkdKCVMTuAp343I{URTyx^tgV?&EZ$F{ga@45Q6?`9=e$SwdUjo^7;vp6i}tkleWi zMgymLVmlwSa4vK&03>&Ek-N}n>AX-umbe!I!qZ}dnzu;PQo}0((=x?e>|PFtd0sJS z@w`GoO57^}p=q^y6`;9$%G@PJOXoF8vKA4XO5N)aHE-JFE(L_A^_Fx4qFdZNZ!`?^ zPHEa~cx7PPs+h~&+W;}oD+eu}w<}16dj}vi?Q-t~)V!wxw0PdFBzq9SsnWd{QS+uM zcO@V^?X#c<-TM)h@&RDvZVkDsjF!%al;kiXI90okAPR4)MuaAZ1$Dcfi1O@lyO3et z8+N+^;mK=BeT32+aQlgYZw??Db@LpwHI6bvYK|F}xq&oA3@-$xm|{-2LhiwI4ZENGwmGNL?Rbzeb-dGCO`4-lTNS<>r-(%kR9K@52F9d|#X zQodyM5lRp{%mV}VFqu;-CvmnH_6;Q&J3yfMy#10YGs=5 zf+cr9Of&bJpU2$HoTiHHbkM>%-!lUc^OSth;(3;W6nJI>LepH&96-%`3P6kJc}g-L z5u6G=3lKGLD)JNp!qY+vy2P^xQ7JD52E0`@F9m)PnwMFmV$X6!;pxSQ(6qvWmUvbo z%JXW^DrA`VmU&75;c1N}T}vp9s9aQsX;FqC! zt3@jJY(o^DUXBP&+bw8?X9uD@@AB+K2E4Zd5t?>e(mjOIT>8G*^3$5Ch*_O(@R}8^i5!5<_Y{9v89T9$}9gQ7LyoFWFixyRFusFY9J80S1^h#@y;k%hOgO6SpYJtSSQ z$-SP7#K3p;63X)>8>7#2nHW-Y)pLbdaE}2`AEHveW@}t$25l3A+m6*1{nFi-Q2AUl)au!cVImKnSm^}J&i zJ!g~|QuAKJ8uNT$mfU^vd}JowYm6CE^O;yPz0}GyUj$3)#ywvJ6K|F|Z(OkC?whvx zT{Kng57W;5{_i#SG^eRzI~}xe&iBp$#5^S*w0NGSAO+spfY3D8I|oqno&wO~d7hHY zM+B!r?*c^4n~J=Jfbg`?f-dncLR89&fdOw-%}aq_gyv-yso1+5QFwYWA~dbApe5dw zi1NJJy9ycRy=C4KKzLeXN!JoebE$V7G2qRcyrqardA+T%ff!r7QnL|Qa0k`A8Te&r z-fEG`z1t9lrA5;oX5K&%3-kkpb_mK!m2c{G;JbPW<@u70(dWHP45_*5y+SOw$AGsFQ7K=uHLf#*H~rol%)*=8@%9r#Zf zx0rR$D|fe%Y3`I)KL7|%cP;6CLTMiKJ|G6Zd5}<^AKDm0-bcicnkU}J#KLZRthmi0xjq;A~%RWR{pnLWk@OYXigb7nm^Gu?O5 zRJA{#o%;)bFR$L%mCRF>WI7@^<=4+Z6rP@s2u-srXhHpKM0uWDKL;7`-U38unrBJp z6H0So{Q_dZn~UlT5tZ^n8)HfRB4WtRVr1bhtkP2SToFmjY;tk^a$?}SiV5X;g^f{C zzmgbIv$}p2vEUwM^(BZ(d5x{HmKnS$tzXA1yve5eQew!>dM#@Mv$oXB-9}{MovhMk z^jsN9TWxZA{WfCYyUGdWdAp5KQNM#2QnRamC$aDz6@>D<+t%2_4Bk}M?`0O=q^iD> z7;>{u!#Y^MpINHz05RcKq53LBrF_WNILr**RM#J27Tu(p8B*iWu-x@dX33qW-o;G3 zSGe9y47u@YSw6v%x-%Sj;Ijv!xt3Sgm zRd<${bSt}jo;=^f@&%2ixBeot=*_*%keW*xR$u*PX35>v`YX)Ddkxh05kqdSX<63= zOX~XTZwMyc>`r|@vsB$pZS$63-m6!&w~0-6w99wV^V56-EZ^5?2J0U%3*MYLcaRxU z^H9SYs(-{RxqDLon3;61A!bO;Q!VS6U`gF@{d2*jn~l^DGfUOI&@^AyzZ6V$`-<6o zOP%HoJ7+{_-fDKE_3wx|(?`$CG^2tgckeaLvHA~!scJvfe-v!|dS&(;6D+y=tZjY~ zO}QPf|0>$jrsJZiYQIg&{;sgq{SWgA^RGX`G}UK*F6J~Hv~bS%%>cyo^FfQ}Sqf6% zn+*s}bA59FHSZ|^EuQBo$$Ug`D)cQt)V!(4R|p7C3oYmp-y%e%ycihpR@J-|_(f=5 zW|4}0%MpdA7b8N`3JY4|TZt&ot9`4GVcuKjD*=S3HI{TOp){BJ))52VyvbLJsFc^+ z8XJhQ#V0izfdzL^&6|N=hUTpnsob{>QFwYeA~bEcpcTFyi1NJ4w-Xug-U>u$+HFbq z5K42UZ!a<6%~ifiM5VmX#yIHPPYk&^fGl&1kgp05o(@^k!-UdY?K?sYd~-FSJUeU* zx6erosqy$+#DaT-eQrdh?6oy~%-~JH=Vun(BtVR)Pilf%)=|NdyJNtF8>!|9@Iz>h zS)_z7jwn1mfe1}W3)mliaP44wwBnG~#mr$NB*%*Dk%fyhHtG+A5f_n`3`Vf`!HCy94 zGkDYQyTL5H$sJ!mG34f^mUW9+_k4198=2-#c?|=A@O0Ob-Y1miLEi&n;F|{t<@uqF zG30wh45@kIdrU06#}J`BKeaWUF@rb5zUR!sn~eB|i6J*HG_2RYm&{UiuZRh^n$j?W zsFdH>8gH4wn^E68X34@Nz-!KDFcw#;xG|jT01r4(i z<#}$y9AvV{Rsf_s!TlpreQHMYiDX7Hx8VI8yZCYu^ci6J-Z zwX6-y+R`9*8#KL=25X$pz zTVoG1cvIQ1msxm|s)kBp$jv?t>tMrvW~sUZ#DrUg8mbVL@*!K}Ff({l-Ef3ibdzdk zNR30oayK}cC3l_%7c=o*;RZJ`X5aptgBbG*#^}WP=U; zAxKz?Skf4wG$$J3#K1Qv2<16xV{|p7h#@t{8`8wWdvp=X^9ftyBr|x^-EfLoc$1!n zZeqyIX$|XK!x?6&y0gTjTiNCF%epRDQrF*bLon%PcN+ScrRr{Ko3{k>UW2N=O>DU16#oFCQod_z+-C-F z1{)qQi*7Q=45@jjVGT7rVwT)JX?V;`y4Mghq~@uX^-Qp&Zn)vOVA9P-8itvr>RxD? zuNz(prn-H_Y`!IKruj$6GnwX%(DCQq3YOH3HoOx|e%`2H$=!QRbFATmV5-_r4Ic%Y z?>Qz|a`%~;GyUAmbYDbMZpRzGiZ~KbC3b=EkJ~(d6slOp)?oz7Z3y9T;wlARLTo& zj3xd>#E_fC$iiD#rKRY(B9fNbZ1R^9LvGeaok%@P*N}JJhWh8C2$>siS#K3oz6Uy^; z8>7O%gBVh?%fFLYc#jG~dERYn>|q9PD*bzzg*U14R}w>R_GwrL{rj1v>JAVSZWZ!Z zAu8oVw#H#*@TS^-gjsZxYGz1{L&I|Woy?LukKe^iyjR%oCWhR2wJe`tNnOD27filc zfLT$$+y%AGqoS#5k0BdxXq6)9xe!S)o1E~+iGlA*5Xy7X#^~~=h#@t{{b^$1J-P_x z`Gl=;k{P_|_Mc)F-lWIhO$@m?tzn(>pJA4&J4;Num0dnhp6_A#f=1KpzsM|lb1yTb z=8}fh=fBJ>xx4DW!c4r^fWMCza&t|~x-M8!*YCd}m~^u{{(feux|`bOEy29!SGBi^ z4R_3I96(gccWsUP%;3$S{{ge;CWFk7nui+JkpB_01LZ6OPQtW)@z#^1anKHs@+Izx}#m* zOr9@ed8Q)tD(ybxpQcm?nb9zs#;H@ zOR(vl;YK&JRGnAb^oge21{(dMEo~YQ%xI&k4Nl5Fs<74lG4cf6*e*xV^V0$$mSY-C zqA|`acys351T&;2sbO_BrkEvn#~ahkqbe_G2`1gFr?Hz^s_wL= zd9Lw{V5-}*%;sC_H0RklJwkIqv+HfVD42YYUcr*POPXe1<7L5AwO1Rj2sYhwps|lx zs_vS$d0jN+w!iU)X!A|)H1-Roy1h9m`<7_mYgG5Q*%N$co#rk(XFzD~Yj%T;4~RK4 zK+nrGgMuY@4>ir9#z%swYM(Sd7Hs@_W%e8rEV+BCZ9WrCxgBnNF4}z4k;Y-cRJSiC zVZUyCDcV;3E8z)gYu)aRaNda6y`4lm+W1birL9IqQ`Nqoggw^yLA2HVr^b)$iT?!n z>yhckL{rs%o|OGXVXOM_#;=Me=qo<4`MAPX_unS{#CPQrR^*5Il=-(mVVW8+KQnWh z4q7|4I28sKAZp%J6et9Qr-c@D zNnjD8QeF%Uc&ln&3j888FSAI+f#rz8(~A+IX@vzX39Lkv=hcB#$T06M3zPuD(;7>< zmQb2Y1M7$ZZ{8FrMO4b`ZH*1Y*b?elY96*-2MJP}O2v3JB z>0v@?t_~a_2EMtPP@Ww&hCARShSYchE@Htw!T~p;Quf*!K4$PH5b!gLZW16yG$1uW zE$gUY$=xwv!i`jO1o$B|$1GAJ5JwcAoCKzO=q zN$(R%^I+fsG4RcUg!25*#uy4bB8JpF2|Oki-eZVRo}bzp&zQlR;lOid;Y~&Y!^DuA z7aG>v-6TTN*iK~&0bY>l_f;LT{@9kb{rqs)++_Zrq%-~+Sd?o;3+GwEJq z#F*A3HJ`PtFM=g?ihE1ah)$#g_; z%5R#1C_FJA5t?RM(1NDfi1IwQX$~^ry#Yc#};{rNoe%^;*^jW^HMbyN$@iJ6Wa8=(#eIw%X+KrftN)ca;;$^L87f zqG<;)q-IysPGaFbDhTCyx2>^<8N8`%+RH4wNmWxNG2~{ShIO!MKeJTb0b;_fLQPeO zO8JnjahMsrsct&LEV@ZGGo;3$VY!=}%#u4#lZ%;nuW*x_7;@v)vV4Lib%7?oVDilZ z%!)S2T~OORDw?YH7_z~J!4M=YMJ#EIP?{4>abn<`6NK`dv@yDxQpAv&<4tK|;XS$t z<@toIagrIl>25m3EWAliQ#Uc>=Cp=&uIUW3RNYx((yi?BdGdS@%NI17-lmJpqBr+4 zLuxK*Sba^GnI(5uo31bu?={fWM+~{Sre$3hEUD{nx*?c!vpY@w%u;nXwar_Cd9O*; z-X=EOaY}FiQ7PZGHSRNmH-k+Nm_;`kWQNo{)Ubw{9x+Sqo-{pXCf#d@8B+69%X%hQ zQa9Z6TrlZoBTd81Qgtsh&DTvY1ykL=Vm99rH`9V6af zu;lK&ra9L1K`>SAr>2jB&G#G=EV=v4%$Y%MX1Xt;DYxTIUqzd4nmKn|G*#`lN!i~O zwz~fTpD_Ra6NHSLciS3!n8BOM;9h3oO{#*G#E_eP z8rH$!erBn<1H^<|g@RRxO8JnjahMsrsSX}t7Tu(p8B*iWu-ri>v*gYbbTJd}6%M+I zAvazv%O_Y;7YOXsX&{$i^F5r3iX1L{iKqCxUTe;JXrp@|?6W zx`HWUNX_wJnpk*`E<$-eVQZXZ25-89ru zdsx1p(ewr{GK=2a%M7Wxq+#_1FEdN-t_H6#6Yn(;>?4NUT+_0y3zpRN2X6=_-Rw@V zpINHzrnY%YFz*Fb?QLSi9rKz85S8*>TjM@6crzG$z%07SATy-qp@uaSe8eoddlG!i zOuE+)Go->xK`>SAr{G7y=6jAYYg)71ebzR=h^E|*2fvCo-88e+xM-@{ zZ-PCuS+XO$@1-+dPL@ zc#i@?d7fu$%x4B~3Y!-&3vW`?Tu2PLS*T$xX^=2gtZdzCep5JPU(Xjy9oOX^CS*9j)wY*TY7vsB%BZF7TQ zZfRDv8;MPKw9A{x^JOe=)o99_w=s*}T+R%s*{)$#H1A-R-0f=K$xOOe1v8{(x0ba> zu%xcCd9Ps7&8nI!nWgIXX_^O{_Y0=FJ-}?dWvID|7;=aB@>uGigHr+Ga>}Hm#^J<$u(UjXjvtP8OO#^}%ZC16xN!dpgwz@w?o}e4s z({8`Z!FSea?y_?Rgyz0x zH`x3@F!>&Xf+cqkHO-;sM}nzppEN%fY`*7^V9DK6ZS$FE%I$FTbJ6CTjx-Morn-GG z3Hx>POVPIKUkOi0TkCdjg!4wk?(HPn(dKueEp0U_nyU8wBnmQ4QhZ*lMcc5nO7jDM~Z&7V_LUsbvj^!R<&^bhnZOS}AUpSQn( zeyyd?pMK8#RJ!M%>@%}B_%naz;jaUKedX=>UHlxq+oTOL-JjFo9dQ1QeCC+_F)2!I z{@GfeZvVWF@h90ivju%U|1Nv{s?UeN($Z(G?(qBLH}(qJysiAxPL0%vJipdQ>NAI@GdxUS!-#65;%lvlw1UICH zZ}+Rt(YsCe_4(s(`gPNPxA0dw^SR64Kls-`Wy;V0ISqgR`Hj7L^ah&wSI^$y&q!b0 zUv-Y&ZPEtv>;8A$>sNoC`mc!mI!(0n{q+ZXhe><$*I4>jp=U`?%Ku7!^?CX?%ll+n z{`yI;mwc1-`N-b~^iBDBc~5yO)d}(r(&s<9S4;IOPV|5N_s>4^UwwWf?^NjV-(Rh% z{k#5u`@H=Pf3TnVG7bG2{ayC>RiBUEXDz)F6CHiG{`>l5{!;osdAYwX(bwni`gQx& z?*sjJjQl>zweA!r*Y8jAbHT*F zWa(+ClW*5I<>&ve{QUJBdu{0}Lo@$s*c<$r%)b@-9L>^G+~Ma)&qT$m z=g&!&-0{7B_2(&lO(wplNqbBC$Uph>r*#_XRp8G_mfT7E{_6AeZ=T$5RR5Gc|EkY_ za<7*BE}VEL|2Y%?{>gu@{6qY$P46q9XX(F6zxq7=nW==L_V4TS@84(s%D>P2`~Ld({q|ec$tTFIe6DIY zm96gS&t`NByUc&4p-*r_YWQpQtIpB8P4yn)uk_z_uV4Ln>c1ixlfOEArL?;QV>J^!lD ze{!#u{4O-V1JYNMX6fG*ccjl%&yt>$Kf_;rp8n19KB`ytpR(s)_4!Zk)l$8R6TS4m z-T%J6(sys`*HL=SR6pPUQ{NYV_505H6_(zq>i2Mt(4Rm5U_XKW`~BDIr!M~UmGpYa z?`Zkogw#r%>ffO3N_)y%{fcu{XUJPfKc%XFKKS?b{p-Ka$nT-aw5qSPe1^(a_p0x9 zfA#s3-^l8334i{FfB*gW{r&IzTm7E-zwrM4r~dEGU;nfVavzIB%MmZmCiCM8(v*Z&W*a!I4y^*`l!Z!uCirm;Yt|Z#IhBUi8ExKw zKbNx5rci0N!P9!N-C(p^LU`WzljQw86aIH|_KAsZYc}ORmWQ@wo4lV-mS>asaXV=$ zLOZezoOXqFX4|}<=TsO@F7IZ|9-}d*%Fte;op`b;RGDq?v`=UchV~mRoeyM5-hcNC zg{pog`0)^H4jYX*RfmokZC>`IYNLUZLulP0r_tis6LJ|O@8`MUkUQJp$t$)#(84(o z@&l4*oE$LPXb8_iB{_-+O~-!Hyq`C~|3Q+Mc;(M~+s6Y9=3cseb#=R#+UmdXXw0cMbkS(@vM2Q#4V*3sZC~iJ(c<}P=!!w|ex5rJ>dQ8Gx+b>QK?~>p&<#NH zvM1jO^&2gnZz{Hlc@(sGey<>7p$~x2^eOZa&^+UwF{7Op#`9+-`GN>e+ zPIJR^&^ZN$GjV%Ccphu!8;v;?h8Gy^#FItg!fb=5g+jX|yvS(jyf{m8r_zs0jVE(t znbDY2ad^4W=DcE~fzt}1EeWqQT0E}~uQJHQxn<#!Y=fsYV!IZ!a4rq610;9yrf{jz z(s{j-Yyf0Sn5KW^F9SR7~T&EPX`P-aZ4y%m2L2JNNf*-7S7e-BY>DE zSA!PM4h32NQGtZ9`%JVl{<2y5?=EsDU`N=;rvBSiFr=m1Hn{prXBQp@s&nENZ zEYcK2W@j5X&5g`K=M)&u#1;jSd90alH0D$oSzxpiPZmWAvkjgW3hk1}BBQ1A;w;IX zNy64^NNiIPAi1AB(lnxiqp4 zkle|eBBe%4=k-dm0gx>bnl@%>?hg8Kv+;C}Y&9BlDvxY4+MHKzG;rE3v=xyZMvLcN zk(~y~om*ivaM~@ldq4~4%E(?oawk_sDvg%T`xNA0WIrH09Wdy`EulzNw!zaOu{{i0 zI9ErG0Aik84O%=q6vQ2I0z#7~;sP{xPdMT>S~`1`#D@q@fruYbcvAq7XoRMqB|S82&Uh3LHq&$kU@;?BJ2K(@itU9r6n zS~w3z9spvVJP2AmKU9#R$Rj{#dJ=gIsCmy2Xz~11NuD8s({SWDqUKE_kzqi1dSO9d zM_wW-%rbTJ` zY)QWmO7nQ+D>2NQGk1*>%JVm5%#30qlfN@VYJTLb%x?g(yy(w8z{jbqnQk=Zlpmd8 zw7C=VjRsD$gtj0$+i3ATH#)~4xpNDQ22S(Dc0Op~To_#dNbcmKXra;4d7*+Vi7oW(@Q<=GQ;A;Y{k9CZW2lh=~^2&Fj?^%Dc%96&T0o z95bwm4W`6G*#=J$v5kQi&WUIo5cA{&Xz`p>kgjM75Sorh(}0@ybb%JnCzRwQA~r%#%y&_O z)_p{98jL;sW7&{XeXX5iWO!XJS`O3C9y?D zOXtN|k~@`tTxvX-Bg>4&oQh-1jW*{M8x5RR2yIDhrP1Pfb!?SECeAI3m1G+{tr6R` zpoMd3Y#kuElQ+dmjh4>qm1F}TTVgbA%+lN)^y6mZ=^WW=H0D$u+h(*muiR+hv|VT` zVmpi$&%0tf4U#*z!f4>MTWt4$7S5Hiy@2FSu8LI}EuHr%$iditKzKS}(1}|@v8rr? zr$b_U7_@M%jvWESJh>XQcy=g=JLUw0CQr--XzreH%x$!E_9}@F5u5@sKceua03gvA zO+ia~lu(|JWsTg8^kc+0AxC0HV@`=!+-P%N!f4=>6xyy>%4qR?JeD>{?%Xb;fzt`G zJqcPkcgIcvk~_I4)@`(OKCK|8wG`Tcqi{;q`#&f@1ECT?E8DuNSm@lF`Jwu?y^HU{xh6ql>vFC`IH;u%G z0paO|1$`ZRiKvuc0V8+ol$H^rrSlsld5Z{6qp^30!kb1Bq3OK^9gBTHl;=;ekH~=c zjsY^Qg{IGz^b4UhkH@|e!@N0j*Epd(e?!L17HnklcVn-U9M7Ol?ywNbsJEdu};gx}Dt70y1*#?MtUO8y- zyj?*mT6O?J)2^1CfSUJIfELfYm1GYhI90anMbx~hs-+STp7vSLgDv|JmGS{#sTvWQ92V5w;zX2ZPm2o~=Dpz-Hy}KDEvb)CngcC*s%Vk7)zS?pH8RoqMEq#FSbj^}pCzR&?mK(%?H{WULM^wr;ZH-&RxYr^zw}F-0 zVM=_!Xz6@cN$w+p(_qU3MBz&2X zym_Q$7*Q#|urXe@yd;L)yh0Y`J`xM>F-9oQpOG;$j*U$I!VKPww|r$5+$3|(I5VW?o0j!mu;lJX&dmJ&m&l9% z+zNc0%9`m$V@~<;8Ah8sA>U}=G)rg;;NJ)GpAT+IxuL3l8 zPg%UgXz9F0N!B8QQ)zr1qUKGT;-!G_wBC|#Ky*u-=Z%J8-YHF+4X+GLTNQJ8d>bI< zdF7zR^L7QPi0=S|rd{!!fSUJIfELfYm1GYhI90~?B5K}L6|V$@r+pUmV0=HKQa%8T z+^wN_mC@4qkdhom1gGlw5k%ol)ripKu%Pa^6H%T$aThYod&6-zAUt_3sgF>a193kw z@XY~4qj8>tw#HFrNX;?BGB=Q>h~b666jRKJcpMP(yaZ_RoK%pmcnT1jj>pr0n)h^p z7SAV?e}i-^M0dl8}O zk_GLHUq+PYtMMzyFz+3R_W{DwHA{M(P@4PWH;4gmz7y|9RLVDPja$UH7nhpbz{>5A z*E(RdbiS)3_YuKqF#Z5hc+(&vG(EJSL-9w5^86(J7#Z;1Aw+0;YDu3FO7n31IWgeP zBk^HGrToIicpZO947quQEOUz~ts{W&^v06DC6wmT_&Z|Yn@0)d`Mr%X7XLsDsreND zNG!a^7^2f!dH!r`d|?J}#^Ya^1vkmuJkAWM`9`dnt<=gi-vvwVewb$NH^A13&88&s zz%&)iCZ7&kIOn&{0L1k3L5t^E3R2KI8xWf2w$1_6yr%%Pc%G*u^AW+Ruyp~V=1oPd zg@Ew1(1I>$U4*EV7Xt&{s+yMqzX;9CEK+gnazx?j#fZ?f!h)8xu0)jQ)vc?LVcuKT zS^@}9Yb@znLTN5-T}KRf^QP8PM5Vmm*4RLdEv-_s5m;~s)w~(_WoX`Nk;+@QAqr0~ zM}(&B7PO*u2ckUhYTbzpcy9$FH0`#edkCeuvUM*p;LTO7m554tpN(;_bw4rW<^ZzH zEkdnTfbew4k{%|M=IYiX#K1RK6Uwv0#&EYfi6J$fRu{409^qCuqEhzS8a`(5CeZ3< z7TqL3jA*OW1huTAf+csyfC)EJ%@M<&mI$FaW|0!DaYS>cXU<3NJ$(`1IV#v)+E$bGu z?zPI@ZDit|tkPZd+yF`UZSr9217OTdz~?h*kWii<+89HvkBA{PPg)-n%lw=(dkhiE z^HW>n88dh@-1?kZc$1OVVPeS53k~aa>q};-x>v-cTiN9|MW;I;X&JChjdr%wx@b zqcNw#!~&z8c(N!_m~HU1P-vGV78xy_7iUTCRQhqL@nnuHGa7R$PAoUtoL6i#a9Sa> zC5e?ri|5seRR) zn~kS)WUJAbQ+Z;W(dN8zqk+?Qp{+>lFj_qCO6)X9?%WEafzxiW-2+-US0?rXk~_I7 zQE9Yv-lrf36Z-+->3~5eZV4r-vJIXNiS1#~!nrze1Q7G&YS7}@p&;&r6A+p_2^XNb zd%_8~(bCzgBtArN3MBl9!kYqsL=!XxE$LB0c|MjkayQbC5#xj$i5ZPKB@%I?&3Or< zfm2dwyAmm*#q;q*+90`eyNm`-C&cz7XyM$QI0Z=V;Eky4nc)o2I6L;pd4P+ZU-4)yWpoQ~b;sGG$$%CN9^Fsw0N<0FDrYDKV zfSUIVffmnCmE;*BI1MMBBWm6>k{AYrrxzCVb>bzWQho)D+^tjEMvRuuZa|k~_JmthO{?2h0h+s~tgXao>AXfs)*^yaY1=wP&6_s0l>)-kdP}+i(JgH}Z!`?^ zPHEa~cx7PPs+h~$wgFqjvxwesz!t+hXr-FIT7XA)8;~k zd2hJQ4G2$OOX?$(=0KaD82IJ@qR}>da7ZHW0_aZ{mB@5cub{SEgueM!5hI#KmTOS}iU9+Uu38lHe?FKR6 z&3D@R5tZ^yTjLfn?zKtHZD8egn35bYS~}lVlKY6@G}!h4QFzlJA~Zd;phIns5aszv z+hb(FdxsFA>8T}sMkvk0ZO@4TZysqIMpVi#Y>d}!FNq;HuaJeeFw?Z;2=FrL4awMj zODN5wZSRPIpC2WZ=l3?oSlb6;NX@6VkHo@zj1kK7XJpJwVk48kFoQSaZC{xMH_4nc z&J3yfre%E>EV=uUGbeukOXjx9eVodg=|*Et`Nf{kb;Z4kgjA35SorB(}0@ybb%JnCzRwQA~8!qYWNdYw?3`;#|_0dKyO z>_=3}H*Jku#JHD~n%lt2?U2_#V6=3;t0eak!D%r008x0;AR;t9w4g)DM~L$LB>5N_ z@ZKRrXnJZ%pAky)aPm1Z;LRh+VML|;!p3-=d`S$sd4()A66yvG=#)7p9dY-@aB25-ibUzr6r$=p2745|4>teNf9 z$~4~vOYVM{=EQG+sl4{=W@wr!w$nii=lu2=fSBjygBH)T6r`YiHXt<3ZJz_Ec~1do z@jOpS<|BerVfz9^&6|qa3jyJ2p#@#iz6en%F9rs@RW&aKei53NS)}6j<%q)5ixHt| zg#|5XUx_HstJ_y0!@Rewy#x@R)>zWDgwkBvzK$61=1uLTh)Q|At+9a^TiT^&Be38O zs(CZ;%h0^lB9*sqLlmA~jtEWLEoepi4n%q0)xHxM@ZJhUXxeQ__Yg{RW&2)Yz?-Yu zD-o6QJ{#j;`+j1`%>iVYTZG!H0O9G7B|S_i&DHHkh=FgeCX{D~jp1&05<_Y{?Ji=$ zJ;Lp7M5XMtHGItAO`zS+EV@a67}0jA32IqK1xxOZ0TXVNo2R5ghLM>gC_yWR2u_Li zIHK^m1R^vgEofJJ3Q?Yqx2KT-@9jc_rW2O*B%w5Sx1S;gyt${n8&N5rwlU7NpCN|a zoJAJi!YZ9d&-IXW!6x^%UnB;;tCvuoFWDGc-o@ z3MSudT(IQso3{B~G*#`7oSpmapM0E}%59zdINfN>DL*yCXmeh^(ZFez&=#a-8!eva zrsfzVcW!~vz-gY?&Ic`=3sVaK$(>x3Dl}R;FI12vsYQVBwAi5LEz-2q@QT2+OfeUy zmIGp*R}5M_uTYSZ)Ji~TTAf-2Xzre}REg2jd5w~+MFgkP)H+1Xn>M9N0pV%ACEbAN zmK4t$4a2-snl>9=8JM;z=JM1wK+N;XL5t_@3R02U0SHaIQab@P@2LPSo_8zB9z<}e zOzlO~ys0Wx2?$U7Ea<`1enh2w02sMjL#ZmGrSl;rIgAKS)u|(h!kelQp~+!E-6)_Kp)?0leq!L81BgabJO^!!qs)++V}@mJAWad&3xO%7m=mcu zAm(`q(Be6%AYG{xAT%9Mr2#eX=>jdDPbkSrL~!a(okG;SsVCJ92v4Ui=(*GxM5TNd z81Pord>;5cXue>PdQ%q>g{Su-LenJ++LyYFD9=|@SCC=eJCN!Fgr{qk^g5w5_or?U z1KxZm)sLu@Z`vBSh;c6^HMfD4+aa%Gz-Z}wS4r+8g41B?0iy7xK}2YJXhDZkj}Ybg zN$N2&;JrhL(Dc-jJ|mRo;nZ_tz?(->!-z`xg^lq#^^zEJ^9ot!7E?M#0O9G4C4EaM z&7-Mz#K1R?63X*?8)Gc>ff!QrDfN+9c#kner*-iB+1B{N4Bm{VzA_7LlDT=D8B+6& zSTj4Qm1({UmfZa?&CG9pU3sazj-Q*6X{y*x2Q8fQJ7xf4o|g|=JkL^)f{xjM&@{JW z4xr{e1)#b(A71<@L7424ZaK zkeZFaf;*_@&A=~1^Hz&g-mwi)czQV^G;Oz_6&*Ve<#|`fPGrD)D-fY+wZk&Qr$d(XFrhS8cN`%GzPXxEo*g!ZyTeHg zsqu8Uhz0iuceoLive(w|F@raO4nMQ#CIMnZJESJ4WgQhPxjP0-W21D)Y{?u^k{BX5 zB|74W!kZF^(3G^GT^%Vzc|P8eMh3jM3lW-5SkjY((%ju~iWu|HGurWvS@fJyW=PF@4Qs691GD7rQ^!YU(!Iu*AvK?gH8V}EO!Gys zq;9<9t6<{IGUts8mfU^QHouFes{LWwx!?cO6MIhS$^+9>Fq?cjXyKfno&kvI=Ytl{ zvlOHtJsS|3=BDQWYTi=-T0GBFlKF_>RG40XsCiRSx)2ba7Fy6H=|zZ2c`-2Ht*Ut` z@QcvA%pw)1mm>;KFGhr>6&AE4y%JHLSEpAY!@RdFT>=PCYb@znLTN5duOkM$c~iO+ zQ7NytH8v1qOIm6+0t@b-nl}T#49#0DQh9nCqVV)`L}=P>K`YWb5aoGSdM7gAy%mVi zwA+&IA(ZCI^j>1Xo2$~5h)Q{%jd3u&pBQp;09oc1p>!1>JRP#6hY6**I(>u~_~vRt zd3M+s?zEE_QsYUxhz0iur`?E3*=uX~n8BMs+RrSyNq`v9wA2K(tfPV@cgKJUH&V?J z;D^v0vq*__98q|B0uh>$7PKp!LX_v@=`=FnyeFQGhNvN8J7mx&=YSJPLB1@{<8_aQ3f zYqrL9X7HvzeS=welRN2tV#v)+E$bGu?xp4KHZskf@;V0q;pwg=y-z63gXssvz&8&P z%JV}TV<`QI7*g{j{g_yIk0C;NerjtxV+L=A)6bcOHyKF}6GLuZXjre)FPWw4UJ(;+ zHKlU|Q7ON%HQq9VH>2ry%%Yo&GDB+KYgl9H56qIgPw9`$qooJ{he@EI8Qamw5~ifPq#?6c;MGUDq-kBzr`8j9y z=pvNo6Sl@lX7HxF^Axl2COw_q#E_fQ8rHeaGt5$TXNgI-vdibm^F1tI&}e!)FEWeX z+{+B9xujwBbzWwc++FRw!c4r^KxZE@ z!IHc8n&w#N2f4r`VeGAw-IhONpZ;o$~Xck+I zJ>~kASnae5v8R0BYOBq7`Bp=xHA-9H zTWhs^Uhi9Hk$>+N`3j~RK5bCjjijY>p>Go*nU}Zu3au9B%|^0?kR3iuTc>Ge2mah{ zeVrjYt;U{;eY>nS;}u&Copvj2iEoe9@_CpkROvgE zLS(wU z86_>BUm3}3MtBpmqgsAXjLg;<{&B0t`J<71VuYs&-)BbY zrU^zceQ}_ZzORhR{N4AB8FcR?A+!9LemK&fKrv7Get}_cPVbrmD)Vn<%=L34o&N|! zYyM`efB(C`KXXUs=SkV6`}JFp`ao@KosE#HhV#o4=3{nKnDpEsXB)%e>Vx?48=Q-SUda zw9_yb`*#syzgJ9JKJPY=68|1TFzxg2CDh(iLRvoWH3PNN$ z>qyT5#a!t>4+h^{$>>$T%okjZi^9;FOO`c#L7*zru<450UL!4?tNqsrv0ttxEuU`~ zh|hnM5KMmmEkf-*KGO0zU?f3CcnbSNjM|%`{xBgjH8{|iKfA zNC|%jqxAIzBbd4!Xv&{tROSJHA2aN|!~PT@G7UP?J3uiH`R{^3H$U_bF{Z z9{aWC0kJYS%m@ryEzXaOGTmYcRvBeJmLQg2LFBnsLWqn zj7k4jFtp~o{~K8Rj!B?0|6s=405{V4r!ZtQ<^LrtdP(}7DPd^MZ%@`A#nQXK8S~%o ze}T+ZnV&O7GuvwHDLXL7YBOJETMeD&DQ!+*zSZ)1VPJtpGVkVC4V@OL?PAi>IXAF` zkj%?@fn2M_d8vV{2rMH+rsWp3w`kK!%gZCvD#M%~SWSriUOs90yv9HZ0&5Auv_7zo z(9E8qK!MfbyunB|GQv|~U=ySErfq>jLS)+PNVhP$BOvou%dmH9({{@%BGXR8TpZX% zi2YtMY5Ba{KuQ982*I>3u$NGKPYG%Hyx&L;Fv3%5;2@*+rm{dOAu=6uphp9T8P)O; zVq~^f18v9?2NZK< z;5-<7b0wo!12SK5H7*K6Yc5%qeStPzvAilWT{Fzpf$N0W?^TnQ&o>Oj7r03XCV$`- zq4pjhY55#5k{}~Ig##f*?M=}@m=Kv79B3>MVN}b_#GqSEb1U(qY>qpmM4*FF`g(#9 zOx+GN6-Y8F^FW}F8TQ`cK#CBV1|8`gpqPgOcfp{W9|ndP)$%=8<31RV16uQdSeYBL zYKE;A=SN2Jgb|)b0#6yGn?@MH^vr>d2A(r2^UJ^sX3)K(j9_}@NM8fRJQjEZ2HiX! z7-Lk+Z(WQJfp=i&&3k6qSInpxCq$-?j`R~y%oBmnVDQZoKxO{oVoV0Uf}u6v1K+^n zcT6%mt48J@uEtMc$Yv_=OIY-h^yVpHXw7f1=GLH0+vudU9M(OMMj9^;hKnrTtGAi@>nsv;u_ZHO@5F*nC zN4gOx=E9myV9?FmY6=0(sWoB~5@&eWU+i{5d$rh-u|pLI3P2}3rOHRpwemsEmr zwMJ_$c(N`kmfl?=CcP*#&j?moMtZ)&61A=|!c%q4bw=rT)r?@e;Xr*gHyM@LUvrBY zbgz#QOaVt41d2Ia69R*7j@E=3)pCQ25vz%Sp*PLU;#WAOR`y*KQrsmcYC6E+yAnWU z?shR!HAyhEW}v1IEPBUqO^Q)154sw6gdv-un!Cc{mprT)0z+@^d9v;c>v4_VJzyrk z$tgV|-^~gRLwe$pM{1seVed-6HUd=UXD-HQ&2uoc=4H(bu=pLLKxKaAYP=SPY{qKd z2#a4bUNZ)U-n{i-eW-aSEK~O$OuWi1e}wPHMgHWWnW*{9thqt{PC8ErLusaRS!Rr5depCR%1`u!8ul&@v^OkPVr(rG*?jpo~ub8xa z-fbWy!99dv+85kQsJ*9zw0z!gBnKGbsWfeLhSddNz3OO2I33eBm|Q`c#BYbkB_u` z4j4(05uU=q5To{{XfRBOObre+7K|{eg_lfnpvDz5#=79uJN&s^zyX z#)sfLF!bg`82`J`?;Ab%S<_VxOe{nG;gI~eWn(x7HVDUR98J$%t z^AA_!r!ZtQ75pVEdP#colrXgBH&}CP(MmUe6ie^^+GgfAzgqh;dzz`Xvq?+m?Akem z*so-hme2DHB&T*hA($4{E+Ew2lS5iQFEWzFjPR6OyM$4DQ(kQ@Au=s>pet&ZF{kZCw>u|cRHlv+Fgv&*NYj!wA+D})b3$a=6$t$ znL+oKFoJ2nBRv2Vb7}2CFzDv8+EPZfe8|N(T6-7_y*a`x`--aCGD2iJ=17kN#av!{ z0t~*n9H`7EU5tv_Q($P#ncCA}(K{~JRxqmNv#!QDVaTSk_Pnt0l1ebH)@scKPu4}n z(z{E2kNW6$*9c!+FQ(^dwq;x3OLdrP|V@l z5EyiGv^LDBmK$7*SZxFhy=i6^zrrcCvhSjh;x0K++W`jOl>jPpw~LXgO@g5{1GRl% z(L07~Q;ceP(ABsj4A~6T-W3+ViUz;BU#J{Pr0EbjM|&>Lb-&da#Lr{%DuO7vahHLl@TJ-F-LkFDCY9e z2{8EPa-cGwbTKMIr@+vfGojO9(K{}ODj3!BSy$tnFl191Ixj4|q!Ns)A+5RK$-1am zdUuJK^di%Ih4@u$zUGjsL)RIluU9jI>4pRKg>Et`vp;l;8Fa6Y5ljI`8U%_t914L! zH%CKZMz!4FV#GobF!ZLGS^Ns8)XKh#LW;ZOM5qG{zAFJ#=57}w6-t7kH3OkOu;?Ab zp%kN99&|PC2tzhQp}WH3mplv&fuT3|JX!aJ^*E$=5147+lvOuOh)jX;3QO<4hrS6D@0tW-R-M-T@MQf| zEUlXg{ZdSRS^ADC#nQXq!kk+t&2;xiHBIebYTN$;P?x!NMmUSjGg+e6Y({v>uA9Rs z{VtmkO!FLQPThP)WnNgffEjde4kMTrInu>IG3VAT0fTPNtIK6n%S&C16?MzN(3|DV z;#WAOmF&AbNUL0Oe%)#?_^y1QGOuwl3hLH^p*8F4)`3OuD5@)9RLdJ&jg7*PO<~<8 zVew10)fIxFH=8|KTZFZvPVcrdli%c&wzKbwAnkO?#dW*D;Jb=}%DmgfD5={6hSuz> z+Y1)IqXekT`(2F#!jMgA-9cgTOUmj>!O)vS9;~BvhlOS8j(|z8s;VnvRLjR)jpM?Q zO?ll3Vc{j^!qA$N9;}MGQ^L}_Gj*qh$?v*cR{@6Job_a#Q!K5ktUIrm^0G={U9Ho* z3!cr3s%dI3F`HlLl&+BPW`(ODU31CRb=SeLccove1}gIn7sFR~6AZ2K*WCh(-{Au) zbHLRI3PU#Gx{$E=CDFPt7<$v-!HU&Igk|cQ!NjZFaw~iv6*=yqNz`=+3pXc(p*7te ztW;f6Sb8^5*C$MV*Kl15480ljWZh9LtsAPltC)D%!@411nYw$P&HIY^xX#o*02^;~ z%a7puVUeGBXh!OuGHY&_zmv`*!qA#$9<0&2=fcvvmvt|MN&iODcZ~`|YhHP>UMrT? zjn%zTOuTHoZcJFF?yX1jL)|;YG`H`CEwA*_d=&4DE6pd5-9+7I#gunUD3;!R@n}xg zeN{|T`@QZP*#8&CKX=)EI?YqsobY_B<@3Vu0*hqc&9NFfEmGUXq@{Ci zcnKkym-E88R*Ume16dJXMu<$yEoyJkrj?eLN2XPVIX}Fb5c|D+((-wYffR(-5`t-c zcpagcJw@RHtHpVPk!)myr^4_iM(s`8!i9v$wAqnvVRT1W=B<`t@6@L4mRCfkorbwM zyo(U~y<*bxdAEU-g!d4FXF-?lMqb) z@GU~^JwDR%Ibb9~MtBN`LyX#+qTw(hGBr5RSUAF{mYaz|x0>cw;z!vWcSwnF2cz`$ z1S6Qb9cU_?WK`yXa33@5y~E)YAu79cd#=WPFdm1s<^i!X zH)PchTP@CyjN}O;JdK2(GDpTdyMRQQ*$=q2gRQ^L@i-(bzHM=Ra@Q7patYnz$h{Oaw?>}jUj z&L%CLv+L&&V!x72T0YM+kevGYgkV}&zkpDCPY!AMyvRrvGs07D{Srp)O?maXgvhki zfv%`u#;BH;6N7Fw%`1tY$L3WIDZhR-qxAKBMlh{$pau178I^f`{W@mYdyDD|2$5-n zBi#rTb7B1^FzDuO^@WUTd9$mr1&kf_TCvu6qUoU0^({2Y^ zQon~$nfKN2Wd_|_!U(4Qj`RRf%%$}Q!JwPV>Ps2b@*x-FX#HU@^yUb&>?^A3%LtL_ zm?J$76mxm~2{8EPa-cGwbTKOGPl2H|XX;ObMen#=U%{xB&$=4tgdv;C`t!oVODe&* zTCX)1JXseNOYbfb)4Hgk%5Gu4VkFlX;iJ`7+UkP{smb4j!~d8zj8HR3qv+z^>2j5FBz{N z14D1#dayp!zY~_Jdk-dFMf0qNab~CUN73LHpM)WsiTcmN!gnTwp*3GTSd;Z%g{61j z>%R#T@0t{b*8Bi#ZUb8B=BHw5-BkTA#pIWz-bk1&=Lx}xKHfi}h&p>h-<`aTxVZ#DK?L9f91_P$ahIHE=m3N7N&uC)+r>yV zB*D;{frdV?=pDliDMqzC=xW>%hHQo!?h1=v@~~kD486JM$+|DB#|?V-fSLA9S&hSl z$n?mOJ^_k(q~R$TeDerUnV-2BqYcl&(3+PGFTmn=i~^PUm8SC;DTn2{TEN2$K!YQp}-{nDC<&yIoSA)TKL!0EP6*#V*#UD z-r#C%6ozaH8#f7yU$U*S5DdN9?8(|9tR0Pdx0RXvCa1KWeOCl&r%Ntw+yw^TRSZ<- z-7ZE+;~p@yW?$o8u=pJ%KxN+VY8()TY)Tss3X5M-)>sOL-W>8^9c?@;EK_#`OnOyS zV;Q4bKIUp17lv%g8&3!eFDVy>)|~WURWzOwmfoFdJS|Lq*X70vF!biEC+nPIXv72c84CdSj zzL#z$6ie^Ecr+&)zbdAw{oeRZvH9Ou`p!wk(z_p?&7Z2Nw^NP3R9m}rN;OUG@Bd`~ zG1%t*ul}fV>>6{&zLx}BXla|l(3?wHqpAbw7BMS(%_vDb4&x?#? zF(W+XMwT#YZ_1105+c)52f8A%j8QEwCkEYWnpYA(kIkzbQhsDLqxAKBMlh{$paqe& zjLN(|vW^+{-l9kWAu?@nq#J=^E{tpfgKpjyDP&a3n_Z19VC;x!%~oRl?}lhrI4e^0 zuT|#lMzWI;o{A&87^Rzv8NsyMftEz}Fe>xD$X;g9y(Nrb+V4mY0L5GyIS2;bTox&1 zRLh54jH8jmVCc;eX4zL%Mal?~>6jxu4is~FcZ>p+ z`IW2jS{Sk!i@XsQzhpcz28Q0e^yet5EeDwftwMSdwJzbt*nlw#@KZ(+`Dl4iR5 zqnf7nFSXOZ_y6yAj;yACx6X)WMfg0^NMj9{AQKy#YrGb;1KrUlHP zdvh4Uw8)Vz28ubiX$cr~b6!&}qgr0-VytLd28P}&XBNN0DXnDRXbE=Eby9x$|KU(;T&_#GucW!~><91wzra~U1igG#gvy-3hQc<-d*r)UQ|s}dx_cP!saSUM7rWg zuK~qe-EO(`(+X3&#$ zN3pbSsOhd^;$;t;hJ3B}U8FCNXwrmu==YQHyqQ*3$Xq+;pa4`I%2 zmS(#9shWB_)$~iX@zV6WQ>tldfBz@@kHI$gf9V(h`}d#!{hLoSy`0W7Eix;b#pc-# zDZ60_YI%dJ zu~8VZDQw;(EPlzh=0Y&^X0s=2i?DVy>)lpn@|&E}cJ^Hnq@6CgxOo>Cd{;40nRmMw zCCz)l(3*YCd%@y&lmL}^zpHUT7_upCJ}4}HNm+9#7MI7{2D4U}%lM`4(9G z4j)jN1Fl9;7_tdBhlIs1i8hD9(3=JiR;)Q9EK}DECSK*1TjBet$Z-!%qPas@xH%yV zt?Bk)rJ9q%(z}7?K4J2^hMQAh=*^%f>yBb+-B9yg#l*`VHV+BQ)ZO!J-dD`W&8GGN z*!0G%mSIM<{K(aKA`ID#G(QybQ4lcLvkvP@W}ZaJ8Em0Mm3-{*ydAzT5_zYGrnqI7uyAv+Ftld32dkuIkFfM^U&~%$;$0=e(3<_8tOJUrb)_u_ z6%#KjYbh0$sXOG+Jlb+tG0p7}Ve>1iTFSuCn`54=RvjdxydsSuW_JL}mzrYaBwM#1%^JdgpJs#mxVU@;_fX`-Gu20Z&#?v9vDS5>ib1 zHOZ^EwA*_w2F74N)z|kC0aTZQ{ItKEWPXYXr@|{ifL*G zTKW_l?;LJP3Cq+CdN%KBE*G#Wc6~{*!%QwI8>b`v>9+d9#=1k$7iV zX`XoOMp~XKro3ZBvGnelM{~60xni2ymn|<8Ti!XUSbF!$v-w&z^>(b~jcUtF$6Lk} z)7-xO5B7(acdG5wzlSgWUljl6D&34Lmfn5zY<^Nry`5|NTk+{de|s%KXfZ&S5-zI@v$xL6Z}mKi$x2VRQj|C&zNK{&!1GbdhKlTa7*C zMweLazc2Hmxzi1wmMZOv=rXItdHFQS`rkcymY2yZMYGCk>?uFG+G;aj=35P&)+lX3 zbgk9$d3|)9MY8^PVNtYTy5Z9XwcSWsIu}Ma5t23i^0sK9)#AL_NVX8NBZ_J3G|igc zfj_rfUuVcptFfoz=q{_xc*Ryjr`<|h65V69eBKw`Ymuz!3rnnqPW#pN0BPx58a+rz z*7VC|(Ne3$`H+DejUFaMrXv>3`rnqSXxVhbr(v|2v}nWrM!zyD^Y`dCW@M4QlZ4EQVfx`n ze*(ok75xQ9mbE#(YYM2$znL*N#*K9TBMhzio3W<%XTi^zF>GdAjXh<@=2&gU&$b#m z%~RT(*nF$y^TOByi)7x-u^KupQrpF(rE_j<2_c!6^J2MHi}O+gSrJ=Ch)l~ZYH!h| zm6n%Brd5VHKen0>`@MY9@_CJc6vWmNf@yth9if>$MX>^_#d(8~Y-EI|!q_H8?M>Ta zg@nko*^zExbVp3)t(IZ$)TZs0S45_rhPgPlixB(0V$$+?w}F(z_7H+;Uu-X-_MQ^b z@_E0J9AJc}(%3;p?M-E|QbJ@p>U_-^PXA!3Omhe z9VcEoeT2;2Pe3tG#6E+;zn=gq^A{ImGWHb=t@$4N1{S|#5~$2Sm@&7N8|nO07_ym) z{Sp?vB>m2mFtp~kC+m-5>D}Lq`S16>*34CzpEE@>+iL77yLFD$X1>g}8amBW+ML$; zR?FvwtqUxYc{j&u=(I>}7n7FGxvfhG$-JD`nrpQE z$}s1*t|r8OFQ2r0USl8yt!oLvw7zv6p_x5Jtp!$#^9Cc?$Oun`t(zFNH*ISzBt)jo zj&uv7J6dJlY8m!UZQ5>mMP%A(n2TF?5n{hrOjbhB*z)ysl4?BqjXa_BbZJ) z(2CYmjLLkb^)xf=y_Z`n2$AWmBRvNcb7kv!F!<(5Mz6NYe8JVYC=9K+WLfqF+H}S8 zs>pQBFju!;C&YfQnzVerVIaQNn}lHUx85Su-s2-Jp94k`WQ3=1Ylu;MQ?xZqh)fL* zG}annRLjl8pj%CIEAgXjjyt48YX_tB^#miBx*ce$HOZ*V1Fe0`u=ftPrU;Q~(2?E& zig~E@E*Nz4!`2~2wS3RjxDUqTR;_tJtjrBrZNpZJ^CKg9!U#_ztxp-Hn?@MH^vr>d zwmxT6=9jH6m_hfBGJ@%qBYh1N^H}Q}FzDv-)-gu4{MNbk1&@Lx}xeHfi}h&p>k8<`aTx zVcP;i?L9f9YGw5C)BbWk?Gzb)PxGe+*-5hNTGpgkV z7bDgd0Yh(^nZ>VgO0Dd>D5SVcPPBD^!FMHq%G~W@q}q~TXw5)dA6WE`;kFc`S{`&Y z?g&FRLv443#V>i-HUx&=-1B7J7uMr8y?ek+ev?yrM82C9ABObAC6BZ{1;gHzer*J( z%+Fkm(YEJcXwA#E7hv%_MuE!w%GG!+4B3pey%83_WV~$*483{l!TQklPFSYyJ(zfv zTmA^&kBj`tLo?C#nOSq={GD{35Qf%#@nB81eHE78eQ*0FO!_yHzH3q#TJyt`^;5C5 zZmR8>=6ie@Zdp7^5rm6j#u`|E@!_S%V%+;Bnv#rLSvg32CHsfVm4V~sGZBBf? z)$(~^e1SzW@8(zyoffI>V$#w%H@<|B%*%Q4T&u--se!DBFC#>z<6QlN~ZSg`vWZLXV zw=lXRF7sB)uy<Fmr#3832FJf-$)KH z!c%GdAfxuCvUn*WG97ZDN8^VX)$$QyWVTkt%d8gXV@7hE5uVE9Cm5xh${E3Q(t%dQ zPcbUD+rP4tRp=K6mw<#JQ#d)C8Jm4GGA~tE($|yE?Jg+fi_*SyecwX zGtAZT>x9_vRg;#_Hw?rVzexxtfBY7q_8uQ;`5Z8kAR|15;~_@vP0@Im5SbbrXe=IK zRLjl8pj%CIEAgXjjyt48yn|8tdV-3~MrPcka=K)jC`_TJ%miV&Fw9qApQn1|wb z!JwNT#)lZy@;z7MJ{XVVTJwNdnH#d&hpiUpM@I655uQfkPZ_0~Mi{~L%z=)^pED}+ z%lHds(7mIKV0z_9UjxNF7JmZ<-8>#2V^qs;U5pR$cVOtvduG{J%xE7cM5d39^b=6b z6YOfbtFJn~8%ZWj^n&y?n&tvl{hm_yGno;_CJ|mdc zIM9OjwT#NVzI`1t?7cbj*<+2a378{R9|%b2(6%Pr4Wt?We%dnltUE!J>Cu zZm(ce%V%AUbHb2KW&3$y;U$$|Ty58y3!bctiluj#h-qEaQDwI5g26YB0G0Wfi!s{%91N{_+5Q47 ze#anLPY%bQ(|Enw{E(3-8p zqBof4?Zhu)^G=6U+_8&M`g$=Vn07nRl8!x$%Dk^*FEi-g5=JoXccce^VlM4C2nO9; z)=|o+mJhiYM>`IKp*KgEWnWR%QAUVN#~kT#pqR@$PJqETmjjjgq>E9}aS9BrIn!|( zEPBV~jtWM#eAd-CCk)wCcAOU$UQ!9h)efz>;K{nESbBGfnDipke1-T`Y`*4@synVT zN?)&L1k()%>g%}4sLcM3Tg;$)eT-lVIMN_c%;Am@7<6;ABh09l8(fT7M+6MLX=WC` z!YQ?~@1l_6E;-TB0S4cd04j60i;?O`f}u479erTYJBB+_jB0t%)wm-J*$j2u6&Anb zVaE^{dUMZ{bzfMIJM``WGwqwQI)@37>5(IS0u=K|$5Sx)<`JMWKXWlgJD!7~H7`3} zfW_|^1uF9^SL3xXWHZ+BMp*ok@s2St^yaMx>qEyoVVS!3VA88*bdEEs<&Un$Ct=8D zqT{o$@RA8(Xw4T7)?~+5Vd>rXj&H)myC%Vy)u}Z#OY5dOekmruEPcn6V(Hy) zVb1N8X1e>Mnx^(Iwe5ca=*-+YBay}CnJiIjHX}S`cg|syewWP%rg;uDr*l4|GB500 zzzn)KhY?JR9O+`9m~%UqfI&Csb>=dv<)tphiq2(V=*@Cw@hhCtO7>kIq*X3CzjHMh zd{;hDnb)`&1)Xcb(3%gLS6m=Fbs^tx?#ztYtrm%C9u=pk0It#(jo6VlAEyCK- zsdrnM$!~H>+u3(TkaoJ{;?7-Q@Lk0~W!~*#lyvR^Lu>YR?gfkAQ36!v{jSCVVaTSm z^PsT!C1stZVCc;u57yDn!@@FkN5G_4Rdtpzs^w#@#&KcDro8inu<(*{VQ9@s4^~Cz zDPif|na|8t zvl3O1uDRsu&g)>!1C{xPi{b0M35M4AJ8yx-@9+VYIpAspg&~`8XGmE5l4xfb z483XaV8uEk!ZLNuVB%G7xfQ;TiX8XQBsx2Ug_{$?(3)-!R;n{8EWI1(>=P!xYq&E7 zhTaT%vhFCB)(v&uRZP6>Vds#rOx-=t=6%I{+-YhbfQ>i0tldfBz@@kHI$ge=}cX{_O{T&P-(f44I#^t;U|R z6LYLK<7Hb7o#rWRPGY{*@_AumfkiU!=2#7#7OCxG($YCMv4oJ!%Xx`htHpV#fviX@ zBSfa<7PYr%(@M+BBhxCwoS#@ti2YtZY5BayKnfCT3Bj~Jv5wHpo}xs7)#ALtNH#LU zQ(959j~BRqu@ zAx7;@(L|UKnHn5uED>Q;%gw}~TTOE-@uO^xJETOSgHif=f)PyJ4m6cWGAi>xqK_H& z-r+=w5Sa!Y=^db$hZ1+epqn2ih8WfIJy+vC7>^TL^MF{H8?w5Ftrq7;M)HIao<7{T<+fsQ7gGb;1T#0zH7y`zj^dgVx81I0X+cmoFAJf0Y1RLgH&j1P%-VCc+Lmt=UQ}dV^`+PW&P^?{rATUAq{iuNO0dX}1F{>Dt4n%=^0bGK20dVFc5D zM|uD#=F+Z%V9?EFU8Rg_`H+iowCgY!dUJ$X_7zoKWrWCd%#j`kin+Y&1Q>jCIZ&BT zx)>E*r@+vfGhL^_qIX>Gs$f*hXI+hR!jMg6*Lh*#C6!=Y?b4bHo~(h)jcTEaIYkq(=w;Qc= z^HZ_3ZmR2-V)DzT?+qw%G z)$(RnV+$BNy0vC2vFHt^c{}lo*u2vr6?gAql)hff2&UZ*w4{3vqcZR7-pdTSw}cT) z`yJ^4pqNX$4}w8Amvxsis^vp2#?kJ>VCc;eX4zL%b(aw$(=kVS94O}U?h|0}&E-I4 zKIvjqbe{r4YtD3^28-Ttxx0c{{GAgsb`xZ0kULPZv0**8Y6mz&c1P0w4?G7`l zLpDR*cZJ0-dDuM!hTh!sWZf6m<8Hlsz)bt5te#;)WP0RCp8&-?()|<+zIgW z89n2SYWbt9@kto6ndts3EWBhw7+UkigEiUxRakoWz5AOm@vccQX7y;z4^P%l#nQT| z?q7<@FH7GsrC56RTbOfuq?zvisHUm?OYO|R03@?|tXpB8X(Y25;VHXk4x{w-Y(_B6 zbD%jr^BI+SVb20)(7ic~U|Qrz7X!td+p`1=x;d{Wmr*S*bum`-ECWMtmNScA;gnXg z@A4q6a>@BUtHI#A@`1{{#>FV;Sqp~NtnXO|7QLgWr+`r{Z*Vm>3PU!9J)4BZFWJ^p z2!`Hl_GE1l){Y*%+saISlT+HxzAJ*X(;i-DDh4X^ZWp7ZXAc-!v#)0_Sp1F> zpfc}wH4X?vHl;lWg~cx^>nR08Zw`5|j`kcDmZ>`eCcUbvr;Jf8A9FR13qv;LJtu^P zmy`=bYfgHwDtb-{OYhF~oE9d(>vB&87l)jik2;NMpRmHCE?;p@2xhSvCdZh^(`@Bx)M;A#Yg zA)9bdNLc)mXipdny=m}Z#d;#bGIh;h;#F?B6~2#(9QV*9dOC!Kn-jv&nr;tPswXKd zy&LH16DGfFxF-dM-VA!O?kJYl4fWhrOuX!2&ycW8-969deZ_p-V`?9OjW@dGN9_Aq z$zhS7cxXm?o(hX@PQN=M46S+Q!5Zy(E-bx!+4Dk}c-N>fwC0s3>$PHO-B`~X#l*|T zd&Y!i>fU-ZKlHp)Omq8Q*z!s*%}4RhxYB&`*iH0&26Ju_-%B?Wiluj7Jerd|Ulr5T ze((9F*!=G+ednZN>D>>{=1%2H{~UB36W{3 z16`3^#;BH;6N7Fw%`1tY$L3WIDL=WIQTlp5Bbe4W(1PSzMrB@~T*nN1Z&9*<5ScbO z(v3hd7bZ7>K{szp7BZ^k&9254Fm@!hW-GDi4W@ZJ@r&5J(;*cncQHy|FJ=VOZU2kJ}SWK?E<@)k4bULPZv0**8Y z6mvKk0)uXjCc}(sxxvMVB_m+yO*6Cj6;7#@eHVokcgcxl2N--;0;tU0E=DSu1Vd{E zl6_#&JBE`fMzuWXYTOZqY=)9|g~cydE_Z|-@r?hEU2Qtuux)4nOIcbE{F9y!t{ zKrxRbpMt?Rj{ueVnTs)+d=7@zyiC3Ti{CK{ROVN%#%p27W-R$eSp1UlNrtUqM^r{)XcfW->w^y3!?vHAk+P~EP_j`XTE1A_heXE#f8p&)% zc*^db!zg_{n-NU&9B5AOd`4wn*t>ukbZ-tLm=-zG#XvFV_AUW~ZqDn?WmL;cU5pjI z%fQf^<;>z&IHi^ByF5s%TylQzYB2b&e4sL~aWM*d*Mgxn>wDLMMeiu;Enrm38(fWz z!jMg2?wlb67Ix&5NpOYA-RHT-aAdiAYx*={2C3t9!45!8ca}mHCE?;p@E#hSvCdZ-K?{ z@Bx)M;A#YgA)9b-NLc)mXm1z{y=m}Z#d;&cGIh;h;#F?B6~2#(9QV*9dOL)Ln-jv& znr;tPsy8Vty&LH56DGfFxHkoc-VA!O?kJYl4fWntOuX!2?~t%e-969deZ_p-Yib{W zO>dmhH_WJ(AGsP&gdv-e-lxLCOGbpDHP1X)qrK0CrFSoTUkDTL8Wo1tyz*qdRxGU> z>wTk`c-eUGn6OOUTaV_4-gk;=Zr=-AUdfwTedF*=y7{Pd^1DxprF9d%pA}QSH=$U1 z_r;?*+51&7P3`yIZ;CDNoK!5m`ytG^ebP*KKUGt2r+R;>HeQ;3cSSCLw~EP6*#Ujd_9-r#C%6ozaH`!)%SU$U*Q5DdN9?8(|9tQ~!Nx0RXvCa1KW zeOCl&r%NvG+XV*SRSZ<--7ZE+-ySfuW?$c4u=pJ%KxN+VY8()TY)bnM3X5M-)>jIK z-W>8^9ql_TEK_#`OnOySUm2rXKIUp17lv%g`%VZ8FDVy>)|~WURrH+_mfoG|J1tCp z*X6znF!biEC+nPIXYY+h7NQ+tWo{6eR6g?(2A>6%Nf?z;{K z-&GA%<{K`CukR)pTI27#1s1=<2UO;Os}U52Y{GpZVew0%ePJ;4ron?1>x&4>)HQ>N zSGna@_&zFf+(VP->kt-hP6$J5x;qgYxu)OS}g z@v?_~L&7q3_dJ{T74vbQseJ%8y)mnQm{Bc1ay6a^LpCFQPlbh-j0i((o_VlF`<@F+ z?_T!35GLL=Dh#c8<;i-jSXwvM_eL@Cvhlt#VVSzO9?cJZ?-bMAz85yXaz_6+7<%*3 zll4ilv~HsBvtr82CKOBWzIZez`@Slssr}yfO|j*jlfs(SuXjH@n?F@kZ>RcxsWx7k zzG_M}P3>>Rp4+e4>GqGoHurz|7t{X&^uK@g>F3w;G?UO-sVqpdU2=B+95C$H)30R% zm3f|vk<&jP46Rw%zW^+LM-EV#7r7dXg&~{V{w2cVm*n;5f}uA{Jy`#h0Xd1&(cR|^X_=L)$I(ysJbQTC?AibwIJSuC)K4V&Y|G{iVV(b%#8fNBa*ernx;LY<^``e;F8hbIg-< zT(PvSy#It^%FD_XOYcs4G%NZ~DW<7C(|=mA@y^Tr6~Z!gXFZ$eR8wy&`_HSkc4?(z zUhOxv7ygrd(O{eVOYj9=?3S;<_f;Za^UzfHUuV|b6n`h3tA(L8H#}Ir{+q(mJAeNz zVbZ^m^j$t-XidPA6;v#(3-^Z<6EBPQhlOS88a$e@{)l3l+h$?QE4?(W;+?3{#65P2 z{tm^IcO(=`@47vjss5y5n%aT>KE=j6hx=2)GIfKV%{!{8w?qARRa;*AuzyG~&F#Ja zWZzfq$NlF1f%rn+?4@}m-WgV!Cmy?z{-=s5?-)@my?f@-9PNLun5On+{|m7HFNJ^Z zbTg`0diTn+`C2vgcC7!6YV*I*^rhqdV~S~R-~I>tL;pL~cIw|NUuai*?LI2+jjP?K z|IkkKe^zbnstMIJwO{^&J=y71KdLP+N2yi~5$;=I&AR-~2@BGYn<+FP_~rRC+3X_aBlPpu}z zelMT2d|qQ91*x@!U|OGAM`&hGQL4adao%7g8yVrLFtv$Md(*a5At5qtcBESv-I0=c zt7X_bwQ0NM6_IJDVJ=SXBE){Ln6!M}Z6GD7J%nJ|m)c9Hy{Ckb0GeO{Y z?Dwik%jX*g;!E8m1d~5?i%@%ykF4GuJxiZH6>W@6B- zrn!~)Q8vdNQXm%%@0#U zjB5Fwt8pKU$0@COK&;FSSp&mXi}NERdBO-!BdMp1(oG|bV0z|2M^n!kmHB1r1vBX0 zQARMma-^?;VjfGq0fTNHPmM9E<+m=zhtxYT^yWRY>?>vrj1wZ$M@RYzDCUXOXE6BY z37|56aWN)SU%}9t@2PKK@jE6Noi!ly4_D)-Fk~~8`XwxSNqX~?Ftp}3SaS!^N;iKL zOYi>LX684)0sAt0nyI$4NlWMKfjNZOuVj;!&+`l}qTQW5|s>qeFJ-$LHCw0f@!}aJpdGQ>A*oS=;pG4Qbx6W$i+B1 za2O1|Il?UaimHJ!LS#DTNRI=>Tt09D48FM>sLUr_jEaF%U}(*mfzx2oJ1!4YFskLV zuEsfG$fk1Oys+?+N-(YtXw3yr)g;Q!}-$fzC zU2%Ooa59r+kX4*H+7#t=b@8)5NF#s|j0(3`g&tPcb4gk|d9gNawsJZo^A+3EaIH2B3QVaR4;;Ipvs zoe5!R%@+^WD~8%Z^Fd8CWWCjKfszhh*rA!saRS!HSkL@`DN+%rW8x>etS0m zsHUm?YulOM{|D_m?P;dk&L%CLvj^u8V!x72T0YM+ketE!gkV}YxPVZ5PY!AMyvRrv zGs08u;1WjdO?iX4gvhkifvy-_#;BH;6N7Fw%`1tY$L3WIDSvP^qxAKBMlh{$pap|# z8I^hc;5ug5dy57O2$5-nBi#rTbK&47FzDuOgN2N0d9$mr1&keoTC6^yUb&>?^7U%LtL_m?J$76m$9D2{8EPa-cGwbTKLhPl2H|X9iD$Men#gSiz{4 z&$=4tgdv;C!SlkxODe&*I;b@lJXseNOYbfblU`(+uMoeA&DR`K_26|z>Fd>uV7lQz zeS zB_{?uz~H+QKxOWBF;as`Ftlc1un#PH$M9f^Q7sR;8h3;to1wwG!s3@a92^2eZ|-@r z?hEVjpx!-TrhQY^?O{S>dgMr-0L45q_!JDjc?77;&s>br!RKIT&C9_TVDURffy(^K z)p#uo*^CXo5f;B>d~gg5y?N`w`Y`xTSf=hhnDnX{x5pXP@<&(WlQ3j6G5A?nc*%q? zwC0NkYjW_bu=MWx;5T97U6WwUx~(-oJXt>#OY5cve<>!vEPcn6V(Hy)Va~lR&2;xi zHBIebYG?ih;7-sFX&8p&)%c*?##hf(@^HY1qkInbQj^BI+S;q3*?pnG!|!L-Pc zE(VG@_x2Jn=;plJxr}Ogsf)4V_A)T^W;wI?6;5d-`z{aCDwmvpdo>t*S3Xdg*SHu3 zx7UK9HS2G$1B>2Kbi062EpKo&HVQ*Fg|{~ei(j(sb|Dygv)PliMOZs->)lpn@|&E} zcJ^Hnq@6Cg`1UR^_^x80GVgXVN^b7~Lu>Zk-U}ALqXekT`(2F#!jMhr?SsPNmz3Qu z1w(HRd9aS&J}fL#cLYp&Rn_e>Mzws*)i^E;*_7WtAuPP4To_t&(t}lT`;@Ts?#%7e z!sK^dzFh%^-kkMhol`8WtGs<)G38~I!n%4}?=E;YFRG@gy~J#Op`B*jsUluFU4hKq zYd|qq-@Xn8|GpZi%r{&N-|d@VXpR5&EwK0qJ9_wDG@nJ)<_s76${pW?SFnjgSOJUMo{(oAT zfyrwls|{F)x&LtilP?SW;}({Vd5ldjFhl?7sE^rvqf-u&`?K5pB8Lq~^q+{Z)R%ML zjS2&in1Pl2CoU|^QvW1`$#*4%fk@iO$^Z+o(SNeQAq9|Fv#dzx@HHS#8$OVx8tFR6Q58%~cx9FHk5w&(}1C zZ3~o!r$ucGmDYNvP@(j^SlcWi4NXODOG#_JRNPjiG%_u-X;-!_CoRe=6hnPgcV4CV z#pJx&CY7|UA+7rL64LOr)}}3OTSr=%H?*xMhV^cFTdC5>w9&TR#9E%q+BP#oeR+FZ z8EH}8;%IDT#?CfGwkejnL3iGv_~qoh%O+K{?Ix}I^$ODPw8y5cY}-p(nfJHtBZm5J zC24p%VA~#KEzebLhnS(hT-{bhT9gkv7{}U$Cb8P(xQCM(Ks&*N$T1z2#YVNW5%^ML@pXxmw<)Y zWyMq%>CRUbzn+}0+oXoJ8>Cgg-as0jZrZesZMR4(^PRTa#8BUDBn?k@ZQFaS<+-Wt zJ~Pypo7ByqR7ghiJG+T6^*#A9T6g%xVU%tuUX(~Ne%(#RCFZNseP zIocLs27NioTA5=GMzSr=3`A0G31-n9N!H4ob~G}=kYuziD=fNXtZkGTn7lQxKD50P zmX5t=rn+io`xt3a{^)3Y5{4w>ZJ&k3my8PokuL_;MB7(kVfMZ4n=tvV31-Z0N92c* z^%Gc#O}704CS8`>F$pZpehYJ6yEJp`4>Wc3uWDQW?r&GOs^?kSW)5j+DrlceTJ?(s zq~U44O}US^7c~FqP)@3*dz=|%Gx&z zi!RyTUd9YewisDkg|)LCvu(tro9xmKa<81FT@JaTeK#}cTNSL8d5?op*}j(sb2{Vd>aWW~!^|+p9^7@^MGwgfJwj zX+J3}zNAJNh@3L8YTHi>3$wHBXM{<2U1_gn1}5i>tn!^>}>c*KaKWR}8 zIvQbNND^(22#YU?3Imatft75J3k$PUdqS9eS5g>=q>Zc$un-$<&jOP#8*3jGmX5tO zG(WVz1E!w77q(nU$!ymcyOSdy0h9MW0SmG5_RqkS-x~)OW?u}=iT1C+)Y0$l-+(Q5 zP5=wDAHtmHl4g$mgeInw?Z2SSm*&1Z2~8dSJuUl>#@6${>W!)2|F~zk^2^zImbRHg z8k!1Rb4jayy?``4&9`X_T?DtQ-ME1M(F^le~WUb5x9F2p*kfh3WNLX}9wX2F5m>f2+j=7EqOUI5fQ(aZ>swOSU z#~qCm!jPoKby8S-NsTZNIb~qgx=srVv$L)MphfJ5Ocd+z~svUF1N6B%wueNff;h?sE^s|#u*)c z(xM!6G{VA=BSu2Es> z*jq#MgXB^ZMW6Z$hqmlIqScr|gJ_A!O8wVCWb=y%sQV9T8o z!kXQI*$-p$Cp0mgbp3)hUz%Gr2~8dS4eWUx$j;F}8e7l*(i`e;fI6)8Gu<;-n#D48 z=dhONf{wY&p!W+{EAxB@qp)KEGZ0zSv5;AGM4M(y?>K=6PshTGw#_ z+GuGVFt2s!=*4N-mo&DXUuHM>VyAqS+@I~P7x}sYY3R5iEcNBwcN>I($V~&QvE!Do zFuT)nTbO)Tqc9M;Yh>L67Gg~u_kqcmHFq=#OUE7P30tl-Ay342ngMxg z$XYs{0aNa10TyP@4b9e$7r@lfR~;{b&3F1cT7{)!uZ_(%XkzN_a6wxx4RpAHsi&T4 z*;<(T*&%<lSqsl}2KRbmSnrm*OO-~ZjkfJ3*798D-pma3b7}CRMn1lUDtD1!;KNW7Af;_mWoT{qB9lP~WX24NnJb+k>p-xypTr8S2Z` z?kduveAvM_=03s=d=xBTrh9u+e z&%)wM#)W~%7Xxd;{Z&|)eRqEoCf_x|jM<%t{4lb90t>N8_b*`5Ww{-bz{2deFz0nj zGspfwQ%C=*w)OA+PIaq#o~3Q(kcOs$&bg#jzgR#Tp61)Mg`EpXEAyhxg~U+bEhG(3 zi*4H_tmV0=b15^_my0`#NQ?3^2V-UDa%Nz%f>?BgU0Ox%6|=P3A(wQnVFrDxgtaoS zbudah*D(W;4V~+mrS2&2EF~?<8y$^J!jPn_bF;AMlI@*k%)n%ek+oG=J3BGkMohZN zF6|)q%30dwkSjWOGlRZW!CIO3I2e_kdzpdA{?2{OqB|;CEAs(Io=EV`t+ zvx*s*95%3ybsiCxjvZyDx~jgjnzSe%cQj52Lz0@#lfvRlYJ`EvDFdsv^R%!qJKK3i zm~_{b&RS+*a?Z#)4=lv$IxhfIE~^vPwNA_~8k?7(siT*Ptt|A^tBpukZQJXt<+-8r z1~cf(4Xl;JDZq+$pZuHapyx} z>DVJ?@>Ndx3A^7c@>2uS()mnS{N)y5AoAS6YVCX>EX-bYz7!_ilP?Q&x`m}<9%IuB%uuI}`k1Y5oaynC7UiI$5f+9d(awml_>!nF5Q!OB$gju7%axSO_KdMRIr0%O zdG8aj5F79O3{3gGabRKg#n7DS{0dAR{oeTv*mCCturT`}%y}MZ=GaeYVmjIR3)*~X z?z@xF)Y0G5vj1poJ^!oTuzvsJQJ1UdS=wd}X=p0&%q6Y*#RAgsG~cEz^eiB)%!@n= ziJ`t*NE)6N+qO$s%X5)uDKpfUi#p3kf z%+7kw2$Sx*;;Cf@Cg+T-^T0x^&T|2na#@|Qu6Z!KXl!1BrjA}FHeG0!u9AE8EM0fV z4W1j!pl>y>R_2=yMx*BzGZ4Asxy>xPqmi{T-*q(Z2}6=5&wXLhCC#2DW?=HbzfGu}U2y1p1W0SF!uWBCj?eC0%QT z#a}KF1|n+>tkSM^!oqAr*Lq>nUFBV+%)n%$k+lg}h?RA11}0y&y{k-EI=02w+zQN{ zT{^mr*?gl@-ofsdi@eK#RCMhY7Js=y7>MjKuqwOu3JbISUHgQ|cU1}lkpo87L0}

j*IQ^r*1u%KENqW?*vM$T|Tm#A>=u0#h!l0TyPb49(iE z)4*%g;-P9ePHrs z&0S5x(y<4I=Hsr1z|_-6!j>yd$P@9MWk z^PT>#R$=MbYh$wwnwYw~T+o(F16^)l>Zxa1winu=E1IyOh>!2(3VTbx<-Mir*EfWf9QG# zZ9D!R+(4^M*+=lbF~~kmgN}E77WO=^{BDkoLsLh;Ov9e&`U-75|K9Zt-r#?mx!n`c z)X^W)vVUr99iQy_rMZEZPikyE|2^#+f3!F3n!o>hYvzm@%`;kO{O|uKVE*LQooC6$ z|9^MAbN+2$D)7!F?f-rKKeK=|Jk7Uh3%v_SEAt}nLSm@z7Ltai#kTDd*798BUCIpg zB`wMu9gR)GkfhAJSy*(*c5fLoFxg^cZ57r|FJ{|_NjLqQX8Qm4e=~T?|MRBO z4wk9Ai?uvgcy}{{-mhS-%zGS+O7C7~AhO@Pk6Cm_C2M6q;Ak8ah9p(qL&Bm)_Yo5n4R^W5hmSr z#aqh^OwJiu=YfS-o%aGT<+3_qUGrjg(b&8MO&z^VY`V}cT_yMGS-S3!8@xA|LEma% zt;{zaj7IM*W*~CMdz)EwMH8(6L07sA5qmG`AE=`O#wl^K}4HnQ4)g_zsx0w!M; z@VbSiV;*DE3(SyLM}5pzH_qtxlNRNmqY)N{BvEffSbRxT7>L9StfV(CEX-2ggfRK8 zq%aUk8(A4(AvWsG0+TNr^NtEj$KD#6AH45?si*ISO;^tB9%BY3AC0U}z(Q=?`x%&W z**LH;`(kKLc)tQuN56Z&0bA~z5Z3H&%zhY~KcR`~r1uxJ`O@5~NoeZmZ(z^sMs|+= z(b#(am)^+z2FU;Kzwu^t)AcmX%D1!qGrX4jZ<@neo(sC?GGprN|K2ZPt<3WsjKb~( z%s^yO_d;gT9fhowd9kChL>Q73buSebT~gd##0*T98CWa3mkUeBRxp#Va>}dN{bG?< z8<3LjHNxUAmk0xqwFXvc_c~!=wxN5yFzK%H?owu8veC%e1T4hLx;F!pFWcT-CM+G> zVr*^&=FV;%-NtOb(JAj>_sd1zWk4#rcMFTZTp6Z zvr~pgd_-Gr;CMuXNW6OUKR`o9Cg4Xb?(5 zzO1>sNmx4ez|ef${ScUX`bgMvr3rZ=zS9iIQ$yC${S26LM+>kpdv0j9cE13oj=t)C z32eU8-`y%K9eZtTwm}n9cee}La%rI34NN`tOw0B{JJhY`K5>I?p6T;51CyYU6$Tb! z(e4N^<+3QSFpC+Q$?iBXbu`tT0Jhwj1Qup#V>1IyOh>!3(3VTbx<`Sjr*EfWf9QS( zZ9D!R+(4^2o9!DDH*@SGr0Di1Xkt3v{TbTmyW`N*(J#}mC%V5vThG6De}gyB?g?n> z=nr7e^C3G&e`;(UpX~mnxgnS5zCWq4_5Am=Z~W2TuxtL(TmSw3@Be-a=c7LhO|xv< zIjrTmz&BSh=J{u^RN$EBI~aw&1e9!M9$RbXU2r zlo^<8G_p1U3$ZfaW?=GV+kIui(y=YZ=2l?t^y%m}X7i0sc?Y{+F7hq|QsLVzEdFwZ zFc8^eU{(6|3JbISzJ0>vyDEi&$N?kkAg~at@*M&uUsmm_5|)k~HZ+gFC92*_Sl7o?m7+_+qDgmEErw`MLpV@ZAs=f4M;zh}<-=8hy8fh1nh7 zZDI0Vjlw|Wu90;QScoOUE74b%J&l3e5c>nDl8p)ZEUtd6H~X(1#P)B;By00Pd(GJz0eN% z^xP+I(9JV?{LH{4Xk>+fg;>-V0j69Q1r}y8Lo?}%15-y+z67x4&LprfOBQ%~Pc!~WoV2W>n49^BxoXZDNA3GRw9(RWXzJ*fY1k9K zuh7=>@4j#F2HHIV%-KCU`eR!5PmQhPlfGY?8*+JWmi26gwp_Zsrwo{Sx@B7SR%q|+(erKM zhTLpIc8Kqk1G3AIRrKrzrrc2hEX?*8nw33!fvKbWd-efa?yLkBW(SPTgV4mZs^<{2 z<B|ISFmFv<8|wdTJVWZO>_F z>-pK9Gw_DoeWj-sn0k6{TK0L3t>bk)7c@8U@;Yc=>(TRz)4p*@d&91|EN;o4z=T{C z->C=Wx*==mxdBYMqXAf$-83{Cdu{1XGr_jW-rRN#6>EG|aOIx6+qtB;dxAwe% zww}N0c?oaG-Tt0dVCw1XY1wTWTgTl!F3kDhf>dFTS6eU$rI~TU)~Uq5CQqllk~~pQYXL3wugg<< z-r!%KZ~pymxxe&3LQfkZ-K0?UT;|`bG*e&R?k~$ze%_*Owkpj|KTq5KYp34ef9}ZN zo@#dGiFK;*@6OXHuOd&>(;h%8{d@D2p7;Cr<(sMRR_2L%IsoZGg{tQ&{~@KB`f|0u zDo^?Ou%p!hDJe~EQ zQQE0@uJ~*7l%LOOoAachsm_0awCYQBN^{N6(?#3%5^H6?{GT!PBLDMh{tHvh^*pgo z4gMQ>I^{LwiF&#TXrupDp3?Ij|LuG;_1(riQBQXvy{Az1+~mKnG*e%0_BZ7zKR?hk zkNppoMy5yk)_Mh`gnx@tNLTPw<<$tNPQ}6iwt$E7N zueD7ZX=rl$U8J>M3i#bhBa_Fr^^!K^m)Vy${(W;s!2chiry!(Zg{tSMKcY0&m!k@$ z=a{BR`r}H&Q_7!ETI-#pLg_iJZ8D^xY1E%3t@YBFe^hB?dTY~u@V_H1%I_6p>eZQn zu{`DHkJ{!FX=obve~phhnL5e6cEr>uYf1rV6pG4!ssW)o>>Dhq5Tt@YCO zK$+6Ww8ggFO4^+PnYZN)>rHgpk@w1#(=N@qBCuO&tnXDQl%Dr!n##alrQvCRV4u=j z?^G(3o)2i7gQTIUDsYIj)=SlaDy5O>uuXd`aD=odA61O0SL*}SdCJenwap3A&{PvR zNm})#8q)A|%BHOioF=WzX9H)5VZD1LP^&aDowIGvvzF(&zy)T|m+MG-Eg>hmDYNvQK9sFSKHhp z4NXmf`=qsAY7R6hjZ6=0+Q)&1q(%9WVyLg`&QBD-nVg^6q?W)l(yCu?Aq`K@ZQ9nr z3)0H`D)5pR*1P^dtJ28y+O}_YFEc^`M0|=hwP9w^pQrpB z)HY$#&=d_sNUOdSB@It8n>HDUlUC+bAVCcE-6UyvO53&>*77_W$TCBHc`PtWT9n^9 z7#{-fn1RWAV$l^=njIWdyj=RoGIc+(mgn)nXJ*j*dExNhSlogrzRYeP>b_i2OFP{s0TJzfT z6YEqEoSUapHw*GaJ3LCbVZNFAZegCNr^S#iQK)(@3NBTesV^4?i}IA8 zmuZ@n!R1OL(~5j+y@F1w@?NoWTCF*k1lK5y^}P~>((_tPQyN^SG(2qxu2zC_Nw0HU~*VQ&sQ~X|0#4gH=i+(_x$TSnvpGQ9h~| zQ?J$stMinfk87I~q@k%Mc#^d0OEsk7>6A@d8$3-~na>8#5W{-+O0ZUGWIAWto@Xu3 zb-@eFpfA^v_F7Qpi;l)6VIXojZ&?e_>1y7qS5DV8=Z4@7rLn%(pip|gsc9O6x0Hsb zJHgvZYrWH`P zQqo#46^DwHMy6#p?aI({(xSXVG1OOe=T(YdOwOxqQb}kHY1OZnkcOwVHf?EW9cg9W z5L!)rBDsnW=_(YD>hTAs^7o0*}$yggJ#T9mgq8e5sMGla-C#Zouu&N~#poSb*r zq>9jP(yCvtAPrA@Y}(4uUee0EKeUe+>bsSs;pu>Fdyus}SA`BSLw&hAR7F~p4?7sg zLPwZ^$x&iiE9yhlN+Z*8+x7%&d9DeaWCne?hP5)EaxiK`rbs4k;pwhzdylm|H-+vqLw&h9)I?g8A2=9~Ll2pO$s=OX z6?W+fx!26nQ-|CVdd3X;Rtsxoe(qqjhF&lOkyoLY%u;vwL#?Dm`L(0bCJag3A(yb| zl0eAK3`{&mmRDGz5N1AN(oJ?LsN9y=Nw0<&;0N`(q-1G9crj&%~M+ zrr*isabY0x#lV^feH9jF-$UPoss4@Rc1;Kaksn6ZPhcT78TtiGxoi?xnEf_3|3Fhm z|4!Lc|N3Wt&I(Vhp89i6o>-@X@Z3C|@(S`qJ3LCjVZNFAZegCNr^S#i zQK)(@3NKZfsV^6Yi}IA8muZ@n;pIvr(~5j+y@F1w@?NoWTCF*kgx4sI^}P~>((_tP zQyN~UG(2qxuUFcscgn-1dCJclwaq5d&{P)QOj_%u?cp+|k!g!zC_Nw0HU~*VQ&sp7X|0#4 z!&OQn(_x$TSojEOQ9h~|Q?J&CtMinfk87I~q@k%Me3G>4OEsk7>6A@d8$L~1na_sL z5W{-+O1M^OWIAWto@Xu3b>R!lpfA^v_F7oxi;l)6VIXojZ&?e_>1y7qS5DV8=Z5eN zrLn%(pip|gsc9O+x0HsbJK@_(YrWH`Pr~Dk$Heu4x6b(m6tG*N^4NozfHW`kS zR_0VVK@9cXBx!g`+qN0j@;n;OGDCfNEIdkDl;1iSAHwgLfysMfSu1Atjwy{yA8p%D ztmSz;{Fxc_<#E=^{KdhT2!CY;BHzQ`m_>I?kal*j%s(8BpTdx2GW<(e>XO{clfppc zH?!vTaw|vv01LCfmO1q=zg}yZb(#g~9EGaqg5J4GV|}GSq4Ydo(-ihDP#T^V^)6Ie z>zzV{((__%vxGD>74eow1!_!)uwzPL0X=UEfyPg=bsSs;pu>Fdyus} zSM?rZhWc`KZxv}#KI~u|>pj8@OpX%ET2bFytu!(nw{1_bmgkz@lgywm*RWRRQw~OL z?`dWra<=yjv(z0|dTU9G@;OK2yf7rG>%AZ>zNC&B*Lo4TXk=Xi7G{?fGruTOZ&7x> zs%@^5hNgzz8>CfVY9I|yH*MO+-dm)V`A+X`VyN#nl7^?dw(ULE^4!#WpBd`Q&Am;e zMfrh)@woRPGcb8XEV{xjJt6m+S$gV_TY8@{gTB?mTA80a7_Gf8n1RTv-j~c$cldi- zNsIDpN25&`lDK4b;;xV$k!V2|b<|C%HX=cQ)G%^Kk+c0Z+j`l{FL0^ut zR_2(4k?f5#1Cdm3f?0G&lC?6Y9gU1IBpL0^3X3io>m6kVCT|U_554b%rDN}z$ycd) zc4Um$x%^QOe&drcBpL7hEG+(=abY0x#lV{A{VFWXzW06;Cf_w73`Bk~YhHv~Ir0-& zh)wqX0w!IS``#q5F#Bz6{(+{B{#H-YHZlJulWaOGragQDiA;t(S@;MM@*nGMjc~WI1V3UZEK3tGe?l z#V;o3)i$XlvWB$k*Govl(^{LhG_sDgGH-~iCx-QId8AZnWZG!kZelIZWs%LyP+#62 zDI+b)TO5t8%-9)0WSe5C8+7L#ieFC7yKGWLWH)KmuUC+Ur#&`pWn?dDW!@jzM-27d zO49Ijz_vZeTAr&ShnS(hTpg(*Ey{--jAM}_%)sO*v8)yKk!q!p>9}osg0(!?L{2h; zzFfmvnNK+wwUN`zK;&%X471c7S0c5fMfsegab6gb)I}}`i!Z5T#|%7HMU^6S++c_1#9&@O0O;kyg^8{MylI6NV)2h)Y;>Ng(281|}XO%PXu<1T!BotxYrf{7NHJ(6$Y;mgi_B z!VLOyl(jO)9E@Zn&J09Skp#2ojwEYkPCFVIVMsC>$qI`u8Ha= zW~!@Z_KlGi<&TcWCt*l39{DURzGPe&h<1hsX~j>nE@f zn~eMdCS8`>F$pZpehYJ6pEPsq4>Wc3uWDPr0qC3BIx{+hoM(}wT60K4Q$gQc(yI3g zNW;^7o3^lT0cmAk)VGir>br%c;c2mLyM(no7xgV=hWc`GUlD0hUglt|>|4$ZOjZz! zuCPn1$h~5gRy*X9zBSCCZE z7G1KvuZ$U(Y%#L73TtN{X4{BKH`%2fQXV31LW5 z(|1x>d`XQk5IJRF)%Kkh7G`Jr&Ipt4y3$w63{1`$S?7U;SY6)*V9I56!n)Rn*+paX z5;S%6GO_7GyL45#H#=I-(shU2(079w)?2x+HLzCZn+`@}-z{b!a;NV$v*?aS*2;X> z(YPlJNt*iZ3yUsk?rUNOCJzj($9)flrDKnn$yYh$C+vQ+$WIMOOW!kL@t0eKfyi?M ztF`ZiurPbo_fnX2m%p!-8JN5_vf6-!n7hvfOuj78=N6WZd5ldjFhhMh>SH$F=#+!( zzF*|90g3iSh&3-tzmv;RVIUGSu#$aoVPTf)O9)f_8_DfT3Ima}k(B`!VxxUoVDe>S zeWSwCvA2fihrV~f)YJFEmMcxjNAaC8Kt36=@xIT%lsm?Oh1nNFbE5AnFm?2M-#2Fe zPn7@MIWhq(%zhY~KcR`~WZy4n)4$Pwmrg=cM}JSt{-d$={O{C_so(vuKW9a!euk+( z=j4fXDu~X_(^b9eqcdtZil}4s>w(WV= z@?00azzq6w9ciycWxnWWToMK%m-Cjj0G+Ppy?W(zU2|@T-cTCrdkqSu=bM_QF?vgB zc)An4t+duVjS8jbyV~X+X=rMS-Y2c~QggIPX=Hj}(>{(qBrVF16hnPgcYdPy&E)*l zCbdMLkyibB3u$+{lr?H$D^N_L0=wct;}B> zjEU%1W+3uC`i)t1#{_9-_sjgl(fBD0NhYJegrzRYy*w!lM1C`CUO%^TLsL=z zQqo#4755h@jZDjI+LiswNsICd#ZX_>omVM-F*&ccNhSSjNUMImgfu*@wP{QH*O6A{ z4gKqhVZB@4U#c`RZM1DSv6knu{>{u#U*6tdMp~4&I2v1-v9lkMZHlFC(4BWEemObs zvPl*FyGg5ly@E76?XhVq`}dMo=KcNqh@rk)NgAFG*tQ2*%X3x#A!evASNB(u7UjbZ z#V z@O0CrZS22ATAAEozjid*gdvH$-z6-% zB+&0>1|}XO%PXurY72}6?c z{?EeV-x(JMB3}%wiTU> z#^xVr>gZp~p8EHH%-U(4W^Pkrw4Gj>cAI?2I9@O|jGs zy7LajFDK_+HmM@Eo3!fJD@eoB9-Fo@wwJUr?~m;xhWc(LX?Qwd+a6>s&sDKQ%urvh zj#ZHs<--ofvDgu2U~-gL){6RAwbICR+_pWzTApiSCz(NCu3@drryPvh*lA`UayE8` zS?Z1}v0Boie9qB0FAPcQVi$zPm((%iS`3kkM%E=@VRl(D)kV7VRmHC-=j%49A$Ehb z>em}c!_!ThwlQ{#v@+j`-6n?mZX;=Ux@+6sV=d23vHQ$WUv7>ykrw3#4#wlyLuO#| zh*)%mU3x<9HM8{8A-BYyF@wI#QnU9#(rWpf%rI9IU+lE=ob2JuV27NioTA5=GMlu#>1|q3g zf?0G&lC?6Y9gU1IBpHomg+-T)#YUNd$y)>KL+qWfbnHDd)m1YG#z>3uM@Qq6FeDj| zeHIp9GA;~6z8F{&v9H3y?0f8+F!`<6Ih5%#(n{lF3ath1Quq$g*k6P znmP6dnmYPdwWodq5T7xS-^$Ljw9OpS&{Qxmm$d5F3rNG$e4Dm#U;$}mUNo?f80x!) zq~U3?ZM%fEJQoctWrq54@jwx2QC{X?tQ=U*3`|xKi>|OstH`}#mR39Dl7ThMpl_A1 zR_3)1M(MyhW+1X*U_G78YHyeV~jPm~1h!whC+K0A|~W zNjKT09pqj)OS>F$#lUW6(6=gBEAt))qjF#`GZ5K7u#Z`EMK1BZk~ zmsAf_F$0ss2G+5GBf`?Lqs&xS)elsY7UkoP#tC6aQZsN;SbRy1Fc3LqVAT$s78Yh_ z2hIqS?z%Ei%M47;8CmCng;?Fd1z^f$b;7zffZ0W3^Aa?5^fIyOLMzRT*DGEwU1gcN z*ICPR!@vz@(EAOnmHDQF(Kv968Hn5&xXmoOqmi{T-*q(Z2}6>mf&0RuOPU9on1RUy z1MBg?Lt*LIBWChdPWcJD-z@S|1JW|^Oj!Ko7GWUr+`wubcp)szUJbkyCf(&9Xk`W_ zuZ^rWU?JunZ~>Dq3k~XW~qUMF!`>eFc3)_Ss7ptds_A%jjiW@tsB;Ff52&0-1=Fp(;S7W=YsfLrLp`1h0^nUO;Z?Opfo%! ziZ4`J>zzV{((__%vxGD>6~&j5)_SQpUZgZKEwgD?#+Q>8~ z;%i8&e!YY=Jgv29OXKTEEAxit>|R_6WjeZ)}Ttt1Uk2W;De ztmU~Xeux?B%hmBJ(xQCW!8jH_!VFA~63bdqAFoy#nU34GCs@mKP5dM?=*u;%mHCu| zQ5!$a3`EYx&oE2faV1_$T9nT@8s~)}NnQMcu=tWXW?YLSa?!}T1T4%hE2g?gcfP9l z_2hirCN;!wkXHSA18I1=Y11~wZ;@8!JMr7ZP~UAN4NrG%+k33#xha018S2Z;@g~xu z{J_C@9Dm3ROdb)7uCPl_$h~Hko;u`~_%mkEw^~>$^K%EIHU5Gbh`frwWR|+aA8#cs z%C8-bHepEOj=O|KmjvQ&W?XQsMp=HM7< zQU2&?d=iEvu=Z(l&EQLsP-vT+*svFCYz1^KII~ z!3Ct1dC}lPVyN#Hl7^?nw(Szu@?12ylo{&F#e+qpMR}Qnv2t)ZGcZ{}EV{xjts?h| zSz7IoO9t04gT7V5TA9~67^Q>jn1RTK!S&2ica#s7k{0ESj>aZoNK!VqSy*(*_Q5h{ zV6w%?+A6G_gP3h2Cf#J0c947JEbVg06@$B(LEoxit;~BIjLN~i%s^!S;67&29hIz= z`GBKwP#BU_4IUB}T~a+*#SBai8(7B%j|fZ0jxtkSRX=85hDyRH}-ES88sR3yjd?qaZa*Hq!d2V2}4!#f;X0HZc z3X|^g54JJ`lh;O88?X>_54wQKmjwph!qPF1vFQb7Xi!Ie%vLwfO!!HQa?sHT3qz9V zU_@AaNmLk!#0;$DU|d+3r3MqiKqPHsWq^g)=wKF@eA(FGsIYYGt)cm0@EtJq z^u4g?braogDlHZN4=3-AQQb=Aq9|5a~TzyC>0EuWd3LC&*CQmr|pp{XD- zm$d4=0@Cm_-=-~0EFi7SixLZop}t#48lD#0wo6#cb5UX`Gt`%h6Gfy&d6|Q;GO?T) zn5-ZcU1672k$c4~t#-&Ii8aiiZx~l-OQkGRj^j(Jq|`?VlOig z*`L_QEV`qTwK5-YG!6;iW8xMw5V@1M%`Cd3k+m}4bu{h? zLz1S%ePPih&50&vVDiAgdYpJDEFF8qOuot~KVkQqMSf~PS`yEM#b0g_1|rW5tk%Q} zVPW z2n$1!Xd)skz9cFPL}CV3G7%RRW~oF%n0!}K7>J~etPHRa8%<<^$(M~KMunwgZw<{4 ziFd%%)Az!rD`yUkF$0s2M%E`_AvT`)3{1If99WorF*GLQddG(H(`Xm3gtFu|yb>6b&sE7F|+2RKyHS zmKj(phn5RV$5t?tuX4((*!^OWR~wL$p*6zdFP8`dk+lX^>Cif1VYXpty)fyn@}W{@ zV6xH3+5{}b%7!)rlP}voR3Q7 z{ZKVCFgb2yod6bMHA5$XDVNm%3$s&(X6?{vVCv}Ep)ADDbu^H7tpbnJnl`FQ9dF!l72u;oe<@6 z8IY%jtYzpKFy)RGU}5&$&}pi5 zdg_^$?S*z|NY8!ZhTLpIg5o=VK*EMBIurq>+z|y9W-&uEITQz`j;4kZ%>JJw|G9G{ z2`tRg#%2bZn2ru*p-ulrb4$mDMuDlPZ>M2@7>-gl*FU<|Sd{SfU`R{4p_@ljH z*ZiHjHT8e{#r~X?ocf8T{+yF1)~O&lH&3U$f;>@A^8qbPF33}QUX)yzZ>GLmm?!FK zF{Dcrs-BCIOOeA^7BS*vxzh`l_fWm)_Q4svP@}Y+G5*oCGF0n%-iyY z^(H#)$b03=X_w|)k=(5`*7qtDO3!;VO=WVg((trDxld`WcPbT1&j+;4LDJAvl{`dR z>!s>smD0#`*rq*}JVIKOk1EF0tM$q1Jmu%(+U5jlXsSt`B(3^V4QY5fWz*IsPm@;W zv&l2Wu-?6rtW_GB&e^u-S<7=>@&YsH%XOr^mX!ITqj5n)_=>A6kYntVZ8nO`Me62p4epKMhcnO@tr zZLH z1|q+iH7~`j9Qgw*%>G*D)W7^v)-vlf3(`3XRnG;fxk_Vwr9h$dJYUlkrWPm-Pm59u zmDYNvP@(j^SlcWi4NXO|Jc z(yCuCAq`J!ZQ9b*I?~F#A+??u*1P4YQl*h;qiws1wLF)lHZwzgd3&miv?yWQ)shzFbB@M&VMtP!x*#mRq>dTaQixnMvMvD&v&)K^UzD!5C_7)( zHrGi*Q$y+oY1Nk+NW;@jo3=4^i?lM|N!=!f`fej>c)Dxb-eWD#O{x3LP+x9NHIWwO z2M)&L)I(-q@`zY;gI)xuhtpF0?>sTa&ZZ`CY`=0tHOulPE7>N8}*1R;ga^xql5SvW> z0w!IS``#q5F#Bz6{(+{B{fB&bgoz`gkKE7QwKi}DJ^P+!%ZS1EomIj^=! zCFwP!Rli|h*AA7KV2M~P*vs83fbjZDXF+Y_wixh8#*8T92E*2;X! z!Kh82W(Fc>(`T5a?zob!B`wP59F6nBkfbhsL0EiA9W$<_5xHn&T>=(nmlac8q&r_# z{CaY}Zj&0)H%O~~y@515-Lz>N)3-<~^PTi7sai?9vqDum4H#0Et7+GFnh0>V$h-qz_G3-|wnS!=$n6*4d(-CISm!qte zIp$y_({W}Xl1e9-MRz1wD|6b>$OuD{(R5Z=bjetHlo^=3HLyOU-w8{{-ZN8OHFJ23 zv?zacG(HJKlJWFsVeuv7!a(GUfi;o-DlE*tr@sl4@0wu7>|sQH7+F7oh1g{J7cl9v z+>S|LVfI^?^M<9FV}GEjqkmO<>NfzH8N>Ol>^w``%pna;1;cYmtA4$JG(63>X$yxJ zkXGhJ!wZR_zFSBdo)+7-OIXWu(eP4cs4o`}7m*g_WepNQ0WCgM43cIw5+$&~j zwL>l$Uc(IfRtalmUh80#4zFVdA{&O+GfUl3K3qy#ls7sWn}i`r+3;pz(Iwl5%b0=5 z79(q`uyzh(wvCu{lU>?D?v=B&%OO_`?`8<Ae#M?{P3HhxalAk^RH_m_>I~vR38; zj>bV@NK!R?NLX}9^>7t4Fga{s9UDF(EFC+_Om$WLa5ZUBKJI9o5QZc*!zYEsm(&OY zky8d%?eJ+~VRm--j40pRoJQB0n`CEyK@*#b0g_1|rW5tk&Td!ouv; z@JnIRUH;)#W?=H#$Z7)?V(wuVF!{2;uv=I<<}o(CzzhxRsE^rvqf-u&`?E8Ck;4Wg zIvf#}`f~2OQDGnwGq94wabaPW8cqn4?@9^-k+hMO0TyDT!&zYRWn;sm!qTy~hUSOi zcfi!s_rjJdO~^;_oiRW@8M5)=&&-^c;or-VabRKg#n7A>{t8ST{XYB+*!1r!w{rqm znEfy|e?k+}$>CqnMoTB5siVKAW&hFGdj8kCVg2?8oMvULpT#=OQK)(@$jnt5%P&wU zJJHmM}DhP3L}OGv}hTAQ{svyQYfZ^*1ChV^cFrc`NU+GyKuVlB^Qna#{l zU*4W6BQ45X9F48a*qK3On_{UObmtw4Urx@uY*IyLH)++cSCEFMJvMD+W-n=F-k;e= z4E5bg((rV^wmryNo~ts4n4!L0ov9)%%7-0{W0@n&z~m^gtQGZ{YNe6sxNUoawLI5k zPBMeOT*F$KPdOO1nbXWbDYT_s;g#>jFA@QkB-JCVMsEb`7A8HWLy}Cd@-;lGGB#-+4syhVe(xQ%$Plb$PXjy zC$JEk%=`i-U6$K12`tQh3v=FxG;{0^Gc%>>t_3 zEV`qTwK5-YG!6DW-gh_W@8L4FkCg+T-^T0x^ZsY0pRoJQB0n`CEhEo_#b0g_1|rW5tk#hi z!ouv;$V*|;UH*|)W?=H#$Z7)?V(t+aF!{2;h+9}X<}o(CzzmJ(sE^s|#+g|^X;BV3 z8ew5b5*>*Mi!X@^1Cf}4l^lr+3$xTnLYRD4QW%J&jjRl?5E~uI0+TNr8yOXrj=eQB zKa9Ksrk=hRwp>Zc?Cco3lOrDillMLW3$gK$&%l)58wVC}kzo5;R=Ds@#O&$F`E&Gqg*7LvWjj7-NjLyjBm$UOMZ8L{7 zG!>6g!w@O$m^I8X^G`o%&h-}ENXO_C7JX=ayls7sW zn}i`rS$4Cq=#uT(GG<`1#mL$!tesiRwh@zVvP(P2y>gazIpm7$Zf4N8Dp)J?9tWc` zyO$Y=?9c9F7Tr0pRoJQB0n`CE!k(n;xD%d1Ci$j zR%`Z!urPa-eJM=3%b#s!1}3kKtTtdF=FYl+$(IGPZei(|$Jq1&GnCa)AG6hsGv4?~ zi*nG>2n$1!Xf`4&z9cFPL}CV3G8-2bW~ppKn0!}K7>J~etPHRa8_i~c$(M~~M}?(h zZw<{4*>}Ly)Az!rD`&nLV+JN4jjT_=LTo(y8JKd}IIuALVrWiezXDT7zh}PzTkf0? z*6cT!{V+CvLKD-;>@R5ZrMXp;(A3f2z@GO8**W@0W9#`}dPDsU&>L(0%+VPv&0?9l zb6CrB!JE0vp!W+{EAxB@qwviFW+1ZY%|d3;9fhowd9kChL>Q73y;&+Ox}^9`5i>AZ zW?-#+vs_p@wt|^_l~Z2D?iY)^+JKb2StBg|a)~eyS!-aGzF8+M%r?APFHE|t{7oq{ zFxhBiZ2}fzWp6eElP}x;rc78mw#C@o3e25vbaWfD`9`O_gWWF|d6xmHc(Yqr{N)N^ zAhO56s(iCoSeWg9vrm|OSEVozIbdWR1QuddZw>*IFROl2B`h5~{Qo$&`;e&HuK)Kv zQ4-N@5g`$6iwKDbiwKDbdmtntEFvT#EFvT#EFvT#?17Mou!xX|u!xX|u!xX|um?gS z!Xj!M$8lyHbsWcWW_%jwirCD3{m#>4t@T;o?=kmZ+x1?rW4`OW_WtJ%wxvAs`w)1S;1p zRQ>N8Lg9An_e~-BUG+ksa@$JX0SdK--*J z1xUTV$w|M3`r~iCzY{Oy%{JwO_?=czK3TT5-=CSB?x}RS_t)8qGl`e#fBJd-8W&y!aoF{NE$n5>RS2m6IM-wARzV$CVfSfARlbo>sKp zGdaKbqrPz3{GEC=^>2URuNj`H|FWsSW*OD|JI^!Q*i896qtd_UDw}-IJY&PB1)llF zcIrF%Mx}o*R5y#rhE4^Z#bi76r9w}Ev60gfhwXCDQnE$!GDDbO)&5>#_(JmcN{6Y) zvx;oZUoRpXKCO1x7JJr^t(@0+))F!G-BM4nv60hy$L$8T<#UN=BNOJAw|Yv*7R{Sn z#bze9dr;Y8DDwvG?`?)JC4cX5n94jm$=3Y!GP2>*E{AQoXE)i(d9P;=5$1Qx$%aq+ z9Jl+~md_QQ15B7-uJlxpEt(Iyh$EguOyF{usHrPzJ(b2rPDdTL$Jmz7Ri5Ka&@Wf9 zt(;G|h-%MCCQv!;ImMKD$0biS*`oQ3t2ir!EH$2ULh(y#n7HCW<-C=;02FQ)4QXDa z{e9W+wdC)s4pW`y8rhn^UPm^3y6&*8_uL>`Ip6Z!B*Oe|J=yT-w&V5=+w!@=bC(J8 z%Z;7}vPJVf7xB<@p9x$Z5Jj(WnjVpNjcj`CGBLQvw&zL~vh37d_ z<{hn`X0k=|OIPtq2w7S@uZ5zQy!W&)fy)~!^;W2l9^Bp$Id#*tj#gtMrw@+XPi)KQ zHqU1!=$G5rR?c5sM7!rJ6R3Rmd}E5<(ayGV{^2Tq3L%Tf^GhgtNxRuj;zIJf5=_kOKqY0RMu9>t z?HLD>UY5Nh4HRw}A?I{RnQecd)aqYTPyOHh9p*HGeUWZ1^=0+(e((JP#$ z735tZn^wBaMIEb{px-KDTRE?G5yc&Am_TJ+$6BV$J4!o>$rjD)UBw0=WGU&`C=|V9 zYexwaxNNdgn}yomf!h`$=}k`4HuA2NO*>rXvW}fh&~KHot(we7V1dHA)&N(m`U@h+Kx)HMe|WtaZCtVsydDf z#V@H60+kaMs=DK(P`I7$I3*;#>rzKG6S$nQQfGlet)}A~kn*w`p{{h`cHUZEfKsa$ zi8e0u)|wkJU3T1FWm`VibzEbDez}fq<$T>m)OXxq0+m}GH<_Y$)U&OeZ@Y>+Ldeq4 zaaSmMNn=L?6S&;7P!Buq3#GLOO!BMT=11&(qnICCl%|d+Lh&y*34zK}3)S55Oeox5 zbUYW5-qqUC%mgkkt<)=^P;2RU4J5zpeMgH>T6<$H-varuL#ywYHgBBnZ6#YYe{dC_ zgpj4J0dSjy@pe??r&ZEovzf9Wfxan(T-JE$>VKgc$#>#)uD&LdknFYwMM!u)PN+3;zh<8~3-^0~mfmLZ#5IRoUu}8fkLgudk#o>S&dLvyttjWmKUJZ z>P4dIg-+9D@~)OmS6${h?=>dqx9Zqd&evT;z4rzasNC}2WQyKV&$e>D?JDjFAxnez zu2A%nMsEWXxZJZ)554z=(%J(i`BiT7Blf;g%#STfllO^G{L4*3pz_p0HG7{4h1(17 zb0O(nt=?uPaCvE^UIB$#i}y8<{Id7n7NNBE##+7w@}pO)@0d1koYvV&wrKv~Dn1Dz zOPlwzQ2dfMAyD~Zq1wG)g~IK-_nVOXu67|%`C+Ag0)?8#`wK{ZS-|TNN^4$A8T9&q z)T>`;dgb)a028=`tW+2%)FR$KAmwEdpm2*?%7ixtq*jyOIMDLWgitd(aZ6dtQ7Cau zd&i;Xmu9a@L#fpa&~rMG&elJQ*85-jV(MRjeA7CO>%}y~aXX7``JC4|n+f`@Jhqkd zTo;kwIgbfc7Ie;Mir$gWwsKzRDi#SLOF`#iq39)rodrzbvcy6y?_4UB)|N5JuX3AL zu=j;xUTIN^I#&tBzg#2)DyuD2apxMLa9h{8R!DkRX=gDLxU9EQ8-PNsq;n&X{Iac` zB|>R!leOFoN4 zAyC<8rS=1bT1DppAo*pLofSf9?VzPR(s>9-y&e{tURm2&$pkJ(t<*7~P^;=Z4y3%S z3Mkx8Sjy_olR#?qbmu9c`JIbxl=zpGvdRBl_TJ3yh< z(0La~epzE@gHT$#XDJ_c-Um{z4}_Li+LTA)cN#%?Y}uMRp8zTEXaWkirQ{wkaRj@67bI zg7V3-wRL_5lHQU1LK{%HeX*47onL{}>i5oXK+8MZfx_*FwfqSsuAa_cP|HgLogN_d z>diq1JAF_)bw7B4uC{F<@OuH+!a3APXP?k>eDZg*Edr%hqdDkAXAEk+Cp+Wt1^-_& zdv^j#t)_C)ql(sgx^rB4fiF)hTJM>hU;I&DIBou#ugrh_Q~sXeGyec$#>#)uD%_CbmFYwJL!u)PN+3;zh<8~3-^0~mbmzkTUL=}c=rmm>?`qj})n%^pU1NfNtB!5ueBDLV`))9S$}Qhbrsy5@ zY%Ay6uHudmvNZVa3Pmqz^ffSn%RLMA(05-btvz6pU*$GGV(%Np{Me#2`JM>HzuY7Q zDo-s`v+tQuxV`W_7n0u9>T6~KmzP%R6;P@#V=_S0+lZos@?ZhDBQmLz6r_iY8L{PA6DuoP^fu)zkuYI z1$-W%wC1&xL7xvuz50cwS5EH=Fo8?RN`-+!E#m6~QeGAT3b&}GO!#6zYBlML11;}N z2sN_{x0JOUg%a1aZyaiVY4)l#lv>RIJ*NxlZ2hBXz5k^z{`;>!|NDROP3!vS`ssmb zK0eKG+|FWKKIe7KW`cezk8R~V*G1%a&0_+U1zq!*qIcx8t(+ISibX=mQqZ+nD0)d@ zR{;~aEU{3_yOs*2wPj55tK8-l?0un_S6Y;!u2n+uFBb`c%4!Q$+_gq1+}3ri6_Van z+EvU1F6*t-2B1(Y>DmY+ziew)iBMYGWGy!XxxGuPTbSlIy3O0z`%*FQuqb6+JB8w3 zE)xQkT^6dmYqwCi?d{qlB)_X%2vqi2sr^8qR?&3;NPbymSA|eoJ7_77bR7axuZM-E zSJrk_GJ(rcD|HMg)T+9U11T@70t&Yima@9*B#>G?-E|6Re&?mGYN51t##)|*64#op zb5Ns8Yk<7crPcE}=?jY1`$hJGTHbzGaQR@RJ^_VVTi0hG4jenBlS4Rm>c)T=iK9qjT!?bQ9?1-hEInf`!ynQb9h(d#gjxJJ7AphmwNfl{l{ z9CV^92DRRkU2*sV-JO6^t0|!8_>s=mQAKM#-8HVfke6qFKdorJXL5e=M}6V6`Ac8@ zzkmPx-+%G*)BhGa%`mnz1Jl?v%Vo~<&t_uk*R#Kt$F_2w>mu^~^O!(ofqy)8-e7PZS|K3rL|4gax;+I{aW3^G{4bp z-p1aSig|}cDf90XihsFG2vl}isB-^qp>W&l-yDb zzXeFWzR5|yh5Dmk@9)G5dh@jIRwi)yV5L3*g<6~cGm!GKHlT3(Vkz7GUxC!>cmFq_ z<(=(7;r7E?{)7@&kN+3c^3s6c1EgNPIq0C@2eni8gBSej>D>XLv=*|KVJLBp`1_zn zmqwt}YBUF(@W-Imd(t0=FVNiyAZK=KHI<1!ae2E9>3~q`adHDBN~g%JS~rKx%bw_a30-o#jB`w$EDbhZ5I{ z?gLQEODnr8fYj^39Q2XyLr^>Q!{7zKy0*JgD6Ji}mdBvPwW|9#)acSGD7AVb2VLEL z5^BAl?mh)y$h$9fR|BcnGdbzAiq?8f_c`SSzPtwNE8TiOpYw|g>I|{PW-U&;N7Qzh&yLyuj>#>pw2<-(vnX7u5W~ynieGdqH6Szng!4H~-&a{8XGw+`*%C_74+ANe_f&R*GlE@qQEL+Gxd8# zMx}qRRyM_fHO7Wd>jGDn>9m?Njft|)?>i5cwO8?%aY{~<>jSZjn2KE@+sqd5p^YdRQmUIWm6xxVQlzxD{#};PJO4|sPymK>gEpF z(5WGCmu#oL)EHuzeV~Pqt`&U@YP2o{+8i>rG_Cr>73v z=D;(umGg_hb0Vg`+Zt##HgbCDxP8U8d~ON6X2SgP`#=lXqWO)hc+14c04nbc_0J8{ zg025n{`UuU^NDQe)E4+mw&s`G$c9f}9JcL&uVgFd?}2YbnBQ$D8$SJT-2P-+K6?Vc zm@vN_2zbaA&0ZG~4EUJ9#ZT1K71M(OV%e1|IQ1}Ha1hgl4n%<_grO@ADm}w__QE6-`GxlC*P>_?}h4S5!ukGAh?)pr@mAe zEHE~5TH>%>9$ZScXkKOr^Q+q5D-2&q{$A-Y6$Mw3t@-OkWW%S`4%_138nTu1y5L$O zroLMmEH*ZBTJN~sz_xrY32tP<{PNad3E84~ldIUw#P%R6TMT91p#8ng@TKJM9S&1j za3|TCzg|W*eA?x(Ef4M{TRHCy?jgebZaLZTX`kbEKil%TB6xra^UIaN3bIA>K^Ji( zc!&vH4ihzXMQyOs*vRRq2?V=(7y(m;WRoUN{)y-A1p;KM(8rhm(sv{dd zU3b{l2XBzAoNonh5@CL~o^1GZ+i`n`ZTZ{~yvv07<;GwG*`oQLi+C8k&jc4W3;6Wj8+E%=!U`sFsZmGc)D(H{KD1S;Qy z-uQKPEp#ag@IV1{y5f(z0 zNU%>R{yPyNP>EWoL@*{4ZpmO=NPbsB2vkx`%?WXpEu%o8mJW^sNiWO(UK%LeGS>1B zlv@2erT_WA|3g!EPW?3l)>%e1|IQ1|Ha1hgl4n%<_grO@ADU-u__QE2-`GxlC*P>_ z?}h4S5!ukGAheilr@mAeDlj&3TH>%>9$HGaXkKOr^Q+q5D-2&q{$A-Y6@^xjt@-Ok zWW%S`4%_0;8nTu1y3kr8roLMmDmFH9TJN~sz_xrY32kJ;{PNaN3E84~ldIUw#P$#> zTMT91p#8ng@TKJM9S&1jXeZg4zg|W*eA?x(Ef4J`TRHCy?IFVaZaLZTX`kbEKil%T zB6NTW^UIZ?3bIA>K^Ji(bchLD4ihzXMQy0k*vRRqoC*5nDz=sL2^Ucv zI>`hor$eWhGViz)swP`BpK%pug^;BtbWSLKNevTMLa3a#QWt>2?V=&gi?qKl8@`tO zebr&A3tb~y^VjRhhELZWw)LSKWGm-ep_@dQ->oMbKHYZQ-eFrlH-zpoVSc$W)Ihdq zzULwyhVCzHPlSD zXnyG`UI`&fOX#&w^pf|X7AA0cW2N2-^)ZCoJ0hoUn%2{5Y~=L8ar=pF`P>%z%mn>% z8{5kHi;HLvePsfb@1bu@(L37NR?a_M#ZMt*@q~T}MK1}2JWSx?wNSy3PbjVVnKZAO z-V-2OG>2S8SO{4np+2GbB@rP|iCU;cC?*tc$xvKKepiBtnLVhatkft_sHH>WK+?;y zccg*BEhFTd9x1c!50qN{YwCag1t2`F=igh|-!s(BEV7|fUe9c@HGe&iZ1^rXvYwqx&~KHot(we7V1dPA)&N(m`U@h+MY_XMe|WtaZCtVs(OwK#V@H6 z0+kaMs=DW-P`I7$IVB{$>rziO6S$nQQfGlet)}N3kn*w`p|14ccHUZEfKsa$iKZ7$ zP1D1*hRaTu*-Y(Kw&inO&ow6K`#QFj^K}D?JDjFAxlHg zU7_eDjXe!a;BwDGJ?yzJl-3?F$**#oAF=n1Vt#BTWA z^IS-JS8Go*6S%yzQm=qQt)=HRko>auJuO0M?Txj33*^Tht-fQL-{>}fAn#{}TgCjz zqO|pV7Rvl`_IKNaK;?^tYVY|f6mH*pz6r_iY8L{PA6DuoP^fu&egVlZ3-ow|(wf&& z277!!>eVl_ywawG#P0+^30t;EPal(W!ub@_9z3 zf6rAm`QdrShEEH^^NsD)ck+!&|6ZtW7Lg5|3c`!YcIr!o;R0hLrzH;C<>94di{@p9 zFu$t(y~6N?Zmyj)*H@S+3&i+w$;k zvX%4R@E#(}@0ODdpY}O!_p>dZE5ZkuFuzD|G=V+%6i@yh!`|vf*pV-&Y-`y6`o!HGjR1Z1{BDVOt-*LAG+f6~0M?`Q3W5 z;nQu$?H#t|b3^zp6Xus2!wqDM=6f#UVfa21xI7?=Ug0!7BJUd6^w?!?3O`|jeyfRX z<^0q|G>4xtfy#^UbEeEYTEop`i{_WE;*}7xw1i&^MK5_DZeaqKH&*JcP#?p%y(4n! zrfI#c#zsyb9Jim?md|bB&rHxSx3R69zqp9@@K+{K`5ykp6uqOJZRPyKRs0k}7Ekz> zQ1p^O*uw-aUJDfr`-IY(pGoto>AeB6MRUkigoThL67Ca6J3u{y?eKzowr0zx#X5Tg|^`sGC`2 zL#Mpn*<@?}VjkJ>X|BUIzjq$l%6UQWd?L*6=93Md7CLShu`QnqdKWWcez~x>fNasc z#6>LcUCIP5%ZQ>^I87_ayFxatbeW5KS201qRm8S(UhN`^d)F|5%DUdQOqq9-_7;;Z zn%BFE4MNCL(z{V8ddb$_5+-ojWTiF>wY?X&Ekx3roThE$T`8M(xXfj}JDH&0Dq~wY z?{X34y}Ow}WpD2ursy5zY%Aw|u42CsvQ+dQ5Q<(>*;~N`E(a~tk={c>Y3(qR=2f-5 zm1K+NqpsqZ5VBPD9v6yVQY8c`CoEKT?@6I>JKcLqNP5?$-fAXrIb)^H0)<*l?>Qjl zWi>)w>Ba55wY&hORxc85T-aA@Zp3uiaeI|*`CQj~jS2eYI<}Sbbr(_JdxHs7ZuQ<| zir!JrwsOAhD((m&OGEEnq39)zy$wv@a?e6N?7c6P)*dj)uX39ovGidY=fz zzuY7QDo-s`bMG^uaC_1FTu6FXYi~0XxV*GduYf|WrS~Af84W07(W|OV?>v?3ur@0Q>{Jwc)E9V7$^NBFOn@=`;TIjf4#I}4c=v&N$ z`Q^gC08ywh&2ga+xr+Tl$WqaFKqz`iWnTpoxE!=lNBRy4 zrM1IMnpf5KRgx{5kGhIuLda6pcU&lbNtF<&oUl;UeJ6#&?R4KMA?aP0`l^}0<&2d& z3lwTKedmCbm(>V$r4P6B*75?BTD?d#z0hg8Oy1S9>8i_I*LRHx`mH*)mGgBMQQvoi z2~=+N-DHa1QO~w=zU?aR2q8;D-(8{TC5?RzOyF|QLOtxeFO=3EFv+iSn;)_FjbeUm zQJVUm2*tnLBm^o?EmU*gGof&M(f3?PdRJ>-GZVPHv{J8tLan9mHIV$W_kArwY3+@* zd<*2qKCQlE+PraEe=FId`Gc$YB!nz&eV>Kmm$V6i$`=dO-uG1~+`jjH6O!N6E(9t+ ztkh4SQ1kTt0+L@A=<^7rHLs-%_W6L+t6yk(<@Ejl6S#z|R2V4KB7J>8%F7}^;TE-& ziM|++T21!FftGhBgqqopTgqCFLWyg-ZyaiVY4)l#lv>RIJ*OY(Z2hBXz5k^z%zpvu zpSpf}WEz`hu$kIfY|H1o{@F~>_jzn9=eaH-zkePRs4VE8&lJ5QpKay5&{ZrFLY9L5 z#X`|b3i}I~z-5VrTHe1@D6K7Hl3(REuVC*B#k|s@6!otXihsFC2vk;EsN()LLgBWq zf31-8uG0QuCU9AAr8WSCT1o##Ao*om`%8q<+9qqc8OZJZTHV4lztL^p#@?5Td51+Q z>)$C9|8kiSsO+*(<^8*b!fkK=9wGT%c2D*G#h(%L~wd8Gdk zka|5VG`+I6zmf@Dj#{Z>K%rLEe;i18Srt&Yov@VE{U?Fc>goPdK=V5<^;Zj}wKLZ8 zER?v`^q+$oU0MU=m42-ooX#)zkFP5^s|0|GM{oel# zX!^fb_Re;oaQk5`e?p0?r~en!^3p)R2S~kobI`$lAJk6W4_=_FZCeQZUI4am4mHx> z2Q|7X0;N`?Ip{=x3~Ie6`{Uxp|3u{f9@&p6(x4Uhx0L|9g2_(R$D1 z{Nj)L!fEq&>ebZ0{eiz`M5g}Brv92`RP*n=$ZTUX<@1b6|DLOC@+0$%4WAZ7<{R6o z@8lbm{=HD$EFv2^6+{-3?bMeFBL&7rPD>oN%Ogw47R}2HVSZKndxhZ($=@p-rlQCy zvNeCbh-~<@+F@H9SwpsRUKd$Q#MF07BgMu>PU{`F8`zf5C6SFxm|xx+DIr@lZ*moz znb;mdWs9NA8??W-8NQVKy~ANDi|iy@^ViGBhEKa3w&juCWGm;rkv&A1-z_H_KJ9bd z?q^#*S40jlVSc$XQbD$8KIkHjL=G{5%VDCXuBeSv8XGwsb=)3fTRvAsjx#~OT*bC> zKH(y&BPW?a<#gl}Q|29)BGqJz<}b&+diYyNs2+3@MQ!?r$hgKXt|D{_+v^SkwA!>8Mh+dFK_=Z45#Cd@B4 zMjFT#&G%fy!^nLmaCtx!y~1gFMBX*B>9Nb)6nVk~{Z-c?p*}`%dq?EdP16Qijg6c>IBq|&EuY&W zpP8UvZev?He{m7*k*`dk@;&m6DSAgc+sgTetN1B|ES|_Oq39)nh=&PWycQ}L@d>3h zKa=KF(+2`%i{_B42n!)gB+@4oza%0ADp3oSh{S}#Eg6Xm$?r-qF>?Twl$9C<3bk}( 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

    @N;(-VC5K!#^BzT% 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 literal 0 HcmV?d00001 diff --git a/bin/IlmImfUtil-2_2.dll b/bin/IlmImfUtil-2_2.dll new file mode 100644 index 0000000000000000000000000000000000000000..6fdc89e658591f052cdf4eecb1621e50f508f18f GIT binary patch literal 158208 zcmeEv3w%_?_5W^?g%tw35mtg?S#;HCtVV+xx>$FU4cvu|1_6zVf{h}rS`o4c3J4~t z?C-K|YJL7{l|JlCTWzcOs+tf?f*>zj1oc;6ZM`un_$Ut_?Em{cbMHQqO$^l9{(qle zKH|MQbLY&=nKNh3oO9+()rC#AT$|07hkuEL&Gs0c{0qqcKj(jTn{DXmCx+S{KIHi^ zkJ%&7kC`^-oAbSM=UsEfyi2e4)?WJUZ(mdA{l?|qdC_lszxi!%=$xtEtFO82@{@)P z8RRoT&+NKo!x8`W>Alv!LqE9Y-Xrn*ciR&8jFjiTdtCC|dyiY5pWQPW&%rN#cF!n0 z+oEUO%kPf(ug~s%RMPj|Wf9%f=wj_oy8G%Lrp>@X&nf2(qA9Z27`(rz1NrDb`#<96Gv z>FH?7LPvT+=KD!?moKbC(r?Z&o6NqO{jk3DqBSSYyX?}sOKrAe-$g3B_a2_p@J#y) zfP79;pV{WPkWmes48pS<&$PdQ&DMOcl;`DL3e_*gzVt+hLDLJ9{^i+d^-*qJg1Dg49dQ}Ej6n8XC5@)b$?%Vd01zqY7z z-*I-^2L7ePpM_72u9pbkNf7OhZy?2l|6x?%YXqm@pMuvm#|ca@{)See%J(ezcV&aW zY9iq40)L2t{}ZH`@M{(P6-Y7RUyIi^$G4bZG%EP}E%@WI!C!_?jbedMY9@Y=V!|J$ z;LjmAW&%HW1%8-d9HZb5jhOh^acma+2>kUs((#{y-&&{epB?_QXcembiUogBHu$qp z*0@sOTli1GpReF+Dfp-075Ha@ak+wjk_CTcHu$S10RCWsZ{Z&)CVt+WFYRA}6caz! z;uZL3g5gl`ziz>Q{FrR`!KcRk+le0w|41?6|3JZ?LvZ*b{_zU@Gr_nItwPe-7W@m6 z@M965^Stwe(}L#(&j+yvwDyqCyFZagXtBF}%K#~&f2`^6m%bdE;agaCc+^o@y1VPp zaQ()FYjntF3n$vj%SN3V-J|Jttyas^^u?zXX^n}cgTns(OC90j{arbwiHQDpEmr3% z()7qFn%20kZXiBSR6CnAeE>_i+Y${&FsONe`DQ%gy-wv!s(y5Zf#x>@|83+ zM+ZGg=G@7pLJyr%cuX_+SpD8WT`B86!7SriJ?)elsWagz2B`YIiRdBq>+{%^E{B%b z)U~DY<>*xN>ngo1tiNb}{t?!Ju)nQtpw!b<+#A?G;X8tL0IUM}XF@kY0-2{2p^3Jx zp_*Rjo2w%$qF+WtNWZn*jg_U%`U?q99pE%2JU_yNy$kCb5}snm3bTvd^If3BJ;3dHsGcRcswv+r{fP-3+HmEav8i%4<(?8Jkea2OwR88Nm#X`Qo z?DhawA1z)zDni(sjM0#cP*1Cdc5CcFHEJrEnO?;~!S|Z*&-#4$8nEePgWc?iSJOvo zq{l-mU8_4HY}xyoey-Cv4a2X+Dx8`=5noTh^Ds@H*Sir4v1n2#1 zFQ(srMtegmB0g^fqhF}Srup0&*}>HFl0;J^oPbCkx9obLuvV*IGs^hIXJ8K?8a?Ej zrLZ3H)wos%3s+PWF1vB0O>h;NRJQ-P*$G`=f*B{wa3nhz87Twr;l zajj%l;JsbQ?2?N>Xa~_guW`kf*FLRrYu(k4k>}19eyGK7S%x1$m)lkqU&dEgLHRQL z)S6rclbY}nScQ~TOnC??4>6?~Da}mTjFinxc?~JAF=ZE0c4_s7J$fI00$5J^?1OyK zxYgBAk7`sKn*R0mvsG@i%FT9q(N1qz4`4==m#}3ncaEmFxC-np_auB3c4szsgGp+j zvLua}tBtT2Ozj<|&05T^#ez=5g=JcckzBx?H1g*4M%O2aL{pL{b!SKaJbeGBeZmh+ z6*kl!EabWyu3wkX+JmyC0V8kYYPG}A2BX>FP2d+K;fz1>2gSMq&feYfUFRI|u9xEDcj4HW`l@78|mFstLK=o zc(|b6953`D+vnDU1Q>!r#rM zX!#s+EDT?5b)FV?gsTX*VUS8ynJVW&)EJ82#EcL=xJ(#baG6%$vdmb|VUM4)EaCb7 zM3j%8vqG&nTx_(&F()F?8f!jPeP`Fg(9yJGhOxW!0x%~@n&xG#nxxBab5T6=QiMa#zQVszi=*AP$K(J6R_r`)= zz1$ZI`jA$Hv?AcUWJRz9k5g6zPf4OZiJ~O_E&lIvmt&C#dOtuy$p=^wWSK~QZ_dy7 zU3Y?=lE42D{1;ClWYGU*Axw(e;HO$~M<-P>S>(+C#X}KickEu1Q#U>mA96YbfQTO4 z`$P$#8hM9;!UDV7>~)80`sBS@e0W%Ec_R;^4Cemiy~bYVYw?P`T}Oiae-h?2w(nkJ zuN$n&&l)ZiDkKr0(5I0ml^D$V@dVmsYYX|jwvhf@NMB=I=>iBf8IWItEX`I~x(?5P z&2@e=un_W?%w)_hNRUM#oU z0=wG@dar=qXoLi`h{)J7B&Fo!_-3^CI&wHJcXqV8z6D(OAAqRZT4=WQLkvbQZ6#1y z?=qOu<3ypc%Z*~(#AuDp(SZricp#xki-DnPPVOi%(ZMn`xAo4wj$Jrc270r>uOa-V zZt!10!w&|2PkyM{Uqbl$=JYNsk}AleaDf9wc4%HFtOVWN~X|tGQ7WmTs%_OEw z_#+Pne$TB!@Vt!S2KDg6*<2x9Fh`y_9I7xUG>1-|(4cuAOVXxh| zyKb~re?y^r9;zDF1+|m5T(oR>?AW&E&CRn%y;ZY_5UH3AjYeAg?=v|K(4`Bm{2t^VW00+8^c09Ivf`N!0c&l|tH zWpo`9FOx*DHqGBM55K3$@8S-vexGwbeuw0D{l4P};SBY0hcR?0N57(wG7s21DwIdH z{NJm7fQ>S%Cg!ZKox306<{aU{nbSk*GaI)?2SVh6q7(9xYV4<9PiyRHpx5Ittk-RKhxk()n1CPKxO5M(vU4 zee4F4&_K*473P%zc~?R7SE`s2PJjSMXJ%_)I+S-*-Nhg9Ra3BD{thiLTt!M`LP3kS zmkGL~;P@PyR=QS;HLk*R3hH}9Q~|wTSqh;Pdv#5}!0De_=vui1x&EnM*Y}_iwT1i@ zqg*S$rQUq5@6E!SzUHnyi`*arS5R-p>u~Nt*PxPw=czLEAnup|)}mNh+)-}6S8MUA z?Fmo)crZ@t7`bQ08b~>|MvF&$frMuw^Qct_XjCP}9lL`9CqIx(jDMf&Q*2uPcn$lV z8dd`RJ=6~g&jnIC?g*+vzM4pENpmQ+qyyUfDl7;5tlAjdMfsv5sBcSn-hxq!R2lc| zLnDn{Z%dZ`V#4!$GDk;AW1E?Co;%_BeKPAZW<6hwTfBjUO39gt*lWA z&y-}=70kNO%JL>Wrzf*CW}Rha`4XNZl3B+y%g3zvbfC^e{Sl|Lm5%XzBvHTM3HC>! z{-u$Ew)iTJO6dmU&_OI<&YtCKIjg8+oq5T{=`7KdpVIjgrYD&H+pg6Y6zYqH>({yy z?vTD|#SEWU-yEW1^?75GgRp0SGW2ITvo+4>YRu?NDheZpfzSEFt+h|2MZ{`TnuL3> z_5aC}s=sOA!PgJjq6iDOEQoW)k-0D5Yc7auWI>$DMC?wmAgVs1GvVd|8YFs5oke`Qq){;fM;$VBYs+DA+GYbxEhuKn;efI)yiSLIXX40SGz@rI$F~QiDFvmqqku3;ZN$L!7I8> z2St9R<=v5TDc(G2w7*ukL^bEX4N3Qox9sK zk-xwF%ll93-_by5Kl&%~sWN313GQLOia>JkVx_CncSUDHS*cY0MG?K(GzCOGP~J9h z0-y>jvF;~B zWI{C14~vXDHF_M2)B)7`E*M0hzu2VA7nt%L-Rv8Yar4}+#$TG%K-hrL5xdacc{@^| z_W(py_E4q2X8CmcN7uEHSkM{P2ZUp`D*ps`)DhOVca2d^uCbaN^Rs_puo6Ba!e7i@ z@COWr`UGcWTuIasiP^gHkj4+4DBujbR!=Cz|Fpv3iU9tdT^L-pw9xKqe1?n|Ru=z4 zr>o(&_`&(K>_%n@kA}9(zt7bO86BTZb}w60Xp2s33l?IsPIk9d6e1OBWZDyy`3Lx` z0dlG3p{@gf(R?6TL-QorUr0ndiD+yTV&DhlX?KE&>n^CPJ6; zz*p1+o7Sm5dI0qqI_9r&OOM=L*e0T%7oa%%Fj)A_2&>i6qXj4E$lcm4Yn?)2x`XzM5PZax@iqAB!MgjP*X@iJmIlADhNCVQd;tgI?Ga zwqZ=Rx8=D}bt~&DQB07McV0oa#40r9T(uLxjIslFdJFatT09>W5_H{=N%7%!O!0(g zEGkTi=%^&OO{DY8N?P0U{M{-s7a1V4C|!OCOr6dpP7lu2-$w6#nNv5Yz9T^_TzpY0 z_EynD)J6-xe(9_$j_Bb)7+P3Zokn95GAHccJRg?MAU2iGDrh)zp93A#1dBUlFBjnQ z1U*3sq=K4AZ4P!qcFo^0-y4hv63{B>lkr7?7B9y-W%g?pr7*dK-UZD4Q4nN*cv zXLU9ju+ zsh`YGh&Q+rR3`wF<0um=+hC@PHydcBO{YK54w_}-6gU&_g%EKTj0N4*rQ>mih|bCt@@f)j4eYooYj^2tyaUOVdd;Yy-Wt-w!|w|2*@vBGBfk#n0dKH)4GQ=Y&6UM3 za6=l>o3ST7EeLW}pGJ>|`a0-(5Su_4hwjv3G!L!xu{;I*Q}*Mzd@Y;PioMM@#)7P{ zMZ`Aat>f{kJKQHQ#WMwKk7RIx_Zq*4iedwjZz)ZF|ET)@H9q2=F`3`r#P5@TB7dE) z>5D)UFGX|+e*>ZKs2c|oSB`Ra zsM}oMYekw~P<$BDs)Mw&nw^iL*;>5t_{`ScI8tZlYKli# zEyZ4!E$tePE_S&{&4Vz2uNG7D2mAq>V57inVO1`FKsNw1IvnwDaW(uAJtfC<2Y0vF>%JYL$gbpBe7x7fT}H^ zNKCDk#SIHinYrMc6Vazshih}R+%+1Oojlj-oK~=hyy)p*1|Vl)A}2)rYpxrhjhixO z!RUz4G{na__+U=3*dFAX10JHoY-d*-L(^f%jXSPB8R%@>3dfN(8SDc5Bh!OG4=TH^ zHKCNgn|9z?SU%w#<~4S_&aJ=WYqC;fEvHR4X+cEB7|F1A7QC5Aq}y}jj)BNY+EYGw zBau+12^x{Or>^;!&rCB)mi@8D)vem{uNuHI+eI0c^sn-o{!iCn@o6#z6fL_7K;)k^ z`%EwXPmMx?kO2SP{!a(xuk)yEHn)En{zT$0!>!)G(O-rhG$rt$p(WI`r}WPs<{6s! zy7|Mr3{z){hI(j_%=HHTA!LB*{wDJTSfBnJE_VfdcqY1C?#Zy>p5w)Dw0k1VxNb@u z(0IU|ES1i{`s<>F+ zVS>*Le}*W`!2Pbo)PqSS@CQh92J7hz0MQ}F6~T1h=;=RZ6`}h;5AOlWo1-Y60p-jAHB{T+okcUeWquD}>_HDOSBUo9B9VACwn88iCF=cZCkCy4?VL1# z!jIK{H0~G;Da@Kv#+p~UuNOra=I-l-&@&p9a;kZJ7TRExd_W3L*{>J-s56a0o;)!7 zbr$=tz~2n|?r#5;D)a-hFLzsysL&MM==)$U(W7RA6H))X(fE^0RH&af8Q(|MR6Rq- zQ1_bJi$fqYiKH96puU}C|Gwe-8@v!EjB-7wHrBcAGQJZ)DJ+UX#<;-zbJRhJ^ zjyt%4i{)bFi&d21Um5-d@DCDNMK%7_;NL9hLk*sh05y<_2hzE}?IxD8$cJbF3@o(0ioeon@K?GW)PSwV-Y4dO9U0T! zMQg-gX_$89)V;97n~qB7;INr;RMOC*$GP1!oAVSn6*_?S{K0(F4011|tv8C$7zJ;r zRKT>ADpO`xfRjq2luY;bV1|R1#jiB+OXBj&6%&pmdZ)7Y%~wQ87q!iWB}vUF=CHU-6|)KuzgBCKjU zu^z$xvs}+#4vmrndV((3V`Sg{js*j9o8b=eaYZa|Io$psN|)D6isfOUo>Wq&CnPqZ`QHbG_F>gw!VG<~6Q$5z^q^uCd1x*C z`Zj90n>8I%qUDVos5kLNnKo{6(Sk7?&x(@R*cEsL)B|&6Y=@SBLT_@>yw}kjOq}_^ z)_hUdfY@;X*VaP|YCdD|4HJpqzb?+P&0~ zhU0l7G=Igc>yD)@&YK2!El$Ux28;!{Mjm{KZ>Z_IO?VIn5BjJU=sZyw^_gYKK?=98 z<$#7=fwdef*E;}$L8Pl`P}eXflQAY+!nIl=tyAJX%3D&cXH zSGumNK#95jmIVWI*9H9@^Ds=HgM94Tq4&hYJ{fZd?pYv(+leoFZ{^|s53xae1j zC}}Yg!!DxQW21328XSfca0H%Bk@yUn$Sx`h>+|vD4Nxt-sSYk#Jl>QCEPJ|~A`uTW zFNoM#x;w06pgQ%M!cctduyNOpT3Sr2(CnoBE~L9E^)@(w!OA`tTcbpq7QZns(dv(m zTKuL-vEoSs<*KET_6Ad@rbK?KhL!>HOr#dm=6oeL1|R1nm3>9&R^`A6X{`k62{HnT zjNHjV@TV}l-l+W>$%X4lb>?~^{I1{U?IQX&+^|SQY6E#;eX+9$YHuE_`*Z;g)_tlD z*1b=Nz-Pp%QOgEXV1EwQ{jHFzS?cUvkArn<(c6rJb>qzQEzrfEV3tfjUbg`NvmdWJ zDO`UeeWR-Mv&?c;`r6b%I~@hX{$XSQiShtHBP{OAcU>Hx$Q?eMiZ< zt&-G!5vgx7RpbkL9uIn=2m@gJ{Vj`(tdk`89v)s~f85Qg?XcsF+@va9Sw>$%rWXL9 zWQ><5##J~M`}B&uM8~*_{KbdIrWE1_RN~-5v7lG4$cKM-=f!}T@O*YCS`l}A2dDnk zZY1uw$$W?F(MsQTz)X0a!TEwr-=mZdS3UER?plC#sw&^N4;L7=_;B4OrQ?nz@PlFl zYP9wSUo(4xKfHFRH>%kWC&I*~tL#}WupRoagvW#Oct!Sc@TD`pV&+WEOL#uUAqSP^ zW>&711ux`RlUeVhv4#PrO?XrD6P~rnteeIl>v?7=m#&q*fS_zm0pU8{)5B`A2lx~rGm|}Ruumxr*@L6(Q@nWiu)oPR-V^P;jW_(l z*p9ek?cr<=_mgo)v-zGjf}hc)okW5bboat*VP5(O&Q<06H-axn>A2&`k*WcGjG!AB zRU^2dRWJ_wxbgDG>NW1^MB|JZ%*jOf6x#oE$2>k#2*3YU0y7alG^t?8iobz~iXfhl z4QfR6W)+SNa63w9}t*{zm3pFh&Y#>{@VBB+foR6 zS@8GdP{MJ9%;pn+aB`5Yq~UJ~_)Ks33op4zJN&9pUmT?7D{LyA zLU%VO@psW)3xDsEO}xUKO#E#bf?~Sk13pstE53!mO#FQpDi0HX)D@+je^S0d+-~XD zyS4i3mDe!*PvEMN^hKu4*Z*q7Ro+^02=1vH4!AWw;~m z=HK5S+P{$=OoO?eV~ zC0chMkH1;=UHq3z(+~E!7jr*V!hH{XM z({)s3Lvx+GDmGHGozcUP-c?WqUo}b4+)=m(*5C&Lw9+Te)wmmCin;%Qb1XJl$a2F} z;c5h5#P*V&webEML*Kc!a=O<+YYxo~-qAF^2c4Zi1rUwyw3CtLrf{y~{I7;L<&I15 z3w(*MW0L@X5WW@vz$xM%h-AN={(%Mb4@7y`vSaiV(45L+uX~MC(9WE&4)`&I^U%bL zFv_AR1NcyqNF7t0(IL={A)(sc`6-dj`Q)GCmSnh8A{o*m&LP?59f4eI{pjp!LPCQP z{Gvd*iW6fo)|_ldZ+(R)A^QqE!8dY>coG)ibU%uJUT@1WXha?#;&7O?w*%N)dR(%b z1#}3t(;*Za=@=B}<$_Te^#(V#H$pei(i6L_g6R5;Q}rqPDbK-Rt%bq~`*NjmLbR1C z#;%}60jsOi7ClDO8+=W~4VDaS+3Dx49};}XZnVlAZSVXxO^MiY!__+!j#qob`a0tb z$OH||t_B>SL0$#`_%ufJmA+*F2`F;T1F+wi&7o?n^6%|BiHMb<8fof}NHbvKm>Z_2`Fkiq*qSS}1NK#PVViNB)L#eMqBWPz zlrMVpgkF2=(G_DhPm${Fo!Fb8&q;I{XPfE!q$4U_;c1((2HtMO)5FNK%7pbDL22%U zu(jfhk{(I-qb1Z|g3T&qeAI=;29@jfFma7V$B=8fY`@DN{;$*(A}jzt+-OXZ3hO4O zDw9KAz4vYiyQa&2rM+t$x=K2_!Tf!E`oMatbO!pNAX&yiJy!aQx#BYIgA1uC;^C5{ zqQDe_G^I~vfTroeWQeA~=5&>6Sl@?mI7UQ&1B6S$E&&;U`|J&@wv!HAjn4@VKdEeZ zw+<)8CWBt;w7xViVVva z4&9CT%cA4c@m(Z(!zz6f=OmC0ghYIEjaNmsw}oSQz93Y2PWUIU?W9T}DDL#|)Sv0@ zIzOxr6leOQ6}6}d6tw1tP>`h6eb`kThQEz`oSHv{oIfctdrwTCuF!VkodWOMAF?ZG z4wk{wvNjr)cW5oqYU89V4emNz({B|XW;}Q~ctUKH>WmGY;XYuYra$akhE9Q`R8**o z5f{p$tAIK!*nLk@%_EkOnd^MBBD73_dM|bg5BYXPzrIkzz?$nXSwMXPgcH^e>%v)B z=-sXJjTqrW=-K4o55j3zgme2}t&Pk6B;jcOJwiB(z^*QGcj5nC7-QB}w@TxIC`#@) z6;;D6$1F3_fEy@ukKoz-NqSoJfdOK0^;rIHvh= z;Q0q!BEbsC<>;-$-I;#6hDd7Q5Y^xi>AT(ttN@TL%iQxo1CzZFtUz5=dV7_BPgRoj zOnXC(01}fFROR2VCfHF;woO1Fdl$D35x{VJQtj0 zFHg?78tG*l(XSp6(U-Wi_}N~Z9884kKXYrYis>-SW^%^N<~{OyAI(Fz76^gw2NGCS z-H$c@l4r1T#?J?eGPosLXI5E-D%&Fd{lI}ai>l2^keI|l*qTLW;uI>d*}u;#H4E z;+3yL{rFYU!eEI0xC@r$ICtJ+oq#X-^tWW}TE&@s$y+q-Xt9X_;ADix6Y>)v!E1UI z&LHefxNd%oxI9x%+!f&nx~p*&6V&;0SG}B)F7Dvr^LdN$|KqN^28vVT-c8EmBYI9! z069i@qFScM%}&{CQpt5#ukm@`>$ScFL>b+r`A63kb>2$*j^|vQFF~-p$?6eOk2BTd zbUtLXL9RG0REKVkK)f-G{3hf5f$Ry-KjJ4I=8xoINU-6`M}aSp$|fTZcqE{R-a(Jz zI3@>Yz-I`=_ymL+g!d_jl!ugJKy8ZX0}z@Aae46JPELhq2dBQ9314m_Pb#k(O-J-! z0$n_5D)VspT4Gp?V&vPIr%eygU+_i;0C)2j?1D8K6QGrB!nFCP>s!P=)ssJIrp|~i zVo;)(;jgrqH8a4P)VZ0IGQ|i&b=D+=&XuqCA}MZW43#2QqB1zwsykS^wSi&k*_)3_fz72`A5xNrks zz{fKz1Xg>x`xjnz2x-WQ|AeBJ{0Ia{s5P)&m?qhShXjDFE4FEhs8!U<-NO7J z{ttvE7RwT+=(%u!f<8eJFp#DHQc@Dp;|kI2nDKhxe`A~n0Gu?dH(S1r z0Rg?q7%w?8i_9@seawLO)?f@N23O+$5Z(Y2-s~Rm-a%K)y;1M*uILVLwUpXq9M%Kg z-Mzwt>ovNY=8vfn$E&a{;GhP~kR|WH_rK{N{4s@JWx}6D_#&Q*d^|AtKuu9Z$7%eIMCsP>o?TEFGIGrlz}isd zdaxtBe4lyT-;9653{(D)_&4%fi69dHMt)oIZ`8+-PjJ?M5L!%sXUnxjh+O%vV#Cu3 zk=ND8u=u3dlB7S0rl0SoFA10()_?e)#xL=LCyJzm19O8ZEQz2bN+l&Ic_Ao87n_Zo zf0bqmNHau0f=JY1Eamc$b?v~yM4wbDSuemx+?Q(l9#=!1)K7+rjZqm{31xh+R>aHL zi;g8clhmU^J;tlYX?&#r$$TUyQ%>KR{=3E0pJe*)#?SE@kBLcflhN_466@&53o%R@ zlXT=YD?zV|#HkftWrMI|GwaJhx?uYQ=y{5atA$H~5my$~xh+oI0p5+xaUS-dMVkNO zq9~SJY%`xXcD}|zQ0%z}B2)u<<)`F3(2j`Iui|Btq{qwnE7>J+59!}%$F>_kHez2T zB&|Gy|J0YTNOS}^EZtaY*7n2~0Y{@*8|2tI*!qCWFzB^z7g-X4v1RKWMqico0bBm< zR;+^3)H_6G$knFET&T|P^9Xo`0z&DzMn~^V6Mc7!Qn7c@SM|o)LuSwq#}}$^ocNUF z%upF=f(>R77IMmqke4Fck`^-T2S&?>-u=tsnl~qE9y!jmZES;-?&Tr$C_WyH^53gc&FgwH_q3>7?M4K}3&A;B|#haaZ?@{5X} zA+Z0|@iVBE*QXH8+2Us)SK?Zs-;F29XN;#L?DfDwm=$bo~??D3;*JLHbd#jQUv*D zlktWG(~><=awY!y|Hw)VHa40|6;3VmT&lSHQ7ZOL#@V=%higZ=fRes?B;^51{=kN` zNVYngjBjMA|LIpU>W5Qqa`8_J9wLZfi;uMzJ0Up~lvZV+yRU7^G^oWM@GZk6uGC)- zGHB)75sC*4U*(GZXZkk3_);R#2!q6*0j>T$ zd)?Lb`w^t(49vRt*=HHkaXy@DHg*$pd5~OltzPN76Q45lehAhuijI}0Pi%*Af@mn? zjwcwN0E&wCiW1~gTr86(_HlclWNm``@5`NZ(|tUE{~0@S4MTf8VS_*LJ zP-^MAR8_I^z^b^^tYS>>Rs0qxk}8Nu?&+(jW{VYaOc!dp8XpX5>UIk`wrd$PFwTzw zf-UX0&^KZtVqa0B#jk}ZU|{Y*5HWJzk`dMX11w2%lW_?K4w5G5`zvSxC)q2|AyH?Y z`s#V3OnrsG!gO5124W7i0CNa8?rDXDZJhTq_vbjQVQK-YktbS!i+L6u^A!o8Tuc+3 zLupm&){TaDB!`SX6O^=+rqA4OK`n$TPy!@kINt$~_|zix>jY9}QY{3n0FDv_MllSd zI;4WohJixH!%!z8OCq_?g7DtDb#ocLAxB$4c}hc5?Jl%kVZ z6>lgpURj6MwYOlml1QF{z=;&tlRFGI=?BLjfT(d5MGGJ^1knGeXTJ|#=kzXr_6*&nJS^!O!U8l1Aab^@(2!S&?ym`)%Lt$;lYU#B$W~n0-7?jXu%0MX7C}S zLYKfWSklr-V_O3VoAfcUWOghcZZ)l%e`e7w1w`?)a23@Kx26+2+OPVV?X#G5z7`;0+daW7bwa@s<3%$0-`z5v~ zr36TwFF`2Y3m{~^4dg)5Re>9|mN#<}?ka5itz#hiW;p_)PJ^gpAlR7FsR~P~Xq$2S z$R9Xt5~uiC?$*I5%y`8MLDI1Dr?IQ<`{O>^qvgIVu_UuL2MdC&m*#B${Q)%RbNxkM zfxD);n5FIuf^NBuBE(Lmk!@w~HTJq%I9qyu`}XHtD$u`Bf6ga=0h0Tt{W%*s6~%(^ zZ@ypXp!_3`6GJSf_rKo%@C)p~M)KmDkZ-2pZaF{X;lykGuU+y1N&(%m2HX)_&qQ_S*Af2>obk}uI8s|8AY z^y&cpu|A>ys-E)4>N0=-@AAhwt3`Poe8K)$Msr_azi@x7b3`2YH~V8V5Rb#j&O)t_nE4z_CVKk3iZ@KhfTL)iQrm_O4i_lT+Di}Ppt8?+T9kgV=j zUz9)7GP9C?`!ik2hzWGK`Qtx&@n@=sPqL=}Yy6ou{rXGvXS(SXG3VW&9(C$*wR+6v zqc?x1F>ewBy&H8h{h5HrEdESCf&`!G&velnAg~_(O#gtI#QJU~{h7w%Gx$G=Kht)g ztH1tCz5Da*FqS>6bW|m~I4yIr$%lpk|H|+$04;%W&Eu>Tku{!XjmS)fOR%=zrsm;x z$;ZB5v5|y|m}m$ISMe^f~Pr@P)Kzmf4=UoE+Kk zbB@)Xdw$h7eilgnKZl=v#xCXX<=8Ck>Baxb&roJiYsSwhqc`-4Xd(u~bjBKbgxFhq zn%$Brpq~B+-TbFshJP0T4mJ+|1z#|{nf_BsGsvUQ*c5@HWTz_rM$&4#@f_8jY@Wej z#vuKko=4ZII-sw71a=|RmhO3UIIxgxuI%sK)VF8&9}U<`LJ?hi(*I~H{K*c;|EQ`H zn#TvAFwN?JH2(uu@dfxF@jkUS;7a_DR$*gcJp40sI^#aI7-E+=l5R-9yiYJFZb&Op z(sDy$VNP4OjEtIqn8z75^ECZc+;IlurKI}{Z3DXD@f9$hmzPb(Qx92=Nc4K44&o1z z)6)?tIlq(o%edp_u5R!bSn#hl;a}VX{?r42|Ki)-;2&neA7aA)?7{Bs{}9N_=J=Fs ze|CSRT|Y&!G=HV>2v^^95dKO%=a=#)Y9jnhf1({QcYyX`xj%sW$z*&}`ZwiiM(-Qt z5AyCu=EO+%2YC#JgslD`uRhJMlO~}|#~6jM|4jdj1+W+NwNz)yyeV#Co`)7COIAjf z-QQxMR7V#Jr;Hay^55=naWv*@|NSj+KlOR0SAthuL3pi)a!9y1>5y=2%K0EV%(Qo> zlKu&QgvGunaaghCk00;Y4vOfLFu%E*PPx+!t4uL#^|!9i~=Z?koR4 ze}rD{^B|`G<@b5ebpHvgv5+~l+~;8#?-${V|Ihpp+D>MtdiO^dfG&wYLec{gQ$l9_eTjxua8&x=@B7XD7s)R7UoZ2nk&r(8C_FTYKf%?9;xhjG!5(4^0EkvttA ziAzLx9|*BPBySY)@;HSuyKwyxd8~*3!@T#*rDvdJAKqwu{g1NpU{~Hx{|7nGdT{;^ zAH3VM{->YJsQ)1RAF{8vw44Tv6~JC8+yh~`y)s~Y;{nzW)9XU`d0X#uHDi*zYqLyq z?(5yQR(_5X!)mfe1lsvq~(fh_6n^P09G_SL^%-ksjRo9<8bZ-MoW z{(Vc{d+pyv0CJ%H`}4RFss6#<{aj+rBt5S=cH#>Eh=b@~I=za~8}jcDiQ4s;AOS2o zHsiiur#g3+^^VTP>1Ao0@O*cJMC?*$B5NUQ$@FO0{P@LUH+Yxw5azzda3kNY1t zs`qMW!ElS_nJ_gmeiA}B_lVzRXI^^zq=!`5zT+o}cM0x*944jXj!&Lf72;5Ev^f@K zNVQ+S%4RWMQrmSTw~ny>C!-iU7`!6;T4Wm!s2tw@7~>HK$vJ~Lx0pFEBs|w7bN==h zmIC&k4K+=A^K`Ca7-- z7k`ZSr+WTCgawHQa2xvD_9#4j5uG$P9Hp>LrsI+uYO-MWB*Y7?J0`3@hd96j1pzoM ze-%A%TnuiDVG|xIonH{H#T7jr;o5cK`1qSjn?JmtwFvNJRY?~CIhsH(h{E7`j1DW# zf#CpqQBqaA9b74_kKcy=EU(0I;`$B_0jRil|^9JD%QfLsuAm-uWjKM`W9(IT8yX?_d&}dhED@vi^=pWinbj9;; z>ejic*znzCU4`P23BQhD{U>?z&Z7mEQbsUdVK#@2Ni?UmCdD81P=RVs0ozlc+EZY) zN0at&Fx-{?*7>7VgM#`C!Q#!TL9R?}@0dTdvUvUE`1t<@x`}FOTC$;;z9(EpyU`DK zRa1a%oJt(ESxBcUKD?Zyb2drmbQ$z5RmCq^;~jK8nm2g1G$Kbx=sm6q7+07{x|0w9 zCX>=g2+&gaC~X!yf&R zO_4fPdxV;m{C5@nU(Nj_z6cft_0CG(HHQ7Ox#GAQZsJ4&kFMqz&rMr@Li+QFF)KQl{^Mx1Fu$ZHAF95Q*on(DS~c4+fPS1tPfsA#qay-_BLHqz*xK!c1xh`?mgBfRuWfULg&Sr~^2K-TaT zdj4oV7w6oL3F9 z!?oHLVC<$)>}!Ir7XM)4Yl4Zd;oHNB)`w?{nH&QY_FmV8h=~o1fyjt4G8AHLwxBG>L|G?Lb}CQ?5h{R2*h18l2U`p` za9EzfPeQ6(f(ZQ}D?-C50t5rNN}S$6b~7*OJgzAnl`>R)^VN_DESBIq zPsk~`zS4g)0_S4=SqZ%Y)>9&^r!vWUaC{JyrXnqz+?4v!ulNdS{+rpRlJe(tXZ5c> z^;OP8*fi4otM_B?nCV}gFJJ9V`|5dPyZS1-fAtlcAtAQC*o%L4Tuk!4_*XaMY_?*b zH1hTCU;Rs}k(2(_|IHRA%|?)f>Z!G#yE*dk@$AAL#wz3LW2 zuF)qdF%S1|VE$>Q+|`7O`yiDD@+RrScZ6aQ_ord5%$+HDul^m#nJok`M$-c&Sk<-I zcwe}7F9aBkD@=U+V@i-2?*m>kE?dcvUr+>%0p^4Lee=gcT8PB+&Jw5U!VpD^!S$;A*+LFCe8^DOx&>-tKu;r-y}&)1N?5lRtjzA8uO zFLSuFl{u;vXLPa`xA~^21qL?X_wC*cS|En5mY(=cfB( zSKGuNTf@~aPB3wCfX15kJY>8w33LheUX+I%k=2Zsuod791hX`b#zhEIcqJlI&c{aY z25{atML7P~w?{NFGzc4$`q7@O_A8Xu4lI7K>n_XfD@**~TboJwKwO3;RtcC{>eo!6 z7^~qvw3vZsQ!*F&E1r?rc|5xsj8q zX;!Kx8CgWvL)0i*f2-1JoFj5Oc!r!FG9#d6=?|pqkBz((^khFYFV$t}E>s>opk2bC zTtPD^7h(fSyk;0~ROA~7GpV3lMre`vHAvUh`5whnO!`WmfBRo~pJTfmeufnCulF~% z)>|{)?Wv{m2mM8VUNb_R)eyRiXO9v{-)PVL+wt4Z=W^6`K1Zqp;|{$IS? z=$8=hHpM?oB^eGndbP*kWy3$jW84>Xtp>{kbKZeFrJeJJf^J>VCnHV>&LzQl5N8mL z-3(HisBj{h8SZ0p(uU{X7agWi4Tg7Y*ZKdTyX#m+;Kcq9X6alFQ8p2**@+9`W4vw> z2@54yvxb#4>PA=%mx+i7zK!vvlEK9IsjG_z#HJoY~i55*+!9kJoJV_Q2vb zlPr`bhR3nNB_UQY(sf%^Y^W8!Ib93+g`F4ra33Yw?B|89yNBD*{+}26g$XO`d7%?b zVEsHVbdd=w{k+gykiOX-m|C!sH29X`NvDr5D}M78QvU&*7rI^i6??{SUTUUiJ1>-D zcJfP$-~4@SxDWii(35+FZj$kv?>B!RpB|bQK}rArj^FHpet};7U+{UM#}ELtcd%dh zc_EjC?aMrV^QFgcKHYEN{5BLH-QF8Uu$1OjKAe5i1k1yb-7Z zvAnOO`^yXS&9iUtu*hQE#tjCRwFw5MdTv#sv&rk^}SbhLwwx3A?(((q*h>3JTc+j*-i zfjL+i2OGccXL-?o_X+QNfNxIJhU)tZ) z6aJ1>M9~4l7yX^sb0c~=?6?k$(&x^Nk zVJPJxCrO}{5-k$e3e8{bjOI&>Np<5^D>F5}J32TL!+r$eC(E6!$hU6fN+00} z?=(Y{%9uQQhmSkW5W^CemkBUcLABgzMzChGRA;`M9mryz2~akL6-Jz)c9gz5?wch` zFSPtcN_Uqg#?2qQ6iyq4i<>F8#?zOKU-(jmeyhpO0-vLy>aSIoO zC))k<$1Z+0@vQ&KlEuHpl*5?diU@L@=f&U-p-_%a@d+xEpA1%8#2Psefec3)6{$dV z$mCCH{$}1v++tq8DG?!y*I^W2eLhe_$`H3~bVz^GW__w$sTTsywr<6&;{@A{>1VukaRuXmxek?sq zzJq^j!)8}y2f=^r-z?zmC@h(Zs(bWjdRl+-&Dy`z4xOB}Lmp}K?55A_j}{MRxJZQb zHJ!ALo70Q&y;9!m>i+Q9-M(h1?BQ~~^E>7aLfz{dglJa_XSgjeqk93v)|gmW?q4)^ z$(fBWFC6E;pk&EdJ&5VnYE3sVG?{Kk>gC;%^*jic&4r!EqN0T74thq%9o|)V$eGo+ zW0d(`t;MZd#xMA9@K;uiGH@Piri*wD{m%ml&ymcdeKDZn&UV1saIe7X+s7R;7B1dQ zcutnmamNT%2vB>yW&8me`^4vct47JOgP!dV!kUg(_`J8E*~VjL4m{g$OXmEPIrlI} zdA6&YffJq|+{Utwhxtg|9{lb|dbpdn2UjnW&ZVvkzxkUiV-Az@2Dc_{k{V7CB zt+)8wdnCLHkAQ*$;Q`?ML6$~Zk)L07{Ow_F6tq4!{`Nujci?|ue~-p-|9 zHS`F^QZYx_`qZ*`UX!&R;`G%r4rPyp&zzv$mr1oA!bd4l?M*I;Yt#aAeIEjHI%$)h~4DbLJMEYKW^ zX=_6WP`e5sL$Ns>)ZYCP@2E1w8!V0552;cL`N~`cw$k1H>q?f)EPZ))lYi#eCFg3j zFX$7&A=`v;J|`Z1GA?6#B&%_8t-e)3pXMtHVdT-AO%gE}!&R7Q?fO-st?O>OHUVE3 z1>n=9(Vq!xcQF0#Kf#Y~$C3cw!a}to^tm3qy6kh;gRgTv7>D)XG_D6F+1G=S+13Md zEzp}VCUM7buw-j3aGURGYe5yFt@pMT6fiG+Eodea?(co^M@#9rW3VdJ*IKX;26XfM zQ+aYN_~{RjC~LtZXtwcynS-?;mdv?>Ikzw;b1k^}do1htB_FA^;Pqi?Ye5J)1#~X8 z7Ti$FGFjJxjPZ5%V|)`!|Mla0KfPb$j6Frq}W9bH1LuBx5{zm}g7r%a8=TjawI1`KOdD z(L#D~xE{<8`I{G?7AkIrWQ=26Pl|+v`)gl7B=qLHf_wH=j=OMFbZ`h4@KpLcmOvyA z`dfppNUOeGZ|xk2&l8@lu>D~$FQP1G4($2nd)mO>is{{?DhRP5-Q>9G%uXNMJO!eE za@-YCI_@|}gehFxp;49v7sjIl4+v;8e!~aH^w6`CW4cr39pyJWvW>l8?=f=k>L{i= zhO&>Tk(-DkoJlF|*VjnXQzQ5KOqS_3a=17yefy04`8tfnN&YEgmmH7%(L!IyA1qn& z74XfV>%nHO2eoUo+zwn^Y|7HP57}E!ZBD}Id;D+cd;G`B_`4A@{EHZW*y=d`;GfCy zH{a98AJf0D@n?3%_$v_o9DgZ|@h7JR4Q3gC-~DW*jQ^Rb@t1iih9xzG0Sutf9$rv90=={MajWgh7>rD+OInT<4)$z1Rndmhai@( zWeHrW;Mw^r{6you3C}dupdaxO_xx5Gf(-WBYm7!y6uaL5fJs_m5)N->{0>Y_vnMTo zrz98fu*a$q`?2nLcVV)TUSw67r;mqvqFK$uEd7{@ zD{fG_O=8jQ4f`i}RWt>Dxa)ecbmIDirQWcAsn^w5CY)r&3UGC~=KqVU;atJ?;RGCa{FHJR;Uf`0 z?>2wVm7l=5e7gyL)MhBrJ6DeIXgQ)8u%?KRFACrIU(+&$OA?+N(AIMT{_ z(YPs@Q^uU!RL-1a&Idn7PG=d%_iD}Bu}EQ4Xj#5jZosc~SU@r!Sw^QF6k{skpV zs!Ly{elF<0Wb6_sC0+>X6H*dBVw9Ndd`!=DCE~+@9qq?)E{O9_K%D<|xV}xs7h9%@ zubIPZ9i-tGYyzY4R2f_XMsvIguN`73%myTzW^s&nekiR*#QD63&(E+ zn9=IWG*`oRGzPvAb?kI4u=FQh-SK)oyS3L0&swXtrcm^w0_ZZW{b?2Ukl3K&fH`iR z4(oY7UShr$7lcLpow#uMSzcRS0D;eV zt>YyzvVd0qN2!9>QkyB=uBKia_J3q;whu85S3Q8!*GI|5NBnOwZBJVvevNwQxj$A zC2DXr;_g&iXa!EeL`-amV0f#{XEpYRB50X#7GhOm4Na1psa37&(#1ajRT&m-gfanf z1(ih`j4o->zD_LK-{Qd9r<)e-Fm&iWk877^ShSD9H|k32zV6pk!%hH4L|DR8*{B$@ zhF=y##_EYLur?(;1DMSvZ?3rxJ_7d4b#QJnF}V(2rNtY3QWiCe#Ks>9&!GY%?)W&y zqUsaHfp;Mv30#iBW{&z99~ce%G#)AC+=E1==+f|9Y5w*cjYZYCo!Q_pvYfAyo;-O@m9GRvrIMbm_$_Kc99S^hrxNX5zo90sEM;;AI>>&$CkIIR_WZem z*p({I3%KG(Q+bx`ZXX$5Upg0^bQQ#*ks!2;FBSJ7t+S-9oR^$(`vVvXH4I) zj-Hw)O?5O}C>*B%Z^nBF{sZXz*x1CexWJ|iXWA?M`(5#Y=ojd-DdgYfioc7&!If6g zV=Mi8>c#+}sDc;`*S2A=BI>L5ybjQTt#dU#t<)pF{2&&XypVtWlDyL0UDHFw>v0A< zsBa32kt+DY8;IM0jpoO&2BFm@!TQha(P7f|=YsxqOPtu4hL~Xqd=%QSxM7(K*6+1z zuBsNjg!MqTH_BHj)vW89j@TDc&BiaV8Ykj-B;r#Ox!ZDExP_%fk3w)Y7O-h4TnHB8 zqkxTpT#dC#y*|2G# z1QTtfgU&%%x`T=K5Z0yfox8xv5W>M1o9GN8H!n630~_)=aR7wR{Mf|dvFi#$v1>-j z!Ai^o2ob$&A2)315l;!V(IREa4as;)PD&rTP9*G9xNW-xW2ero(xL z7`*@(T?-gZL4ECAdu|B9LfIHY392*p+yE!N=*&>rl_R5P6KkQeIU}RyeMj=%=Oome@U+}Oj^^O0PBQTT-Y1yv;3tgQbn}g9At>65@2xG2 zWzm|vDwRqSd^psTsZUH2oli(6pVNy3#8 zb|T^FT8dQBYaNe#i2dBAvIIL{yUfB)8MB^LS^Crv?3&3^zoN!>6|>^g z(Nz;UcPt`Q$76iN8i_E}|G{T`C{&$yF}fMDU+N6mp`){3>c(?;rT&i)eI91Y{zCsp zSpT1KGsiBS=wf_5#X^)J0igpXmPN*$*kSSLv}EBdx?Q*ub{THkcv}6}ja~dS=6wj} ziN*J62tUOpVRbvK3QwpqWER5U2zpJ){uie!6ewLggXd-X#*#}ae+_I-YJxbDPqF+1 z1Z*`v#onU{W1s&ctedd`A$@&_j%--jHX5(tGzqq~I65r0OY!$Wd9n3amu5+Q^l5{@ zjftex7CVglOt6oDV6|B8Y}Yjo%3UA2ZUiA99)YQLETW6lB38rr@AYc~$$gBeKG}e# zT`Mr`oxvRl^j}LZ<)L zaj0s5s>;~L=1Ym8PY?u~`SxTXc{t~Ye+jB2A}qVF)!xoxhy&ISJbV1^f@qMQ-|e^b zPjH#M7!!IP%NIN>Lr0&w&d1BxwHUg_$yLTUX(PE5VrAMC;+RRWw2K#`Be1BqNPA{v$R^W(d{G842MlVm0>db2m0z`UNdg=doui|*$g{Jj2 z-tXRvhV(h!dP_RH*svz4sZ>OXp>0u}LKF~uiQm6dzg02u9Em-Wud&w+enQG#Ciw5epR)cP?L(LQ$cI@HGHMM4 zR>&?knaB81f_H=$T7yU=Gq5IM?s!Gv%4Fm03Y4l}tEEsR{()pL>XON@FixK3#W{lu z5sao#tN++NFBx<|^Y5BhAxUruK19o%?AH7n7o1{!l-q^mR;_p!wl)%z;RSFOPR$af zcBrTO;9X^j1UwM;FW^z(cd%S0JjY&#VM6%N!ub$I%{#@`8@AK2o*{%{R2^>!!RxoH z9Gm{=+mYm%hmmk439SGF6TX#J4Su(_D!D;&m+Cv(Bl9_UKvV? zqQr#DmJ@5@uZi6guEO>FpQ=mY0 zNooV0Hlqm9B_%y)(a4D&vbDzbMID|YPQw?*EapI?qWZYfM=>nnITv zZERk8X6aV-dl!CFS+*8W9I8FWO5bj#|J;23N%COuAX75~}<@%D^zcFvrm%hz)5GF}_`iOGL^#(OG3BpQ&C7rnu* z^8HBM@vF-)we^=E{=|;CtD_@$BKpuj6v?=ICg$lf`Eeo6%v22qg>; z?D%=(_+e;hK}OPo5!5aXxdU*mI#FR6eyTbqbgSd`v^om2)p1`*k2>a^#&%}NI&`c)%jZ>{5MJd^4=szTR zkZ%ktKFaths^Y4)8@0m^_FDi8zhAIul1BjVh2}d}2x?0%_%>RJihbac){16nOO9k- zy0&D)e1X$HZOO?}8vehk5Va*yXiFr>wb(^LjMc{Lqez(@n*M?@VVZh{KS>k#Yddq$ zCo~#iGZmBHZQYWPSHa0|bUJC2Yxh(4rH zy`uZ3KIHtXO$-2Drat6I=2*H9KzV*1EAEdzq*O|xUMWF+$Ro{w9*RA}xr-Z3iC&r)OV*I5U zrY^*BnEIs_yf{}&tan$LNXWC0a9a&B2wCzEWxl2>5NZW~h7wb(VF*7+%dr;lA>*Zd zqksYJK~ogxd%|;=z=}Kei$o$H5I@Kxex#J=gzrn`Y@_k?;Yk!7eXfO~_eml@V@~`w zX@Nx~9apfV$Nr80AdwiCbCWNU`HNT|NFPUG-MiTVZtXBuaX_GyAvIyuTJFaa${2IC zx=8de2g5I%-|d@UJa)P?Dl5PE3Gy=e1=&ULd<|!l*MVC|o7*ejQfr0jKLPvic_!1S zJPunLGdz*SDMlLK0#wK*m};QB7mY*C;E?idFy6R`J}A|0C-Zt~y%67{Tu$CCL^&WiMGm}wq;+lMIErVcMT2KcO-DxMESDu zIkqScVpi=mmf+Sjj7R08;pNSvWW1-tKDx=c4?ZrOZv({;IYA7ORXddt@^KE+nKrl0 zHm_)R%V<~Qk7e9~$_N?fkKztFR=Y%ukaO9g#bxYR<)dDBk3;#OZJqf3p$G*XMyWhEo0>BiF{V0U*nkj7dq$B4%T#PhJN|7#sdl6NSPV(5 z5>5mhijBq|adIiNes;`9w!hHTuv8E;Ie<dK0QeE78%%P+3Ty;M30=CBJ`*-|})7Ux4)Z^hb>& zti*<7;xk6RyqiS!9D5W$vK*s~BU{kN!Xrll_FCuDT&qI`|Btvg0k5jM+Q&~q5&}s` z7=j6kULa_cp;tf~=NnA)qC_KtVkktR!&o@a30lfBy zx}n(Zb!$PdoAb$9;&JTG9#c(PdWe-f>X4J_M!)_}ui3KvZ~C|Fs^0szmJ@sK-?kwv zvVYST=GetmAH+;Jg#M&i^={Sif4#``Y8~o3l{l>37oPuQy0?K>xL0d%7f#UG(BNJP z8#{r0N>~f4K-^AbZ_SK)_GGuvyJkic?dxIJy;{BM)kf)R!(OdjdNudC{FdH&wHEh5 zytKhyt-h;QQ$qLd(Y;!`-K(|yFRoTRpvpJDUe(%j!@XLD>DBzGPe|7H^k>Kft3RtZ zS+UZO{_IoLpIuR``m;+l6l$2FVKQM#^~tEU4Q`Ce;U@Rzh|5J8{r;)!P3{7P*xP~M zKJhzEVRK&fg~@ri_<@q?yo678(yLs>rLJZ*#TSgr7T^>*bS=%*~~p99qMk zP3{C`FVGcjEu!Im1x8S80bcJw5HBC}Q6y5p=Y$LR2vfj6_^-+rdd#%+cxXHo)q1S? zIr}AQ>et$JuWm^HePkf!!ikvLT+UQ-L_+(f%3y%OaqxByN9R?E*Rpv zy#BTbbR6bxR#~?iPtwY8hud!Uct^&+87Bi?kf+kB&0ze;BuBN6@(HRx54#UET;oV?jnxmQRY-j#^x}o2lm4PD4ul^e@uj@l+gk24i@PUBb9`SRZ>f1_{ zE*{O)zm%Hv zO!%sg32@&CyMh-^e7N4IiRSSs4 zcjA)Dy@+(DdjnU?Rrz;9q{`?gc>|?p#?{R9bqiRb3XsuQ)Ty;r&2pdC?LwcsLhYVw z(W@aEkzg1xSvx-mcRxAOK**sCv2 z9#a_CiPI`jrRg}ZeT^XWch}w-eg1x@dp1t_Wd81`s@pYxzcZ-k??9v%rJ&~TC>q6X zuiLEK0F>EyEOS`5Flaf@saC-F+b;A;s_KiwU z>0sI*E?9HYn^-~X4#vzU(NR1NPu0InKSlK~7hpOV{(gw*Urx;%V7ixss(bmhiFLG& z<>_7yxfvo~buSl(yBD8n9Rp=O-qk+-^ZrF8^v_u=5S>ufzcBUF;EBEhM^BU72Fxz1 z+xgPNqfM}NsGLH0^-R1yM?_EFCy(4pa8k@RV4 z=+jt?=rG(bi%>_&9^KaqbGmwg)ptR9Pz)CPaNTCF zn~k+9*Ftw7HCzk*M6HEz3kEaG?-Z#Yq+AT$sQlhlenXYtFGiRZ&>PD4Zcub$rxE-= zhe#}e-oy86=sZYg$BM=S`O5hcoLB_qRQW zVk71gyzzQIe%M08dt)-BapRN%&R5A=t)i=84f6uoT0FwkoF7Ki8O#S{Pw^NvU*NuC zy4qJ1CCu3N_h6Oy7+u?c5~=GNxK&CDS@DNK65Z!KZMIB$i=X@~Zs@})erlVD!N8Rs#3}Je-{J!(S z9Mv$Y;~zTHJ|D!sn7%4Gu@h@b&*`9j=Vc89@pSNWWJG6r`2{TU`0p-d(dpB{uf<-7 z_KVZO)22b`9!>{4FH)Jvc=|x-Q62a2P6r2)GlYM2i55OHSaoe<)wS3&O~0XxYO((9 za9H;-_PydBuVz*ZJ`2I_Lkx*H9IPuqtm^o!gz)LuH!qQuJ{|iBcByIuIV*U}-v%!-KB@g0E9z>oEesLkftrI{nyuE`@ak4P~yoZhkgSBw~8U2qrpecR}4Pf zs~D)G!Sk?_f=fI<=OvzC^=Suir2dVYdnAWtUgD9LqO#pd@IrN+nw9OI1Z&qNo@{pv z+^D2(=Pqao@o%uO1$)t$YfOd#dNH{6Dj(>;p<& zc5*;@GegJd1Ip{v0c9!c#9OM4U=vhLBf3r~@t!{!9uG&9t2JD!;VKPF3F?TF*}jt53Jq^YWPI{d&-IW8 zQO+ofE2mZ!uSJhl>8{E~$yDW6qLv38Jg_ByX`}kbxEyq%eiR1xhq8%NtLCYlPjsre zH5Xx?RZ#2Ras=yK%~d(*+pw(Iyc_J}8bo%3Cz<)a@j1NxV3pB(+c_q}xkJ-qZTYS}e zCQ}p7S5+|37KP75Npd_$Fyr6jUV`A-h@eE3WD9){2 zT=RFa#?=f@2`TQcss*iC&qh5j#oE+5FWu{2YuKp+)62Ran5KuMy^*93o>}_fkRpLvh2aSAAP6^?SIqXc3jze zf4gZ2l5CeN=0w&P&f> z1M2C#6#E;xy{708&k-CR z?484H z>wMS6Fk;>a_^H<7d(U@w#A~ts|D*HW&*t`?-y4%9zkmHZE5Gl8Z}j}``FytsaeB@` z@A+;s7HpiHW5L#{yQI6-m!cxich^*+xzJz=uin11k9ae6($o>JBIMl8I^|_$el|%J z@Qe_1+ud!eS)cH%{_n+^M!)C!S z6YU-yEi>YLmrC6MrEoA3QXSGo;S-qf9nnzC;2nd$ zKk|T=v-uhQsETT3g>D+?qnEnwo}WbcPKVo4-Hv=~apb!}EvP=#N4~X(wH{k!1_@b@ z)w!|#Re@cQgAvem&tb2r7Gt&U1g54&m*f&0yJD-Q5~{E)&zeHA0+b~-*0;hF_Z!t| zj4Ep!$Bd5)SMEahB#6MQQ;w6rR5^fpUVaa4ei`&i!9thcALp@51)DrRItGY5V2--JIgIgS$WMCj-*)s>sod-S zxh`AwNh%6YDQJmgjsq)op-c;p;2^ zN9W5bp+6Qus(a)86{h|ZjHl*&d1jJ1U%ucWbH02YBFXvkS+wGO`HiYsZ&h9UURC)A zIA6|U9IQn5y2B7>XZ{-jhv&<05vuavtD5xz^BFx|s{0j0MVv3cq5khkpD(An+YlVR zj;YuSAwArgVwxP~xOwelR9Q+x7k7D{>LK)P8MOq}$IWP)=-)0-+xFhtD9?jNBNrm}n8 zhD~az*yDNgA$KE4BhQ-;x$Bf)<;JFFG<9oF!{v%bTc#)D_9$Ywo=-yb0RL3gb>buK=u32&2#T3=dSjw4oLO|8PJ86Ft;}VK_sTyQ|g>**j@2S5#Gw0VcI<4bt zDEc#%N%>3F2pSBJp!lYM9zjp!`v~7ZenKT{{9Fnpm14P;Vr$A!{}AvX+st%`RV$@E z?gCiNT5FGcFawf49H1aq6{L90KbHnk?0oO?>Y>cj&4 zt%a_9ka}Zx= z`gMNl8^4KAliv1(1gQDBdmgr!cJJ;SU5e1o(Pip+m3ppK&voi~w|f3YJ?qr-KK0zF zo)4%e`FDUOgXE&nMLLN%d?{&&}$&MLqwbo{j3cO+9z0=X2`Wq@KIf zbGLf#QO{=ed|5qTRnOPevqe4MRL{57^Ii39RnPa;bH93isGhERex#lU)$?EK*{+_S zsOM+u`GtCRsOQ(}`K@|>r=HG<%!gR@j8o49^-NUH{_2^mo&(e~O+5#x=MeQAs-79@ zIZQo|QqQB+)2E&z)iX;yk5$iX^*lj6$ExRe_4KRf1ofPxo+qnkj(VP|o~Ntlnd%u( z&&leUJb`KXP}v*RlW*>Hj^3f3lf(d<(8-FTvJomv(2;h)LShZd&k7oBncV+t={ zx8SA3=kWeI8r+oBKXe59;LEfXiM)x?iN9Xtfg+|pM@$*>9sfwUh~36JY6`u#^YsJ! z)X^!gj`048`Zfror13j05H&Rm|1H87i15E6kfmM~LaWASKuDE6<+OLphD{lRZJ!l< zi5>rtVi@BST?gJifGz~vYuIAR*8NBLBE9Tu8j&&K}4?uzXN()i<5xecfMR z3XhjaFXfaUp;HjbB)kSSeLvpbb{5?VI_jk*=gt)@J*V;FLL{&mL;b?ncHVoYkP3R)ILp9Cqm5gKW=*jBDhC{zgfZMoD$@i z9^cd##n4|~28BLRcSzcx7BUC_Z9TQ->^OH3`tQ8zAIIe?E%T~pp!?dMJE{@-#pYJN zKR+)uuO)xYTV+G0R_`@O*e|-@rgE0i$mzKsp9Zw{Qt;)2Aaf?yY+T8BtfA|^cJQ>6 z=Z}nWK0!8b-I_N4%dMTApOnXbvOT!<`Lwp5px{(qAvb-vYjDI&=KVfgKH?Vu`ftua zYF%v0!joT-K{4!Z`yqyQ#A&-yBg?@Zg*^up)rjI?b=+t)UC;*;55xygYbqNuv9Udv z`p1+lcq_jAUlSTt`P9c8_!2x++<#y(g}8m)VJ!bl_bp5gaddJyQV#F935^H(x-;OY z=btxbLyd#k6Q6f;QP#M9bGznec+CYJUV&hwLGC5m(bp}2<-kEJzIz&c+>`MTPsT^h zMv0p5XsGubPcB9{I}L4B z*yb}jeu-ovVQImdlzO}z$3(T=h;a8YJkT8C-8Hb-X{`}=+iF;J8%ljL{(eMW^ZcJ# z=Tq~xuZ_PIZufO8N8MQS7N>b81L%${%sNTn+`bG}T?!{Wi zF>Br`KMr~(lJy&CVp1U2z%QA8+m&DHZH)&og-)N1{{-VJ%GKMR4uH$5*0aVm)yGVE z1&wFh)T;be{M^(uh3%iDrWLfO4vc?fWDK^Gy6O;N1Ac=XrT0{aLt!HOXl!PbtiIobovh zNth?jKP5M#{L-mowxvFmI|MI|Wd!>)!FoOS!k;#R+0K49GoZY`P?pbDTWE8C#yN7D}- z!5rCFy(>5|eJ&!d`rBE-S9am0-Olp<>_bmNtOKd)DoD!N2zN8!G4c5|jltAB%(}K} z(YhUCTe>s&Wy_I`U$%7Oas_))wl#dl>lFTNVm2Q`@n3^w{k!^E_t9@VJJDxf2S|NV zw?+KP0%NzKbvgLfR_g7PlHI0mkLWgrZ-uEpx7U59e&q$#b0j|Bfoj`#Vq=@jlD+Sn z&dzl$_@rzg@KnsIGfH`gT-N_->;m9B26*m_zZ_ny|L#9Piu*zf+yNXsYEoE#T^we2 zx{q*Zs!4eg;HJ}~NqMB-K34hP0B}d>rhUA-NV7ptm|m>Ihcf&daN8Mw=$II_MHraS ziSjrey{JI_o%oJYlvm%vWgh;P z9><=K(daNL3|8aKPF$R>#;2DfK1$biv5du?qh}nCk;e27`-0VY?Iz`qtjkqN_-;Ys z#OH%m{exBbb7A~Vvb!Exh*AF(=p5u9beoZZ_rP;8K*j$+h2Ud`_`fq{)gLAD@V}@h z{$n-&m>&6mc_Ae${%Wj}`CAj)xFe{?XVnxC`W{31R}3-8Adt9CAo*f@ zOj(MWvT%65{7bHB@!kM)%G76k`%taqT z#y2OImto$(KeO@CAU%0@6uxsNe-#>G%_mw$E2Lj%cpYMjq_q7YKXe#zZkS%_GM+TlDIxwkY^~WOn1VroHxvDdE#UI(+?DdJvReY<8T?}Ir zk>q&j$pod|msh=YXZ$B=ItOxBwl66wUX+Lb3S0T{!X?F1@~U6XPim@uW#uR57B4B! zt8U3l+NHYRT+Cipempm~AaCWTx#eXgxhp>@UQ)I&H|fo!eF)n&@p-a-zAC>xe>Fb2 zRDch9$8SP^hY#A%`mAckw`J3Ut5R-&*v{NlO>v{!&+1IgtBSt?6lXLh#5iTyXA~vG zI%Oly2oZ+G*MIdb`bXc@M+W~)RasoY)cdzDOG5M*#GHzl`Kw zk+XuKaR?oc&<3qx}K?hW-n&qZ${-B>?8H-3?9UbH3rf&Y* zkY!7D#y6+x4BHvM3pUh76?EjXi%D_RvZ-Je(~N&`_XU%h@x2bLit^L45>8JjpMY;e zBF3tw#GUcguwXCA`6A!-RmHD?t8DP9Cg0BZQdr}uUVI2PR0cFZ)Z-mK_3fXDjik6$(Vbm))TQ_w!~<=lqmI8??| zgwvxly?7*S)%S41fMcf?1for%7Ivn;H3D`pIo;I0npPF6h`MSZc6e%B2Cxp2CoMiU z@cYQ1dQB4pQA-PhRcj~)qfd?U%x&Pnr5ov*wXnJssEH;9?J4k=+5+C zfG0*rHgE95)CMo{wx`~P+`uhQ3O$2DAuWJ*04qkk{$IRxWaEhV9Mucp!;Hu#>`yVb z^!Jq5XiU2Zt}4!Of`6WH-+SYJrMk%Y7xD3`;Az{-xzU%=nSM0cSLb7mpP$y5&UaU^ zs63JO&wR>WQ{dC?x9QIJAzE5+YpX9f5%!7sX~BtGgSfjy15Tshm}rEZwjHxdeBLMi zGRj232ZLXt3dK*OQ&j=ZCpnm<1y`N%_!MMFc>?-T2bMP{G2Oh%X{5tI>6zL;HvHTZ~1pi|Lz%NIUnlA>m1GNtZux1_IYQ z=SS-KwtDVS&qnq9L_IaVmb+H@ysVy2;NCp`;m@d#|5xv_hdp<9?LTz3cKOm4tXY@s z;GW-fe4WwQ*V2xEr%0QD8sZC9e-y0dad@nH8K%#!-1?Z!XoP4!oe+-A{rIB2h@g9w zwyl`^v~AH7Ao7poQxI^s;bSrrU&aFC_aLh69)6z*uL_4>j2CKIS(Pf+LZkQiheP}e zhVnvnfXq4UH_(C8`@L=vIN)UmUVA8ORie%$E0u61?{N5C+{G`g8^3>Ho+|vR*9Dk= zLtgKeX9a<&)iL3%eS8n^@89W!*N0;xea32(zH)60KG2?nVWe6I@U7e#LByG&Gm1**uZw_(*)M2a9>ptCRm zIXeSikWMQdfX}G~s|Ry_e)fJu*m-tFDsmT?20*vPw^=YVKJvLf==f2Gim8JtSb20$ z@3aGwAE$)%J*@Ko3i5S*N&|<;`t&c1k)HB@l}U|gGv4wa@wF-caBNlnA=aO`FTPWs z+3&`~z2zg(e>tOd4=*+0m#OgTb(r2eZDr7hSrS3dzcqMkG|&65%SU6%N8`Z;Yt0PU zrzE<+yi)|F+4|XOV*FqC82=&@zZnZ)Qz&8ie${vja$J@NYKPyQ0t-1#5suiZ%||z* zG=d!(b>1Nw{UXfK^idmML4Hf$)k3?iXHWgrg}6$<{wgz;W0aZ&wG9O8wq!hX1qzrx z4}wtL*GOx#(FO9^)TnJWG+UP#g7ePkXL zl(;9G_`^+nj|~2e8+1q*Av%7Januy8N|2)Op*@YW`{(Uo!S;mzqjMiTlJ>psQMJYw&DZmDw9IsVhX{;zb#X9Httu|O$}2!v)guVq^Q>r9$SqpRptzM@(!#fXt*BON{qZ{Fp=!A!$ zawNxm5UMQip1ui2zsv~z(EfD$S$9vEnJ4c`+%NV^+TZzHip0ZT+Rt;th3-#=E?oYG zr?-|4zDlB89}%T(Hk@sj;}MqRjk&K}Vg@5(YKf-)es%;nNd0wB2g`nBDfRbU1h#d2 zhR3IT{ELq^KKA2bG!OG*LAI40lJQ37Gt>W#`mF8f9kbh3Lq?Z72b?s0+b_v?eVA`J zRp@vy??nH2%LkI2I;IpOw^!}d`Wp5OR+)Nk5H5gF?FO=}vg(xy8{k0e#iI)=AhwcBbR zigPSxP8q9;bN(HysVRy9rI|dvLMCD64AIP2MKFJsE-*)UTPB#RY`&QD0L%=z9@S&> z(aTY2)%b@rPErQKq3S_ldpNmV->NaXY%z*&Gy>pJNv?AT!D9$K+EVebvLzVKmLRhw z6xKY`);!deEze_#f@~?IPv__)tvSQne)57fs7r$_bT9jv=(*_-^lYoev#lBrRY2kT zq{(Y)!AE@$S*7eM#)znZmf|vBMXqzcs=jU>)_oRrG`Sw=%Jmejd$!j7Lb}l9F@Nsg z6;Y&M&LZVx7)5GLhWkWtCLdj%kK=S3xgwlDr%O81Dc~GVgJfLWkVQHJ!s*$}Vney+ zxFg;}sVUtNOX^?S{wuxob%y@qcP;ubzv}$#aKUD?U<<>U6QFV?b5t?vB=8L%$n%qN z=jaJK2@G$$0jJoJoTa{Jv%VKHe@%V=fK0;7yK?^42%}<3jrF5q+17Gq0y{dsfLVTmkOoYK+ zK|T|}r|k?%&EaDrALAqCmym9lj$cXpL!yh#KThODmYS@GJ@Y9i$u2T*lw7Un>3_IB zd_tGx-Z{^Ci>$}`a6h9(sSmtU(8c_AVb1o`_NujrNCr|qiF?D!K3=Jqx`YWb+<;|4xf;$bR_ zE^j5vr}+oTe^XKy33O5QVaEqbj@T9&*s-v?1V zCOMGc)<98<0VfSH6Q5t16Yn^Uskd#d-iqUzuoCOQmvyY|Z*M{Mu(#X)P272b5Eb@p zI82YtG1Y16lnN_2AO39VinsY6p7|k@f>Y6TQvts^7YgSGx3O29vFKaJNh>`=9kJrz z`y4oNTj4B1O-c^H9egv{#ph|S(EznK`igr3cM5Qv;|uPL9|>=azt|v+Plc7{x%iH6 z01&M1U8-HyRcD-zP)puWI3bU5ATJT%-hY#lH$;1V4jv+J^PVnwpTJw>y+hIw(EyQmo+WQ2yiNLG)$%&N271$nP)puWIGH{I(g$$2 z*XZ)d9u;&i*7D-CyuZUsyaw7l>H8Lbmb};DggnN9JSymZuwJF_RqgdBfXMrr(`TtKkHK5y-3zOh zx0W`Kys_}JC;|+0*Jg}mb}N{ZPEv;mbaERB~SbOKYcci!>9oBzF=^?b{7e*7JNvs zN$`EabAF)d7YVKxG)g`p?t_9y`8EAa!Fs_xf+J7V;nxd3Ao#lA*McWZ&~(!UuNVA_ z;75YzOw@Fn1^tt>`=^5U3AP9(pQOXj6ue3BUBMwI>+tggZxY-inD9d#K31?)uuia9 z(8jbw5x`M}^sp+l~d{nSqaO_z+{1U;9g0Bnq=lmDuOuqF`y+8T3mz1GO}gAEn%{S#XQH@$f~N`=3eFb{30@<( zUT~w}bAq1;9u)qqf=2$L^R)b{1d9Ys_#`QZ69kVE%n~|RaJS$?g0+Ib5S%U;koa+e zM$UN>Zrq^*P9-M$PJLdCLgU|$rcTCvz0(yToOElW(BT%A^D6ww|De!i z+~1uaf+Gy+>nu9*_v+V(aQeFzU9@!gH)^_>Kp*I73?22`2!Fb_2%Q^+j&W>5`rz-n z_!<3}uYm^`stuN*P9@xaaT~ef3%r*=r+*1BTSp7$pG~(#=-lt23;bUA0e!vjYY@6t4_$qYZeK+s zbi1iMMdOSmS1wt4^%7rk#oXdh*}|nugm?B$n!etr>7G1MySE5dPSF0&NgDTvzfbtS zDehLm4+TRfYx=YtjZNbJs^B)k4w1j{7?A_LHi&L(f$g_weVWe}J%uhL`b;k=_AOqx zWZ~lS#l8yP>?QMj%YAc~E-jt6aLMel;$^<2^L=F?nK!#^w(shNOXe-TnqIS)_!cgn zy`b2)sQ9YlMZU%5%gTInz^Hst*}~AGu4snivhq30W-kscTDW9^Z~pALWlKvH=h=%E z`R10)Ub3Wk(K6q{B}$UwJ6=-YIMnazh4acvlx`)(3m24>{r{=d@lb87&vB0Tjq|a- z9#6f)*>QEr(q)mEwQ!jtb8^ediWi5lm*6|Q&}ZBsP!|s?9&Q{ zi^Y_Qit3{XiRLU^a@Fib3+MTkm6fv4LQ9t|RJC5*WlNVr>m>`El3OF|mvgGFhyJrQ zntEr@+t2zRlKvBDgtG_n($xuFQxrP(GeiDI_hVy$>`!I_z5L)EVJK&lMQ8da`ZvPg z81ip|o10BE4DsscU|eJTY+!HwSgp`C0DYjRAwSoXkN!aK`DpU9C-mx<@rc$h01PUr z(bKV3=<0#KUg$c6&i80{I;N)t{>Cu>LU13>I8|ryQ{%#Ix_;Hlyr(En=S$%^8jTEG zomGbE=6odhhc5XX=NiG+TP|KY%1cDN!=WoVOu9``=%~*@_*289>h-u=2=u{CLw{G& zT{%^!vtF?F0`2ap+`azCk5~Q4lH#i)`fzkh(!!;yJsZ6+dY97TWyR=Ytlob9($a{& z9vzs;AL=?1eAuT&3<%?Wxm`WZLiF7nLeNj42jio-V&Sr~Wxm;qN{eUDTdoxl`3sjU zD=sZV-$;e^5F-NwMgcHV@kdgw=-s_vU9xn^I3)q^QFvG&;z-}Tr5K->Rz>7v^0Zrq zy5fpZ@!YcFdA_pcp<Hm05JNBJ3}=EI)yG<0MC*hR;75rEq#5l#QY z`cYxg;b6(BhuhnJ$jLk3@;}zakKsnHnRk~UoN{Wvhpt8FoX5NKizc`5FzFgCI+I?g z6Jf}|Jqlec{7pI%pU~;>1AP)ZT6!ylt}Y54^Zy|H887Zn!Vl=>C+x#O`UZ>6q=Wt~ z@HdA1TP-?!;2<{M&#?TSH<(v3acm1N#cw2zv=K_5| z8pDt6a1oAv>0S@yi%Si_93YLMv*l*swJ4?|0Q8Xv#?TS-Ug1+4>QU>VYrS2MSB+Oo zzr9eS{~C>zD>ORGHJ02V^Kzjt68d@xZ~wWbYpl@NF7#$ROf&p@pf3`ADob?yX3?Wa z__me{-!hFwON37JsTH}4XNP`(q2cuDXJQH~b3f(+>oarY?Jbe{(&)*Tp6Gmt=OZH+ za_EW9jY7x#4?NQ)m*qASZXb}w@MHOU``rx|9ph0h>&H=l>EefDai<7wZ~Y^Mw_Ub? z&If-QTW+|&`m3&2exOfLMW?F}y1FQI(d7CXyYq`i7qsY1dPR*eFkVFzI`&ta;BO53 zt9G~#r@vaewYz?HdwT-m)Tb2~t=|~CO}F1XAlrEe=mXMFBbJ-ZuLj1V;x9PfH&ZQRmvi2zHxBe7mGjYg#l;~r z!CV&JeK?VmH5Ey3V?;#sA&f>(BP$}g`W#2*pK~!KEyD_)0wSlMDt1?W^Y$mTR=Jz@ zWjuR$bR|*f?Do)raMiwm0ZD^tH;Hh2_Y(upb#FHj{1C4AMWG{K zZ@(DW8NJ4L_jgY)CJ;ZJwo^D(^E?1X?NKpI0A zEuRCs4lkc;qtMy;lK6to7eCOaq;|=*=_-V-E(#s>^yW*)Vbb|`cgZ#NPt*tl`4>f@ zizc_yqGPzXpWTFT%4z-{x{Mb!T>$6XUB(luCgCcPY|I^b^%$Em=c!yBhs zKnKyN#@>GGO2T?p74zeb^RqtJ2wGwCI* z-&7#`mkOW{NMq7L^o~goxK{H#ofL~+_Im2LHXi2#iiU4R$I}_d_OBME?w^H+O<%7)61}= zUpRj`cDONmEXN*dDVF%ya2;>@{RPo>J!A`1j{|zATNNqC85u7aPlxDDY9%*Hyd_%A zDDh-V`}-ntlY-f%cZQdZ*W1L)N*2!NmhiH&*-Pef|6T9H&kpazo2_#1fX6+2Yx8}q zZ%#S(rm;)oB{Vx8luaY))`E4;lq@Y>c+Ju!Wnj3Ro6?HTJpN04J;S~_bBL<1m+&z3 zy$U-_3+H;Yl?>G>3U3jW%)YAFH``1#e2j#RA*PKR`9#T&(qgqU)qTnk!B=*?d?mB7 z`xT9Aul!i(1xv9EnhT`2QXA(o^NEAUUJr8S7Eh}X14cr-IdzO z%5BzP6`pl&rKjB*x)raowQIxvsG$eCgC2ezaC`eb!^a>w`@!EQ9_(il@6z*CpR4-; z(_gfUyIHVRuu;%y)AUAfZ~B6k9LhCx-t?{Qfo_W@ADZAkob+{A{FuJAlD@)^{|z5G~9&;O0!+(2zIXq@kTg+Shz|nSER|jtfJ@OY&z<^U<5Vb+}zE zS~`24Ozc$@#xLNh<+#vn>^mzz((uenwuP6KheAtBu_3G(IhALTUr+g5kMsse0K@c? zj{68M{EbP2rLd)Y{fL&&F6aUh(eUHAoVBluALl(qaIf{yMdQ~9x`2m{{J!<@3%uF= zyek^NI?#Ff#e(14@Hd9_y8STu`QM7puLSZ$3^JYzI-huuzbW4| zPdmzhJ1BIFXXvJT=!)PDSag+A@14(dz4xghVE!VU{;Jw8mCKALs-9Y_P+eKUk4H0? zs&jbVR+fnj8TX7+=_Ns7puTINmrs1`bb8x&y+?nhll_HjrITM~Eqtf@{E%|I{5n7v zfIp4Nw?x<{y-SxiT<=xF-70QF7mc3_x`2m{@w49R;zxZe;coWOMdRnRcIU@>d^-G% zVSW|DT__$5G3D<~Z*33!nmqhkqR>UtFXM0B^)q@IWV|5geBxosm+44;pP|}tp6`RZ zUfc{}I_N*oqGP|X7VbJA4e2_h9{bW{99H$XtENV)$6d8tcd+Co^QO6_OGA3HIu1vV zOBa=^YY?hMsH+T4#ob!Y^hp{Sm!@6(J5JaB=AO-^R;gE1AxsA8Djt(GgEyN@RU%LS}w;PmJ@~FLi$2#(@6|Q`jZnW?xY( z=@qoYlwGS8_O_jY!dR!J2IY=lPlh4wcKA(^wB%t758P=F;77i;v0arH#X5!HgS%2T zNratTORVrp*f&{jLrh+Vi!Go0ZPN-mV{E!+51pZ5Y}X3&%4YZm{MbhP(_$Up%`pz{ zUcuGfa30LQC;%F-*#N&r{0eLFB|ZGoZbAQvUlD$`+Z*ru+|-Hl02({J)YCS#pku#F zW7D}FI)*bHiYN3m=KrpcvLA1? zc-i#Ssly7(Kzk41w?W#yO-sAY-%f{@e+l$3xoOjt^uU)oS6X2`=}-&4G%Q=2Z=)4g z5y*o&v{+%TWhaT@M|*Gl?DUY9*M*mB9&HnuAVacU8cyLL87 zgq>VBS>cVadu1~Mc^NLYeDb%A?J7Z>wA=8RSPzX&Px;xPF(v?eH2LIZsBHPQ#&$I`{kJ3i9vUxwHfW5=vF!9C4`Xb(I0220oZ%0 zd!!*xlM}Wclw%v)6+)a^gyXJ+O%h?J9-FN2CfIw^gFK_@K{>XuU7HXm<4&}H4~yYE*ILB!{|fKD;MbF(9ziR-1oqzaAkS!eP>yYEmy0+J2*;UeNV65*YS~Fh z9>&=9fqZRayV5R2`tL&e@$1QuYtRZWg54{dammYYvE`G$ZERN#;?yG?d#5%@gq`x6 ztngOYqsb>P!^M_Q{_FUj)zoksYDjxcd69RKAp&b47)%jYRxMJP{fSdCxE9nP$i z=!d-ywGJ5X_s^Zb0DDnzbNw*>>}mM7qqB2KQwzU9m){KfHAm9@h<+^*ep6K3)<{1^ z=SKJyD!TSaKSkFO;Wu5;IrBwdrQdW#mj=JO)K8BGy>KTg z%AHj~UFttXzZigDv8Jg#4s8woQZ5r=@*2bReqD`$8QD9KPDXaWcoSS zKMDZGYxWNJll&-D9Po!yLCW_bp7Y(iRgJeMQ|HK8-HaUnXTZH z1OH~>??}F6Nxm?g=AS^?Y@ugT-%+Qnc!s3>*ovsE%HyLr5^lzW3=2DUG9FnOj{6c3~l_q>Pb^2 z^kkaqA&~mN1ElE?H^XUafVA1^A%D9(oduef^tADpw=psg8%18o)E6Ml4skP_=EW%T z$lqI@+3=&@j>J=ul+!B0koMM_s`C!_H9ju$TW1bzn$; zXUJ!9PU`+7r~i)rPW(J{oL(9SohQN_gnPqc#>6{g=Ape!>f#5p475(hQ9H7?Yr zD7FxP28i$qr29T(7|W(|y3WHt0%_Y0r2k8T?*O^4mo!7)EgKGG_!wa0v6{zK7*k1e z3lP%=ry0omZ~K9LfwyIAy1xKvT7Z-_=y*q!+ZZ7G$5bhYXk}Fgo$E1vQFi9YL}%or zG-qIGN_$dkzsA0ygd+AIO`u^o=QzaOK%F`*kFx2Xmao&44rIOIkMc=7^TEhA(E=W( zUvV(UV*KlXG=BoBJOh%)0$g^by9UVo_$`q6u^GsC3A z{q1o3hD*Aw{yC!reYE)B2&B1B+%c&MPU^hAPUv?D@8i_%r!9za}U zXydPNQ)Ie}pxaDCg!v-%zXC{etGG!+69UqfnG)}$Ozsy-Eb1E5D9bCqB#QiIkNkQ| zex1nsPUKI_(E5;urm+|Kl%?wv+RLPV;r_WciVoB9{eghus2@J?W!bk%`3+K+a&SHi zWPUK5W}K04jql_iO>RRJxw}1b10pvda!N(+_2OnYO+gg7|9dP!wZT@=H2_|9XXx-3fix*+YIjU3#uto7(b{n0Vyz45 zY2$Cm!;xvKKUcTm!qYUrM}agSh@0UwjX>I>wO`7KR*(JgS9y(i2FZ)Y=(EwIPc7uI zJq1qHaY}(S*NdCsH1`;NtoB5CF$owiZ;AD1j_&V_E*t2Kn3sn6W2!Uo7CjDd4A>MU zU&cNXnJ>O6dR||6uGZt+pc3mWnWEhcrx^!S`9eLW>3KW(t9Et0?w^~Z$h+GkuTJWg zFJJSY0HnEE+zh9A1Q?bl>jd(*<#j}nm;7jC`dUR^rSQL9U!#1qRY7!wDo7}_-_JflJc}WTD=b<9=;Et>PBW(AE#f;$!dPX`9~eXu#|A{9=!@b zwLtT`1W3(p1G0TR1>`vS(+i^WX%arZi*)!3Ak79K`MeG!pRa)APy5zEQ#l zs`PiQMb|=S8oW=e;vWFg3|*?-G06!|@}wjud0JwqZ&5;_J#VO&xTGf+{#HB|S(oZj zE~+m5RP!4LqzQ_f;WWyhh>QF7k$4spT`A=HF4|k^ex? zzJpV$=>w7m9$bo{ITs3GyW8r z_NkI~1UdEdbpGuJlJ*O6lZNIpAo4&)Uz|Y5NvPTO#-pQ-EsB5j0=!>T5@Z~_7 zt>X5sQyV~Q3~l^XJQZ2L9OUavA@X0M`Q8Mi*)DF<(4iW>oZB` zsYP0zSMS8K?t1$hBK2;@yvB_GwKFuIe*tMmiQc54c?U?F-7Y92b6A`+a9Tae79=7zUyIAYf45WD%sN_%A{-mXO8c2S&UeqDem*Ds? zb`QE`Kx=X+NsZexqvT26(~)^ng!181pz$&-rwvH+qsz5>6_94JDMxEvK>m8(krduz zsPyDVVK4d7?9pYBl^+4gkDp3@R7if@ApWGKSso=nsDm1>$`YJrlJ_}QWwAEZL75VL6WZ{ zB|jNXa|Vz$yMB?so~I^;=cyecGgPGO$*n+|my5K!+r0KF&A)D)4&Mr-$*9)unEu#@ zF2kPlB*-6>=nR_P-x-8?@t_I1KI{EG%tvHzz{@{J_@@c~6NUd;ajX3yWblZ%SSPN` zaqxW#=T`i3w&;3cyJM2$on(x6$@6eF(kgr5lW+&@9`w(@!8-~P$9BhLU`*qLL8+SuO$9k{lpyjn@yUnFhKK>EKc_>o}WLhYXgw2cpw2-0ui zWCErINQ$Aq*7gOznpr^F?DkIn z_WZXnioEq6c_ERPCg}(OY37NW;WXDqkw^Y9gA-6k`Z7>4H1Jb-_>UWg+Qxnr)BYeJR9@-9CRvpT$ zzd)yX3y`)Z!54w7L;D2Z75@)_G%k?y(0>B!*JxfHK$`R$ba|fzWV>81?q`AI`5}0F_kqFPwiKEB#Dw^RkQztjktwy>-3AD+b{;W3tWykKu{|=6t^qCe^Ft5D zxkB{00Z96n#QhF17Vhj-c);9V zzMu7a&-^NEelH8ZSA-u>@dGM;K*dkwW@h(yvgf5cS(64k8IP&CPxFArWHpzr17Blk z<8Sw~k>yx8UDu~jtCqVFNHgUF?PfU5EFf)m{ULunN0^N{!X;7X2u(~I6b}i%(*3%h zya^Z&e!GDQz*b;iV9DRL+*^P&4+AOpLm<=N31s?j{ZP~C^bbb*2RRwHM5ezzTKb=h zOn>DxoqlJJ<~IpQ^Mbe;PE!N)rl0)P{C18b>**Bi8zf^MihCN?zCp$c?CbB={Lg+- zv2)e~S-%Dzo#-5mIawy=ulAju0OHWpKC9^lJ*VSM2C8~F9%FXQ{K!1_>-t`TxTBCs zq^lSG-xdAaf%N}Qu>Zw+@Ax!eJVX=#8UABIN~N2~af-iw_))uzrpUZpfH-DDQvmF$>6Y+zcfDQTueg$Olr7+kvbXe*&^zOny_#9{QH1r!1OsAoWrA z+varL1z;X<(1B-TF~@CrK0>g;rFoMAAziI&j@Z4+zF(9p9861 zU$hI-rAs@3HEhT?7ye1`IR{8R`Rk7#wV(NXWd4l+4f}SQfTZ(5AkDi##yRC}<#bj8 zDR(1~`S^vnhrOfoaS@Q=_X25FzpLF(0IB~gKGHb5eXB2GTSE$uXf>>vcSk>G&Ox@}lu;wfMCP-TIfv z4etN}$?roT)7=mKDEY0C{#37r`rC6|Sq~*TMQBsE;McfI&vk9LJ^xRpa>3EGY4z>en(qGVg^}aw7_678vN?Y$r@Mvw+be{leQnzY% zw0-JLpvQN>l-y|hsLcqkdq{^r4Wx+Wg?=!~I_zb(5X%f~1ARVev&t>o7R zaWkA|T$KDGe>10dV$3UU7lNS^zFalq`qXm=3EervtBUjtG~!(Vkj_5qOY4j}unqZ_rn z-qur%NMrkEO*iS!hy-&DkoCW}dAy5wq|q@jw~_Rg18sk%i)o==d3z)4#WkR1Utiy# z<-H4}NqAb*Uj(F?1tgzM;=U2_$kXnBsZUILqLW^RAMWC%WB(?7!oXJVnlSA;T`uHH z8-H(m^lHYw4ErzNBU-Ot0BIfXGe8c~m~G)BSrO&9Eo6`)nXh z3h2V=7P;i_-H%@jKf5l}LSNfW9xPX4(Myr}@Gxju1~l!G?qLsWcQ%l5W&z2Mv@}lx z$M$@PmUrIOnMpm|K52&mX@|Aq*84sQP9w_sJ^akRz3uL;O|*E@>qkD(oCLJf zZMTV;FGr^PRM498FOqz}N%H+kAUVc7rPw+tK=PU??sE~>+b*b6wDqn25|iemc*45h zqf4Qbflu;(n$*KN;$}F_EFf)mzLURqeVYwG=0h{i7ij9GpLs?4ok3C#_I;?8UkZ+(zL#{rY(|Decfb$2OW8r)u@v%6)?nXS{r#jxXK$Y8 ziErgiAH5c7LY%>fgBshT%y+^X8;*~zTl;TAW?Jqxp4P` zz0%{K1ixhbC}aO?k!|rF(3(C7!A{^`TDLtwnvZ~tmwiaL!?S^Gf4>7#m-m6xF|J*Y z+tYzuZ(C8ow=n(`$wZ zH{am^O(nu_vS=dQLc@0=&&1F0iEs-|9l{^AXl!@1`j>bk_KExGI`IyW=KMJA&h+2YjLH(_$dY`92_JZUIu}7eLmh)Gu{?S_CBB zgFwpO38d`79l9R<0Lc2Y8b~^Q9@N!lXCnPHwV&zmHXzN{;vSgIdoZJL4`!IPkI<)x z`N#gY67k75G*k0g0iU$blflD_3=9X=mZ`AroKA<&53$k-wtHR zi$KPE3CQ#x)la*R2dZ>M>5n!+w{|K20?46RFY+=c^uylSaAyea_jupkX-2$TKuf;u zQg+`8CW_uefJ|2=km))aNc~1hIIPM9zS4Z|0@4imT9-HffSab^8(r=x|JLO@5Xkgh zF7AaumA)Z-&#J53I-ny>qm*l=@IOK14IIle%;C;aNMF}Y1KvE;<>p(f^Q~U=-6ELQ zU;Ezxr17Wd{BHx&d;UA@*Hw#ZccovP&bk6{3#*EbNp8CHI#5Mh2tLQY~ zGF|3AAk#Zu@Khk{`jtS|^=rkyTJTOF`=BNu`=B?)-xd4}=pU$g{sl<$CXlv_LAt$< z0kU1K15);1ft0xqNST8N>-Ike$nkV7kaXLDl>GsavVSl{@7J9NWdC);11N4W-M(q!Sh)+57Khk`*2sQ!PzrQN(Rv^>$cOcXC z5s>Zvkc7jkOzkMmFF8x|TRB?i*E2x!+kdRiucMCB?&E;uGX}`~St0H!AoYqiZib+9 zv(%GukVmsf*Rj%Sp@B`8pEFd>sR%{K>;K|8sz>A2*Bp zZlKB+Pe0Nq^`J=PKMkbWW$KOUUynrpIw)%Y>PkIueyrmq3x=|_ybpmibz^jTE*q=e zbAd{qDD6D08uKwJ#}tV_RrvMPzvdv0>0gU}q-87u79OeP)B$OR9i{b{0Hk^C=;--U z1b#Hll5fXL{8NQrwElH1;^6zKDqUtC*?dKe^Dcg7{ukkv`Cs5CG0p|}8JY;U(6nQo z`JFY_wB2fMJK5Z)igSt}Z;2(-b`Lx*$vLjDcwave>+HTx zCidkrC#1JRtkSI?=45drG0!nFe;DIDg5U4Jhp67uM!v_S#5pNgqo2U6DiHCjQcZ)<{oJAN5|#~Kzte&3`wQ-W`g&=|QhVXqSz zDnK5!QRp6sLe~g7>TdY?VD}FbCKmYcZCWo~VWveO)&`NW7HRPs_T>%m|4-7}DBt!n z`Z2waMM=m0(?#Bg-Q_aJGT`sc+cf&)+buMPKhv0Hc&QNmF#L<6@MoK?gnu*{h6TS_ zL}SZY9Yv0zH{Wk={+DjkyAi-&3*;nzgtq-p%)3!ejrg_lcRI%1Gf)@s<31Djs{GZ! zRMe|~V9$=fVoX6%M~m>Q0w+LUgz@eq-}B-f1)iBUH^C1--mwWxj{fs6McS+%-y6k$!a40_NDB%l zbcg)Pf%q9dwZDSQyTBiQ%`YO&d!QTg6aV|+;6Fc{cKp0<{AZBEb7%aAki+w0!>j&f z==&=8<5zSN@*T)|F6ZQ&=WwpYah-Dm?gwzMg6m7JVY!~-nvDBM+!N#7+0aHH${7DO z;uO6O_XNa2x|(7C|Jpkj@VKgS@2{iTpm#2ilLR6&TK$6Bif4{8+;e7|?E zHG6J*W|Fqi=lPC#o`3#p)_&LfuFJdDUVH7!>I3~#sH3^)!2!THsb7*EI$$H+y!=n z1K=%i=9}mR*MU!gZQyb68aV0Cd1?x{9^3{V0f)i4f5}so;8UOryaY!46&s)dYy$hh z8{pg{j02zw+zh@6c7vC}JK&7JVFOfwM({Pz4W0!@z=Xf&sny`y;6*UvtvodqJS_YV z7)27q;1w|Sojer;9pDi7kjhs9a6kAJI43V(Ed{rNhrosT z`RWdE1l%YOvG9ETEno!m!P($O@F1AVd+gr>~mjhBj2HU9$au%zKVj!!1%NC)iUr&a36RLTyhTbU>A5BOg}eYMZjyq=jE$I;4|mv ztG|LT73QmdfG=IZ`wFA;)!pEI7g7dLG$vnt9Xtu%0Anx8S1ZA1!F`|)EW4Qeg6U)P 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 ZZPT_@Z)@4sv+c;XQSGjFlpW>Y{{xEGXD$E$ literal 0 HcmV?d00001 diff --git a/bin/IlmThread-2_2.dll b/bin/IlmThread-2_2.dll new file mode 100644 index 0000000000000000000000000000000000000000..7ccc537081bfa08d5b34b23c769c04becd7ee6aa GIT binary patch literal 43520 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 R9Zz&TL52R~{--4HzX8G>5E%df literal 0 HcmV?d00001 diff --git a/bin/Imath-2_2.dll b/bin/Imath-2_2.dll new file mode 100644 index 0000000000000000000000000000000000000000..65514a89843f2766489d9945608c08c2cb0d165f GIT binary patch literal 84480 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 literal 0 HcmV?d00001 diff --git a/empty b/empty deleted file mode 100644 index e69de29..0000000 diff --git a/exrflatten.cpp b/exrflatten.cpp new file mode 100644 index 0000000..bdfce8c --- /dev/null +++ b/exrflatten.cpp @@ -0,0 +1,699 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace Imf; +using namespace Imath; + +const int NO_OBJECT_ID = 0; + +// This currently processes all object IDs at once, which means we need enough memory to hold all +// output buffers at once. We could make a separate pass for each object ID to reduce memory usage, +// so we only need to hold one at a time. +// +// Not currently supported/tested: +// - data window is untested +// - tiled images +// - volumes (samples with non-zero depth) +// - arbitrary channel mappings, including layers (we assume "R", "G", "B", "A", "Z", "ZBack", "id") +// - separate per-color alpha (RA, GA, BA) +// - (and lots of other stuff, EXR is "too general") + +string vssprintf(const char *fmt, va_list va) +{ + // Work around a gcc bug: passing a va_list to vsnprintf alters it. va_list is supposed + // to be by value. + va_list vc; + va_copy(vc, va); + + int iBytes = vsnprintf(NULL, 0, fmt, vc); + char *pBuf = (char*) alloca(iBytes + 1); + vsnprintf(pBuf, iBytes + 1, fmt, va); + return string(pBuf, iBytes); +} + +string ssprintf(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + return vssprintf(fmt, va); +} + +string subst(string s, string from, string to) +{ + int start = 0; + while(1) + { + auto pos = s.find(from, start); + if(pos == string::npos) + break; + + string before = s.substr(0, pos); + string after = s.substr(pos + from.size()); + s = before + to + after; + start = pos + to.size(); + } + + return s; +} + +/* + * Return the last named component of dir: + * a/b/c -> c + * a/b/c/ -> c + */ +string basename(const string &dir) +{ + size_t end = dir.find_last_not_of("/\\"); + if( end == dir.npos ) + return ""; + + size_t start = dir.find_last_of("/\\", end); + if(start == dir.npos) + start = 0; + else + ++start; + + return dir.substr(start, end-start+1); +} + +string setExtension(string path, const string &ext) +{ + auto pos = path.rfind('.'); + if(pos != string::npos) + path = path.substr(0, pos); + + return path + ext; +} + +// Given a filename like "abcdef.1234.exr", return "1234". +string getFrameNumberFromFilename(string s) +{ + // abcdef.1234.exr -> abcdef.1234 + s = setExtension(s, ""); + + auto pos = s.rfind("."); + if(pos == string::npos) + return ""; + + string frameString = s.substr(pos+1); + return frameString; +} + +// http://www.openexr.com/TechnicalIntroduction.pdf: +void splitVolumeSample( + float a, float c, // Opacity and color of original sample + float zf, float zb, // Front and back of original sample + float z, // Position of split + float& af, float& cf, // Opacity and color of part closer than z + float& ab, float& cb) // Opacity and color of part further away than z +{ + // Given a volume sample whose front and back are at depths zf and zb respectively, split the + // sample at depth z. Return the opacities and colors of the two parts that result from the split. + // + // The code below is written to avoid excessive rounding errors when the opacity of the original + // sample is very small: + // + // The straightforward computation of the opacity of either part requires evaluating an expression + // of the form + // + // 1 - pow (1-a, x). + // + // However, if a is very small, then 1-a evaluates to 1.0 exactly, and the entire expression + // evaluates to 0.0. + // + // We can avoid this by rewriting the expression as + // + // 1 - exp (x * log (1-a)), + // + // and replacing the call to log() with a call to the function log1p(), which computes the logarithm + // of 1+x without attempting to evaluate the expression 1+x when x is very small. + // + // Now we have + // + // 1 - exp (x * log1p (-a)). + // + // However, if a is very small then the call to exp() returns 1.0, and the overall expression still + // evaluates to 0.0. We can avoid that by replacing the call to exp() with a call to expm1(): + // + // -expm1 (x * log1p (-a)) + // + // expm1(x) computes exp(x) - 1 in such a way that the result is accurate even if x is very small. + + assert (zb > zf && z >= zf && z <= zb); + a = max (0.0f, min (a, 1.0f)); + if (a == 1) + { + af = ab = 1; + cf = cb = c; + } + else + { + float xf = (z - zf) / (zb - zf); + float xb = (zb - z) / (zb - zf); + if (a > numeric_limits::min()) + { + af = -expm1 (xf * log1p (-a)); + cf = (af / a) * c; + ab = -expm1 (xb * log1p (-a)); + cb = (ab / a) * c; + } + else + { + af = a * xf; + cf = c * xf; + ab = a * xb; + cb = c * xb; + } + } +} + +void mergeOverlappingSamples( + float a1, float c1, // Opacity and color of first sample + float a2, float c2, // Opacity and color of second sample + float &am, float &cm) // Opacity and color of merged sample +{ + // This function merges two perfectly overlapping volume or point samples. Given the color and + // opacity of two samples, it returns the color and opacity of the merged sample. + // + // The code below is written to avoid very large rounding errors when the opacity of one or both + // samples is very small: + // + // * The merged opacity must not be computed as 1 - (1-a1) * (1-a2)./ If a1 and a2 are less than + // about half a floating-point epsilon, the expressions (1-a1) and (1-a2) evaluate to 1.0 exactly, + // and the merged opacity becomes 0.0. The error is amplified later in the calculation of the + // merged color. + // + // Changing the calculation of the merged opacity to a1 + a2 - a1*a2 avoids the excessive rounding + // error. + // + // * For small x, the logarithm of 1+x is approximately equal to x, but log(1+x) returns 0 because + // 1+x evaluates to 1.0 exactly. This can lead to large errors in the calculation of the merged + // color if a1 or a2 is very small. + // + // The math library function log1p(x) returns the logarithm of 1+x, but without attempting to + // evaluate the expression 1+x when x is very small. + + a1 = max (0.0f, min (a1, 1.0f)); + a2 = max (0.0f, min (a2, 1.0f)); + am = a1 + a2 - a1 * a2; + if (a1 == 1 && a2 == 1) + cm = (c1 + c2) / 2; + else if (a1 == 1) + cm = c1; + else if (a2 == 1) + cm = c2; + else + { + static const float MAX = numeric_limits::max(); + float u1 = -log1p (-a1); + float v1 = (u1 < a1 * MAX)? u1 / a1: 1; + float u2 = -log1p (-a2); + float v2 = (u2 < a2 * MAX)? u2 / a2: 1; + float u = u1 + u2; + float w = (u > 1 || am < u * MAX)? am / u: 1; + cm = (c1 * v1 + c2 * v2) * w; + } +} + +template +class FBArray { +public: + Array2D data; + + FBArray() + { + } + + ~FBArray() + { + for(int y = 0; y < data.height(); y++) + { + for(int x = 0; x < data.width(); x++) + delete[] data[y][x]; + } + } + + void alloc(const Array2D &sampleCount) + { + for(int y = 0; y < data.height(); y++) + { + for(int x = 0; x < data.width(); x++) + data[y][x] = new T[sampleCount[y][x]]; + } + } + + void AddArrayToFramebuffer(string name, PixelType pt, const Header &header, DeepFrameBuffer &frameBuffer) + { + Box2i dataWindow = header.dataWindow(); + int width = dataWindow.max.x - dataWindow.min.x + 1; + int height = dataWindow.max.y - dataWindow.min.y + 1; + data.resizeErase(height, width); + + DeepSlice slice(pt, + (char *) (&data[0][0] - dataWindow.min.x - dataWindow.min.y * data.width()), + sizeof(T *), sizeof(T *) * data.width(), sizeof(T)); + frameBuffer.insert(name, slice); + } +}; + +// A simple container for an output EXR containing only RGBA data. +class SimpleImage +{ +public: + struct pixel { + float rgba[4]; + }; + vector data; + int width, height; + Header header; + + SimpleImage(int width_, int height_): + header(width_, height_) + { + width = width_; + height = height_; + data.resize(width*height); + } + + void setColor(float r, float g, float b, float a) + { + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + const int pixelIdx = x + y*width; + data[pixelIdx].rgba[0] = r; + data[pixelIdx].rgba[1] = g; + data[pixelIdx].rgba[2] = b; + data[pixelIdx].rgba[3] = a; + } + } + } + + void write(string filename) const + { + Header headerCopy(header); + headerCopy.channels().insert("R", Channel(FLOAT)); + headerCopy.channels().insert("G", Channel(FLOAT)); + headerCopy.channels().insert("B", Channel(FLOAT)); + headerCopy.channels().insert("A", Channel(FLOAT)); + + FrameBuffer frameBuffer; + frameBuffer.insert("R", Slice(FLOAT, (char *) &data.data()->rgba[0], sizeof(pixel), sizeof(pixel) * width)); + frameBuffer.insert("G", Slice(FLOAT, (char *) &data.data()->rgba[1], sizeof(pixel), sizeof(pixel) * width)); + frameBuffer.insert("B", Slice(FLOAT, (char *) &data.data()->rgba[2], sizeof(pixel), sizeof(pixel) * width)); + frameBuffer.insert("A", Slice(FLOAT, (char *) &data.data()->rgba[3], sizeof(pixel), sizeof(pixel) * width)); + + OutputFile file(filename.c_str(), headerCopy); + file.setFrameBuffer(frameBuffer); + file.writePixels(height); + } +}; + +struct DeepSample +{ + float rgba[4]; + float zNear, zFar; + uint32_t objectId; +}; + +void ReadEXR(DeepScanLineInputFile &file, Array2D> &samples) +{ + const Header &header = file.header(); + Box2i dataWindow = header.dataWindow(); + const int width = dataWindow.max.x - dataWindow.min.x + 1; + const int height = dataWindow.max.y - dataWindow.min.y + 1; + + DeepFrameBuffer frameBuffer; + + Array2D sampleCount; + sampleCount.resizeErase(height, width); + frameBuffer.insertSampleCountSlice(Slice(UINT, + (char *) (&sampleCount[0][0] - dataWindow.min.x - dataWindow.min.y * width), + sizeof(unsigned int), sizeof(unsigned int) * width)); + + // Set up the channels that we need. This would be a lot cleaner if we could use a single data + // structure for all data, but the EXR library doesn't seem to support interleaved data for deep + // samples. + FBArray dataR; + dataR.AddArrayToFramebuffer("R", FLOAT, header, frameBuffer); + + FBArray dataG; + dataG.AddArrayToFramebuffer("G", FLOAT, header, frameBuffer); + + FBArray dataB; + dataB.AddArrayToFramebuffer("B", FLOAT, header, frameBuffer); + + FBArray dataA; + dataA.AddArrayToFramebuffer("A", FLOAT, header, frameBuffer); + + FBArray dataId; + dataId.AddArrayToFramebuffer("id", UINT, header, frameBuffer); + + FBArray dataZ; + dataZ.AddArrayToFramebuffer("Z", FLOAT, header, frameBuffer); + + FBArray dataZB; + dataZB.AddArrayToFramebuffer("ZBack", FLOAT, header, frameBuffer); + + file.setFrameBuffer(frameBuffer); + file.readPixelSampleCounts(dataWindow.min.y, dataWindow.max.y); + + // Allocate the channels now that we know the number of samples per pixel. + dataR.alloc(sampleCount); + dataG.alloc(sampleCount); + dataB.alloc(sampleCount); + dataA.alloc(sampleCount); + dataId.alloc(sampleCount); + dataZ.alloc(sampleCount); + dataZB.alloc(sampleCount); + + // Read the main image data. + file.readPixels(dataWindow.min.y, dataWindow.max.y); + + samples.resizeErase(height, width); + + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + vector &out = samples[y][x]; + samples[y][x].resize(sampleCount[y][x]); + for(int s = 0; s < sampleCount[y][x]; ++s) + { + out[s].rgba[0] = dataR.data[y][x][s]; + out[s].rgba[1] = dataG.data[y][x][s]; + out[s].rgba[2] = dataB.data[y][x][s]; + out[s].rgba[3] = dataA.data[y][x][s]; + out[s].zNear = dataZ.data[y][x][s]; + out[s].zFar = dataZB.data[y][x][s]; + out[s].objectId = dataId.data[y][x][s]; + + // Try to work around bad Arnold default IDs. If you don't explicitly specify an object ID, + // Arnold seems to write uninitialized memory or some other random-looking data to it. + if(out[s].objectId > 1000000) + out[s].objectId = NO_OBJECT_ID; + } + } + } +} + +// Given a list of samples on a pixel, return a list of sample indices sorted by depth, furthest +// from the camera first. +void sortSamplesByDepth(vector &samples) +{ + // Sort samples by depth. + sort(samples.begin(), samples.end(), [](const auto &lhs, const auto &rhs) { + return lhs.zNear > rhs.zNear; + }); +} + +struct Layer +{ + string name; + int objectId; + shared_ptr image; + + Layer(string name_, int width, int height) + { + name = name_; + image = make_shared(width, height); + } +}; + +/* + * Create a set of images, one per object ID in the input image, which can be combined with + * additive blending to get the original image. This is useful because the layers can be + * edited simply on a per-object basis and composited in a simpler application like Photoshop. + * + * Normally, samples are composited with "over" compositing. The order of samples is important: + * + * r = 0 // current color + * r = r0*a0 + r*(1-a0); // overlay r0/a0, and reduce everything under it + * r = r1*a1 + r*(1-a1); // overlay r1/a1, and reduce everything under it + * r = r2*a2 + r*(1-a2); // overlay r2/a2, and reduce everything under it + * ... + * + * which iteratively adds each sample on top to the output, and reduces the contribution + * of everything underneath it in the process. This is repeated for each RGBA channel. + * + * We want to know the final contribution of each sample at the end, so instead we do: + * + * r[0] = r0*a0 // r*(1-a0) is zero since this is the first layer + * + * r[1]= r1*a1 // overlay r1/a1 + * r[0] *= (1-a1) // and reduce everything under it + * + * r[2] = r2*a2 // overlay r2/a2 + * r[1] *= (1-a2) // and reduce everything under it + * r[0] *= (1-a2) // and reduce everything under it + * + * This tracks each term separately: instead of applying the r*(1-a0) term accumulatively, + * we track its effect on each individual sample underneath it. Adding r[0]+r[1]+r[2] + * would be equivalent to the normal compositing formula. + * + * Since this is simple addition, the order of samples no longer matters. We can then + * combine samples by object ID, and the resulting images can be added together with simple + * additive blending. + */ +void SeparateIntoAdditiveLayers(vector &layers, const Array2D> &samples) +{ +/* layers.push_back(Layer("test", samples.width(), samples.height())); + layers.back().objectId = 0; + auto image = layers.back().image;*/ + + map> imagesPerObjectId; + + for(int y = 0; y < samples.height(); y++) + { + for(int x = 0; x < samples.width(); x++) + { + const vector &samplesForPixel = samples[y][x]; + + struct AccumulatedSample { + AccumulatedSample() + { + for(int i = 0; i < 4; ++i) + rgba[i] = 0; + } + float rgba[4]; + int objectId; + float zNear; + }; + + vector sampleLayers; + for(const DeepSample &sample: samplesForPixel) + { + AccumulatedSample new_sample; + new_sample.objectId = sample.objectId; + new_sample.zNear = sample.zNear; + for(int i = 0; i < 4; ++i) + new_sample.rgba[i] = sample.rgba[i]; + + // Apply the alpha term to each sample underneath this one. + float a = sample.rgba[3]; + for(AccumulatedSample &sample: sampleLayers) + { + for(int i = 0; i < 4; ++i) + sample.rgba[i] *= 1-a; + } + + // Add the new sample. + sampleLayers.push_back(new_sample); + } + + // Combine samples by object ID, creating a layer for each. + // + // We could do this in one pass instead of two, but debugging is easier in two passes. + const int pixelIdx = x + y*samples.width(); +/* for(const AccumulatedSample &sample: sampleLayers) + { + for(int i = 0; i < 4; ++i) + image->data[pixelIdx].rgba[i] += sample.rgba[i]; + } */ + + for(const AccumulatedSample &sample: sampleLayers) + { + int objectId = sample.objectId; + if(imagesPerObjectId.find(objectId) == imagesPerObjectId.end()) + { + layers.push_back(Layer("color", samples.width(), samples.height())); + Layer &layer = layers.back(); + layer.objectId = objectId; + imagesPerObjectId[objectId] = layer.image; + } + + auto image = imagesPerObjectId.at(objectId); + for(int i = 0; i < 4; ++i) + image->data[pixelIdx].rgba[i] += sample.rgba[i]; + } + } + } +} + +void readObjectIdNames(const Header &header, map &objectIdNames) +{ + for(auto it = header.begin(); it != header.end(); ++it) + { + auto &attr = it.attribute(); + if(strcmp(attr.typeName(), "string")) + continue; + + string headerName = it.name(); + if(headerName.substr(0, 9) != "ObjectId/") + continue; + + string idString = headerName.substr(9); + int id = atoi(idString.c_str()); + const StringAttribute &value = dynamic_cast(attr); + objectIdNames[id] = value.value(); + } +} + +void readDeepScanlineFile(string filename, string output) +{ + DeepScanLineInputFile file(filename.c_str()); + const Header &header = file.header(); + +/* + const ChannelList &channels = file.header().channels(); + for(auto i = channels.begin(); i != channels.end(); ++i) + { + const Channel &channel = i.channel(); + printf("... %s: %i\n", i.name(), channel.type); + } + + set layerNames; + channels.layers(layerNames); + for(const string &layerName: layerNames) + { + printf("layer: %s", layerName.c_str()); + ChannelList::ConstIterator layerBegin, layerEnd; + channels.channelsInLayer(layerName, layerBegin, layerEnd); + for(auto j = layerBegin; j != layerEnd; ++j) + { + cout << "\tchannel " << j.name() << endl; + } + } +*/ + Array2D> samples; + ReadEXR(file, samples); + + // Sort all samples by depth. If we want to support volumes, this is where we'd do the rest + // of "tidying", splitting samples where they overlap using splitVolumeSample. + for(int y = 0; y < samples.height(); y++) + { + for(int x = 0; x < samples.width(); x++) + { + vector &samplesForPixel = samples[y][x]; + sortSamplesByDepth(samplesForPixel); + } + } + + // Separate the image into layers. + vector layers; + + SeparateIntoAdditiveLayers(layers, samples); + + // If this file has names for object IDs, read them. + map objectIdNames; + readObjectIdNames(header, objectIdNames); + + if(!objectIdNames.empty()) + { + printf("Object ID names:\n"); + for(auto it: objectIdNames) + printf("Id %i: %s\n", it.first, it.second.c_str()); + printf("\n"); + } + + // Set the layer with the object ID 0 to "default", unless a name for that ID + // was specified explicitly. + if(objectIdNames.find(NO_OBJECT_ID) == objectIdNames.end()) + objectIdNames[NO_OBJECT_ID] = "default"; + + // Write the results. + for(int i = 0; i < layers.size(); ++i) + { + auto &layer = layers[i]; + + // Copy all image attributes, except for built-in EXR headers that we shouldn't set. + for(auto it = header.begin(); it != header.end(); ++it) + { + auto &attr = it.attribute(); + string headerName = it.name(); + if(headerName == "channels" || + headerName == "chunkCount" || + headerName == "compression" || + headerName == "lineOrder" || + headerName == "type" || + headerName == "version") + continue; + + if(headerName.substr(0, 9) == "ObjectId/") + continue; + + layer.image->header.insert(headerName, attr); + } + + // Do simple substitutions on the output filename. + string outputName = output; + string objectIdName; + if(objectIdNames.find(layer.objectId) != objectIdNames.end()) + objectIdName = objectIdNames.at(layer.objectId); + else + objectIdName = ssprintf("#%i", layer.objectId); + + // : the name of the object ID that we got from the EXR file, or "#100" if we + // only have a number. + outputName = subst(outputName, "", objectIdName); + + // : the output layer that we generated. This is currently always "color". + outputName = subst(outputName, "", layer.name); + + // : the input filename, with the directory and ".exr" removed. + string inputName = filename; + inputName = basename(inputName); + inputName = setExtension(inputName, ""); + outputName = subst(outputName, "", inputName); + + // : the input filename's frame number, given a "abcdef.1234.exr" filename. + // It would be nice if there was an EXR attribute contained the frame number. + outputName = subst(outputName, "", getFrameNumberFromFilename(filename)); + + printf("Writing: %s\n", outputName.c_str()); + layer.image->write(outputName); + } +} + +int main(int argc, char **argv) +{ + if(argc < 3) { + fprintf( stderr, "Usage: exrflatten input.exr output\n" ); + return 1; + } + + readDeepScanlineFile(argv[1], argv[2]); + return 0; +} + diff --git a/exrflatten.sln b/exrflatten.sln new file mode 100644 index 0000000..ee36b01 --- /dev/null +++ b/exrflatten.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25029.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exrflatten", "exrflatten.vcxproj", "{9C9F1D42-292A-4DA0-A2AD-C46618E0ABED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9C9F1D42-292A-4DA0-A2AD-C46618E0ABED}.Debug|x64.ActiveCfg = Debug|x64 + {9C9F1D42-292A-4DA0-A2AD-C46618E0ABED}.Debug|x64.Build.0 = Debug|x64 + {9C9F1D42-292A-4DA0-A2AD-C46618E0ABED}.Release|x64.ActiveCfg = Release|x64 + {9C9F1D42-292A-4DA0-A2AD-C46618E0ABED}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/exrflatten.vcxproj b/exrflatten.vcxproj new file mode 100644 index 0000000..e585e7e --- /dev/null +++ b/exrflatten.vcxproj @@ -0,0 +1,101 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {9C9F1D42-292A-4DA0-A2AD-C46618E0ABED} + Win32Proj + exrflatten + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + false + Unicode + + + + + + + + + + + + + + + true + $(VC_IncludePath);$(WindowsSDK_IncludePath);OpenEXR\include + $(SolutionDir)\build\$(Configuration)\ + bin\ + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);OpenEXR\include + $(SolutionDir)\build\$(Configuration)\ + bin\ + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + /wd4018 /wd4800 /wd4267 %(AdditionalOptions) + + + Console + true + OpenEXR\lib;%(AdditionalLibraryDirectories) + IlmImf-2_2.lib;%(AdditionalDependencies) + bin\$(TargetName)$(TargetExt) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + /wd4018 /wd4800 /wd4267 %(AdditionalOptions) + + + Console + true + true + true + OpenEXR\lib;%(AdditionalLibraryDirectories) + IlmImf-2_2.lib;%(AdditionalDependencies) + bin\$(TargetName)$(TargetExt) + + + + + + + + + \ No newline at end of file diff --git a/exrflatten.vcxproj.filters b/exrflatten.vcxproj.filters new file mode 100644 index 0000000..bd7abc7 --- /dev/null +++ b/exrflatten.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file