LCOV - code coverage report
Current view: directory - frmts/dted - dted_api.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 327 240 73.4 %
Date: 2012-04-28 Functions: 11 9 81.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: dted_api.c 22606 2011-06-28 20:31:23Z rouault $
       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 22606 2011-06-28 20:31:23Z rouault $");
      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            1640 : char *DTEDGetField( char szResult[81], const char *pachRecord, int nStart, int nSize )
      49                 : 
      50                 : {
      51            1640 :     CPLAssert( nSize < 81 );
      52            1640 :     memcpy( szResult, pachRecord + nStart - 1, nSize );
      53            1640 :     szResult[nSize] = '\0';
      54                 : 
      55            1640 :     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             984 : static const char* stripLeadingZeros(const char* buf)
      67                 : {
      68             984 :     const char* ptr = buf;
      69                 : 
      70                 :     /* Go until we run out of characters  or hit something non-zero */
      71                 : 
      72            2994 :     while( *ptr == '0' && *(ptr+1) != '\0' )
      73                 :     {
      74            1026 :         ptr++;
      75                 :     }
      76                 : 
      77             984 :     return ptr;
      78                 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                              DTEDOpen()                              */
      82                 : /************************************************************************/
      83                 : 
      84             164 : DTEDInfo * DTEDOpen( const char * pszFilename,
      85                 :                      const char * pszAccess,
      86                 :                      int bTestOpen )
      87                 : 
      88                 : {
      89                 :     VSILFILE   *fp;
      90                 :     char        achRecord[DTED_UHL_SIZE];
      91             164 :     DTEDInfo    *psDInfo = NULL;
      92                 :     double      dfLLOriginX, dfLLOriginY;
      93             164 :     int deg = 0;
      94             164 :     int min = 0;
      95             164 :     int sec = 0;
      96             164 :     int bSwapLatLong = FALSE;
      97                 :     char szResult[81];
      98                 :     int bIsWeirdDTED;
      99                 :     char chHemisphere;
     100                 : /* -------------------------------------------------------------------- */
     101                 : /*      Open the physical file.                                         */
     102                 : /* -------------------------------------------------------------------- */
     103             300 :     if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb") )
     104             136 :         pszAccess = "rb";
     105                 :     else
     106              28 :         pszAccess = "r+b";
     107                 :     
     108             164 :     fp = VSIFOpenL( pszFilename, pszAccess );
     109                 : 
     110             164 :     if( fp == NULL )
     111                 :     {
     112               0 :         if( !bTestOpen )
     113                 :         {
     114                 : #ifndef AVOID_CPL
     115               0 :             CPLError( CE_Failure, CPLE_OpenFailed,
     116                 : #else
     117                 :             fprintf( stderr, 
     118                 : #endif
     119                 :                       "Failed to open file %s.",
     120                 :                       pszFilename );
     121                 :         }
     122                 : 
     123               0 :         return NULL;
     124                 :     }
     125                 : 
     126                 : /* -------------------------------------------------------------------- */
     127                 : /*      Read, trying to find the UHL record.  Skip VOL or HDR           */
     128                 : /*      records if they are encountered.                                */
     129                 : /* -------------------------------------------------------------------- */
     130                 :     do
     131                 :     {
     132             166 :         if( VSIFReadL( achRecord, 1, DTED_UHL_SIZE, fp ) != DTED_UHL_SIZE )
     133                 :         {
     134               0 :             if( !bTestOpen )
     135                 :             {
     136                 : #ifndef AVOID_CPL
     137               0 :                CPLError( CE_Failure, CPLE_OpenFailed,
     138                 : #else
     139                 :                fprintf( stderr, 
     140                 : #endif
     141                 :                           "Unable to read header, %s is not DTED.",
     142                 :                           pszFilename );
     143                 :             }
     144               0 :             VSIFCloseL( fp );
     145               0 :             return NULL;
     146                 :         }
     147                 : 
     148             166 :     } while( EQUALN(achRecord,"VOL",3) || EQUALN(achRecord,"HDR",3) );
     149                 : 
     150             164 :     if( !EQUALN(achRecord,"UHL",3) )
     151                 :     {
     152               0 :         if( !bTestOpen )
     153                 :         {
     154                 : #ifndef AVOID_CPL
     155               0 :             CPLError( CE_Failure, CPLE_OpenFailed,
     156                 : #else
     157                 :             fprintf( stderr, 
     158                 : #endif
     159                 :                       "No UHL record.  %s is not a DTED file.",
     160                 :                       pszFilename );
     161                 :         }
     162               0 :         VSIFCloseL( fp );
     163               0 :         return NULL;
     164                 :     }
     165                 :     
     166                 : /* -------------------------------------------------------------------- */
     167                 : /*      Create and initialize the DTEDInfo structure.                   */
     168                 : /* -------------------------------------------------------------------- */
     169             164 :     psDInfo = (DTEDInfo *) CPLCalloc(1,sizeof(DTEDInfo));
     170                 : 
     171             164 :     psDInfo->fp = fp;
     172                 : 
     173             164 :     psDInfo->bUpdate = EQUAL(pszAccess,"r+b");
     174                 : 
     175             164 :     psDInfo->nUHLOffset = (int)VSIFTellL( fp ) - DTED_UHL_SIZE;
     176             164 :     psDInfo->pachUHLRecord = (char *) CPLMalloc(DTED_UHL_SIZE);
     177             164 :     memcpy( psDInfo->pachUHLRecord, achRecord, DTED_UHL_SIZE );
     178                 : 
     179             164 :     psDInfo->nDSIOffset = (int)VSIFTellL( fp );
     180             164 :     psDInfo->pachDSIRecord = (char *) CPLMalloc(DTED_DSI_SIZE);
     181             164 :     VSIFReadL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, fp );
     182                 :     
     183             164 :     psDInfo->nACCOffset = (int)VSIFTellL( fp );
     184             164 :     psDInfo->pachACCRecord = (char *) CPLMalloc(DTED_ACC_SIZE);
     185             164 :     VSIFReadL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, fp );
     186                 : 
     187             328 :     if( !EQUALN(psDInfo->pachDSIRecord,"DSI",3)
     188             164 :         || !EQUALN(psDInfo->pachACCRecord,"ACC",3) )
     189                 :     {
     190                 : #ifndef AVOID_CPL
     191               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
     192                 : #else
     193                 :         fprintf( stderr, 
     194                 : #endif
     195                 :                  "DSI or ACC record missing.  DTED access to\n%s failed.",
     196                 :                  pszFilename );
     197                 :         
     198               0 :         VSIFCloseL( fp );
     199               0 :         return NULL;
     200                 :     }
     201                 : 
     202             164 :     psDInfo->nDataOffset = (int)VSIFTellL( fp );
     203                 : 
     204                 :     /* DTED3 file from http://www.falconview.org/trac/FalconView/downloads/20 */
     205                 :     /* (co_elevation.zip) has really weird offsets that don't comply with the 89020B specification */
     206             164 :     bIsWeirdDTED = achRecord[4] == ' ';
     207                 : 
     208                 : /* -------------------------------------------------------------------- */
     209                 : /*      Parse out position information.  Note that we are extracting    */
     210                 : /*      the top left corner of the top left pixel area, not the         */
     211                 : /*      center of the area.                                             */
     212                 : /* -------------------------------------------------------------------- */
     213             164 :     if (!bIsWeirdDTED)
     214                 :     {
     215             164 :         psDInfo->dfPixelSizeX =
     216             164 :             atoi(DTEDGetField(szResult,achRecord,21,4)) / 36000.0;
     217                 : 
     218             164 :         psDInfo->dfPixelSizeY =
     219             164 :             atoi(DTEDGetField(szResult,achRecord,25,4)) / 36000.0;
     220                 : 
     221             164 :         psDInfo->nXSize = atoi(DTEDGetField(szResult,achRecord,48,4));
     222             164 :         psDInfo->nYSize = atoi(DTEDGetField(szResult,achRecord,52,4));
     223                 :     }
     224                 :     else
     225                 :     {
     226               0 :         psDInfo->dfPixelSizeX =
     227               0 :             atoi(DTEDGetField(szResult,achRecord,41,4)) / 36000.0;
     228                 : 
     229               0 :         psDInfo->dfPixelSizeY =
     230               0 :             atoi(DTEDGetField(szResult,achRecord,45,4)) / 36000.0;
     231                 : 
     232               0 :         psDInfo->nXSize = atoi(DTEDGetField(szResult,psDInfo->pachDSIRecord,563,4));
     233               0 :         psDInfo->nYSize = atoi(DTEDGetField(szResult,psDInfo->pachDSIRecord,567,4));
     234                 :     }
     235                 : 
     236                 :     /* create a scope so I don't need to declare these up top */
     237             164 :     if (!bIsWeirdDTED)
     238                 :     {
     239             164 :         deg = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,5,3)));
     240             164 :         min = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,8,2)));
     241             164 :         sec = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,10,2)));
     242             164 :         chHemisphere = achRecord[11];
     243                 :     }
     244                 :     else
     245                 :     {
     246               0 :         deg = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,9,3)));
     247               0 :         min = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,12,2)));
     248               0 :         sec = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,14,2)));
     249               0 :         chHemisphere = achRecord[15];
     250                 :     }
     251                 : 
     252                 :     /* NOTE : The first version of MIL-D-89020 was buggy.
     253                 :        The latitude and longitude of the LL cornder of the UHF record was inverted.
     254                 :        This was fixed in MIL-D-89020 Amendement 1, but some products may be affected.
     255                 :        We detect this situation by looking at N/S in the longitude field and
     256                 :        E/W in the latitude one
     257                 :     */
     258                 : 
     259             164 :     dfLLOriginX = deg + min / 60.0 + sec / 3600.0;
     260             164 :     if( chHemisphere == 'W' )
     261             118 :         dfLLOriginX *= -1;
     262              46 :     else if ( chHemisphere == 'N' )
     263               2 :         bSwapLatLong = TRUE;
     264              44 :     else if ( chHemisphere == 'S' )
     265                 :     {
     266               0 :         dfLLOriginX *= -1;
     267               0 :         bSwapLatLong = TRUE;
     268                 :     }
     269                 : 
     270             164 :     if (!bIsWeirdDTED)
     271                 :     {
     272             164 :         deg = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,13,3)));
     273             164 :         min = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,16,2)));
     274             164 :         sec = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,18,2)));
     275             164 :         chHemisphere = achRecord[19];
     276                 :     }
     277                 :     else
     278                 :     {
     279               0 :         deg = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,25,3)));
     280               0 :         min = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,28,2)));
     281               0 :         sec = atoi(stripLeadingZeros(DTEDGetField(szResult,achRecord,30,2)));
     282               0 :         chHemisphere = achRecord[31];
     283                 :     }
     284                 : 
     285             164 :     dfLLOriginY = deg + min / 60.0 + sec / 3600.0;
     286             164 :     if( chHemisphere == 'S' || (bSwapLatLong && chHemisphere == 'W'))
     287               2 :         dfLLOriginY *= -1;
     288                 : 
     289             164 :     if (bSwapLatLong)
     290                 :     {
     291               2 :         double dfTmp = dfLLOriginX;
     292               2 :         dfLLOriginX = dfLLOriginY;
     293               2 :         dfLLOriginY = dfTmp;
     294                 :     }
     295                 : 
     296             164 :     psDInfo->dfULCornerX = dfLLOriginX - 0.5 * psDInfo->dfPixelSizeX;
     297             164 :     psDInfo->dfULCornerY = dfLLOriginY - 0.5 * psDInfo->dfPixelSizeY
     298             164 :         + psDInfo->nYSize * psDInfo->dfPixelSizeY;
     299                 : 
     300             164 :     return psDInfo;
     301                 : }
     302                 : 
     303                 : 
     304                 : 
     305                 : /************************************************************************/
     306                 : /*                            DTEDReadPoint()                           */
     307                 : /*                                                                      */
     308                 : /*      Read one single sample. The coordinates are given from the      */
     309                 : /*      top-left corner of the file (contrary to the internal           */
     310                 : /*      organisation or a DTED file)                                    */
     311                 : /************************************************************************/
     312                 : 
     313               0 : int DTEDReadPoint( DTEDInfo * psDInfo, int nXOff, int nYOff, GInt16* panVal)
     314                 : {
     315                 :     int nOffset;
     316                 :     GByte pabyData[2];
     317                 : 
     318               0 :     if (nYOff < 0 || nXOff < 0 || nYOff >= psDInfo->nYSize || nXOff >= psDInfo->nXSize)
     319                 :     {
     320                 : #ifndef AVOID_CPL
     321               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     322                 : #else
     323                 :         fprintf( stderr, 
     324                 : #endif
     325                 :                   "Invalid raster coordinates (%d,%d) in DTED file.\n", nXOff, nYOff);
     326               0 :         return FALSE;
     327                 :     }
     328                 : 
     329               0 :     nOffset = psDInfo->nDataOffset + nXOff * (12+psDInfo->nYSize*2) + 8 + 2 * (psDInfo->nYSize-1-nYOff);
     330               0 :     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
     331               0 :         || VSIFReadL( pabyData, 2, 1, psDInfo->fp ) != 1)
     332                 :     {
     333                 : #ifndef AVOID_CPL
     334               0 :         CPLError( CE_Failure, CPLE_FileIO,
     335                 : #else
     336                 :         fprintf( stderr, 
     337                 : #endif
     338                 :                   "Failed to seek to, or read (%d,%d) at offset %d\n"
     339                 :                   "in DTED file.\n",
     340                 :                   nXOff, nYOff, nOffset );
     341               0 :         return FALSE;
     342                 :     }
     343                 : 
     344               0 :     *panVal = ((pabyData[0] & 0x7f) << 8) | pabyData[1];
     345                 : 
     346               0 :     if( pabyData[0] & 0x80 )
     347                 :     {
     348               0 :         *panVal *= -1;
     349                 : 
     350                 :         /*
     351                 :         ** It seems that some files are improperly generated in twos
     352                 :         ** complement form for negatives.  For these, redo the job
     353                 :         ** in twos complement.  eg. w_069_s50.dt0
     354                 :         */
     355               0 :         if(( *panVal < -16000 ) && (*panVal != DTED_NODATA_VALUE))
     356                 :         {
     357               0 :             *panVal = (pabyData[0] << 8) | pabyData[1];
     358                 : 
     359               0 :             if( !bWarnedTwoComplement )
     360                 :             {
     361               0 :                 bWarnedTwoComplement = TRUE;
     362                 : #ifndef AVOID_CPL
     363               0 :                 CPLError( CE_Warning, CPLE_AppDefined,
     364                 : #else
     365                 :                 fprintf( stderr,
     366                 : #endif
     367                 :                             "The DTED driver found values less than -16000, and has adjusted\n"
     368                 :                             "them assuming they are improperly two-complemented.  No more warnings\n"
     369                 :                             "will be issued in this session about this operation." );
     370                 :             }
     371                 :         }
     372                 :     }
     373                 : 
     374               0 :     return TRUE;
     375                 : }
     376                 : 
     377                 : /************************************************************************/
     378                 : /*                          DTEDReadProfile()                           */
     379                 : /*                                                                      */
     380                 : /*      Read one profile line.  These are organized in bottom to top    */
     381                 : /*      order starting from the leftmost column (0).                    */
     382                 : /************************************************************************/
     383                 : 
     384               0 : int DTEDReadProfile( DTEDInfo * psDInfo, int nColumnOffset,
     385                 :                      GInt16 * panData )
     386                 : {
     387               0 :     return DTEDReadProfileEx( psDInfo, nColumnOffset, panData, FALSE);
     388                 : }
     389                 : 
     390            9262 : int DTEDReadProfileEx( DTEDInfo * psDInfo, int nColumnOffset,
     391                 :                        GInt16 * panData, int bVerifyChecksum )
     392                 : {
     393                 :     int         nOffset;
     394                 :     int         i;
     395                 :     GByte       *pabyRecord;
     396                 : 
     397                 : /* -------------------------------------------------------------------- */
     398                 : /*      Read data record from disk.                                     */
     399                 : /* -------------------------------------------------------------------- */
     400            9262 :     pabyRecord = (GByte *) CPLMalloc(12 + psDInfo->nYSize*2);
     401                 :     
     402            9262 :     nOffset = psDInfo->nDataOffset + nColumnOffset * (12+psDInfo->nYSize*2);
     403                 : 
     404           18524 :     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
     405           18524 :         || VSIFReadL( pabyRecord, (12+psDInfo->nYSize*2), 1, psDInfo->fp ) != 1)
     406                 :     {
     407                 : #ifndef AVOID_CPL
     408               0 :         CPLError( CE_Failure, CPLE_FileIO,
     409                 : #else
     410                 :         fprintf( stderr, 
     411                 : #endif
     412                 :                   "Failed to seek to, or read profile %d at offset %d\n"
     413                 :                   "in DTED file.\n",
     414                 :                   nColumnOffset, nOffset );
     415               0 :         CPLFree( pabyRecord );
     416               0 :         return FALSE;
     417                 :     }
     418                 : 
     419                 : /* -------------------------------------------------------------------- */
     420                 : /*      Translate data values from "signed magnitude" to standard       */
     421                 : /*      binary.                                                         */
     422                 : /* -------------------------------------------------------------------- */
     423         2428124 :     for( i = 0; i < psDInfo->nYSize; i++ )
     424                 :     {
     425         2418862 :         panData[i] = ((pabyRecord[8+i*2] & 0x7f) << 8) | pabyRecord[8+i*2+1];
     426                 : 
     427         2418862 :         if( pabyRecord[8+i*2] & 0x80 )
     428                 :         {
     429               0 :             panData[i] *= -1;
     430                 : 
     431                 :             /*
     432                 :             ** It seems that some files are improperly generated in twos
     433                 :             ** complement form for negatives.  For these, redo the job
     434                 :             ** in twos complement.  eg. w_069_s50.dt0
     435                 :             */
     436               0 :             if(( panData[i] < -16000 ) && (panData[i] != DTED_NODATA_VALUE))
     437                 :             {
     438               0 :                 panData[i] = (pabyRecord[8+i*2] << 8) | pabyRecord[8+i*2+1];
     439                 : 
     440               0 :                 if( !bWarnedTwoComplement )
     441                 :                 {
     442               0 :                     bWarnedTwoComplement = TRUE;
     443                 : #ifndef AVOID_CPL
     444               0 :                     CPLError( CE_Warning, CPLE_AppDefined,
     445                 : #else
     446                 :                     fprintf( stderr,
     447                 : #endif
     448                 :                               "The DTED driver found values less than -16000, and has adjusted\n"
     449                 :                               "them assuming they are improperly two-complemented.  No more warnings\n"
     450                 :                               "will be issued in this session about this operation." );
     451                 :                 }
     452                 :             }
     453                 :         }
     454                 :     }
     455                 : 
     456            9262 :     if (bVerifyChecksum)
     457                 :     {
     458               2 :         unsigned int nCheckSum = 0;
     459                 :         unsigned int fileCheckSum;
     460                 : 
     461                 :         /* -------------------------------------------------------------------- */
     462                 :         /*      Verify the checksum.                                            */
     463                 :         /* -------------------------------------------------------------------- */
     464                 : 
     465             502 :         for( i = 0; i < psDInfo->nYSize*2 + 8; i++ )
     466             500 :             nCheckSum += pabyRecord[i];
     467                 : 
     468               4 :         fileCheckSum = (pabyRecord[8+psDInfo->nYSize*2+0] << 24) |
     469               2 :                         (pabyRecord[8+psDInfo->nYSize*2+1] << 16) |
     470               2 :                         (pabyRecord[8+psDInfo->nYSize*2+2] << 8) |
     471               2 :                         pabyRecord[8+psDInfo->nYSize*2+3];
     472                 : 
     473               2 :         if ((GIntBig)fileCheckSum > (GIntBig)(0xff * (8+psDInfo->nYSize*2)))
     474                 :         {
     475                 :             static int bWarned = FALSE;
     476               0 :             if (! bWarned)
     477                 :             {
     478               0 :                 bWarned = TRUE;
     479                 : #ifndef AVOID_CPL
     480               0 :                 CPLError( CE_Warning, CPLE_AppDefined,
     481                 : #else
     482                 :                 fprintf( stderr,
     483                 : #endif
     484                 :                             "The DTED driver has read from the file a checksum "
     485                 :                             "with an impossible value (0x%X) at column %d.\n"
     486                 :                             "Check with your file producer.\n"
     487                 :                             "No more warnings will be issued in this session about this operation.",
     488                 :                             fileCheckSum, nColumnOffset);
     489                 :             }
     490                 :         }
     491               2 :         else if (fileCheckSum != nCheckSum)
     492                 :         {
     493                 : #ifndef AVOID_CPL
     494               2 :             CPLError( CE_Warning, CPLE_AppDefined,
     495                 : #else
     496                 :             fprintf( stderr,
     497                 : #endif
     498                 :                       "The DTED driver has found a computed and read checksum "
     499                 :                       "that do not match at column %d.\n",
     500                 :                       nColumnOffset);
     501               2 :             CPLFree( pabyRecord );
     502               2 :             return FALSE;
     503                 :         }
     504                 :     }
     505                 : 
     506            9260 :     CPLFree( pabyRecord );
     507                 : 
     508            9260 :     return TRUE;
     509                 : }
     510                 : 
     511                 : /************************************************************************/
     512                 : /*                          DTEDWriteProfile()                          */
     513                 : /************************************************************************/
     514                 : 
     515           28108 : int DTEDWriteProfile( DTEDInfo * psDInfo, int nColumnOffset,
     516                 :                      GInt16 * panData )
     517                 : 
     518                 : {
     519                 :     int         nOffset;
     520           28108 :     int         i, nCheckSum = 0;
     521                 :     GByte       *pabyRecord;
     522                 : 
     523                 : /* -------------------------------------------------------------------- */
     524                 : /*      Format the data record.                                         */
     525                 : /* -------------------------------------------------------------------- */
     526           28108 :     pabyRecord = (GByte *) CPLMalloc(12 + psDInfo->nYSize*2);
     527                 :     
     528        33263096 :     for( i = 0; i < psDInfo->nYSize; i++ )
     529                 :     {
     530        33234988 :         int     nABSVal = ABS(panData[psDInfo->nYSize-i-1]);
     531        33234988 :         pabyRecord[8+i*2] = (GByte) ((nABSVal >> 8) & 0x7f);
     532        33234988 :         pabyRecord[8+i*2+1] = (GByte) (nABSVal & 0xff);
     533                 : 
     534        33234988 :         if( panData[psDInfo->nYSize-i-1] < 0 )
     535         4217475 :             pabyRecord[8+i*2] |= 0x80;
     536                 :     }
     537                 : 
     538           28108 :     pabyRecord[0] = 0xaa;
     539           28108 :     pabyRecord[1] = 0;
     540           28108 :     pabyRecord[2] = (GByte) (nColumnOffset / 256);
     541           28108 :     pabyRecord[3] = (GByte) (nColumnOffset % 256);
     542           28108 :     pabyRecord[4] = (GByte) (nColumnOffset / 256);
     543           28108 :     pabyRecord[5] = (GByte) (nColumnOffset % 256);
     544           28108 :     pabyRecord[6] = 0;
     545           28108 :     pabyRecord[7] = 0;
     546                 : 
     547                 : /* -------------------------------------------------------------------- */
     548                 : /*      Compute the checksum.                                           */
     549                 : /* -------------------------------------------------------------------- */
     550        66722948 :     for( i = 0; i < psDInfo->nYSize*2 + 8; i++ )
     551        66694840 :         nCheckSum += pabyRecord[i];
     552                 : 
     553           28108 :     pabyRecord[8+psDInfo->nYSize*2+0] = (GByte) ((nCheckSum >> 24) & 0xff);
     554           28108 :     pabyRecord[8+psDInfo->nYSize*2+1] = (GByte) ((nCheckSum >> 16) & 0xff);
     555           28108 :     pabyRecord[8+psDInfo->nYSize*2+2] = (GByte) ((nCheckSum >> 8) & 0xff);
     556           28108 :     pabyRecord[8+psDInfo->nYSize*2+3] = (GByte) (nCheckSum & 0xff);
     557                 : 
     558                 : /* -------------------------------------------------------------------- */
     559                 : /*      Write the record.                                               */
     560                 : /* -------------------------------------------------------------------- */
     561           28108 :     nOffset = psDInfo->nDataOffset + nColumnOffset * (12+psDInfo->nYSize*2);
     562                 : 
     563           56216 :     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
     564           56216 :         || VSIFWriteL( pabyRecord,(12+psDInfo->nYSize*2),1,psDInfo->fp ) != 1)
     565                 :     {
     566                 : #ifndef AVOID_CPL
     567               0 :         CPLError( CE_Failure, CPLE_FileIO,
     568                 : #else
     569                 :         fprintf( stderr, 
     570                 : #endif
     571                 :                   "Failed to seek to, or write profile %d at offset %d\n"
     572                 :                   "in DTED file.\n",
     573                 :                   nColumnOffset, nOffset );
     574               0 :         CPLFree( pabyRecord );
     575               0 :         return FALSE;
     576                 :     }
     577                 : 
     578           28108 :     CPLFree( pabyRecord );
     579                 : 
     580           28108 :     return TRUE;
     581                 :     
     582                 : }
     583                 : 
     584                 : /************************************************************************/
     585                 : /*                      DTEDGetMetadataLocation()                       */
     586                 : /************************************************************************/
     587                 : 
     588            3068 : static void DTEDGetMetadataLocation( DTEDInfo *psDInfo, 
     589                 :                                      DTEDMetaDataCode eCode, 
     590                 :                                      char **ppszLocation, int *pnLength )
     591                 : {
     592            3068 :     int bIsWeirdDTED = psDInfo->pachUHLRecord[4] == ' ';
     593                 : 
     594            3068 :     switch( eCode )
     595                 :     {
     596                 :       case DTEDMD_ORIGINLONG:
     597             136 :         if (bIsWeirdDTED)
     598               0 :             *ppszLocation = psDInfo->pachUHLRecord + 8;
     599                 :         else
     600             136 :             *ppszLocation = psDInfo->pachUHLRecord + 4;
     601             136 :         *pnLength = 8;
     602             136 :         break;
     603                 : 
     604                 :       case DTEDMD_ORIGINLAT:
     605             136 :         if (bIsWeirdDTED)
     606               0 :             *ppszLocation = psDInfo->pachUHLRecord + 24;
     607                 :         else
     608             136 :             *ppszLocation = psDInfo->pachUHLRecord + 12;
     609             136 :         *pnLength = 8;
     610             136 :         break;
     611                 : 
     612                 :       case DTEDMD_VERTACCURACY_UHL:
     613             140 :         if (bIsWeirdDTED)
     614               0 :             *ppszLocation = psDInfo->pachUHLRecord + 56;
     615                 :         else
     616             140 :             *ppszLocation = psDInfo->pachUHLRecord + 28;
     617             140 :         *pnLength = 4;
     618             140 :         break;
     619                 : 
     620                 :       case DTEDMD_SECURITYCODE_UHL:
     621             140 :         if (bIsWeirdDTED)
     622               0 :             *ppszLocation = psDInfo->pachUHLRecord + 60;
     623                 :         else
     624             140 :             *ppszLocation = psDInfo->pachUHLRecord + 32;
     625             140 :         *pnLength = 3;
     626             140 :         break;
     627                 : 
     628                 :       case DTEDMD_UNIQUEREF_UHL:
     629             140 :         if (bIsWeirdDTED)
     630               0 :             *ppszLocation = NULL;
     631                 :         else
     632             140 :             *ppszLocation = psDInfo->pachUHLRecord + 35;
     633             140 :         *pnLength = 12;
     634             140 :         break;
     635                 : 
     636                 :       case DTEDMD_DATA_EDITION:
     637             140 :         if (bIsWeirdDTED)
     638               0 :             *ppszLocation = psDInfo->pachDSIRecord + 174;
     639                 :         else
     640             140 :             *ppszLocation = psDInfo->pachDSIRecord + 87;
     641             140 :         *pnLength = 2;
     642             140 :         break;
     643                 : 
     644                 :       case DTEDMD_MATCHMERGE_VERSION:
     645             140 :         if (bIsWeirdDTED)
     646               0 :             *ppszLocation = psDInfo->pachDSIRecord + 176;
     647                 :         else
     648             140 :             *ppszLocation = psDInfo->pachDSIRecord + 89;
     649             140 :         *pnLength = 1;
     650             140 :         break;
     651                 : 
     652                 :       case DTEDMD_MAINT_DATE:
     653             140 :         if (bIsWeirdDTED)
     654               0 :             *ppszLocation = psDInfo->pachDSIRecord + 177;
     655                 :         else
     656             140 :             *ppszLocation = psDInfo->pachDSIRecord + 90;
     657             140 :         *pnLength = 4;
     658             140 :         break;
     659                 : 
     660                 :       case DTEDMD_MATCHMERGE_DATE:
     661             140 :         if (bIsWeirdDTED)
     662               0 :             *ppszLocation = psDInfo->pachDSIRecord + 181;
     663                 :         else
     664             140 :             *ppszLocation = psDInfo->pachDSIRecord + 94;
     665             140 :         *pnLength = 4;
     666             140 :         break;
     667                 : 
     668                 :       case DTEDMD_MAINT_DESCRIPTION:
     669             140 :         if (bIsWeirdDTED)
     670               0 :             *ppszLocation = psDInfo->pachDSIRecord + 185;
     671                 :         else
     672             140 :             *ppszLocation = psDInfo->pachDSIRecord + 98;
     673             140 :         *pnLength = 4;
     674             140 :         break;
     675                 : 
     676                 :       case DTEDMD_PRODUCER:
     677             140 :         if (bIsWeirdDTED)
     678               0 :             *ppszLocation = psDInfo->pachDSIRecord + 189;
     679                 :         else
     680             140 :             *ppszLocation = psDInfo->pachDSIRecord + 102;
     681             140 :         *pnLength = 8;
     682             140 :         break;
     683                 : 
     684                 :       case DTEDMD_VERTDATUM:
     685             140 :         if (bIsWeirdDTED)
     686               0 :             *ppszLocation = psDInfo->pachDSIRecord + 267;
     687                 :         else
     688             140 :             *ppszLocation = psDInfo->pachDSIRecord + 141;
     689             140 :         *pnLength = 3;
     690             140 :         break;
     691                 : 
     692                 :       case DTEDMD_HORIZDATUM:
     693             140 :         if (bIsWeirdDTED)
     694               0 :             *ppszLocation = psDInfo->pachDSIRecord + 270;
     695                 :         else
     696             140 :             *ppszLocation = psDInfo->pachDSIRecord + 144; 
     697             140 :         *pnLength = 5; 
     698             140 :         break; 
     699                 : 
     700                 :       case DTEDMD_DIGITIZING_SYS:
     701             140 :         if (bIsWeirdDTED)
     702               0 :             *ppszLocation = NULL;
     703                 :         else
     704             140 :             *ppszLocation = psDInfo->pachDSIRecord + 149;
     705             140 :         *pnLength = 10;
     706             140 :         break;
     707                 : 
     708                 :       case DTEDMD_COMPILATION_DATE:
     709             140 :         if (bIsWeirdDTED)
     710               0 :             *ppszLocation = NULL;
     711                 :         else
     712             140 :             *ppszLocation = psDInfo->pachDSIRecord + 159;
     713             140 :         *pnLength = 4;
     714             140 :         break;
     715                 : 
     716                 :       case DTEDMD_HORIZACCURACY:
     717             140 :         *ppszLocation = psDInfo->pachACCRecord + 3;
     718             140 :         *pnLength = 4;
     719             140 :         break;
     720                 : 
     721                 :       case DTEDMD_REL_HORIZACCURACY:
     722             140 :         *ppszLocation = psDInfo->pachACCRecord + 11;
     723             140 :         *pnLength = 4;
     724             140 :         break;
     725                 : 
     726                 :       case DTEDMD_REL_VERTACCURACY:
     727             140 :         *ppszLocation = psDInfo->pachACCRecord + 15;
     728             140 :         *pnLength = 4;
     729             140 :         break;
     730                 : 
     731                 :       case DTEDMD_VERTACCURACY_ACC:
     732             140 :         *ppszLocation = psDInfo->pachACCRecord + 7;
     733             140 :         *pnLength = 4;
     734             140 :         break;
     735                 : 
     736                 :       case DTEDMD_SECURITYCODE_DSI:
     737             140 :         *ppszLocation = psDInfo->pachDSIRecord + 3;
     738             140 :         *pnLength = 1;
     739             140 :         break;
     740                 : 
     741                 :       case DTEDMD_UNIQUEREF_DSI:
     742             140 :         if (bIsWeirdDTED)
     743               0 :             *ppszLocation = NULL;
     744                 :         else
     745             140 :             *ppszLocation = psDInfo->pachDSIRecord + 64;
     746             140 :         *pnLength = 15;
     747             140 :         break;
     748                 : 
     749                 :       case DTEDMD_NIMA_DESIGNATOR:
     750             136 :         if (bIsWeirdDTED)
     751               0 :             *ppszLocation = psDInfo->pachDSIRecord + 118;
     752                 :         else
     753             136 :             *ppszLocation = psDInfo->pachDSIRecord + 59;
     754             136 :         *pnLength = 5;
     755             136 :         break;
     756                 : 
     757                 :       default:
     758               0 :         *ppszLocation = NULL;
     759               0 :         *pnLength = 0;
     760                 :     }
     761            3068 : }
     762                 : 
     763                 : /************************************************************************/
     764                 : /*                          DTEDGetMetadata()                           */
     765                 : /************************************************************************/
     766                 : 
     767            2992 : char *DTEDGetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode )
     768                 : 
     769                 : {
     770                 :     int nFieldLen;
     771                 :     char *pszFieldSrc;
     772                 :     char *pszResult;
     773                 : 
     774            2992 :     DTEDGetMetadataLocation( psDInfo, eCode, &pszFieldSrc, &nFieldLen );
     775            2992 :     if( pszFieldSrc == NULL )
     776               0 :         return strdup( "" );
     777                 : 
     778            2992 :     pszResult = (char *) malloc(nFieldLen+1);
     779            2992 :     strncpy( pszResult, pszFieldSrc, nFieldLen );
     780            2992 :     pszResult[nFieldLen] = '\0';
     781                 : 
     782            2992 :     return pszResult;
     783                 : }
     784                 : 
     785                 : /************************************************************************/
     786                 : /*                          DTEDSetMetadata()                           */
     787                 : /************************************************************************/
     788                 : 
     789              76 : int DTEDSetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode, 
     790                 :                      const char *pszNewValue )
     791                 : 
     792                 : {
     793                 :     int nFieldLen;
     794                 :     char *pszFieldSrc;
     795                 : 
     796              76 :     if( !psDInfo->bUpdate )
     797               0 :         return FALSE;
     798                 : 
     799                 : /* -------------------------------------------------------------------- */
     800                 : /*      Get the location in the headers to update.                      */
     801                 : /* -------------------------------------------------------------------- */
     802              76 :     DTEDGetMetadataLocation( psDInfo, eCode, &pszFieldSrc, &nFieldLen );
     803              76 :     if( pszFieldSrc == NULL )
     804               0 :         return FALSE;
     805                 : 
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*      Update it, padding with spaces.                                 */
     808                 : /* -------------------------------------------------------------------- */
     809              76 :     memset( pszFieldSrc, ' ', nFieldLen );
     810              76 :     strncpy( pszFieldSrc, pszNewValue, 
     811              76 :              MIN((size_t)nFieldLen,strlen(pszNewValue)) );
     812                 : 
     813                 : /* -------------------------------------------------------------------- */
     814                 : /*      Write all headers back to disk.                                 */
     815                 : /* -------------------------------------------------------------------- */
     816              76 :     VSIFSeekL( psDInfo->fp, psDInfo->nUHLOffset, SEEK_SET );
     817              76 :     VSIFWriteL( psDInfo->pachUHLRecord, 1, DTED_UHL_SIZE, psDInfo->fp );
     818                 : 
     819              76 :     VSIFSeekL( psDInfo->fp, psDInfo->nDSIOffset, SEEK_SET );
     820              76 :     VSIFWriteL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, psDInfo->fp );
     821                 : 
     822              76 :     VSIFSeekL( psDInfo->fp, psDInfo->nACCOffset, SEEK_SET );
     823              76 :     VSIFWriteL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, psDInfo->fp );
     824                 : 
     825              76 :     return TRUE;
     826                 : }
     827                 : 
     828                 : /************************************************************************/
     829                 : /*                             DTEDClose()                              */
     830                 : /************************************************************************/
     831                 : 
     832             164 : void DTEDClose( DTEDInfo * psDInfo )
     833                 : 
     834                 : {
     835             164 :     VSIFCloseL( psDInfo->fp );
     836                 : 
     837             164 :     CPLFree( psDInfo->pachUHLRecord );
     838             164 :     CPLFree( psDInfo->pachDSIRecord );
     839             164 :     CPLFree( psDInfo->pachACCRecord );
     840                 :     
     841             164 :     CPLFree( psDInfo );
     842             164 : }

Generated by: LCOV version 1.7