LCOV - code coverage report
Current view: directory - frmts/dted - dted_api.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 263 205 77.9 %
Date: 2010-01-09 Functions: 11 9 81.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: dted_api.c 17398 2009-07-16 04:16:26Z chaitanya $
       3                 :  *
       4                 :  * Project:  DTED Translator
       5                 :  * Purpose:  Implementation of DTED/CDED access functions.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "dted_api.h"
      31                 : 
      32                 : #ifndef AVOID_CPL
      33                 : CPL_CVSID("$Id: dted_api.c 17398 2009-07-16 04:16:26Z chaitanya $");
      34                 : #endif
      35                 : 
      36                 : static int bWarnedTwoComplement = FALSE;
      37                 : 
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                            DTEDGetField()                            */
      41                 : /*                                                                      */
      42                 : /*      Extract a field as a zero terminated string.  Address is        */
      43                 : /*      deliberately 1 based so the getfield arguments will be the      */
      44                 : /*      same as the numbers in the file format specification.           */
      45                 : /************************************************************************/
      46                 : 
      47                 : static
      48             610 : char *DTEDGetField( char szResult[81], const char *pachRecord, int nStart, int nSize )
      49                 : 
      50                 : {
      51                 :     CPLAssert( nSize < 81 );
      52             610 :     memcpy( szResult, pachRecord + nStart - 1, nSize );
      53             610 :     szResult[nSize] = '\0';
      54                 : 
      55             610 :     return szResult;
      56                 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                         StripLeadingZeros()                          */
      60                 : /*                                                                      */
      61                 : /*      Return a pointer to the first non-zero character in BUF.        */
      62                 : /*      BUF must be null terminated.                                    */
      63                 : /*      If buff is all zeros, then it will point to the last non-zero   */
      64                 : /************************************************************************/
      65                 : 
      66             366 : static const char* stripLeadingZeros(const char* buf)
      67                 : {
      68             366 :     const char* ptr = buf;
      69                 : 
      70                 :     /* Go until we run out of characters  or hit something non-zero */
      71                 : 
      72            1119 :     while( *ptr == '0' && *(ptr+1) != '\0' )
      73                 :     {
      74             387 :         ptr++;
      75                 :     }
      76                 : 
      77             366 :     return ptr;
      78                 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                              DTEDOpen()                              */
      82                 : /************************************************************************/
      83                 : 
      84              61 : DTEDInfo * DTEDOpen( const char * pszFilename,
      85                 :                      const char * pszAccess,
      86                 :                      int bTestOpen )
      87                 : 
      88                 : {
      89                 :     FILE        *fp;
      90                 :     char        achRecord[DTED_UHL_SIZE];
      91              61 :     DTEDInfo    *psDInfo = NULL;
      92                 :     double      dfLLOriginX, dfLLOriginY;
      93              61 :     int deg = 0;
      94              61 :     int min = 0;
      95              61 :     int sec = 0;
      96              61 :     int bSwapLatLong = FALSE;
      97                 :     char szResult[81];
      98                 : 
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Open the physical file.                                         */
     101                 : /* -------------------------------------------------------------------- */
     102             108 :     if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb") )
     103              47 :         pszAccess = "rb";
     104                 :     else
     105              14 :         pszAccess = "r+b";
     106                 :     
     107              61 :     fp = VSIFOpenL( pszFilename, pszAccess );
     108                 : 
     109              61 :     if( fp == NULL )
     110                 :     {
     111               0 :         if( !bTestOpen )
     112                 :         {
     113                 : #ifndef AVOID_CPL
     114               0 :             CPLError( CE_Failure, CPLE_OpenFailed,
     115                 : #else
     116                 :             fprintf( stderr, 
     117                 : #endif
     118                 :                       "Failed to open file %s.",
     119                 :                       pszFilename );
     120                 :         }
     121                 : 
     122               0 :         return NULL;
     123                 :     }
     124                 : 
     125                 : /* -------------------------------------------------------------------- */
     126                 : /*      Read, trying to find the UHL record.  Skip VOL or HDR           */
     127                 : /*      records if they are encountered.                                */
     128                 : /* -------------------------------------------------------------------- */
     129                 :     do
     130                 :     {
     131              62 :         if( VSIFReadL( achRecord, 1, DTED_UHL_SIZE, fp ) != DTED_UHL_SIZE )
     132                 :         {
     133               0 :             if( !bTestOpen )
     134                 :             {
     135                 : #ifndef AVOID_CPL
     136               0 :                CPLError( CE_Failure, CPLE_OpenFailed,
     137                 : #else
     138                 :                fprintf( stderr, 
     139                 : #endif
     140                 :                           "Unable to read header, %s is not DTED.",
     141                 :                           pszFilename );
     142                 :             }
     143               0 :             VSIFCloseL( fp );
     144               0 :             return NULL;
     145                 :         }
     146                 : 
     147              62 :     } while( EQUALN(achRecord,"VOL",3) || EQUALN(achRecord,"HDR",3) );
     148                 : 
     149              61 :     if( !EQUALN(achRecord,"UHL",3) )
     150                 :     {
     151               0 :         if( !bTestOpen )
     152                 :         {
     153                 : #ifndef AVOID_CPL
     154               0 :             CPLError( CE_Failure, CPLE_OpenFailed,
     155                 : #else
     156                 :             fprintf( stderr, 
     157                 : #endif
     158                 :                       "No UHL record.  %s is not a DTED file.",
     159                 :                       pszFilename );
     160                 :         }
     161               0 :         VSIFCloseL( fp );
     162               0 :         return NULL;
     163                 :     }
     164                 :     
     165                 : /* -------------------------------------------------------------------- */
     166                 : /*      Create and initialize the DTEDInfo structure.                   */
     167                 : /* -------------------------------------------------------------------- */
     168              61 :     psDInfo = (DTEDInfo *) CPLCalloc(1,sizeof(DTEDInfo));
     169                 : 
     170              61 :     psDInfo->fp = fp;
     171                 : 
     172              61 :     psDInfo->bUpdate = EQUAL(pszAccess,"r+b");
     173                 :     
     174              61 :     psDInfo->nXSize = atoi(DTEDGetField(szResult,achRecord,48,4));
     175              61 :     psDInfo->nYSize = atoi(DTEDGetField(szResult,achRecord,52,4));
     176                 : 
     177              61 :     psDInfo->nUHLOffset = (int)VSIFTellL( fp ) - DTED_UHL_SIZE;
     178              61 :     psDInfo->pachUHLRecord = (char *) CPLMalloc(DTED_UHL_SIZE);
     179              61 :     memcpy( psDInfo->pachUHLRecord, achRecord, DTED_UHL_SIZE );
     180                 : 
     181              61 :     psDInfo->nDSIOffset = (int)VSIFTellL( fp );
     182              61 :     psDInfo->pachDSIRecord = (char *) CPLMalloc(DTED_DSI_SIZE);
     183              61 :     VSIFReadL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, fp );
     184                 :     
     185              61 :     psDInfo->nACCOffset = (int)VSIFTellL( fp );
     186              61 :     psDInfo->pachACCRecord = (char *) CPLMalloc(DTED_ACC_SIZE);
     187              61 :     VSIFReadL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, fp );
     188                 : 
     189             122 :     if( !EQUALN(psDInfo->pachDSIRecord,"DSI",3)
     190              61 :         || !EQUALN(psDInfo->pachACCRecord,"ACC",3) )
     191                 :     {
     192                 : #ifndef AVOID_CPL
     193               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
     194                 : #else
     195                 :         fprintf( stderr, 
     196                 : #endif
     197                 :                  "DSI or ACC record missing.  DTED access to\n%s failed.",
     198                 :                  pszFilename );
     199                 :         
     200               0 :         VSIFCloseL( fp );
     201               0 :         return NULL;
     202                 :     }
     203                 : 
     204              61 :     psDInfo->nDataOffset = (int)VSIFTellL( fp );
     205                 : 
     206                 : /* -------------------------------------------------------------------- */
     207                 : /*      Parse out position information.  Note that we are extracting    */
     208                 : /*      the top left corner of the top left pixel area, not the         */
     209                 : /*      center of the area.                                             */
     210                 : /* -------------------------------------------------------------------- */
     211              61 :     psDInfo->dfPixelSizeX =
     212              61 :         atoi(DTEDGetField(szResult,achRecord,21,4)) / 36000.0;
     213                 : 
     214              61 :     psDInfo->dfPixelSizeY =
     215              61 :         atoi(DTEDGetField(szResult,achRecord,25,4)) / 36000.0;
     216                 : 
     217                 :     /* create a scope so I don't need to declare these up top */
     218              61 :     deg = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,5,3)));
     219              61 :     min = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,8,2)));
     220              61 :     sec = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,10,2)));
     221                 : 
     222                 :     /* NOTE : The first version of MIL-D-89020 was buggy.
     223                 :        The latitude and longitude of the LL cornder of the UHF record was inverted.
     224                 :        This was fixed in MIL-D-89020 Amendement 1, but some products may be affected.
     225                 :        We detect this situation by looking at N/S in the longitude field and
     226                 :        E/W in the latitude one
     227                 :     */
     228                 : 
     229              61 :     dfLLOriginX = deg + min / 60.0 + sec / 3600.0;
     230              61 :     if( achRecord[11] == 'W' )
     231              38 :         dfLLOriginX *= -1;
     232              23 :     else if ( achRecord[11] == 'N' )
     233               1 :         bSwapLatLong = TRUE;
     234              22 :     else if ( achRecord[11] == 'S' )
     235                 :     {
     236               0 :         dfLLOriginX *= -1;
     237               0 :         bSwapLatLong = TRUE;
     238                 :     }
     239                 : 
     240              61 :     deg = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,13,3)));
     241              61 :     min = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,16,2)));
     242              61 :     sec = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,18,2)));
     243                 : 
     244              61 :     dfLLOriginY = deg + min / 60.0 + sec / 3600.0;
     245              61 :     if( achRecord[19] == 'S' || (bSwapLatLong && achRecord[19] == 'W'))
     246               1 :         dfLLOriginY *= -1;
     247                 : 
     248              61 :     if (bSwapLatLong)
     249                 :     {
     250               1 :         double dfTmp = dfLLOriginX;
     251               1 :         dfLLOriginX = dfLLOriginY;
     252               1 :         dfLLOriginY = dfTmp;
     253                 :     }
     254                 : 
     255              61 :     psDInfo->dfULCornerX = dfLLOriginX - 0.5 * psDInfo->dfPixelSizeX;
     256              61 :     psDInfo->dfULCornerY = dfLLOriginY - 0.5 * psDInfo->dfPixelSizeY
     257              61 :         + psDInfo->nYSize * psDInfo->dfPixelSizeY;
     258                 : 
     259              61 :     return psDInfo;
     260                 : }
     261                 : 
     262                 : 
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                            DTEDReadPoint()                           */
     266                 : /*                                                                      */
     267                 : /*      Read one single sample. The coordinates are given from the      */
     268                 : /*      top-left corner of the file (contrary to the internal           */
     269                 : /*      organisation or a DTED file)                                    */
     270                 : /************************************************************************/
     271                 : 
     272               0 : int DTEDReadPoint( DTEDInfo * psDInfo, int nXOff, int nYOff, GInt16* panVal)
     273                 : {
     274                 :     int nOffset;
     275                 :     GByte pabyData[2];
     276                 : 
     277               0 :     if (nYOff < 0 || nXOff < 0 || nYOff >= psDInfo->nYSize || nXOff >= psDInfo->nXSize)
     278                 :     {
     279                 : #ifndef AVOID_CPL
     280               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     281                 : #else
     282                 :         fprintf( stderr, 
     283                 : #endif
     284                 :                   "Invalid raster coordinates (%d,%d) in DTED file.\n", nXOff, nYOff);
     285               0 :         return FALSE;
     286                 :     }
     287                 : 
     288               0 :     nOffset = psDInfo->nDataOffset + nXOff * (12+psDInfo->nYSize*2) + 8 + 2 * (psDInfo->nYSize-1-nYOff);
     289               0 :     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
     290               0 :         || VSIFReadL( pabyData, 2, 1, psDInfo->fp ) != 1)
     291                 :     {
     292                 : #ifndef AVOID_CPL
     293               0 :         CPLError( CE_Failure, CPLE_FileIO,
     294                 : #else
     295                 :         fprintf( stderr, 
     296                 : #endif
     297                 :                   "Failed to seek to, or read (%d,%d) at offset %d\n"
     298                 :                   "in DTED file.\n",
     299                 :                   nXOff, nYOff, nOffset );
     300               0 :         return FALSE;
     301                 :     }
     302                 : 
     303               0 :     *panVal = ((pabyData[0] & 0x7f) << 8) | pabyData[1];
     304                 : 
     305               0 :     if( pabyData[0] & 0x80 )
     306                 :     {
     307               0 :         *panVal *= -1;
     308                 : 
     309                 :         /*
     310                 :         ** It seems that some files are improperly generated in twos
     311                 :         ** complement form for negatives.  For these, redo the job
     312                 :         ** in twos complement.  eg. w_069_s50.dt0
     313                 :         */
     314               0 :         if(( *panVal < -16000 ) && (*panVal != DTED_NODATA_VALUE))
     315                 :         {
     316               0 :             *panVal = (pabyData[0] << 8) | pabyData[1];
     317                 : 
     318               0 :             if( !bWarnedTwoComplement )
     319                 :             {
     320               0 :                 bWarnedTwoComplement = TRUE;
     321                 : #ifndef AVOID_CPL
     322               0 :                 CPLError( CE_Warning, CPLE_AppDefined,
     323                 : #else
     324                 :                 fprintf( stderr,
     325                 : #endif
     326                 :                             "The DTED driver found values less than -16000, and has adjusted\n"
     327                 :                             "them assuming they are improperly two-complemented.  No more warnings\n"
     328                 :                             "will be issued in this session about this operation." );
     329                 :             }
     330                 :         }
     331                 :     }
     332                 : 
     333               0 :     return TRUE;
     334                 : }
     335                 : 
     336                 : /************************************************************************/
     337                 : /*                          DTEDReadProfile()                           */
     338                 : /*                                                                      */
     339                 : /*      Read one profile line.  These are organized in bottom to top    */
     340                 : /*      order starting from the leftmost column (0).                    */
     341                 : /************************************************************************/
     342                 : 
     343               0 : int DTEDReadProfile( DTEDInfo * psDInfo, int nColumnOffset,
     344                 :                      GInt16 * panData )
     345                 : {
     346               0 :     return DTEDReadProfileEx( psDInfo, nColumnOffset, panData, FALSE);
     347                 : }
     348                 : 
     349            3300 : int DTEDReadProfileEx( DTEDInfo * psDInfo, int nColumnOffset,
     350                 :                        GInt16 * panData, int bVerifyChecksum )
     351                 : {
     352                 :     int         nOffset;
     353                 :     int         i;
     354                 :     GByte       *pabyRecord;
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Read data record from disk.                                     */
     358                 : /* -------------------------------------------------------------------- */
     359            3300 :     pabyRecord = (GByte *) CPLMalloc(12 + psDInfo->nYSize*2);
     360                 :     
     361            3300 :     nOffset = psDInfo->nDataOffset + nColumnOffset * (12+psDInfo->nYSize*2);
     362                 : 
     363            6600 :     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
     364            6600 :         || VSIFReadL( pabyRecord, (12+psDInfo->nYSize*2), 1, psDInfo->fp ) != 1)
     365                 :     {
     366                 : #ifndef AVOID_CPL
     367               0 :         CPLError( CE_Failure, CPLE_FileIO,
     368                 : #else
     369                 :         fprintf( stderr, 
     370                 : #endif
     371                 :                   "Failed to seek to, or read profile %d at offset %d\n"
     372                 :                   "in DTED file.\n",
     373                 :                   nColumnOffset, nOffset );
     374               0 :         CPLFree( pabyRecord );
     375               0 :         return FALSE;
     376                 :     }
     377                 : 
     378                 : /* -------------------------------------------------------------------- */
     379                 : /*      Translate data values from "signed magnitude" to standard       */
     380                 : /*      binary.                                                         */
     381                 : /* -------------------------------------------------------------------- */
     382         1051680 :     for( i = 0; i < psDInfo->nYSize; i++ )
     383                 :     {
     384         1048380 :         panData[i] = ((pabyRecord[8+i*2] & 0x7f) << 8) | pabyRecord[8+i*2+1];
     385                 : 
     386         1048380 :         if( pabyRecord[8+i*2] & 0x80 )
     387                 :         {
     388               0 :             panData[i] *= -1;
     389                 : 
     390                 :             /*
     391                 :             ** It seems that some files are improperly generated in twos
     392                 :             ** complement form for negatives.  For these, redo the job
     393                 :             ** in twos complement.  eg. w_069_s50.dt0
     394                 :             */
     395               0 :             if(( panData[i] < -16000 ) && (panData[i] != DTED_NODATA_VALUE))
     396                 :             {
     397               0 :                 panData[i] = (pabyRecord[8+i*2] << 8) | pabyRecord[8+i*2+1];
     398                 : 
     399               0 :                 if( !bWarnedTwoComplement )
     400                 :                 {
     401               0 :                     bWarnedTwoComplement = TRUE;
     402                 : #ifndef AVOID_CPL
     403               0 :                     CPLError( CE_Warning, CPLE_AppDefined,
     404                 : #else
     405                 :                     fprintf( stderr,
     406                 : #endif
     407                 :                               "The DTED driver found values less than -16000, and has adjusted\n"
     408                 :                               "them assuming they are improperly two-complemented.  No more warnings\n"
     409                 :                               "will be issued in this session about this operation." );
     410                 :                 }
     411                 :             }
     412                 :         }
     413                 :     }
     414                 : 
     415            3300 :     if (bVerifyChecksum)
     416                 :     {
     417               1 :         unsigned int nCheckSum = 0;
     418                 :         unsigned int fileCheckSum;
     419                 : 
     420                 :         /* -------------------------------------------------------------------- */
     421                 :         /*      Verify the checksum.                                            */
     422                 :         /* -------------------------------------------------------------------- */
     423                 : 
     424             251 :         for( i = 0; i < psDInfo->nYSize*2 + 8; i++ )
     425             250 :             nCheckSum += pabyRecord[i];
     426                 : 
     427               2 :         fileCheckSum = (pabyRecord[8+psDInfo->nYSize*2+0] << 24) |
     428               1 :                         (pabyRecord[8+psDInfo->nYSize*2+1] << 16) |
     429               1 :                         (pabyRecord[8+psDInfo->nYSize*2+2] << 8) |
     430               1 :                         pabyRecord[8+psDInfo->nYSize*2+3];
     431                 : 
     432               1 :         if ((GIntBig)fileCheckSum > (GIntBig)(0xff * (8+psDInfo->nYSize*2)))
     433                 :         {
     434                 :             static int bWarned = FALSE;
     435               0 :             if (! bWarned)
     436                 :             {
     437               0 :                 bWarned = TRUE;
     438                 : #ifndef AVOID_CPL
     439               0 :                 CPLError( CE_Warning, CPLE_AppDefined,
     440                 : #else
     441                 :                 fprintf( stderr,
     442                 : #endif
     443                 :                             "The DTED driver has read from the file a checksum "
     444                 :                             "with an impossible value (0x%X) at column %d.\n"
     445                 :                             "Check with your file producer.\n"
     446                 :                             "No more warnings will be issued in this session about this operation.",
     447                 :                             fileCheckSum, nColumnOffset);
     448                 :             }
     449                 :         }
     450               1 :         else if (fileCheckSum != nCheckSum)
     451                 :         {
     452                 : #ifndef AVOID_CPL
     453               1 :             CPLError( CE_Warning, CPLE_AppDefined,
     454                 : #else
     455                 :             fprintf( stderr,
     456                 : #endif
     457                 :                       "The DTED driver has found a computed and read checksum "
     458                 :                       "that do not match at column %d.\n",
     459                 :                       nColumnOffset);
     460               1 :             CPLFree( pabyRecord );
     461               1 :             return FALSE;
     462                 :         }
     463                 :     }
     464                 : 
     465            3299 :     CPLFree( pabyRecord );
     466                 : 
     467            3299 :     return TRUE;
     468                 : }
     469                 : 
     470                 : /************************************************************************/
     471                 : /*                          DTEDWriteProfile()                          */
     472                 : /************************************************************************/
     473                 : 
     474           14054 : int DTEDWriteProfile( DTEDInfo * psDInfo, int nColumnOffset,
     475                 :                      GInt16 * panData )
     476                 : 
     477                 : {
     478                 :     int         nOffset;
     479           14054 :     int         i, nCheckSum = 0;
     480                 :     GByte       *pabyRecord;
     481                 : 
     482                 : /* -------------------------------------------------------------------- */
     483                 : /*      Format the data record.                                         */
     484                 : /* -------------------------------------------------------------------- */
     485           14054 :     pabyRecord = (GByte *) CPLMalloc(12 + psDInfo->nYSize*2);
     486                 :     
     487        16631548 :     for( i = 0; i < psDInfo->nYSize; i++ )
     488                 :     {
     489        16617494 :         int     nABSVal = ABS(panData[psDInfo->nYSize-i-1]);
     490        16617494 :         pabyRecord[8+i*2] = (GByte) ((nABSVal >> 8) & 0x7f);
     491        16617494 :         pabyRecord[8+i*2+1] = (GByte) (nABSVal & 0xff);
     492                 : 
     493        16617494 :         if( panData[psDInfo->nYSize-i-1] < 0 )
     494               0 :             pabyRecord[8+i*2] |= 0x80;
     495                 :     }
     496                 : 
     497           14054 :     pabyRecord[0] = 0xaa;
     498           14054 :     pabyRecord[1] = 0;
     499           14054 :     pabyRecord[2] = (GByte) (nColumnOffset / 256);
     500           14054 :     pabyRecord[3] = (GByte) (nColumnOffset % 256);
     501           14054 :     pabyRecord[4] = (GByte) (nColumnOffset / 256);
     502           14054 :     pabyRecord[5] = (GByte) (nColumnOffset % 256);
     503           14054 :     pabyRecord[6] = 0;
     504           14054 :     pabyRecord[7] = 0;
     505                 : 
     506                 : /* -------------------------------------------------------------------- */
     507                 : /*      Compute the checksum.                                           */
     508                 : /* -------------------------------------------------------------------- */
     509        33361474 :     for( i = 0; i < psDInfo->nYSize*2 + 8; i++ )
     510        33347420 :         nCheckSum += pabyRecord[i];
     511                 : 
     512           14054 :     pabyRecord[8+psDInfo->nYSize*2+0] = (GByte) ((nCheckSum >> 24) & 0xff);
     513           14054 :     pabyRecord[8+psDInfo->nYSize*2+1] = (GByte) ((nCheckSum >> 16) & 0xff);
     514           14054 :     pabyRecord[8+psDInfo->nYSize*2+2] = (GByte) ((nCheckSum >> 8) & 0xff);
     515           14054 :     pabyRecord[8+psDInfo->nYSize*2+3] = (GByte) (nCheckSum & 0xff);
     516                 : 
     517                 : /* -------------------------------------------------------------------- */
     518                 : /*      Write the record.                                               */
     519                 : /* -------------------------------------------------------------------- */
     520           14054 :     nOffset = psDInfo->nDataOffset + nColumnOffset * (12+psDInfo->nYSize*2);
     521                 : 
     522           28108 :     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
     523           28108 :         || VSIFWriteL( pabyRecord,(12+psDInfo->nYSize*2),1,psDInfo->fp ) != 1)
     524                 :     {
     525               0 :         CPLFree( pabyRecord );
     526                 : #ifndef AVOID_CPL
     527               0 :         CPLError( CE_Failure, CPLE_FileIO,
     528                 : #else
     529                 :         fprintf( stderr, 
     530                 : #endif
     531                 :                   "Failed to seek to, or write profile %d at offset %d\n"
     532                 :                   "in DTED file.\n",
     533                 :                   nColumnOffset, nOffset );
     534               0 :         CPLFree( pabyRecord );
     535               0 :         return FALSE;
     536                 :     }
     537                 : 
     538           14054 :     CPLFree( pabyRecord );
     539                 : 
     540           14054 :     return TRUE;
     541                 :     
     542                 : }
     543                 : 
     544                 : /************************************************************************/
     545                 : /*                      DTEDGetMetadataLocation()                       */
     546                 : /************************************************************************/
     547                 : 
     548             931 : static void DTEDGetMetadataLocation( DTEDInfo *psDInfo, 
     549                 :                                      DTEDMetaDataCode eCode, 
     550                 :                                      char **ppszLocation, int *pnLength )
     551                 : {
     552             931 :     switch( eCode )
     553                 :     {
     554                 :       case DTEDMD_VERTACCURACY_UHL:
     555              49 :         *ppszLocation = psDInfo->pachUHLRecord + 28;
     556              49 :         *pnLength = 4;
     557              49 :         break;
     558                 : 
     559                 :       case DTEDMD_SECURITYCODE_UHL:
     560              49 :         *ppszLocation = psDInfo->pachUHLRecord + 32;
     561              49 :         *pnLength = 3;
     562              49 :         break;
     563                 : 
     564                 :       case DTEDMD_UNIQUEREF_UHL:
     565              49 :         *ppszLocation = psDInfo->pachUHLRecord + 35;
     566              49 :         *pnLength = 12;
     567              49 :         break;
     568                 : 
     569                 :       case DTEDMD_DATA_EDITION:
     570              49 :         *ppszLocation = psDInfo->pachDSIRecord + 87;
     571              49 :         *pnLength = 2;
     572              49 :         break;
     573                 : 
     574                 :       case DTEDMD_MATCHMERGE_VERSION:
     575              49 :         *ppszLocation = psDInfo->pachDSIRecord + 89;
     576              49 :         *pnLength = 1;
     577              49 :         break;
     578                 : 
     579                 :       case DTEDMD_MAINT_DATE:
     580              49 :         *ppszLocation = psDInfo->pachDSIRecord + 90;
     581              49 :         *pnLength = 4;
     582              49 :         break;
     583                 : 
     584                 :       case DTEDMD_MATCHMERGE_DATE:
     585              49 :         *ppszLocation = psDInfo->pachDSIRecord + 94;
     586              49 :         *pnLength = 4;
     587              49 :         break;
     588                 : 
     589                 :       case DTEDMD_MAINT_DESCRIPTION:
     590              49 :         *ppszLocation = psDInfo->pachDSIRecord + 98;
     591              49 :         *pnLength = 4;
     592              49 :         break;
     593                 : 
     594                 :       case DTEDMD_PRODUCER:
     595              49 :         *ppszLocation = psDInfo->pachDSIRecord + 102;
     596              49 :         *pnLength = 8;
     597              49 :         break;
     598                 : 
     599                 :       case DTEDMD_VERTDATUM:
     600              49 :         *ppszLocation = psDInfo->pachDSIRecord + 141;
     601              49 :         *pnLength = 3;
     602              49 :         break;
     603                 : 
     604                 :       case DTEDMD_HORIZDATUM: 
     605              49 :         *ppszLocation = psDInfo->pachDSIRecord + 144; 
     606              49 :         *pnLength = 5; 
     607              49 :         break; 
     608                 : 
     609                 :       case DTEDMD_DIGITIZING_SYS:
     610              49 :         *ppszLocation = psDInfo->pachDSIRecord + 149;
     611              49 :         *pnLength = 10;
     612              49 :         break;
     613                 : 
     614                 :       case DTEDMD_COMPILATION_DATE:
     615              49 :         *ppszLocation = psDInfo->pachDSIRecord + 159;
     616              49 :         *pnLength = 4;
     617              49 :         break;
     618                 : 
     619                 :       case DTEDMD_HORIZACCURACY:
     620              49 :         *ppszLocation = psDInfo->pachACCRecord + 3;
     621              49 :         *pnLength = 4;
     622              49 :         break;
     623                 : 
     624                 :       case DTEDMD_REL_HORIZACCURACY:
     625              49 :         *ppszLocation = psDInfo->pachACCRecord + 11;
     626              49 :         *pnLength = 4;
     627              49 :         break;
     628                 : 
     629                 :       case DTEDMD_REL_VERTACCURACY:
     630              49 :         *ppszLocation = psDInfo->pachACCRecord + 15;
     631              49 :         *pnLength = 4;
     632              49 :         break;
     633                 : 
     634                 :       case DTEDMD_VERTACCURACY_ACC:
     635              49 :         *ppszLocation = psDInfo->pachACCRecord + 7;
     636              49 :         *pnLength = 4;
     637              49 :         break;
     638                 : 
     639                 :       case DTEDMD_SECURITYCODE_DSI:
     640              49 :         *ppszLocation = psDInfo->pachDSIRecord + 3;
     641              49 :         *pnLength = 1;
     642              49 :         break;
     643                 : 
     644                 :       case DTEDMD_UNIQUEREF_DSI:
     645              49 :         *ppszLocation = psDInfo->pachDSIRecord + 64;
     646              49 :         *pnLength = 15;
     647              49 :         break;
     648                 : 
     649                 :       default:
     650               0 :         *ppszLocation = NULL;
     651               0 :         *pnLength = 0;
     652                 :     }
     653             931 : }
     654                 : 
     655                 : /************************************************************************/
     656                 : /*                          DTEDGetMetadata()                           */
     657                 : /************************************************************************/
     658                 : 
     659             893 : char *DTEDGetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode )
     660                 : 
     661                 : {
     662                 :     int nFieldLen;
     663                 :     char *pszFieldSrc;
     664                 :     char *pszResult;
     665                 : 
     666             893 :     DTEDGetMetadataLocation( psDInfo, eCode, &pszFieldSrc, &nFieldLen );
     667             893 :     if( pszFieldSrc == NULL )
     668               0 :         return VSIStrdup( "" );
     669                 : 
     670             893 :     pszResult = (char *) malloc(nFieldLen+1);
     671             893 :     strncpy( pszResult, pszFieldSrc, nFieldLen );
     672             893 :     pszResult[nFieldLen] = '\0';
     673                 : 
     674             893 :     return pszResult;
     675                 : }
     676                 : 
     677                 : /************************************************************************/
     678                 : /*                          DTEDSetMetadata()                           */
     679                 : /************************************************************************/
     680                 : 
     681              38 : int DTEDSetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode, 
     682                 :                      const char *pszNewValue )
     683                 : 
     684                 : {
     685                 :     int nFieldLen;
     686                 :     char *pszFieldSrc;
     687                 : 
     688              38 :     if( !psDInfo->bUpdate )
     689               0 :         return FALSE;
     690                 : 
     691                 : /* -------------------------------------------------------------------- */
     692                 : /*      Get the location in the headers to update.                      */
     693                 : /* -------------------------------------------------------------------- */
     694              38 :     DTEDGetMetadataLocation( psDInfo, eCode, &pszFieldSrc, &nFieldLen );
     695              38 :     if( pszFieldSrc == NULL )
     696               0 :         return FALSE;
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*      Update it, padding with spaces.                                 */
     700                 : /* -------------------------------------------------------------------- */
     701              38 :     memset( pszFieldSrc, ' ', nFieldLen );
     702              38 :     strncpy( pszFieldSrc, pszNewValue, 
     703              38 :              MIN((size_t)nFieldLen,strlen(pszNewValue)) );
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*      Write all headers back to disk.                                 */
     707                 : /* -------------------------------------------------------------------- */
     708              38 :     VSIFSeekL( psDInfo->fp, psDInfo->nUHLOffset, SEEK_SET );
     709              38 :     VSIFWriteL( psDInfo->pachUHLRecord, 1, DTED_UHL_SIZE, psDInfo->fp );
     710                 : 
     711              38 :     VSIFSeekL( psDInfo->fp, psDInfo->nDSIOffset, SEEK_SET );
     712              38 :     VSIFWriteL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, psDInfo->fp );
     713                 : 
     714              38 :     VSIFSeekL( psDInfo->fp, psDInfo->nACCOffset, SEEK_SET );
     715              38 :     VSIFWriteL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, psDInfo->fp );
     716                 : 
     717              38 :     return TRUE;
     718                 : }
     719                 : 
     720                 : /************************************************************************/
     721                 : /*                             DTEDClose()                              */
     722                 : /************************************************************************/
     723                 : 
     724              61 : void DTEDClose( DTEDInfo * psDInfo )
     725                 : 
     726                 : {
     727              61 :     VSIFCloseL( psDInfo->fp );
     728                 : 
     729              61 :     CPLFree( psDInfo->pachUHLRecord );
     730              61 :     CPLFree( psDInfo->pachDSIRecord );
     731              61 :     CPLFree( psDInfo->pachACCRecord );
     732                 :     
     733              61 :     CPLFree( psDInfo );
     734              61 : }

Generated by: LCOV version 1.7