LCOV - code coverage report
Current view: directory - frmts/dted - dteddataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 359 292 81.3 %
Date: 2012-12-26 Functions: 21 15 71.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: dteddataset.cpp 24517 2012-05-30 21:07:47Z rouault $
       3                 :  *
       4                 :  * Project:  DTED Translator
       5                 :  * Purpose:  GDALDataset driver for DTED translator.
       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                 : #include "gdal_pam.h"
      32                 : #include "ogr_spatialref.h"
      33                 : 
      34                 : CPL_CVSID("$Id: dteddataset.cpp 24517 2012-05-30 21:07:47Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void    GDALRegister_DTED(void);
      38                 : CPL_C_END
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                              DTEDDataset                             */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46                 : class DTEDRasterBand;
      47                 : 
      48                 : class DTEDDataset : public GDALPamDataset
      49                 : {
      50                 :     friend class DTEDRasterBand;
      51                 : 
      52                 :     char        *pszFilename;
      53                 :     DTEDInfo    *psDTED;
      54                 :     int         bVerifyChecksum;
      55                 :     char       *pszProjection;
      56                 : 
      57                 :   public:
      58                 :                  DTEDDataset();
      59                 :     virtual     ~DTEDDataset();
      60                 :     
      61                 :     virtual const char *GetProjectionRef(void);
      62                 :     virtual CPLErr GetGeoTransform( double * );
      63                 :     
      64               1 :     const char* GetFileName() { return pszFilename; }
      65                 :     void SetFileName(const char* pszFilename);
      66                 :     
      67                 :     static GDALDataset *Open( GDALOpenInfo * );
      68                 :     static int Identify( GDALOpenInfo * );
      69                 : };
      70                 : 
      71                 : /************************************************************************/
      72                 : /* ==================================================================== */
      73                 : /*                            DTEDRasterBand                             */
      74                 : /* ==================================================================== */
      75                 : /************************************************************************/
      76                 : 
      77                 : class DTEDRasterBand : public GDALPamRasterBand
      78              72 : {
      79                 :     friend class DTEDDataset;
      80                 : 
      81                 :     int   bNoDataSet;
      82                 :     double  dfNoDataValue;
      83                 : 
      84                 :   public:
      85                 : 
      86                 :                 DTEDRasterBand( DTEDDataset *, int );
      87                 :     
      88                 :     virtual CPLErr IReadBlock( int, int, void * );
      89                 :     virtual CPLErr IWriteBlock( int, int, void * );
      90                 : 
      91                 :     virtual double  GetNoDataValue( int *pbSuccess = NULL );
      92                 : 
      93              23 :     virtual const char* GetUnitType() { return "m"; }
      94                 : };
      95                 : 
      96                 : 
      97                 : /************************************************************************/
      98                 : /*                           DTEDRasterBand()                            */
      99                 : /************************************************************************/
     100                 : 
     101              72 : DTEDRasterBand::DTEDRasterBand( DTEDDataset *poDS, int nBand )
     102                 : 
     103                 : {
     104              72 :     this->poDS = poDS;
     105              72 :     this->nBand = nBand;
     106                 :     
     107              72 :     eDataType = GDT_Int16;
     108                 : 
     109              72 :     bNoDataSet = TRUE;
     110              72 :     dfNoDataValue = (double) DTED_NODATA_VALUE;
     111                 : 
     112                 :     /* For some applications, it may be valuable to consider the whole DTED */
     113                 :     /* file as single block, as the column orientation doesn't fit very well */
     114                 :     /* with some scanline oriented algorithms */
     115                 :     /* Of course you need to have a big enough case size, particularly for DTED 2 */
     116                 :     /* datasets */
     117                 :     nBlockXSize = CSLTestBoolean(CPLGetConfigOption("GDAL_DTED_SINGLE_BLOCK", "NO")) ?
     118              72 :                             poDS->GetRasterXSize() : 1;
     119              72 :     nBlockYSize = poDS->GetRasterYSize();
     120              72 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                             IReadBlock()                             */
     124                 : /************************************************************************/
     125                 : 
     126            4994 : CPLErr DTEDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     127                 :                                   void * pImage )
     128                 : 
     129                 : {
     130            4994 :     DTEDDataset *poDTED_DS = (DTEDDataset *) poDS;
     131            4994 :     int         nYSize = poDTED_DS->psDTED->nYSize;
     132                 :     GInt16      *panData;
     133                 : 
     134                 :     (void) nBlockXOff;
     135            4994 :     CPLAssert( nBlockYOff == 0 );
     136                 : 
     137            4994 :     if (nBlockXSize != 1)
     138                 :     {
     139               0 :         panData = (GInt16 *) pImage;
     140               0 :         GInt16* panBuffer = (GInt16*) CPLMalloc(sizeof(GInt16) * nBlockYSize);
     141                 :         int i;
     142               0 :         for(i=0;i<nBlockXSize;i++)
     143                 :         {
     144               0 :             if( !DTEDReadProfileEx( poDTED_DS->psDTED, i, panBuffer,
     145                 :                                     poDTED_DS->bVerifyChecksum ) )
     146                 :             {
     147               0 :                 CPLFree(panBuffer);
     148               0 :                 return CE_Failure;
     149                 :             }
     150                 :             int j;
     151               0 :             for(j=0;j<nBlockYSize;j++)
     152                 :             {
     153               0 :                 panData[j * nBlockXSize + i] = panBuffer[nYSize - j - 1];
     154                 :             }
     155                 :         }
     156                 : 
     157               0 :         CPLFree(panBuffer);
     158               0 :         return CE_None;
     159                 :     }
     160                 :     
     161                 : /* -------------------------------------------------------------------- */
     162                 : /*      Read the data.                                                  */
     163                 : /* -------------------------------------------------------------------- */
     164            4994 :     panData = (GInt16 *) pImage;
     165            4994 :     if( !DTEDReadProfileEx( poDTED_DS->psDTED, nBlockXOff, panData,
     166                 :                             poDTED_DS->bVerifyChecksum ) )
     167               1 :         return CE_Failure;
     168                 : 
     169                 : /* -------------------------------------------------------------------- */
     170                 : /*      Flip line to orient it top to bottom instead of bottom to       */
     171                 : /*      top.                                                            */
     172                 : /* -------------------------------------------------------------------- */
     173          634106 :     for( int i = nYSize/2; i >= 0; i-- )
     174                 :     {
     175                 :         GInt16  nTemp;
     176                 : 
     177          629113 :         nTemp = panData[i];
     178          629113 :         panData[i] = panData[nYSize - i - 1];
     179          629113 :         panData[nYSize - i - 1] = nTemp;
     180                 :     }
     181                 : 
     182            4993 :     return CE_None;
     183                 : }
     184                 : 
     185                 : /************************************************************************/
     186                 : /*                             IReadBlock()                             */
     187                 : /************************************************************************/
     188                 : 
     189               0 : CPLErr DTEDRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     190                 :                                   void * pImage )
     191                 : 
     192                 : {
     193               0 :     DTEDDataset *poDTED_DS = (DTEDDataset *) poDS;
     194                 :     GInt16      *panData;
     195                 : 
     196                 :     (void) nBlockXOff;
     197               0 :     CPLAssert( nBlockYOff == 0 );
     198                 : 
     199               0 :     if (poDTED_DS->eAccess != GA_Update)
     200               0 :         return CE_Failure;
     201                 : 
     202               0 :     if (nBlockXSize != 1)
     203                 :     {
     204               0 :         panData = (GInt16 *) pImage;
     205               0 :         GInt16* panBuffer = (GInt16*) CPLMalloc(sizeof(GInt16) * nBlockYSize);
     206                 :         int i;
     207               0 :         for(i=0;i<nBlockXSize;i++)
     208                 :         {
     209                 :             int j;
     210               0 :             for(j=0;j<nBlockYSize;j++)
     211                 :             {
     212               0 :                 panBuffer[j] = panData[j * nBlockXSize + i];
     213                 :             }
     214               0 :             if( !DTEDWriteProfile( poDTED_DS->psDTED, i, panBuffer) )
     215                 :             {
     216               0 :                 CPLFree(panBuffer);
     217               0 :                 return CE_Failure;
     218                 :             }
     219                 :         }
     220                 : 
     221               0 :         CPLFree(panBuffer);
     222               0 :         return CE_None;
     223                 :     }
     224                 : 
     225               0 :     panData = (GInt16 *) pImage;
     226               0 :     if( !DTEDWriteProfile( poDTED_DS->psDTED, nBlockXOff, panData) )
     227               0 :         return CE_Failure;
     228                 : 
     229               0 :     return CE_None;
     230                 : }
     231                 : 
     232                 : /************************************************************************/
     233                 : /*                           GetNoDataValue()                           */
     234                 : /************************************************************************/
     235                 : 
     236              67 : double DTEDRasterBand::GetNoDataValue( int * pbSuccess )
     237                 : 
     238                 : {
     239              67 :     if( pbSuccess )
     240              58 :         *pbSuccess = bNoDataSet;
     241                 : 
     242              67 :     return dfNoDataValue;
     243                 : }
     244                 : 
     245                 : /************************************************************************/
     246                 : /*                            ~DTEDDataset()                            */
     247                 : /************************************************************************/
     248                 : 
     249              72 : DTEDDataset::DTEDDataset()
     250                 : {
     251              72 :     pszFilename = CPLStrdup("unknown");
     252              72 :     pszProjection = CPLStrdup("");
     253              72 :     bVerifyChecksum = CSLTestBoolean(CPLGetConfigOption("DTED_VERIFY_CHECKSUM", "NO"));
     254              72 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                            ~DTEDDataset()                            */
     258                 : /************************************************************************/
     259                 : 
     260              72 : DTEDDataset::~DTEDDataset()
     261                 : 
     262                 : {
     263              72 :     FlushCache();
     264              72 :     CPLFree(pszFilename);
     265              72 :     CPLFree( pszProjection );
     266              72 :     if( psDTED != NULL )
     267              72 :         DTEDClose( psDTED );
     268              72 : }
     269                 : 
     270                 : /************************************************************************/
     271                 : /*                            SetFileName()                             */
     272                 : /************************************************************************/
     273                 : 
     274              72 : void DTEDDataset::SetFileName(const char* pszFilename)
     275                 : 
     276                 : {
     277              72 :     CPLFree(this->pszFilename);
     278              72 :     this->pszFilename = CPLStrdup(pszFilename);
     279              72 : }
     280                 : 
     281                 : /************************************************************************/
     282                 : /*                              Identify()                              */
     283                 : /************************************************************************/
     284                 : 
     285           14202 : int DTEDDataset::Identify( GDALOpenInfo * poOpenInfo )
     286                 : 
     287                 : {
     288                 :     int         i;
     289                 : 
     290                 : /* -------------------------------------------------------------------- */
     291                 : /*      Does the file start with one of the possible DTED header        */
     292                 : /*      record types, and do we have a UHL marker?                      */
     293                 : /* -------------------------------------------------------------------- */
     294           14202 :     if( poOpenInfo->nHeaderBytes < 240 )
     295           12181 :         return FALSE;
     296                 : 
     297            2021 :     if( !EQUALN((const char *)poOpenInfo->pabyHeader,"VOL",3)
     298                 :         && !EQUALN((const char *)poOpenInfo->pabyHeader,"HDR",3)
     299                 :         && !EQUALN((const char *)poOpenInfo->pabyHeader,"UHL",3) )
     300                 :     {
     301            1949 :         return FALSE;
     302                 :     }
     303                 : 
     304              72 :     int bFoundUHL = FALSE;
     305             145 :     for(i=0;i<poOpenInfo->nHeaderBytes-3 && !bFoundUHL ;i += DTED_UHL_SIZE)
     306                 :     {
     307              73 :         if( EQUALN((const char *)poOpenInfo->pabyHeader + i,"UHL", 3) )
     308                 :         {
     309              72 :             bFoundUHL = TRUE;
     310                 :         }
     311                 :     }
     312              72 :     if (!bFoundUHL)
     313               0 :         return FALSE;
     314                 : 
     315              72 :     return TRUE;
     316                 : }
     317                 : 
     318                 : /************************************************************************/
     319                 : /*                                Open()                                */
     320                 : /************************************************************************/
     321                 : 
     322            3984 : GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
     323                 : 
     324                 : {
     325                 :     int         i;
     326                 :     DTEDInfo    *psDTED;
     327                 : 
     328            3984 :     if (!Identify(poOpenInfo))
     329            3912 :         return NULL;
     330                 : 
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Try opening the dataset.                                        */
     333                 : /* -------------------------------------------------------------------- */
     334              72 :     psDTED = DTEDOpen( poOpenInfo->pszFilename, (poOpenInfo->eAccess == GA_Update) ? "rb+" : "rb", TRUE );
     335                 : 
     336              72 :     if( psDTED == NULL )
     337               0 :         return( NULL );
     338                 : 
     339                 : /* -------------------------------------------------------------------- */
     340                 : /*      Create a corresponding GDALDataset.                             */
     341                 : /* -------------------------------------------------------------------- */
     342                 :     DTEDDataset         *poDS;
     343                 : 
     344              72 :     poDS = new DTEDDataset();
     345              72 :     poDS->SetFileName(poOpenInfo->pszFilename);
     346                 : 
     347              72 :     poDS->eAccess = poOpenInfo->eAccess;
     348              72 :     poDS->psDTED = psDTED;
     349                 : 
     350                 : /* -------------------------------------------------------------------- */
     351                 : /*      Capture some information from the file that is of interest.     */
     352                 : /* -------------------------------------------------------------------- */
     353              72 :     poDS->nRasterXSize = psDTED->nXSize;
     354              72 :     poDS->nRasterYSize = psDTED->nYSize;
     355                 :     
     356              72 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     357                 :     {
     358               0 :         delete poDS;
     359               0 :         return NULL;
     360                 :     }
     361                 :     
     362                 : /* -------------------------------------------------------------------- */
     363                 : /*      Create band information objects.                                */
     364                 : /* -------------------------------------------------------------------- */
     365              72 :     poDS->nBands = 1;
     366             288 :     for( i = 0; i < poDS->nBands; i++ )
     367              72 :         poDS->SetBand( i+1, new DTEDRasterBand( poDS, i+1 ) );
     368                 : 
     369                 : /* -------------------------------------------------------------------- */
     370                 : /*      Collect any metadata available.                                 */
     371                 : /* -------------------------------------------------------------------- */
     372                 :     char *pszValue;
     373                 : 
     374              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL );
     375              72 :     poDS->SetMetadataItem( "DTED_VerticalAccuracy_UHL", pszValue );
     376              72 :     free( pszValue );
     377                 : 
     378              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC );
     379              72 :     poDS->SetMetadataItem( "DTED_VerticalAccuracy_ACC", pszValue );
     380              72 :     free( pszValue );
     381                 : 
     382              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL );
     383              72 :     poDS->SetMetadataItem( "DTED_SecurityCode_UHL", pszValue );
     384              72 :     free( pszValue );
     385                 : 
     386              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI );
     387              72 :     poDS->SetMetadataItem( "DTED_SecurityCode_DSI", pszValue );
     388              72 :     free( pszValue );
     389                 : 
     390              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL );
     391              72 :     poDS->SetMetadataItem( "DTED_UniqueRef_UHL", pszValue );
     392              72 :     free( pszValue );
     393                 : 
     394              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI );
     395              72 :     poDS->SetMetadataItem( "DTED_UniqueRef_DSI", pszValue );
     396              72 :     free( pszValue );
     397                 : 
     398              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_DATA_EDITION );
     399              72 :     poDS->SetMetadataItem( "DTED_DataEdition", pszValue );
     400              72 :     free( pszValue );
     401                 : 
     402              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION );
     403              72 :     poDS->SetMetadataItem( "DTED_MatchMergeVersion", pszValue );
     404              72 :     free( pszValue );
     405                 : 
     406              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_MAINT_DATE );
     407              72 :     poDS->SetMetadataItem( "DTED_MaintenanceDate", pszValue );
     408              72 :     free( pszValue );
     409                 : 
     410              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE );
     411              72 :     poDS->SetMetadataItem( "DTED_MatchMergeDate", pszValue );
     412              72 :     free( pszValue );
     413                 : 
     414              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION );
     415              72 :     poDS->SetMetadataItem( "DTED_MaintenanceDescription", pszValue );
     416              72 :     free( pszValue );
     417                 : 
     418              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_PRODUCER );
     419              72 :     poDS->SetMetadataItem( "DTED_Producer", pszValue );
     420              72 :     free( pszValue );
     421                 : 
     422              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_VERTDATUM );
     423              72 :     poDS->SetMetadataItem( "DTED_VerticalDatum", pszValue );
     424              72 :     free( pszValue );
     425                 : 
     426              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_HORIZDATUM );
     427              72 :     poDS->SetMetadataItem( "DTED_HorizontalDatum", pszValue );
     428              72 :     free( pszValue );
     429                 : 
     430              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_DIGITIZING_SYS );
     431              72 :     poDS->SetMetadataItem( "DTED_DigitizingSystem", pszValue );
     432              72 :     free( pszValue );
     433                 : 
     434              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_COMPILATION_DATE );
     435              72 :     poDS->SetMetadataItem( "DTED_CompilationDate", pszValue );
     436              72 :     free( pszValue );
     437                 : 
     438              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_HORIZACCURACY );
     439              72 :     poDS->SetMetadataItem( "DTED_HorizontalAccuracy", pszValue );
     440              72 :     free( pszValue );
     441                 : 
     442              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY );
     443              72 :     poDS->SetMetadataItem( "DTED_RelHorizontalAccuracy", pszValue );
     444              72 :     free( pszValue );
     445                 : 
     446              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_REL_VERTACCURACY );
     447              72 :     poDS->SetMetadataItem( "DTED_RelVerticalAccuracy", pszValue );
     448              72 :     free( pszValue );
     449                 :     
     450              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_ORIGINLAT );
     451              72 :     poDS->SetMetadataItem( "DTED_OriginLatitude", pszValue );
     452              72 :     free( pszValue );
     453                 :     
     454              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_ORIGINLONG );
     455              72 :     poDS->SetMetadataItem( "DTED_OriginLongitude", pszValue );
     456              72 :     free( pszValue );
     457                 :     
     458              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_NIMA_DESIGNATOR ); 
     459              72 :     poDS->SetMetadataItem( "DTED_NimaDesignator", pszValue ); 
     460              72 :     free( pszValue );
     461                 : 
     462              72 :     pszValue = DTEDGetMetadata( psDTED, DTEDMD_PARTIALCELL_DSI );
     463              72 :     poDS->SetMetadataItem( "DTED_PartialCellIndicator", pszValue );
     464              72 :     free( pszValue ); 
     465                 : 
     466              72 :     poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      Initialize any PAM information.                                 */
     470                 : /* -------------------------------------------------------------------- */
     471              72 :     poDS->SetDescription( poOpenInfo->pszFilename );
     472              72 :     poDS->TryLoadXML();
     473                 : 
     474                 :     // if no SR in xml, try aux
     475              72 :     const char* pszPrj = poDS->GDALPamDataset::GetProjectionRef();
     476              72 :     if( !pszPrj || strlen(pszPrj) == 0 )
     477                 :     {
     478              72 :         GDALDataset* poAuxDS = GDALFindAssociatedAuxFile( poOpenInfo->pszFilename, GA_ReadOnly, poDS );
     479              72 :         if( poAuxDS )
     480                 :         {
     481               0 :             pszPrj = poAuxDS->GetProjectionRef();
     482               0 :             if( pszPrj && strlen(pszPrj) > 0 )
     483                 :             {
     484               0 :                 CPLFree( poDS->pszProjection );
     485               0 :                 poDS->pszProjection = CPLStrdup(pszPrj);
     486                 :             }
     487                 : 
     488               0 :             GDALClose( poAuxDS );
     489                 :         }
     490                 :     }
     491                 : 
     492                 : /* -------------------------------------------------------------------- */
     493                 : /*      Support overviews.                                              */
     494                 : /* -------------------------------------------------------------------- */
     495              72 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     496              72 :     return( poDS );
     497                 : }
     498                 : 
     499                 : /************************************************************************/
     500                 : /*                          GetGeoTransform()                           */
     501                 : /************************************************************************/
     502                 : 
     503              76 : CPLErr DTEDDataset::GetGeoTransform( double * padfTransform )
     504                 : 
     505                 : {
     506              76 :     padfTransform[0] = psDTED->dfULCornerX;
     507              76 :     padfTransform[1] = psDTED->dfPixelSizeX;
     508              76 :     padfTransform[2] = 0.0;
     509              76 :     padfTransform[3] = psDTED->dfULCornerY;
     510              76 :     padfTransform[4] = 0.0;
     511              76 :     padfTransform[5] = psDTED->dfPixelSizeY * -1;
     512                 : 
     513              76 :     return( CE_None );
     514                 : }
     515                 : 
     516                 : /************************************************************************/
     517                 : /*                          GetProjectionRef()                          */
     518                 : /************************************************************************/
     519                 : 
     520              71 : const char *DTEDDataset::GetProjectionRef()
     521                 : 
     522                 : {
     523                 :     // get xml and aux SR first
     524              71 :     const char* pszPrj = GDALPamDataset::GetProjectionRef();
     525              71 :     if(pszPrj && strlen(pszPrj) > 0)
     526               0 :         return pszPrj;
     527                 : 
     528              71 :     if (pszProjection && strlen(pszProjection) > 0)
     529               0 :         return pszProjection;
     530                 : 
     531              71 :     pszPrj = GetMetadataItem( "DTED_HorizontalDatum");
     532              71 :     if (EQUAL(pszPrj, "WGS84"))
     533                 :     {
     534              70 :         return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
     535                 :     }
     536               1 :     else if (EQUAL(pszPrj, "WGS72"))
     537                 :     {
     538                 :         static int bWarned = FALSE;
     539               1 :         if (!bWarned)
     540                 :         {
     541               1 :             bWarned = TRUE;
     542                 :             CPLError( CE_Warning, CPLE_AppDefined,
     543                 :                       "The DTED file %s indicates WGS72 as horizontal datum. \n"
     544                 :                       "As this is outdated nowadays, you should contact your data producer to get data georeferenced in WGS84.\n"
     545                 :                       "In some cases, WGS72 is a wrong indication and the georeferencing is really WGS84. In that case\n"
     546                 :                       "you might consider doing 'gdal_translate -of DTED -mo \"DTED_HorizontalDatum=WGS84\" src.dtX dst.dtX' to\n"
     547                 :                       "fix the DTED file.\n"
     548               1 :                       "No more warnings will be issued in this session about this operation.", GetFileName() );
     549                 :         }
     550               1 :         return "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4322\"]]"; 
     551                 :     }
     552                 :     else
     553                 :     {
     554                 :         static int bWarned = FALSE;
     555               0 :         if (!bWarned)
     556                 :         {
     557               0 :             bWarned = TRUE;
     558                 :             CPLError( CE_Warning, CPLE_AppDefined,
     559                 :                       "The DTED file %s indicates %s as horizontal datum, which is not recognized by the DTED driver. \n"
     560                 :                       "The DTED driver is going to consider it as WGS84.\n"
     561               0 :                       "No more warnings will be issued in this session about this operation.", GetFileName(), pszPrj );
     562                 :         }
     563               0 :         return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
     564                 :     }
     565                 : }
     566                 : 
     567                 : /************************************************************************/
     568                 : /*                           DTEDCreateCopy()                           */
     569                 : /*                                                                      */
     570                 : /*      For now we will assume the input is exactly one proper          */
     571                 : /*      cell.                                                           */
     572                 : /************************************************************************/
     573                 : 
     574                 : static GDALDataset *
     575              32 : DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     576                 :                 int bStrict, char ** papszOptions, 
     577                 :                 GDALProgressFunc pfnProgress, void * pProgressData )
     578                 : 
     579                 : {
     580                 :     (void) pProgressData;
     581                 :     (void) pfnProgress;
     582                 :     (void) papszOptions;
     583                 :     (void) bStrict;
     584                 : 
     585                 : 
     586                 : /* -------------------------------------------------------------------- */
     587                 : /*      Some some rudimentary checks                                    */
     588                 : /* -------------------------------------------------------------------- */
     589              32 :     int nBands = poSrcDS->GetRasterCount();
     590              32 :     if (nBands == 0)
     591                 :     {
     592                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     593               1 :                   "DTED driver does not support source dataset with zero band.\n");
     594               1 :         return NULL;
     595                 :     }
     596                 :     
     597              31 :     if (nBands != 1)
     598                 :     {
     599                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
     600               4 :                   "DTED driver only uses the first band of the dataset.\n");
     601               4 :         if (bStrict)
     602               4 :             return NULL;
     603                 :     }
     604                 : 
     605              27 :     if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) )
     606               0 :         return NULL;
     607                 : 
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      Work out the level.                                             */
     610                 : /* -------------------------------------------------------------------- */
     611                 :     int nLevel;
     612                 : 
     613              27 :     if( poSrcDS->GetRasterYSize() == 121 )
     614               2 :         nLevel = 0;
     615              25 :     else if( poSrcDS->GetRasterYSize() == 1201 )
     616               3 :         nLevel = 1;
     617              22 :     else if( poSrcDS->GetRasterYSize() == 3601 )
     618               0 :         nLevel = 2;
     619                 :     else
     620                 :     {
     621                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     622              22 :                "The source does not appear to be a properly formatted cell." );
     623              22 :         nLevel = 1;
     624                 :     }
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*      Checks the input SRS                                            */
     628                 : /* -------------------------------------------------------------------- */
     629              27 :     OGRSpatialReference ogrsr_input;
     630              27 :     OGRSpatialReference ogrsr_wgs84;
     631              27 :     char* c = (char*)poSrcDS->GetProjectionRef();
     632              27 :     ogrsr_input.importFromWkt(&c);
     633              27 :     ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" );
     634              27 :     if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE)
     635                 :     {
     636                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     637                 :                   "The source projection coordinate system is %s. Only WGS 84 is supported.\n"
     638                 :                   "The DTED driver will generate a file as if the source was WGS 84 projection coordinate system.",
     639               0 :                   poSrcDS->GetProjectionRef() );
     640                 :     }
     641                 : 
     642                 : /* -------------------------------------------------------------------- */
     643                 : /*      Work out the LL origin.                                         */
     644                 : /* -------------------------------------------------------------------- */
     645                 :     int  nLLOriginLat, nLLOriginLong;
     646                 :     double adfGeoTransform[6];
     647                 : 
     648              27 :     poSrcDS->GetGeoTransform( adfGeoTransform );
     649                 : 
     650                 :     nLLOriginLat = (int) 
     651              27 :         floor(adfGeoTransform[3] 
     652              27 :               + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5);
     653                 :     
     654              27 :     nLLOriginLong = (int) floor(adfGeoTransform[0] + 0.5);
     655                 : 
     656              57 :     if (fabs(nLLOriginLat - (adfGeoTransform[3] 
     657              27 :               + (poSrcDS->GetRasterYSize() - 0.5) * adfGeoTransform[5])) > 1e-10 ||
     658               3 :         fabs(nLLOriginLong - (adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10)
     659                 :     {
     660                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     661                 :                "The corner coordinates of the source are not properly "
     662              24 :                "aligned on plain latitude/longitude boundaries.");
     663                 :     }
     664                 : 
     665                 : /* -------------------------------------------------------------------- */
     666                 : /*     Check horizontal source size.                                    */
     667                 : /* -------------------------------------------------------------------- */
     668                 :     int expectedXSize;
     669              27 :     if( ABS(nLLOriginLat) >= 80 )
     670               0 :         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 6 + 1;
     671              27 :     else if( ABS(nLLOriginLat) >= 75 )
     672               0 :         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 4 + 1;
     673              27 :     else if( ABS(nLLOriginLat) >= 70 )
     674               0 :         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 3 + 1;
     675              27 :     else if( ABS(nLLOriginLat) >= 50 )
     676               1 :         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 2 + 1;
     677                 :     else
     678              26 :         expectedXSize = poSrcDS->GetRasterYSize();
     679                 : 
     680              27 :     if (poSrcDS->GetRasterXSize() != expectedXSize)
     681                 :     {
     682                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     683                 :                "The horizontal source size is not conformant with the one "
     684                 :                "expected by DTED Level %d at this latitude (%d pixels found instead of %d).", nLevel,
     685               0 :                 poSrcDS->GetRasterXSize(), expectedXSize);
     686                 :     }
     687                 : 
     688                 : /* -------------------------------------------------------------------- */
     689                 : /*      Create the output dted file.                                    */
     690                 : /* -------------------------------------------------------------------- */
     691                 :     const char *pszError;
     692                 : 
     693              27 :     pszError = DTEDCreate( pszFilename, nLevel, nLLOriginLat, nLLOriginLong );
     694                 : 
     695              27 :     if( pszError != NULL )
     696                 :     {
     697                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     698              13 :                   "%s", pszError );
     699              13 :         return NULL;
     700                 :     }
     701                 : 
     702                 : /* -------------------------------------------------------------------- */
     703                 : /*      Open the DTED file so we can output the data to it.             */
     704                 : /* -------------------------------------------------------------------- */
     705                 :     DTEDInfo *psDTED;
     706                 : 
     707              14 :     psDTED = DTEDOpen( pszFilename, "rb+", FALSE );
     708              14 :     if( psDTED == NULL )
     709               0 :         return NULL;
     710                 : 
     711                 : /* -------------------------------------------------------------------- */
     712                 : /*      Read all the data in a single buffer.                           */
     713                 : /* -------------------------------------------------------------------- */
     714              14 :     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
     715                 :     GInt16      *panData;
     716                 : 
     717                 :     panData = (GInt16 *) 
     718              14 :         VSIMalloc(sizeof(GInt16) * psDTED->nXSize * psDTED->nYSize);
     719              14 :     if (panData == NULL)
     720                 :     {
     721               0 :         CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
     722               0 :         DTEDClose(psDTED);
     723               0 :         return NULL;
     724                 :     }
     725                 : 
     726           14668 :     for( int iY = 0; iY < psDTED->nYSize; iY++ )
     727                 :     {
     728                 :         poSrcBand->RasterIO( GF_Read, 0, iY, psDTED->nXSize, 1, 
     729                 :                             (void *) (panData + iY * psDTED->nXSize), psDTED->nXSize, 1, 
     730           14654 :                             GDT_Int16, 0, 0 );
     731                 : 
     732           14654 :         if( pfnProgress && !pfnProgress(0.5 * (iY+1) / (double) psDTED->nYSize, NULL, pProgressData ) )
     733                 :         {
     734                 :             CPLError( CE_Failure, CPLE_UserInterrupt, 
     735               0 :                         "User terminated CreateCopy()" );
     736               0 :             DTEDClose( psDTED );
     737               0 :             CPLFree( panData );
     738               0 :             return NULL;
     739                 :         }
     740                 :     }
     741                 : 
     742                 :     int bSrcBandHasNoData;
     743              14 :     double srcBandNoData = poSrcBand->GetNoDataValue(&bSrcBandHasNoData);
     744                 : 
     745                 : /* -------------------------------------------------------------------- */
     746                 : /*      Write all the profiles.                                         */
     747                 : /* -------------------------------------------------------------------- */
     748                 :     GInt16      anProfData[3601];
     749              14 :     int         dfNodataCount=0;
     750                 :     GByte       iPartialCell;
     751                 : 
     752           14068 :     for( int iProfile = 0; iProfile < psDTED->nXSize; iProfile++ )
     753                 :     {
     754        16631548 :         for( int iY = 0; iY < psDTED->nYSize; iY++ )
     755                 :         {
     756        16617494 :             anProfData[iY] = panData[iProfile + iY * psDTED->nXSize];
     757        16617494 :             if ( bSrcBandHasNoData && anProfData[iY] == srcBandNoData)
     758                 :             {
     759               0 :                 anProfData[iY] = DTED_NODATA_VALUE;
     760               0 :                 dfNodataCount++;
     761                 :             }
     762        16617494 :             else if ( anProfData[iY] == DTED_NODATA_VALUE )
     763              11 :                 dfNodataCount++;
     764                 :         }
     765           14054 :         DTEDWriteProfile( psDTED, iProfile, anProfData );
     766                 : 
     767           14054 :         if( pfnProgress
     768                 :             && !pfnProgress( 0.5 + 0.5 * (iProfile+1) / (double) psDTED->nXSize,
     769                 :                              NULL, pProgressData ) )
     770                 :         {
     771                 :             CPLError( CE_Failure, CPLE_UserInterrupt, 
     772               0 :                       "User terminated CreateCopy()" );
     773               0 :             DTEDClose( psDTED );
     774               0 :             CPLFree( panData );
     775               0 :             return NULL;
     776                 :         }
     777                 :     }
     778              14 :     CPLFree( panData );
     779                 : 
     780                 : /* -------------------------------------------------------------------- */
     781                 : /* Partial cell indicator: 0 for complete coverage; 1-99 for incomplete */
     782                 : /* -------------------------------------------------------------------- */
     783                 :     char szPartialCell[3];
     784                 : 
     785              14 :     if ( dfNodataCount == 0 )
     786               3 :         iPartialCell = 0;
     787                 :     else
     788                 :     {
     789                 :       iPartialCell = (GByte)int(floor(100.0 - 
     790              11 :            (dfNodataCount*100.0/(psDTED->nXSize * psDTED->nYSize))));
     791              11 :         if (iPartialCell < 1)
     792               0 :            iPartialCell=1;
     793                 :     }
     794              14 :     sprintf(szPartialCell,"%02d",iPartialCell);
     795              14 :     DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell); 
     796                 : 
     797                 : /* -------------------------------------------------------------------- */
     798                 : /*      Try to copy any matching available metadata.                    */
     799                 : /* -------------------------------------------------------------------- */
     800              14 :     if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) != NULL )
     801                 :         DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL, 
     802               2 :                      poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) );
     803                 : 
     804              14 :     if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) != NULL )
     805                 :         DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC, 
     806               2 :                     poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) );
     807                 : 
     808              14 :     if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) != NULL )
     809                 :         DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL, 
     810               2 :                     poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) );
     811                 : 
     812              14 :     if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) != NULL )
     813                 :         DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI, 
     814               2 :                     poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) );
     815                 : 
     816              14 :     if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) != NULL )
     817                 :         DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL, 
     818               2 :                          poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) );
     819                 : 
     820              14 :     if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) != NULL )
     821                 :         DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI, 
     822               2 :                          poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) );
     823                 : 
     824              14 :     if( poSrcDS->GetMetadataItem( "DTED_DataEdition" ) != NULL )
     825                 :         DTEDSetMetadata( psDTED, DTEDMD_DATA_EDITION, 
     826               2 :                          poSrcDS->GetMetadataItem( "DTED_DataEdition" ) );
     827                 : 
     828              14 :     if( poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) != NULL )
     829                 :         DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION, 
     830               2 :                      poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) );
     831                 : 
     832              14 :     if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) != NULL )
     833                 :         DTEDSetMetadata( psDTED, DTEDMD_MAINT_DATE, 
     834               2 :                          poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) );
     835                 : 
     836              14 :     if( poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) != NULL )
     837                 :         DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE, 
     838               2 :                          poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) );
     839                 : 
     840              14 :     if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) != NULL )
     841                 :         DTEDSetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION, 
     842               2 :                  poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) );
     843                 : 
     844              14 :     if( poSrcDS->GetMetadataItem( "DTED_Producer" ) != NULL )
     845                 :         DTEDSetMetadata( psDTED, DTEDMD_PRODUCER, 
     846               2 :                          poSrcDS->GetMetadataItem( "DTED_Producer" ) );
     847                 : 
     848              14 :     if( poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) != NULL )
     849                 :         DTEDSetMetadata( psDTED, DTEDMD_VERTDATUM, 
     850               2 :                          poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) );
     851                 : 
     852              14 :     if( poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) != NULL )
     853                 :         DTEDSetMetadata( psDTED, DTEDMD_HORIZDATUM, 
     854               2 :                          poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) );
     855                 : 
     856              14 :     if( poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) != NULL )
     857                 :         DTEDSetMetadata( psDTED, DTEDMD_DIGITIZING_SYS, 
     858               2 :                          poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) );
     859                 : 
     860              14 :     if( poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) != NULL )
     861                 :         DTEDSetMetadata( psDTED, DTEDMD_COMPILATION_DATE, 
     862               2 :                          poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) );
     863                 : 
     864              14 :     if( poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) != NULL )
     865                 :         DTEDSetMetadata( psDTED, DTEDMD_HORIZACCURACY, 
     866               2 :                      poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) );
     867                 : 
     868              14 :     if( poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) != NULL )
     869                 :         DTEDSetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY, 
     870               2 :                    poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) );
     871                 : 
     872              14 :     if( poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) != NULL )
     873                 :         DTEDSetMetadata( psDTED, DTEDMD_REL_VERTACCURACY, 
     874               2 :                      poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) );
     875                 : 
     876                 : /* -------------------------------------------------------------------- */
     877                 : /*      Try to open the resulting DTED file.                            */
     878                 : /* -------------------------------------------------------------------- */
     879              14 :     DTEDClose( psDTED );
     880                 : 
     881                 : /* -------------------------------------------------------------------- */
     882                 : /*      Reopen and copy missing information into a PAM file.            */
     883                 : /* -------------------------------------------------------------------- */
     884                 :     GDALPamDataset *poDS = (GDALPamDataset *) 
     885              14 :         GDALOpen( pszFilename, GA_ReadOnly );
     886                 : 
     887              14 :     if( poDS )
     888              14 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
     889                 : 
     890              14 :     return poDS;
     891                 : }
     892                 : 
     893                 : /************************************************************************/
     894                 : /*                         GDALRegister_DTED()                          */
     895                 : /************************************************************************/
     896                 : 
     897             582 : void GDALRegister_DTED()
     898                 : 
     899                 : {
     900                 :     GDALDriver  *poDriver;
     901                 : 
     902             582 :     if( GDALGetDriverByName( "DTED" ) == NULL )
     903                 :     {
     904             561 :         poDriver = new GDALDriver();
     905                 :         
     906             561 :         poDriver->SetDescription( "DTED" );
     907                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     908             561 :                                    "DTED Elevation Raster" );
     909                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     910             561 :                                    "frmt_various.html#DTED" );
     911                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
     912             561 :                                    "Byte Int16 UInt16" );
     913                 : 
     914             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     915                 : 
     916             561 :         poDriver->pfnOpen = DTEDDataset::Open;
     917             561 :         poDriver->pfnIdentify = DTEDDataset::Identify;
     918             561 :         poDriver->pfnCreateCopy = DTEDCreateCopy;
     919                 : 
     920             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     921                 :     }
     922             582 : }
     923                 : 

Generated by: LCOV version 1.7