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); }
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; } } }
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; }
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(); }
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; } } }