コード例 #1
0
ファイル: EngrdaWidget.cpp プロジェクト: Siddharthk/opticks
void EngrdaWidget::updateData(QTreeWidgetItem* pItem)
{
   if (pItem != NULL && pItem->childCount() == 0)
   {
      mpValueType->setEnabled(true);
      mpDataUnits->setEnabled(true);
      mpData->setEnabled(true);
      DynamicObject* pDo = reinterpret_cast<DynamicObject*>(qvariant_cast<void*>(pItem->data(0, Qt::UserRole)));
      try
      {
         if (pDo != NULL)
         {
            Endian endian(BIG_ENDIAN_ORDER);
            unsigned int cols = dv_cast<unsigned int>(pDo->getAttribute(Nitf::TRE::ENGRDA::ENGMTXC));
            unsigned int rows = dv_cast<unsigned int>(pDo->getAttribute(Nitf::TRE::ENGRDA::ENGMTXR));
            std::string type = dv_cast<std::string>(pDo->getAttribute(Nitf::TRE::ENGRDA::ENGTYP));
            std::string units = dv_cast<std::string>(pDo->getAttribute(Nitf::TRE::ENGRDA::ENGDATU));
            unsigned int dts = dv_cast<unsigned int>(pDo->getAttribute(Nitf::TRE::ENGRDA::ENGDTS));
            if (dts == 0)
            {
               return;
            }
            const std::vector<unsigned char>& data = dv_cast<Blob>(pDo->getAttribute(Nitf::TRE::ENGRDA::ENGDATA));
            if (data.empty())
            {
               return;
            }
            const void* pData = reinterpret_cast<const void*>(&data.front());

            mpValueType->setText(QString("%1 byte %2").arg(dts).arg(QString::fromStdString(type)));
            mpDataUnits->setText(QString::fromStdString(units));
            mpData->setColumnCount(cols);
            mpData->setRowCount(rows);

            bool isAscii = false;
            EncodingType encoding;
            if (type == "S" && dts == 1)
            {
               encoding = INT1SBYTE;
            }
            else if (type == "S" && dts == 2)
            {
               encoding = INT1SBYTE;
            }
            else if (type == "S" && dts == 2)
            {
               encoding = INT2SBYTES;
            }
            else if (type == "S" && dts == 4)
            {
               encoding = INT4SBYTES;
            }
            else if (type == "R" && dts == 4)
            {
               encoding = FLT4BYTES;
            }
            else if (type == "R" && dts == 8)
            {
               encoding = FLT8BYTES;
            }
            else if (type == "C" && dts == 8)
            {
               encoding = FLT8COMPLEX;
            }
            else if (type == "I" && dts == 1)
            {
               encoding = INT1UBYTE;
            }
            else if (type == "I" && dts == 2)
            {
               encoding = INT2UBYTES;
            }
            else if (type == "I" && dts == 4)
            {
               encoding = INT4UBYTES;
            }
            else if (type == "A")
            {
               isAscii = true;
               if (dts != 1)
               {
                  return;
               }
            }
            unsigned int datc  = data.size() / dts;
            if ((!encoding.isValid() && !isAscii) || datc != (rows * cols))
            {
               mpData->setEnabled(false);
               return;
            }
            for (size_t row = 0; row < rows ; ++row)
            {
               for (size_t col = 0; col < cols; ++col)
               {
                  if (isAscii)
                  {
                     // Not tested due to lack of test data
                     size_t idx = col + (row * cols); // datc chars per item
                     const QByteArray buf(reinterpret_cast<const char*>(pData) + idx, 1);
                     QTableWidgetItem* pItem = new QTableWidgetItem(QString(buf));
                     mpData->setItem(row, col, pItem);
                  }
                  else if (encoding == FLT8COMPLEX)
                  {
                     // Complex hasn't been tested due to lack of test data
                     //
                     size_t idx = (col * 2) + (row * cols * 2); // 2 floats per item
                     double real = std::numeric_limits<double>::quiet_NaN();
                     switchOnEncoding(FLT4BYTES, getDataValue, pData, idx, real, endian);
                     idx++;
                     double imag = std::numeric_limits<double>::quiet_NaN();
                     switchOnEncoding(FLT4BYTES, getDataValue, pData, idx, imag, endian);
                     QTableWidgetItem* pItem = new QTableWidgetItem(
                        QString::number(real, 'g', 12) + ", " + QString::number(imag, 'g', 12));
                     mpData->setItem(row, col, pItem);
                  }
                  else
                  {
                     size_t idx = col + row * cols;
                     double val = std::numeric_limits<double>::quiet_NaN();
                     switchOnEncoding(encoding, getDataValue, pData, idx, val, endian);
                     QTableWidgetItem* pItem = new QTableWidgetItem(QString::number(val, 'g', 12));
                     mpData->setItem(row, col, pItem);
                  }
               }
            }
         }
         return;
      }
      catch(const std::bad_cast&)
      {
      }
   }

   mpValueType->setText(QString());
   mpDataUnits->setText(QString());
   mpData->clear();
   mpValueType->setEnabled(false);
   mpDataUnits->setEnabled(false);
   mpData->setEnabled(false);
}
コード例 #2
0
ファイル: Jpeg2000Pager.cpp プロジェクト: Tom-VdE/opticks
CachedPage::UnitPtr Jpeg2000Pager::populateImageData(const DimensionDescriptor& startRow,
                                                     const DimensionDescriptor& startColumn,
                                                     unsigned int concurrentRows, unsigned int concurrentColumns) const
{
   VERIFYRV(startRow.isOnDiskNumberValid() == true, CachedPage::UnitPtr());
   VERIFYRV(startColumn.isOnDiskNumberValid() == true, CachedPage::UnitPtr());
   VERIFYRV(concurrentRows > 0, CachedPage::UnitPtr());
   VERIFYRV(concurrentColumns > 0, CachedPage::UnitPtr());

   // Get the rows, colums, and bands to load
   unsigned int onDiskStartRow = startRow.getOnDiskNumber();
   unsigned int onDiskStopRow = onDiskStartRow + concurrentRows;
   unsigned int onDiskStartColumn = startColumn.getOnDiskNumber();
   unsigned int onDiskStopColumn = onDiskStartColumn + concurrentColumns;

   const RasterElement* pRaster = getRasterElement();
   VERIFYRV(pRaster != NULL, CachedPage::UnitPtr());

   const RasterDataDescriptor* pDescriptor = dynamic_cast<const RasterDataDescriptor*>(pRaster->getDataDescriptor());
   VERIFYRV(pDescriptor != NULL, CachedPage::UnitPtr());

   const RasterFileDescriptor* pFileDescriptor =
      dynamic_cast<const RasterFileDescriptor*>(pDescriptor->getFileDescriptor());
   VERIFYRV(pFileDescriptor != NULL, CachedPage::UnitPtr());

   const std::vector<DimensionDescriptor>& allBands = pFileDescriptor->getBands();
   if (allBands.empty() == true)
   {
      return CachedPage::UnitPtr();
   }

   // Create the output data
   unsigned int numPixels = concurrentRows * concurrentColumns * allBands.size();
   unsigned int numBytes = numPixels * getBytesPerBand();

   if (numPixels > static_cast<unsigned int>(std::numeric_limits<int>::max()))   // ArrayResource only allocates up
                                                                                 // to INT_MAX number of values
   {
      return CachedPage::UnitPtr();
   }

   ArrayResource<Out> pDestination(numPixels, true);
   char* pDest = reinterpret_cast<char*>(pDestination.get());
   if (pDest == NULL)
   {
      return CachedPage::UnitPtr();
   }

   memset(pDest, 0, numPixels);

   // Decode the image from the file, first trying the codestream format then the file format
   opj_image_t* pImage = decodeImage(onDiskStartRow, onDiskStartColumn, onDiskStopRow, onDiskStopColumn,
      Jpeg2000Utilities::J2K_CFMT);
   if (pImage == NULL)
   {
      pImage = decodeImage(onDiskStartRow, onDiskStartColumn, onDiskStopRow, onDiskStopColumn,
         Jpeg2000Utilities::JP2_CFMT);
   }

   if (pImage == NULL)
   {
      return CachedPage::UnitPtr();
   }

   // Populate the output image data
   int bandFactor = 1;

   std::string filename = pRaster->getFilename();
   if (filename.empty() == false)
   {
      QStringList parts = QString::fromStdString(filename).split('.');
      foreach (QString part, parts)
      {
         bool error;
         EncodingType dataType = StringUtilities::fromXmlString<EncodingType>(part.toStdString(), &error);
         if (dataType.isValid() == true && error == false)
         {
            int currentBandFactor = Jpeg2000Utilities::get_num_bands(dataType);
            if (currentBandFactor > 0)
            {
               bandFactor = currentBandFactor;
               break;
            }
         }
      }
コード例 #3
0
vector<ImportDescriptor*> Nitf::NitfImporterShell::getImportDescriptors(const string &filename)
{
   vector<ImportDescriptor*> retval;

   if (filename.empty())
   {
      return retval;
   }

   Nitf::OssimFileResource pFile(filename);
   if (pFile.get() == NULL)
   {
      return retval;
   }

   Nitf::OssimImageHandlerResource pHandler(filename);
   if (pHandler.get() == NULL || pHandler->canCastTo("ossimNitfTileSource") == false)
   {
      return retval;
   }

   ossimNitfFileHeaderV2_X* pFileHeader =
      PTR_CAST(ossimNitfFileHeaderV2_X, pFile->getHeader().get());
   if (pFileHeader == NULL)
   {
      return retval;
   }

   // Not all segments are importable.  This is generally due to the segment
   // using an unsupported compression format.  Only generate descriptors
   // for the importable segments.
   vector<ossim_uint32> importableImageSegments;
   pHandler->getEntryList(importableImageSegments);

   // Create map of TRE parsers.
   // The sole purpose of this map is to force DLLs to stay loaded while the metadata is being imported.
   std::map<std::string, TrePlugInResource> parsers;

   for (vector<ossim_uint32>::iterator segmentIter = importableImageSegments.begin();
        segmentIter != importableImageSegments.end(); ++segmentIter)
   {
      // Do not call pHandler->setCurrentEntry as it is a very expensive operation
      // which causes up to a several second delay on files with many large images.
      const ossim_uint32& currentIndex = *segmentIter;
      ossimNitfImageHeaderV2_X* pImgHeader =
         PTR_CAST(ossimNitfImageHeaderV2_X, pFile->getNewImageHeader(currentIndex));
      if (pImgHeader == NULL)
      {
         continue;
      }

      EncodingType dataType = ossimImageHeaderToEncodingType(pImgHeader);
      if (dataType.isValid() == false)
      {
         continue;
      }

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

      ImportDescriptorResource pImportDescriptor(getImportDescriptor(filename, imageName,
         pFile.get(), pFileHeader, pImgHeader));
      if (pImportDescriptor.get() == NULL)
      {
         continue;
      }

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

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

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

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

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

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

      RasterFileDescriptor* pFd = dynamic_cast<RasterFileDescriptor*>(
         RasterUtilities::generateAndSetFileDescriptor(pDd, filename, imageName, LITTLE_ENDIAN_ORDER));

      string errorMessage;
      if (Nitf::importMetadata(currentIndex + 1, pFile, pFileHeader, pImgHeader, pDd, parsers, errorMessage) == true)
      {
         if (pImgHeader->hasTransparentCode() == true)
         {
            vector<int> badValues;
            badValues.push_back(static_cast<int>(pImgHeader->getTransparentCode()));
            pDd->setBadValues(badValues);
         }

         // If red, green, OR blue bands are valid, set the display mode to RGB.
         if (pDd->getDisplayBand(RED).isValid() == true ||
             pDd->getDisplayBand(GREEN).isValid() == true ||
             pDd->getDisplayBand(BLUE).isValid() == true)
         {
            pDd->setDisplayMode(RGB_MODE);
         }
         // Otherwise, if the gray band is valid, set the display mode to GRAYSCALE.
         else if (pDd->getDisplayBand(GRAY).isValid() == true)
         {
            pDd->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)
         {
            pDd->setDisplayBand(RED, bands[0]);
            pDd->setDisplayBand(GREEN, bands[1]);
            pDd->setDisplayBand(BLUE, bands[2]);
            pDd->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)
         {
            pDd->setDisplayBand(GRAY, bands[0]);
            pDd->setDisplayMode(GRAYSCALE_MODE);
         }
         else
         {
            continue;
         }

         mParseMessages[imageName] = errorMessage;
         retval.push_back(pImportDescriptor.release());
      }
   }

   return retval;
}
コード例 #4
0
ファイル: NitfImporterShell.cpp プロジェクト: Tom-VdE/opticks
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();
}
コード例 #5
0
ファイル: Jpeg2000Importer.cpp プロジェクト: Tom-VdE/opticks
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;
         }
      }
   }