Esempio n. 1
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*> LandsatEtmPlusImporter::getImportDescriptors(const string& filename)
{
   vector<ImportDescriptor*> descriptors;
   if (filename.empty())
   {
      return descriptors;
   }
   if (!readHeader(filename))
   {
      return descriptors;
   }

   string lowGainDatasetName = filename + " Low Gain";
   string highGainDatasetName = filename + " High Gain";
   string panDatasetName = filename + " Panchromatic";

   if (!mFieldHRF.empty() && !mFieldHTM.empty())
   {
      // low gain
      RasterDataDescriptor* pDescriptor = RasterUtilities::generateRasterDataDescriptor(lowGainDatasetName, NULL,
         mNumRows, mNumCols, 7, BSQ, INT1UBYTE, IN_MEMORY);
      VERIFYRV(pDescriptor != NULL, descriptors);
      pDescriptor->setValidDataTypes(vector<EncodingType>(1, INT1UBYTE));
      ImportDescriptorResource pLowGainImportDescriptor(pDescriptor);
      VERIFYRV(pLowGainImportDescriptor.get() != NULL, descriptors);

      RasterFileDescriptor* pFileDescriptor = static_cast<RasterFileDescriptor*>(
         RasterUtilities::generateAndSetFileDescriptor(pDescriptor, filename, "L", LITTLE_ENDIAN_ORDER));
      VERIFYRV(pFileDescriptor != NULL, descriptors);
      vector<int> badValues;
      badValues.push_back(0);
      pDescriptor->setBadValues(badValues);
      pFileDescriptor->setBandFiles(getBandFilenames(filename, LOW_GAIN));

      DynamicObject* pMetadata = pDescriptor->getMetadata();
      populateMetaData(pMetadata, pFileDescriptor, LOW_GAIN);

      pDescriptor->setDisplayMode(RGB_MODE);
      pDescriptor->setDisplayBand(GRAY, pDescriptor->getOriginalBand(0));
      pDescriptor->setDisplayBand(RED, pDescriptor->getOriginalBand(3));
      pDescriptor->setDisplayBand(GREEN, pDescriptor->getOriginalBand(2));
      pDescriptor->setDisplayBand(BLUE, pDescriptor->getOriginalBand(1));
      pDescriptor->getUnits()->setUnitType(DIGITAL_NO);

      descriptors.push_back(pLowGainImportDescriptor.release());

      // high gain
      pDescriptor = static_cast<RasterDataDescriptor*>(pDescriptor->copy(highGainDatasetName, NULL));
      VERIFYRV(pDescriptor != NULL, descriptors);
      ImportDescriptorResource pHighGainImportDescriptor(pDescriptor);
      VERIFYRV(pHighGainImportDescriptor.get() != NULL, descriptors);
      pHighGainImportDescriptor->setImported(false);
      pFileDescriptor = static_cast<RasterFileDescriptor*>(
         RasterUtilities::generateAndSetFileDescriptor(pDescriptor, filename, "H", LITTLE_ENDIAN_ORDER));
      VERIFYRV(pFileDescriptor != NULL, descriptors);
      pFileDescriptor->setBandFiles(getBandFilenames(filename, HIGH_GAIN));
      pMetadata = pDescriptor->getMetadata();
      populateMetaData(pMetadata, pFileDescriptor, HIGH_GAIN);

      descriptors.push_back(pHighGainImportDescriptor.release());
   }

   if (!mFieldHPN.empty())
   {
      // panchromatic
      RasterDataDescriptor* pDescriptor = RasterUtilities::generateRasterDataDescriptor(panDatasetName, NULL,
         mB8Rows, mB8Cols, 1, BSQ, INT1UBYTE, IN_MEMORY);
      VERIFYRV(pDescriptor != NULL, descriptors);
      pDescriptor->setValidDataTypes(vector<EncodingType>(1, INT1UBYTE));
      ImportDescriptorResource pPanImportDescriptor(pDescriptor);
      VERIFYRV(pPanImportDescriptor.get() != NULL, descriptors);
      pPanImportDescriptor->setImported(false);

      RasterFileDescriptor* pFileDescriptor = static_cast<RasterFileDescriptor*>(
         RasterUtilities::generateAndSetFileDescriptor(pDescriptor, filename, "Pan", LITTLE_ENDIAN_ORDER));
      VERIFYRV(pFileDescriptor != NULL, descriptors);
      vector<int> badValues;
      badValues.push_back(0);
      pDescriptor->setBadValues(badValues);
      pFileDescriptor->setBandFiles(getBandFilenames(filename, PANCHROMATIC));
      DynamicObject* pMetadata = pDescriptor->getMetadata();
      populateMetaData(pMetadata, pFileDescriptor, PANCHROMATIC);

      pDescriptor->setDisplayMode(GRAYSCALE_MODE);
      pDescriptor->setDisplayBand(GRAY, pDescriptor->getOriginalBand(0));
      pDescriptor->getUnits()->setUnitType(DIGITAL_NO);

      descriptors.push_back(pPanImportDescriptor.release());
   }

   return descriptors;
}
Esempio n. 3
0
bool EditDataDescriptor::execute(PlugInArgList* pInArgList, PlugInArgList* pOutArgList)
{
   StepResource pStep("Execute Wizard Item", "app", "055486F4-A9DB-4FDA-9AA7-75D1917E2C87");
   pStep->addProperty("Item", getName());
   mpStep = pStep.get();

   if (extractInputArgs(pInArgList) == false)
   {
      return false;
   }

   // Set the values in the data descriptor
   VERIFY(mpDescriptor != NULL);

   // File descriptor
   if (mpFileDescriptor != NULL)
   {
      mpDescriptor->setFileDescriptor(mpFileDescriptor);
   }

   // Processing location
   if (mpProcessingLocation != NULL)
   {
      mpDescriptor->setProcessingLocation(*mpProcessingLocation);
   }

   RasterDataDescriptor* pRasterDescriptor = dynamic_cast<RasterDataDescriptor*>(mpDescriptor);
   RasterFileDescriptor* pRasterFileDescriptor = dynamic_cast<RasterFileDescriptor*>(mpFileDescriptor);
   SignatureDataDescriptor* pSignatureDescriptor = dynamic_cast<SignatureDataDescriptor*>(mpDescriptor);
   SignatureFileDescriptor* pSignatureFileDescriptor = dynamic_cast<SignatureFileDescriptor*>(mpFileDescriptor);

   if (pRasterDescriptor != NULL)
   {
      if (pRasterFileDescriptor != NULL)
      {
         // Set the rows and columns to match the rows and columns in the file descriptor before creating the subset
         const vector<DimensionDescriptor>& rows = pRasterFileDescriptor->getRows();
         pRasterDescriptor->setRows(rows);

         const vector<DimensionDescriptor>& columns = pRasterFileDescriptor->getColumns();
         pRasterDescriptor->setColumns(columns);

         const vector<DimensionDescriptor>& bands = pRasterFileDescriptor->getBands();
         pRasterDescriptor->setBands(bands);
      }

      // Data type
      if (mpDataType != NULL)
      {
         pRasterDescriptor->setDataType(*mpDataType);
      }

      // InterleaveFormat
      if (mpInterleave != NULL)
      {
         pRasterDescriptor->setInterleaveFormat(*mpInterleave);
      }

      // Bad values
      if (mpBadValues != NULL)
      {
         pRasterDescriptor->setBadValues(*mpBadValues);
      }

      // Rows
      if ((mpStartRow != NULL) || (mpEndRow != NULL) || (mpRowSkipFactor != NULL))
      {
         // We need to obtain this origRows from the FileDescriptor if present since an importer
         // may generate a subset by default in which case the DataDescriptor will not contain all
         // the rows and subsetting will not work correctly. We
         // can't just set mpFileDescriptor = pRasterDescriptor->getFileDescriptor() since we only
         // want to replace the DataDescriptor's row list if one of the subset options is specified
         const RasterFileDescriptor* pFileDesc(pRasterFileDescriptor);
         if (pFileDesc == NULL)
         {
            pFileDesc = dynamic_cast<const RasterFileDescriptor*>(pRasterDescriptor->getFileDescriptor());
         }
         const vector<DimensionDescriptor>& origRows = (pFileDesc != NULL) ?
            pFileDesc->getRows() : pRasterDescriptor->getRows();
         unsigned int startRow = 0;
         if (mpStartRow != NULL)
         {
            startRow = *mpStartRow;
         }
         else if (origRows.empty() == false)
         {
            startRow = origRows.front().getOriginalNumber() + 1;
         }

         unsigned int endRow = 0;
         if (mpEndRow != NULL)
         {
            endRow = *mpEndRow;
         }
         else if (origRows.empty() == false)
         {
            endRow = origRows.back().getOriginalNumber() + 1;
         }

         unsigned int rowSkip = 0;
         if (mpRowSkipFactor != NULL)
         {
            rowSkip = *mpRowSkipFactor;
         }

         vector<DimensionDescriptor> rows;
         for (unsigned int i = 0; i < origRows.size(); ++i)
         {
            DimensionDescriptor rowDim = origRows[i];
            unsigned int originalNumber = rowDim.getOriginalNumber() + 1;
            if ((originalNumber >= startRow) && (originalNumber <= endRow))
            {
               rows.push_back(rowDim);
               i += rowSkip;
            }
         }

         pRasterDescriptor->setRows(rows);
      }

      // Columns
      if ((mpStartColumn != NULL) || (mpEndColumn != NULL) || (mpColumnSkipFactor != NULL))
      {
         // We need to obtain this origColumns from the FileDescriptor if present since an importer
         // may generate a subset by default in which case the DataDescriptor will not contain all
         // the columns and subsetting will not work correctly. We
         // can't just set mpFileDescriptor = pRasterDescriptor->getFileDescriptor() since we only
         // want to replace the DataDescriptor's column list if one of the subset options is specified
         const RasterFileDescriptor* pFileDesc(pRasterFileDescriptor);
         if (pFileDesc == NULL)
         {
            pFileDesc = dynamic_cast<const RasterFileDescriptor*>(pRasterDescriptor->getFileDescriptor());
         }
         const vector<DimensionDescriptor>& origColumns = (pFileDesc != NULL) ?
            pFileDesc->getColumns() : pRasterDescriptor->getColumns();

         unsigned int startColumn = 0;
         if (mpStartColumn != NULL)
         {
            startColumn = *mpStartColumn;
         }
         else if (origColumns.empty() == false)
         {
            startColumn = origColumns.front().getOriginalNumber() + 1;
         }

         unsigned int endColumn = 0;
         if (mpEndColumn != NULL)
         {
            endColumn = *mpEndColumn;
         }
         else if (origColumns.empty() == false)
         {
            endColumn = origColumns.back().getOriginalNumber() + 1;
         }

         unsigned int columnSkip = 0;
         if (mpColumnSkipFactor != NULL)
         {
            columnSkip = *mpColumnSkipFactor;
         }

         vector<DimensionDescriptor> columns;
         for (unsigned int i = 0; i < origColumns.size(); ++i)
         {
            DimensionDescriptor columnDim = origColumns[i];
            unsigned int originalNumber = columnDim.getOriginalNumber() + 1;
            if ((originalNumber >= startColumn) && (originalNumber <= endColumn))
            {
               columns.push_back(columnDim);
               i += columnSkip;
            }
         }

         pRasterDescriptor->setColumns(columns);
      }

      // Bands
      if ((mpStartBand != NULL) || (mpEndBand != NULL) || (mpBandSkipFactor != NULL) || (mpBadBandsFile != NULL))
      {
         // We need to obtain this origBands from the FileDescriptor if present since an importer
         // may generate a subset by default in which case the DataDescriptor will not contain all
         // the bands and subsetting (especially by bad band file) will not work correctly. We
         // can't just set mpFileDescriptor = pRasterDescriptor->getFileDescriptor() since we only
         // want to replace the DataDescriptor's band list if one of the subset options is specified
         const RasterFileDescriptor* pFileDesc(pRasterFileDescriptor);
         if (pFileDesc == NULL)
         {
            pFileDesc = dynamic_cast<const RasterFileDescriptor*>(pRasterDescriptor->getFileDescriptor());
         }
         const vector<DimensionDescriptor>& origBands = (pFileDesc != NULL) ?
            pFileDesc->getBands() : pRasterDescriptor->getBands();

         unsigned int startBand = 0;
         if (mpStartBand != NULL)
         {
            startBand = *mpStartBand;
         }
         else if (origBands.empty() == false)
         {
            startBand = origBands.front().getOriginalNumber() + 1;
         }

         unsigned int endBand = 0;
         if (mpEndBand != NULL)
         {
            endBand = *mpEndBand;
         }
         else if (origBands.empty() == false)
         {
            endBand = origBands.back().getOriginalNumber() + 1;
         }

         unsigned int bandSkip = 0;
         if (mpBandSkipFactor != NULL)
         {
            bandSkip = *mpBandSkipFactor;
         }

         // Get the bad bands from the file
         vector<unsigned int> badBands;
         if (mpBadBandsFile != NULL)
         {
            string filename = *mpBadBandsFile;
            if (filename.empty() == false)
            {
               FILE* pFile = fopen(filename.c_str(), "rb");
               if (pFile != NULL)
               {
                  char line[1024];
                  while (fgets(line, 1024, pFile) != NULL)
                  {
                     unsigned int bandNumber = 0;

                     int iValues = sscanf(line, "%u", &bandNumber);
                     if (iValues == 1)
                     {
                        badBands.push_back(bandNumber);
                     }
                  }

                  fclose(pFile);
               }
            }
         }

         vector<DimensionDescriptor> bands;
         for (unsigned int i = 0; i < origBands.size(); ++i)
         {
            DimensionDescriptor bandDim = origBands[i];
            unsigned int originalNumber = bandDim.getOriginalNumber() + 1;
            if ((originalNumber >= startBand) && (originalNumber <= endBand))
            {
               bool bBad = false;
               for (unsigned int j = 0; j < badBands.size(); ++j)
               {
                  unsigned int badBandNumber = badBands[j];
                  if (originalNumber == badBandNumber)
                  {
                     bBad = true;
                     break;
                  }
               }

               if (bBad == false)
               {
                  bands.push_back(bandDim);
                  i += bandSkip;
               }
            }
         }

         pRasterDescriptor->setBands(bands);
      }

      // X pixel size
      if (mpPixelSizeX != NULL)
      {
         pRasterDescriptor->setXPixelSize(*mpPixelSizeX);
      }

      // Y pixel size
      if (mpPixelSizeY != NULL)
      {
         pRasterDescriptor->setYPixelSize(*mpPixelSizeY);
      }

      // Units
      if ((mpUnitsName != NULL) || (mpUnitsType != NULL) ||
         (mpUnitsScale != NULL) || (mpUnitsRangeMin != NULL) || (mpUnitsRangeMax != NULL))
      {
         const Units* pOrigUnits = pRasterDescriptor->getUnits();

         FactoryResource<Units> pUnits;
         VERIFY(pUnits.get() != NULL);

         // Name
         if (mpUnitsName != NULL)
         {
            pUnits->setUnitName(*mpUnitsName);
         }
         else if (pOrigUnits != NULL)
         {
            pUnits->setUnitName(pOrigUnits->getUnitName());
         }

         // Type
         if (mpUnitsType != NULL)
         {
            pUnits->setUnitType(*mpUnitsType);
         }
         else if (pOrigUnits != NULL)
         {
            pUnits->setUnitType(pOrigUnits->getUnitType());
         }

         // Scale
         if (mpUnitsScale != NULL)
         {
            pUnits->setScaleFromStandard(*mpUnitsScale);
         }
         else if (pOrigUnits != NULL)
         {
            pUnits->setScaleFromStandard(pOrigUnits->getScaleFromStandard());
         }

         // Range minimum
         if (mpUnitsRangeMin != NULL)
         {
            pUnits->setRangeMin(*mpUnitsRangeMin);
         }
         else if (pOrigUnits != NULL)
         {
            pUnits->setRangeMin(pOrigUnits->getRangeMin());
         }

         // Range maximum
         if (mpUnitsRangeMax != NULL)
         {
            pUnits->setRangeMax(*mpUnitsRangeMax);
         }
         else if (pOrigUnits != NULL)
         {
            pUnits->setRangeMax(pOrigUnits->getRangeMax());
         }

         pRasterDescriptor->setUnits(pUnits.get());
      }

      // Display mode
      if (mpDisplayMode != NULL)
      {
         pRasterDescriptor->setDisplayMode(*mpDisplayMode);
      }

      // Display bands
      // Gray
      if (mpGrayBand != NULL)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(*mpGrayBand - 1);
         pRasterDescriptor->setDisplayBand(GRAY, band);
      }

      // Red
      if (mpRedBand != NULL)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(*mpRedBand - 1);
         pRasterDescriptor->setDisplayBand(RED, band);
      }

      // Green
      if (mpGreenBand != NULL)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(*mpGreenBand - 1);
         pRasterDescriptor->setDisplayBand(GREEN, band);
      }

      // Blue
      if (mpBlueBand != NULL)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(*mpBlueBand - 1);
         pRasterDescriptor->setDisplayBand(BLUE, band);
      }
   }
   else if (pSignatureDescriptor != NULL)
   {
      if (mpComponentName != NULL)
      {
         const Units* pOrigUnits = pSignatureDescriptor->getUnits(*mpComponentName);
         FactoryResource<Units> pUnits;
         if (pOrigUnits != NULL)
         {
            *pUnits = *pOrigUnits;
         }
         if (mpUnitsName != NULL)
         {
            pUnits->setUnitName(*mpUnitsName);
         }
         if (mpUnitsType != NULL)
         {
            pUnits->setUnitType(*mpUnitsType);
         }
         if (mpUnitsScale != NULL)
         {
            pUnits->setScaleFromStandard(*mpUnitsScale);
         }
         if (mpUnitsRangeMin != NULL)
         {
            pUnits->setRangeMin(*mpUnitsRangeMin);
         }
         if (mpUnitsRangeMax != NULL)
         {
            pUnits->setRangeMax(*mpUnitsRangeMax);
         }
         pSignatureDescriptor->setUnits(*mpComponentName, pUnits.get());
      }
   }

   reportComplete();
   return true;
}