summaryrefslogtreecommitdiff
path: root/src/core/FileFormatSpi1D.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/FileFormatSpi1D.cpp')
-rw-r--r--src/core/FileFormatSpi1D.cpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/core/FileFormatSpi1D.cpp b/src/core/FileFormatSpi1D.cpp
new file mode 100644
index 0000000..2835c50
--- /dev/null
+++ b/src/core/FileFormatSpi1D.cpp
@@ -0,0 +1,261 @@
+/*
+Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of Sony Pictures Imageworks nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <OpenColorIO/OpenColorIO.h>
+
+#include "FileTransform.h"
+#include "Lut1DOp.h"
+#include "pystring/pystring.h"
+
+#include <cstdio>
+#include <sstream>
+
+/*
+Version 1
+From -7.5 3.7555555555555555
+Components 1
+Length 4096
+{
+ 0.031525943963232252
+ 0.045645604561056156
+ ...
+}
+
+*/
+
+
+OCIO_NAMESPACE_ENTER
+{
+ ////////////////////////////////////////////////////////////////
+
+ namespace
+ {
+ class LocalCachedFile : public CachedFile
+ {
+ public:
+ LocalCachedFile()
+ {
+ lut = Lut1D::Create();
+ };
+ ~LocalCachedFile() {};
+
+ Lut1DRcPtr lut;
+ };
+
+ typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
+
+
+ class LocalFileFormat : public FileFormat
+ {
+ public:
+
+ ~LocalFileFormat() {};
+
+ virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
+
+ virtual CachedFileRcPtr Read(std::istream & istream) const;
+
+ virtual void BuildFileOps(OpRcPtrVec & ops,
+ const Config& config,
+ const ConstContextRcPtr & context,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const;
+ };
+
+ void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
+ {
+ FormatInfo info;
+ info.name = "spi1d";
+ info.extension = "spi1d";
+ info.capabilities = FORMAT_CAPABILITY_READ;
+ formatInfoVec.push_back(info);
+ }
+
+ // Try and load the format
+ // Raise an exception if it can't be loaded.
+
+ CachedFileRcPtr LocalFileFormat::Read(std::istream & istream) const
+ {
+ Lut1DRcPtr lut1d = Lut1D::Create();
+
+ // Parse Header Info
+ int lut_size = -1;
+ float from_min = 0.0;
+ float from_max = 1.0;
+ int version = -1;
+ int components = -1;
+
+ const int MAX_LINE_SIZE = 4096;
+ char lineBuffer[MAX_LINE_SIZE];
+
+ // PARSE HEADER INFO
+ {
+ std::string headerLine("");
+ do
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ headerLine = std::string(lineBuffer);
+ if(pystring::startswith(headerLine, "Version"))
+ {
+ if(sscanf(lineBuffer, "Version %d", &version)!=1)
+ throw Exception("Invalid 'Version' Tag");
+ }
+ else if(pystring::startswith(headerLine, "From"))
+ {
+ if(sscanf(lineBuffer, "From %f %f", &from_min, &from_max)!=2)
+ throw Exception("Invalid 'From' Tag");
+ }
+ else if(pystring::startswith(headerLine, "Components"))
+ {
+ if(sscanf(lineBuffer, "Components %d", &components)!=1)
+ throw Exception("Invalid 'Components' Tag");
+ }
+ else if(pystring::startswith(headerLine, "Length"))
+ {
+ if(sscanf(lineBuffer, "Length %d", &lut_size)!=1)
+ throw Exception("Invalid 'Length' Tag");
+ }
+ }
+ while (istream.good() && !pystring::startswith(headerLine,"{"));
+ }
+
+ if(version == -1)
+ throw Exception("Could not find 'Version' Tag");
+ if(version != 1)
+ throw Exception("Only format version 1 supported.");
+ if (lut_size == -1)
+ throw Exception("Could not find 'Length' Tag");
+ if (components == -1)
+ throw Exception("Could not find 'Components' Tag");
+ if (components<0 || components>3)
+ throw Exception("Components must be [1,2,3]");
+
+
+
+ for(int i=0; i<3; ++i)
+ {
+ lut1d->from_min[i] = from_min;
+ lut1d->from_max[i] = from_max;
+ lut1d->luts[i].clear();
+ lut1d->luts[i].reserve(lut_size);
+ }
+
+ {
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+
+ int lineCount=0;
+ float values[4];
+
+ while (istream.good())
+ {
+ // If 1 component is specificed, use x1 x1 x1 defaultA
+ if(components==1 && sscanf(lineBuffer,"%f",&values[0])==1)
+ {
+ lut1d->luts[0].push_back(values[0]);
+ lut1d->luts[1].push_back(values[0]);
+ lut1d->luts[2].push_back(values[0]);
+ ++lineCount;
+ }
+ // If 2 components are specificed, use x1 x2 0.0
+ else if(components==2 && sscanf(lineBuffer,"%f %f",&values[0],&values[1])==2)
+ {
+ lut1d->luts[0].push_back(values[0]);
+ lut1d->luts[1].push_back(values[1]);
+ lut1d->luts[2].push_back(0.0);
+ ++lineCount;
+ }
+ // If 3 component is specificed, use x1 x2 x3 defaultA
+ else if(components==3 && sscanf(lineBuffer,"%f %f %f",&values[0],&values[1],&values[2])==3)
+ {
+ lut1d->luts[0].push_back(values[0]);
+ lut1d->luts[1].push_back(values[1]);
+ lut1d->luts[2].push_back(values[2]);
+ ++lineCount;
+ }
+
+ if(lineCount == lut_size) break;
+
+ istream.getline(lineBuffer, MAX_LINE_SIZE);
+ }
+
+ if(lineCount!=lut_size)
+ throw Exception("Not enough entries found.");
+ }
+
+ // 1e-5 rel error is a good threshold when float numbers near 0
+ // are written out with 6 decimal places of precision. This is
+ // a bit aggressive, I.e., changes in the 6th decimal place will
+ // be considered roundoff error, but changes in the 5th decimal
+ // will be considered lut 'intent'.
+ // 1.0
+ // 1.000005 equal to 1.0
+ // 1.000007 equal to 1.0
+ // 1.000010 not equal
+ // 0.0
+ // 0.000001 not equal
+ lut1d->maxerror = 1e-5f;
+ lut1d->errortype = ERROR_RELATIVE;
+
+ LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
+ cachedFile->lut = lut1d;
+ return cachedFile;
+ }
+
+ void LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
+ const Config& /*config*/,
+ const ConstContextRcPtr & /*context*/,
+ CachedFileRcPtr untypedCachedFile,
+ const FileTransform& fileTransform,
+ TransformDirection dir) const
+ {
+ LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
+
+ if(!cachedFile) // This should never happen.
+ {
+ std::ostringstream os;
+ os << "Cannot build Spi1D Op. Invalid cache type.";
+ throw Exception(os.str().c_str());
+ }
+
+ TransformDirection newDir = CombineTransformDirections(dir,
+ fileTransform.getDirection());
+
+ CreateLut1DOp(ops,
+ cachedFile->lut,
+ fileTransform.getInterpolation(),
+ newDir);
+ }
+ }
+
+ FileFormat * CreateFileFormatSpi1D()
+ {
+ return new LocalFileFormat();
+ }
+}
+OCIO_NAMESPACE_EXIT