1668
1973
return NITFReconcileAttachments( psFile );
1976
/************************************************************************/
1977
/* NITFFindValFromEnd() */
1978
/************************************************************************/
1980
static const char* NITFFindValFromEnd(char** papszMD,
1983
const char* pszDefault)
1985
int nVarLen = strlen(pszVar);
1986
int nIter = nMDSize-1;
1987
for(;nIter >= 0;nIter--)
1989
if (strncmp(papszMD[nIter], pszVar, nVarLen) == 0 &&
1990
papszMD[nIter][nVarLen] == '=')
1991
return papszMD[nIter] + nVarLen + 1;
1996
/************************************************************************/
1997
/* NITFGenericMetadataReadTREInternal() */
1998
/************************************************************************/
2000
static char** NITFGenericMetadataReadTREInternal(char **papszMD,
2003
CPLXMLNode* psOutXMLNode,
2004
const char* pszTREName,
2005
const char *pachTRE,
2007
CPLXMLNode* psTreNode,
2009
const char* pszMDPrefix,
2013
for(psIter = psTreNode->psChild;
2014
psIter != NULL && *pbError == FALSE;
2015
psIter = psIter->psNext)
2017
if (psIter->eType == CXT_Element &&
2018
psIter->pszValue != NULL &&
2019
strcmp(psIter->pszValue, "field") == 0)
2021
const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
2022
const char* pszLongName = CPLGetXMLValue(psIter, "longname", NULL);
2023
const char* pszLength = CPLGetXMLValue(psIter, "length", NULL);
2025
if (pszLength != NULL)
2026
nLength = atoi(pszLength);
2029
const char* pszLengthVar = CPLGetXMLValue(psIter, "length_var", NULL);
2030
if (pszLengthVar != NULL)
2032
char** papszMDIter = papszMD;
2033
while(papszMDIter != NULL && *papszMDIter != NULL)
2035
if (strstr(*papszMDIter, pszLengthVar) != NULL)
2037
const char* pszEqual = strchr(*papszMDIter, '=');
2038
if (pszEqual != NULL)
2040
nLength = atoi(pszEqual + 1);
2048
if (pszName != NULL && nLength > 0)
2050
char* pszMDItemName;
2051
char** papszTmp = NULL;
2053
if (*pnTreOffset + nLength > nTRESize)
2056
CPLError( CE_Warning, CPLE_AppDefined,
2057
"Not enough bytes when reading %s TRE "
2058
"(at least %d needed, only %d available)",
2059
pszTREName, *pnTreOffset + nLength, nTRESize );
2063
pszMDItemName = CPLStrdup(
2064
CPLSPrintf("%s%s", pszMDPrefix, pszName));
2066
NITFExtractMetadata( &papszTmp, pachTRE, *pnTreOffset,
2067
nLength, pszMDItemName );
2068
if (*pnMDSize + 1 >= *pnMDAlloc)
2070
*pnMDAlloc = (*pnMDAlloc * 4 / 3) + 32;
2071
papszMD = (char**)CPLRealloc(papszMD, *pnMDAlloc * sizeof(char**));
2073
papszMD[*pnMDSize] = papszTmp[0];
2074
papszMD[(*pnMDSize) + 1] = NULL;
2079
if (psOutXMLNode != NULL)
2081
const char* pszVal = strchr(papszMD[(*pnMDSize) - 1], '=') + 1;
2082
CPLXMLNode* psFieldNode;
2083
CPLXMLNode* psNameNode;
2084
CPLXMLNode* psValueNode;
2086
CPLAssert(pszVal != NULL);
2088
CPLCreateXMLNode(psOutXMLNode, CXT_Element, "field");
2090
CPLCreateXMLNode(psFieldNode, CXT_Attribute, "name");
2092
CPLCreateXMLNode(psFieldNode, CXT_Attribute, "value");
2093
CPLCreateXMLNode(psNameNode, CXT_Text,
2094
(pszName[0] || pszLongName == NULL) ? pszName : pszLongName);
2095
CPLCreateXMLNode(psValueNode, CXT_Text, pszVal);
2098
CPLFree(pszMDItemName);
2100
*pnTreOffset += nLength;
2102
else if (nLength > 0)
2104
*pnTreOffset += nLength;
2109
CPLError( CE_Warning, CPLE_AppDefined,
2110
"Invalid item construct in %s TRE in XML ressource",
2115
else if (psIter->eType == CXT_Element &&
2116
psIter->pszValue != NULL &&
2117
strcmp(psIter->pszValue, "loop") == 0)
2119
const char* pszCounter = CPLGetXMLValue(psIter, "counter", NULL);
2120
const char* pszIterations = CPLGetXMLValue(psIter, "iterations", NULL);
2121
const char* pszFormula = CPLGetXMLValue(psIter, "formula", NULL);
2122
const char* pszMDSubPrefix = CPLGetXMLValue(psIter, "md_prefix", NULL);
2123
int nIterations = -1;
2125
if (pszCounter != NULL)
2127
char* pszMDItemName = CPLStrdup(
2128
CPLSPrintf("%s%s", pszMDPrefix, pszCounter));
2129
nIterations = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
2130
CPLFree(pszMDItemName);
2131
if (nIterations < 0)
2133
CPLError( CE_Warning, CPLE_AppDefined,
2134
"Invalid loop construct in %s TRE in XML ressource : "
2135
"invalid 'counter' %s",
2136
pszTREName, pszCounter );
2141
else if (pszIterations != NULL)
2143
nIterations = atoi(pszIterations);
2145
else if (pszFormula != NULL &&
2146
strcmp(pszFormula, "(NPART+1)*(NPART)/2") == 0)
2148
char* pszMDItemName = CPLStrdup(
2149
CPLSPrintf("%s%s", pszMDPrefix, "NPART"));
2150
int NPART = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
2151
CPLFree(pszMDItemName);
2154
CPLError( CE_Warning, CPLE_AppDefined,
2155
"Invalid loop construct in %s TRE in XML ressource : "
2156
"invalid 'counter' %s",
2157
pszTREName, "NPART" );
2161
nIterations = NPART * (NPART + 1) / 2;
2163
else if (pszFormula != NULL &&
2164
strcmp(pszFormula, "(NUMOPG+1)*(NUMOPG)/2") == 0)
2166
char* pszMDItemName = CPLStrdup(
2167
CPLSPrintf("%s%s", pszMDPrefix, "NUMOPG"));
2168
int NUMOPG = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
2169
CPLFree(pszMDItemName);
2172
CPLError( CE_Warning, CPLE_AppDefined,
2173
"Invalid loop construct in %s TRE in XML ressource : "
2174
"invalid 'counter' %s",
2175
pszTREName, "NUMOPG" );
2179
nIterations = NUMOPG * (NUMOPG + 1) / 2;
2181
else if (pszFormula != NULL &&
2182
strcmp(pszFormula, "NPAR*NPARO") == 0)
2184
char* pszMDNPARName = CPLStrdup(
2185
CPLSPrintf("%s%s", pszMDPrefix, "NPAR"));
2186
int NPAR = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPARName, "-1"));
2187
char* pszMDNPAROName = CPLStrdup(
2188
CPLSPrintf("%s%s", pszMDPrefix, "NPARO"));
2189
int NPARO= atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPAROName, "-1"));
2190
CPLFree(pszMDNPARName);
2191
CPLFree(pszMDNPAROName);
2194
CPLError( CE_Warning, CPLE_AppDefined,
2195
"Invalid loop construct in %s TRE in XML ressource : "
2196
"invalid 'counter' %s",
2197
pszTREName, "NPAR" );
2203
CPLError( CE_Warning, CPLE_AppDefined,
2204
"Invalid loop construct in %s TRE in XML ressource : "
2205
"invalid 'counter' %s",
2206
pszTREName, "NPAR0" );
2210
nIterations = NPAR*NPARO;
2212
else if (pszFormula != NULL &&
2213
strcmp(pszFormula, "NPLN-1") == 0)
2215
char* pszMDItemName = CPLStrdup(
2216
CPLSPrintf("%s%s", pszMDPrefix, "NPLN"));
2217
int NPLN = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
2218
CPLFree(pszMDItemName);
2221
CPLError( CE_Warning, CPLE_AppDefined,
2222
"Invalid loop construct in %s TRE in XML ressource : "
2223
"invalid 'counter' %s",
2224
pszTREName, "NPLN" );
2228
nIterations = NPLN-1;
2230
else if (pszFormula != NULL &&
2231
strcmp(pszFormula, "NXPTS*NYPTS") == 0)
2233
char* pszMDNPARName = CPLStrdup(
2234
CPLSPrintf("%s%s", pszMDPrefix, "NXPTS"));
2235
int NXPTS = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPARName, "-1"));
2236
char* pszMDNPAROName = CPLStrdup(
2237
CPLSPrintf("%s%s", pszMDPrefix, "NYPTS"));
2238
int NYPTS= atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPAROName, "-1"));
2239
CPLFree(pszMDNPARName);
2240
CPLFree(pszMDNPAROName);
2243
CPLError( CE_Warning, CPLE_AppDefined,
2244
"Invalid loop construct in %s TRE in XML ressource : "
2245
"invalid 'counter' %s",
2246
pszTREName, "NXPTS" );
2252
CPLError( CE_Warning, CPLE_AppDefined,
2253
"Invalid loop construct in %s TRE in XML ressource : "
2254
"invalid 'counter' %s",
2255
pszTREName, "NYPTS" );
2259
nIterations = NXPTS*NYPTS;
2263
CPLError( CE_Warning, CPLE_AppDefined,
2264
"Invalid loop construct in %s TRE in XML ressource : "
2265
"missing or invalid 'counter' or 'iterations' or 'formula'",
2271
if (nIterations > 0)
2274
const char* pszPercent;
2275
int bHasValidPercentD = FALSE;
2276
CPLXMLNode* psRepeatedNode = NULL;
2277
CPLXMLNode* psLastChild = NULL;
2279
/* Check that md_prefix has one and only %XXXXd pattern */
2280
if (pszMDSubPrefix != NULL &&
2281
(pszPercent = strchr(pszMDSubPrefix, '%')) != NULL &&
2282
strchr(pszPercent+1,'%') == NULL)
2284
const char* pszIter = pszPercent + 1;
2285
while(*pszIter != '\0')
2287
if (*pszIter >= '0' && *pszIter <= '9')
2289
else if (*pszIter == 'd')
2291
bHasValidPercentD = atoi(pszPercent + 1) <= 10;
2299
if (psOutXMLNode != NULL)
2301
CPLXMLNode* psNumberNode;
2302
CPLXMLNode* psNameNode;
2303
const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
2304
psRepeatedNode = CPLCreateXMLNode(psOutXMLNode, CXT_Element, "repeated");
2307
psNameNode = CPLCreateXMLNode(psRepeatedNode, CXT_Attribute, "name");
2308
CPLCreateXMLNode(psNameNode, CXT_Text, pszName);
2310
psNumberNode = CPLCreateXMLNode(psRepeatedNode, CXT_Attribute, "number");
2311
CPLCreateXMLNode(psNumberNode, CXT_Text, CPLSPrintf("%d", nIterations));
2313
psLastChild = psRepeatedNode->psChild;
2314
while(psLastChild->psNext != NULL)
2315
psLastChild = psLastChild->psNext;
2318
for(iIter = 0; iIter < nIterations && *pbError == FALSE; iIter++)
2320
char* pszMDNewPrefix = NULL;
2321
CPLXMLNode* psGroupNode = NULL;
2322
if (pszMDSubPrefix != NULL)
2324
if (bHasValidPercentD)
2326
char* szTmp = (char*)CPLMalloc(
2327
strlen(pszMDSubPrefix) + 10 + 1);
2328
sprintf(szTmp, pszMDSubPrefix, iIter + 1);
2329
pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%s",
2330
pszMDPrefix, szTmp));
2334
pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%s%04d_",
2335
pszMDPrefix, pszMDSubPrefix, iIter + 1));
2338
pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%04d_",
2339
pszMDPrefix, iIter + 1));
2341
if (psRepeatedNode != NULL)
2343
CPLXMLNode* psIndexNode;
2344
psGroupNode = CPLCreateXMLNode(NULL, CXT_Element, "group");
2345
CPLAssert(psLastChild->psNext == NULL);
2346
psLastChild->psNext = psGroupNode;
2347
psLastChild = psGroupNode;
2348
psIndexNode = CPLCreateXMLNode(psGroupNode, CXT_Attribute, "index");
2349
CPLCreateXMLNode(psIndexNode, CXT_Text, CPLSPrintf("%d", iIter));
2352
papszMD = NITFGenericMetadataReadTREInternal(papszMD,
2363
CPLFree(pszMDNewPrefix);
2367
else if (psIter->eType == CXT_Element &&
2368
psIter->pszValue != NULL &&
2369
strcmp(psIter->pszValue, "if") == 0)
2371
const char* pszCond = CPLGetXMLValue(psIter, "cond", NULL);
2372
const char* pszEqual = NULL;
2373
if (pszCond != NULL && strcmp(pszCond, "QSS!=U AND QOD!=Y") == 0)
2375
char* pszQSSName = CPLStrdup(
2376
CPLSPrintf("%s%s", pszMDPrefix, "QSS"));
2377
char* pszQODName = CPLStrdup(
2378
CPLSPrintf("%s%s", pszMDPrefix, "QOD"));
2379
const char* pszQSSVal = NITFFindValFromEnd(papszMD, *pnMDSize, pszQSSName, NULL);
2380
const char* pszQODVal = NITFFindValFromEnd(papszMD, *pnMDSize, pszQODName, NULL);
2381
if (pszQSSVal == NULL)
2383
CPLDebug("NITF", "Cannot find if cond variable %s", "QSS");
2385
else if (pszQODVal == NULL)
2387
CPLDebug("NITF", "Cannot find if cond variable %s", "QOD");
2389
else if (strcmp(pszQSSVal, "U") != 0 && strcmp(pszQODVal, "Y") != 0)
2391
papszMD = NITFGenericMetadataReadTREInternal(papszMD,
2403
CPLFree(pszQSSName);
2404
CPLFree(pszQODName);
2406
else if (pszCond != NULL && (pszEqual = strchr(pszCond, '=')) != NULL)
2408
char* pszCondVar = (char*)CPLMalloc(pszEqual - pszCond + 1);
2409
const char* pszCondExpectedVal = pszEqual + 1;
2410
char* pszMDItemName;
2411
const char* pszCondVal;
2412
int bTestEqual = TRUE;
2413
memcpy(pszCondVar, pszCond, pszEqual - pszCond);
2414
if (pszEqual - pszCond > 1 && pszCondVar[pszEqual - pszCond - 1] == '!')
2417
pszCondVar[pszEqual - pszCond - 1] = '\0';
2419
pszCondVar[pszEqual - pszCond] = '\0';
2420
pszMDItemName = CPLStrdup(
2421
CPLSPrintf("%s%s", pszMDPrefix, pszCondVar));
2422
pszCondVal = NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, NULL);
2423
if (pszCondVal == NULL)
2425
CPLDebug("NITF", "Cannot find if cond variable %s",
2428
else if ((bTestEqual && strcmp(pszCondVal, pszCondExpectedVal) == 0) ||
2429
(!bTestEqual && strcmp(pszCondVal, pszCondExpectedVal) != 0))
2431
papszMD = NITFGenericMetadataReadTREInternal(papszMD,
2443
CPLFree(pszMDItemName);
2444
CPLFree(pszCondVar);
2448
CPLError( CE_Warning, CPLE_AppDefined,
2449
"Invalid if construct in %s TRE in XML ressource : "
2450
"missing or invalid 'cond' attribute",
2456
else if (psIter->eType == CXT_Element &&
2457
psIter->pszValue != NULL &&
2458
strcmp(psIter->pszValue, "if_remaining_bytes") == 0)
2460
if (*pnTreOffset < nTRESize)
2462
papszMD = NITFGenericMetadataReadTREInternal(papszMD,
2477
//CPLDebug("NITF", "Unknown element : %s", psIter->pszValue ? psIter->pszValue : "null");
2483
/************************************************************************/
2484
/* NITFGenericMetadataReadTRE() */
2485
/************************************************************************/
2488
char **NITFGenericMetadataReadTRE(char **papszMD,
2489
const char* pszTREName,
2490
const char *pachTRE,
2492
CPLXMLNode* psTreNode)
2494
int nTreLength, nTreMinLength = -1, nTreMaxLength = -1;
2497
const char* pszMDPrefix;
2498
int nMDSize, nMDAlloc;
2500
nTreLength = atoi(CPLGetXMLValue(psTreNode, "length", "-1"));
2501
nTreMinLength = atoi(CPLGetXMLValue(psTreNode, "minlength", "-1"));
2502
nTreMaxLength = atoi(CPLGetXMLValue(psTreNode, "maxlength", "-1"));
2504
if( (nTreLength > 0 && nTRESize != nTreLength) ||
2505
(nTreMinLength > 0 && nTRESize < nTreMinLength) )
2507
CPLError( CE_Warning, CPLE_AppDefined,
2508
"%s TRE wrong size, ignoring.", pszTREName );
2512
pszMDPrefix = CPLGetXMLValue(psTreNode, "md_prefix", "");
2514
nMDSize = nMDAlloc = CSLCount(papszMD);
2516
papszMD = NITFGenericMetadataReadTREInternal(papszMD,
2528
if (bError == FALSE && nTreLength > 0 && nTreOffset != nTreLength)
2530
CPLError( CE_Warning, CPLE_AppDefined,
2531
"Inconsistant declaration of %s TRE",
2534
if (nTreOffset < nTRESize)
2535
CPLDebug("NITF", "%d remaining bytes at end of %s TRE",
2536
nTRESize -nTreOffset, pszTREName);
2542
/************************************************************************/
2543
/* NITFLoadXMLSpec() */
2544
/************************************************************************/
2546
#define NITF_SPEC_FILE "nitf_spec.xml"
2548
static CPLXMLNode* NITFLoadXMLSpec(NITFFile* psFile)
2551
if (psFile->psNITFSpecNode == NULL)
2553
const char* pszXMLDescFilename = CPLFindFile("gdal", NITF_SPEC_FILE);
2554
if (pszXMLDescFilename == NULL)
2556
CPLDebug("NITF", "Cannot find XML file : %s", NITF_SPEC_FILE);
2559
psFile->psNITFSpecNode = CPLParseXMLFile(pszXMLDescFilename);
2560
if (psFile->psNITFSpecNode == NULL)
2562
CPLDebug("NITF", "Invalid XML file : %s", pszXMLDescFilename);
2567
return psFile->psNITFSpecNode;
2570
/************************************************************************/
2571
/* NITFFindTREXMLDescFromName() */
2572
/************************************************************************/
2574
static CPLXMLNode* NITFFindTREXMLDescFromName(NITFFile* psFile,
2575
const char* pszTREName)
2577
CPLXMLNode* psTreeNode;
2578
CPLXMLNode* psTresNode;
2581
psTreeNode = NITFLoadXMLSpec(psFile);
2582
if (psTreeNode == NULL)
2585
psTresNode = CPLGetXMLNode(psTreeNode, "=tres");
2586
if (psTresNode == NULL)
2588
CPLDebug("NITF", "Cannot find <tres> root element");
2592
for(psIter = psTresNode->psChild;psIter != NULL;psIter = psIter->psNext)
2594
if (psIter->eType == CXT_Element &&
2595
psIter->pszValue != NULL &&
2596
strcmp(psIter->pszValue, "tre") == 0)
2598
const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
2599
if (pszName != NULL && strcmp(pszName, pszTREName) == 0)
2609
/************************************************************************/
2610
/* NITFCreateXMLTre() */
2611
/************************************************************************/
2613
CPLXMLNode* NITFCreateXMLTre(NITFFile* psFile,
2614
const char* pszTREName,
2615
const char *pachTRE,
2618
int nTreLength, nTreMinLength = -1, nTreMaxLength = -1;
2621
CPLXMLNode* psTreNode;
2622
CPLXMLNode* psOutXMLNode = NULL;
2623
int nMDSize = 0, nMDAlloc = 0;
2625
psTreNode = NITFFindTREXMLDescFromName(psFile, pszTREName);
2626
if (psTreNode == NULL)
2628
if (!(EQUALN(pszTREName, "RPF", 3) || strcmp(pszTREName, "XXXXXX") == 0))
2630
CPLDebug("NITF", "Cannot find definition of TRE %s in %s",
2631
pszTREName, NITF_SPEC_FILE);
2636
nTreLength = atoi(CPLGetXMLValue(psTreNode, "length", "-1"));
2637
nTreMinLength = atoi(CPLGetXMLValue(psTreNode, "minlength", "-1"));
2638
nTreMaxLength = atoi(CPLGetXMLValue(psTreNode, "maxlength", "-1"));
2640
if( (nTreLength > 0 && nTRESize != nTreLength) ||
2641
(nTreMinLength > 0 && nTRESize < nTreMinLength) )
2643
CPLError( CE_Warning, CPLE_AppDefined,
2644
"%s TRE wrong size, ignoring.", pszTREName );
2648
psOutXMLNode = CPLCreateXMLNode(NULL, CXT_Element, "tre");
2649
CPLCreateXMLNode(CPLCreateXMLNode(psOutXMLNode, CXT_Attribute, "name"),
2650
CXT_Text, pszTREName);
2652
CSLDestroy(NITFGenericMetadataReadTREInternal(NULL,
2664
if (bError == FALSE && nTreLength > 0 && nTreOffset != nTreLength)
2666
CPLError( CE_Warning, CPLE_AppDefined,
2667
"Inconsistant declaration of %s TRE",
2670
if (nTreOffset < nTRESize)
2671
CPLDebug("NITF", "%d remaining bytes at end of %s TRE",
2672
nTRESize -nTreOffset, pszTREName);
2674
return psOutXMLNode;
2677
/************************************************************************/
2678
/* NITFGenericMetadataRead() */
2680
/* Add metadata from TREs of file and image objects in the papszMD list */
2681
/* pszSpecificTRE can be NULL, in which case all TREs listed in */
2682
/* data/nitf_resources.xml that have md_prefix defined will be looked */
2683
/* for. If not NULL, only the specified one will be looked for. */
2684
/************************************************************************/
2686
char **NITFGenericMetadataRead( char **papszMD,
2689
const char* pszSpecificTREName)
2691
CPLXMLNode* psTreeNode = NULL;
2692
CPLXMLNode* psTresNode = NULL;
2693
CPLXMLNode* psIter = NULL;
2695
if (psFile == NULL && psImage == NULL)
2698
psTreeNode = NITFLoadXMLSpec(psFile ? psFile : psImage->psFile);
2699
if (psTreeNode == NULL)
2702
psTresNode = CPLGetXMLNode(psTreeNode, "=tres");
2703
if (psTresNode == NULL)
2705
CPLDebug("NITF", "Cannot find <tres> root element");
2709
for(psIter = psTresNode->psChild;psIter!=NULL;psIter = psIter->psNext)
2711
if (psIter->eType == CXT_Element &&
2712
psIter->pszValue != NULL &&
2713
strcmp(psIter->pszValue, "tre") == 0)
2715
const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
2716
const char* pszMDPrefix = CPLGetXMLValue(psIter, "md_prefix", NULL);
2717
if (pszName != NULL && ((pszSpecificTREName == NULL && pszMDPrefix != NULL) ||
2718
(pszSpecificTREName != NULL && strcmp(pszName, pszSpecificTREName) == 0)))
2722
const char *pachTRE = NULL;
2725
pachTRE = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,
2726
pszName, &nTRESize);
2727
if( pachTRE != NULL )
2728
papszMD = NITFGenericMetadataReadTRE(
2729
papszMD, pszName, pachTRE, nTRESize, psIter);
2731
if (psImage != NULL)
2733
const char *pachTRE = NULL;
2736
pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
2737
pszName, &nTRESize);
2738
if( pachTRE != NULL )
2739
papszMD = NITFGenericMetadataReadTRE(
2740
papszMD, pszName, pachTRE, nTRESize, psIter);
2742
if (pszSpecificTREName)