PageRenderTime 35ms CodeModel.GetById 18ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/src/core/FileFormatSpi1D.cpp

http://github.com/imageworks/OpenColorIO
C++ | 261 lines | 165 code | 38 blank | 58 comment | 37 complexity | 8359afc16fe38344aa5761cb92e7f066 MD5 | raw file
  1/*
  2Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
  3All Rights Reserved.
  4
  5Redistribution and use in source and binary forms, with or without
  6modification, are permitted provided that the following conditions are
  7met:
  8* Redistributions of source code must retain the above copyright
  9  notice, this list of conditions and the following disclaimer.
 10* Redistributions in binary form must reproduce the above copyright
 11  notice, this list of conditions and the following disclaimer in the
 12  documentation and/or other materials provided with the distribution.
 13* Neither the name of Sony Pictures Imageworks nor the names of its
 14  contributors may be used to endorse or promote products derived from
 15  this software without specific prior written permission.
 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 17"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 18LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 19A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 20OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 21SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 22LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 26OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27*/
 28
 29#include <OpenColorIO/OpenColorIO.h>
 30
 31#include "FileTransform.h"
 32#include "Lut1DOp.h"
 33#include "pystring/pystring.h"
 34
 35#include <cstdio>
 36#include <sstream>
 37
 38/*
 39Version 1
 40From -7.5 3.7555555555555555
 41Components 1
 42Length 4096
 43{
 44        0.031525943963232252
 45        0.045645604561056156
 46	...
 47}
 48
 49*/
 50
 51
 52OCIO_NAMESPACE_ENTER
 53{
 54    ////////////////////////////////////////////////////////////////
 55    
 56    namespace
 57    {
 58        class LocalCachedFile : public CachedFile
 59        {
 60        public:
 61            LocalCachedFile()
 62            {
 63                lut = Lut1D::Create();
 64            };
 65            ~LocalCachedFile() {};
 66            
 67            Lut1DRcPtr lut;
 68        };
 69        
 70        typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
 71        
 72        
 73        class LocalFileFormat : public FileFormat
 74        {
 75        public:
 76            
 77            ~LocalFileFormat() {};
 78            
 79            virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
 80            
 81            virtual CachedFileRcPtr Read(std::istream & istream) const;
 82            
 83            virtual void BuildFileOps(OpRcPtrVec & ops,
 84                         const Config& config,
 85                         const ConstContextRcPtr & context,
 86                         CachedFileRcPtr untypedCachedFile,
 87                         const FileTransform& fileTransform,
 88                         TransformDirection dir) const;
 89        };
 90        
 91        void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
 92        {
 93            FormatInfo info;
 94            info.name = "spi1d";
 95            info.extension = "spi1d";
 96            info.capabilities = FORMAT_CAPABILITY_READ;
 97            formatInfoVec.push_back(info);
 98        }
 99        
100        // Try and load the format
101        // Raise an exception if it can't be loaded.
102
103        CachedFileRcPtr LocalFileFormat::Read(std::istream & istream) const
104        {
105            Lut1DRcPtr lut1d = Lut1D::Create();
106
107            // Parse Header Info
108            int lut_size = -1;
109            float from_min = 0.0;
110            float from_max = 1.0;
111            int version = -1;
112            int components = -1;
113
114            const int MAX_LINE_SIZE = 4096;
115            char lineBuffer[MAX_LINE_SIZE];
116
117            // PARSE HEADER INFO
118            {
119                std::string headerLine("");
120                do
121                {
122                    istream.getline(lineBuffer, MAX_LINE_SIZE);
123                    headerLine = std::string(lineBuffer);
124                    if(pystring::startswith(headerLine, "Version"))
125                    {
126                        if(sscanf(lineBuffer, "Version %d", &version)!=1)
127                            throw Exception("Invalid 'Version' Tag");
128                    }
129                    else if(pystring::startswith(headerLine, "From"))
130                    {
131                        if(sscanf(lineBuffer, "From %f %f", &from_min, &from_max)!=2)
132                            throw Exception("Invalid 'From' Tag");
133                    }
134                    else if(pystring::startswith(headerLine, "Components"))
135                    {
136                        if(sscanf(lineBuffer, "Components %d", &components)!=1)
137                            throw Exception("Invalid 'Components' Tag");
138                    }
139                    else if(pystring::startswith(headerLine, "Length"))
140                    {
141                        if(sscanf(lineBuffer, "Length %d", &lut_size)!=1)
142                            throw Exception("Invalid 'Length' Tag");
143                    }
144                }
145                while (istream.good() && !pystring::startswith(headerLine,"{"));
146            }
147
148            if(version == -1)
149                throw Exception("Could not find 'Version' Tag");
150            if(version != 1)
151                throw Exception("Only format version 1 supported.");
152            if (lut_size == -1)
153                throw Exception("Could not find 'Length' Tag");
154            if (components == -1)
155                throw Exception("Could not find 'Components' Tag");
156            if (components<0 || components>3)
157                throw Exception("Components must be [1,2,3]");
158
159
160
161            for(int i=0; i<3; ++i)
162            {
163                lut1d->from_min[i] = from_min;
164                lut1d->from_max[i] = from_max;
165                lut1d->luts[i].clear();
166                lut1d->luts[i].reserve(lut_size);
167            }
168
169            {
170                istream.getline(lineBuffer, MAX_LINE_SIZE);
171
172                int lineCount=0;
173                float values[4];
174
175                while (istream.good())
176                {
177                    // If 1 component is specificed, use x1 x1 x1 defaultA
178                    if(components==1 && sscanf(lineBuffer,"%f",&values[0])==1)
179                    {
180                        lut1d->luts[0].push_back(values[0]);
181                        lut1d->luts[1].push_back(values[0]);
182                        lut1d->luts[2].push_back(values[0]);
183                        ++lineCount;
184                    }
185                    // If 2 components are specificed, use x1 x2 0.0
186                    else if(components==2 && sscanf(lineBuffer,"%f %f",&values[0],&values[1])==2)
187                    {
188                        lut1d->luts[0].push_back(values[0]);
189                        lut1d->luts[1].push_back(values[1]);
190                        lut1d->luts[2].push_back(0.0);
191                        ++lineCount;
192                    }
193                    // If 3 component is specificed, use x1 x2 x3 defaultA
194                    else if(components==3 && sscanf(lineBuffer,"%f %f %f",&values[0],&values[1],&values[2])==3)
195                    {
196                        lut1d->luts[0].push_back(values[0]);
197                        lut1d->luts[1].push_back(values[1]);
198                        lut1d->luts[2].push_back(values[2]);
199                        ++lineCount;
200                    }
201
202                    if(lineCount == lut_size) break;
203
204                    istream.getline(lineBuffer, MAX_LINE_SIZE);
205                }
206
207                if(lineCount!=lut_size)
208                    throw Exception("Not enough entries found.");
209            }
210
211            // 1e-5 rel error is a good threshold when float numbers near 0
212            // are written out with 6 decimal places of precision.  This is
213            // a bit aggressive, I.e., changes in the 6th decimal place will
214            // be considered roundoff error, but changes in the 5th decimal
215            // will be considered lut 'intent'.
216            // 1.0
217            // 1.000005 equal to 1.0
218            // 1.000007 equal to 1.0
219            // 1.000010 not equal
220            // 0.0
221            // 0.000001 not equal
222            lut1d->maxerror = 1e-5f;
223            lut1d->errortype = ERROR_RELATIVE;
224
225            LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
226            cachedFile->lut = lut1d;
227            return cachedFile;
228        }
229
230        void LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
231                                  const Config& /*config*/,
232                                  const ConstContextRcPtr & /*context*/,
233                                  CachedFileRcPtr untypedCachedFile,
234                                  const FileTransform& fileTransform,
235                                  TransformDirection dir) const
236        {
237            LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
238
239            if(!cachedFile) // This should never happen.
240            {
241                std::ostringstream os;
242                os << "Cannot build Spi1D Op. Invalid cache type.";
243                throw Exception(os.str().c_str());
244            }
245
246            TransformDirection newDir = CombineTransformDirections(dir,
247                fileTransform.getDirection());
248
249            CreateLut1DOp(ops,
250                          cachedFile->lut,
251                          fileTransform.getInterpolation(),
252                          newDir);
253        }
254    }
255    
256    FileFormat * CreateFileFormatSpi1D()
257    {
258        return new LocalFileFormat();
259    }
260}
261OCIO_NAMESPACE_EXIT