Example #1
0
bool ThresholdData::execute(PlugInArgList* pInArgList, PlugInArgList* pOutArgList)
{
   VERIFY(pInArgList != NULL);
   StepResource pStep("Execute Wizard Item", "app", "{2501975d-7cd5-49b0-a3e7-49f7106793c0}");
   pStep->addProperty("Item", getName());
   mpStep = pStep.get();

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

   const RasterDataDescriptor* pDesc = static_cast<const RasterDataDescriptor*>(mpInputElement->getDataDescriptor());
   VERIFY(pDesc);
   DimensionDescriptor band;
   if (mDisplayBandNumber > 0)
   {
      band = pDesc->getOriginalBand(mDisplayBandNumber - 1);
      if (band.isValid() == false)
      {
         reportError("The specified band is invalid.", "{a529538b-5b82-425d-af10-385a2581beec}");
         return false;
      }
   }
   else
   {
      band = pDesc->getActiveBand(mDisplayBandNumber);
   }
   FactoryResource<DataRequest> pReq;
   pReq->setInterleaveFormat(BSQ);
   pReq->setBands(band, band, 1);
   DataAccessor acc = mpInputElement->getDataAccessor(pReq.release());
   if (!acc.isValid())
   {
      reportError("Unable to access data element.", "{b5f1b7dd-7cf7-4cd5-b5bc-7b747d3561b9}");
      return false;
   }

   // If necessary, convert region units
   if (mRegionUnits != RAW_VALUE)
   {
      Statistics* pStatistics = mpInputElement->getStatistics(band);
      if (pStatistics == NULL)
      {
         reportError("Unable to calculate data statistics.", "{61a44ced-a4aa-4423-b379-5783137eb980}");
         return false;
      }
      mFirstThreshold = convertToRawUnits(pStatistics, mRegionUnits, mFirstThreshold);
      mSecondThreshold = convertToRawUnits(pStatistics, mRegionUnits, mSecondThreshold);
   }
   FactoryResource<BitMask> pBitmask;
   for (unsigned int row = 0; row < pDesc->getRowCount(); ++row)
   {
      reportProgress("Thresholding data", 100 * row / pDesc->getRowCount(),
         "{2fc3dbea-1307-471c-bba2-bf86032be518}");
      for (unsigned int col = 0; col < pDesc->getColumnCount(); ++col)
      {
         VERIFY(acc.isValid());
         double val = ModelServices::getDataValue(pDesc->getDataType(), acc->getColumn(), 0);
         switch (mPassArea)
         {
         case UPPER:
            if (val >= mFirstThreshold)
            {
               pBitmask->setPixel(col, row, true);
            }
            break;
         case LOWER:
            if (val <= mFirstThreshold)
            {
               pBitmask->setPixel(col, row, true);
            }
            break;
         case MIDDLE:
            if (val >= mFirstThreshold && val <= mSecondThreshold)
            {
               pBitmask->setPixel(col, row, true);
            }
            break;
         case OUTSIDE:
            if (val <= mFirstThreshold || val >= mSecondThreshold)
            {
               pBitmask->setPixel(col, row, true);
            }
            break;
         default:
            reportError("Unknown or invalid pass area.", "{19c92b3b-52e9-442b-a01f-b545f819f200}");
            return false;
         }
         acc->nextColumn();
      }
      acc->nextRow();
   }
   std::string aoiName = pDesc->getName() + "_aoi";
   ModelResource<AoiElement> pAoi(aoiName, mpInputElement);
   if (pAoi.get() == NULL)
   {
      reportWarning("Overwriting existing AOI.", "{d953a030-dd63-43a1-98db-b0f491dee123}");
      Service<ModelServices>()->destroyElement(
         Service<ModelServices>()->getElement(aoiName, TypeConverter::toString<AoiElement>(), mpInputElement));
      pAoi = ModelResource<AoiElement>(aoiName, mpInputElement);
   }
   if (pAoi.get() == NULL)
   {
      reportError("Unable to create output AOI.", "{f76c2f4d-9a7f-4055-9383-022116cdcadb}");
      return false;
   }
   pAoi->addPoints(pBitmask.get());
   AoiLayer* pLayer = NULL;
   if (mpView != NULL)
   {
      if ((pLayer = static_cast<AoiLayer*>(mpView->createLayer(AOI_LAYER, pAoi.get()))) == NULL)
      {
         reportWarning("Unable to create AOI layer, continuing thresholding.",
            "{5eca6ea0-33c1-4b1a-b777-c8e1b86fd2fb}");
      }
   }
   if (pOutArgList != NULL)
   {
      pOutArgList->setPlugInArgValue("Result", pAoi.get());
      if (pLayer != NULL)
      {
         pOutArgList->setPlugInArgValue("Result Layer", pLayer);
      }
   }
   pAoi.release();

   reportComplete();
   return true;
}
Example #2
0
void ChippingWindow::createView()
{
   if (mpChippingWidget == NULL)
   {
      return;
   }

   RasterElement* pRaster = getRasterElement();
   if (pRaster == NULL)
   {
      return;
   }

   // Create the new raster element from the primary element of the source.
   // Note that this does not chip displayed elements if they differ from the primary element.
   // This causes a special case below where the stretch values are being applied to the chipped layer.
   RasterElement* pRasterChip = pRaster->createChip(pRaster->getParent(), "_chip",
      mpChippingWidget->getChipRows(), mpChippingWidget->getChipColumns(), mpChippingWidget->getChipBands());
   if (pRasterChip == NULL)
   {
      QMessageBox::critical(this, windowTitle(), "Unable to create a new cube!");
      return;
   }

   const RasterDataDescriptor* pDescriptor =
      dynamic_cast<const RasterDataDescriptor*>(pRasterChip->getDataDescriptor());
   VERIFYNRV(pDescriptor != NULL);

   // Create a view for the new chip
   SpatialDataWindow* pWindow = dynamic_cast<SpatialDataWindow*>(
      Service<DesktopServices>()->createWindow(pRasterChip->getName(), SPATIAL_DATA_WINDOW));
   if (pWindow == NULL)
   {
      return;
   }

   SpatialDataView* pView = pWindow->getSpatialDataView();
   if (pView == NULL)
   {
      Service<DesktopServices>()->deleteWindow(pWindow);
      return;
   }

   UndoLock lock(pView);
   if (pView->setPrimaryRasterElement(pRasterChip) == false)
   {
      Service<DesktopServices>()->deleteWindow(pWindow);
      return;
   }

   // RasterLayerImp is needed for the call to setCurrentStretchAsOriginalStretch().
   RasterLayerImp* pLayer = dynamic_cast<RasterLayerImp*>(pView->createLayer(RASTER, pRasterChip));
   if (pLayer == NULL)
   {
      Service<DesktopServices>()->deleteWindow(pWindow);
      return;
   }

   string origName = pRaster->getName();

   SpatialDataWindow* pOrigWindow = dynamic_cast<SpatialDataWindow*>(
      Service<DesktopServices>()->getWindow(origName, SPATIAL_DATA_WINDOW));
   if (pOrigWindow != NULL)
   {
      SpatialDataView* pOrigView = pOrigWindow->getSpatialDataView();
      if (pOrigView != NULL)
      {
         LayerList* pLayerList = pOrigView->getLayerList();
         if (pLayerList != NULL)
         {
            RasterLayer* pOrigLayer = static_cast<RasterLayer*>(pLayerList->getLayer(RASTER, pRaster));
            if (pOrigLayer != NULL)
            {
               // Set the stretch type first so that stretch values are interpreted correctly.
               pLayer->setStretchType(GRAYSCALE_MODE, pOrigLayer->getStretchType(GRAYSCALE_MODE));
               pLayer->setStretchType(RGB_MODE, pOrigLayer->getStretchType(RGB_MODE));
               pLayer->setDisplayMode(pOrigLayer->getDisplayMode());

               // Set the properties of the cube layer in the new view.
               // For each channel, display the first band if the previously displayed band was chipped.
               vector<RasterChannelType> channels = StringUtilities::getAllEnumValues<RasterChannelType>();
               for (vector<RasterChannelType>::const_iterator iter = channels.begin(); iter != channels.end(); ++iter)
               {
                  bool bandCopied = true;
                  DimensionDescriptor newBand;
                  DimensionDescriptor oldBand = pOrigLayer->getDisplayedBand(*iter);
                  if (oldBand.isOriginalNumberValid() == true)
                  {
                     newBand = pDescriptor->getOriginalBand(oldBand.getOriginalNumber());
                  }

                  if (newBand.isValid() == false)
                  {
                     bandCopied = false;
                     newBand = pDescriptor->getBands().front();
                  }

                  // No need to explicitly set the RasterElement here since the new view only has one RasterElement.
                  pLayer->setDisplayedBand(*iter, newBand);

                  // Use the default stretch properties if the displayed band was removed from the view or
                  // if the non-primary raster element was displayed. Otherwise, copy the stretch properties.
                  if (bandCopied && pRaster == pOrigLayer->getDisplayedRasterElement(*iter))
                  {
                     // Set the stretch units first so that stretch values are interpreted correctly.
                     pLayer->setStretchUnits(*iter, pOrigLayer->getStretchUnits(*iter));

                     double lower;
                     double upper;
                     pOrigLayer->getStretchValues(*iter, lower, upper);
                     pLayer->setStretchValues(*iter, lower, upper);
                  }
               }

               pLayer->setCurrentStretchAsOriginalStretch();
               pView->refresh();
            }
         }
      }
   }

   // Create a GCP layer
   if (pRaster->isGeoreferenced() == true)
   {
      const vector<DimensionDescriptor>& rows = mpChippingWidget->getChipRows();
      const vector<DimensionDescriptor>& columns = mpChippingWidget->getChipColumns();
      if ((rows.empty() == false) && (columns.empty() == false))
      {
         // Get the geocoordinates at the chip corners
         VERIFYNRV(rows.front().isActiveNumberValid() == true);
         VERIFYNRV(rows.back().isActiveNumberValid() == true);
         VERIFYNRV(columns.front().isActiveNumberValid() == true);
         VERIFYNRV(columns.back().isActiveNumberValid() == true);

         unsigned int startRow = rows.front().getActiveNumber();
         unsigned int endRow = rows.back().getActiveNumber();
         unsigned int startCol = columns.front().getActiveNumber();
         unsigned int endCol = columns.back().getActiveNumber();

         GcpPoint ulPoint;
         ulPoint.mPixel = LocationType(startCol, startRow);
         ulPoint.mCoordinate = pRaster->convertPixelToGeocoord(ulPoint.mPixel);

         GcpPoint urPoint;
         urPoint.mPixel = LocationType(endCol, startRow);
         urPoint.mCoordinate = pRaster->convertPixelToGeocoord(urPoint.mPixel);

         GcpPoint llPoint;
         llPoint.mPixel = LocationType(startCol, endRow);
         llPoint.mCoordinate = pRaster->convertPixelToGeocoord(llPoint.mPixel);

         GcpPoint lrPoint;
         lrPoint.mPixel = LocationType(endCol, endRow);
         lrPoint.mCoordinate = pRaster->convertPixelToGeocoord(lrPoint.mPixel);

         GcpPoint centerPoint;
         centerPoint.mPixel = LocationType((startCol + endCol) / 2, (startRow + endRow) / 2);
         centerPoint.mCoordinate = pRaster->convertPixelToGeocoord(centerPoint.mPixel);

         // Reset the coordinates to be in active numbers relative to the chip
         const vector<DimensionDescriptor>& chipRows = pDescriptor->getRows();
         const vector<DimensionDescriptor>& chipColumns = pDescriptor->getColumns();

         VERIFYNRV(chipRows.front().isActiveNumberValid() == true);
         VERIFYNRV(chipRows.back().isActiveNumberValid() == true);
         VERIFYNRV(chipColumns.front().isActiveNumberValid() == true);
         VERIFYNRV(chipColumns.back().isActiveNumberValid() == true);

         unsigned int chipStartRow = chipRows.front().getActiveNumber();
         unsigned int chipEndRow = chipRows.back().getActiveNumber();
         unsigned int chipStartCol = chipColumns.front().getActiveNumber();
         unsigned int chipEndCol = chipColumns.back().getActiveNumber();
         ulPoint.mPixel = LocationType(chipStartCol, chipStartRow);
         urPoint.mPixel = LocationType(chipEndCol, chipStartRow);
         llPoint.mPixel = LocationType(chipStartCol, chipEndRow);
         lrPoint.mPixel = LocationType(chipEndCol, chipEndRow);
         centerPoint.mPixel = LocationType((chipStartCol + chipEndCol) / 2, (chipStartRow + chipEndRow) / 2);

         // Create the GCP list
         Service<ModelServices> pModel;

         GcpList* pGcpList = static_cast<GcpList*>(pModel->createElement("Corner Coordinates",
            TypeConverter::toString<GcpList>(), pRasterChip));
         if (pGcpList != NULL)
         {
            list<GcpPoint> gcps;
            gcps.push_back(ulPoint);
            gcps.push_back(urPoint);
            gcps.push_back(llPoint);
            gcps.push_back(lrPoint);
            gcps.push_back(centerPoint);

            pGcpList->addPoints(gcps);

            // Create the layer
            if (pView->createLayer(GCP_LAYER, pGcpList) == NULL)
            {
               QMessageBox::warning(this, windowTitle(), "Could not create a GCP layer.");
            }
         }
         else
         {
            QMessageBox::warning(this, windowTitle(), "Could not create a GCP list.");
         }
      }
   }
}
Example #3
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());
               }
bool RasterElementImporterShell::validate(const DataDescriptor* pDescriptor,
                                          const vector<const DataDescriptor*>& importedDescriptors,
                                          string& errorMessage) const
{
   bool isValid = ImporterShell::validate(pDescriptor, importedDescriptors, errorMessage);
   if (isValid == false)
   {
      ValidationTest errorTest = getValidationError();
      if (errorTest == NO_PRE_POST_BAND_BYTES)
      {
         errorMessage += "  Preband and postband bytes are not supported for interleave formats other than BSQ.";
      }
      else if (errorTest == NO_BAND_FILES)
      {
         errorMessage += "  Bands in multiple files are not supported for interleave formats other than BSQ.";
      }
      else if ((errorTest == NO_INTERLEAVE_CONVERSIONS) || (errorTest == NO_ROW_SKIP_FACTOR) ||
         (errorTest == NO_COLUMN_SKIP_FACTOR) || (errorTest == NO_BAND_SUBSETS))
      {
         errorMessage = errorMessage.substr(0, errorMessage.length() - 1);
         errorMessage += " with on-disk read-only processing.";
      }
   }
   else
   {
      // Check for display bands that are not loaded
      const RasterDataDescriptor* pRasterDescriptor = dynamic_cast<const RasterDataDescriptor*>(pDescriptor);
      VERIFY(pRasterDescriptor != NULL);

      DimensionDescriptor grayBand = pRasterDescriptor->getDisplayBand(GRAY);
      if (grayBand.isOriginalNumberValid() == true)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(grayBand.getOriginalNumber());
         if (band.isValid() == false)
         {
            if (errorMessage.empty() == false)
            {
               errorMessage += "\n";
            }

            errorMessage += "The gray display band is not available.  The first loaded band will be displayed instead.";
         }
      }

      DimensionDescriptor redBand = pRasterDescriptor->getDisplayBand(RED);
      if (redBand.isOriginalNumberValid() == true)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(redBand.getOriginalNumber());
         if (band.isValid() == false)
         {
            if (errorMessage.empty() == false)
            {
               errorMessage += "\n";
            }

            errorMessage += "The red display band is not available.  The first loaded band will be displayed instead.";
         }
      }

      DimensionDescriptor greenBand = pRasterDescriptor->getDisplayBand(GREEN);
      if (greenBand.isOriginalNumberValid() == true)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(greenBand.getOriginalNumber());
         if (band.isValid() == false)
         {
            if (errorMessage.empty() == false)
            {
               errorMessage += "\n";
            }

            errorMessage += "The green display band is not available.  The first loaded band will be "
               "displayed instead.";
         }
      }

      DimensionDescriptor blueBand = pRasterDescriptor->getDisplayBand(BLUE);
      if (blueBand.isOriginalNumberValid() == true)
      {
         DimensionDescriptor band = pRasterDescriptor->getOriginalBand(blueBand.getOriginalNumber());
         if (band.isValid() == false)
         {
            if (errorMessage.empty() == false)
            {
               errorMessage += "\n";
            }

            errorMessage += "The blue display band is not available.  The first loaded band will be displayed instead.";
         }
      }
   }

   return isValid;
}
std::vector<ImportDescriptor*> LandsatGeotiffImporter::createImportDescriptors(const std::string& filename,
   const DynamicObject* pImageMetadata,
   Landsat::LandsatImageType type)
{
   std::string suffix;
   if (type == Landsat::LANDSAT_VNIR)
   {
      suffix = "vnir";
   }
   else if (type == Landsat::LANDSAT_PAN)
   {
      suffix = "pan";
   }
   else if (type == Landsat::LANDSAT_TIR)
   {
      suffix = "tir";
   }
   std::vector<ImportDescriptor*> descriptors;
   std::string spacecraft = dv_cast<std::string>(
      pImageMetadata->getAttributeByPath("LANDSAT_MTL/L1_METADATA_FILE/PRODUCT_METADATA/SPACECRAFT_ID"), "");
   std::vector<std::string> bandNames = Landsat::getSensorBandNames(spacecraft, type);
   if (bandNames.empty())
   {
      //this spacecraft and iamge type
      //isn't meant to have any bands, so terminate early
      //e.g. spacecraft == "Landsat5" && type == Landsat::LANDSAT_PAN
      return descriptors;
   }
   std::vector<unsigned int> validBands;
   std::vector<std::string> bandFiles = Landsat::getGeotiffBandFilenames(
      pImageMetadata, filename, type, validBands);
   if (bandFiles.empty())
   {
      mWarnings.push_back("Unable to locate band files for " + suffix + " product."); 
      return descriptors;
   }
   ImportDescriptorResource pImportDescriptor(filename + "-" + suffix,
      TypeConverter::toString<RasterElement>(), NULL, false);
   if (pImportDescriptor.get() == NULL)
   {
      return descriptors;
   }
   RasterDataDescriptor* pDescriptor = dynamic_cast<RasterDataDescriptor*>(pImportDescriptor->getDataDescriptor());
   if (pDescriptor == NULL)
   {
      return descriptors;
   }
   pDescriptor->setProcessingLocation(ON_DISK);
   DynamicObject* pMetadata = pDescriptor->getMetadata();
   pMetadata->merge(pImageMetadata);
   FactoryResource<RasterFileDescriptor> pFileDescriptorRes;
   pDescriptor->setFileDescriptor(pFileDescriptorRes.get());
   RasterFileDescriptor* pFileDescriptor = dynamic_cast<RasterFileDescriptor*>(pDescriptor->getFileDescriptor());
   pFileDescriptor->setFilename(filename);

   std::string tiffFile = bandFiles[0];
   if (!Landsat::parseBasicsFromTiff(tiffFile, pDescriptor))
   {
      mWarnings.push_back("Unable to parse basic information about image from tiff file for " + suffix + " product.");
      return descriptors;
   }
   if (pDescriptor->getBandCount() != 1 || pDescriptor->getDataType() != INT1UBYTE)
   {
      mWarnings.push_back("Improperly formatted tiff file for " + suffix + " product.");
      return descriptors;
   }
   pDescriptor->setInterleaveFormat(BSQ); //one tiff file per band.
   pFileDescriptor->setInterleaveFormat(BSQ);
   std::vector<DimensionDescriptor> bands = RasterUtilities::generateDimensionVector(
      bandFiles.size(), true, false, true);
   pDescriptor->setBands(bands);
   pFileDescriptor->setBands(bands);
   pDescriptor->setBadValues(std::vector<int>(1, 0));
   pFileDescriptor->setDatasetLocation(suffix);

   //special metadata here
   Landsat::fixMtlMetadata(pMetadata, type, validBands);

   std::vector<std::string> defaultImport = OptionsLandsatImport::getSettingDefaultImport();
   bool fallbackToDn = false;
   descriptors.push_back(pImportDescriptor.release());

   if (type == Landsat::LANDSAT_VNIR)
   {
      //attempt to display true-color
      DimensionDescriptor redBand = RasterUtilities::findBandWavelengthMatch(0.630, 0.690, pDescriptor);
      DimensionDescriptor greenBand = RasterUtilities::findBandWavelengthMatch(0.510, 0.590, pDescriptor);
      DimensionDescriptor blueBand = RasterUtilities::findBandWavelengthMatch(0.410, 0.490, pDescriptor);
      if (redBand.isValid() && greenBand.isValid() && blueBand.isValid())
      {
         pDescriptor->setDisplayMode(RGB_MODE);
         pDescriptor->setDisplayBand(RED, redBand);
         pDescriptor->setDisplayBand(GREEN, greenBand);
         pDescriptor->setDisplayBand(BLUE, blueBand);
      }
   }

   std::vector<std::pair<double, double> > radianceFactors = Landsat::determineRadianceConversionFactors(
      pMetadata, type, validBands);
   bool shouldDefaultImportRadiance =
      std::find(defaultImport.begin(), defaultImport.end(), suffix + "-Radiance") != defaultImport.end();
   if (radianceFactors.size() == bandFiles.size())
   {
      //we have enough to create radiance import descriptor
      RasterDataDescriptor* pRadianceDescriptor = dynamic_cast<RasterDataDescriptor*>(
         pDescriptor->copy(filename + "-" + suffix + "-radiance", NULL));
      if (pRadianceDescriptor != NULL)
      {
         pRadianceDescriptor->setDataType(FLT4BYTES);
         pRadianceDescriptor->setValidDataTypes(std::vector<EncodingType>(1, pRadianceDescriptor->getDataType()));
         pRadianceDescriptor->setBadValues(std::vector<int>(1, -100));
         FactoryResource<Units> pUnits;
         pUnits->setUnitType(RADIANCE);
         pUnits->setUnitName("w/(m^2*sr*um)");
         pUnits->setScaleFromStandard(1.0);
         pRadianceDescriptor->setUnits(pUnits.get());
         FileDescriptor* pRadianceFileDescriptor = pRadianceDescriptor->getFileDescriptor();
         if (pRadianceFileDescriptor != NULL)
         {
            pRadianceFileDescriptor->setDatasetLocation(suffix + "-radiance");
            ImportDescriptorResource pRadianceImportDescriptor(pRadianceDescriptor,
               shouldDefaultImportRadiance);
            descriptors.push_back(pRadianceImportDescriptor.release());
         }
      }
   }
   else if (shouldDefaultImportRadiance)
   {
      fallbackToDn = true;
   }

   std::vector<double> reflectanceFactors = Landsat::determineReflectanceConversionFactors(
      pMetadata, type, validBands);
   bool shouldDefaultImportReflectance =
      std::find(defaultImport.begin(), defaultImport.end(), suffix + "-Reflectance") != defaultImport.end();
   if (radianceFactors.size() == bandFiles.size() && reflectanceFactors.size() == bandFiles.size())
   {
      //we have enough to create reflectance import descriptor
      RasterDataDescriptor* pReflectanceDescriptor = dynamic_cast<RasterDataDescriptor*>(
         pDescriptor->copy(filename + "-" + suffix + "-reflectance", NULL));
      if (pReflectanceDescriptor != NULL)
      {
         pReflectanceDescriptor->setDataType(INT2SBYTES);
         pReflectanceDescriptor->setValidDataTypes(
            std::vector<EncodingType>(1, pReflectanceDescriptor->getDataType()));
         pReflectanceDescriptor->setBadValues(std::vector<int>(1, std::numeric_limits<short>::max()));
         FactoryResource<Units> pUnits;
         pUnits->setUnitType(REFLECTANCE);
         pUnits->setUnitName("Reflectance");
         pUnits->setScaleFromStandard(1/10000.0);
         pReflectanceDescriptor->setUnits(pUnits.get());
         FileDescriptor* pReflectanceFileDescriptor = pReflectanceDescriptor->getFileDescriptor();
         if (pReflectanceFileDescriptor != NULL)
         {
            pReflectanceFileDescriptor->setDatasetLocation(suffix + "-reflectance");
            ImportDescriptorResource pReflectanceImportDescriptor(pReflectanceDescriptor,
               shouldDefaultImportReflectance);
            descriptors.push_back(pReflectanceImportDescriptor.release());
         }
      }
   }
   else if (shouldDefaultImportReflectance)
   {
      fallbackToDn = true;
   }

   double K1 = 0.0;
   double K2 = 0.0;
   bool haveTemperatureFactors = Landsat::getTemperatureConstants(pMetadata, type,
      K1, K2);
   bool shouldDefaultImportTemperature =
      std::find(defaultImport.begin(), defaultImport.end(), suffix + "-Temperature") != defaultImport.end();
   if (radianceFactors.size() == bandFiles.size() && haveTemperatureFactors)
   {
      //we have enough to create temperature import descriptor
      RasterDataDescriptor* pTemperatureDescriptor = dynamic_cast<RasterDataDescriptor*>(
         pDescriptor->copy(filename + "-" + suffix + "-temperature", NULL));
      if (pTemperatureDescriptor != NULL)
      {
         pTemperatureDescriptor->setDataType(FLT4BYTES);
         pTemperatureDescriptor->setValidDataTypes(
            std::vector<EncodingType>(1, pTemperatureDescriptor->getDataType()));
         pTemperatureDescriptor->setBadValues(std::vector<int>(1, -1));
         FactoryResource<Units> pUnits;
         pUnits->setUnitType(EMISSIVITY);
         pUnits->setUnitName("K");
         pUnits->setScaleFromStandard(1.0);
         pTemperatureDescriptor->setUnits(pUnits.get());
         FileDescriptor* pTemperatureFileDescriptor = pTemperatureDescriptor->getFileDescriptor();
         if (pTemperatureFileDescriptor != NULL)
         {
            pTemperatureFileDescriptor->setDatasetLocation(suffix + "-temperature");
            ImportDescriptorResource pTemperatureImportDescriptor(pTemperatureDescriptor,
               shouldDefaultImportTemperature);
            descriptors.push_back(pTemperatureImportDescriptor.release());
         }
      }
   }
   else if (shouldDefaultImportTemperature)
   {
      fallbackToDn = true;
   }

   if (fallbackToDn ||
      std::find(defaultImport.begin(), defaultImport.end(), suffix + "-DN") != defaultImport.end())
   {
      pImportDescriptor->setImported(true);
   }

   return descriptors;
}