int main( int nArgc, char ** papszArgv ) { NITFFile *psFile; int iSegment, iFile; char szTemp[100]; int bDisplayTRE = FALSE; int bExtractSHP = FALSE, bExtractSHPInMem = FALSE; if( nArgc < 2 ) { printf( "Usage: nitfdump [-tre] [-extractshp | -extractshpinmem] <nitf_filename>*\n" ); exit( 1 ); } for( iFile = 1; iFile < nArgc; iFile++ ) { if ( EQUAL(papszArgv[iFile], "-tre") ) bDisplayTRE = TRUE; else if ( EQUAL(papszArgv[iFile], "-extractshp") ) bExtractSHP = TRUE; else if ( EQUAL(papszArgv[iFile], "-extractshpinmem") ) { bExtractSHP = TRUE; bExtractSHPInMem = TRUE; } } /* ==================================================================== */ /* Loop over all files. */ /* ==================================================================== */ for( iFile = 1; iFile < nArgc; iFile++ ) { int bHasFoundLocationTable = FALSE; if ( EQUAL(papszArgv[iFile], "-tre") ) continue; if ( EQUAL(papszArgv[iFile], "-extractshp") ) continue; if ( EQUAL(papszArgv[iFile], "-extractshpinmem") ) continue; /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ psFile = NITFOpen( papszArgv[iFile], FALSE ); if( psFile == NULL ) exit( 2 ); printf( "Dump for %s\n", papszArgv[iFile] ); /* -------------------------------------------------------------------- */ /* Dump first TRE list. */ /* -------------------------------------------------------------------- */ if( psFile->pachTRE != NULL ) { int nTREBytes = psFile->nTREBytes; const char *pszTREData = psFile->pachTRE; printf( "File TREs:" ); while( nTREBytes > 10 ) { int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 )); if (nThisTRESize < 0 || nThisTRESize > nTREBytes - 11) { NITFGetField(szTemp, pszTREData, 0, 6 ); printf(" Invalid size (%d) for TRE %s", nThisTRESize, szTemp); break; } printf( " %6.6s(%d)", pszTREData, nThisTRESize ); pszTREData += nThisTRESize + 11; nTREBytes -= (nThisTRESize + 11); } printf( "\n" ); if (bDisplayTRE) { nTREBytes = psFile->nTREBytes; pszTREData = psFile->pachTRE; while( nTREBytes > 10 ) { char *pszEscaped; int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 )); if (nThisTRESize < 0 || nThisTRESize > nTREBytes - 11) { break; } pszEscaped = CPLEscapeString( pszTREData + 11, nThisTRESize, CPLES_BackslashQuotable ); printf( "TRE '%6.6s' : %s\n", pszTREData, pszEscaped); CPLFree(pszEscaped); pszTREData += nThisTRESize + 11; nTREBytes -= (nThisTRESize + 11); } } } /* -------------------------------------------------------------------- */ /* Dump Metadata */ /* -------------------------------------------------------------------- */ DumpMetadata( "File Metadata:", " ", psFile->papszMetadata ); /* -------------------------------------------------------------------- */ /* Dump general info about segments. */ /* -------------------------------------------------------------------- */ NITFCollectAttachments( psFile ); NITFReconcileAttachments( psFile ); for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ ) { NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment; printf( "Segment %d (Type=%s):\n", iSegment + 1, psSegInfo->szSegmentType ); printf( " HeaderStart=" CPL_FRMT_GUIB ", HeaderSize=%u, DataStart=" CPL_FRMT_GUIB ", DataSize=" CPL_FRMT_GUIB "\n", psSegInfo->nSegmentHeaderStart, psSegInfo->nSegmentHeaderSize, psSegInfo->nSegmentStart, psSegInfo->nSegmentSize ); printf( " DLVL=%d, ALVL=%d, LOC=C%d,R%d, CCS=C%d,R%d\n", psSegInfo->nDLVL, psSegInfo->nALVL, psSegInfo->nLOC_C, psSegInfo->nLOC_R, psSegInfo->nCCS_C, psSegInfo->nCCS_R ); printf( "\n" ); } /* -------------------------------------------------------------------- */ /* Report details of images. */ /* -------------------------------------------------------------------- */ for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ ) { NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment; NITFImage *psImage; NITFRPC00BInfo sRPCInfo; int iBand; char **papszMD; if( !EQUAL(psSegInfo->szSegmentType,"IM") ) continue; psImage = NITFImageAccess( psFile, iSegment ); if( psImage == NULL ) { printf( "NITFAccessImage(%d) failed!\n", iSegment ); continue; } printf( "Image Segment %d, %dPx%dLx%dB x %dbits:\n", iSegment + 1, psImage->nCols, psImage->nRows, psImage->nBands, psImage->nBitsPerSample ); printf( " PVTYPE=%s, IREP=%s, ICAT=%s, IMODE=%c, IC=%s, COMRAT=%s, ICORDS=%c\n", psImage->szPVType, psImage->szIREP, psImage->szICAT, psImage->chIMODE, psImage->szIC, psImage->szCOMRAT, psImage->chICORDS ); if( psImage->chICORDS != ' ' ) { printf( " UL=(%.15g,%.15g), UR=(%.15g,%.15g) Center=%d\n LL=(%.15g,%.15g), LR=(%.15g,%.15g)\n", psImage->dfULX, psImage->dfULY, psImage->dfURX, psImage->dfURY, psImage->bIsBoxCenterOfPixel, psImage->dfLLX, psImage->dfLLY, psImage->dfLRX, psImage->dfLRY ); } printf( " IDLVL=%d, IALVL=%d, ILOC R=%d,C=%d, IMAG=%s\n", psImage->nIDLVL, psImage->nIALVL, psImage->nILOCRow, psImage->nILOCColumn, psImage->szIMAG ); printf( " %d x %d blocks of size %d x %d\n", psImage->nBlocksPerRow, psImage->nBlocksPerColumn, psImage->nBlockWidth, psImage->nBlockHeight ); if( psImage->pachTRE != NULL ) { int nTREBytes = psImage->nTREBytes; const char *pszTREData = psImage->pachTRE; printf( " Image TREs:" ); while( nTREBytes > 10 ) { int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 )); if (nThisTRESize < 0 || nThisTRESize > nTREBytes - 11) { NITFGetField(szTemp, pszTREData, 0, 6 ); printf(" Invalid size (%d) for TRE %s", nThisTRESize, szTemp); break; } printf( " %6.6s(%d)", pszTREData, nThisTRESize ); pszTREData += nThisTRESize + 11; nTREBytes -= (nThisTRESize + 11); } printf( "\n" ); if (bDisplayTRE) { nTREBytes = psImage->nTREBytes; pszTREData = psImage->pachTRE; while( nTREBytes > 10 ) { char *pszEscaped; int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 )); if (nThisTRESize < 0 || nThisTRESize > nTREBytes - 11) { break; } pszEscaped = CPLEscapeString( pszTREData + 11, nThisTRESize, CPLES_BackslashQuotable ); printf( " TRE '%6.6s' : %s\n", pszTREData, pszEscaped); CPLFree(pszEscaped); pszTREData += nThisTRESize + 11; nTREBytes -= (nThisTRESize + 11); } } } /* Report info from location table, if found. */ if( psImage->nLocCount > 0 ) { int i; bHasFoundLocationTable = TRUE; printf( " Location Table\n" ); for( i = 0; i < psImage->nLocCount; i++ ) { printf( " LocName=%s, LocId=%d, Offset=%d, Size=%d\n", GetLocationNameFromId(psImage->pasLocations[i].nLocId), psImage->pasLocations[i].nLocId, psImage->pasLocations[i].nLocOffset, psImage->pasLocations[i].nLocSize ); } printf( "\n" ); } if( strlen(psImage->pszComments) > 0 ) printf( " Comments:\n%s\n", psImage->pszComments ); for( iBand = 0; iBand < psImage->nBands; iBand++ ) { NITFBandInfo *psBandInfo = psImage->pasBandInfo + iBand; printf( " Band %d: IREPBAND=%s, ISUBCAT=%s, %d LUT entries.\n", iBand + 1, psBandInfo->szIREPBAND, psBandInfo->szISUBCAT, psBandInfo->nSignificantLUTEntries ); } if( NITFReadRPC00B( psImage, &sRPCInfo ) ) { DumpRPC( psImage, &sRPCInfo ); } papszMD = NITFReadUSE00A( psImage ); if( papszMD != NULL ) { DumpMetadata( " USE00A TRE:", " ", papszMD ); CSLDestroy( papszMD ); } papszMD = NITFReadBLOCKA( psImage ); if( papszMD != NULL ) { DumpMetadata( " BLOCKA TRE:", " ", papszMD ); CSLDestroy( papszMD ); } papszMD = NITFReadSTDIDC( psImage ); if( papszMD != NULL ) { DumpMetadata( " STDIDC TRE:", " ", papszMD ); CSLDestroy( papszMD ); } DumpMetadata( " Image Metadata:", " ", psImage->papszMetadata ); printf("\n"); } /* ==================================================================== */ /* Report details of graphic segments. */ /* ==================================================================== */ for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ ) { NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment; char achSubheader[298]; int nSTYPEOffset; if( !EQUAL(psSegInfo->szSegmentType,"GR") && !EQUAL(psSegInfo->szSegmentType,"SY") ) continue; /* -------------------------------------------------------------------- */ /* Load the graphic subheader. */ /* -------------------------------------------------------------------- */ if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, SEEK_SET ) != 0 || VSIFReadL( achSubheader, 1, sizeof(achSubheader), psFile->fp ) < 258 ) { CPLError( CE_Warning, CPLE_FileIO, "Failed to read graphic subheader at " CPL_FRMT_GUIB ".", psSegInfo->nSegmentHeaderStart ); continue; } // NITF 2.0. (also works for NITF 2.1) nSTYPEOffset = 200; if( STARTS_WITH_CI(achSubheader+193, "999998") ) nSTYPEOffset += 40; /* -------------------------------------------------------------------- */ /* Report some standard info. */ /* -------------------------------------------------------------------- */ printf( "Graphic Segment %d, type=%2.2s, sfmt=%c, sid=%10.10s\n", iSegment + 1, achSubheader + 0, achSubheader[nSTYPEOffset], achSubheader + 2 ); printf( " sname=%20.20s\n", achSubheader + 12 ); printf("\n"); } /* ==================================================================== */ /* Report details of text segments. */ /* ==================================================================== */ for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ ) { char *pabyHeaderData; char *pabyTextData; NITFSegmentInfo *psSegment = psFile->pasSegmentInfo + iSegment; if( !EQUAL(psSegment->szSegmentType,"TX") ) continue; printf( "Text Segment %d\n", iSegment + 1); /* -------------------------------------------------------------------- */ /* Load the text header */ /* -------------------------------------------------------------------- */ /* Allocate one extra byte for the NULL terminating character */ pabyHeaderData = (char *) CPLCalloc(1, (size_t) psSegment->nSegmentHeaderSize + 1); if (VSIFSeekL(psFile->fp, psSegment->nSegmentHeaderStart, SEEK_SET) != 0 || VSIFReadL(pabyHeaderData, 1, (size_t) psSegment->nSegmentHeaderSize, psFile->fp) != psSegment->nSegmentHeaderSize) { CPLError( CE_Warning, CPLE_FileIO, "Failed to read %d bytes of text header data at " CPL_FRMT_GUIB ".", psSegment->nSegmentHeaderSize, psSegment->nSegmentHeaderStart); CPLFree(pabyHeaderData); continue; } printf(" Header : %s\n", pabyHeaderData); CPLFree(pabyHeaderData); /* -------------------------------------------------------------------- */ /* Load the raw TEXT data itself. */ /* -------------------------------------------------------------------- */ /* Allocate one extra byte for the NULL terminating character */ pabyTextData = (char *) CPLCalloc(1,(size_t)psSegment->nSegmentSize+1); if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart, SEEK_SET ) != 0 || VSIFReadL( pabyTextData, 1, (size_t)psSegment->nSegmentSize, psFile->fp ) != psSegment->nSegmentSize ) { CPLError( CE_Warning, CPLE_FileIO, "Failed to read " CPL_FRMT_GUIB " bytes of text data at " CPL_FRMT_GUIB ".", psSegment->nSegmentSize, psSegment->nSegmentStart ); CPLFree( pabyTextData ); continue; } printf(" Data : %s\n", pabyTextData); printf("\n"); CPLFree( pabyTextData ); } /* -------------------------------------------------------------------- */ /* Report details of DES. */ /* -------------------------------------------------------------------- */ for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ ) { NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment; NITFDES *psDES; int nOffset = 0; char szTREName[7]; int nThisTRESize; int nRPFDESOffset = -1; if( !EQUAL(psSegInfo->szSegmentType,"DE") ) continue; psDES = NITFDESAccess( psFile, iSegment ); if( psDES == NULL ) { printf( "NITFDESAccess(%d) failed!\n", iSegment ); continue; } printf( "DE Segment %d:\n", iSegment + 1 ); printf( " Segment TREs:" ); nOffset = 0; while (NITFDESGetTRE( psDES, nOffset, szTREName, NULL, &nThisTRESize)) { printf( " %6.6s(%d)", szTREName, nThisTRESize ); if (strcmp(szTREName, "RPFDES") == 0) nRPFDESOffset = nOffset + 11; nOffset += 11 + nThisTRESize; } printf( "\n" ); if (bDisplayTRE) { char* pabyTREData = NULL; nOffset = 0; while (NITFDESGetTRE( psDES, nOffset, szTREName, &pabyTREData, &nThisTRESize)) { char* pszEscaped = CPLEscapeString( pabyTREData, nThisTRESize, CPLES_BackslashQuotable ); printf( " TRE '%6.6s' : %s\n", szTREName, pszEscaped); CPLFree(pszEscaped); nOffset += 11 + nThisTRESize; NITFDESFreeTREData(pabyTREData); } } /* Report info from location table, if found. */ if( !bHasFoundLocationTable && nRPFDESOffset >= 0 ) { int i; int nLocCount = 0; NITFLocation* pasLocations; VSIFSeekL(psFile->fp, psSegInfo->nSegmentStart + nRPFDESOffset, SEEK_SET); pasLocations = NITFReadRPFLocationTable(psFile->fp, &nLocCount); if (pasLocations) { printf( " Location Table\n" ); for( i = 0; i < nLocCount; i++ ) { printf( " LocName=%s, LocId=%d, Offset=%d, Size=%d\n", GetLocationNameFromId(pasLocations[i].nLocId), pasLocations[i].nLocId, pasLocations[i].nLocOffset, pasLocations[i].nLocSize ); } CPLFree(pasLocations); printf( "\n" ); } } DumpMetadata( " DES Metadata:", " ", psDES->papszMetadata ); if ( bExtractSHP && CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE_USE") != NULL ) { char szFilename[32]; char szRadix[32]; if (bExtractSHPInMem) snprintf(szRadix, sizeof(szRadix), "/vsimem/nitf_segment_%d", iSegment + 1); else snprintf(szRadix, sizeof(szRadix), "nitf_segment_%d", iSegment + 1); if (NITFDESExtractShapefile(psDES, szRadix)) { OGRDataSourceH hDS; OGRRegisterAll(); snprintf(szFilename, sizeof(szFilename), "%s.SHP", szRadix); hDS = OGROpen(szFilename, FALSE, NULL); if (hDS) { int nGeom = 0; OGRLayerH hLayer = OGR_DS_GetLayer(hDS, 0); if (hLayer) { OGRFeatureH hFeat; printf("\n"); while ( (hFeat = OGR_L_GetNextFeature(hLayer)) != NULL ) { OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat); if (hGeom) { char* pszWKT = NULL; OGR_G_ExportToWkt(hGeom, &pszWKT); if (pszWKT) printf(" Geometry %d : %s\n", nGeom ++, pszWKT); CPLFree(pszWKT); } OGR_F_Destroy(hFeat); } } OGR_DS_Destroy(hDS); } } if (bExtractSHPInMem) { snprintf(szFilename, sizeof(szFilename), "%s.SHP", szRadix); VSIUnlink(szFilename); snprintf(szFilename, sizeof(szFilename), "%s.SHX", szRadix); VSIUnlink(szFilename); snprintf(szFilename, sizeof(szFilename), "%s.DBF", szRadix); VSIUnlink(szFilename); } } } /* -------------------------------------------------------------------- */ /* Close. */ /* -------------------------------------------------------------------- */ NITFClose( psFile ); } CPLFinderClean(); CPLCleanupTLS(); VSICleanupFileManager(); OGRCleanupAll(); exit( 0 ); }
int main( int argc, char ** argv ) { const char *pszFilename = NULL; int nDumpTree = FALSE; int nDumpDict = FALSE; int nRastReport = FALSE; int i, nXSize, nYSize, nBands; HFAHandle hHFA; const Eprj_MapInfo *psMapInfo; const Eprj_ProParameters *psProParameters; const Eprj_Datum *psDatum; /* -------------------------------------------------------------------- */ /* Handle arguments. */ /* -------------------------------------------------------------------- */ for( i = 1; i < argc; i++ ) { if( EQUAL(argv[i],"-dd") ) nDumpDict = TRUE; else if( EQUAL(argv[i],"-dt") ) nDumpTree = TRUE; else if( EQUAL(argv[i],"-dr") ) nRastReport = TRUE; else if( pszFilename == NULL ) pszFilename = argv[i]; else { Usage(); exit( 1 ); } } if( pszFilename == NULL ) { Usage(); exit( 1 ); } /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ hHFA = HFAOpen( pszFilename, "r" ); if( hHFA == NULL ) { printf( "HFAOpen() failed.\n" ); exit( 100 ); } /* -------------------------------------------------------------------- */ /* Do we want to walk the tree dumping out general information? */ /* -------------------------------------------------------------------- */ if( nDumpDict ) { HFADumpDictionary( hHFA, stdout ); } /* -------------------------------------------------------------------- */ /* Do we want to walk the tree dumping out general information? */ /* -------------------------------------------------------------------- */ if( nDumpTree ) { HFADumpTree( hHFA, stdout ); } /* -------------------------------------------------------------------- */ /* Dump indirectly collected data about bands. */ /* -------------------------------------------------------------------- */ HFAGetRasterInfo( hHFA, &nXSize, &nYSize, &nBands ); if( nRastReport ) { printf( "Raster Size = %d x %d\n", nXSize, nYSize ); for( i = 1; i <= nBands; i++ ) { int nDataType, nColors, nOverviews, iOverview; double *padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins; int nBlockXSize, nBlockYSize, nCompressionType; HFAGetBandInfo( hHFA, i, &nDataType, &nBlockXSize, &nBlockYSize, &nCompressionType ); nOverviews = HFAGetOverviewCount( hHFA, i ); printf( "Band %d: %dx%d tiles, type = %d\n", i, nBlockXSize, nBlockYSize, nDataType ); for( iOverview=0; iOverview < nOverviews; iOverview++ ) { HFAGetOverviewInfo( hHFA, i, iOverview, &nXSize, &nYSize, &nBlockXSize, &nBlockYSize, NULL ); printf( " Overview: %dx%d (blocksize %dx%d)\n", nXSize, nYSize, nBlockXSize, nBlockYSize ); } if( HFAGetPCT( hHFA, i, &nColors, &padfRed, &padfGreen, &padfBlue, &padfAlpha, &padfBins ) == CE_None ) { int j; for( j = 0; j < nColors; j++ ) { printf( "PCT[%d] = %f,%f,%f %f\n", (padfBins != NULL) ? (int) padfBins[j] : j, padfRed[j], padfGreen[j], padfBlue[j], padfAlpha[j]); } } /* -------------------------------------------------------------------- */ /* Report statistics. We need to dig directly into the C++ API. */ /* -------------------------------------------------------------------- */ HFABand *poBand = hHFA->papoBand[i-1]; HFAEntry *poStats = poBand->poNode->GetNamedChild( "Statistics" ); if( poStats != NULL ) { printf( " Min: %g Max: %g Mean: %g\n", poStats->GetDoubleField( "minimum" ), poStats->GetDoubleField( "maximum" ), poStats->GetDoubleField( "mean" ) ); printf( " Median: %g Mode: %g Stddev: %g\n", poStats->GetDoubleField( "median" ), poStats->GetDoubleField( "mode" ), poStats->GetDoubleField( "stddev" ) ); } else printf( " No Statistics found.\n" ); } /* -------------------------------------------------------------------- */ /* Dump the map info structure. */ /* -------------------------------------------------------------------- */ psMapInfo = HFAGetMapInfo( hHFA ); if( psMapInfo != NULL ) { printf( "MapInfo.proName = %s\n", psMapInfo->proName ); printf( "MapInfo.upperLeftCenter.x = %.2f\n", psMapInfo->upperLeftCenter.x ); printf( "MapInfo.upperLeftCenter.y = %.2f\n", psMapInfo->upperLeftCenter.y ); } else { printf( "No Map Info found\n" ); } } psProParameters = HFAGetProParameters( hHFA ); psDatum = HFAGetDatum( hHFA ); HFAClose( hHFA ); VSICleanupFileManager(); CPLCleanupTLS(); #ifdef DBMALLOC malloc_dump(1); #endif exit( 0 ); }