void ExportOptionsDlg::accept()
{
   // Update the user's subset changes in the file descriptor
   RasterFileDescriptor* pRasterFileDescriptor = dynamic_cast<RasterFileDescriptor*>(mpExporter->getFileDescriptor());
   if ((pRasterFileDescriptor != NULL) && (mpSubsetPage != NULL))
   {
      // Rows
      vector<DimensionDescriptor> rows = mpSubsetPage->getSubsetRows();
      std::transform(rows.begin(), rows.end(), rows.begin(), SetOnDiskNumber());
      pRasterFileDescriptor->setRows(rows);

      // Columns
      vector<DimensionDescriptor> columns = mpSubsetPage->getSubsetColumns();
      std::transform(columns.begin(), columns.end(), columns.begin(), SetOnDiskNumber());
      pRasterFileDescriptor->setColumns(columns);

      // Bands
      vector<DimensionDescriptor> bands = mpSubsetPage->getSubsetBands();
      std::transform(bands.begin(), bands.end(), bands.begin(), SetOnDiskNumber());
      pRasterFileDescriptor->setBands(bands);
   }

   // Validate with the exporter
   string errorMessage;
   ValidationResultType result = mpExporter->validate(errorMessage);
   if (result == VALIDATE_FAILURE)
   {
      if (errorMessage.empty() == true)
      {
         errorMessage = "Unable to validate inputs.";
      }

      QMessageBox::critical(this, "Export Options", QString::fromStdString(errorMessage));
      return;
   }
   else if (result == VALIDATE_INFO)
   {
      // Exporters returning VALIDATE_INFO must provide a value for the error message
      VERIFYNRV(errorMessage.empty() == false);

      if (QMessageBox::warning(this, "Export Options", QString::fromStdString(errorMessage), QMessageBox::Ok,
         QMessageBox::Cancel) == QMessageBox::Cancel)
      {
         return;
      }
   }
   else if (result == VALIDATE_INPUT_REQUIRED)
   {
      if (errorMessage.empty() == true)
      {
         errorMessage = "Additional input is required.";
      }

      QMessageBox::critical(this, "Export Options", QString::fromStdString(errorMessage));
      return;
   }

   QDialog::accept();
}
ExportOptionsDlg::ExportOptionsDlg(ExporterResource& pExporter, QWidget* pParent) :
   QDialog(pParent),
   mpExporter(pExporter),
   mpTabWidget(NULL),
   mpSubsetPage(NULL),
   mpExporterPage(NULL)
{
   // Options widget
   QStackedWidget* pStack = new QStackedWidget(this);

   // Subset page
   RasterElement* pRasterElement = dynamic_cast<RasterElement*>(mpExporter->getItem());
   RasterFileDescriptor* pRasterWholeCubeFileDescriptor = NULL;
   RasterDataDescriptor* pRasterOrgDataDescriptor = NULL;
   if (pRasterElement != NULL)
   {
      pRasterOrgDataDescriptor = dynamic_cast<RasterDataDescriptor*>(pRasterElement->getDataDescriptor());
      if (pRasterOrgDataDescriptor != NULL)
      {
         // we are creating a file descriptor for export from the original cube, because the SubsetWidget
         // uses DimensionDescriptor::operator= compare's to determine selection which dictate that on-disk,
         // original and active numbers need to be identical, this guarantees that DimensionDescriptors will
         // compare correctly.
         pRasterWholeCubeFileDescriptor = dynamic_cast<RasterFileDescriptor*>(
            RasterUtilities::generateFileDescriptorForExport(pRasterOrgDataDescriptor, "foobar"));
      }
   }
   RasterFileDescriptor* pRasterFileDescriptor = dynamic_cast<RasterFileDescriptor*>(mpExporter->getFileDescriptor());
   if ((pRasterFileDescriptor != NULL) && (pRasterWholeCubeFileDescriptor != NULL) &&
      (pRasterOrgDataDescriptor != NULL))
   {
      mpSubsetPage = new SubsetWidget();
      mpSubsetPage->setExportMode(true);

      // Rows
      const vector<DimensionDescriptor>& orgRows = pRasterWholeCubeFileDescriptor->getRows();
      const vector<DimensionDescriptor>& selectedRows = pRasterFileDescriptor->getRows();
      mpSubsetPage->setRows(orgRows, selectedRows);

      // Columns
      const vector<DimensionDescriptor>& orgColumns = pRasterWholeCubeFileDescriptor->getColumns();
      const vector<DimensionDescriptor>& selectedColumns = pRasterFileDescriptor->getColumns();
      mpSubsetPage->setColumns(orgColumns, selectedColumns);

      // Bands
      const vector<DimensionDescriptor>& orgBands = pRasterWholeCubeFileDescriptor->getBands();
      const vector<DimensionDescriptor>& selectedBands = pRasterFileDescriptor->getBands();
      vector<string> bandNames = RasterUtilities::getBandNames(pRasterOrgDataDescriptor);
      mpSubsetPage->setBands(orgBands, bandNames, selectedBands);

      // Initial bad band file directory
      QString strDirectory;

      string filename = pRasterFileDescriptor->getFilename();
      if (filename.empty() == false)
      {
         QFileInfo fileInfo(QString::fromStdString(filename));
         strDirectory = fileInfo.absolutePath();
      }

      mpSubsetPage->setBadBandFileDirectory(strDirectory);
   }

   // Exporter page
   if (mpExporter->getPlugIn() != NULL)
   {
      mpExporterPage = mpExporter->getExportOptionsWidget();
   }

   // Horizontal line
   QFrame* pLine = new QFrame(this);
   pLine->setFrameStyle(QFrame::HLine | QFrame::Sunken);

   // Buttons
   QDialogButtonBox* pButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
      Qt::Horizontal, this);

   // Layout
   QVBoxLayout* pLayout = new QVBoxLayout(this);
   pLayout->setMargin(10);
   pLayout->setSpacing(10);
   pLayout->addWidget(pStack, 10);
   pLayout->addWidget(pLine);
   pLayout->addWidget(pButtonBox);

   // Initialization
   QString strWindowTitle = "Export Options";

   SessionItem* pSessionItem = mpExporter->getItem();
   if (pSessionItem != NULL)
   {
      string name = pSessionItem->getDisplayName();
      if (name.empty() == true)
      {
         name = pSessionItem->getName();
      }

      if (name.empty() == false)
      {
         strWindowTitle += ": " + QString::fromStdString(name);
      }
   }

   setWindowTitle(strWindowTitle);
   setModal(true);

   if ((mpSubsetPage != NULL) || (mpExporterPage != NULL))
   {
      QWidget* pSubsetWidget = NULL;
      if (mpSubsetPage != NULL)
      {
         pSubsetWidget = new QWidget();
         mpSubsetPage->setParent(pSubsetWidget);

         QVBoxLayout* pSubsetLayout = new QVBoxLayout(pSubsetWidget);
         if (mpExporterPage != NULL)
         {
            pSubsetLayout->setMargin(10);
         }
         else
         {
            pSubsetLayout->setMargin(0);
         }

         pSubsetLayout->setSpacing(10);
         pSubsetLayout->addWidget(mpSubsetPage);
      }

      QWidget* pExporterWidget = NULL;
      if (mpExporterPage != NULL)
      {
         pExporterWidget = new QWidget();
         mpExporterPage->setParent(pExporterWidget);

         QVBoxLayout* pExporterLayout = new QVBoxLayout(pExporterWidget);
         if (mpSubsetPage != NULL)
         {
            pExporterLayout->setMargin(10);
         }
         else
         {
            pExporterLayout->setMargin(0);
         }

         pExporterLayout->setSpacing(10);
         pExporterLayout->addWidget(mpExporterPage);
      }

      if ((pSubsetWidget != NULL) && (pExporterWidget != NULL))
      {
         QString strExporterCaption = mpExporterPage->windowTitle();
         if (strExporterCaption.isEmpty() == true)
         {
            PlugIn* pPlugIn = mpExporter->getPlugIn();
            if (pPlugIn != NULL)
            {
               strExporterCaption = QString::fromStdString(pPlugIn->getName());
            }

            if (strExporterCaption.isEmpty() == true)
            {
               strExporterCaption = "Exporter";
            }
         }

         mpTabWidget = new QTabWidget(this);
         mpTabWidget->setTabPosition(QTabWidget::North);
         mpTabWidget->addTab(pSubsetWidget, "Subset");
         mpTabWidget->addTab(pExporterWidget, strExporterCaption);
         pStack->addWidget(mpTabWidget);
      }
      else if (pSubsetWidget != NULL)
      {
         pStack->addWidget(pSubsetWidget);
         pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
      }
      else if (pExporterWidget != NULL)
      {
         pStack->addWidget(pExporterWidget);
      }
   }

   if (pStack->count() == 0)
   {
      QLabel* pNoOptionsLabel = new QLabel("No options are available", this);
      pNoOptionsLabel->setAlignment(Qt::AlignCenter);
      pNoOptionsLabel->setMinimumSize(250, 100);

      pStack->addWidget(pNoOptionsLabel);
   }

   // Connections
   VERIFYNR(connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept())));
   VERIFYNR(connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())));
}
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;
}
bool RasterElementImporterShell::performImport() const
{
   Progress* pProgress = getProgress();
   StepResource pStep("Perform import", "app", "762EF4BB-8813-4e45-B1BD-4CD237F7C151");

   FAIL_IF(mpRasterElement == NULL, "Could not find RasterElement", return false);

   RasterDataDescriptor* pDescriptor = dynamic_cast<RasterDataDescriptor*>(
      mpRasterElement->getDataDescriptor());
   FAIL_IF(pDescriptor == NULL, "Could not find RasterDataDescriptor", return false);

   string message;

//#pragma message(__FILE__ "(" STRING(__LINE__) ") : warning : Re-evaluate this code when plug-ins " \
//   "are being loaded into the global symbol space (tclarke)")
   // This was changed from a try/catch due to a problem with the exceptions 
   // not being caught and propagating up to QApplication::notify on solaris.
   // it is believed this is due to how we load plug-ins;
   // they are loaded into a private symbol space. When this changes,
   // re-evaluate the try/catch model.
   if (pDescriptor->getProcessingLocation() == ON_DISK_READ_ONLY)
   {
      Service<SessionManager> pSessionManager;
      if (pSessionManager->isSessionLoading() == false)
      {
         RasterFileDescriptor* pOrigFileDescriptor = dynamic_cast<RasterFileDescriptor*>(pDescriptor->getFileDescriptor());
         std::vector<DimensionDescriptor> orgRows = pOrigFileDescriptor->getRows();
         std::vector<DimensionDescriptor> orgColumns = pOrigFileDescriptor->getColumns();
         std::vector<DimensionDescriptor> orgBands = pOrigFileDescriptor->getBands();

         std::vector<DimensionDescriptor>::iterator iter;
         unsigned int i = 0;
         for (iter = orgRows.begin(), i = 0; iter != orgRows.end(); ++iter, ++i)
         {
            iter->setActiveNumber(i);
         }
         for (iter = orgColumns.begin(), i = 0; iter != orgColumns.end(); ++iter, ++i)
         {
            iter->setActiveNumber(i);
         }
         for (iter = orgBands.begin(), i = 0; iter != orgBands.end(); ++iter, ++i)
         {
            iter->setActiveNumber(i);
         }
         vector<DimensionDescriptor> selectedRows = getSelectedDims(orgRows,
            pDescriptor->getRows());
         vector<DimensionDescriptor> selectedColumns = getSelectedDims(orgColumns,
            pDescriptor->getColumns());
         vector<DimensionDescriptor> selectedBands = getSelectedDims(orgBands,
            pDescriptor->getBands());

         if (!RasterUtilities::chipMetadata(mpRasterElement->getMetadata(),
            selectedRows, selectedColumns, selectedBands))
         {
            return checkAbortOrError("Could not chip metadata", pStep.get());
         }
      }

      if (createRasterPager(mpRasterElement) == false)
      {
         return checkAbortOrError("Could not create pager for RasterElement", pStep.get());
      }
   }
   else
   {
      if (mpRasterElement->createDefaultPager() == false)
      {
         return checkAbortOrError("Could not allocate resources for new RasterElement", pStep.get());
      }
      RasterDataDescriptor* pSourceDescriptor = RasterUtilities::generateUnchippedRasterDataDescriptor(mpRasterElement);
      if (pSourceDescriptor == NULL)
      {
         return checkAbortOrError("Could not get unchipped RasterDataDescriptor", pStep.get());
      }

      ModelResource<RasterElement> pSourceRaster(pSourceDescriptor);
      if (pSourceRaster.get() == NULL)
      {
         return checkAbortOrError("Could not create source RasterElement", pStep.get());
      }

      if (createRasterPager(pSourceRaster.get()) == false)
      {
         return checkAbortOrError("Could not create pager for source RasterElement", pStep.get());
      }

      if (copyData(pSourceRaster.get()) == false)
      {
         return checkAbortOrError("Could not copy data from source RasterElement", pStep.get());
      }

      double value = 0.0;
      uint64_t badValueCount = mpRasterElement->sanitizeData(value);
      if (badValueCount != 0)
      {
         if (mpProgress != NULL)
         {
            string message = StringUtilities::toDisplayString(badValueCount) + " bad value(s) found in data.\n" +
               "Bad values set to " + StringUtilities::toDisplayString(value);
            mpProgress->updateProgress(message, 100, WARNING);
         }
      }
   }

   pStep->finalize(Message::Success);
   return true;
}
Exemple #5
0
std::vector<ImportDescriptor*> FitsImporter::getImportDescriptors(const std::string& fname)
{
   std::string filename = fname;
   std::vector<std::vector<std::string> >& errors = mErrors[fname];
   std::vector<std::vector<std::string> >& warnings = mWarnings[fname];
   errors.clear();
   warnings.clear();
   int status=0;
   std::vector<ImportDescriptor*> descriptors;

   FitsFileResource pFile(filename);
   if (!pFile.isValid())
   {
      errors.resize(1);
      errors[0].push_back(pFile.getStatus());
      RETURN_DESCRIPTORS;
   }

   int hduCnt = 0;
   int specificHdu = 0;
   int hdu = 1;
   if (!splitFilename(filename, hduCnt, specificHdu, hdu, pFile, errors, warnings))
   {
      RETURN_DESCRIPTORS;
   }
   errors.resize(hduCnt+1);
   warnings.resize(hduCnt+1);

   for(; hdu <= hduCnt; ++hdu)
   {
      std::string datasetName = filename + "[" + StringUtilities::toDisplayString(hdu) + "]";
      int hduType;
      CHECK_FITS(fits_movabs_hdu(pFile, hdu, &hduType, &status), hdu, false, continue);
      ImportDescriptorResource pImportDescriptor(static_cast<ImportDescriptor*>(NULL));
      FactoryResource<DynamicObject> pMetadata;
      VERIFYRV(pMetadata.get() != NULL, descriptors);
      { // scope
         std::vector<std::string> comments;
         char pCard[81];
         char pValue[81];
         char pComment[81];
         int nkeys = 0;
         CHECK_FITS(fits_get_hdrspace(pFile, &nkeys, NULL, &status), hdu, true, ;);
         for(int keyidx = 1; keyidx <= nkeys; ++keyidx)
         {
            CHECK_FITS(fits_read_keyn(pFile, keyidx, pCard, pValue, pComment, &status), hdu, true, continue);
            std::string name = StringUtilities::stripWhitespace(std::string(pCard));
            std::string val = StringUtilities::stripWhitespace(std::string(pValue));
            std::string comment = StringUtilities::stripWhitespace(std::string(pComment));
            if (!val.empty())
            {
               pMetadata->setAttributeByPath("FITS/" + name, val);
            }
            else if (!comment.empty())
            {
               comments.push_back(comment);
            }
         }
         if (!comments.empty())
         {
            // ideally, this would add a multi-line string but Opticks doesn't display this properly
            // pMetadata->setAttributeByPath("FITS/COMMENT", StringUtilities::join(comments, "\n"));
            for(unsigned int idx = 0; idx < comments.size(); ++idx)
            {
               pMetadata->setAttributeByPath("FITS/COMMENT/" + StringUtilities::toDisplayString(idx), comments[idx]);
            }
         }
      }
      switch(hduType)
      {
      case IMAGE_HDU:
      {
         pImportDescriptor = ImportDescriptorResource(datasetName, TypeConverter::toString<RasterElement>());
         VERIFYRV(pImportDescriptor.get() != NULL, descriptors);

         EncodingType fileEncoding;
         InterleaveFormatType interleave(BSQ);
         unsigned int rows=0;
         unsigned int cols=0;
         unsigned int bands=1;

         int bitpix;
         int naxis;
         long axes[3];
         CHECK_FITS(fits_get_img_param(pFile, 3, &bitpix, &naxis, axes, &status), hdu, false, continue);
         switch(bitpix)
         {
         case BYTE_IMG:
            fileEncoding = INT1UBYTE;
            break;
         case SHORT_IMG:
            fileEncoding = INT2SBYTES;
            break;
         case LONG_IMG:
            fileEncoding = INT4SBYTES;
            break;
         case FLOAT_IMG:
            fileEncoding = FLT4BYTES;
            break;
         case DOUBLE_IMG:
            fileEncoding = FLT8BYTES;
            break;
         default:
            warnings[hdu].push_back("Unsupported BITPIX value " + StringUtilities::toDisplayString(bitpix) + ".");
            continue;
         }
         EncodingType dataEncoding = checkForOverflow(fileEncoding, pMetadata.get(), hdu, errors, warnings);
         if (naxis == 1)
         {
            // 1-D data is a signature
            pImportDescriptor = ImportDescriptorResource(datasetName, TypeConverter::toString<Signature>());
            pMetadata->setAttributeByPath(METADATA_SIG_ENCODING, dataEncoding);
            pMetadata->setAttributeByPath(METADATA_SIG_LENGTH, axes[0]);

            RasterUtilities::generateAndSetFileDescriptor(pImportDescriptor->getDataDescriptor(), filename,
               StringUtilities::toDisplayString(hdu), BIG_ENDIAN_ORDER);

            // add units
            SignatureDataDescriptor* pSigDd =
               dynamic_cast<SignatureDataDescriptor*>(pImportDescriptor->getDataDescriptor());
            if (pSigDd != NULL)
            {
               FactoryResource<Units> pUnits;
               pUnits->setUnitName("Custom");
               pUnits->setUnitType(CUSTOM_UNIT);
               pSigDd->setUnits("Reflectance", pUnits.get());
            }

            break; // leave switch()
         }
         else if (naxis == 2)
         {
            cols = axes[0];
            rows = axes[1];
         }
         else if (naxis == 3)
         {
            cols = axes[0];
            rows = axes[1];
            bands = axes[2];
         }
         else
         {
            errors[hdu].push_back(StringUtilities::toDisplayString(naxis) + " axis data not supported.");
         }

         RasterDataDescriptor* pDataDesc = RasterUtilities::generateRasterDataDescriptor(
            datasetName, NULL, rows, cols, bands, interleave, dataEncoding, IN_MEMORY);
         pImportDescriptor->setDataDescriptor(pDataDesc);
         if (specificHdu == 0 && hdu == 1 && naxis == 2 && (axes[0] <= 5 || axes[1] <= 5))
         {
            // use 5 as this is a good top end for the number of astronomical band pass filters
            // in general usage. this is not in a spec anywhere and is derived from various sample
            // FITS files for different astronomical instruments.
            //
            // There's a good chance this is really a spectrum. (0th HDU)
            // We'll create an import descriptor for the spectrum version of this
            // And disable the raster descriptor by default
            pImportDescriptor->setImported(false);
            ImportDescriptorResource pSigDesc(datasetName, TypeConverter::toString<SignatureLibrary>());
            DynamicObject* pSigMetadata = pSigDesc->getDataDescriptor()->getMetadata();
            pSigMetadata->merge(pMetadata.get());
            std::vector<double> centerWavelengths;
            unsigned int cnt = (axes[0] <= 5) ? axes[1] : axes[0];
            double startVal = StringUtilities::fromDisplayString<double>(
               dv_cast<std::string>(pMetadata->getAttributeByPath("FITS/MINWAVE"), "0.0"));
            double endVal = StringUtilities::fromDisplayString<double>(
               dv_cast<std::string>(pMetadata->getAttributeByPath("FITS/MAXWAVE"), "0.0"));
            double incr = (endVal == 0.0) ? 1.0 : ((endVal - startVal) / static_cast<double>(cnt));
            centerWavelengths.reserve(cnt);
            for (unsigned int idx = 0; idx < cnt; idx++)
            {
               centerWavelengths.push_back(startVal + (idx * incr));
            }
            pSigMetadata->setAttributeByPath(CENTER_WAVELENGTHS_METADATA_PATH, centerWavelengths);

            // Units
            std::string unitsName = dv_cast<std::string>(pMetadata->getAttributeByPath("FITS/BUNIT"), std::string());
            if (!unitsName.empty())
            {
               FactoryResource<Units> units;
               units->setUnitName(unitsName);
               units->setUnitType(RADIANCE);
               SignatureDataDescriptor* pSigDd =
                  dynamic_cast<SignatureDataDescriptor*>(pSigDesc->getDataDescriptor());
               if (pSigDd != NULL)
               {
                  pSigDd->setUnits("Reflectance", units.get());
               }
            }

            RasterUtilities::generateAndSetFileDescriptor(pSigDesc->getDataDescriptor(),
               filename, StringUtilities::toDisplayString(hdu), BIG_ENDIAN_ORDER);

            // If units are not available, set custom units into the data descriptor so that the user can
            // modify them - this must occur after the call to RasterUtilities::generateAndSetFileDescriptor()
            // so that the file descriptor will still display no defined units
            if (unitsName.empty())
            {
               FactoryResource<Units> units;
               units->setUnitName("Custom");
               units->setUnitType(CUSTOM_UNIT);
               SignatureDataDescriptor* pSigDd = dynamic_cast<SignatureDataDescriptor*>(pSigDesc->getDataDescriptor());
               if (pSigDd != NULL)
               {
                  pSigDd->setUnits("Reflectance", units.get());
               }
            }

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

         RasterFileDescriptor* pFileDescriptor = dynamic_cast<RasterFileDescriptor*>(
            RasterUtilities::generateAndSetFileDescriptor(pDataDesc, filename,
            StringUtilities::toDisplayString(hdu), BIG_ENDIAN_ORDER));
         if (pFileDescriptor != NULL)
         {
            unsigned int bitsPerElement = RasterUtilities::bytesInEncoding(fileEncoding) * 8;
            pFileDescriptor->setBitsPerElement(bitsPerElement);
         }

         break; // leave switch()
      }
      case ASCII_TBL:
      case BINARY_TBL:
         warnings[hdu].push_back("Tables not supported. [HDU " + StringUtilities::toDisplayString(hdu) + "]");
         continue;
      default:
         warnings[hdu].push_back("HDU " + StringUtilities::toDisplayString(hdu) + " is an unknown type.");
         continue;
      }

      pImportDescriptor->getDataDescriptor()->setMetadata(pMetadata.release());
      pImportDescriptor->setImported(errors[hdu].empty());
      descriptors.push_back(pImportDescriptor.release());
   }
ImportDescriptor* Nitf::NitfImporterShell::getImportDescriptor(const string& filename, ossim_uint32 imageSegment,
                                                               const Nitf::OssimFileResource& pFile,
                                                               const ossimNitfFileHeaderV2_X* pFileHeader,
                                                               const ossimNitfImageHeaderV2_X* pImageSubheader)
{
   if (pImageSubheader == NULL)
   {
      return NULL;
   }

   EncodingType dataType = ossimImageHeaderToEncodingType(pImageSubheader);
   if (dataType.isValid() == false)
   {
      return NULL;
   }

   stringstream imageNameStream;
   imageNameStream << "I" << imageSegment + 1;
   string imageName = imageNameStream.str();

   ImportDescriptorResource pImportDescriptor(filename + "-" + imageName,
      TypeConverter::toString<RasterElement>(), NULL);
   VERIFYRV(pImportDescriptor.get() != NULL, NULL);
   pImportDescriptor->setImported(pImageSubheader->getRepresentation() != "NODISPLY");

   RasterDataDescriptor* pDescriptor = dynamic_cast<RasterDataDescriptor*>(pImportDescriptor->getDataDescriptor());
   VERIFYRV(pDescriptor != NULL, NULL);

   vector<DimensionDescriptor> bands =  RasterUtilities::generateDimensionVector(pImageSubheader->getNumberOfBands(),
      true, false, true);
   pDescriptor->setBands(bands);

   vector<DimensionDescriptor> rows = RasterUtilities::generateDimensionVector(pImageSubheader->getNumberOfRows(),
      true, false, true);
   pDescriptor->setRows(rows);

   vector<DimensionDescriptor> cols = RasterUtilities::generateDimensionVector(pImageSubheader->getNumberOfCols(),
      true, false, true);
   pDescriptor->setColumns(cols);

   if (pImageSubheader->getIMode() == "P")
   {
      pDescriptor->setInterleaveFormat(BIP);
   }
   else if (pImageSubheader->getIMode() == "R")
   {
      pDescriptor->setInterleaveFormat(BIL);
   }
   else
   {
      pDescriptor->setInterleaveFormat(BSQ);
   }

   pDescriptor->setDataType(dataType);
   pDescriptor->setValidDataTypes(vector<EncodingType>(1, dataType));
   pDescriptor->setProcessingLocation(IN_MEMORY);

   map<string, TrePlugInResource> parsers;
   string errorMessage;

   // Set the file descriptor
   RasterFileDescriptor* pFileDescriptor = dynamic_cast<RasterFileDescriptor*>(
      RasterUtilities::generateAndSetFileDescriptor(pDescriptor, filename, imageName, LITTLE_ENDIAN_ORDER));
   if (pFileDescriptor == NULL)
   {
      return NULL;
   }

   // Set the bits per element, which may be different than the data type in the data descriptor,
   // using NBPP instead of ABPP as is done in ossimNitfTileSource.cpp.
   unsigned int bitsPerPixel = static_cast<unsigned int>(pImageSubheader->getBitsPerPixelPerBand());
   pFileDescriptor->setBitsPerElement(bitsPerPixel);

   // Populate the metadata and set applicable values in the data descriptor
   if (Nitf::importMetadata(imageSegment + 1, pFile, pFileHeader, pImageSubheader, pDescriptor, parsers,
      errorMessage) == true)
   {
      // Populate specific fields in the data descriptor or file descriptor from the TREs
      const DynamicObject* pMetadata = pDescriptor->getMetadata();
      VERIFYRV(pMetadata, NULL);

      // Pixel size - This info is contained in multiple TREs, but there is no documentation on which
      // TRE contains the more precise value if multiple TREs containing the info are present.  Choosing
      // the order ACFTA, BANDSA, ACFTB, and BANDSB where the later "B" TREs will overwrite the values
      // contained in the earlier "A" TREs.  The BANDSB TRE contains GSD values for each band, which is
      // currently not supported, so only set the pixel size if the values in all bands are the same.
      double xGsd = 1.0;
      double yGsd = 1.0;

      const string acrftaPath[] =
      {
         Nitf::NITF_METADATA,
         Nitf::TRE_METADATA,
         "ACFTA",
         "0",
         END_METADATA_NAME
      };

      const DynamicObject* pAcrftA = dv_cast<DynamicObject>(&pMetadata->getAttributeByPath(acrftaPath));
      if (pAcrftA != NULL)
      {
         // The ACFTA spec calls out specific spacing units for "SAR" and "EO-IR" data, but does not indicate how
         // this is determined.  It seems to be related to the ACFTB SENSOR_ID_TYPE field, but that field is not
         // present in the ACFTA TRE.  So just check for "SAR" data from the ICAT field in the image subheader
         // and assume every other data type is "EO-IR" data.
         const string imageCategory = pImageSubheader->getCategory().trim();

         const DataVariant& rowSpacing = pAcrftA->getAttribute(Nitf::TRE::ACFTA::ROW_SPACING);
         if (rowSpacing.isValid() == true)
         {
            if (imageCategory == "SAR")
            {
               yGsd = getGsd(rowSpacing, "f");     // Feet
            }
            else
            {
               yGsd = getGsd(rowSpacing, "r");     // Micro-radians
            }
         }

         const DataVariant& columnSpacing = pAcrftA->getAttribute(Nitf::TRE::ACFTA::COL_SPACING);
         if (columnSpacing.isValid() == true)
         {
            if (imageCategory == "SAR")
            {
               xGsd = getGsd(columnSpacing, "f");  // Feet
            }
            else
            {
               xGsd = getGsd(columnSpacing, "r");  // Micro-radians
            }
         }
      }

      const string bandsaPath[] =
      {
         Nitf::NITF_METADATA,
         Nitf::TRE_METADATA,
         "BANDSA",
         "0",
         END_METADATA_NAME
      };

      const DynamicObject* pBandsA = dv_cast<DynamicObject>(&pMetadata->getAttributeByPath(bandsaPath));
      if (pBandsA != NULL)
      {
         const DataVariant& rowSpacing = pBandsA->getAttribute(Nitf::TRE::BANDSA::ROW_SPACING);
         if (rowSpacing.isValid() == true)
         {
            const DataVariant& rowSpacingUnits = pBandsA->getAttribute(Nitf::TRE::BANDSA::ROW_SPACING_UNITS);
            if (rowSpacingUnits.isValid() == true)
            {
               yGsd = getGsd(rowSpacing, rowSpacingUnits.toXmlString());
            }
         }

         const DataVariant& columnSpacing = pBandsA->getAttribute(Nitf::TRE::BANDSA::COL_SPACING);
         if (columnSpacing.isValid() == true)
         {
            const DataVariant& columnSpacingUnits = pBandsA->getAttribute(Nitf::TRE::BANDSA::COL_SPACING_UNITS);
            if (columnSpacingUnits.isValid() == true)
            {
               xGsd = getGsd(columnSpacing, columnSpacingUnits.toXmlString());
            }
         }
      }

      const string acrftbPath[] =
      {
         Nitf::NITF_METADATA,
         Nitf::TRE_METADATA,
         "ACFTB",
         "0",
         END_METADATA_NAME
      };

      const DynamicObject* pAcrftB = dv_cast<DynamicObject>(&pMetadata->getAttributeByPath(acrftbPath));
      if (pAcrftB != NULL)
      {
         const DataVariant& rowSpacing = pAcrftB->getAttribute(Nitf::TRE::ACFTB::ROW_SPACING);
         if (rowSpacing.isValid() == true)
         {
            const DataVariant& rowSpacingUnits = pAcrftB->getAttribute(Nitf::TRE::ACFTB::ROW_SPACING_UNITS);
            if (rowSpacingUnits.isValid() == true)
            {
               yGsd = getGsd(rowSpacing, rowSpacingUnits.toXmlString());
            }
         }

         const DataVariant& columnSpacing = pAcrftB->getAttribute(Nitf::TRE::ACFTB::COL_SPACING);
         if (columnSpacing.isValid() == true)
         {
            const DataVariant& columnSpacingUnits = pAcrftB->getAttribute(Nitf::TRE::ACFTB::COL_SPACING_UNITS);
            if (columnSpacingUnits.isValid() == true)
            {
               xGsd = getGsd(columnSpacing, columnSpacingUnits.toXmlString());
            }
         }
      }

      const string bandsbPath[] =
      {
         Nitf::NITF_METADATA,
         Nitf::TRE_METADATA,
         "BANDSB",
         "0",
         END_METADATA_NAME
      };

      const DynamicObject* pBandsB = dv_cast<DynamicObject>(&pMetadata->getAttributeByPath(bandsbPath));
      if (pBandsB != NULL)
      {
         bool validRowGsd = false;

         const DataVariant& rowGsd = pBandsB->getAttribute(Nitf::TRE::BANDSB::ROW_GSD);
         if (rowGsd.isValid() == true)
         {
            const DataVariant& rowGsdUnits = pBandsB->getAttribute(Nitf::TRE::BANDSB::ROW_GSD_UNIT);
            if (rowGsdUnits.isValid() == true)
            {
               yGsd = getGsd(rowGsd, rowGsdUnits.toXmlString());
               validRowGsd = true;
            }
         }

         if (validRowGsd == false)
         {
            if (pBandsB->getAttribute(Nitf::TRE::BANDSB::ROW_GSD + "#0").isValid())
            {
               double commonYGsd = -1.0;

               unsigned int numBands = pDescriptor->getBandCount();
               for (unsigned int i = 0; i < numBands; ++i)
               {
                  double bandYGsd = -1.0;
                  string bandPostfix = "#" + StringUtilities::toDisplayString(i);

                  const DataVariant& bandRowGsd = pBandsB->getAttribute(Nitf::TRE::BANDSB::ROW_GSD + bandPostfix);
                  if (bandRowGsd.isValid() == true)
                  {
                     const DataVariant& bandRowGsdUnits = pBandsB->getAttribute(Nitf::TRE::BANDSB::ROW_GSD_UNIT +
                        bandPostfix);
                     if (bandRowGsdUnits.isValid() == true)
                     {
                        bandYGsd = getGsd(bandRowGsd, bandRowGsdUnits.toXmlString());
                     }
                  }

                  if (bandYGsd == commonYGsd)
                  {
                     continue;
                  }

                  if (commonYGsd != -1.0)
                  {
                     commonYGsd = -1.0;
                     break;
                  }

                  commonYGsd = bandYGsd;
               }

               if (commonYGsd != 1.0)
               {
                  yGsd = commonYGsd;
               }
            }
         }

         bool validColumnGsd = false;

         const DataVariant& columnGsd = pBandsB->getAttribute(Nitf::TRE::BANDSB::COL_GSD);
         if (columnGsd.isValid() == true)
         {
            const DataVariant& columnGsdUnits = pBandsB->getAttribute(Nitf::TRE::BANDSB::COL_GSD_UNITS);
            if (columnGsdUnits.isValid() == true)
            {
               xGsd = getGsd(columnGsd, columnGsdUnits.toXmlString());
               validColumnGsd = true;
            }
         }

         if (validColumnGsd == false)
         {
            if (pBandsB->getAttribute(Nitf::TRE::BANDSB::COL_GSD + "#0").isValid())
            {
               double commonXGsd = -1.0;

               unsigned int numBands = pDescriptor->getBandCount();
               for (unsigned int i = 0; i < numBands; ++i)
               {
                  double bandXGsd = -1.0;
                  string bandPostfix = "#" + StringUtilities::toDisplayString(i);

                  const DataVariant& bandRowGsd = pBandsB->getAttribute(Nitf::TRE::BANDSB::COL_GSD + bandPostfix);
                  if (bandRowGsd.isValid() == true)
                  {
                     const DataVariant& bandRowGsdUnits = pBandsB->getAttribute(Nitf::TRE::BANDSB::COL_GSD_UNIT +
                        bandPostfix);
                     if (bandRowGsdUnits.isValid() == true)
                     {
                        bandXGsd = getGsd(bandRowGsd, bandRowGsdUnits.toXmlString());
                     }
                  }

                  if (bandXGsd == commonXGsd)
                  {
                     continue;
                  }

                  if (commonXGsd != -1.0)
                  {
                     commonXGsd = -1.0;
                     break;
                  }

                  commonXGsd = bandXGsd;
               }

               if (commonXGsd != 1.0)
               {
                  xGsd = commonXGsd;
               }
            }
         }
      }

      double magFactor = 1.0;
      ossimString imag = pImageSubheader->getImageMagnification().trim();
      if (imag.empty() == false)
      {
         // Need to multiply the GSD values by the image magnification (IMAG) value in the image subheader
         if (imag[0] == '/')
         {
            ossimString reciprocal = imag.substr(1);
            magFactor = 1.0 / reciprocal.toDouble();
         }
         else
         {
            magFactor = imag.toDouble();
         }

         xGsd *= magFactor;
         yGsd *= magFactor;
      }

      pDescriptor->setXPixelSize(xGsd);
      pDescriptor->setYPixelSize(yGsd);

      // Higher precision GCPs
      const string blockaPath[] =
      {
         Nitf::NITF_METADATA,
         Nitf::TRE_METADATA,
         "BLOCKA",
         "0",
         END_METADATA_NAME
      };

      const DynamicObject* pBlockA = dv_cast<DynamicObject>(&pMetadata->getAttributeByPath(blockaPath));
      if (pBlockA != NULL)
      {
         const DataVariant& blockLines = pBlockA->getAttribute(Nitf::TRE::BLOCKA::L_LINES);
         if (blockLines.isValid() == true)
         {
            unsigned int numBlockRows = 0;
            if (blockLines.getValue<unsigned int>(numBlockRows) == true)
            {
               // Need to multiply the number of rows by the image magnification (IMAG) value in the image subheader
               numBlockRows = static_cast<unsigned int>(static_cast<double>(numBlockRows) * magFactor);
               if (numBlockRows == pFileDescriptor->getRowCount())
               {
                  list<GcpPoint> updatedGcps;

                  list<GcpPoint> gcps = pFileDescriptor->getGcps();
                  for (list<GcpPoint>::iterator iter = gcps.begin(); iter != gcps.end(); ++iter)
                  {
                     GcpPoint gcp = *iter;
                     string coordinateText;

                     list<GcpPoint>::size_type index = updatedGcps.size();
                     if (index == 0)
                     {
                        const DataVariant& gcp1 = pBlockA->getAttribute(Nitf::TRE::BLOCKA::FRFC_LOC);
                        if (gcp1.isValid() == true)
                        {
                           coordinateText = gcp1.toXmlString();
                        }
                     }
                     else if (index == 1)
                     {
                        const DataVariant& gcp2 = pBlockA->getAttribute(Nitf::TRE::BLOCKA::FRLC_LOC);
                        if (gcp2.isValid() == true)
                        {
                           coordinateText = gcp2.toXmlString();
                        }
                     }
                     else if (index == 2)
                     {
                        const DataVariant& gcp3 = pBlockA->getAttribute(Nitf::TRE::BLOCKA::LRLC_LOC);
                        if (gcp3.isValid() == true)
                        {
                           coordinateText = gcp3.toXmlString();
                        }
                     }
                     else if (index == 3)
                     {
                        const DataVariant& gcp4 = pBlockA->getAttribute(Nitf::TRE::BLOCKA::LRFC_LOC);
                        if (gcp4.isValid() == true)
                        {
                           coordinateText = gcp4.toXmlString();
                        }
                     }

                     if (StringUtilities::isAllBlank(coordinateText) == false)
                     {
                        coordinateText.insert(10, ", ");
                        LatLonPoint latLon(coordinateText);
                        gcp.mCoordinate = latLon.getCoordinates();
                     }

                     updatedGcps.push_back(gcp);
                  }

                  pFileDescriptor->setGcps(updatedGcps);
               }
            }
         }
      }

      // This only checks the first BANDSB. It is possible to have multiple BANDSB TREs.
      // If someone runs across real data where the bad band info is in another BANDSB TRE
      // this code will need to be modified.
      if (pBandsB != NULL && pBandsB->getAttribute(Nitf::TRE::BANDSB::BAD_BAND + "#0").isValid())
      {
         const vector<DimensionDescriptor>& curBands = pDescriptor->getBands();
         vector<DimensionDescriptor> newBands;
         for (size_t idx = 0; idx < curBands.size(); ++idx)
         {
            const int* pVal = dv_cast<int>(&pBandsB->getAttribute(
               Nitf::TRE::BANDSB::BAD_BAND + "#" + StringUtilities::toDisplayString(idx)));
            if (pVal == NULL || *pVal == 1) // 0 == invalid or suspect band, 1 = valid band
            {
               newBands.push_back(curBands[idx]);
            }
         }
         pDescriptor->setBands(newBands);
      }

      // Bad values
      if (pImageSubheader->hasTransparentCode() == true)
      {
         vector<int> badValues;
         badValues.push_back(static_cast<int>(pImageSubheader->getTransparentCode()));
         pDescriptor->setBadValues(badValues);
      }

      // If red, green, OR blue bands are valid, set the display mode to RGB.
      if (pDescriptor->getDisplayBand(RED).isValid() == true ||
         pDescriptor->getDisplayBand(GREEN).isValid() == true ||
         pDescriptor->getDisplayBand(BLUE).isValid() == true)
      {
         pDescriptor->setDisplayMode(RGB_MODE);
      }
      // Otherwise, if the gray band is valid, set the display mode to GRAYSCALE.
      else if (pDescriptor->getDisplayBand(GRAY).isValid() == true)
      {
         pDescriptor->setDisplayMode(GRAYSCALE_MODE);
      }
      // Otherwise, if at least 3 bands are available, set the display mode to RGB,
      // and set the first three bands to red, green, and blue respectively.
      else if (bands.size() >= 3)
      {
         pDescriptor->setDisplayBand(RED, bands[0]);
         pDescriptor->setDisplayBand(GREEN, bands[1]);
         pDescriptor->setDisplayBand(BLUE, bands[2]);
         pDescriptor->setDisplayMode(RGB_MODE);
      }
      // Otherwise, if at least 1 band is available, set the display mode to GRAYSCALE,
      // and set the first band to GRAY.
      else if (bands.empty() == false)
      {
         pDescriptor->setDisplayBand(GRAY, bands[0]);
         pDescriptor->setDisplayMode(GRAYSCALE_MODE);
      }
      else
      {
         return NULL;
      }

      // Special initialization for J2K compressed image segments
      const string compressionPath[] =
      {
         Nitf::NITF_METADATA,
         Nitf::IMAGE_SUBHEADER,
         Nitf::ImageSubheaderFieldNames::COMPRESSION,
         END_METADATA_NAME
      };

      string imageCompression = pMetadata->getAttributeByPath(compressionPath).toDisplayString();
      if ((imageCompression == Nitf::ImageSubheaderFieldValues::IC_C8) ||
         (imageCompression == Nitf::ImageSubheaderFieldValues::IC_M8))
      {
         // Per Section 8.1 of the BIIF Profile for JPEG 2000 Version 01.10 (BPJ2K01.10),
         // if the values in the J2K data differ from the values in the image subheader,
         // the J2K values are given precedence.
         opj_image_t* pImage = getImageInfo(filename, imageSegment, OPJ_CODEC_J2K);
         if (pImage == NULL)
         {
            pImage = getImageInfo(filename, imageSegment, OPJ_CODEC_JP2);
         }

         if (pImage != NULL)
         {
            // Bits per element
            unsigned int bitsPerElement = pImage->comps->prec;
            if (bitsPerElement != pFileDescriptor->getBitsPerElement())
            {
               pFileDescriptor->setBitsPerElement(bitsPerElement);
            }

            // Data type
            EncodingType dataType = INT1UBYTE;
            if (bitsPerElement <= 8)
            {
               if (pImage->comps->sgnd)
               {
                  dataType = INT1SBYTE;
               }
               else
               {
                  dataType = INT1UBYTE;
               }
            }
            else if (bitsPerElement <= 16)
            {
               if (pImage->comps->sgnd)
               {
                  dataType = INT2SBYTES;
               }
               else
               {
                  dataType = INT2UBYTES;
               }
            }
            else if (bitsPerElement <= 32)
            {
               if (pImage->comps->sgnd)
               {
                  dataType = INT4SBYTES;
               }
               else
               {
                  dataType = INT4UBYTES;
               }
            }
            else if (bitsPerElement <= 64)
            {
               dataType = FLT8BYTES;
            }

            if (dataType != pDescriptor->getDataType())
            {
               pDescriptor->setDataType(dataType);
            }

            // Rows
            unsigned int numRows = pImage->comps->h;
            if (numRows != pFileDescriptor->getRowCount())
            {
               vector<DimensionDescriptor> rows = RasterUtilities::generateDimensionVector(numRows, true, false, true);
               pDescriptor->setRows(rows);
               pFileDescriptor->setRows(rows);
            }

            // Columns
            unsigned int numColumns = pImage->comps->w;
            if (numColumns != pFileDescriptor->getColumnCount())
            {
               vector<DimensionDescriptor> columns = RasterUtilities::generateDimensionVector(numColumns, true, false,
                  true);
               pDescriptor->setColumns(columns);
               pFileDescriptor->setColumns(columns);
            }

            // Bands
            unsigned int numBands = pImage->numcomps;
            if (numBands != pFileDescriptor->getBandCount())
            {
               vector<DimensionDescriptor> bands = RasterUtilities::generateDimensionVector(numBands, true, false,
                  true);
               pDescriptor->setBands(bands);
               pFileDescriptor->setBands(bands);
            }

            // Cleanup
            opj_image_destroy(pImage);
         }

         // Set the interleave format as BIP, which is the interleave format for J2K data
         pDescriptor->setInterleaveFormat(BIP);
         pFileDescriptor->setInterleaveFormat(BIP);
      }

      mParseMessages[imageSegment] = errorMessage;
   }

   return pImportDescriptor.release();
}
TreExportStatus Nitf::BandsaParser::exportMetadata(const RasterDataDescriptor &descriptor, 
   const RasterFileDescriptor &exportDescriptor, DynamicObject &tre, 
   unsigned int & ownerIndex, string & tagType, string &errorMessage) const
{
   // Find out if we are exporting a subset of the original bands. If so then delete the
   // band info for the excluded bands.

   const DynamicObject* pMetadata = descriptor.getMetadata();
   VERIFYRV(pMetadata != NULL, REMOVE);
   try
   {
      const DataVariant& nitfMetadata = pMetadata->getAttribute(Nitf::NITF_METADATA);
      const DynamicObject* pExistingBandsa = getTagHandle(dv_cast<DynamicObject>(nitfMetadata), "BANDSA", FindFirst());
      if (!pExistingBandsa)
      {
         return UNCHANGED;
      }

      const vector<DimensionDescriptor>& exportBands = exportDescriptor.getBands();

      VERIFYRV(!exportBands.empty(), REMOVE);

      tre.setAttribute(Nitf::TRE::BANDSA::ROW_SPACING,
         pExistingBandsa->getAttribute(Nitf::TRE::BANDSA::ROW_SPACING));
      tre.setAttribute(Nitf::TRE::BANDSA::ROW_SPACING_UNITS,
         pExistingBandsa->getAttribute(Nitf::TRE::BANDSA::ROW_SPACING_UNITS));
      tre.setAttribute(Nitf::TRE::BANDSA::COL_SPACING,
         pExistingBandsa->getAttribute(Nitf::TRE::BANDSA::COL_SPACING));
      tre.setAttribute(Nitf::TRE::BANDSA::COL_SPACING_UNITS,
         pExistingBandsa->getAttribute(Nitf::TRE::BANDSA::COL_SPACING_UNITS));
      tre.setAttribute(Nitf::TRE::BANDSA::FOCAL_LENGTH,
         pExistingBandsa->getAttribute(Nitf::TRE::BANDSA::FOCAL_LENGTH));

      unsigned int bandcount(0);

      for (vector<DimensionDescriptor>::const_iterator iter = exportBands.begin(); iter != exportBands.end(); ++iter)
      {
         // Use the original band number to find the associated band data in the original TRE
         LOG_IF(!iter->isOriginalNumberValid(), continue);
         unsigned int origBandNum = iter->getOriginalNumber();

         stringstream bandStreamStr;
         bandStreamStr << "#" << bandcount;
         string bandStr(bandStreamStr.str());

         stringstream origBandStreamStr;
         origBandStreamStr << "#" << origBandNum;
         string origBandStr(origBandStreamStr.str());

         ++bandcount;

         string fieldName;
         string origFieldName;

         fieldName = BANDSA::BANDPEAK + bandStr;
         origFieldName = BANDSA::BANDPEAK + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDLBOUND + bandStr;
         origFieldName = BANDSA::BANDLBOUND + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDUBOUND + bandStr;
         origFieldName = BANDSA::BANDUBOUND + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDWIDTH + bandStr;
         origFieldName = BANDSA::BANDWIDTH + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDCALDRK + bandStr;
         origFieldName = BANDSA::BANDCALDRK + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDCALINC + bandStr;
         origFieldName = BANDSA::BANDCALINC + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDRESP + bandStr;
         origFieldName = BANDSA::BANDRESP + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDASD + bandStr;
         origFieldName = BANDSA::BANDASD + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));

         fieldName = BANDSA::BANDGSD + bandStr;
         origFieldName = BANDSA::BANDGSD + origBandStr;
         tre.setAttribute(fieldName, pExistingBandsa->getAttribute(origFieldName));
      }

      tre.setAttribute(Nitf::TRE::BANDSA::BANDCOUNT, bandcount);
   }
   catch (const bad_cast&)
   {
      return REMOVE;
   }
   catch (const string& message)
   {
      errorMessage = message;
      return REMOVE;
   }

   return REPLACE;
}
void ImportOptionsDlg::setCurrentDataset(ImportDescriptor* pImportDescriptor)
{
   if (pImportDescriptor == NULL)
   {
      return;
   }

   if (pImportDescriptor == mpCurrentDataset)
   {
      return;
   }

   // Apply changes to the current data set if necessary
   bool bSuccess = true;
   if ((mpCurrentDataset != NULL) && (mEditDataDescriptorModified == true))
   {
      if (mPromptForChanges == true)
      {
         int iReturn = QMessageBox::question(this, APP_NAME, "Apply changes to data?",
            QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::Cancel);
         if ((iReturn == QMessageBox::Yes) || (iReturn == QMessageBox::YesToAll))
         {
            bSuccess = applyChanges();
            if (iReturn == QMessageBox::YesToAll)
            {
               mPromptForChanges = false;
            }
         }
         else if (iReturn == QMessageBox::No)
         {
            // Update the validation icon for the original data descriptor
            validateDataset(mpCurrentDataset->getDataDescriptor());
         }
         else if (iReturn == QMessageBox::Cancel)
         {
            bSuccess = false;
         }
      }
      else
      {
         bSuccess = applyChanges();
      }
   }

   if (bSuccess == false)
   {
      // Select the tree widget item for the previously selected data set
      selectCurrentDatasetItem();
      return;
   }

   mpCurrentDataset = pImportDescriptor;

   // Destroy the existing edit data descriptor if necessary
   Service<ModelServices> pModel;
   if (mpEditDescriptor != NULL)
   {
      Classification* pClassification = mpEditDescriptor->getClassification();
      if (pClassification != NULL)
      {
         VERIFYNR(pClassification->detach(SIGNAL_NAME(Subject, Modified),
            Slot(this, &ImportOptionsDlg::editClassificationModified)));
      }

      RasterDataDescriptor* pRasterDescriptor = dynamic_cast<RasterDataDescriptor*>(mpEditDescriptor);
      if (pRasterDescriptor != NULL)
      {
         VERIFYNR(pRasterDescriptor->detach(SIGNAL_NAME(RasterDataDescriptor, RowsChanged),
            Slot(this, &ImportOptionsDlg::editDataDescriptorRowsModified)));
         VERIFYNR(pRasterDescriptor->detach(SIGNAL_NAME(RasterDataDescriptor, ColumnsChanged),
            Slot(this, &ImportOptionsDlg::editDataDescriptorColumnsModified)));
         VERIFYNR(pRasterDescriptor->detach(SIGNAL_NAME(RasterDataDescriptor, BandsChanged),
            Slot(this, &ImportOptionsDlg::editDataDescriptorBandsModified)));
      }

      RasterFileDescriptor* pRasterFileDescriptor =
         dynamic_cast<RasterFileDescriptor*>(mpEditDescriptor->getFileDescriptor());
      if (pRasterFileDescriptor != NULL)
      {
         VERIFYNR(pRasterFileDescriptor->detach(SIGNAL_NAME(RasterFileDescriptor, RowsChanged),
            Slot(this, &ImportOptionsDlg::editFileDescriptorRowsModified)));
         VERIFYNR(pRasterFileDescriptor->detach(SIGNAL_NAME(RasterFileDescriptor, ColumnsChanged),
            Slot(this, &ImportOptionsDlg::editFileDescriptorColumnsModified)));
         VERIFYNR(pRasterFileDescriptor->detach(SIGNAL_NAME(RasterFileDescriptor, BandsChanged),
            Slot(this, &ImportOptionsDlg::editFileDescriptorBandsModified)));
      }

      VERIFYNR(mpEditDescriptor->detach(SIGNAL_NAME(Subject, Modified),
         Slot(this, &ImportOptionsDlg::editDataDescriptorModified)));
      pModel->destroyDataDescriptor(mpEditDescriptor);
      mpEditDescriptor = NULL;
      mEditDataDescriptorModified = false;
   }

   // Create a new data descriptor to validate the user inputs
   DataDescriptor* pDescriptor = mpCurrentDataset->getDataDescriptor();
   if (pDescriptor != NULL)
   {
      mpEditDescriptor = pDescriptor->copy();
   }

   VERIFYNRV(mpEditDescriptor != NULL);
   VERIFYNR(mpEditDescriptor->attach(SIGNAL_NAME(Subject, Modified),
      Slot(this, &ImportOptionsDlg::editDataDescriptorModified)));

   RasterDataDescriptor* pRasterDescriptor = dynamic_cast<RasterDataDescriptor*>(mpEditDescriptor);
   FileDescriptor* pFileDescriptor = mpEditDescriptor->getFileDescriptor();
   RasterFileDescriptor* pRasterFileDescriptor = dynamic_cast<RasterFileDescriptor*>(pFileDescriptor);

   if (pRasterDescriptor != NULL)
   {
      VERIFYNR(pRasterDescriptor->attach(SIGNAL_NAME(RasterDataDescriptor, RowsChanged),
         Slot(this, &ImportOptionsDlg::editDataDescriptorRowsModified)));
      VERIFYNR(pRasterDescriptor->attach(SIGNAL_NAME(RasterDataDescriptor, ColumnsChanged),
         Slot(this, &ImportOptionsDlg::editDataDescriptorColumnsModified)));
      VERIFYNR(pRasterDescriptor->attach(SIGNAL_NAME(RasterDataDescriptor, BandsChanged),
         Slot(this, &ImportOptionsDlg::editDataDescriptorBandsModified)));
   }

   if (pRasterFileDescriptor != NULL)
   {
      VERIFYNR(pRasterFileDescriptor->attach(SIGNAL_NAME(RasterFileDescriptor, RowsChanged),
         Slot(this, &ImportOptionsDlg::editFileDescriptorRowsModified)));
      VERIFYNR(pRasterFileDescriptor->attach(SIGNAL_NAME(RasterFileDescriptor, ColumnsChanged),
         Slot(this, &ImportOptionsDlg::editFileDescriptorColumnsModified)));
      VERIFYNR(pRasterFileDescriptor->attach(SIGNAL_NAME(RasterFileDescriptor, BandsChanged),
         Slot(this, &ImportOptionsDlg::editFileDescriptorBandsModified)));
   }

   // Select the tree widget item for the current data set
   selectCurrentDatasetItem();

   // Disconnect pages
   updateConnections(false);

   // Subset page
   if (pRasterFileDescriptor != NULL)
   {
      // Show the tab if necessary
      if (mpTabWidget->indexOf(mpSubsetPage) == -1)
      {
         mpTabWidget->insertTab(2, mpSubsetPage, "Subset");
      }

      // Rows
      const vector<DimensionDescriptor>& rows = pRasterFileDescriptor->getRows();
      const vector<DimensionDescriptor>& loadedRows = pRasterDescriptor->getRows();
      mpSubsetPage->setRows(rows, loadedRows);

      // Columns
      const vector<DimensionDescriptor>& columns = pRasterFileDescriptor->getColumns();
      const vector<DimensionDescriptor>& loadedColumns = pRasterDescriptor->getColumns();
      mpSubsetPage->setColumns(columns, loadedColumns);

      // Bands
      const vector<DimensionDescriptor>& bands = pRasterFileDescriptor->getBands();
      const vector<DimensionDescriptor>& selectedBands = pRasterDescriptor->getBands();
      setSubsetBands(bands, selectedBands);

      // Initial bad band file directory
      if (pFileDescriptor != NULL)
      {
         QString strDirectory;

         string filename = pFileDescriptor->getFilename();
         if (filename.empty() == false)
         {
            QFileInfo fileInfo(QString::fromStdString(filename));
            strDirectory = fileInfo.absolutePath();
         }

         mpSubsetPage->setBadBandFileDirectory(strDirectory);
      }
   }
   else
   {
      // Remove the subset page, since the file descriptor either isn't
      // present or isn't a RasterFileDescriptor, just a FileDescriptor
      int index = mpTabWidget->indexOf(mpSubsetPage);
      if (index != -1)
      {
         mpTabWidget->removeTab(index);
      }
   }

   // Data descriptor page - enable editing for all fields
   mpDataPage->setDataDescriptor(mpEditDescriptor, true);

   // File descriptor page
   bool editFilePage = false;
   if (pRasterFileDescriptor != NULL)
   {
      unsigned int numRows = pRasterFileDescriptor->getRowCount();
      unsigned int numColumns = pRasterFileDescriptor->getColumnCount();
      unsigned int bitsPerElement = pRasterFileDescriptor->getBitsPerElement();
      unsigned int numBands = pRasterFileDescriptor->getBandCount();
      if ((numRows == 0) || (numColumns == 0) || (numBands == 0) || (bitsPerElement == 0))
      {
         editFilePage = true;
      }
   }

   mpFilePage->setFileDescriptor(pFileDescriptor, editFilePage);

   int iIndex = mpTabWidget->indexOf(mpFilePage);
   if (iIndex != -1)
   {
      if (pFileDescriptor == NULL)
      {
         mpTabWidget->removeTab(iIndex);
      }
   }
   else
   {
      if (pFileDescriptor != NULL)
      {
         mpTabWidget->insertTab(1, mpFilePage, "File");
      }
   }

   // Classification page
   updateClassificationLabel();

   Classification* pClassification = mpEditDescriptor->getClassification();
   if (pClassification != NULL)
   {
      VERIFYNR(pClassification->attach(SIGNAL_NAME(Subject, Modified),
         Slot(this, &ImportOptionsDlg::editClassificationModified)));
      mpClassificationPage->setClassification(pClassification);
   }

   // Metadata page
   mpMetadataPage->setMetadata(mpEditDescriptor->getMetadata());

   // Wavelengths page
   bool bWavelengthsPageActive = false;
   if (mpTabWidget->currentWidget() == mpWavelengthsPage)
   {
      bWavelengthsPageActive = true;
   }

   int index = mpTabWidget->indexOf(mpWavelengthsPage);
   if (index != -1)
   {
      mpTabWidget->removeTab(index);
   }

   if (pRasterFileDescriptor != NULL)
   {
      // Populate the wavelengths with the file descriptor bands since the metadata wavelengths
      // apply to all bands in the file
      mpWavelengthsPage->setWavelengths(pRasterFileDescriptor->getBands(), mpEditDescriptor->getMetadata());

      if (pRasterDescriptor != NULL)
      {
         mpWavelengthsPage->highlightActiveBands(pRasterDescriptor->getBands());
      }

      mpTabWidget->addTab(mpWavelengthsPage, "Wavelengths");

      if (bWavelengthsPageActive == true)
      {
         mpTabWidget->setCurrentWidget(mpWavelengthsPage);
      }
   }

   // Importer page
   bool bImporterPageActive = false;
   if (mpImporterPage != NULL)
   {
      if (mpTabWidget->currentWidget() == mpImporterPage)
      {
         bImporterPageActive = true;
      }
   }

   removeImporterPage();

   if (mpImporter != NULL)
   {
      mpImporterPage = mpImporter->getImportOptionsWidget(mpEditDescriptor);
      if (mpImporterPage != NULL)
      {
         QLayout* pLayout = mpImporterPage->layout();
         if (pLayout != NULL)
         {
            if (pLayout->margin() <= 0)
            {
               pLayout->setMargin(10);
            }
         }

         QString strCaption = mpImporterPage->windowTitle();
         if (strCaption.isEmpty() == true)
         {
            strCaption = "Importer";
         }

         mpTabWidget->addTab(mpImporterPage, strCaption);

         if (bImporterPageActive == true)
         {
            mpTabWidget->setCurrentWidget(mpImporterPage);
         }
      }

      // Set the valid processing locations on the data page.  This must be done after getting the import options
      // widget from the importer so that the auto importer will correctly query the importer that is used.
      // This can be changed if the importer design (and auto importer) is modified to support valid processing
      // locations for a specific data set.
      vector<ProcessingLocation> locations;
      if (mpImporter->isProcessingLocationSupported(IN_MEMORY) == true)
      {
         locations.push_back(IN_MEMORY);
      }

      if (mpImporter->isProcessingLocationSupported(ON_DISK) == true)
      {
         locations.push_back(ON_DISK);
      }

      if (mpImporter->isProcessingLocationSupported(ON_DISK_READ_ONLY) == true)
      {
         locations.push_back(ON_DISK_READ_ONLY);
      }

      mpDataPage->setValidProcessingLocations(locations);
   }

   // Validate the current data descriptor
   validateEditDataset();

   // Reconnect the pages
   updateConnections(true);

   // Notify connected objects
   emit currentDatasetChanged(mpCurrentDataset);
}
Exemple #9
0
bool Jpeg2000Importer::populateDataDescriptor(RasterDataDescriptor* pDescriptor)
{
   if (pDescriptor == NULL)
   {
      return false;
   }

   RasterFileDescriptor* pFileDescriptor = dynamic_cast<RasterFileDescriptor*>(pDescriptor->getFileDescriptor());
   VERIFY(pFileDescriptor != NULL);

   const string& fileName = pFileDescriptor->getFilename();
   if (fileName.empty() == true)
   {
      return false;
   }

   opj_image_t* pImage = getImageInfo(fileName, true);
   if (pImage == NULL)
   {
      return false;
   }

   // Bits per element
   unsigned int bitsPerElement = pImage->comps->prec;
   pFileDescriptor->setBitsPerElement(bitsPerElement);

   // Data type
   EncodingType dataType = INT1UBYTE;
   if (bitsPerElement <= 8)
   {
      if (pImage->comps->sgnd)
      {
         dataType = INT1SBYTE;
      }
      else
      {
         dataType = INT1UBYTE;
      }
   }
   else if (bitsPerElement <= 16)
   {
      if (pImage->comps->sgnd)
      {
         dataType = INT2SBYTES;
      }
      else
      {
         dataType = INT2UBYTES;
      }
   }
   else if (bitsPerElement <= 32)
   {
      if (pImage->comps->sgnd)
      {
         dataType = INT4SBYTES;
      }
      else
      {
         dataType = INT4UBYTES;
      }
   }
   else if (bitsPerElement <= 64)
   {
      dataType = FLT8BYTES;
   }

   // Override with information from the filename, if present.
   unsigned int bandFactor = 0;
   QStringList parts = QString::fromStdString(fileName).split('.');
   foreach (QString part, parts)
   {
      bool error;
      EncodingType dataTypeTemp = StringUtilities::fromXmlString<EncodingType>(part.toStdString(), &error);
      if (dataTypeTemp.isValid() == true && error == false)
      {
         bandFactor = Jpeg2000Utilities::get_num_bands(dataTypeTemp);
         if (bandFactor != 0)
         {
            dataType = dataTypeTemp;
            break;
         }
      }
   }
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;
}
bool FileDescriptorWidget::applyToFileDescriptor(FileDescriptor* pFileDescriptor)
{
   if (mReadOnly == true)
   {
      return true;
   }

   if (mModified == false)
   {
      return true;
   }

   if (pFileDescriptor == NULL)
   {
      return true;
   }

   // Endian
   QString strEndian = getDescriptorValue("Endian");
   if (strEndian.isEmpty() == false)
   {
      bool bError = true;
      EndianType endian = StringUtilities::fromDisplayString<EndianType>(strEndian.toStdString(), &bError);
      if (bError == false)
      {
         pFileDescriptor->setEndian(endian);
      }
   }

   // Raster element file descriptor items
   RasterFileDescriptor* pRasterDescriptor = dynamic_cast<RasterFileDescriptor*>(pFileDescriptor);
   if (pRasterDescriptor == NULL)
   {
      return true;
   }

   // Bits per element
   QString strBitsPerElement = getDescriptorValue("Bits Per Element");
   if (strBitsPerElement.isEmpty() == false)
   {
      unsigned int bitsPerElement = strBitsPerElement.toUInt();
      pRasterDescriptor->setBitsPerElement(bitsPerElement);
   }

   // Header bytes
   QString strHeaderBytes = getDescriptorValue("Header Bytes");
   if (strHeaderBytes.isEmpty() == false)
   {
      unsigned int headerBytes = strHeaderBytes.toUInt();
      pRasterDescriptor->setHeaderBytes(headerBytes);
   }

   // Trailer bytes
   QString strTrailerBytes = getDescriptorValue("Trailer Bytes");
   if (strTrailerBytes.isEmpty() == false)
   {
      unsigned int trailerBytes = strTrailerBytes.toUInt();
      pRasterDescriptor->setTrailerBytes(trailerBytes);
   }

   // Preline bytes
   QString strPrelineBytes = getDescriptorValue("Preline Bytes");
   if (strPrelineBytes.isEmpty() == false)
   {
      unsigned int prelineBytes = strPrelineBytes.toUInt();
      pRasterDescriptor->setPrelineBytes(prelineBytes);
   }

   // Postline bytes
   QString strPostlineBytes = getDescriptorValue("Postline Bytes");
   if (strPostlineBytes.isEmpty() == false)
   {
      unsigned int postlineBytes = strPostlineBytes.toUInt();
      pRasterDescriptor->setPostlineBytes(postlineBytes);
   }

   // Pixel size
   QString strPixelSize = getDescriptorValue("X Pixel Size");
   if (strPixelSize.isEmpty() == false)
   {
      pRasterDescriptor->setXPixelSize(strPixelSize.toDouble());
   }

   strPixelSize = getDescriptorValue("Y Pixel Size");
   if (strPixelSize.isEmpty() == false)
   {
      pRasterDescriptor->setYPixelSize(strPixelSize.toDouble());
   }

   // Units
   Units* pUnits = pRasterDescriptor->getUnits();
   if (pUnits != NULL)
   {
      // Name
      QString strUnitsName = getDescriptorValue("Name");
      if (strUnitsName.isEmpty() == false)
      {
         pUnits->setUnitName(strUnitsName.toStdString());
      }

      // Type
      QString strUnitsType = getDescriptorValue("Type");
      if (strUnitsType.isEmpty() == false)
      {
         UnitType unitType;

         bool bError = true;
         unitType = StringUtilities::fromDisplayString<UnitType>(strUnitsType.toStdString(), &bError);
         if (bError == false)
         {
            pUnits->setUnitType(unitType);
         }
      }

      // Scale
      QString strUnitsScale = getDescriptorValue("Scale");
      if (strUnitsScale.isEmpty() == false)
      {
         double dScale = strUnitsScale.toDouble();
         pUnits->setScaleFromStandard(dScale);
      }

      // Range minimum
      QString strMinimum = getDescriptorValue("Range Minimum");
      if (strMinimum.isEmpty() == false)
      {
         double dMinimum = strMinimum.toDouble();
         pUnits->setRangeMin(dMinimum);
      }

      // Range maximum
      QString strMaximum = getDescriptorValue("Range Maximum");
      if (strMaximum.isEmpty() == false)
      {
         double dMaximum = strMaximum.toDouble();
         pUnits->setRangeMax(dMaximum);
      }
   }

   // Interleave format
   QString strInterleave = getDescriptorValue("Interleave Format");
   if (strInterleave.isEmpty() == false)
   {
      bool bError = true;
      string interleaveVal = strInterleave.toStdString();
      InterleaveFormatType interleave;
      if ((interleaveVal == StringUtilities::toDisplayString(BSQ) + BSQ_SINGLE_SUFFIX) ||
          (interleaveVal == StringUtilities::toDisplayString(BSQ) + BSQ_MULTI_SUFFIX))
      {
         interleave = BSQ;
         bError = false;
      }
      else
      {
         interleave = StringUtilities::fromDisplayString<InterleaveFormatType>(interleaveVal, &bError);
      }
      if (bError == false)
      {
         pRasterDescriptor->setInterleaveFormat(interleave);
      }
   }

   // Band files
   vector<string> bandFiles;

   QTreeWidgetItem* pFilenameItem = getDescriptorItem("Filename");
   if (pFilenameItem != NULL)
   {
      bool bMultipleFiles = false;
      for (int i = 0; i < pFilenameItem->childCount(); ++i)
      {
         QTreeWidgetItem* pBandFileItem = pFilenameItem->child(i);
         if (pBandFileItem != NULL)
         {
            string bandFile;

            QString strBandFile = pBandFileItem->text(1);
            if (strBandFile.isEmpty() == false)
            {
               bandFile = strBandFile.toStdString();
               bMultipleFiles = true;
            }

            bandFiles.push_back(bandFile);
         }
      }

      if (bMultipleFiles == false)
      {
         bandFiles.clear();
      }
   }

   pRasterDescriptor->setBandFiles(bandFiles);

   // Preband bytes
   QString strPrebandBytes = getDescriptorValue("Preband Bytes");
   if (strPrebandBytes.isEmpty() == false)
   {
      unsigned int prebandBytes = strPrebandBytes.toUInt();
      pRasterDescriptor->setPrebandBytes(prebandBytes);
   }

   // Postband bytes
   QString strPostbandBytes = getDescriptorValue("Postband Bytes");
   if (strPostbandBytes.isEmpty() == false)
   {
      unsigned int postbandBytes = strPostbandBytes.toUInt();
      pRasterDescriptor->setPostbandBytes(postbandBytes);
   }

   return true;
}
void FileDescriptorWidget::initialize()
{
   mpTreeWidget->clear();
   mpGcpTree->clear();
   mpGcpGroup->hide();

   if (mpFileDescriptor == NULL)
   {
      return;
   }

   // Filename
   QTreeWidgetItem* pFilenameItem = new QTreeWidgetItem(mpTreeWidget);
   if (pFilenameItem != NULL)
   {
      string filename = mpFileDescriptor->getFilename();

      pFilenameItem->setText(0, "Filename");
      pFilenameItem->setText(1, QString::fromStdString(filename));
   }

   // Data set location
   QTreeWidgetItem* pDatasetLocationItem = new QTreeWidgetItem(mpTreeWidget);
   if (pDatasetLocationItem != NULL)
   {
      string datasetLocation = mpFileDescriptor->getDatasetLocation();

      pDatasetLocationItem->setText(0, "Data Set Location");
      pDatasetLocationItem->setText(1, QString::fromStdString(datasetLocation));
   }

   // Endian
   QTreeWidgetItem* pEndianItem = new QTreeWidgetItem(mpTreeWidget);
   if (pEndianItem != NULL)
   {
      EndianType endian = mpFileDescriptor->getEndian();
      string endianText = StringUtilities::toDisplayString(endian);

      pEndianItem->setText(0, "Endian");
      pEndianItem->setText(1, QString::fromStdString(endianText));

      if (mReadOnly == false)
      {
         QComboBox* pEndianCombo = new QComboBox(mpTreeWidget);
         pEndianCombo->setEditable(false);
         pEndianCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(LITTLE_ENDIAN_ORDER)));
         pEndianCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(BIG_ENDIAN_ORDER)));
         pEndianCombo->hide();

         mpTreeWidget->setCellWidgetType(pEndianItem, 1, CustomTreeWidget::COMBO_BOX);
         mpTreeWidget->setComboBox(pEndianItem, 1, pEndianCombo);
      }
   }

   // Raster element file descriptor items
   RasterFileDescriptor* pRasterDescriptor = dynamic_cast<RasterFileDescriptor*>(mpFileDescriptor);
   if (pRasterDescriptor == NULL)
   {
      return;
   }

   mpGcpGroup->show();

   // Rows
   QTreeWidgetItem* pRowsItem = new QTreeWidgetItem();
   if (pRowsItem != NULL)
   {
      unsigned int rows = pRasterDescriptor->getRowCount();

      pRowsItem->setText(0, "Rows");
      pRowsItem->setText(1, QString::number(rows));

      mpTreeWidget->insertTopLevelItem(2, pRowsItem);
      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pRowsItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Columns
   QTreeWidgetItem* pColumnsItem = new QTreeWidgetItem();
   if (pColumnsItem != NULL)
   {
      unsigned int columns = pRasterDescriptor->getColumnCount();

      pColumnsItem->setText(0, "Columns");
      pColumnsItem->setText(1, QString::number(columns));

      mpTreeWidget->insertTopLevelItem(3, pColumnsItem);
      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pColumnsItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Bits per element
   QTreeWidgetItem* pBitsPerElementItem = new QTreeWidgetItem();
   if (pBitsPerElementItem != NULL)
   {
      unsigned int bitsPerElement = pRasterDescriptor->getBitsPerElement();

      pBitsPerElementItem->setText(0, "Bits Per Element");
      pBitsPerElementItem->setText(1, QString::number(bitsPerElement));

      mpTreeWidget->insertTopLevelItem(4, pBitsPerElementItem);
      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pBitsPerElementItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Header bytes
   QTreeWidgetItem* pHeaderBytesItem = new QTreeWidgetItem(mpTreeWidget);
   if (pHeaderBytesItem != NULL)
   {
      unsigned int headerBytes = pRasterDescriptor->getHeaderBytes();

      pHeaderBytesItem->setText(0, "Header Bytes");
      pHeaderBytesItem->setText(1, QString::number(headerBytes));

      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pHeaderBytesItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Trailer bytes
   QTreeWidgetItem* pTrailerBytesItem = new QTreeWidgetItem(mpTreeWidget);
   if (pTrailerBytesItem != NULL)
   {
      unsigned int trailerBytes = pRasterDescriptor->getTrailerBytes();

      pTrailerBytesItem->setText(0, "Trailer Bytes");
      pTrailerBytesItem->setText(1, QString::number(trailerBytes));

      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pTrailerBytesItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Preline bytes
   QTreeWidgetItem* pPrelineBytesItem = new QTreeWidgetItem(mpTreeWidget);
   if (pPrelineBytesItem != NULL)
   {
      unsigned int prelineBytes = pRasterDescriptor->getPrelineBytes();

      pPrelineBytesItem->setText(0, "Preline Bytes");
      pPrelineBytesItem->setText(1, QString::number(prelineBytes));

      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pPrelineBytesItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Postline bytes
   QTreeWidgetItem* pPostlineBytesItem = new QTreeWidgetItem(mpTreeWidget);
   if (pPostlineBytesItem != NULL)
   {
      unsigned int postlineBytes = pRasterDescriptor->getPostlineBytes();

      pPostlineBytesItem->setText(0, "Postline Bytes");
      pPostlineBytesItem->setText(1, QString::number(postlineBytes));

      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pPostlineBytesItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Pixel size
   QTreeWidgetItem* pXPixelSizeItem = new QTreeWidgetItem(mpTreeWidget);
   if (pXPixelSizeItem != NULL)
   {
      double pixelSize = pRasterDescriptor->getXPixelSize();

      pXPixelSizeItem->setText(0, "X Pixel Size");
      pXPixelSizeItem->setText(1, QString::number(pixelSize));

      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pXPixelSizeItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   QTreeWidgetItem* pYPixelSizeItem = new QTreeWidgetItem(mpTreeWidget);
   if (pYPixelSizeItem != NULL)
   {
      double pixelSize = pRasterDescriptor->getYPixelSize();

      pYPixelSizeItem->setText(0, "Y Pixel Size");
      pYPixelSizeItem->setText(1, QString::number(pixelSize));

      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pYPixelSizeItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Units
   const Units* pUnits = pRasterDescriptor->getUnits();
   if (pUnits != NULL)
   {
      QTreeWidgetItem* pUnitsItem = new QTreeWidgetItem(mpTreeWidget);
      if (pUnitsItem != NULL)
      {
         pUnitsItem->setText(0, "Units");
         pUnitsItem->setBackgroundColor(1, Qt::lightGray);

         // Name
         QTreeWidgetItem* pNameItem = new QTreeWidgetItem(pUnitsItem);
         if (pNameItem != NULL)
         {
            string unitsName = pUnits->getUnitName();

            pNameItem->setText(0, "Name");
            pNameItem->setText(1, QString::fromStdString(unitsName));

            if (mReadOnly == false)
            {
               mpTreeWidget->setCellWidgetType(pNameItem, 1, CustomTreeWidget::LINE_EDIT);
            }
         }

         // Type
         QTreeWidgetItem* pTypeItem = new QTreeWidgetItem(pUnitsItem);
         if (pTypeItem != NULL)
         {
            UnitType unitType = pUnits->getUnitType();
            string unitTypeText = StringUtilities::toDisplayString(unitType);

            pTypeItem->setText(0, "Type");
            pTypeItem->setText(1, QString::fromStdString(unitTypeText));

            if (mReadOnly == false)
            {
               QComboBox* pUnitTypeCombo = new QComboBox(mpTreeWidget);
               pUnitTypeCombo->setEditable(false);
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(ABSORBANCE)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(ABSORPTANCE)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(DIGITAL_NO)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(DISTANCE)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(EMISSIVITY)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(RADIANCE)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(REFLECTANCE)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(REFLECTANCE_FACTOR)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(TRANSMITTANCE)));
               pUnitTypeCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(CUSTOM_UNIT)));
               pUnitTypeCombo->hide();

               mpTreeWidget->setCellWidgetType(pTypeItem, 1, CustomTreeWidget::COMBO_BOX);
               mpTreeWidget->setComboBox(pTypeItem, 1, pUnitTypeCombo);
            }
         }

         // Scale
         QTreeWidgetItem* pScaleItem = new QTreeWidgetItem(pUnitsItem);
         if (pScaleItem != NULL)
         {
            double dScale = pUnits->getScaleFromStandard();

            pScaleItem->setText(0, "Scale");
            pScaleItem->setText(1, QString::number(dScale));

            if (mReadOnly == false)
            {
               mpTreeWidget->setCellWidgetType(pScaleItem, 1, CustomTreeWidget::LINE_EDIT);
            }
         }

         // Range minimum
         QTreeWidgetItem* pMinimumItem = new QTreeWidgetItem(pUnitsItem);
         if (pMinimumItem != NULL)
         {
            double dMinimum = pUnits->getRangeMin();

            pMinimumItem->setText(0, "Range Minimum");
            pMinimumItem->setText(1, QString::number(dMinimum));

            if (mReadOnly == false)
            {
               mpTreeWidget->setCellWidgetType(pMinimumItem, 1, CustomTreeWidget::LINE_EDIT);
            }
         }

         // Range maximum
         QTreeWidgetItem* pMaximumItem = new QTreeWidgetItem(pUnitsItem);
         if (pMaximumItem != NULL)
         {
            double dMaximum = pUnits->getRangeMax();

            pMaximumItem->setText(0, "Range Maximum");
            pMaximumItem->setText(1, QString::number(dMaximum));

            if (mReadOnly == false)
            {
               mpTreeWidget->setCellWidgetType(pMaximumItem, 1, CustomTreeWidget::LINE_EDIT);
            }
         }
      }
   }

   // GCPs
   if (mpGcpTree != NULL)
   {
      const list<GcpPoint>& gcps = pRasterDescriptor->getGcps();
      if (gcps.empty() == false)
      {
         list<GcpPoint>::const_iterator iter;
         unsigned int i = 0;

         for (iter = gcps.begin(), i = 0; iter != gcps.end(); ++iter, ++i)
         {
            GcpPoint gcp = *iter;

            QTreeWidgetItem* pGcpItem = new QTreeWidgetItem(mpGcpTree);
            if (pGcpItem != NULL)
            {
               QString strLatitude;
               QString strLongitude;
               LatLonPoint latLonPoint(gcp.mCoordinate);

               string latText = latLonPoint.getLatitudeText();
               if (latText.empty() == false)
               {
                  strLatitude = QString::fromStdString(latText);
               }

               string longText = latLonPoint.getLongitudeText();
               if (longText.empty() == false)
               {
                  strLongitude = QString::fromStdString(longText);
               }

               pGcpItem->setText(0, QString("GCP ") + QString::number(i + 1));
               pGcpItem->setText(1, QString::number(gcp.mPixel.mX + 1.0));
               pGcpItem->setText(2, QString::number(gcp.mPixel.mY + 1.0));
               pGcpItem->setText(3, strLatitude);
               pGcpItem->setText(4, strLongitude);
            }
         }

         mpGcpTree->setEnabled(true);
      }
      else
      {
         mpGcpTree->setEnabled(false);
      }
   }

   // Bands
   QTreeWidgetItem* pBandsItem = new QTreeWidgetItem();
   if (pBandsItem != NULL)
   {
      unsigned int bands = pRasterDescriptor->getBandCount();

      pBandsItem->setText(0, "Bands");
      pBandsItem->setText(1, QString::number(bands));

      mpTreeWidget->insertTopLevelItem(4, pBandsItem);
      if (mReadOnly == false)
      {
         mpTreeWidget->setCellWidgetType(pBandsItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Interleave format
   InterleaveFormatType interleave = pRasterDescriptor->getInterleaveFormat();

   QTreeWidgetItem* pInterleaveItem = new QTreeWidgetItem();
   if (pInterleaveItem != NULL)
   {
      string interleaveText = StringUtilities::toDisplayString(interleave);
      if (interleave == BSQ)
      {
         const vector<const Filename*>& bandFiles = pRasterDescriptor->getBandFiles();
         if (bandFiles.size() > 0)
         {
            interleaveText += BSQ_MULTI_SUFFIX;
         }
         else
         {
            interleaveText += BSQ_SINGLE_SUFFIX;
         }
      }
      pInterleaveItem->setText(0, "Interleave Format");
      pInterleaveItem->setText(1, QString::fromStdString(interleaveText));

      mpTreeWidget->insertTopLevelItem(7, pInterleaveItem);
      if (mReadOnly == false)
      {
         QComboBox* pInterleaveCombo = new QComboBox(mpTreeWidget);
         pInterleaveCombo->setEditable(false);
         pInterleaveCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(BIL)));
         pInterleaveCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(BIP)));
         pInterleaveCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(BSQ) + BSQ_SINGLE_SUFFIX));
         pInterleaveCombo->addItem(QString::fromStdString(StringUtilities::toDisplayString(BSQ) + BSQ_MULTI_SUFFIX));
         pInterleaveCombo->hide();

         mpTreeWidget->setCellWidgetType(pInterleaveItem, 1, CustomTreeWidget::COMBO_BOX);
         mpTreeWidget->setComboBox(pInterleaveItem, 1, pInterleaveCombo);
      }
   }

   // Band files
   const vector<const Filename*>& bandFiles = pRasterDescriptor->getBandFiles();
   for (unsigned int i = 0; i < bandFiles.size(); ++i)
   {
      string bandFilename = bandFiles[i]->getFullPathAndName();
      if (bandFilename.empty() == false)
      {
         QTreeWidgetItem* pBandItem = new QTreeWidgetItem(pFilenameItem);
         if (pBandItem != NULL)
         {
            pBandItem->setText(0, QString::number(i + 1));
            pBandItem->setText(1, QString::fromStdString(bandFilename));

            if (mReadOnly == false)
            {
               mpTreeWidget->setCellWidgetType(pBandItem, 1, CustomTreeWidget::BROWSE_FILE_EDIT);
               mpTreeWidget->setFileBrowser(pBandItem, 1, mpFileBrowser);
            }
         }
      }
   }

   // Preband bytes
   QTreeWidgetItem* pPrebandBytesItem = new QTreeWidgetItem();
   if (pPrebandBytesItem != NULL)
   {
      QString strPrebandBytes;
      QColor cellColor = Qt::lightGray;

      if (interleave == BSQ)
      {
         strPrebandBytes = QString::number(pRasterDescriptor->getPrebandBytes());
         cellColor = Qt::white;
      }

      pPrebandBytesItem->setText(0, "Preband Bytes");
      pPrebandBytesItem->setText(1, strPrebandBytes);
      pPrebandBytesItem->setBackgroundColor(1, cellColor);

      mpTreeWidget->insertTopLevelItem(12, pPrebandBytesItem);
      if ((mReadOnly == false) && (interleave == BSQ))
      {
         mpTreeWidget->setCellWidgetType(pPrebandBytesItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }

   // Postband bytes
   QTreeWidgetItem* pPostbandBytesItem = new QTreeWidgetItem();
   if (pPostbandBytesItem != NULL)
   {
      QString strPostbandBytes;
      QColor cellColor = Qt::lightGray;

      if (interleave == BSQ)
      {
         strPostbandBytes = QString::number(pRasterDescriptor->getPostbandBytes());
         cellColor = Qt::white;
      }

      pPostbandBytesItem->setText(0, "Postband Bytes");
      pPostbandBytesItem->setText(1, strPostbandBytes);
      pPostbandBytesItem->setBackgroundColor(1, cellColor);

      mpTreeWidget->insertTopLevelItem(13, pPostbandBytesItem);
      if ((mReadOnly == false) && (interleave == BSQ))
      {
         mpTreeWidget->setCellWidgetType(pPostbandBytesItem, 1, CustomTreeWidget::LINE_EDIT);
      }
   }
}
bool IceExporterShell::execute(PlugInArgList* pInArgList, PlugInArgList* pOutArgList)
{
   string filename;

   try
   {
      // Set up subclasses
      parseInputArgs(pInArgList);

      // Get the RasterElement and RasterFileDescriptor
      RasterElement* pOutputCube = NULL;
      RasterFileDescriptor* pOutputFileDescriptor = NULL;
      getOutputCubeAndFileDescriptor(pOutputCube, pOutputFileDescriptor);
      ICEVERIFY_MSG(pOutputCube != NULL, "No Raster Element specified.");
      ICEVERIFY_MSG(pOutputFileDescriptor != NULL, "No Raster File Descriptor specified.");

      RasterDataDescriptor* pRasterDescriptor = dynamic_cast<RasterDataDescriptor*>(pOutputCube->getDataDescriptor());
      ICEVERIFY_MSG(pRasterDescriptor != NULL, "Raster Element is invalid.");

      // Open the file for writing
      filename = pOutputFileDescriptor->getFilename().getFullPathAndName();
      Hdf5FileResource fileResource(H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT));
      ICEVERIFY_MSG(*fileResource >= 0, "Unable to create file " + filename)

      IceWriter writer(*fileResource, mFileType);
      mpWriter = &writer;
      if (mpOptionsWidget.get() != NULL)
      {
         writer.setChunkSize(mpOptionsWidget->getChunkSize() * 1024 * 1024);
         writer.setCompressionType(mpOptionsWidget->getCompressionType());
         writer.setGzipCompressionLevel(mpOptionsWidget->getGzipCompressionLevel());
      }
      if ((pRasterDescriptor->getDataType() == INT4SCOMPLEX || pRasterDescriptor->getDataType() == FLT8COMPLEX)
       && (writer.getCompressionType() == GZIP || writer.getCompressionType() == SHUFFLE_AND_GZIP))
      {
         std::string msgtxt = "Compression not supported with complex data types, data will not be compressed.";
         MessageResource msg(msgtxt, "app", "{7B050EE4-D025-43b2-AD8F-DF8E28FA8551}");
         if (mpProgress != NULL)
         {
            mpProgress->updateProgress(msgtxt, 1, WARNING);
         }
      }

      writer.writeFileHeader();
      abortIfNecessary();

      // Write the cube to the file
      writer.writeCube(outputCubePath(), pOutputCube, pOutputFileDescriptor, mpProgress);
      abortIfNecessary();

      // Allow subclasses to write class-specific information to the file
      finishWriting(writer);
      abortIfNecessary();

      // Finished
      mpWriter = NULL;
      if (mpProgress != NULL)
      {
         mpProgress->updateProgress("Ice export complete.", 100, NORMAL);
      }
   }

   catch (const IceException& ex)
   {
      if (mpProgress != NULL)
      {
         string msg = ex.getFailureMessage();
         if (msg.empty())
         {
            msg = "Unknown error. Failed to create file.";
         }

         mpProgress->updateProgress(msg, 0, ERRORS);
      }

      ex.addToMessageLog();
      if (filename.empty() == false)
      {
         remove(filename.c_str());
      }

      mpWriter = NULL;
      return false;
   }

   catch (const IceAbortException&)
   {
      if (mpProgress != NULL)
      {
         mpProgress->updateProgress("Ice export aborted.", 0, ABORT);
      }

      if (filename.empty() == false)
      {
         remove(filename.c_str());
      }

      mpWriter = NULL;
      return false;
   }

   return true;
}
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;
}