LCOV - code coverage report
Current view: directory - frmts/raw - btdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 329 245 74.5 %
Date: 2010-01-09 Functions: 20 17 85.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: btdataset.cpp 16706 2009-04-02 03:44:07Z warmerdam $
       3                 :  *
       4                 :  * Project:  VTP .bt Driver
       5                 :  * Purpose:  Implementation of VTP .bt elevation format read/write support.
       6                 :  *           http://www.vterrain.org/Implementation/Formats/BT.html
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2003, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "rawdataset.h"
      32                 : #include "ogr_spatialref.h"
      33                 : 
      34                 : CPL_CVSID("$Id: btdataset.cpp 16706 2009-04-02 03:44:07Z warmerdam $");
      35                 : 
      36                 : CPL_C_START
      37                 : void    GDALRegister_BT(void);
      38                 : CPL_C_END
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                              BTDataset                               */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46                 : class BTDataset : public GDALPamDataset
      47                 : {
      48                 :     friend class BTRasterBand;
      49                 : 
      50                 :     FILE        *fpImage;       // image data file.
      51                 : 
      52                 :     int         bGeoTransformValid;
      53                 :     double      adfGeoTransform[6];
      54                 : 
      55                 :     char        *pszProjection;
      56                 :     
      57                 :     double      dfVScale;
      58                 : 
      59                 :     int         nVersionCode;  // version times 10.
      60                 : 
      61                 :     int         bHeaderModified;
      62                 :     unsigned char abyHeader[256];
      63                 : 
      64                 :     float        m_fVscale;
      65                 : 
      66                 :   public:
      67                 : 
      68                 :                 BTDataset();
      69                 :                 ~BTDataset();
      70                 : 
      71                 :     virtual const char *GetProjectionRef(void);
      72                 :     virtual CPLErr SetProjection( const char * );
      73                 :     virtual CPLErr GetGeoTransform( double * );
      74                 :     virtual CPLErr SetGeoTransform( double * );
      75                 : 
      76                 :     virtual void   FlushCache();
      77                 : 
      78                 :     static GDALDataset *Open( GDALOpenInfo * );
      79                 :     static GDALDataset *Create( const char * pszFilename,
      80                 :                                 int nXSize, int nYSize, int nBands,
      81                 :                                 GDALDataType eType, char ** papszOptions );
      82                 : };
      83                 : 
      84                 : /************************************************************************/
      85                 : /* ==================================================================== */
      86                 : /*                            BTRasterBand                              */
      87                 : /* ==================================================================== */
      88                 : /************************************************************************/
      89                 : 
      90                 : class BTRasterBand : public GDALRasterBand
      91              54 : {
      92                 :     FILE          *fpImage;
      93                 : 
      94                 :   public:
      95                 : 
      96                 :                    BTRasterBand( GDALDataset * poDS, FILE * fp,
      97                 :                                  GDALDataType eType );
      98                 : 
      99                 :     virtual CPLErr IReadBlock( int, int, void * );
     100                 :     virtual CPLErr IWriteBlock( int, int, void * );
     101                 : 
     102                 :     virtual const char* GetUnitType();
     103                 :     virtual CPLErr SetUnitType(const char*);
     104                 :   virtual double GetNoDataValue( int* = NULL );
     105                 : };
     106                 : 
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                           BTRasterBand()                             */
     110                 : /************************************************************************/
     111                 : 
     112              27 : BTRasterBand::BTRasterBand( GDALDataset *poDS, FILE *fp, GDALDataType eType )
     113                 : 
     114                 : {
     115              27 :     this->poDS = poDS;
     116              27 :     this->nBand = 1;
     117              27 :     this->eDataType = eType;
     118              27 :     this->fpImage = fp;
     119                 : 
     120              27 :     nBlockXSize = 1;
     121              27 :     nBlockYSize = poDS->GetRasterYSize();
     122              27 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                             IReadBlock()                             */
     126                 : /************************************************************************/
     127                 : 
     128              80 : CPLErr BTRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     129                 :                                   void * pImage )
     130                 : 
     131                 : {
     132              80 :     int nDataSize = GDALGetDataTypeSize( eDataType ) / 8;
     133                 :     int i;
     134                 : 
     135                 :     CPLAssert( nBlockYOff == 0  );
     136                 : 
     137                 : /* -------------------------------------------------------------------- */
     138                 : /*      Seek to profile.                                                */
     139                 : /* -------------------------------------------------------------------- */
     140              80 :     if( VSIFSeekL( fpImage, 
     141                 :                    256 + nBlockXOff * nDataSize * nRasterYSize, 
     142                 :                    SEEK_SET ) != 0 )
     143                 :     {
     144                 :         CPLError( CE_Failure, CPLE_FileIO, 
     145               0 :                   ".bt Seek failed:%s", VSIStrerror( errno ) );
     146               0 :         return CE_Failure;
     147                 :     }
     148                 : 
     149                 : /* -------------------------------------------------------------------- */
     150                 : /*      Read the profile.                                               */
     151                 : /* -------------------------------------------------------------------- */
     152              80 :     if( VSIFReadL( pImage, nDataSize, nRasterYSize, fpImage ) != 
     153                 :         (size_t) nRasterYSize )
     154                 :     {
     155                 :         CPLError( CE_Failure, CPLE_FileIO, 
     156               0 :                   ".bt Read failed:%s", VSIStrerror( errno ) );
     157               0 :         return CE_Failure;
     158                 :     }
     159                 : 
     160                 : /* -------------------------------------------------------------------- */
     161                 : /*      Swap on MSB platforms.                                          */
     162                 : /* -------------------------------------------------------------------- */
     163                 : #ifdef CPL_MSB 
     164                 :     GDALSwapWords( pImage, nDataSize, nRasterYSize, nDataSize );
     165                 : #endif    
     166                 : 
     167                 : /* -------------------------------------------------------------------- */
     168                 : /*      Vertical flip, since GDAL expects values from top to bottom,    */
     169                 : /*      but in .bt they are bottom to top.                              */
     170                 : /* -------------------------------------------------------------------- */
     171             880 :     for( i = 0; i < nRasterYSize / 2; i++ )
     172                 :     {
     173                 :         GByte abyWrk[8];
     174                 : 
     175             800 :         memcpy( abyWrk, ((GByte *) pImage) + i * nDataSize, nDataSize );
     176                 :         memcpy( ((GByte *) pImage) + i * nDataSize, 
     177                 :                 ((GByte *) pImage) + (nRasterYSize - i - 1) * nDataSize, 
     178             800 :                 nDataSize );
     179                 :         memcpy( ((GByte *) pImage) + (nRasterYSize - i - 1) * nDataSize, 
     180             800 :                 abyWrk, nDataSize );
     181                 :     }
     182                 : 
     183              80 :     return CE_None;
     184                 : }
     185                 : 
     186                 : /************************************************************************/
     187                 : /*                            IWriteBlock()                             */
     188                 : /************************************************************************/
     189                 : 
     190              80 : CPLErr BTRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     191                 :                                   void * pImage )
     192                 : 
     193                 : {
     194              80 :     int nDataSize = GDALGetDataTypeSize( eDataType ) / 8;
     195                 :     GByte *pabyWrkBlock;
     196                 :     int i;
     197                 : 
     198                 :     CPLAssert( nBlockYOff == 0  );
     199                 : 
     200                 : /* -------------------------------------------------------------------- */
     201                 : /*      Seek to profile.                                                */
     202                 : /* -------------------------------------------------------------------- */
     203              80 :     if( VSIFSeekL( fpImage, 
     204                 :                    256 + nBlockXOff * nDataSize * nRasterYSize, 
     205                 :                    SEEK_SET ) != 0 )
     206                 :     {
     207                 :         CPLError( CE_Failure, CPLE_FileIO, 
     208               0 :                   ".bt Seek failed:%s", VSIStrerror( errno ) );
     209               0 :         return CE_Failure;
     210                 :     }
     211                 : 
     212                 : /* -------------------------------------------------------------------- */
     213                 : /*      Allocate working buffer.                                        */
     214                 : /* -------------------------------------------------------------------- */
     215              80 :     pabyWrkBlock = (GByte *) CPLMalloc(nDataSize * nRasterYSize);
     216                 : 
     217                 : /* -------------------------------------------------------------------- */
     218                 : /*      Vertical flip data into work buffer, since GDAL expects         */
     219                 : /*      values from top to bottom, but in .bt they are bottom to        */
     220                 : /*      top.                                                            */
     221                 : /* -------------------------------------------------------------------- */
     222            1680 :     for( i = 0; i < nRasterYSize; i++ )
     223                 :     {
     224                 :         memcpy( pabyWrkBlock + (nRasterYSize - i - 1) * nDataSize, 
     225            1600 :                 ((GByte *) pImage) + i * nDataSize, nDataSize );
     226                 :     }
     227                 : 
     228                 : /* -------------------------------------------------------------------- */
     229                 : /*      Swap on MSB platforms.                                          */
     230                 : /* -------------------------------------------------------------------- */
     231                 : #ifdef CPL_MSB 
     232                 :     GDALSwapWords( pabyWrkBlock, nDataSize, nRasterYSize, nDataSize );
     233                 : #endif    
     234                 : 
     235                 : /* -------------------------------------------------------------------- */
     236                 : /*      Read the profile.                                               */
     237                 : /* -------------------------------------------------------------------- */
     238              80 :     if( VSIFWriteL( pabyWrkBlock, nDataSize, nRasterYSize, fpImage ) != 
     239                 :         (size_t) nRasterYSize )
     240                 :     {
     241               0 :         CPLFree( pabyWrkBlock );
     242                 :         CPLError( CE_Failure, CPLE_FileIO, 
     243               0 :                   ".bt Write failed:%s", VSIStrerror( errno ) );
     244               0 :         return CE_Failure;
     245                 :     }
     246                 : 
     247              80 :     CPLFree( pabyWrkBlock );
     248                 : 
     249              80 :     return CE_None;
     250                 : }
     251                 : 
     252                 : 
     253               8 : double BTRasterBand::GetNoDataValue( int* pbSuccess /*= NULL */ )
     254                 : {
     255               8 :   if(pbSuccess != NULL)
     256               8 :     *pbSuccess = TRUE;
     257                 : 
     258               8 :   return -32768;
     259                 : }
     260                 : 
     261                 : 
     262                 : /************************************************************************/
     263                 : /*                            GetUnitType()                             */
     264                 : /************************************************************************/
     265                 : 
     266               0 : static bool approx_equals(float a, float b)
     267                 : {
     268               0 :     const float epsilon = (float)1e-5;
     269               0 :     return (fabs(a-b) <= epsilon);
     270                 : }
     271                 : 
     272               0 : const char* BTRasterBand::GetUnitType(void)
     273                 : {
     274               0 :     const BTDataset& ds = *(BTDataset*)poDS;
     275               0 :     float f = ds.m_fVscale;
     276               0 :     if(f == 1.0f)
     277               0 :         return "m";
     278               0 :     if(approx_equals(f, 0.3048f))
     279               0 :         return "ft";
     280               0 :     if(approx_equals(f, 1200.0f/3937.0f))
     281               0 :         return "sft";
     282                 : 
     283                 :     // todo: the BT spec allows for any value for
     284                 :     // ds.m_fVscale, so rigorous adherence would
     285                 :     // require testing for all possible units you
     286                 :     // may want to support, such as km, yards, miles, etc.
     287                 :     // But m/ft/sft seem to be the top three.
     288                 : 
     289               0 :     return "";
     290                 : } 
     291                 : 
     292                 : /************************************************************************/
     293                 : /*                            SetUnitType()                             */
     294                 : /************************************************************************/
     295                 : 
     296               0 : CPLErr BTRasterBand::SetUnitType(const char* psz)
     297                 : {
     298               0 :     BTDataset& ds = *(BTDataset*)poDS;
     299               0 :     if(EQUAL(psz, "m"))
     300               0 :         ds.m_fVscale = 1.0f;
     301               0 :     else if(EQUAL(psz, "ft"))
     302               0 :         ds.m_fVscale = 0.3048f;
     303               0 :     else if(EQUAL(psz, "sft"))
     304               0 :         ds.m_fVscale = 1200.0f / 3937.0f;
     305                 :     else
     306               0 :         return CE_Failure;
     307                 : 
     308                 : 
     309               0 :     float fScale = ds.m_fVscale;
     310                 : 
     311                 :     CPL_LSBPTR32(&fScale);
     312                 : 
     313                 :     // Update header's elevation scale field.
     314               0 :     memcpy(ds.abyHeader + 62, &fScale, sizeof(fScale));
     315                 : 
     316               0 :     ds.bHeaderModified = TRUE;
     317               0 :     return CE_None;
     318                 : } 
     319                 : 
     320                 : /************************************************************************/
     321                 : /* ==================================================================== */
     322                 : /*                              BTDataset                               */
     323                 : /* ==================================================================== */
     324                 : /************************************************************************/
     325                 : 
     326                 : /************************************************************************/
     327                 : /*                             BTDataset()                              */
     328                 : /************************************************************************/
     329                 : 
     330              27 : BTDataset::BTDataset()
     331                 : {
     332              27 :     fpImage = NULL;
     333              27 :     bGeoTransformValid = FALSE;
     334              27 :     adfGeoTransform[0] = 0.0;
     335              27 :     adfGeoTransform[1] = 1.0;
     336              27 :     adfGeoTransform[2] = 0.0;
     337              27 :     adfGeoTransform[3] = 0.0;
     338              27 :     adfGeoTransform[4] = 0.0;
     339              27 :     adfGeoTransform[5] = 1.0;
     340              27 :     pszProjection = NULL;
     341                 : 
     342              27 :     bHeaderModified = FALSE;
     343              27 : }
     344                 : 
     345                 : /************************************************************************/
     346                 : /*                             ~BTDataset()                             */
     347                 : /************************************************************************/
     348                 : 
     349              54 : BTDataset::~BTDataset()
     350                 : 
     351                 : {
     352              27 :     FlushCache();
     353              27 :     if( fpImage != NULL )
     354              27 :         VSIFCloseL( fpImage );
     355              27 :     CPLFree( pszProjection );
     356              54 : }
     357                 : 
     358                 : /************************************************************************/
     359                 : /*                             FlushCache()                             */
     360                 : /*                                                                      */
     361                 : /*      We override this to include flush out the header block.         */
     362                 : /************************************************************************/
     363                 : 
     364              27 : void BTDataset::FlushCache()
     365                 : 
     366                 : {
     367              27 :     GDALDataset::FlushCache();
     368                 : 
     369              27 :     if( !bHeaderModified )
     370              19 :         return;
     371                 : 
     372               8 :     bHeaderModified = FALSE;
     373                 : 
     374               8 :     VSIFSeekL( fpImage, 0, SEEK_SET );
     375               8 :     VSIFWriteL( abyHeader, 256, 1, fpImage );
     376                 : }
     377                 : 
     378                 : /************************************************************************/
     379                 : /*                          GetGeoTransform()                           */
     380                 : /************************************************************************/
     381                 : 
     382               4 : CPLErr BTDataset::GetGeoTransform( double * padfTransform )
     383                 : 
     384                 : {
     385               4 :     memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
     386                 : 
     387               4 :     if( bGeoTransformValid )
     388               4 :         return CE_None;
     389                 :     else
     390               0 :         return CE_Failure;
     391                 : }
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                          SetGeoTransform()                           */
     395                 : /************************************************************************/
     396                 : 
     397               8 : CPLErr BTDataset::SetGeoTransform( double *padfTransform )
     398                 : 
     399                 : {
     400               8 :     CPLErr eErr = CE_None;
     401                 : 
     402               8 :     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
     403               8 :     if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
     404                 :     {
     405                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     406               0 :                   ".bt format does not support rotational coefficients in geotransform, ignoring." );
     407               0 :         eErr = CE_Failure;
     408                 :     }
     409                 : 
     410                 : /* -------------------------------------------------------------------- */
     411                 : /*      Compute bounds, and update header info.                         */
     412                 : /* -------------------------------------------------------------------- */
     413                 :     double dfLeft, dfRight, dfTop, dfBottom;
     414                 : 
     415               8 :     dfLeft = adfGeoTransform[0];
     416               8 :     dfRight = dfLeft + adfGeoTransform[1] * nRasterXSize;
     417               8 :     dfTop = adfGeoTransform[3];
     418               8 :     dfBottom = dfTop + adfGeoTransform[5] * nRasterYSize;
     419                 : 
     420               8 :     memcpy( abyHeader + 28, &dfLeft, 8 );
     421               8 :     memcpy( abyHeader + 36, &dfRight, 8 );
     422               8 :     memcpy( abyHeader + 44, &dfBottom, 8 );
     423               8 :     memcpy( abyHeader + 52, &dfTop, 8 );
     424                 : 
     425                 :     CPL_LSBPTR64( abyHeader + 28 );
     426                 :     CPL_LSBPTR64( abyHeader + 36 );
     427                 :     CPL_LSBPTR64( abyHeader + 44 );
     428                 :     CPL_LSBPTR64( abyHeader + 52 );
     429                 :     
     430               8 :     bHeaderModified = TRUE;
     431                 : 
     432               8 :     return eErr;
     433                 : }
     434                 : 
     435                 : /************************************************************************/
     436                 : /*                          GetProjectionRef()                          */
     437                 : /************************************************************************/
     438                 : 
     439               4 : const char *BTDataset::GetProjectionRef()
     440                 : 
     441                 : {
     442               4 :     if( pszProjection == NULL )
     443               0 :         return "";
     444                 :     else
     445               4 :         return pszProjection;
     446                 : }
     447                 : 
     448                 : /************************************************************************/
     449                 : /*                           SetProjection()                            */
     450                 : /************************************************************************/
     451                 : 
     452               7 : CPLErr BTDataset::SetProjection( const char *pszNewProjection )
     453                 : 
     454                 : {
     455               7 :     CPLErr eErr = CE_None;
     456                 : 
     457               7 :     CPLFree( pszProjection );
     458               7 :     pszProjection = CPLStrdup( pszNewProjection );
     459                 : 
     460               7 :     bHeaderModified = TRUE;
     461                 : 
     462                 : /* -------------------------------------------------------------------- */
     463                 : /*      Parse projection.                                               */
     464                 : /* -------------------------------------------------------------------- */
     465               7 :     OGRSpatialReference oSRS( pszProjection );
     466                 :     GInt16  nShortTemp;
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      Linear units.                                                   */
     470                 : /* -------------------------------------------------------------------- */
     471               7 :     if( oSRS.IsGeographic() )
     472               3 :         nShortTemp = 0;
     473                 :     else 
     474                 :     {
     475               4 :         double dfLinear = oSRS.GetLinearUnits();
     476                 : 
     477               4 :         if( ABS(dfLinear - 0.3048) < 0.0000001 )
     478               0 :             nShortTemp = 2;
     479               4 :         else if( ABS(dfLinear - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
     480               1 :             nShortTemp = 3;
     481                 :         else
     482               3 :             nShortTemp = 1;
     483                 :     }
     484                 : 
     485               7 :     nShortTemp = CPL_LSBWORD16( 1 );
     486               7 :     memcpy( abyHeader + 22, &nShortTemp, 2 );
     487                 :     
     488                 : /* -------------------------------------------------------------------- */
     489                 : /*      UTM Zone                                                        */
     490                 : /* -------------------------------------------------------------------- */
     491                 :     int bNorth;
     492                 : 
     493               7 :     nShortTemp = oSRS.GetUTMZone( &bNorth );
     494               7 :     if( bNorth )
     495               4 :         nShortTemp = -nShortTemp;
     496                 : 
     497               7 :     nShortTemp = CPL_LSBWORD16( nShortTemp );
     498               7 :     memcpy( abyHeader + 24, &nShortTemp, 2 );
     499                 :     
     500                 : /* -------------------------------------------------------------------- */
     501                 : /*      Datum                                                           */
     502                 : /* -------------------------------------------------------------------- */
     503               7 :     if( oSRS.GetAuthorityName( "GEOGCS|DATUM" ) != NULL
     504                 :         && EQUAL(oSRS.GetAuthorityName( "GEOGCS|DATUM" ),"EPSG") )
     505               7 :         nShortTemp = atoi(oSRS.GetAuthorityName( "GEOGCS|DATUM" )) + 2000;
     506                 :     else
     507               0 :         nShortTemp = -2;
     508               7 :     nShortTemp = CPL_LSBWORD16( nShortTemp ); /* datum unknown */
     509               7 :     memcpy( abyHeader + 26, &nShortTemp, 2 );
     510                 : 
     511                 : /* -------------------------------------------------------------------- */
     512                 : /*      Write out the projection to a .prj file.                        */
     513                 : /* -------------------------------------------------------------------- */
     514               7 :     const char  *pszPrjFile = CPLResetExtension( GetDescription(), "prj" );
     515                 :     FILE * fp;
     516                 : 
     517               7 :     fp = VSIFOpenL( pszPrjFile, "wt" );
     518               7 :     if( fp != NULL )
     519                 :     {
     520               7 :         VSIFPrintfL( fp, "%s\n", pszProjection );
     521               7 :         VSIFCloseL( fp );
     522               7 :         abyHeader[60] = 1;
     523                 :     }
     524                 :     else
     525                 :     {
     526                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     527               0 :                   "Unable to write out .prj file." );
     528               0 :         eErr = CE_Failure;
     529                 :     }
     530                 : 
     531               7 :     return eErr;
     532                 : }
     533                 : 
     534                 : 
     535                 : /************************************************************************/
     536                 : /*                                Open()                                */
     537                 : /************************************************************************/
     538                 : 
     539            8550 : GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
     540                 : 
     541                 : {
     542                 : /* -------------------------------------------------------------------- */
     543                 : /*      Verify that this is some form of binterr file.                  */
     544                 : /* -------------------------------------------------------------------- */
     545            8550 :     if( poOpenInfo->nHeaderBytes < 256)
     546            8320 :         return NULL;
     547                 : 
     548             230 :     if( strncmp( (const char *) poOpenInfo->pabyHeader, "binterr", 7 ) != 0 )
     549             203 :         return NULL;
     550                 : 
     551                 : /* -------------------------------------------------------------------- */
     552                 : /*      Create the dataset.                                             */
     553                 : /* -------------------------------------------------------------------- */
     554                 :     BTDataset  *poDS;
     555                 : 
     556              27 :     poDS = new BTDataset();
     557                 :  
     558              27 :     memcpy( poDS->abyHeader, poOpenInfo->pabyHeader, 256 );
     559                 : 
     560                 : /* -------------------------------------------------------------------- */
     561                 : /*      Get the version.                                                */
     562                 : /* -------------------------------------------------------------------- */
     563                 :     char szVersion[4];
     564                 : 
     565              27 :     strncpy( szVersion, (char *) (poDS->abyHeader + 7), 3 );
     566              27 :     szVersion[3] = '\0';
     567              27 :     poDS->nVersionCode = (int) (atof(szVersion) * 10);
     568                 : 
     569                 : /* -------------------------------------------------------------------- */
     570                 : /*      Extract core header information, being careful about the        */
     571                 : /*      version.                                                        */
     572                 : /* -------------------------------------------------------------------- */
     573                 :     GInt32 nIntTemp;
     574                 :     GInt16 nDataSize;
     575                 :     GDALDataType eType;
     576                 : 
     577              27 :     memcpy( &nIntTemp, poDS->abyHeader + 10, 4 );
     578              27 :     poDS->nRasterXSize = CPL_LSBWORD32( nIntTemp );
     579                 :     
     580              27 :     memcpy( &nIntTemp, poDS->abyHeader + 14, 4 );
     581              27 :     poDS->nRasterYSize = CPL_LSBWORD32( nIntTemp );
     582                 : 
     583              27 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     584                 :     {
     585               0 :         delete poDS;
     586               0 :         return NULL;
     587                 :     }
     588                 : 
     589              27 :     memcpy( &nDataSize, poDS->abyHeader+18, 2 );
     590              27 :     nDataSize = CPL_LSBWORD16( nDataSize );
     591                 : 
     592              42 :     if( poDS->abyHeader[20] != 0 && nDataSize == 4 )
     593              15 :         eType = GDT_Float32;
     594              18 :     else if( poDS->abyHeader[20] == 0 && nDataSize == 4 )
     595               6 :         eType = GDT_Int32;
     596              12 :     else if( poDS->abyHeader[20] == 0 && nDataSize == 2 )
     597               6 :         eType = GDT_Int16;
     598                 :     else
     599                 :     {
     600                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     601                 :                   ".bt file data type unknown, got datasize=%d.", 
     602               0 :                   nDataSize );
     603               0 :         delete poDS;
     604               0 :         return NULL;
     605                 :     }
     606                 : 
     607                 :     /*
     608                 :         rcg, apr 7/06: read offset 62 for vert. units.
     609                 :         If zero, assume 1.0 as per spec.
     610                 : 
     611                 :     */
     612              27 :     memcpy( &poDS->m_fVscale, poDS->abyHeader + 62, 4 );
     613                 :     CPL_LSBPTR32(&poDS->m_fVscale);
     614              27 :     if(poDS->m_fVscale == 0.0f)
     615               0 :         poDS->m_fVscale = 1.0f; 
     616                 : 
     617                 : /* -------------------------------------------------------------------- */
     618                 : /*      Try to read a .prj file if it is indicated.                     */
     619                 : /* -------------------------------------------------------------------- */
     620              27 :     OGRSpatialReference oSRS;           
     621                 : 
     622              27 :     if( poDS->nVersionCode >= 12 && poDS->abyHeader[60] != 0 )
     623                 :     {
     624                 :         const char  *pszPrjFile = CPLResetExtension( poOpenInfo->pszFilename, 
     625              11 :                                                      "prj" );
     626                 :         FILE *fp;
     627                 : 
     628              11 :         fp = VSIFOpenL( pszPrjFile, "rt" );
     629              11 :         if( fp != NULL )
     630                 :         {
     631                 :             char *pszBuffer, *pszBufPtr;
     632              11 :             int  nBufMax = 100000;
     633                 :             int nBytes;
     634                 : 
     635              11 :             pszBuffer = (char *) CPLMalloc(nBufMax);
     636              11 :             nBytes = VSIFReadL( pszBuffer, 1, nBufMax-1, fp );
     637              11 :             VSIFCloseL( fp );
     638                 : 
     639              11 :             pszBuffer[nBytes] = '\0';
     640                 : 
     641              11 :             pszBufPtr = pszBuffer;
     642              11 :             if( oSRS.importFromWkt( &pszBufPtr ) != OGRERR_NONE )
     643                 :             {
     644                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
     645               0 :                           "Unable to parse .prj file, coordinate system missing." );
     646                 :             }
     647              11 :             CPLFree( pszBuffer );
     648                 :         }
     649                 :     }
     650                 : 
     651                 : /* -------------------------------------------------------------------- */
     652                 : /*      If we didn't find a .prj file, try to use internal info.        */
     653                 : /* -------------------------------------------------------------------- */
     654              27 :     if( oSRS.GetRoot() == NULL )
     655                 :     {
     656                 :         GInt16 nUTMZone, nDatum, nHUnits;
     657                 :         
     658              16 :         memcpy( &nUTMZone, poDS->abyHeader + 24, 2 );
     659              16 :         nUTMZone = CPL_LSBWORD16( nUTMZone );
     660                 :         
     661              16 :         memcpy( &nDatum, poDS->abyHeader + 26, 2 );
     662              16 :         nDatum = CPL_LSBWORD16( nDatum );
     663                 :         
     664              16 :         memcpy( &nHUnits, poDS->abyHeader + 22, 2 );
     665              16 :         nHUnits = CPL_LSBWORD16( nHUnits );
     666                 : 
     667              16 :         if( nUTMZone != 0 )
     668               0 :             oSRS.SetUTM( ABS(nUTMZone), nUTMZone > 0 );
     669              16 :         else if( nHUnits != 0 )
     670              16 :             oSRS.SetLocalCS( "Unknown" );
     671                 :         
     672              16 :         if( nHUnits == 1 )
     673              16 :             oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
     674               0 :         else if( nHUnits == 2 )
     675               0 :             oSRS.SetLinearUnits( SRS_UL_FOOT, atof(SRS_UL_FOOT_CONV) );
     676               0 :         else if( nHUnits == 3 )
     677               0 :             oSRS.SetLinearUnits( SRS_UL_US_FOOT, atof(SRS_UL_US_FOOT_CONV) );
     678                 : 
     679                 :         // Translate some of the more obvious old USGS datum codes 
     680              16 :         if( nDatum == 0 )
     681               0 :             nDatum = 6201;
     682              16 :         else if( nDatum == 1 )
     683               0 :             nDatum = 6209;
     684              16 :         else if( nDatum == 2 )
     685               0 :             nDatum = 6210;
     686              16 :         else if( nDatum == 3 )
     687               0 :             nDatum = 6202;
     688              16 :         else if( nDatum == 4 )
     689               0 :             nDatum = 6203;
     690              16 :         else if( nDatum == 4 )
     691               0 :             nDatum = 6203;
     692              16 :         else if( nDatum == 6 )
     693               0 :             nDatum = 6222;
     694              16 :         else if( nDatum == 7 )
     695               0 :             nDatum = 6230;
     696              16 :         else if( nDatum == 13 )
     697               0 :             nDatum = 6267;
     698              16 :         else if( nDatum == 14 )
     699               0 :             nDatum = 6269;
     700              16 :         else if( nDatum == 17 )
     701               0 :             nDatum = 6277;
     702              16 :         else if( nDatum == 19 )
     703               0 :             nDatum = 6284;
     704              16 :         else if( nDatum == 21 )
     705               0 :             nDatum = 6301;
     706              16 :         else if( nDatum == 22 )
     707               0 :             nDatum = 6322;
     708              16 :         else if( nDatum == 23 )
     709               0 :             nDatum = 6326;
     710                 : 
     711              16 :         if( !oSRS.IsLocal() )
     712                 :         {
     713               0 :             if( nDatum >= 6000 )
     714                 :             {
     715                 :                 char szName[32];
     716               0 :                 sprintf( szName, "EPSG:%d", nDatum-2000 );
     717               0 :                 oSRS.SetWellKnownGeogCS( szName );
     718                 :             }
     719                 :             else
     720               0 :                 oSRS.SetWellKnownGeogCS( "WGS84" );
     721                 :         }                
     722                 :     }
     723                 : 
     724                 : /* -------------------------------------------------------------------- */
     725                 : /*      Convert coordinate system back to WKT.                          */
     726                 : /* -------------------------------------------------------------------- */
     727              27 :     if( oSRS.GetRoot() != NULL )
     728              27 :         oSRS.exportToWkt( &poDS->pszProjection );
     729                 : 
     730                 : /* -------------------------------------------------------------------- */
     731                 : /*      Get georeferencing bounds.                                      */
     732                 : /* -------------------------------------------------------------------- */
     733              27 :     if( poDS->nVersionCode >= 11 )
     734                 :     {
     735                 :         double dfLeft, dfRight, dfTop, dfBottom;
     736                 : 
     737              27 :         memcpy( &dfLeft, poDS->abyHeader + 28, 8 );
     738                 :         CPL_LSBPTR64( &dfLeft );
     739                 :         
     740              27 :         memcpy( &dfRight, poDS->abyHeader + 36, 8 );
     741                 :         CPL_LSBPTR64( &dfRight );
     742                 :         
     743              27 :         memcpy( &dfBottom, poDS->abyHeader + 44, 8 );
     744                 :         CPL_LSBPTR64( &dfBottom );
     745                 :         
     746              27 :         memcpy( &dfTop, poDS->abyHeader + 52, 8 );
     747                 :         CPL_LSBPTR64( &dfTop );
     748                 : 
     749              27 :         poDS->adfGeoTransform[0] = dfLeft;
     750              27 :         poDS->adfGeoTransform[1] = (dfRight - dfLeft) / poDS->nRasterXSize;
     751              27 :         poDS->adfGeoTransform[2] = 0.0;
     752              27 :         poDS->adfGeoTransform[3] = dfTop;
     753              27 :         poDS->adfGeoTransform[4] = 0.0;
     754              27 :         poDS->adfGeoTransform[5] = (dfBottom - dfTop) / poDS->nRasterYSize;
     755                 :         
     756              27 :         poDS->bGeoTransformValid = TRUE;
     757                 :     }
     758                 :     
     759                 : /* -------------------------------------------------------------------- */
     760                 : /*      Re-open the file with the desired access.                       */
     761                 : /* -------------------------------------------------------------------- */
     762                 : 
     763              27 :     if( poOpenInfo->eAccess == GA_Update )
     764              12 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
     765                 :     else
     766              15 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     767                 : 
     768              27 :     if( poDS->fpImage == NULL )
     769                 :     {
     770                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     771                 :                   "Failed to re-open %s within BT driver.\n",
     772               0 :                   poOpenInfo->pszFilename );
     773               0 :         return NULL;
     774                 :     }
     775              27 :     poDS->eAccess = poOpenInfo->eAccess;
     776                 : 
     777                 : /* -------------------------------------------------------------------- */
     778                 : /*      Create band information objects                                 */
     779                 : /* -------------------------------------------------------------------- */
     780              27 :     poDS->SetBand( 1, new BTRasterBand( poDS, poDS->fpImage, eType ) );
     781                 : 
     782                 : #ifdef notdef
     783                 :     poDS->bGeoTransformValid = 
     784                 :         GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
     785                 :                            poDS->adfGeoTransform );
     786                 : #endif
     787                 : 
     788                 : /* -------------------------------------------------------------------- */
     789                 : /*      Initialize any PAM information.                                 */
     790                 : /* -------------------------------------------------------------------- */
     791              27 :     poDS->SetDescription( poOpenInfo->pszFilename );
     792              27 :     poDS->TryLoadXML();
     793                 : 
     794                 : /* -------------------------------------------------------------------- */
     795                 : /*      Check for overviews.                                            */
     796                 : /* -------------------------------------------------------------------- */
     797              27 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     798                 : 
     799              27 :     return( poDS );
     800                 : }
     801                 : 
     802                 : /************************************************************************/
     803                 : /*                               Create()                               */
     804                 : /************************************************************************/
     805                 : 
     806              37 : GDALDataset *BTDataset::Create( const char * pszFilename,
     807                 :                                  int nXSize, int nYSize, int nBands,
     808                 :                                  GDALDataType eType,
     809                 :                                  char ** papszOptions )
     810                 : 
     811                 : {
     812                 : 
     813                 : /* -------------------------------------------------------------------- */
     814                 : /*      Verify input options.                                           */
     815                 : /* -------------------------------------------------------------------- */
     816              37 :     if( eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_Float32 )
     817                 :     {
     818                 :         CPLError( CE_Failure, CPLE_AppDefined,
     819                 :               "Attempt to create .bt dataset with an illegal\n"
     820                 :               "data type (%s), only Int16, Int32 and Float32 supported.\n",
     821              25 :               GDALGetDataTypeName(eType) );
     822                 : 
     823              25 :         return NULL;
     824                 :     }
     825                 : 
     826              12 :     if( nBands != 1 )
     827                 :     {
     828                 :         CPLError( CE_Failure, CPLE_AppDefined,
     829                 :                "Attempt to create .bt dataset with %d bands, only 1 supported",
     830               0 :                   nBands );
     831                 : 
     832               0 :         return NULL;
     833                 :     }
     834                 : 
     835                 : /* -------------------------------------------------------------------- */
     836                 : /*      Try to create the file.                                         */
     837                 : /* -------------------------------------------------------------------- */
     838                 :     FILE        *fp;
     839                 : 
     840              12 :     fp = VSIFOpenL( pszFilename, "wb" );
     841                 : 
     842              12 :     if( fp == NULL )
     843                 :     {
     844                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     845                 :                   "Attempt to create file `%s' failed.\n",
     846               0 :                   pszFilename );
     847               0 :         return NULL;
     848                 :     }
     849                 : 
     850                 : /* -------------------------------------------------------------------- */
     851                 : /*      Setup base header.                                              */
     852                 : /* -------------------------------------------------------------------- */
     853                 :     unsigned char abyHeader[256];
     854                 :     GInt32 nTemp;
     855                 :     GInt16 nShortTemp;
     856                 : 
     857              12 :     memset( abyHeader, 0, 256 );
     858              12 :     memcpy( abyHeader, "binterr1.3", 10 );
     859                 :     
     860              12 :     nTemp = CPL_LSBWORD32( nXSize );
     861              12 :     memcpy( abyHeader+10, &nTemp, 4 );
     862                 :     
     863              12 :     nTemp = CPL_LSBWORD32( nYSize );
     864              12 :     memcpy( abyHeader+14, &nTemp, 4 );
     865                 : 
     866              12 :     nShortTemp = CPL_LSBWORD16( GDALGetDataTypeSize( eType ) / 8 );
     867              12 :     memcpy( abyHeader + 18, &nShortTemp, 2 );
     868                 :     
     869              12 :     if( eType == GDT_Float32 )
     870               6 :         abyHeader[20] = 1;
     871                 :     else
     872               6 :         abyHeader[20] = 0;
     873                 :     
     874              12 :     nShortTemp = CPL_LSBWORD16( 1 ); /* meters */
     875              12 :     memcpy( abyHeader + 22, &nShortTemp, 2 );
     876                 :     
     877              12 :     nShortTemp = CPL_LSBWORD16( 0 ); /* not utm */
     878              12 :     memcpy( abyHeader + 24, &nShortTemp, 2 );
     879                 :     
     880              12 :     nShortTemp = CPL_LSBWORD16( -2 ); /* datum unknown */
     881              12 :     memcpy( abyHeader + 26, &nShortTemp, 2 );
     882                 :     
     883                 : /* -------------------------------------------------------------------- */
     884                 : /*      Set dummy extents.                                              */
     885                 : /* -------------------------------------------------------------------- */
     886              12 :     double dfLeft=0, dfRight=nXSize, dfTop=nYSize, dfBottom=0;
     887                 : 
     888              12 :     memcpy( abyHeader + 28, &dfLeft, 8 );
     889              12 :     memcpy( abyHeader + 36, &dfRight, 8 );
     890              12 :     memcpy( abyHeader + 44, &dfBottom, 8 );
     891              12 :     memcpy( abyHeader + 52, &dfTop, 8 );
     892                 : 
     893                 :     CPL_LSBPTR64( abyHeader + 28 );
     894                 :     CPL_LSBPTR64( abyHeader + 36 );
     895                 :     CPL_LSBPTR64( abyHeader + 44 );
     896                 :     CPL_LSBPTR64( abyHeader + 52 );
     897                 :     
     898                 : /* -------------------------------------------------------------------- */
     899                 : /*      Set dummy scale.                                                */
     900                 : /* -------------------------------------------------------------------- */
     901              12 :     float fScale = 1.0;
     902                 : 
     903              12 :     memcpy( abyHeader + 62, &fScale, 4 );
     904                 :     CPL_LSBPTR32( abyHeader + 62 );
     905                 :     
     906                 : /* -------------------------------------------------------------------- */
     907                 : /*      Write to disk.                                                  */
     908                 : /* -------------------------------------------------------------------- */
     909              12 :     VSIFWriteL( (void *) abyHeader, 256, 1, fp );
     910              12 :     if( VSIFSeekL( fp, (GDALGetDataTypeSize(eType)/8) * nXSize * nYSize - 1, 
     911                 :                    SEEK_CUR ) != 0 
     912                 :         || VSIFWriteL( abyHeader+255, 1, 1, fp ) != 1 )
     913                 :     {
     914                 :         CPLError( CE_Failure, CPLE_FileIO, 
     915                 :                   "Failed to extent file to its full size, out of disk space?"
     916               0 :                   );
     917                 : 
     918               0 :         VSIFCloseL( fp );
     919               0 :         VSIUnlink( pszFilename );
     920               0 :         return NULL;
     921                 :     }
     922                 : 
     923              12 :     VSIFCloseL( fp );
     924                 : 
     925              12 :     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     926                 : }
     927                 : 
     928                 : /************************************************************************/
     929                 : /*                          GDALRegister_BT()                           */
     930                 : /************************************************************************/
     931                 : 
     932             338 : void GDALRegister_BT()
     933                 : 
     934                 : {
     935                 :     GDALDriver  *poDriver;
     936                 : 
     937             338 :     if( GDALGetDriverByName( "BT" ) == NULL )
     938                 :     {
     939             336 :         poDriver = new GDALDriver();
     940                 : 
     941             336 :         poDriver->SetDescription( "BT" );
     942                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
     943             336 :                                    "VTP .bt (Binary Terrain) 1.3 Format" );
     944                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
     945             336 :                                    "frmt_various.html#BT" );
     946             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bt" );
     947                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
     948             336 :                                    "Int16 Int32 Float32" );
     949             336 :         poDriver->pfnOpen = BTDataset::Open;
     950             336 :         poDriver->pfnCreate = BTDataset::Create;
     951                 : 
     952             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     953                 :     }
     954             338 : }

Generated by: LCOV version 1.7