LCOV - code coverage report
Current view: directory - frmts/elas - elasdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 210 189 90.0 %
Date: 2011-12-18 Functions: 18 13 72.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $
       3                 :  *
       4                 :  * Project:  ELAS Translator
       5                 :  * Purpose:  Complete implementation of ELAS translator module for GDAL.
       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 "gdal_pam.h"
      31                 : 
      32                 : CPL_CVSID("$Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $");
      33                 : 
      34                 : CPL_C_START
      35                 : void  GDALRegister_ELAS(void);
      36                 : CPL_C_END
      37                 : 
      38                 : typedef struct {
      39                 :     GInt32  NBIH; /* bytes in header, normaly 1024 */
      40                 :     GInt32      NBPR; /* bytes per data record (all bands of scanline) */
      41                 :     GInt32  IL; /* initial line - normally 1 */
      42                 :     GInt32  LL; /* last line */
      43                 :     GInt32  IE; /* initial element (pixel), normally 1 */
      44                 :     GInt32  LE; /* last element (pixel) */
      45                 :     GInt32  NC; /* number of channels (bands) */
      46                 :     GInt32  H4321;  /* header record identifier - always 4321. */
      47                 :     char  YLabel[4]; /* Should be "NOR" for UTM */
      48                 :     GInt32      YOffset;/* topleft pixel center northing */
      49                 :     char  XLabel[4]; /* Should be "EAS" for UTM */
      50                 :     GInt32      XOffset;/* topleft pixel center easting */
      51                 :     float YPixSize;/* height of pixel in georef units */
      52                 :     float XPixSize;/* width of pixel in georef units */
      53                 :     float Matrix[4]; /* 2x2 transformation matrix.  Should be
      54                 :                               1,0,0,1 for pixel/line, or
      55                 :                               1,0,0,-1 for UTM */
      56                 :     GByte IH19[4];/* data type, and size flags */
      57                 :     GInt32  IH20; /* number of secondary headers */
      58                 :     char  unused1[8];
      59                 :     GInt32  LABL; /* used by LABL module */
      60                 :     char  HEAD; /* used by HEAD module */
      61                 :     char  Comment1[64];
      62                 :     char  Comment2[64];
      63                 :     char  Comment3[64];
      64                 :     char  Comment4[64];
      65                 :     char  Comment5[64];
      66                 :     char  Comment6[64];
      67                 :     GUInt16 ColorTable[256];  /* RGB packed with 4 bits each */
      68                 :     char  unused2[32];
      69                 : } ELASHeader;
      70                 : 
      71                 : 
      72                 : /************************************************************************/
      73                 : /* ==================================================================== */
      74                 : /*        ELASDataset       */
      75                 : /* ==================================================================== */
      76                 : /************************************************************************/
      77                 : 
      78                 : class ELASRasterBand;
      79                 : 
      80                 : class ELASDataset : public GDALPamDataset
      81                 : {
      82                 :     friend class ELASRasterBand;
      83                 : 
      84                 :     VSILFILE  *fp;
      85                 : 
      86                 :     ELASHeader  sHeader;
      87                 :     int   bHeaderModified;
      88                 : 
      89                 :     GDALDataType eRasterDataType;
      90                 : 
      91                 :     int   nLineOffset;
      92                 :     int   nBandOffset;     // within a line.
      93                 :     
      94                 :     double  adfGeoTransform[6];
      95                 : 
      96                 :   public:
      97                 :                  ELASDataset();
      98                 :                  ~ELASDataset();
      99                 : 
     100                 :     virtual CPLErr GetGeoTransform( double * );
     101                 :     virtual CPLErr SetGeoTransform( double * );
     102                 : 
     103                 :     static GDALDataset *Open( GDALOpenInfo * );
     104                 :     static int          Identify( GDALOpenInfo * );
     105                 :     static GDALDataset *Create( const char * pszFilename,
     106                 :                                 int nXSize, int nYSize, int nBands,
     107                 :                                 GDALDataType eType, char ** papszParmList );
     108                 : 
     109                 :     virtual void FlushCache( void );
     110                 : };
     111                 : 
     112                 : /************************************************************************/
     113                 : /* ==================================================================== */
     114                 : /*                            ELASRasterBand                             */
     115                 : /* ==================================================================== */
     116                 : /************************************************************************/
     117                 : 
     118                 : class ELASRasterBand : public GDALPamRasterBand
     119              68 : {
     120                 :     friend class ELASDataset;
     121                 : 
     122                 :   public:
     123                 : 
     124                 :                    ELASRasterBand( ELASDataset *, int );
     125                 : 
     126                 :     // should override RasterIO eventually.
     127                 :     
     128                 :     virtual CPLErr IReadBlock( int, int, void * );
     129                 :     virtual CPLErr IWriteBlock( int, int, void * ); 
     130                 : };
     131                 : 
     132                 : 
     133                 : /************************************************************************/
     134                 : /*                           ELASRasterBand()                            */
     135                 : /************************************************************************/
     136                 : 
     137              68 : ELASRasterBand::ELASRasterBand( ELASDataset *poDS, int nBand )
     138                 : 
     139                 : {
     140              68 :     this->poDS = poDS;
     141              68 :     this->nBand = nBand;
     142                 : 
     143              68 :     this->eAccess = poDS->eAccess;
     144                 : 
     145              68 :     eDataType = poDS->eRasterDataType;
     146                 : 
     147              68 :     nBlockXSize = poDS->GetRasterXSize();
     148              68 :     nBlockYSize = 1;
     149              68 : }
     150                 : 
     151                 : /************************************************************************/
     152                 : /*                             IReadBlock()                             */
     153                 : /************************************************************************/
     154                 : 
     155              60 : CPLErr ELASRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     156                 :                                    void * pImage )
     157                 : 
     158                 : {
     159              60 :     ELASDataset *poGDS = (ELASDataset *) poDS;
     160              60 :     CPLErr    eErr = CE_None;
     161                 :     long    nOffset;
     162                 :     int     nDataSize;
     163                 : 
     164              60 :     CPLAssert( nBlockXOff == 0 );
     165                 : 
     166              60 :     nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
     167              60 :     nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
     168                 :     
     169                 : /* -------------------------------------------------------------------- */
     170                 : /*      If we can't seek to the data, we will assume this is a newly    */
     171                 : /*      created file, and that the file hasn't been extended yet.       */
     172                 : /*      Just read as zeros.                                             */
     173                 : /* -------------------------------------------------------------------- */
     174              60 :     if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
     175                 :         || VSIFReadL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
     176                 :     {
     177                 :         CPLError( CE_Failure, CPLE_FileIO,
     178                 :                   "Seek or read of %d bytes at %ld failed.\n",
     179               0 :                   nDataSize, nOffset );
     180               0 :         eErr = CE_Failure;
     181                 :     }
     182                 : 
     183              60 :     return eErr;
     184                 : }
     185                 : 
     186                 : /************************************************************************/
     187                 : /*                            IWriteBlock()                             */
     188                 : /************************************************************************/
     189                 : 
     190             190 : CPLErr ELASRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     191                 :                                      void * pImage )
     192                 : 
     193                 : {
     194             190 :     ELASDataset *poGDS = (ELASDataset *) poDS;
     195             190 :     CPLErr    eErr = CE_None;
     196                 :     long    nOffset;
     197                 :     int     nDataSize;
     198                 : 
     199             190 :     CPLAssert( nBlockXOff == 0 );
     200             190 :     CPLAssert( eAccess == GA_Update );
     201                 : 
     202             190 :     nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
     203             190 :     nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
     204                 :     
     205             190 :     if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
     206                 :         || VSIFWriteL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
     207                 :     {
     208                 :         CPLError( CE_Failure, CPLE_FileIO,
     209                 :                   "Seek or write of %d bytes at %ld failed.\n",
     210               0 :                   nDataSize, nOffset );
     211               0 :         eErr = CE_Failure;
     212                 :     }
     213                 : 
     214             190 :     return eErr;
     215                 : }
     216                 : 
     217                 : /************************************************************************/
     218                 : /* ==================================================================== */
     219                 : /*      ELASDataset                                                     */
     220                 : /* ==================================================================== */
     221                 : /************************************************************************/
     222                 : 
     223                 : 
     224                 : /************************************************************************/
     225                 : /*                            ELASDataset()                             */
     226                 : /************************************************************************/
     227                 : 
     228              30 : ELASDataset::ELASDataset()
     229                 : 
     230                 : {
     231              30 :     fp = NULL;
     232                 : 
     233              30 :     adfGeoTransform[0] = 0.0;
     234              30 :     adfGeoTransform[1] = 1.0;
     235              30 :     adfGeoTransform[2] = 0.0;
     236              30 :     adfGeoTransform[3] = 0.0;
     237              30 :     adfGeoTransform[4] = 0.0;
     238              30 :     adfGeoTransform[5] = 1.0;
     239              30 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                            ~ELASDataset()                            */
     243                 : /************************************************************************/
     244                 : 
     245              30 : ELASDataset::~ELASDataset()
     246                 : 
     247                 : {
     248              30 :     FlushCache();
     249                 : 
     250              30 :     if( fp != NULL )
     251                 :     {
     252              30 :         VSIFCloseL( fp );
     253              30 :         fp = NULL;
     254                 :     }
     255              30 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /*                             FlushCache()                             */
     259                 : /*                                                                      */
     260                 : /*      We also write out the header, if it is modified.                */
     261                 : /************************************************************************/
     262                 : 
     263              30 : void ELASDataset::FlushCache()
     264                 : 
     265                 : {
     266              30 :     GDALDataset::FlushCache();
     267                 : 
     268              30 :     if( bHeaderModified )
     269                 :     {
     270              16 :         VSIFSeekL( fp, 0, SEEK_SET );
     271              16 :         VSIFWriteL( &sHeader, 1024, 1, fp );
     272              16 :         bHeaderModified = FALSE;
     273                 :     }
     274              30 : }
     275                 : 
     276                 : /************************************************************************/
     277                 : /*                              Identify()                               */
     278                 : /************************************************************************/
     279                 : 
     280           12897 : int ELASDataset::Identify( GDALOpenInfo * poOpenInfo )
     281                 : 
     282                 : {
     283                 : /* -------------------------------------------------------------------- */
     284                 : /*  First we check to see if the file has the expected header           */
     285                 : /*  bytes.                                                               */
     286                 : /* -------------------------------------------------------------------- */
     287           12897 :     if( poOpenInfo->nHeaderBytes < 256 )
     288           11106 :         return FALSE;
     289                 : 
     290            1791 :     if( CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+0))) != 1024
     291                 :         || CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+28))) != 4321 )
     292                 :     {
     293            1761 :         return FALSE;
     294                 :     }
     295                 : 
     296              30 :     return TRUE;
     297                 : }
     298                 : 
     299                 : /************************************************************************/
     300                 : /*                                Open()                                */
     301                 : /************************************************************************/
     302                 : 
     303            3618 : GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
     304                 : 
     305                 : {
     306            3618 :     if( !Identify(poOpenInfo) )
     307            3588 :         return NULL;
     308                 : 
     309                 : /* -------------------------------------------------------------------- */
     310                 : /*      Create a corresponding GDALDataset.                             */
     311                 : /* -------------------------------------------------------------------- */
     312                 :     ELASDataset   *poDS;
     313                 :     const char    *pszAccess;
     314                 : 
     315              30 :     if( poOpenInfo->eAccess == GA_Update )
     316              17 :         pszAccess = "r+b";
     317                 :     else
     318              13 :         pszAccess = "rb";
     319                 : 
     320              30 :     poDS = new ELASDataset();
     321                 : 
     322              30 :     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, pszAccess );
     323              30 :     if( poDS->fp == NULL )
     324                 :     {
     325                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     326                 :                   "Attempt to open `%s' with acces `%s' failed.\n",
     327               0 :                   poOpenInfo->pszFilename, pszAccess );
     328               0 :         delete poDS;
     329               0 :         return NULL;
     330                 :     }
     331                 : 
     332              30 :     poDS->eAccess = poOpenInfo->eAccess;
     333                 : 
     334                 : /* -------------------------------------------------------------------- */
     335                 : /*      Read the header information.                                    */
     336                 : /* -------------------------------------------------------------------- */
     337              30 :     poDS->bHeaderModified = FALSE;
     338              30 :     if( VSIFReadL( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 )
     339                 :     {
     340                 :         CPLError( CE_Failure, CPLE_FileIO,
     341                 :                   "Attempt to read 1024 byte header filed on file %s\n",
     342               0 :                   poOpenInfo->pszFilename );
     343               0 :         return NULL;
     344                 :     }
     345                 : 
     346                 : /* -------------------------------------------------------------------- */
     347                 : /*      Extract information of interest from the header.                */
     348                 : /* -------------------------------------------------------------------- */
     349                 :     int   nStart, nEnd, nELASDataType, nBytesPerSample;
     350                 :     
     351              30 :     poDS->nLineOffset = CPL_MSBWORD32( poDS->sHeader.NBPR );
     352                 : 
     353              30 :     nStart = CPL_MSBWORD32( poDS->sHeader.IL );
     354              30 :     nEnd = CPL_MSBWORD32( poDS->sHeader.LL );
     355              30 :     poDS->nRasterYSize = nEnd - nStart + 1;
     356                 : 
     357              30 :     nStart = CPL_MSBWORD32( poDS->sHeader.IE );
     358              30 :     nEnd = CPL_MSBWORD32( poDS->sHeader.LE );
     359              30 :     poDS->nRasterXSize = nEnd - nStart + 1;
     360                 : 
     361              30 :     poDS->nBands = CPL_MSBWORD32( poDS->sHeader.NC );
     362                 : 
     363              30 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
     364                 :         !GDALCheckBandCount(poDS->nBands, FALSE))
     365                 :     {
     366               0 :         delete poDS;
     367               0 :         return NULL;
     368                 :     }
     369                 : 
     370              30 :     nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2;
     371              30 :     nBytesPerSample = poDS->sHeader.IH19[3];
     372                 :     
     373              30 :     if( nELASDataType == 0 && nBytesPerSample == 1 )
     374               0 :         poDS->eRasterDataType = GDT_Byte;
     375              50 :     else if( nELASDataType == 1 && nBytesPerSample == 1 )
     376              20 :         poDS->eRasterDataType = GDT_Byte;
     377              15 :     else if( nELASDataType == 16 && nBytesPerSample == 4 )
     378               5 :         poDS->eRasterDataType = GDT_Float32;
     379              10 :     else if( nELASDataType == 17 && nBytesPerSample == 8 )
     380               5 :         poDS->eRasterDataType = GDT_Float64;
     381                 :     else
     382                 :     {
     383               0 :         delete poDS;
     384                 :         CPLError( CE_Failure, CPLE_AppDefined,
     385                 :                   "Unrecognised image data type %d, with BytesPerSample=%d.\n",
     386               0 :                   nELASDataType, nBytesPerSample );
     387               0 :         return NULL;
     388                 :     }
     389                 :     
     390                 : /* -------------------------------------------------------------------- */
     391                 : /*  Band offsets are always multiples of 256 within a multi-band  */
     392                 : /*  scanline of data.           */
     393                 : /* -------------------------------------------------------------------- */
     394                 :     poDS->nBandOffset =
     395              30 :         (poDS->nRasterXSize * GDALGetDataTypeSize(poDS->eRasterDataType)/8);
     396                 : 
     397              30 :     if( poDS->nBandOffset % 256 != 0 )
     398                 :     {
     399                 :         poDS->nBandOffset =
     400              30 :             poDS->nBandOffset - (poDS->nBandOffset % 256) + 256;
     401                 :     }
     402                 : 
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Create band information objects.                                */
     405                 : /* -------------------------------------------------------------------- */
     406                 :     int   iBand;
     407                 : 
     408             196 :     for( iBand = 0; iBand < poDS->nBands; iBand++ )
     409                 :     {
     410              68 :         poDS->SetBand( iBand+1, new ELASRasterBand( poDS, iBand+1 ) );
     411                 :     }
     412                 : 
     413                 : /* -------------------------------------------------------------------- */
     414                 : /*  Extract the projection coordinates, if present.     */
     415                 : /* -------------------------------------------------------------------- */
     416              30 :     if( poDS->sHeader.XOffset != 0 )
     417                 :     {
     418              11 :         CPL_MSBPTR32(&(poDS->sHeader.XPixSize));
     419              11 :         CPL_MSBPTR32(&(poDS->sHeader.YPixSize));
     420                 : 
     421                 :         poDS->adfGeoTransform[0] =
     422              11 :             (GInt32) CPL_MSBWORD32(poDS->sHeader.XOffset);
     423              11 :         poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize;
     424              11 :         poDS->adfGeoTransform[2] = 0.0;
     425                 :         poDS->adfGeoTransform[3] =
     426              11 :             (GInt32) CPL_MSBWORD32(poDS->sHeader.YOffset);
     427              11 :         poDS->adfGeoTransform[4] = 0.0;
     428              11 :         poDS->adfGeoTransform[5] = -1.0 * ABS(poDS->sHeader.YPixSize);
     429                 : 
     430              11 :         CPL_MSBPTR32(&(poDS->sHeader.XPixSize));
     431              11 :         CPL_MSBPTR32(&(poDS->sHeader.YPixSize));
     432                 : 
     433              11 :         poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
     434              11 :         poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5;
     435                 :     }
     436                 :     else
     437                 :     {
     438              19 :         poDS->adfGeoTransform[0] = 0.0;
     439              19 :         poDS->adfGeoTransform[1] = 1.0;
     440              19 :         poDS->adfGeoTransform[2] = 0.0;
     441              19 :         poDS->adfGeoTransform[3] = 0.0;
     442              19 :         poDS->adfGeoTransform[4] = 0.0;
     443              19 :         poDS->adfGeoTransform[5] = 1.0;
     444                 :     }
     445                 :     
     446                 : /* -------------------------------------------------------------------- */
     447                 : /*      Initialize any PAM information.                                 */
     448                 : /* -------------------------------------------------------------------- */
     449              30 :     poDS->SetDescription( poOpenInfo->pszFilename );
     450              30 :     poDS->TryLoadXML();
     451                 : 
     452                 : /* -------------------------------------------------------------------- */
     453                 : /*      Check for external overviews.                                   */
     454                 : /* -------------------------------------------------------------------- */
     455              30 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
     456                 : 
     457              30 :     return( poDS );
     458                 : }
     459                 : 
     460                 : /************************************************************************/
     461                 : /*                               Create()                               */
     462                 : /*                                                                      */
     463                 : /*      Create a new GeoTIFF or TIFF file.                              */
     464                 : /************************************************************************/
     465                 : 
     466              44 : GDALDataset *ELASDataset::Create( const char * pszFilename,
     467                 :                                   int nXSize, int nYSize, int nBands,
     468                 :                                   GDALDataType eType,
     469                 :                                   char ** /* notdef: papszParmList */ )
     470                 : 
     471                 : {
     472                 :     int   nBandOffset;
     473                 :     
     474                 : /* -------------------------------------------------------------------- */
     475                 : /*      Verify input options.                                           */
     476                 : /* -------------------------------------------------------------------- */
     477              44 :     if (nBands <= 0)
     478                 :     {
     479                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     480               1 :                   "ELAS driver does not support %d bands.\n", nBands);
     481               1 :         return NULL;
     482                 :     }
     483                 : 
     484              43 :     if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_Float64 )
     485                 :     {
     486                 :         CPLError( CE_Failure, CPLE_AppDefined,
     487                 :                   "Attempt to create an ELAS dataset with an illegal\n"
     488                 :                   "data type (%d).\n",
     489              24 :                   eType );
     490                 : 
     491              24 :         return NULL;
     492                 :     }
     493                 : 
     494                 : /* -------------------------------------------------------------------- */
     495                 : /*      Try to create the file.                                         */
     496                 : /* -------------------------------------------------------------------- */
     497                 :     FILE  *fp;
     498                 : 
     499              19 :     fp = VSIFOpen( pszFilename, "w" );
     500                 : 
     501              19 :     if( fp == NULL )
     502                 :     {
     503                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     504                 :                   "Attempt to create file `%s' failed.\n",
     505               2 :                   pszFilename );
     506               2 :         return NULL;
     507                 :     }
     508                 :     
     509                 : /* -------------------------------------------------------------------- */
     510                 : /*  How long will each band of a scanline be?     */
     511                 : /* -------------------------------------------------------------------- */
     512              17 :     nBandOffset = nXSize * GDALGetDataTypeSize(eType)/8;
     513                 : 
     514              17 :     if( nBandOffset % 256 != 0 )
     515                 :     {
     516              17 :         nBandOffset = nBandOffset - (nBandOffset % 256) + 256;
     517                 :     }
     518                 : 
     519                 : /* -------------------------------------------------------------------- */
     520                 : /*      Setup header data block.                                        */
     521                 : /*                                                                      */
     522                 : /*      Note that CPL_MSBWORD32() will swap little endian words to      */
     523                 : /*      big endian on little endian platforms.                          */
     524                 : /* -------------------------------------------------------------------- */
     525                 :     ELASHeader  sHeader;
     526                 : 
     527              17 :     memset( &sHeader, 0, 1024 );
     528                 : 
     529              17 :     sHeader.NBIH = CPL_MSBWORD32(1024);
     530                 : 
     531              17 :     sHeader.NBPR = CPL_MSBWORD32(nBands * nBandOffset);
     532                 :     
     533              17 :     sHeader.IL = CPL_MSBWORD32(1);
     534              17 :     sHeader.LL = CPL_MSBWORD32(nYSize);
     535                 : 
     536              17 :     sHeader.IE = CPL_MSBWORD32(1);
     537              17 :     sHeader.LE = CPL_MSBWORD32(nXSize);
     538                 : 
     539              17 :     sHeader.NC = CPL_MSBWORD32(nBands);
     540                 : 
     541              17 :     sHeader.H4321 = CPL_MSBWORD32(4321);
     542                 : 
     543              17 :     sHeader.IH19[0] = 0x04;
     544              17 :     sHeader.IH19[1] = 0xd2;
     545              17 :     sHeader.IH19[3] = (GByte) (GDALGetDataTypeSize(eType) / 8);
     546                 : 
     547              17 :     if( eType == GDT_Byte )
     548              11 :         sHeader.IH19[2] = 1 << 2;
     549               6 :     else if( eType == GDT_Float32 )
     550               3 :         sHeader.IH19[2] = 16 << 2;
     551               3 :     else if( eType == GDT_Float64 )
     552               3 :         sHeader.IH19[2] = 17 << 2;
     553                 : 
     554                 : /* -------------------------------------------------------------------- */
     555                 : /*      Write the header data.                                          */
     556                 : /* -------------------------------------------------------------------- */
     557              17 :     VSIFWrite( &sHeader, 1024, 1, fp );
     558                 : 
     559                 : /* -------------------------------------------------------------------- */
     560                 : /*      Now write out zero data for all the imagery.  This is           */
     561                 : /*      inefficient, but simplies the IReadBlock() / IWriteBlock() logic.*/
     562                 : /* -------------------------------------------------------------------- */
     563                 :     GByte *pabyLine;
     564                 : 
     565              17 :     pabyLine = (GByte *) CPLCalloc(nBandOffset,nBands);
     566            1007 :     for( int iLine = 0; iLine < nYSize; iLine++ )
     567                 :     {
     568             990 :         if( VSIFWrite( pabyLine, 1, nBandOffset, fp ) != (size_t) nBandOffset )
     569                 :         {
     570                 :             CPLError( CE_Failure, CPLE_FileIO,
     571                 :                       "Error writing ELAS image data ... likely insufficient"
     572               0 :                       " disk space.\n" );
     573               0 :             VSIFClose( fp );
     574               0 :             CPLFree( pabyLine );
     575               0 :             return NULL;
     576                 :         }
     577                 :     }
     578                 : 
     579              17 :     CPLFree( pabyLine );
     580                 :     
     581              17 :     VSIFClose( fp );
     582                 : 
     583                 : /* -------------------------------------------------------------------- */
     584                 : /*      Try to return a regular handle on the file.                     */
     585                 : /* -------------------------------------------------------------------- */
     586              17 :     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     587                 : }
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                          GetGeoTransform()                           */
     591                 : /************************************************************************/
     592                 : 
     593               9 : CPLErr ELASDataset::GetGeoTransform( double * padfTransform )
     594                 : 
     595                 : {
     596               9 :     memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
     597                 : 
     598               9 :     return( CE_None );
     599                 : }
     600                 : 
     601                 : /************************************************************************/
     602                 : /*                          SetGeoTransform()                           */
     603                 : /************************************************************************/
     604                 : 
     605              16 : CPLErr ELASDataset::SetGeoTransform( double * padfTransform )
     606                 : 
     607                 : {
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      I don't think it supports rotation, but perhaps it is possible  */
     610                 : /*      for us to use the 2x2 transform matrix to accomplish some       */
     611                 : /*      sort of rotation.                                               */
     612                 : /* -------------------------------------------------------------------- */
     613              16 :     if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
     614                 :     {
     615                 :         CPLError( CE_Failure, CPLE_AppDefined,
     616                 :                   "Attempt to set rotated geotransform on ELAS file.\n"
     617               0 :                   "ELAS does not support rotation.\n" );
     618                 : 
     619               0 :         return CE_Failure;
     620                 :     }
     621                 :     
     622                 : /* -------------------------------------------------------------------- */
     623                 : /*      Remember the new transform, and update the header.              */
     624                 : /* -------------------------------------------------------------------- */
     625                 :     int   nXOff, nYOff;
     626                 :     
     627              16 :     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
     628                 : 
     629              16 :     bHeaderModified = TRUE;
     630                 : 
     631              16 :     nXOff = (int) (adfGeoTransform[0] + adfGeoTransform[1]*0.5);
     632              16 :     nYOff = (int) (adfGeoTransform[3] + adfGeoTransform[5]*0.5);
     633                 : 
     634              16 :     sHeader.XOffset = CPL_MSBWORD32(nXOff);
     635              16 :     sHeader.YOffset = CPL_MSBWORD32(nYOff);
     636                 : 
     637              16 :     sHeader.XPixSize = (float) ABS(adfGeoTransform[1]);
     638              16 :     sHeader.YPixSize = (float) ABS(adfGeoTransform[5]);
     639                 : 
     640              16 :     CPL_MSBPTR32(&(sHeader.XPixSize));
     641              16 :     CPL_MSBPTR32(&(sHeader.YPixSize));
     642                 : 
     643              16 :     strncpy( sHeader.YLabel, "NOR ", 4 );
     644              16 :     strncpy( sHeader.XLabel, "EAS ", 4 );
     645                 : 
     646              16 :     sHeader.Matrix[0] = 1.0;
     647              16 :     sHeader.Matrix[1] = 0.0;
     648              16 :     sHeader.Matrix[2] = 0.0;
     649              16 :     sHeader.Matrix[3] = -1.0;
     650                 :     
     651              16 :     CPL_MSBPTR32(&(sHeader.Matrix[0]));
     652              16 :     CPL_MSBPTR32(&(sHeader.Matrix[1]));
     653              16 :     CPL_MSBPTR32(&(sHeader.Matrix[2]));
     654              16 :     CPL_MSBPTR32(&(sHeader.Matrix[3]));
     655                 :     
     656              16 :     return( CE_None );
     657                 : }
     658                 : 
     659                 : 
     660                 : /************************************************************************/
     661                 : /*                          GDALRegister_ELAS()                        */
     662                 : /************************************************************************/
     663                 : 
     664             558 : void GDALRegister_ELAS()
     665                 : 
     666                 : {
     667                 :     GDALDriver  *poDriver;
     668                 : 
     669             558 :     if( GDALGetDriverByName( "ELAS" ) == NULL )
     670                 :     {
     671             537 :         poDriver = new GDALDriver();
     672                 :         
     673             537 :         poDriver->SetDescription( "ELAS" );
     674                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     675             537 :                                    "ELAS" );
     676                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
     677             537 :                                    "Byte Float32 Float64" );
     678                 : 
     679             537 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     680                 : 
     681             537 :         poDriver->pfnOpen = ELASDataset::Open;
     682             537 :         poDriver->pfnIdentify = ELASDataset::Identify;
     683             537 :         poDriver->pfnCreate = ELASDataset::Create;
     684                 : 
     685             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     686                 :     }
     687             558 : }

Generated by: LCOV version 1.7