PageRenderTime 44ms CodeModel.GetById 14ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/core/FileFormatPandora.cpp

http://github.com/imageworks/OpenColorIO
C++ | 286 lines | 214 code | 37 blank | 35 comment | 58 complexity | ce3331cd9adf6ecc205cdddb051d4eaa 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 <cstdio>
 30#include <iostream>
 31#include <iterator>
 32
 33#include <OpenColorIO/OpenColorIO.h>
 34
 35#include "FileTransform.h"
 36#include "Lut1DOp.h"
 37#include "Lut3DOp.h"
 38#include "ParseUtils.h"
 39#include "pystring/pystring.h"
 40
 41OCIO_NAMESPACE_ENTER
 42{
 43    namespace
 44    {
 45        class LocalCachedFile : public CachedFile
 46        {
 47        public:
 48            LocalCachedFile ()
 49            {
 50                lut3D = Lut3D::Create();
 51            };
 52            ~LocalCachedFile() {};
 53            
 54            Lut3DRcPtr lut3D;
 55        };
 56        
 57        typedef OCIO_SHARED_PTR<LocalCachedFile> LocalCachedFileRcPtr;
 58        
 59        
 60        
 61        class LocalFileFormat : public FileFormat
 62        {
 63        public:
 64            
 65            ~LocalFileFormat() {};
 66            
 67            virtual void GetFormatInfo(FormatInfoVec & formatInfoVec) const;
 68            
 69            virtual CachedFileRcPtr Read(std::istream & istream) const;
 70            
 71            virtual void BuildFileOps(OpRcPtrVec & ops,
 72                         const Config& config,
 73                         const ConstContextRcPtr & context,
 74                         CachedFileRcPtr untypedCachedFile,
 75                         const FileTransform& fileTransform,
 76                         TransformDirection dir) const;
 77        };
 78        
 79        void LocalFileFormat::GetFormatInfo(FormatInfoVec & formatInfoVec) const
 80        {
 81            FormatInfo info;
 82            info.name = "pandora_mga";
 83            info.extension = "mga";
 84            info.capabilities = FORMAT_CAPABILITY_READ;
 85            formatInfoVec.push_back(info);
 86            
 87            FormatInfo info2;
 88            info2.name = "pandora_m3d";
 89            info2.extension = "m3d";
 90            info2.capabilities = FORMAT_CAPABILITY_READ;
 91            formatInfoVec.push_back(info2);
 92        }
 93        
 94        CachedFileRcPtr
 95        LocalFileFormat::Read(std::istream & istream) const
 96        {
 97            // this shouldn't happen
 98            if(!istream)
 99            {
100                throw Exception ("File stream empty when trying to read Pandora lut");
101            }
102            
103            // Validate the file type
104            std::string line;
105            
106            // Parse the file
107            std::string format;
108            int lutEdgeLen = 0;
109            int outputBitDepthMaxValue = 0;
110            std::vector<int> raw3d;
111            
112            {
113                std::vector<std::string> parts;
114                std::vector<int> tmpints;
115                bool inLut3d = false;
116                
117                while(nextline(istream, line))
118                {
119                    // Strip, lowercase, and split the line
120                    pystring::split(pystring::lower(pystring::strip(line)), parts);
121                    if(parts.empty()) continue;
122                    
123                    // Skip all lines starting with '#'
124                    if(pystring::startswith(parts[0],"#")) continue;
125                    
126                    if(parts[0] == "channel")
127                    {
128                        if(parts.size() != 2 || pystring::lower(parts[1]) != "3d")
129                        {
130                            throw Exception("Parse error in Pandora lut. Only 3d luts are currently supported. (channel: 3d).");
131                        }
132                    }
133                    else if(parts[0] == "in")
134                    {
135                        int inval = 0;
136                        if(parts.size() != 2 || !StringToInt( &inval, parts[1].c_str()))
137                        {
138                            throw Exception("Malformed 'in' tag in Pandora lut.");
139                        }
140                        raw3d.reserve(inval*3);
141                        lutEdgeLen = Get3DLutEdgeLenFromNumPixels(inval);
142                    }
143                    else if(parts[0] == "out")
144                    {
145                        if(parts.size() != 2 || !StringToInt( &outputBitDepthMaxValue, parts[1].c_str()))
146                        {
147                            throw Exception("Malformed 'out' tag in Pandora lut.");
148                        }
149                    }
150                    else if(parts[0] == "format")
151                    {
152                        if(parts.size() != 2 || pystring::lower(parts[1]) != "lut")
153                        {
154                            throw Exception("Parse error in Pandora lut. Only luts are currently supported. (format: lut).");
155                        }
156                    }
157                    else if(parts[0] == "values")
158                    {
159                        if(parts.size() != 4 || 
160                           pystring::lower(parts[1]) != "red" ||
161                           pystring::lower(parts[2]) != "green" ||
162                           pystring::lower(parts[3]) != "blue")
163                        {
164                            throw Exception("Parse error in Pandora lut. Only rgb luts are currently supported. (values: red green blue).");
165                        }
166                        
167                        inLut3d = true;
168                    }
169                    else if(inLut3d)
170                    {
171                        if(!StringVecToIntVec(tmpints, parts) || tmpints.size() != 4)
172                        {
173                            std::ostringstream os;
174                            os << "Parse error in Pandora lut. Expected to find 4 integers. Instead found '"
175                            << line << "'";
176                            throw Exception(os.str().c_str());
177                        }
178                        
179                        raw3d.push_back(tmpints[1]);
180                        raw3d.push_back(tmpints[2]);
181                        raw3d.push_back(tmpints[3]);
182                    }
183                }
184            }
185            
186            // Interpret the parsed data, validate lut sizes
187            if(lutEdgeLen*lutEdgeLen*lutEdgeLen != static_cast<int>(raw3d.size()/3))
188            {
189                std::ostringstream os;
190                os << "Parse error in Pandora lut. ";
191                os << "Incorrect number of lut3d entries. ";
192                os << "Found " << raw3d.size()/3 << ", expected " << lutEdgeLen*lutEdgeLen*lutEdgeLen << ".";
193                throw Exception(os.str().c_str());
194            }
195            
196            if(lutEdgeLen*lutEdgeLen*lutEdgeLen == 0)
197            {
198                std::ostringstream os;
199                os << "Parse error in Pandora lut. ";
200                os << "No 3D Lut entries found.";
201                throw Exception(os.str().c_str());
202            }
203            
204            if(outputBitDepthMaxValue <= 0)
205            {
206                std::ostringstream os;
207                os << "Parse error in Pandora lut. ";
208                os << "A valid 'out' tag was not found.";
209                throw Exception(os.str().c_str());
210            }
211            
212            LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
213            
214            // Reformat 3D data
215            cachedFile->lut3D->size[0] = lutEdgeLen;
216            cachedFile->lut3D->size[1] = lutEdgeLen;
217            cachedFile->lut3D->size[2] = lutEdgeLen;
218            cachedFile->lut3D->lut.reserve(raw3d.size());
219            
220            float scale = 1.0f / ((float)outputBitDepthMaxValue - 1.0f);
221            
222            for(int rIndex=0; rIndex<lutEdgeLen; ++rIndex)
223            {
224                for(int gIndex=0; gIndex<lutEdgeLen; ++gIndex)
225                {
226                    for(int bIndex=0; bIndex<lutEdgeLen; ++bIndex)
227                    {
228                        int i = GetLut3DIndex_B(rIndex, gIndex, bIndex,
229                                                lutEdgeLen, lutEdgeLen, lutEdgeLen);
230                        cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+0]) * scale);
231                        cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+1]) * scale);
232                        cachedFile->lut3D->lut.push_back(static_cast<float>(raw3d[i+2]) * scale);
233                    }
234                }
235            }
236            
237            return cachedFile;
238        }
239        
240        void
241        LocalFileFormat::BuildFileOps(OpRcPtrVec & ops,
242                                      const Config& /*config*/,
243                                      const ConstContextRcPtr & /*context*/,
244                                      CachedFileRcPtr untypedCachedFile,
245                                      const FileTransform& fileTransform,
246                                      TransformDirection dir) const
247        {
248            LocalCachedFileRcPtr cachedFile = DynamicPtrCast<LocalCachedFile>(untypedCachedFile);
249            
250            // This should never happen.
251            if(!cachedFile)
252            {
253                std::ostringstream os;
254                os << "Cannot build Truelight .cub Op. Invalid cache type.";
255                throw Exception(os.str().c_str());
256            }
257            
258            TransformDirection newDir = CombineTransformDirections(dir,
259                fileTransform.getDirection());
260            if(newDir == TRANSFORM_DIR_UNKNOWN)
261            {
262                std::ostringstream os;
263                os << "Cannot build file format transform,";
264                os << " unspecified transform direction.";
265                throw Exception(os.str().c_str());
266            }
267            
268            if(newDir == TRANSFORM_DIR_FORWARD)
269            {
270                CreateLut3DOp(ops, cachedFile->lut3D,
271                              fileTransform.getInterpolation(), newDir);
272            }
273            else if(newDir == TRANSFORM_DIR_INVERSE)
274            {
275                CreateLut3DOp(ops, cachedFile->lut3D,
276                              fileTransform.getInterpolation(), newDir);
277            }
278        }
279    }
280    
281    FileFormat * CreateFileFormatPandora()
282    {
283        return new LocalFileFormat();
284    }
285}
286OCIO_NAMESPACE_EXIT