// Note: throws ossimException on error. void ossimRpfUtil::writeDotRpfFiles( const ossimFilename& aDotTocFile, const ossimFilename& outputDir ) { static const char MODULE[] = "ossimRpfUtil::writeDotRpfFiles"; if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered..." << "\na.toc file: " << aDotTocFile << "\noutput directory: " << outputDir << "\n"; } // Parse the a.toc file: ossimRefPtr<ossimRpfToc> toc = new ossimRpfToc(); if ( toc->parseFile(aDotTocFile) != ossimErrorCodes::OSSIM_OK ) { std::string e = MODULE; e += " ERROR:\nCould not open: "; e+= aDotTocFile.string(); throw ossimException(e); } if ( outputDir.expand().exists() == false ) { if ( !outputDir.createDirectory(true, 0775) ) { std::string e = MODULE; e += " ERROR:\nCould not create directory: "; e+= outputDir.c_str(); throw ossimException(e); } } //--- // Go through the entries... //--- ossim_uint32 entries = toc->getNumberOfEntries(); for (ossim_uint32 entry = 0; entry < entries; ++entry) { const ossimRpfTocEntry* tocEntry = toc->getTocEntry(entry); if (tocEntry) { if ( tocEntry->isEmpty() == false ) { writeDotRpfFile(toc.get(), tocEntry, outputDir, entry); } } else { std::string e = MODULE; e += " ERROR: Null entry: "; e += ossimString::toString(entry).string(); throw ossimException(e); } } } // End: ossimRpfUtil::writeDotRpfFiles
void ossimRpfToc::createTocAndCopyFrames( const ossimFilename& dotRpfFile, const ossimFilename& outputDir ) { static const char MODULE[] = "ossimRpfToc::createTocAndCopyFrames"; if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered..." << "\ndot rpf file: " << dotRpfFile << "\noutput directory: " << outputDir << "\n"; } if ( outputDir.expand().exists() == false ) { if ( !outputDir.createDirectory(true, 0775) ) { std::string e = MODULE; e += " ERROR:\nCould not create directory: "; e+= outputDir.c_str(); throw ossimException(e); } } // Open the dot rpf file. std::ifstream* dotRpfStr = new std::ifstream; dotRpfStr->open(dotRpfFile, ios_base::in); if ( !dotRpfStr->good() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not open: "; e += dotRpfFile.c_str(); throw ossimException(e); } ossimFilename sourceADotTocFile = getSourceTocFile(*dotRpfStr); if ( sourceADotTocFile.empty() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not deduce source a.toc file!"; throw ossimException(e); } // Open the source a.toc file. Note the true flag is to keep the file header. ossimRefPtr<ossimRpfToc> sourceADotToc = new ossimRpfToc; if ( sourceADotToc->parseFile(sourceADotTocFile, true) != ossimErrorCodes::OSSIM_OK ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not open: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } ossimRefPtr<const ossimNitfFileHeader> sourceNitfFileHdr = sourceADotToc->getNitfFileHeader(); if ( !sourceNitfFileHdr.valid() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not get nitf file header from: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } ossimRefPtr<const ossimRpfHeader> sourceRpfHdr = sourceADotToc->getRpfHeader(); if ( !sourceRpfHdr.valid() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not get rpf header from: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } // Get the boundary rect sub header from the source a.toc. ossimRefPtr<ossimRpfBoundaryRectSectionSubheader> boundaryRectSectionSubheader = sourceRpfHdr->getNewBoundaryRectSectSubheader(sourceADotTocFile); if ( !boundaryRectSectionSubheader.valid() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not pull boundary rect sub header from source file: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } // Get the boundary rect table from the source a.toc. ossimRefPtr<ossimRpfBoundaryRectTable> boundaryRectTable = sourceRpfHdr->getNewBoundaryRectTable(sourceADotTocFile); if ( !boundaryRectTable.valid() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not pull boundary rect table from source file: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } // Get the frame file subheader from the source a.toc. ossimRefPtr<ossimRpfFrameFileIndexSectionSubheader> frameFileSubHeader = sourceRpfHdr->getNewFrameFileIndexSectionSubheader(sourceADotTocFile); if ( !frameFileSubHeader.valid() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not pull frame file sub header from source file: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } // Get the frame file subsection from the source a.toc. ossimRefPtr<ossimRpfFrameFileIndexSubsection> frameFileSubSection = sourceRpfHdr->getNewFileIndexSubsection(sourceADotTocFile); if ( !frameFileSubSection.valid() ) { delete dotRpfStr; dotRpfStr = 0; std::string e = MODULE; e += " ERROR:\nCould not pull frame file sub section from source file: "; e += sourceADotTocFile.c_str(); throw ossimException(e); } // Open the output file to write to. const ossimFilename A_DOT_TOC_FILE = "a.toc"; ossimFilename dotTocFile = outputDir.dirCat(A_DOT_TOC_FILE); std::ofstream* dotTocStr = new std::ofstream; dotTocStr->open( dotTocFile.c_str(), ios::out|ios::binary ); if ( !dotTocStr->good() ) { delete dotRpfStr; dotRpfStr = 0; delete dotTocStr; dotTocStr =0; std::string e = MODULE; e += " ERROR:\nCould not open: "; e += dotTocFile.c_str(); throw ossimException(e); } // Variables used throughout: ossimRefPtr<ossimProperty> prop = new ossimStringProperty(); ossimString field; ossimString s; std::streampos fileHeaderLength = 0; std::streampos fileLength = 0; ossimRefPtr<ossimNitfFileHeaderV2_0> fileHdr = new ossimNitfFileHeaderV2_0(); // Set the CLEVEL: s = "01"; fileHdr->setComplexityLevel(s); // Set the OSTAID: prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::OSTAID_KW); fileHdr->setProperty(prop); // Set the FDT (date): fileHdr->setDate(); // Set the FTITLE: s = "a.toc"; fileHdr->setTitle(s); // Set the FSCLAS: prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::FSCLAS_KW); fileHdr->setProperty(prop); // Set the FSCODE: prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::FSCODE_KW); fileHdr->setProperty(prop); // Set the FSCTLH: prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::FSCTLH_KW); fileHdr->setProperty(prop); // Set the ONAME: prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::ONAME_KW); fileHdr->setProperty(prop); // Set the OPHONE: prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::OPHONE_KW); fileHdr->setProperty(prop); // Add the rpf header. ossimRpfHeader* rpfHdr = new ossimRpfHeader( *(sourceRpfHdr.get()) ); ossimRefPtr<ossimNitfRegisteredTag> rpfHdrRp = rpfHdr; ossimNitfTagInformation rpfHdrInfo(rpfHdrRp); fileHdr->addTag(rpfHdrInfo); //--- // Write it out... // The first write will be with an rpfheader with no location sections just // to see where the end of the file header is. //--- fileHdr->writeStream(*dotTocStr); //--- // End of file header. Get the header length. This will also be the // start of the location section. //--- std::streampos pos = dotTocStr->tellp(); std::streamoff locationSectionOffset = pos; // Set the header length: fileHdr->setHeaderLength( static_cast<ossim_uint64>(locationSectionOffset) ); // Set the location of the location section. rpfHdr->setLocationSectionPos(locationSectionOffset); // Set the file name. rpfHdr->setFilename(A_DOT_TOC_FILE); // Add the component location records to the header. ossimRpfLocationSection* locSec = rpfHdr->getLocationSection(); // Clear the records copied from the source a.toc. locSec->clearFields(); //--- // Set the length of the locSec to 74. The record itself is 14 bytes plus // an additional 60 bytes for six location records ten bytes each. //--- const ossim_uint16 LOCATION_SECTION_SIZE = 74; locSec->setLocationSectionLength(LOCATION_SECTION_SIZE); // Set the offset which 14 bytes to get to the first record. locSec->setLocationTableOffset(14); // Six records: locSec->setNumberOfComponentLocationRecords(6); // Each record 10 bytes: locSec->setLocationRecordLength(10); // Don't know the aggregate length yet. ossimRpfComponentLocationRecord locRec; // Note: See ossimRpfConstants for enum ossimRpfComponentId const ossim_uint32 RPFHDR_SIZE = 48; const ossim_uint32 LOCATION_SECTION_OFFSET = static_cast<ossim_uint32>(locationSectionOffset); const ossim_uint32 BOUNDARY_SUBHEADER_SIZE = 8; const ossim_uint32 BOUNDARY_RECORD_SIZE = 132; const ossim_uint32 FILE_SUBHEADER_SIZE = 13; // const ossim_uint32 = ; // Record 1 RPFHDR location: ossim_uint32 rpfHdrOffset = 0; if ( fileHdr->getTag(rpfHdrInfo, "RPFHDR") ) { rpfHdrOffset = rpfHdrInfo.getTagDataOffset(); } locRec.m_componentId = OSSIM_RPF_HEADER_COMPONENT; // 128 locRec.m_componentLength = RPFHDR_SIZE; locRec.m_componentLocation = static_cast<ossim_uint32>(rpfHdrInfo.getTagDataOffset()); locSec->addComponentRecord(locRec); if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG)<< "rpf hdr offset: " << rpfHdrOffset << "\n"; locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) ); } // Record 2 location section: locRec.m_componentId = OSSIM_RPF_LOCATION_COMPONENT; // 129 locRec.m_componentLength = LOCATION_SECTION_SIZE; locRec.m_componentLocation = LOCATION_SECTION_OFFSET; locSec->addComponentRecord(locRec); if ( traceDebug() ) { locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) ); } // Record 3 boundary rect sub header section: locRec.m_componentId = OSSIM_RPF_BOUNDARY_RECT_SECTION_SUBHEADER; // 148 locRec.m_componentLength = BOUNDARY_SUBHEADER_SIZE; locRec.m_componentLocation = locRec.m_componentLocation + LOCATION_SECTION_SIZE; locSec->addComponentRecord(locRec); if ( traceDebug() ) { locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) ); } // Capture the location. std::streamoff boundaryRectPosition = locRec.m_componentLocation; // Record 4 boundary rect table: locRec.m_componentId = OSSIM_RPF_BOUNDARY_RECT_TABLE; // 149 locRec.m_componentLength = BOUNDARY_RECORD_SIZE; locRec.m_componentLocation = locRec.m_componentLocation + BOUNDARY_SUBHEADER_SIZE; locSec->addComponentRecord(locRec); if ( traceDebug() ) { locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) ); } // Record 5 file index sub header: locRec.m_componentId = OSSIM_RPF_FRAME_FILE_INDEX_SECTION_SUBHEADER; // 150 locRec.m_componentLength = FILE_SUBHEADER_SIZE; locRec.m_componentLocation = locRec.m_componentLocation + BOUNDARY_RECORD_SIZE; locSec->addComponentRecord(locRec); if ( traceDebug() ) { locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) ); } // Record 6 file index sub header: locRec.m_componentId = OSSIM_RPF_FRAME_FILE_INDEX_SUBSECTION; // 151 locRec.m_componentLength = 0; // need to calculate. locRec.m_componentLocation = locRec.m_componentLocation + FILE_SUBHEADER_SIZE; locSec->addComponentRecord(locRec); if ( traceDebug() ) { locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) ); } // Seek back and re-write... dotTocStr->seekp(0, ios::beg); fileHdr->writeStream(*dotTocStr); dotTocStr->seekp(boundaryRectPosition, ios::beg); // Only writing one entry: boundaryRectSectionSubheader->setNumberOfEntries(1); if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "writing boundaryRectSectionSubheader:\n" << *(boundaryRectSectionSubheader.get()) << "\n"; } //--- // Write the boundary rectangle section. This includes the subheader and subsection. // These coorespond to location records 3 and 4 above. //--- boundaryRectSectionSubheader->writeStream(*dotTocStr); if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "Original boundaryRectTable:\n" << *(boundaryRectTable.get()) << "\n"; } ossim_uint32 entry; if ( getCorespondingEntry( frameFileSubSection.get(), *dotRpfStr, entry ) ) { ossimRpfBoundaryRectRecord boundaryRectRecord; if ( boundaryRectTable->getEntry( entry, boundaryRectRecord) ) { if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "writing boundaryRectTable:\n" << boundaryRectRecord << "\n"; } boundaryRectRecord.writeStream(*dotTocStr); } else { std::string e = MODULE; e += " ERROR:\nCould not get bounding rect record for entry: "; e += ossimString::toString(entry).c_str(); throw ossimException(e); } } else { std::string e = MODULE; e += " ERROR:\nCould not deduce entry from frame list!"; throw ossimException(e); } frameFileSubHeader->setNumberOfIndexRecords( getNumberOfFrames(*dotRpfStr) ); frameFileSubHeader->setNumberOfPathnameRecords(1); const ossim_uint16 FRAME_FILE_INDEX_RECORD_LENGTH = 33; frameFileSubHeader->setIndexRecordLength( FRAME_FILE_INDEX_RECORD_LENGTH ); if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "writing frameFileSubHeader:\n" << *(frameFileSubHeader.get()) << "\n"; } frameFileSubHeader->writeStream( *dotTocStr ); if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) << "writing frameFileSubSection:\n"; } std::streamoff frameFileIndexSectionStartPos = dotTocStr->tellp(); writeFrameFileIndexSection(frameFileSubSection.get(), *dotRpfStr, *dotTocStr); std::streamoff endOfFilePos = dotTocStr->tellp(); // Update the location section length for the frame file index section. locSec->getLocationRecordList()[5].m_componentLength = static_cast<ossim_uint32>(endOfFilePos - frameFileIndexSectionStartPos); // Update the length of all location sections. locSec->setComponentAggregateLength( static_cast<ossim_uint32>(endOfFilePos) - rpfHdr->getLocationSectionLocation() ); fileHdr->setFileLength(static_cast<ossim_uint64>(endOfFilePos)); dotTocStr->seekp(0, ios::beg); fileHdr->writeStream(*dotTocStr); ossimNotify(ossimNotifyLevel_DEBUG) << "Wrote file: " << dotTocFile << "\n"; // Copy the frames to the output directory. copyFrames(*dotRpfStr, outputDir); // Cleanup: delete dotRpfStr; dotRpfStr = 0; delete dotTocStr; dotTocStr =0; }