LCOV - code coverage report
Current view: directory - gcore - gdal_rpcimdio.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 224 130 58.0 %
Date: 2012-12-26 Functions: 7 6 85.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdal_rpcimdio.cpp 22057 2011-03-28 15:20:21Z warmerdam $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Functions for reading RPC and IMD formats, and normalizing.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) HER MAJESTY THE QUEEN IN RIGHT OF CANADA (2008)
      10                 :  * as represented by the Canadian Nuclear Safety Commission
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdal.h"
      32                 : #include "gdal_priv.h"
      33                 : #include "cpl_string.h"
      34                 : #include "cplkeywordparser.h"
      35                 : 
      36                 : CPL_CVSID("$Id: gdal_rpcimdio.cpp 22057 2011-03-28 15:20:21Z warmerdam $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                          GDALLoadRPBFile()                           */
      40                 : /************************************************************************/
      41                 : 
      42                 : static const char *apszRPBMap[] = {
      43                 :     "LINE_OFF",       "IMAGE.lineOffset",
      44                 :     "SAMP_OFF",       "IMAGE.sampOffset",
      45                 :     "LAT_OFF",        "IMAGE.latOffset",
      46                 :     "LONG_OFF",       "IMAGE.longOffset",
      47                 :     "HEIGHT_OFF",     "IMAGE.heightOffset",
      48                 :     "LINE_SCALE",     "IMAGE.lineScale",
      49                 :     "SAMP_SCALE",     "IMAGE.sampScale",
      50                 :     "LAT_SCALE",      "IMAGE.latScale",
      51                 :     "LONG_SCALE",     "IMAGE.longScale",
      52                 :     "HEIGHT_SCALE",   "IMAGE.heightScale",
      53                 :     "LINE_NUM_COEFF", "IMAGE.lineNumCoef",
      54                 :     "LINE_DEN_COEFF", "IMAGE.lineDenCoef",
      55                 :     "SAMP_NUM_COEFF", "IMAGE.sampNumCoef",
      56                 :     "SAMP_DEN_COEFF", "IMAGE.sampDenCoef",
      57                 :     NULL,             NULL };
      58                 : 
      59               8 : char **CPL_STDCALL GDALLoadRPBFile( const char *pszFilename,
      60                 :                                     char **papszSiblingFiles )
      61                 : 
      62                 : {
      63                 : /* -------------------------------------------------------------------- */
      64                 : /*      Try to identify the RPB file in upper or lower case.            */
      65                 : /* -------------------------------------------------------------------- */
      66                 :     CPLString osTarget = GDALFindAssociatedFile( pszFilename, "RPB", 
      67               8 :                                                  papszSiblingFiles, 0 );
      68                 : 
      69               8 :     if( osTarget == "" )
      70               0 :         return NULL;
      71                 : 
      72                 : /* -------------------------------------------------------------------- */
      73                 : /*      Read file and parse.                                            */
      74                 : /* -------------------------------------------------------------------- */
      75               8 :     CPLKeywordParser oParser;
      76                 : 
      77               8 :     VSILFILE *fp = VSIFOpenL( osTarget, "r" );
      78                 : 
      79               8 :     if( fp == NULL )
      80               0 :         return NULL;
      81                 :     
      82               8 :     if( !oParser.Ingest( fp ) )
      83                 :     {
      84               0 :         VSIFCloseL( fp );
      85               0 :         return NULL;
      86                 :     }
      87                 : 
      88               8 :     VSIFCloseL( fp );
      89                 : 
      90                 : /* -------------------------------------------------------------------- */
      91                 : /*      Extract RPC information, in a GDAL "standard" metadata format.  */
      92                 : /* -------------------------------------------------------------------- */
      93                 :     int i;
      94               8 :     char **papszMD = NULL;
      95               8 :     for( i = 0; apszRPBMap[i] != NULL; i += 2 )
      96                 :     {
      97             112 :         const char *pszRPBVal = oParser.GetKeyword( apszRPBMap[i+1] );
      98             112 :         CPLString osAdjVal;
      99                 : 
     100             112 :         if( pszRPBVal == NULL )
     101                 :         {
     102                 :             CPLError( CE_Failure, CPLE_AppDefined,
     103                 :                       "%s file found, but missing %s field (and possibly others).",
     104               0 :                       osTarget.c_str(), apszRPBMap[i+1] );
     105               0 :             CSLDestroy( papszMD );
     106               0 :             return NULL;
     107                 :         }
     108                 : 
     109             112 :         if( strchr(pszRPBVal,',') == NULL )
     110              80 :             osAdjVal = pszRPBVal;
     111                 :         else
     112                 :         {
     113                 :             // strip out commas and turn newlines into spaces.
     114                 :             int j;
     115                 : 
     116            9024 :             for( j = 0; pszRPBVal[j] != '\0'; j++ )
     117                 :             {
     118            8992 :                 switch( pszRPBVal[j] ) 
     119                 :                 {
     120                 :                   case ',':
     121                 :                   case '\n':
     122                 :                   case '\r':
     123             608 :                     osAdjVal += ' ';
     124             608 :                     break;
     125                 :                     
     126                 :                   case '(':
     127                 :                   case ')':
     128              64 :                     break;
     129                 : 
     130                 :                   default:
     131            8320 :                     osAdjVal += pszRPBVal[j];
     132                 :                 }
     133                 :             }
     134                 :         }
     135                 : 
     136             112 :         papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], osAdjVal );
     137                 :     }
     138                 : 
     139               8 :     return papszMD;
     140                 : }
     141                 : 
     142                 : /************************************************************************/
     143                 : /*                          GDALLoadRPCFile()                           */
     144                 : /************************************************************************/
     145                 : 
     146                 : /* Load a GeoEye _rpc.txt file. See ticket http://trac.osgeo.org/gdal/ticket/3639 */
     147                 : 
     148               1 : char **CPL_STDCALL GDALLoadRPCFile( const char *pszFilename,
     149                 :                                     char **papszSiblingFiles )
     150                 : 
     151                 : {
     152                 : /* -------------------------------------------------------------------- */
     153                 : /*      Try to identify the RPC file in upper or lower case.            */
     154                 : /* -------------------------------------------------------------------- */
     155               1 :     CPLString osTarget; 
     156                 : 
     157                 :     /* Is this already a _RPC.TXT file ? */
     158               2 :     if (strlen(pszFilename) > 8 && EQUAL(pszFilename + strlen(pszFilename) - 8, "_RPC.TXT"))
     159               1 :         osTarget = pszFilename;
     160                 :     else
     161                 :     {
     162               0 :         CPLString osSrcPath = pszFilename;
     163               0 :         CPLString soPt(".");
     164               0 :         size_t found = osSrcPath.rfind(soPt);
     165               0 :         if (found == CPLString::npos)
     166               0 :             return NULL;
     167               0 :         osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt");
     168               0 :         CPLString osTarget = osSrcPath; 
     169                 : 
     170               0 :         if( papszSiblingFiles == NULL )
     171                 :         {
     172                 :             VSIStatBufL sStatBuf;
     173                 : 
     174               0 :             if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     175                 :             {
     176               0 :                 osSrcPath = pszFilename;
     177               0 :                 osSrcPath.replace (found, osSrcPath.size() - found, "_RPC.TXT");
     178               0 :                 osTarget = osSrcPath; 
     179                 : 
     180               0 :                 if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     181                 :                 {
     182               0 :                     osSrcPath = pszFilename;
     183               0 :                     osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.TXT");
     184               0 :                     osTarget = osSrcPath; 
     185                 : 
     186               0 :                     if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     187                 :                     {
     188               0 :                         return NULL;
     189                 :                     }
     190                 :                 }
     191                 :             }
     192                 :         }
     193                 :         else
     194                 :         {
     195                 :             int iSibling = CSLFindString( papszSiblingFiles, 
     196               0 :                                         CPLGetFilename(osTarget) );
     197               0 :             if( iSibling < 0 )
     198               0 :                 return NULL;
     199                 : 
     200               0 :             osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
     201               0 :             osTarget += papszSiblingFiles[iSibling];
     202               0 :         }
     203                 :     }
     204                 : 
     205                 : /* -------------------------------------------------------------------- */
     206                 : /*      Read file and parse.                                            */
     207                 : /* -------------------------------------------------------------------- */
     208               1 :     char **papszLines = CSLLoad2( osTarget, 100, 100, NULL );
     209               1 :     if(!papszLines)
     210               0 :         return NULL;
     211                 : 
     212               1 :     char **papszMD = NULL;
     213                 : 
     214                 :     /* From LINE_OFF to HEIGHT_SCALE */
     215              11 :     for(size_t i = 0; i < 19; i += 2 )
     216                 :     {
     217              10 :         const char *pszRPBVal = CSLFetchNameValue(papszLines, apszRPBMap[i] );
     218              10 :         if( pszRPBVal == NULL )
     219                 :         {
     220                 :             CPLError( CE_Failure, CPLE_AppDefined,
     221                 :                 "%s file found, but missing %s field (and possibly others).",
     222               0 :                 osTarget.c_str(), apszRPBMap[i]);
     223               0 :             CSLDestroy( papszMD );
     224               0 :             CSLDestroy( papszLines );
     225               0 :             return NULL;
     226                 :         }
     227                 :         else
     228                 :         {
     229              10 :             papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], pszRPBVal );
     230                 :         }
     231                 :     }
     232                 :        
     233                 :     /* For LINE_NUM_COEFF, LINE_DEN_COEFF, SAMP_NUM_COEFF, SAMP_DEN_COEFF */
     234                 :     /* parameters that have 20 values each */
     235               1 :     for(size_t i = 20; apszRPBMap[i] != NULL; i += 2 )
     236                 :     {
     237               4 :         CPLString soVal;
     238               4 :         for(int j = 1; j <= 20; j++)
     239                 :         {
     240              80 :             CPLString soRPBMapItem;
     241              80 :             soRPBMapItem.Printf("%s_%d", apszRPBMap[i], j);
     242              80 :             const char *pszRPBVal = CSLFetchNameValue(papszLines, soRPBMapItem.c_str() );
     243              80 :             if( pszRPBVal == NULL )
     244                 :             {
     245                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     246                 :                     "%s file found, but missing %s field (and possibly others).",
     247               0 :                     osTarget.c_str(), soRPBMapItem.c_str() );
     248               0 :                 CSLDestroy( papszMD );
     249               0 :                 CSLDestroy( papszLines );
     250               0 :                 return NULL;
     251                 :             }
     252                 :             else
     253                 :             {
     254              80 :                 soVal += pszRPBVal;
     255              80 :                 soVal += " ";
     256                 :             }
     257                 :         }
     258               4 :         papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], soVal.c_str() );
     259                 :     }
     260                 : 
     261               1 :     CSLDestroy( papszLines );
     262               1 :     return papszMD;
     263                 : }
     264                 : 
     265                 : /************************************************************************/
     266                 : /*                          GDALWriteRPBFile()                          */
     267                 : /************************************************************************/
     268                 : 
     269               2 : CPLErr CPL_STDCALL GDALWriteRPBFile( const char *pszFilename, char **papszMD )
     270                 : 
     271                 : {
     272               2 :     CPLString osRPBFilename = CPLResetExtension( pszFilename, "RPB" );
     273                 :     
     274                 : 
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      Read file and parse.                                            */
     277                 : /* -------------------------------------------------------------------- */
     278               2 :     VSILFILE *fp = VSIFOpenL( osRPBFilename, "w" );
     279                 : 
     280               2 :     if( fp == NULL )
     281                 :     {
     282                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     283                 :                   "Unable to create %s for writing.\n%s", 
     284               0 :                   osRPBFilename.c_str(), CPLGetLastErrorMsg() );
     285               0 :         return CE_Failure;
     286                 :     }
     287                 :     
     288                 : /* -------------------------------------------------------------------- */
     289                 : /*      Write the prefix information.                                   */
     290                 : /* -------------------------------------------------------------------- */
     291               2 :     VSIFPrintfL( fp, "%s", "satId = \"QB02\";\n" );
     292               2 :     VSIFPrintfL( fp, "%s", "bandId = \"P\";\n" );
     293               2 :     VSIFPrintfL( fp, "%s", "SpecId = \"RPC00B\";\n" );
     294               2 :     VSIFPrintfL( fp, "%s", "BEGIN_GROUP = IMAGE\n" );
     295               2 :     VSIFPrintfL( fp, "%s", "\terrBias = 0.0;\n" );
     296               2 :     VSIFPrintfL( fp, "%s", "\terrRand = 0.0;\n" );
     297                 : 
     298                 : /* -------------------------------------------------------------------- */
     299                 : /*      Write RPC values from our RPC metadata.                         */
     300                 : /* -------------------------------------------------------------------- */
     301                 :     int i;
     302                 : 
     303              30 :     for( i = 0; apszRPBMap[i] != NULL; i += 2 )
     304                 :     {
     305              28 :         const char *pszRPBVal = CSLFetchNameValue( papszMD, apszRPBMap[i] );
     306                 :         const char *pszRPBTag;
     307                 : 
     308              28 :         if( pszRPBVal == NULL )
     309                 :         {
     310                 :             CPLError( CE_Failure, CPLE_AppDefined,
     311                 :                       "%s field missing in metadata, %s file not written.",
     312               0 :                       apszRPBMap[i], osRPBFilename.c_str() );
     313               0 :             VSIFCloseL( fp );
     314               0 :             VSIUnlink( osRPBFilename );
     315               0 :             return CE_Failure;
     316                 :         }
     317                 : 
     318              28 :         pszRPBTag = apszRPBMap[i+1];
     319              28 :         if( EQUALN(pszRPBTag,"IMAGE.",6) )
     320              28 :             pszRPBTag += 6;
     321                 : 
     322              28 :         if( strstr(apszRPBMap[i], "COEF" ) == NULL )
     323                 :         {
     324              20 :             VSIFPrintfL( fp, "\t%s = %s;\n", pszRPBTag, pszRPBVal );
     325                 :         }
     326                 :         else
     327                 :         {
     328                 :             // Reformat in brackets with commas over multiple lines.
     329                 : 
     330               8 :             VSIFPrintfL( fp, "\t%s = (\n", pszRPBTag );
     331                 : 
     332                 :             char **papszItems = CSLTokenizeStringComplex( pszRPBVal, " ,", 
     333               8 :                                                           FALSE, FALSE );
     334                 : 
     335               8 :             if( CSLCount(papszItems) != 20 )
     336                 :             {
     337                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     338                 :                           "%s field is corrupt (not 20 values), %s file not written.\n%s = %s",
     339                 :                           apszRPBMap[i], osRPBFilename.c_str(),
     340               0 :                           apszRPBMap[i], pszRPBVal );
     341               0 :                 VSIFCloseL( fp );
     342               0 :                 VSIUnlink( osRPBFilename );
     343               0 :                 return CE_Failure;
     344                 :             }
     345                 : 
     346                 :             int j;
     347                 : 
     348             168 :             for( j = 0; j < 20; j++ )
     349                 :             {
     350             160 :                 if( j < 19 )
     351             152 :                     VSIFPrintfL( fp, "\t\t\t%s,\n", papszItems[j] );
     352                 :                 else
     353               8 :                     VSIFPrintfL( fp, "\t\t\t%s);\n", papszItems[j] );
     354                 :             }
     355               8 :             CSLDestroy( papszItems );
     356                 :         }
     357                 :     }
     358                 : 
     359                 : /* -------------------------------------------------------------------- */
     360                 : /*      Write end part                                                  */
     361                 : /* -------------------------------------------------------------------- */
     362               2 :     VSIFPrintfL( fp, "%s", "END_GROUP = IMAGE\n" );
     363               2 :     VSIFPrintfL( fp, "END;\n" );
     364               2 :     VSIFCloseL( fp );
     365                 :     
     366               2 :     return CE_None;
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                           GDAL_IMD_AA2R()                            */
     371                 : /*                                                                      */
     372                 : /*      Translate AA version IMD file to R version.                     */
     373                 : /************************************************************************/
     374                 : 
     375               0 : static int GDAL_IMD_AA2R( char ***ppapszIMD )
     376                 : 
     377                 : {
     378               0 :     char **papszIMD = *ppapszIMD;
     379                 : 
     380                 : /* -------------------------------------------------------------------- */
     381                 : /*      Verify that we have a new format file.                          */
     382                 : /* -------------------------------------------------------------------- */
     383               0 :     const char *pszValue = CSLFetchNameValue( papszIMD, "version" );
     384                 :     
     385               0 :     if( pszValue == NULL )
     386               0 :         return FALSE;
     387                 :     
     388               0 :     if( EQUAL(pszValue,"\"R\"") )
     389               0 :         return TRUE;
     390                 : 
     391               0 :     if( !EQUAL(pszValue,"\"AA\"") )
     392                 :     {
     393               0 :         CPLDebug( "IMD", "The file is not the expected 'version = \"AA\"' format.\nProceeding, but file may be corrupted." );
     394                 :     }
     395                 : 
     396                 : /* -------------------------------------------------------------------- */
     397                 : /*      Fix the version line.                                           */
     398                 : /* -------------------------------------------------------------------- */
     399               0 :     papszIMD = CSLSetNameValue( papszIMD, "version", "\"R\"" );
     400                 : 
     401                 : /* -------------------------------------------------------------------- */
     402                 : /*      remove a bunch of fields.                                       */
     403                 : /* -------------------------------------------------------------------- */
     404                 :     int iKey;
     405                 : 
     406                 :     static const char *apszToRemove[] = {
     407                 :         "productCatalogId",
     408                 :         "childCatalogId",
     409                 :         "productType",
     410                 :         "numberOfLooks",
     411                 :         "effectiveBandwidth",
     412                 :         "mode",
     413                 :         "scanDirection",
     414                 :         "cloudCover",
     415                 :         "productGSD",
     416                 :         NULL };
     417                 : 
     418               0 :     for( iKey = 0; apszToRemove[iKey] != NULL; iKey++ )
     419                 :     {
     420               0 :         int iTarget = CSLFindName( papszIMD, apszToRemove[iKey] );
     421               0 :         if( iTarget != -1 )
     422               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     423                 :     }
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      Replace various min/mean/max with just the mean.                */
     427                 : /* -------------------------------------------------------------------- */
     428                 :     static const char *keylist[] = { 
     429                 :         "CollectedRowGSD",
     430                 :         "CollectedColGSD",
     431                 :         "SunAz",
     432                 :         "SunEl",
     433                 :         "SatAz",
     434                 :         "SatEl",
     435                 :         "InTrackViewAngle",
     436                 :         "CrossTrackViewAngle",
     437                 :         "OffNadirViewAngle",
     438                 :         NULL };
     439                 : 
     440               0 :     for( iKey = 0; keylist[iKey] != NULL; iKey++ )
     441                 :     {
     442               0 :         CPLString osTarget;
     443                 :         int       iTarget;
     444                 : 
     445               0 :         osTarget.Printf( "IMAGE_1.min%s", keylist[iKey] );
     446               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     447               0 :         if( iTarget != -1 )
     448               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     449                 : 
     450               0 :         osTarget.Printf( "IMAGE_1.max%s", keylist[iKey] );
     451               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     452               0 :         if( iTarget != -1 )
     453               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     454                 : 
     455               0 :         osTarget.Printf( "IMAGE_1.mean%s", keylist[iKey] );
     456               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     457               0 :         if( iTarget != -1 )
     458                 :         {
     459               0 :             CPLString osValue = CSLFetchNameValue( papszIMD, osTarget );
     460               0 :             CPLString osLine;
     461                 :             
     462                 :             osTarget.Printf( "IMAGE_1.%c%s", 
     463               0 :                              tolower(keylist[iKey][0]), 
     464               0 :                              keylist[iKey]+1 );
     465                 : 
     466               0 :             osLine = osTarget + "=" + osValue;
     467                 : 
     468               0 :             CPLFree( papszIMD[iTarget] );
     469               0 :             papszIMD[iTarget] = CPLStrdup(osLine);
     470                 :         }
     471                 :     }
     472                 : 
     473               0 :     *ppapszIMD = papszIMD;
     474               0 :     return TRUE;
     475                 : }
     476                 : 
     477                 : /************************************************************************/
     478                 : /*                          GDALLoadIMDFile()                           */
     479                 : /************************************************************************/
     480                 : 
     481              10 : char ** CPL_STDCALL GDALLoadIMDFile( const char *pszFilename,
     482                 :                                      char **papszSiblingFiles )
     483                 : 
     484                 : {
     485                 : /* -------------------------------------------------------------------- */
     486                 : /*      Try to identify the IMD file in upper or lower case.            */
     487                 : /* -------------------------------------------------------------------- */
     488                 :     CPLString osTarget = GDALFindAssociatedFile( pszFilename, "IMD", 
     489              10 :                                                  papszSiblingFiles, 0 );
     490                 : 
     491              10 :     if( osTarget == "" )
     492               0 :         return NULL;
     493                 : 
     494                 : /* -------------------------------------------------------------------- */
     495                 : /*      Read file and parse.                                            */
     496                 : /* -------------------------------------------------------------------- */
     497              10 :     CPLKeywordParser oParser;
     498                 : 
     499              10 :     VSILFILE *fp = VSIFOpenL( osTarget, "r" );
     500                 : 
     501              10 :     if( fp == NULL )
     502               0 :         return NULL;
     503                 :     
     504              10 :     if( !oParser.Ingest( fp ) )
     505                 :     {
     506               0 :         VSIFCloseL( fp );
     507               0 :         return NULL;
     508                 :     }
     509                 : 
     510              10 :     VSIFCloseL( fp );
     511                 : 
     512                 : /* -------------------------------------------------------------------- */
     513                 : /*      Consider version changing.                                      */
     514                 : /* -------------------------------------------------------------------- */
     515              10 :     char **papszIMD = CSLDuplicate( oParser.GetAllKeywords() );
     516              10 :     const char *pszVersion = CSLFetchNameValue( papszIMD, "version" );
     517                 : 
     518              10 :     if( pszVersion == NULL )
     519                 :     {
     520                 :         /* ? */;
     521                 :     }
     522               8 :     else if( EQUAL(pszVersion,"\"AA\"") )
     523                 :     {
     524               0 :         GDAL_IMD_AA2R( &papszIMD );
     525                 :     }
     526                 : 
     527              10 :     return papszIMD;
     528                 : }
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                       GDALWriteIMDMultiLine()                        */
     532                 : /*                                                                      */
     533                 : /*      Write a value that is split over multiple lines.                */
     534                 : /************************************************************************/
     535                 :  
     536               8 : static void GDALWriteIMDMultiLine( VSILFILE *fp, const char *pszValue )
     537                 : 
     538                 : {
     539                 :     char **papszItems = CSLTokenizeStringComplex( pszValue, "(,) ", 
     540               8 :                                                   FALSE, FALSE );
     541               8 :     int nItemCount = CSLCount(papszItems);
     542                 :     int i;
     543                 : 
     544               8 :     VSIFPrintfL( fp, "(\n" );
     545                 : 
     546              80 :     for( i = 0; i < nItemCount; i++ )
     547                 :     {
     548              72 :         if( i == nItemCount-1 )
     549               8 :             VSIFPrintfL( fp, "\t%s );\n", papszItems[i] );
     550                 :         else
     551              64 :             VSIFPrintfL( fp, "\t%s,\n", papszItems[i] );
     552                 :     }
     553               8 :     CSLDestroy( papszItems );
     554               8 : }
     555                 : 
     556                 : /************************************************************************/
     557                 : /*                          GDALWriteIMDFile()                          */
     558                 : /************************************************************************/
     559                 : 
     560               4 : CPLErr CPL_STDCALL GDALWriteIMDFile( const char *pszFilename, char **papszMD )
     561                 : 
     562                 : {
     563               4 :     CPLString osRPBFilename = CPLResetExtension( pszFilename, "IMD" );
     564                 : 
     565                 : /* -------------------------------------------------------------------- */
     566                 : /*      Read file and parse.                                            */
     567                 : /* -------------------------------------------------------------------- */
     568               4 :     VSILFILE *fp = VSIFOpenL( osRPBFilename, "w" );
     569                 : 
     570               4 :     if( fp == NULL )
     571                 :     {
     572                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     573                 :                   "Unable to create %s for writing.\n%s", 
     574               0 :                   osRPBFilename.c_str(), CPLGetLastErrorMsg() );
     575               0 :         return CE_Failure;
     576                 :     }
     577                 : 
     578                 : /* ==================================================================== */
     579                 : /* -------------------------------------------------------------------- */
     580                 : /*      Loop through all values writing.                                */
     581                 : /* -------------------------------------------------------------------- */
     582                 : /* ==================================================================== */
     583                 :     int iKey;
     584               4 :     CPLString osCurSection;
     585                 : 
     586             352 :     for( iKey = 0; papszMD[iKey] != NULL; iKey++ )
     587                 :     {
     588             348 :         char *pszRawKey = NULL;
     589             348 :         const char *pszValue = CPLParseNameValue( papszMD[iKey], &pszRawKey );
     590             348 :         CPLString osKeySection, osKeyItem;
     591             348 :         char *pszDot = strchr(pszRawKey,'.');
     592                 : 
     593                 : /* -------------------------------------------------------------------- */
     594                 : /*      Split stuff like BAND_P.ULLon into section and item.            */
     595                 : /* -------------------------------------------------------------------- */
     596             348 :         if( pszDot == NULL )
     597                 :         {
     598              56 :             osKeyItem = pszRawKey;
     599                 :         }
     600                 :         else
     601                 :         {
     602             292 :             osKeyItem = pszDot+1;
     603             292 :             *pszDot = '\0';
     604             292 :             osKeySection = pszRawKey;
     605                 :         }
     606             348 :         CPLFree( pszRawKey );
     607                 : 
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      Close and/or start sections as needed.                          */
     610                 : /* -------------------------------------------------------------------- */
     611             348 :         if( osCurSection.size() && !EQUAL(osCurSection,osKeySection) )
     612              12 :             VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
     613                 : 
     614             348 :         if( osKeySection.size() && !EQUAL(osCurSection,osKeySection) )
     615              12 :             VSIFPrintfL( fp, "BEGIN_GROUP = %s\n", osKeySection.c_str() );
     616                 : 
     617             348 :         osCurSection = osKeySection;
     618                 : 
     619                 : /* -------------------------------------------------------------------- */
     620                 : /*      Print out simple item.                                          */
     621                 : /* -------------------------------------------------------------------- */
     622             348 :         if( osCurSection.size() )
     623             292 :             VSIFPrintfL( fp, "\t%s = ", osKeyItem.c_str() );
     624                 :         else
     625              56 :             VSIFPrintfL( fp, "%s = ", osKeyItem.c_str() );
     626                 : 
     627             348 :         if( pszValue[0] != '(' )
     628             340 :             VSIFPrintfL( fp, "%s;\n", pszValue );
     629                 :         else
     630               8 :             GDALWriteIMDMultiLine( fp, pszValue );
     631                 :     }
     632                 : 
     633                 : /* -------------------------------------------------------------------- */
     634                 : /*      Close off.                                                      */
     635                 : /* -------------------------------------------------------------------- */
     636               4 :     if( osCurSection.size() )
     637               0 :         VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
     638                 :     
     639               4 :     VSIFPrintfL( fp, "END;\n" );
     640                 :     
     641               4 :     VSIFCloseL( fp );
     642                 :     
     643               4 :     return CE_None;
     644                 : }

Generated by: LCOV version 1.7