Beispiel #1
0
FactoryResource<DynamicObject> Nitf::DesSubheader::createDefaultsDynamicObject(
    const RasterDataDescriptor *pDescriptor)
{
    FactoryResource<DynamicObject> pDesSubheader;

    // Per the NITF spec, the field "DE" must contain the value "DE".
    pDesSubheader->setAttribute(DE, DE);
    return pDesSubheader;
}
Beispiel #2
0
DynamicObject *QueryOptions::toDynamicObject() const
{
    FactoryResource<DynamicObject> pDynObj;
    VERIFYRV(pDynObj.get() != NULL, NULL);

    pDynObj->setAttribute(QUERY_NAME, mQueryName);
    pDynObj->setAttribute(FORMAT_STRING, mFormatString);
    pDynObj->setAttribute(QUERY_STRING, mQueryString);
    pDynObj->setAttribute(SYMBOL_NAME, mSymbolName);
    pDynObj->setAttribute(SYMBOL_SIZE, mSymbolSize);
    pDynObj->setAttribute(LINE_STATE, mLineState);
    pDynObj->setAttribute(LINE_STYLE, mLineStyle);
    pDynObj->setAttribute(LINE_WIDTH, mLineWidth);
    pDynObj->setAttribute(LINE_COLOR, mLineColor);
    pDynObj->setAttribute(LINE_SCALED, mLineScaled);
    pDynObj->setAttribute(FILL_COLOR, mFillColor);
    pDynObj->setAttribute(FILL_STYLE, mFillStyle);
    pDynObj->setAttribute(HATCH_STYLE, mHatchStyle);

    return pDynObj.release();
}
vector<ImportDescriptor*> SignatureSetImporter::createImportDescriptors(DOMTreeWalker* pTree, vector<string> &datasetPath)
{
   vector<ImportDescriptor*> descriptors;
   FactoryResource<DynamicObject> pMetadata;
   VERIFYRV(pMetadata.get() != NULL, descriptors);

   string datasetName = StringUtilities::toDisplayString(mDatasetNumber++);
   for (DOMNode* pChld = pTree->firstChild(); pChld != NULL; pChld = pTree->nextSibling())
   {
      if (XMLString::equals(pChld->getNodeName(), X("metadata")))
      {
         DOMElement* pElmnt = static_cast<DOMElement*>(pChld);
         string name = A(pElmnt->getAttribute(X("name")));
         string val = A(pElmnt->getAttribute(X("value")));
         pMetadata->setAttribute(name, val);
         if (name == "Name")
         {
            datasetName = val;
         }
      }
      else if (XMLString::equals(pChld->getNodeName(), X("signature_set")))
      {
         datasetPath.push_back(datasetName);
         vector<ImportDescriptor*> sub = createImportDescriptors(pTree, datasetPath);
         datasetPath.pop_back();
         descriptors.insert(descriptors.end(), sub.begin(), sub.end());
         pTree->parentNode();
      }
   }
   ImportDescriptorResource pImportDescriptor(datasetName, "SignatureSet", datasetPath);
   VERIFYRV(pImportDescriptor.get() != NULL, descriptors);
   DataDescriptor* pDataDescriptor = pImportDescriptor->getDataDescriptor();
   VERIFYRV(pDataDescriptor != NULL, descriptors);
   FactoryResource<SignatureFileDescriptor> pFileDescriptor;
   VERIFYRV(pFileDescriptor.get() != NULL, descriptors);
   pFileDescriptor->setFilename(mFilename);
   datasetPath.push_back(datasetName);
   string loc = "/" + StringUtilities::join(datasetPath, "/");
   datasetPath.pop_back();
   pFileDescriptor->setDatasetLocation(loc);
   pDataDescriptor->setFileDescriptor(pFileDescriptor.get());
   pDataDescriptor->setMetadata(pMetadata.get());
   descriptors.push_back(pImportDescriptor.release());
   return descriptors;
}
vector<ImportDescriptor*> EnviLibraryImporter::getImportDescriptors(const string& filename)
{
   vector<ImportDescriptor*> descriptors;

   string headerFile = filename;
   string dataFile;
   // assume filename is a header file and try to parse
   bool bSuccess = mFields.populateFromHeader(filename);
   if (bSuccess == false)
   {
      dataFile = filename;           // was passed data file name instead of header file name
      headerFile = findHeaderFile(dataFile);
      if (headerFile.empty() == false)
      {
         bSuccess = mFields.populateFromHeader(headerFile);
      }
   }
   if (bSuccess == true)
   {
      if (dataFile.empty())  // was passed header file name and now need to find the data file name
      {
         dataFile = findDataFile(headerFile);
      }
      if (dataFile.empty())  // no data file found for the header
      {
         return descriptors;
      }

      EnviField* pField = mFields.find("file type");
      if (pField != NULL)
      {
         if (pField->mValue == "ENVI Spectral Library" || 
             pField->mValue == "Spectral Library")
         {
            // Get the name and dataset from the header values
            string name;
            string dataset;

            EnviField* pBandNamesField = mFields.find("band names");
            if (pBandNamesField != NULL)
            {
               if (pBandNamesField->mChildren.empty() == false)
               {
                  EnviField* pNameField = pBandNamesField->mChildren.front();
                  if (pNameField != NULL)
                  {
                     name = pNameField->mValue;
                  }
               }
            }

            EnviField* pDescriptionField = mFields.find("description");
            if (pDescriptionField != NULL)
            {
               // Library name
               if (name.empty() == true)
               {
                  EnviField* pNameField = pDescriptionField->find("library name");
                  if (pNameField != NULL)
                  {
                     name = pNameField->mValue;
                  }
               }

               // Dataset
               EnviField* pDatasetField = pDescriptionField->find("dataset");
               if (pDatasetField != NULL)
               {
                  dataset = pDatasetField->mValue;
               }
            }

            // Create the data descriptor
            Service<ModelServices> pModel;

            RasterElement* pRasterElement = NULL;
            if (dataset.empty() == false)
            {
               pRasterElement = dynamic_cast<RasterElement*>(pModel->getElement(dataset, "RasterElement", NULL));
            }

            if (name.empty() == true)
            {
               // Create a unique default name
               unsigned int libraryNumber = pModel->getElements(pRasterElement, "SignatureLibrary").size();

               DataElement* pSignatureLibrary = NULL;
               do
               {
                  char buffer[64];
                  sprintf(buffer, "%u", ++libraryNumber);

                  name = "Spectral Library " + string(buffer);
                  pSignatureLibrary = pModel->getElement(name, "SignatureLibrary", pRasterElement);
               }
               while (pSignatureLibrary != NULL);
            }

            ImportDescriptor* pImportDescriptor =
               pModel->createImportDescriptor(name, "SignatureLibrary", pRasterElement);
            if (pImportDescriptor != NULL)
            {
               SignatureDataDescriptor* pDescriptor =
                  dynamic_cast<SignatureDataDescriptor*>(pImportDescriptor->getDataDescriptor());
               if (pDescriptor != NULL)
               {
                  // Metadata
                  FactoryResource<DynamicObject> pMetadata;
                  if (pDescriptionField != NULL)
                  {
                     vector<EnviField*>& children = pDescriptionField->mChildren;
                     for (vector<EnviField*>::iterator iter = children.begin(); iter != children.end(); ++iter)
                     {
                        EnviField* pField = *iter;
                        if (pField != NULL)
                        {
                           if ((pField->mTag.empty() == false) && (pField->mValue.empty() == false))
                           {
                              pMetadata->setAttribute(pField->mTag, pField->mValue);
                           }
                        }
                     }
                  }

                  // Signature names
                  EnviField* pSigNamesField = mFields.find("spectra names");
                  if (pSigNamesField != NULL)
                  {
                     vector<string> sigNames;
                     for (unsigned int i = 0; i < pSigNamesField->mChildren.size(); i++)
                     {
                        EnviField* pField = pSigNamesField->mChildren[i];
                        if (pField != NULL)
                        {
                           vector<char> bufferVector(pField->mValue.size() + 1);
                           char* pBuffer = &bufferVector.front();
                           strcpy(pBuffer, pField->mValue.c_str());

                           char* pPtr = strtok(pBuffer, ",");
                           while (pPtr != NULL)
                           {
                              string sigName = StringUtilities::stripWhitespace(string(pPtr));
                              sigNames.push_back(sigName);

                              pPtr = strtok(NULL, ",");
                           }
                        }
                     }

                     if (sigNames.empty() == false)
                     {
                        pMetadata->setAttribute("Signature Names", sigNames);
                     }
                  }

                  // Signature units - Set custom units into the data descriptor so that the
                  // user can modify them even though units are not loaded from the file
                  FactoryResource<Units> pUnits;
                  pUnits->setUnitName("Custom");
                  pUnits->setUnitType(CUSTOM_UNIT);
                  pDescriptor->setUnits("Reflectance", pUnits.get());

                  // Wavelengths
                  EnviField* pSamplesField = mFields.find("samples");
                  if (pSamplesField != NULL)
                  {
                     unsigned int numWavelengths = StringUtilities::fromXmlString<unsigned int>(pSamplesField->mValue);

                     vector<double> wavelengths;
                     unsigned int uiNanometerValues = 0;

                     EnviField* pWavelengthField = mFields.find("wavelength");
                     if (pWavelengthField != NULL)
                     {
                        vector<unsigned int> goodBands;
                        EnviField* pBblField = mFields.find("bbl");
                        if (pBblField != NULL)
                        {
                           // Parse the bad bands list. This method puts the indices of good bands in ascending order.
                           EnviImporter::parseBbl(pBblField, goodBands);

                           // Sort in descending order so that the last one can be popped later
                           // A pop_back is much faster than an erase on the first element
                           reverse(goodBands.begin(), goodBands.end());
                        }

                        unsigned int numWavelengthsRead = 0;
                        for (std::vector<EnviField*>::const_iterator iter = pWavelengthField->mChildren.begin();
                           iter != pWavelengthField->mChildren.end();
                           ++iter)
                        {
                           EnviField* pField = *iter;
                           if (pField != NULL)
                           {
                              vector<char> bufferVector(pField->mValue.size() + 1);
                              char* pBuffer = &(bufferVector.front());
                              strcpy(pBuffer, pField->mValue.c_str());

                              char* pPtr = strtok(pBuffer, ",");
                              while (pPtr != NULL)
                              {
                                 double dWavelength = 0.0;
                                 if (sscanf(pPtr, "%lf", &dWavelength) == 1)
                                 {
                                    if (dWavelength > 50.0)    // Assumed to be in nanometers
                                    {
                                       uiNanometerValues++;
                                    }

                                    // Restrict the number of wavelengths to the number of samples in the header file
                                    if (numWavelengthsRead < numWavelengths)
                                    {
                                       // Only write the wavelength if the value is valid
                                       // Since the bands are in descending order,
                                       // goodBands.back() always holds the next good band.
                                       if (pBblField == NULL ||
                                          (goodBands.empty() == false && goodBands.back() == numWavelengthsRead))
                                       {
                                          if (goodBands.empty() == false)
                                          {
                                             goodBands.pop_back();
                                          }

                                          wavelengths.push_back(dWavelength);
                                       }
                                    }

                                    ++numWavelengthsRead;
                                 }

                                 pPtr = strtok(NULL, ",");
                              }
                           }
                        }

                        VERIFYNR(goodBands.empty() == true);
                     }

                     // Wavelength units
                     bool bConvertWavelengths = false;
                     bool bDetermineUnits = true;

                     EnviField* pUnitsField = mFields.find("wavelength units");
                     if (pUnitsField != NULL)
                     {
                        if (pUnitsField->mValue == "Micrometers")
                        {
                           bDetermineUnits = false;
                        }
                        else if (pUnitsField->mValue == "Nanometers")
                        {
                           bDetermineUnits = false;
                           bConvertWavelengths = true;
                        }
                     }

                     if (bDetermineUnits)
                     {
                        if ((uiNanometerValues * 100) / wavelengths.size() > 50)
                        {
                           bConvertWavelengths = true;
                        }
                     }

                     if (bConvertWavelengths == true)
                     {
                        for (vector<double>::size_type i = 0; i < wavelengths.size(); i++)
                        {
                           wavelengths[i] *= 0.001;
                        }
                     }

                     string pCenterPath[] = { SPECIAL_METADATA_NAME, BAND_METADATA_NAME, 
                        CENTER_WAVELENGTHS_METADATA_NAME, END_METADATA_NAME };
                     pMetadata->setAttributeByPath(pCenterPath, wavelengths);
                  }

                  if (pMetadata->getNumAttributes() > 0)
                  {
                     pDescriptor->setMetadata(pMetadata.get());
                  }

                  // Create the file descriptor
                  FactoryResource<SignatureFileDescriptor> pFileDescriptor;
                  if (pFileDescriptor.get() != NULL)
                  {
                     pFileDescriptor->setFilename(dataFile);
                     pDescriptor->setFileDescriptor(pFileDescriptor.get());
                  }
               }
               descriptors.push_back(pImportDescriptor);
            }
         }
      }
   }

   return descriptors;
}
vector<ImportDescriptor*> SampleHdf4Importer::getImportDescriptors(const string& filename)
{
   vector<ImportDescriptor*> descriptors;

   Hdf4File parsedFile(filename);
   bool bSuccess = getFileData(parsedFile);
   if (bSuccess == true)
   {
      const Hdf4Dataset* pDataset =
         dynamic_cast<const Hdf4Dataset*>(parsedFile.getRootGroup()->getElement("EV_500_RefSB"));
      if ((pDataset != NULL) && (mpModel.get() != NULL))
      {
         Hdf4FileResource pFile(filename.c_str());
         if (pFile.get() != NULL)
         {
            ImportDescriptor* pImportDescriptor = mpModel->createImportDescriptor(filename, "RasterElement", NULL);
            if (pImportDescriptor != NULL)
            {
               RasterDataDescriptor* pDescriptor =
                  dynamic_cast<RasterDataDescriptor*>(pImportDescriptor->getDataDescriptor());
               if (pDescriptor != NULL)
               {
                  FactoryResource<RasterFileDescriptor> pFileDescriptor;
                  if (pFileDescriptor.get() != NULL)
                  {
                     int32 numDims = 0;
                     int32 dataType = 0;
                     int32 numAttr = 0;

                     pFileDescriptor->setFilename(filename);

                     Hdf4DatasetResource pDataHandle(*pFile, pDataset->getName().c_str());
                     int32 dimSizes[MAX_VAR_DIMS] = {0};
                     if (pDataHandle != NULL && *pDataHandle != FAIL)
                     {
                        pFileDescriptor->setDatasetLocation(pDataset->getName());

                        int32 success = SDgetinfo(*pDataHandle, const_cast<char*>(pDataset->getName().c_str()),
                                                  &numDims, dimSizes, &dataType, &numAttr);
                        // find out what type this Dataset is
                        string strDataType = hdf4TypeToString(dataType, 1);
                        if (success == SUCCEED && numDims == 3 && strDataType == "unsigned short")
                        {
                           // Bands
                           vector<DimensionDescriptor> bands =
                              RasterUtilities::generateDimensionVector(dimSizes[0], true, false, true);

                           pDescriptor->setBands(bands);
                           pFileDescriptor->setBands(bands);

                           // Rows
                           vector<DimensionDescriptor> rows =
                              RasterUtilities::generateDimensionVector(dimSizes[1], true, false, true);

                           pDescriptor->setRows(rows);
                           pFileDescriptor->setRows(rows);

                           // Columns
                           vector<DimensionDescriptor> columns =
                              RasterUtilities::generateDimensionVector(dimSizes[2], true, false, true);

                           pDescriptor->setColumns(columns);
                           pFileDescriptor->setColumns(columns);
                        }
                     }

                     // Data type
                     EncodingType e;
                     pDataset->getDataEncoding(e);
                     pDescriptor->setDataType(e);
                     pFileDescriptor->setBitsPerElement(pDescriptor->getBytesPerElement() * 8);

                     // Interleave format
                     pDescriptor->setInterleaveFormat(BSQ);
                     pFileDescriptor->setInterleaveFormat(BSQ);

                     // Metadata
                     FactoryResource<DynamicObject> pMetadata;
                     if (pMetadata.get() != NULL)
                     {
                        const Hdf4Dataset::AttributeContainer& attributes = pDataset->getAttributes();
                        for (Hdf4Dataset::AttributeContainer::const_iterator it = attributes.begin();
                           it != attributes.end(); ++it)
                        {
                           Hdf4Attribute* pAttribute = it->second;
                           if (pAttribute != NULL)
                           {
                              const string& name = pAttribute->getName();
                              const DataVariant& var = pAttribute->getVariant();
                              const unsigned short* pValue = var.getPointerToValue<unsigned short>();
                              if (name == "_FillValue" && pValue != NULL)
                              {
                                 // Bad values
                                 vector<int> badValues;
                                 badValues.push_back(*pValue);

                                 pDescriptor->setBadValues(badValues);
                              }
                              else
                              {
                                 pMetadata->setAttribute(name, var);
                              }
                           }
                        }

                        pDescriptor->setMetadata(pMetadata.get());
                     }
                     pDescriptor->setFileDescriptor(pFileDescriptor.get());
                  }
               }

               descriptors.push_back(pImportDescriptor);
            }
         }
      }
   }

   return descriptors;
}
Beispiel #6
0
vector<ImportDescriptor*> EnviImporter::getImportDescriptors(const string& filename)
{
   string headerFile = filename;
   string dataFile;
   bool bSuccess = parseHeader(headerFile);
   if (bSuccess == false)
   {
      dataFile = filename;           // was passed data file name instead of header file name
      headerFile = findHeaderFile(headerFile);
      if (headerFile.empty() == false)
      {
         bSuccess = parseHeader(headerFile);
      }
   }

   EnviField* pField = NULL;
   vector<ImportDescriptor*> descriptors;
   if (bSuccess == true)
   {
      if (dataFile.empty() == true)  // was passed header file name and now need to find the data file name
      {
         dataFile = findDataFile(headerFile);
      }

      if (dataFile.empty() == false)
      {
         ImportDescriptor* pImportDescriptor = mpModel->createImportDescriptor(dataFile, "RasterElement", NULL);
         if (pImportDescriptor != NULL)
         {
            RasterDataDescriptor* pDescriptor =
               dynamic_cast<RasterDataDescriptor*>(pImportDescriptor->getDataDescriptor());
            if (pDescriptor != NULL)
            {
               FactoryResource<RasterFileDescriptor> pFileDescriptor;
               if (pFileDescriptor.get() != NULL)
               {
                  // Filename
                  pFileDescriptor->setFilename(dataFile);

                  // Coordinate offset
                  int columnOffset = 0;
                  int rowOffset = 0;

                  pField = mFields.find("x start");
                  if (pField != NULL)
                  {
                     // ENVI numbers are 1 based vs Opticks being 0 based
                     columnOffset = atoi(pField->mValue.c_str()) - 1;
                  }

                  pField = mFields.find("y start");
                  if (pField != NULL)
                  {
                     rowOffset = atoi(pField->mValue.c_str()) - 1; // ENVI numbers are 1 based vs Opticks being 0 based
                  }

                  // Rows
                  vector<DimensionDescriptor> rows;
                  pField = mFields.find("lines");
                  if (pField != NULL)
                  {
                     int numRows = atoi(pField->mValue.c_str());
                     for (int i = 0; i < numRows; ++i)
                     {
                        DimensionDescriptor rowDim;
                        rowDim.setOriginalNumber(static_cast<unsigned int>(rowOffset + i));
                        rowDim.setOnDiskNumber(static_cast<unsigned int>(i));
                        rows.push_back(rowDim);
                     }

                     pDescriptor->setRows(rows);
                     pFileDescriptor->setRows(rows);
                  }

                  string samplesStr = "samples";
                  string bandsStr = "bands";

                  // Special case: if the file type is an ENVI Spectral Library, then swap samples with bands
                  // If no file type field exists, assume this is a normal ENVI header (not a Spectral Library)
                  EnviField* pFileTypeField = mFields.find("file type");
                  if (pFileTypeField != NULL && (pFileTypeField->mValue ==
                     "ENVI Spectral Library" || pFileTypeField->mValue == "Spectral Library"))
                  {
                     samplesStr = "bands";
                     bandsStr = "samples";

                     // Since bands and samples are swapped, force the interleave to BIP
                     pField = mFields.find("interleave");
                     if (pField != NULL)
                     {
                        pField->mValue = "bip";
                     }
                  }

                  // Columns
                  vector<DimensionDescriptor> columns;
                  pField = mFields.find(samplesStr);
                  if (pField != NULL)
                  {
                     int numColumns = atoi(pField->mValue.c_str());
                     for (int i = 0; i < numColumns; ++i)
                     {
                        DimensionDescriptor columnDim;
                        columnDim.setOriginalNumber(static_cast<unsigned int>(columnOffset + i));
                        columnDim.setOnDiskNumber(static_cast<unsigned int>(i));
                        columns.push_back(columnDim);
                     }

                     pDescriptor->setColumns(columns);
                     pFileDescriptor->setColumns(columns);
                  }

                  // Bands
                  vector<DimensionDescriptor> bands;
                  pField = mFields.find(bandsStr);
                  if (pField != NULL)
                  {
                     int numBands = atoi(pField->mValue.c_str());
                     bands = RasterUtilities::generateDimensionVector(numBands, true, false, true);
                     pDescriptor->setBands(bands);
                     pFileDescriptor->setBands(bands);
                  }

                  // Description
                  list<GcpPoint> gcps;

                  pField = mFields.find("description");
                  if (pField != NULL)
                  {
                     // Metadata
                     if (pField->mChildren.empty() == false)
                     {
                        FactoryResource<DynamicObject> pMetadata;
                        for (unsigned int i = 0; i < pField->mChildren.size(); ++i)
                        {
                           EnviField* pChild = pField->mChildren[i];
                           if (pChild != NULL)
                           {
                              if (pChild->mTag == "classification")
                              {
                                 // Classification
                                 FactoryResource<Classification> pClassification;
                                 if (pClassification.get() != NULL)
                                 {
                                    string classLevel;
                                    classLevel.append(1, *(pChild->mValue.data()));
                                    pClassification->setLevel(classLevel);

                                    pDescriptor->setClassification(pClassification.get());
                                 }
                              }
                              else if ((pChild->mTag == "ll") || (pChild->mTag == "lr") || (pChild->mTag == "ul") ||
                                 (pChild->mTag == "ur") || (pChild->mTag == "center"))
                              {
                                 GcpPoint gcp;
                                 bool dmsFormat = false;
                                 char ns;
                                 char ew;

                                 sscanf(pChild->mValue.c_str(), "%lg%c %lg%c", &gcp.mCoordinate.mY, &ew,
                                    &gcp.mCoordinate.mX, &ns);
                                 if (fabs(gcp.mCoordinate.mY) > 180.0 || fabs(gcp.mCoordinate.mX) > 90.0)
                                 {
                                    dmsFormat = true;
                                 }

                                 double deg;
                                 double min;
                                 double sec;
                                 if (dmsFormat == true)
                                 {
                                    deg = static_cast<int>(gcp.mCoordinate.mY / 10000.0);
                                    min = static_cast<int>((gcp.mCoordinate.mY - 10000.0 * deg) / 100.0);
                                    sec = gcp.mCoordinate.mY - 10000.0 * deg - 100.0 * min;
                                    gcp.mCoordinate.mY = deg + (min / 60.0) + (sec / 3600.0);
                                 }

                                 if (ew == 'W' || ew == 'w')
                                 {
                                    gcp.mCoordinate.mY = -gcp.mCoordinate.mY;
                                 }

                                 if (dmsFormat)
                                 {
                                    deg = static_cast<int>(gcp.mCoordinate.mX / 10000.0);
                                    min = static_cast<int>((gcp.mCoordinate.mX - 10000.0 * deg) / 100.0);
                                    sec = gcp.mCoordinate.mX - 10000.0 * deg - 100.0 * min;
                                    gcp.mCoordinate.mX = deg + (min / 60.0) + (sec / 3600.0);
                                 }

                                 if (ns == 'S' || ns == 's')
                                 {
                                    gcp.mCoordinate.mX = -gcp.mCoordinate.mX;
                                 }

                                 // ENVI uses a 1-based pixel coordinate system, with each coordinate referring
                                 // to the top-left corner of the pixel, e.g. (1,1) is the top-left
                                 // corner of the pixel in the top-left of the raster cube
                                 // The ENVI pixel coordinate format is described on p. 1126 of the ENVI 4.2 User's Guide
                                 if (pChild->mTag == "ll")
                                 {
                                    gcp.mPixel.mX = 0.0;
                                    gcp.mPixel.mY = 0.0;
                                 }
                                 else if (pChild->mTag == "lr")
                                 {
                                    gcp.mPixel.mX = columns.size() - 1.0;
                                    gcp.mPixel.mY = 0.0;
                                 }
                                 else if (pChild->mTag == "ul")
                                 {
                                    gcp.mPixel.mX = 0.0;
                                    gcp.mPixel.mY = rows.size() - 1.0;
                                 }
                                 else if (pChild->mTag == "ur")
                                 {
                                    gcp.mPixel.mX = columns.size() - 1.0;
                                    gcp.mPixel.mY = rows.size() - 1.0;
                                 }
                                 else if (pChild->mTag == "center")
                                 {
                                    gcp.mPixel.mX = floor((columns.size() - 1.0) / 2.0);
                                    gcp.mPixel.mY = floor((rows.size() - 1.0) / 2.0);
                                 }

                                 gcps.push_back(gcp);
                              }
                              else if (pChild->mTag.empty() == false)
                              {
                                 pMetadata->setAttribute(pChild->mTag, pChild->mValue);
                              }
                           }
                        }

                        if (pMetadata->getNumAttributes() > 0)
                        {
                           pDescriptor->setMetadata(pMetadata.get());
                        }
                     }
                  }

                  if (gcps.empty())  // not in description, check for geo points keyword
                  {
                     pField = mFields.find("geo points");
                     if (pField != NULL)
                     {
                        vector<double> geoValues;
                        const int expectedNumValues = 16;  // 4 values for each of the 4 corners
                        geoValues.reserve(expectedNumValues);
                        for (unsigned int i = 0; i < pField->mChildren.size(); i++)
                        {
                           vectorFromField(pField->mChildren.at(i), geoValues, "%lf");
                        }

                        if (geoValues.size() == expectedNumValues)
                        {
                           vector<double>::iterator iter = geoValues.begin();
                           GcpPoint gcp;
                           while (iter != geoValues.end())
                           {
                              gcp.mPixel.mX = *iter++ - 1.0;  // adjust ref point for ENVI's use of
                              gcp.mPixel.mY = *iter++ - 1.0;  // upper left corner and one-based first pixel
                              gcp.mCoordinate.mX = *iter++;   // GcpPoint has lat as mX and Lon as mY 
                              gcp.mCoordinate.mY = *iter++;   // geo point field has lat then lon value
                              gcps.push_back(gcp);
                           }
                        }
                     }
                  }

                  // GCPs
                  if (gcps.empty() == false)
                  {
                     pFileDescriptor->setGcps(gcps);
                  }

                  // Header bytes
                  pField = mFields.find("header offset");
                  if (pField != NULL)
                  {
                     int headerBytes = atoi(pField->mValue.c_str());
                     pFileDescriptor->setHeaderBytes(static_cast<unsigned int>(headerBytes));
                  }

                  // Data type
                  pField = mFields.find("data type");
                  if (pField != NULL)
                  {
                     vector<EncodingType> validDataTypes;
                     switch (atoi(pField->mValue.c_str()))
                     {
                        case 1:     // char
                           pDescriptor->setDataType(INT1UBYTE);
                           pFileDescriptor->setBitsPerElement(8);
                           
                           // signed char cannot be represented in ENVI header so use the closest thing
                           validDataTypes.push_back(INT1SBYTE);
                           break;

                        case 2:     // short
                           pDescriptor->setDataType(INT2SBYTES);
                           pFileDescriptor->setBitsPerElement(16);
                           break;

                        case 3:     // int
                           pDescriptor->setDataType(INT4SBYTES);
                           pFileDescriptor->setBitsPerElement(32);
                           break;

                        case 4:     // float
                           pDescriptor->setDataType(FLT4BYTES);
                           pFileDescriptor->setBitsPerElement(32);
                           break;

                        case 5:     // double
                           pDescriptor->setDataType(FLT8BYTES);
                           pFileDescriptor->setBitsPerElement(64);
                           break;

                        case 6:     // float complex
                           pDescriptor->setDataType(FLT8COMPLEX);
                           pFileDescriptor->setBitsPerElement(64);
                           break;

                        case 9:     // double complex
                           // not supported
                           break;

                        case 12:    // unsigned short
                           pDescriptor->setDataType(INT2UBYTES);
                           pFileDescriptor->setBitsPerElement(16);
                           break;

                        case 13:    // unsigned int
                           pDescriptor->setDataType(INT4UBYTES);
                           pFileDescriptor->setBitsPerElement(32);
                           break;

                        case 14:    // 64-bit int
                        case 15:    // unsigned 64-bit int
                           // not supported
                           break;

                        case 99:    // integer complex (recognized only by this application)
                           pDescriptor->setDataType(INT4SCOMPLEX);
                           pFileDescriptor->setBitsPerElement(32);
                           break;

                        default:
                           break;
                     }

                     // Bad values
                     EncodingType dataType = pDescriptor->getDataType();
                     if ((dataType != FLT4BYTES) && (dataType != FLT8COMPLEX) && (dataType != FLT8BYTES))
                     {
                        vector<int> badValues;
                        badValues.push_back(0);

                        pDescriptor->setBadValues(badValues);
                     }

                     validDataTypes.push_back(dataType);
                     pDescriptor->setValidDataTypes(validDataTypes);
                  }

                  // Interleave format
                  pField = mFields.find("interleave");
                  if (pField != NULL)
                  {
                     string interleave = StringUtilities::toLower(pField->mValue);
                     if (interleave == "bip")
                     {
                        pDescriptor->setInterleaveFormat(BIP);
                        pFileDescriptor->setInterleaveFormat(BIP);
                     }
                     else if (interleave == "bil")
                     {
                        pDescriptor->setInterleaveFormat(BIL);
                        pFileDescriptor->setInterleaveFormat(BIL);
                     }
                     else if (interleave == "bsq")
                     {
                        pDescriptor->setInterleaveFormat(BSQ);
                        pFileDescriptor->setInterleaveFormat(BSQ);
                     }
                  }

                  // Endian
                  pField = mFields.find("byte order");
                  if (pField != NULL)
                  {
                     int byteOrder = atoi(pField->mValue.c_str());
                     if (byteOrder == 0)
                     {
                        pFileDescriptor->setEndian(LITTLE_ENDIAN_ORDER);
                     }
                     else if (byteOrder == 1)
                     {
                        pFileDescriptor->setEndian(BIG_ENDIAN_ORDER);
                     }
                  }

                  // check for scaling factor
                  pField = mFields.find("reflectance scale factor");
                  if (pField != NULL)
                  {
                     double scalingFactor = 0.0;
                     stringstream scaleStream(pField->mValue);
                     scaleStream >> scalingFactor;
                     if (!scaleStream.fail() && scalingFactor != 0.0)
                     {
                        Units* pUnits = pDescriptor->getUnits();
                        if (pUnits != NULL)
                        {
                           pUnits->setScaleFromStandard(1.0 / scalingFactor);
                           pUnits->setUnitName("Reflectance");
                           pUnits->setUnitType(REFLECTANCE);
                        }
                     }
                  }

                  // Pixel size
                  pField = mFields.find("pixel size");
                  if (pField != NULL)
                  {
                     if (pField->mChildren.size() == 2)
                     {
                        pField = pField->mChildren[0];
                        if (pField != NULL)
                        {
                           double pixelSize = 1.0;
                           if (sscanf(pField->mValue.c_str(), "%g", &pixelSize) == 1)
                           {
                              pDescriptor->setXPixelSize(pixelSize);
                              pFileDescriptor->setXPixelSize(pixelSize);
                           }
                        }

                        pField = pField->mChildren[1];
                        if (pField != NULL)
                        {
                           double pixelSize = 1.0;
                           if (sscanf(pField->mValue.c_str(), "%g", &pixelSize) == 1)
                           {
                              pDescriptor->setYPixelSize(pixelSize);
                              pFileDescriptor->setYPixelSize(pixelSize);
                           }
                        }
                     }
                  }

                  // Default bands
                  pField = mFields.find("default bands");
                  if (pField != NULL)
                  {
                     vector<unsigned int> displayBands;
                     parseDefaultBands(pField, &displayBands);

                     if (displayBands.size() == 1)
                     {
                        DimensionDescriptor grayBand = pFileDescriptor->getOriginalBand(displayBands[0]);

                        pDescriptor->setDisplayBand(GRAY, grayBand);
                        pDescriptor->setDisplayMode(GRAYSCALE_MODE);
                     }
                     else if (displayBands.size() == 3)
                     {
                        DimensionDescriptor redBand = pFileDescriptor->getOriginalBand(displayBands[0]);
                        DimensionDescriptor greenBand = pFileDescriptor->getOriginalBand(displayBands[1]);
                        DimensionDescriptor blueBand = pFileDescriptor->getOriginalBand(displayBands[2]);

                        pDescriptor->setDisplayBand(RED, redBand);
                        pDescriptor->setDisplayBand(GREEN, greenBand);
                        pDescriptor->setDisplayBand(BLUE, blueBand);
                        pDescriptor->setDisplayMode(RGB_MODE);
                     }
                  }

                  // Bad bands
                  pField = mFields.find("bbl");
                  if (pField != NULL)
                  {
                     vector<unsigned int> validBands;
                     parseBbl(pField, validBands);

                     vector<DimensionDescriptor> bandsToLoad;
                     for (vector<unsigned int>::const_iterator iter = validBands.begin();
                        iter != validBands.end();
                        ++iter)
                     {
                        const unsigned int onDiskNumber = *iter;
                        const DimensionDescriptor dim = pFileDescriptor->getOnDiskBand(onDiskNumber);
                        if (dim.isValid())
                        {
                           bandsToLoad.push_back(dim);
                        }
                     }

                     pDescriptor->setBands(bandsToLoad);
                  }

                  DynamicObject* pMetadata = pDescriptor->getMetadata();

                  // Band names
                  pField = mFields.find("band names");
                  if (pField != NULL)
                  {
                     vector<string> bandNames;
                     bandNames.reserve(bands.size());
                     vector<string> strNames;
                     for (vector<EnviField*>::size_type i = 0; i < pField->mChildren.size(); ++i)
                     {
                        strNames = StringUtilities::split(pField->mChildren[i]->mValue, ',');
                        copy(strNames.begin(), strNames.end(), back_inserter(bandNames));
                     }
                     vector<string>::iterator it;
                     for (it = bandNames.begin(); it != bandNames.end(); ++it)
                     {
                        *it = StringUtilities::stripWhitespace(*it);
                     }

                     if (pMetadata != NULL)
                     {
                        string pNamesPath[] = { SPECIAL_METADATA_NAME, BAND_METADATA_NAME,
                           NAMES_METADATA_NAME, END_METADATA_NAME };
                        pMetadata->setAttributeByPath(pNamesPath, bandNames);
                     }
                  }

                  // wavelength units
                  pField = mFields.find("wavelength units");
                  if (pField != NULL)
                  {
                     mWavelengthUnits = strToType(pField->mValue);
                  }

                  // Wavelengths
                  vector<double> centerWavelengths;
                  pField = mFields.find("wavelength");
                  if (pField != NULL)
                  {
                     if ((parseWavelengths(pField, &centerWavelengths) == true) && (pMetadata != NULL))
                     {
                        string pCenterPath[] = { SPECIAL_METADATA_NAME, BAND_METADATA_NAME,
                           CENTER_WAVELENGTHS_METADATA_NAME, END_METADATA_NAME };
                        pMetadata->setAttributeByPath(pCenterPath, centerWavelengths);
                     }
                  }

                  // FWHM
                  pField = mFields.find("fwhm");
                  if (pField != NULL)
                  {
                     vector<double> startWavelengths;
                     vector<double> endWavelengths;

                     if ((parseFwhm(pField, &startWavelengths, &centerWavelengths, &endWavelengths) == true) &&
                        (pMetadata != NULL))
                     {
                        string pStartPath[] = { SPECIAL_METADATA_NAME, BAND_METADATA_NAME,
                           START_WAVELENGTHS_METADATA_NAME, END_METADATA_NAME };
                        pMetadata->setAttributeByPath(pStartPath, startWavelengths);
                        string pEndPath[] = { SPECIAL_METADATA_NAME, BAND_METADATA_NAME,
                           END_WAVELENGTHS_METADATA_NAME, END_METADATA_NAME };
                        pMetadata->setAttributeByPath(pEndPath, endWavelengths);
                     }
                  }

                  // File descriptor
                  pDescriptor->setFileDescriptor(pFileDescriptor.get());
               }
vector<ImportDescriptor*> SignatureImporter::getImportDescriptors(const string& filename)
{
   vector<ImportDescriptor*> descriptors;
   if (filename.empty())
   {
      return descriptors;
   }

   LargeFileResource pSigFile;
   if (!pSigFile.open(filename, O_RDONLY | O_BINARY, S_IREAD))
   {
      return descriptors;
   }

   // load the data
   FactoryResource<DynamicObject> pMetadata;
   VERIFYRV(pMetadata.get() != NULL, descriptors);

   bool readError = false;
   string line;
   string unitName("Reflectance");
   UnitType unitType(REFLECTANCE);
   double unitScale(1.0);

   // parse the metadata
   for (line = pSigFile.readLine(&readError);
      (readError == false) && (line.find('=') != string::npos);
      line = pSigFile.readLine(&readError))
   {
      vector<string> metadataEntry;

      trim(line);
      split(metadataEntry, line, is_any_of("="));
      if (metadataEntry.size() == 2)
      {
         string key = metadataEntry[0];
         string value = metadataEntry[1];
         trim(key);
         trim(value);
         if (ends_with(key, "Bands") || key == "Pixels")
         {
            pMetadata->setAttribute(key, StringUtilities::fromXmlString<unsigned long>(value));
         }
         else if (key == "UnitName")
         {
            unitName = value;
         }
         else if (key == "UnitType")
         {
            unitType = StringUtilities::fromXmlString<UnitType>(value);
         }
         else if (key == "UnitScale")
         {
            unitScale = StringUtilities::fromXmlString<double>(value);
         }
         else
         {
            pMetadata->setAttribute(key, value);
         }
      }
   }
   if ((readError == true) && (pSigFile.eof() != 1))
   {
      return descriptors;
   }
   // Verify that the next line contains float float pairs
   vector<string> dataEntry;

   trim(line);
   split(dataEntry, line, is_space());
   if (dataEntry.size() != 2)
   {
      return descriptors;
   }
   bool error = false;
   StringUtilities::fromXmlString<float>(dataEntry[0], &error);
   !error && StringUtilities::fromXmlString<float>(dataEntry[1], &error);
   if (error)
   {
      return descriptors;
   }

   string datasetName = dv_cast<string>(pMetadata->getAttribute("Name"), filename);

   ImportDescriptorResource pImportDescriptor(datasetName, "Signature");
   VERIFYRV(pImportDescriptor.get() != NULL, descriptors);
   SignatureDataDescriptor* pDataDescriptor =
      dynamic_cast<SignatureDataDescriptor*>(pImportDescriptor->getDataDescriptor());
   VERIFYRV(pDataDescriptor != NULL, descriptors);

   FactoryResource<SignatureFileDescriptor> pFileDescriptor;
   VERIFYRV(pFileDescriptor.get() != NULL, descriptors);
   pFileDescriptor->setFilename(filename);

   FactoryResource<Units> pReflectanceUnits;
   VERIFYRV(pReflectanceUnits.get() != NULL, descriptors);
   pReflectanceUnits->setUnitName(unitName);
   pReflectanceUnits->setUnitType(unitType);
   if (unitScale != 0.0)
   {
      pReflectanceUnits->setScaleFromStandard(1.0 / unitScale);
   }
   pDataDescriptor->setUnits("Reflectance", pReflectanceUnits.get());
   pFileDescriptor->setUnits("Reflectance", pReflectanceUnits.get());

   pDataDescriptor->setFileDescriptor(pFileDescriptor.get());
   pDataDescriptor->setMetadata(pMetadata.get());
   descriptors.push_back(pImportDescriptor.release());
   return descriptors;
}