示例#1
0
 void LoadCDL(CDLTransform * cdl, TiXmlElement * root)
 {
     if(!cdl) return;
     
     if(!root)
     {
         std::ostringstream os;
         os << "Error loading CDL xml. ";
         os << "Null root element.";
         throw Exception(os.str().c_str());
     }
     
     if(std::string(root->Value()) != "ColorCorrection")
     {
         std::ostringstream os;
         os << "Error loading CDL xml. ";
         os << "Root element is type '" << root->Value() << "', ";
         os << "ColorCorrection expected.";
         throw Exception(os.str().c_str());
     }
     
     TiXmlHandle handle( root );
     
     const char * id = root->Attribute("id");
     if(!id) id = "";
     
     cdl->setID(id);
     
     TiXmlElement* desc = handle.FirstChild( "SOPNode" ).FirstChild("Description").ToElement();
     if(desc)
     {
         const char * text = desc->GetText();
         if(text) cdl->setDescription(text);
     }
     
     std::vector<std::string> lineParts;
     std::vector<float> floatArray;
     
     TiXmlElement* slope = handle.FirstChild( "SOPNode" ).FirstChild("Slope").ToElement();
     if(slope)
     {
         const char * text = slope->GetText();
         if(text)
         {
             pystring::split(pystring::strip(text), lineParts);
             if((lineParts.size() != 3) || (!StringVecToFloatVec(floatArray, lineParts)))
             {
                 std::ostringstream os;
                 os << "Error loading CDL xml. ";
                 os << id << ".SOPNode.Slope text '";
                 os << text << "' is not convertible to 3 floats.";
                 throw Exception(os.str().c_str());
             }
             cdl->setSlope(&floatArray[0]);
         }
     }
     
     TiXmlElement* offset = handle.FirstChild( "SOPNode" ).FirstChild("Offset").ToElement();
     if(offset)
     {
         const char * text = offset->GetText();
         if(text)
         {
             pystring::split(pystring::strip(text), lineParts);
             if((lineParts.size() != 3) || (!StringVecToFloatVec(floatArray, lineParts)))
             {
                 std::ostringstream os;
                 os << "Error loading CDL xml. ";
                 os << id << ".SOPNode.Offset text '";
                 os << text << "' is not convertible to 3 floats.";
                 throw Exception(os.str().c_str());
             }
             cdl->setOffset(&floatArray[0]);
         }
     }
     
     TiXmlElement* power = handle.FirstChild( "SOPNode" ).FirstChild("Power").ToElement();
     if(power)
     {
         const char * text = power->GetText();
         if(text)
         {
             pystring::split(pystring::strip(text), lineParts);
             if((lineParts.size() != 3) || (!StringVecToFloatVec(floatArray, lineParts)))
             {
                 std::ostringstream os;
                 os << "Error loading CDL xml. ";
                 os << id << ".SOPNode.Power text '";
                 os << text << "' is not convertible to 3 floats.";
                 throw Exception(os.str().c_str());
             }
             cdl->setPower(&floatArray[0]);
         }
     }
     
     TiXmlElement* sat = handle.FirstChild( "SatNode" ).FirstChild("Saturation").ToElement();
     if(sat)
     {
         const char * text = sat->GetText();
         if(text)
         {
             float satval = 1.0f;
             if(!StringToFloat(&satval, text))
             {
                 std::ostringstream os;
                 os << "Error loading CDL xml. ";
                 os << id << ".SatNode.Saturation text '";
                 os << text << "' is not convertible to float.";
                 throw Exception(os.str().c_str());
             }
             cdl->setSat(satval);
         }
     }
 }
 CachedFileRcPtr
 LocalFileFormat::Read(
     std::istream & istream,
     const std::string & fileName) const
 {
     // this shouldn't happen
     if(!istream)
     {
         throw Exception ("File stream empty when trying to read Iridas .cube lut");
     }
     
     // Parse the file
     std::vector<float> raw;
     
     int size3d[] = { 0, 0, 0 };
     int size1d = 0;
     
     bool in1d = false;
     bool in3d = false;
     
     float domain_min[] = { 0.0f, 0.0f, 0.0f };
     float domain_max[] = { 1.0f, 1.0f, 1.0f };
     
     {
         std::string line;
         std::vector<std::string> parts;
         std::vector<float> tmpfloats;
         int lineNumber = 0;
         
         while(nextline(istream, line))
         {
             ++lineNumber;
             // All lines starting with '#' are comments
             if(pystring::startswith(line,"#")) continue;
             
             // Strip, lowercase, and split the line
             pystring::split(pystring::lower(pystring::strip(line)), parts);
             if(parts.empty()) continue;
             
             if(pystring::lower(parts[0]) == "title")
             {
                 // Optional, and currently unhandled
             }
             else if(pystring::lower(parts[0]) == "lut_1d_size")
             {
                 if(parts.size() != 2
                     || !StringToInt( &size1d, parts[1].c_str()))
                 {
                     ThrowErrorMessage(
                         "Malformed LUT_1D_SIZE tag.",
                         fileName,
                         lineNumber,
                         line);
                 }
                 
                 raw.reserve(3*size1d);
                 in1d = true;
             }
             else if(pystring::lower(parts[0]) == "lut_2d_size")
             {
                 ThrowErrorMessage(
                     "Unsupported tag: 'LUT_2D_SIZE'.",
                     fileName,
                     lineNumber,
                     line);
             }
             else if(pystring::lower(parts[0]) == "lut_3d_size")
             {
                 int size = 0;
                 
                 if(parts.size() != 2
                     || !StringToInt( &size, parts[1].c_str()))
                 {
                     ThrowErrorMessage(
                         "Malformed LUT_3D_SIZE tag.",
                         fileName,
                         lineNumber,
                         line);
                 }
                 size3d[0] = size;
                 size3d[1] = size;
                 size3d[2] = size;
                 
                 raw.reserve(3*size3d[0]*size3d[1]*size3d[2]);
                 in3d = true;
             }
             else if(pystring::lower(parts[0]) == "domain_min")
             {
                 if(parts.size() != 4 || 
                     !StringToFloat( &domain_min[0], parts[1].c_str()) ||
                     !StringToFloat( &domain_min[1], parts[2].c_str()) ||
                     !StringToFloat( &domain_min[2], parts[3].c_str()))
                 {
                     ThrowErrorMessage(
                         "Malformed DOMAIN_MIN tag.",
                         fileName,
                         lineNumber,
                         line);
                 }
             }
             else if(pystring::lower(parts[0]) == "domain_max")
             {
                 if(parts.size() != 4 || 
                     !StringToFloat( &domain_max[0], parts[1].c_str()) ||
                     !StringToFloat( &domain_max[1], parts[2].c_str()) ||
                     !StringToFloat( &domain_max[2], parts[3].c_str()))
                 {
                     ThrowErrorMessage(
                         "Malformed DOMAIN_MAX tag.",
                         fileName,
                         lineNumber,
                         line);
                 }
             }
             else
             {
                 // It must be a float triple!
                 
                 if(!StringVecToFloatVec(tmpfloats, parts) || tmpfloats.size() != 3)
                 {
                     ThrowErrorMessage(
                         "Malformed color triples specified.",
                         fileName,
                         lineNumber,
                         line);
                 }
                 
                 for(int i=0; i<3; ++i)
                 {
                     raw.push_back(tmpfloats[i]);
                 }
             }
         }
     }
     
     // Interpret the parsed data, validate lut sizes
     
     LocalCachedFileRcPtr cachedFile = LocalCachedFileRcPtr(new LocalCachedFile());
     
     if(in1d)
     {
         if(size1d != static_cast<int>(raw.size()/3))
         {
             std::ostringstream os;
             os << "Incorrect number of lut1d entries. ";
             os << "Found " << raw.size() / 3;
             os << ", expected " << size1d << ".";
             ThrowErrorMessage(
                 os.str().c_str(),
                 fileName, -1, "");
         }
         
         // Reformat 1D data
         if(size1d>0)
         {
             cachedFile->has1D = true;
             memcpy(cachedFile->lut1D->from_min, domain_min, 3*sizeof(float));
             memcpy(cachedFile->lut1D->from_max, domain_max, 3*sizeof(float));
             
             for(int channel=0; channel<3; ++channel)
             {
                 cachedFile->lut1D->luts[channel].resize(size1d);
                 for(int i=0; i<size1d; ++i)
                 {
                     cachedFile->lut1D->luts[channel][i] = raw[3*i+channel];
                 }
             }
             
             // 1e-5 rel error is a good threshold when float numbers near 0
             // are written out with 6 decimal places of precision.  This is
             // a bit aggressive, I.e., changes in the 6th decimal place will
             // be considered roundoff error, but changes in the 5th decimal
             // will be considered lut 'intent'.
             // 1.0
             // 1.000005 equal to 1.0
             // 1.000007 equal to 1.0
             // 1.000010 not equal
             // 0.0
             // 0.000001 not equal
             
             cachedFile->lut1D->maxerror = 1e-5f;
             cachedFile->lut1D->errortype = ERROR_RELATIVE;
         }
     }
     else if(in3d)
     {
         cachedFile->has3D = true;
         
         if(size3d[0]*size3d[1]*size3d[2] 
             != static_cast<int>(raw.size()/3))
         {
             std::ostringstream os;
             os << "Incorrect number of lut3d entries. ";
             os << "Found " << raw.size() / 3 << ", expected ";
             os << size3d[0] * size3d[1] * size3d[2] << ".";
             ThrowErrorMessage(
                 os.str().c_str(),
                 fileName, -1, "");
         }
         
         // Reformat 3D data
         memcpy(cachedFile->lut3D->from_min, domain_min, 3*sizeof(float));
         memcpy(cachedFile->lut3D->from_max, domain_max, 3*sizeof(float));
         cachedFile->lut3D->size[0] = size3d[0];
         cachedFile->lut3D->size[1] = size3d[1];
         cachedFile->lut3D->size[2] = size3d[2];
         cachedFile->lut3D->lut = raw;
     }
     else
     {
         ThrowErrorMessage(
             "Lut type (1D/3D) unspecified.",
             fileName, -1, "");
     }
     
     return cachedFile;
 }