LCOV - code coverage report
Current view: directory - frmts/raw - landataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 323 204 63.2 %
Date: 2012-12-26 Functions: 24 12 50.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: landataset.cpp 23033 2011-09-03 18:46:11Z rouault $
       3                 :  *
       4                 :  * Project:  eCognition
       5                 :  * Purpose:  Implementation of Erdas .LAN / .GIS format.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, 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 "rawdataset.h"
      31                 : #include "cpl_string.h"
      32                 : #include "ogr_spatialref.h"
      33                 : 
      34                 : CPL_CVSID("$Id: landataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void  GDALRegister_LAN(void);
      38                 : CPL_C_END
      39                 : 
      40                 : /**
      41                 : 
      42                 : Erdas Header format: "HEAD74"
      43                 : 
      44                 : Offset   Size    Type      Description
      45                 : ------   ----    ----      -----------
      46                 : 0          6     char      magic cookie / version (ie. HEAD74). 
      47                 : 6          2    Int16      Pixel type, 0=8bit, 1=4bit, 2=16bit
      48                 : 8          2    Int16      Number of Bands. 
      49                 : 10         6     char      Unknown.
      50                 : 16         4    Int32      Width
      51                 : 20         4    Int32      Height
      52                 : 24         4    Int32      X Start (offset in original file?)
      53                 : 28         4    Int32      Y Start (offset in original file?)
      54                 : 32        56     char      Unknown.
      55                 : 88         2    Int16      0=LAT, 1=UTM, 2=StatePlane, 3- are projections?
      56                 : 90         2    Int16      Classes in coverage.
      57                 : 92        14     char      Unknown.
      58                 : 106        2    Int16      Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
      59                 : 108        4  Float32      Pixel area. 
      60                 : 112        4  Float32      Upper Left corner X (center of pixel?)
      61                 : 116        4  Float32      Upper Left corner Y (center of pixel?)
      62                 : 120        4  Float32      Width of a pixel.
      63                 : 124        4  Float32      Height of a pixel.
      64                 : 
      65                 : Erdas Header format: "HEADER"
      66                 : 
      67                 : Offset   Size    Type      Description
      68                 : ------   ----    ----      -----------
      69                 : 0          6     char      magic cookie / version (ie. HEAD74). 
      70                 : 6          2    Int16      Pixel type, 0=8bit, 1=4bit, 2=16bit
      71                 : 8          2    Int16      Number of Bands. 
      72                 : 10         6     char      Unknown.
      73                 : 16         4  Float32      Width
      74                 : 20         4  Float32      Height
      75                 : 24         4    Int32      X Start (offset in original file?)
      76                 : 28         4    Int32      Y Start (offset in original file?)
      77                 : 32        56     char      Unknown.
      78                 : 88         2    Int16      0=LAT, 1=UTM, 2=StatePlane, 3- are projections?
      79                 : 90         2    Int16      Classes in coverage.
      80                 : 92        14     char      Unknown.
      81                 : 106        2    Int16      Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
      82                 : 108        4  Float32      Pixel area. 
      83                 : 112        4  Float32      Upper Left corner X (center of pixel?)
      84                 : 116        4  Float32      Upper Left corner Y (center of pixel?)
      85                 : 120        4  Float32      Width of a pixel.
      86                 : 124        4  Float32      Height of a pixel.
      87                 : 
      88                 : All binary fields are in the same byte order but it may be big endian or
      89                 : little endian depending on what platform the file was written on.  Usually
      90                 : this can be checked against the number of bands though this test won't work
      91                 : if there are more than 255 bands. 
      92                 : 
      93                 : There is also some information on .STA and .TRL files at:
      94                 : 
      95                 :   http://www.pcigeomatics.com/cgi-bin/pcihlp/ERDASWR%7CTRAILER+FORMAT
      96                 : 
      97                 : **/
      98                 : 
      99                 : #define ERD_HEADER_SIZE  128
     100                 : 
     101                 : /************************************************************************/
     102                 : /* ==================================================================== */
     103                 : /*                         LAN4BitRasterBand                            */
     104                 : /* ==================================================================== */
     105                 : /************************************************************************/
     106                 : 
     107                 : class LANDataset;
     108                 : 
     109                 : class LAN4BitRasterBand : public GDALPamRasterBand
     110                 : {
     111                 :     GDALColorTable *poCT;
     112                 :     GDALColorInterp eInterp;
     113                 : 
     114                 :   public:
     115                 :                    LAN4BitRasterBand( LANDataset *, int );
     116                 :                   ~LAN4BitRasterBand();
     117                 : 
     118                 :     virtual GDALColorTable *GetColorTable();
     119                 :     virtual GDALColorInterp GetColorInterpretation();
     120                 :     virtual CPLErr SetColorTable( GDALColorTable * ); 
     121                 :     virtual CPLErr SetColorInterpretation( GDALColorInterp );
     122                 : 
     123                 :     virtual CPLErr IReadBlock( int, int, void * );
     124                 : };
     125                 : 
     126                 : /************************************************************************/
     127                 : /* ==================================================================== */
     128                 : /*        LANDataset        */
     129                 : /* ==================================================================== */
     130                 : /************************************************************************/
     131                 : 
     132                 : class LANDataset : public RawDataset
     133                 : {
     134                 :   public:
     135                 :     VSILFILE  *fpImage; // image data file.
     136                 :     
     137                 :     char  pachHeader[ERD_HEADER_SIZE];
     138                 : 
     139                 :     char        *pszProjection;
     140                 :     
     141                 :     double      adfGeoTransform[6];
     142                 : 
     143                 :     CPLString   osSTAFilename;
     144                 :     void        CheckForStatistics(void);
     145                 : 
     146                 :     virtual char **GetFileList();
     147                 : 
     148                 :   public:
     149                 :         LANDataset();
     150                 :               ~LANDataset();
     151                 :     
     152                 :     virtual CPLErr GetGeoTransform( double * padfTransform );
     153                 :     virtual CPLErr SetGeoTransform( double * padfTransform );
     154                 :     virtual const char *GetProjectionRef();
     155                 :     virtual CPLErr SetProjection( const char * );
     156                 : 
     157                 :     static GDALDataset *Open( GDALOpenInfo * );
     158                 :     static GDALDataset *Create( const char * pszFilename,
     159                 :                                 int nXSize, int nYSize, int nBands,
     160                 :                                 GDALDataType eType, char ** papszOptions );
     161                 : };
     162                 : 
     163                 : /************************************************************************/
     164                 : /* ==================================================================== */
     165                 : /*                         LAN4BitRasterBand                            */
     166                 : /* ==================================================================== */
     167                 : /************************************************************************/
     168                 : 
     169                 : /************************************************************************/
     170                 : /*                         LAN4BitRasterBand()                          */
     171                 : /************************************************************************/
     172                 : 
     173               1 : LAN4BitRasterBand::LAN4BitRasterBand( LANDataset *poDS, int nBandIn )
     174                 : 
     175                 : {
     176               1 :     this->poDS = poDS;
     177               1 :     this->nBand = nBandIn;
     178               1 :     this->eDataType = GDT_Byte;
     179                 : 
     180               1 :     nBlockXSize = poDS->GetRasterXSize();;
     181               1 :     nBlockYSize = 1;
     182                 : 
     183               1 :     poCT = NULL;
     184               1 :     eInterp = GCI_Undefined;
     185               1 : }
     186                 : 
     187                 : /************************************************************************/
     188                 : /*                         ~LAN4BitRasterBand()                         */
     189                 : /************************************************************************/
     190                 : 
     191               1 : LAN4BitRasterBand::~LAN4BitRasterBand()
     192                 : 
     193                 : {
     194               1 :     if( poCT )
     195               0 :         delete poCT;
     196               1 : }
     197                 : 
     198                 : /************************************************************************/
     199                 : /*                             IReadBlock()                             */
     200                 : /************************************************************************/
     201                 : 
     202               2 : CPLErr LAN4BitRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     203                 :                                       void * pImage )
     204                 : 
     205                 : {
     206               2 :     LANDataset *poLAN_DS = (LANDataset *) poDS;
     207               2 :     CPLAssert( nBlockXOff == 0  );
     208                 :     
     209                 : /* -------------------------------------------------------------------- */
     210                 : /*      Seek to profile.                                                */
     211                 : /* -------------------------------------------------------------------- */
     212                 :     int nOffset;
     213                 : 
     214                 :     nOffset = 
     215                 :         ERD_HEADER_SIZE
     216                 :         + (nBlockYOff * nRasterXSize * poLAN_DS->GetRasterCount()) / 2
     217               2 :         + ((nBand - 1) * nRasterXSize) / 2;
     218                 : 
     219               2 :     if( VSIFSeekL( poLAN_DS->fpImage, nOffset, SEEK_SET ) != 0 )
     220                 :     {
     221                 :         CPLError( CE_Failure, CPLE_FileIO, 
     222               0 :                   "LAN Seek failed:%s", VSIStrerror( errno ) );
     223               0 :         return CE_Failure;
     224                 :     }
     225                 : 
     226                 : /* -------------------------------------------------------------------- */
     227                 : /*      Read the profile.                                               */
     228                 : /* -------------------------------------------------------------------- */
     229               2 :     if( VSIFReadL( pImage, 1, nRasterXSize/2, poLAN_DS->fpImage ) != 
     230                 :         (size_t) nRasterXSize / 2 )
     231                 :     {
     232                 :         CPLError( CE_Failure, CPLE_FileIO, 
     233               0 :                   "LAN Read failed:%s", VSIStrerror( errno ) );
     234               0 :         return CE_Failure;
     235                 :     }
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      Convert 4bit to 8bit.                                           */
     239                 : /* -------------------------------------------------------------------- */
     240                 :     int i;
     241                 : 
     242               6 :     for( i = nRasterXSize-1; i >= 0; i-- )
     243                 :     {
     244               4 :         if( (i & 0x01) != 0 )
     245               2 :             ((GByte *) pImage)[i] = ((GByte *) pImage)[i/2] & 0x0f;
     246                 :         else
     247               2 :             ((GByte *) pImage)[i] = (((GByte *) pImage)[i/2] & 0xf0)/16;
     248                 :     }
     249                 : 
     250               2 :     return CE_None;
     251                 : }
     252                 : 
     253                 : /************************************************************************/
     254                 : /*                           SetColorTable()                            */
     255                 : /************************************************************************/
     256                 : 
     257               0 : CPLErr LAN4BitRasterBand::SetColorTable( GDALColorTable *poNewCT )
     258                 : 
     259                 : {
     260               0 :     if( poCT )
     261               0 :         delete poCT;
     262               0 :     if( poNewCT == NULL )
     263               0 :         poCT = NULL;
     264                 :     else
     265               0 :         poCT = poNewCT->Clone();
     266                 : 
     267               0 :     return CE_None;
     268                 : }
     269                 : 
     270                 : /************************************************************************/
     271                 : /*                           GetColorTable()                            */
     272                 : /************************************************************************/
     273                 : 
     274               0 : GDALColorTable *LAN4BitRasterBand::GetColorTable()
     275                 : 
     276                 : {
     277               0 :     if( poCT != NULL )
     278               0 :         return poCT;
     279                 :     else
     280               0 :         return GDALPamRasterBand::GetColorTable();
     281                 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /*                       SetColorInterpretation()                       */
     285                 : /************************************************************************/
     286                 : 
     287               0 : CPLErr LAN4BitRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
     288                 : 
     289                 : {
     290               0 :     eInterp = eNewInterp;
     291                 : 
     292               0 :     return CE_None;
     293                 : }
     294                 : 
     295                 : /************************************************************************/
     296                 : /*                       GetColorInterpretation()                       */
     297                 : /************************************************************************/
     298                 : 
     299               0 : GDALColorInterp LAN4BitRasterBand::GetColorInterpretation()
     300                 : 
     301                 : {
     302               0 :     return eInterp;
     303                 : }
     304                 : 
     305                 : /************************************************************************/
     306                 : /* ==================================================================== */
     307                 : /*        LANDataset        */
     308                 : /* ==================================================================== */
     309                 : /************************************************************************/
     310                 : 
     311                 : /************************************************************************/
     312                 : /*                             LANDataset()                             */
     313                 : /************************************************************************/
     314                 : 
     315              24 : LANDataset::LANDataset()
     316                 : {
     317              24 :     fpImage = NULL;
     318              24 :     pszProjection = NULL;
     319              24 : }
     320                 : 
     321                 : /************************************************************************/
     322                 : /*                            ~LANDataset()                             */
     323                 : /************************************************************************/
     324                 : 
     325              24 : LANDataset::~LANDataset()
     326                 : 
     327                 : {
     328              24 :     FlushCache();
     329                 : 
     330              24 :     if( fpImage != NULL )
     331              24 :         VSIFCloseL( fpImage );
     332                 : 
     333              24 :     CPLFree( pszProjection );
     334              24 : }
     335                 : 
     336                 : /************************************************************************/
     337                 : /*                                Open()                                */
     338                 : /************************************************************************/
     339                 : 
     340           12006 : GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     341                 : 
     342                 : {
     343                 : /* -------------------------------------------------------------------- */
     344                 : /*      We assume the user is pointing to the header (.pcb) file.       */
     345                 : /*      Does this appear to be a pcb file?                              */
     346                 : /* -------------------------------------------------------------------- */
     347           12006 :     if( poOpenInfo->nHeaderBytes < ERD_HEADER_SIZE )
     348           11398 :         return NULL;
     349                 : 
     350             608 :     if( !EQUALN((const char *)poOpenInfo->pabyHeader,"HEADER",6)
     351                 :         && !EQUALN((const char *)poOpenInfo->pabyHeader,"HEAD74",6) )
     352             584 :         return NULL;
     353                 : 
     354                 : /* -------------------------------------------------------------------- */
     355                 : /*      Create a corresponding GDALDataset.                             */
     356                 : /* -------------------------------------------------------------------- */
     357                 :     LANDataset  *poDS;
     358                 : 
     359              24 :     poDS = new LANDataset();
     360                 : 
     361              24 :     poDS->eAccess = poOpenInfo->eAccess;
     362                 : 
     363                 : /* -------------------------------------------------------------------- */
     364                 : /*      Adopt the openinfo file pointer for use with this file.         */
     365                 : /* -------------------------------------------------------------------- */
     366              24 :     if( poOpenInfo->eAccess == GA_ReadOnly )
     367              10 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     368                 :     else
     369              14 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
     370                 : 
     371              24 :     if( poDS->fpImage == NULL )
     372               0 :         return NULL;
     373                 : 
     374                 : /* -------------------------------------------------------------------- */
     375                 : /*      Do we need to byte swap the headers to local machine order?     */
     376                 : /* -------------------------------------------------------------------- */
     377              24 :     int bBigEndian = poOpenInfo->pabyHeader[8] == 0;
     378                 :     int bNeedSwap;
     379                 : 
     380              24 :     memcpy( poDS->pachHeader, poOpenInfo->pabyHeader, ERD_HEADER_SIZE );
     381                 : 
     382                 : #ifdef CPL_LSB
     383              24 :     bNeedSwap = bBigEndian;
     384                 : #else
     385                 :     bNeedSwap = !bBigEndian;
     386                 : #endif
     387                 :         
     388              24 :     if( bNeedSwap )
     389                 :     {
     390               2 :         CPL_SWAP16PTR( poDS->pachHeader + 6 );
     391               2 :         CPL_SWAP16PTR( poDS->pachHeader + 8 );
     392                 : 
     393               2 :         CPL_SWAP32PTR( poDS->pachHeader + 16 );
     394               2 :         CPL_SWAP32PTR( poDS->pachHeader + 20 );
     395               2 :         CPL_SWAP32PTR( poDS->pachHeader + 24 );
     396               2 :         CPL_SWAP32PTR( poDS->pachHeader + 28 );
     397                 : 
     398               2 :         CPL_SWAP16PTR( poDS->pachHeader + 88 );
     399               2 :         CPL_SWAP16PTR( poDS->pachHeader + 90 );
     400                 : 
     401               2 :         CPL_SWAP16PTR( poDS->pachHeader + 106 );
     402               2 :         CPL_SWAP32PTR( poDS->pachHeader + 108 );
     403               2 :         CPL_SWAP32PTR( poDS->pachHeader + 112 );
     404               2 :         CPL_SWAP32PTR( poDS->pachHeader + 116 );
     405               2 :         CPL_SWAP32PTR( poDS->pachHeader + 120 );
     406               2 :         CPL_SWAP32PTR( poDS->pachHeader + 124 );
     407                 :     }
     408                 : 
     409                 : /* -------------------------------------------------------------------- */
     410                 : /*      Capture some information from the file that is of interest.     */
     411                 : /* -------------------------------------------------------------------- */
     412                 :     int  nBandCount, nPixelOffset;
     413                 :     GDALDataType eDataType;
     414                 : 
     415              24 :     if( EQUALN(poDS->pachHeader,"HEADER",7) )
     416                 :     {
     417               0 :         poDS->nRasterXSize = (int) *((float *) (poDS->pachHeader + 16));
     418               0 :         poDS->nRasterYSize = (int) *((float *) (poDS->pachHeader + 20));
     419                 :     }
     420                 :     else
     421                 :     {
     422              24 :         poDS->nRasterXSize = *((GInt32 *) (poDS->pachHeader + 16));
     423              24 :         poDS->nRasterYSize = *((GInt32 *) (poDS->pachHeader + 20));
     424                 :     }
     425                 : 
     426              24 :     if( *((GInt16 *) (poDS->pachHeader + 6)) == 0 )
     427                 :     {
     428              18 :         eDataType = GDT_Byte;
     429              18 :         nPixelOffset = 1;
     430                 :     }
     431               6 :     else if( *((GInt16 *) (poDS->pachHeader + 6)) == 1 ) /* 4bit! */
     432                 :     {
     433               1 :         eDataType = GDT_Byte;
     434               1 :         nPixelOffset = -1;
     435                 :     }
     436               5 :     else if( *((GInt16 *) (poDS->pachHeader + 6)) == 2 )
     437                 :     {
     438               5 :         nPixelOffset = 2;
     439               5 :         eDataType = GDT_Int16;
     440                 :     }
     441                 :     else
     442                 :     {
     443                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     444                 :                   "Unsupported pixel type (%d).", 
     445               0 :                   *((GInt16 *) (poDS->pachHeader + 6)) );
     446                 :                   
     447               0 :         delete poDS;
     448               0 :         return NULL;
     449                 :     }
     450                 : 
     451              24 :     nBandCount = *((GInt16 *) (poDS->pachHeader + 8));
     452                 : 
     453              24 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
     454                 :         !GDALCheckBandCount(nBandCount, FALSE))
     455                 :     {
     456               2 :         delete poDS;
     457               2 :         return NULL;
     458                 :     }
     459                 : 
     460                 : /* -------------------------------------------------------------------- */
     461                 : /*      Create band information object.                                 */
     462                 : /* -------------------------------------------------------------------- */
     463              78 :     for( int iBand = 1; iBand <= nBandCount; iBand++ )
     464                 :     {
     465              56 :         if( nPixelOffset == -1 ) /* 4 bit case */
     466                 :             poDS->SetBand( iBand, 
     467               1 :                            new LAN4BitRasterBand( poDS, iBand ) );
     468                 :         else
     469                 :             poDS->SetBand( 
     470                 :                 iBand, 
     471                 :                 new RawRasterBand( poDS, iBand, poDS->fpImage, 
     472                 :                                    ERD_HEADER_SIZE + (iBand-1) 
     473                 :                                    * nPixelOffset * poDS->nRasterXSize,
     474                 :                                    nPixelOffset, 
     475                 :                                    poDS->nRasterXSize*nPixelOffset*nBandCount,
     476              55 :                                    eDataType, !bNeedSwap, TRUE ));
     477                 :     }
     478                 : 
     479                 : /* -------------------------------------------------------------------- */
     480                 : /*      Initialize any PAM information.                                 */
     481                 : /* -------------------------------------------------------------------- */
     482              22 :     poDS->SetDescription( poOpenInfo->pszFilename );
     483              22 :     poDS->CheckForStatistics();
     484              22 :     poDS->TryLoadXML();
     485                 : 
     486                 : /* -------------------------------------------------------------------- */
     487                 : /*      Check for overviews.                                            */
     488                 : /* -------------------------------------------------------------------- */
     489              22 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     490                 : 
     491                 : /* -------------------------------------------------------------------- */
     492                 : /*      Try to interprete georeferencing.                               */
     493                 : /* -------------------------------------------------------------------- */
     494              22 :     poDS->adfGeoTransform[0] = *((float *) (poDS->pachHeader + 112));
     495              22 :     poDS->adfGeoTransform[1] = *((float *) (poDS->pachHeader + 120));
     496              22 :     poDS->adfGeoTransform[2] = 0.0;
     497              22 :     poDS->adfGeoTransform[3] = *((float *) (poDS->pachHeader + 116));
     498              22 :     poDS->adfGeoTransform[4] = 0.0;
     499              22 :     poDS->adfGeoTransform[5] = - *((float *) (poDS->pachHeader + 124));
     500                 : 
     501                 :     // adjust for center of pixel vs. top left corner of pixel.
     502              22 :     poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
     503              22 :     poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5;
     504                 : 
     505                 : /* -------------------------------------------------------------------- */
     506                 : /*      If we didn't get any georeferencing, try for a worldfile.       */
     507                 : /* -------------------------------------------------------------------- */
     508              44 :     if( poDS->adfGeoTransform[1] == 0.0
     509              22 :         || poDS->adfGeoTransform[5] == 0.0 )
     510                 :     {
     511               0 :         if( !GDALReadWorldFile( poOpenInfo->pszFilename, NULL, 
     512                 :                                 poDS->adfGeoTransform ) )
     513                 :             GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
     514               0 :                                poDS->adfGeoTransform );
     515                 :     }
     516                 : 
     517                 : /* -------------------------------------------------------------------- */
     518                 : /*      Try to come up with something for the coordinate system.        */
     519                 : /* -------------------------------------------------------------------- */
     520              22 :     int nCoordSys = *((GInt16 *) (poDS->pachHeader + 88));
     521                 : 
     522              22 :     if( nCoordSys == 0 )
     523                 :     {
     524              22 :         poDS->pszProjection = CPLStrdup(SRS_WKT_WGS84);
     525                 :             
     526                 :     }
     527               0 :     else if( nCoordSys == 1 )
     528                 :     {
     529                 :         poDS->pszProjection = 
     530               0 :             CPLStrdup("LOCAL_CS[\"UTM - Zone Unknown\",UNIT[\"Meter\",1]]");
     531                 :     }
     532               0 :     else if( nCoordSys == 2 )
     533                 :     {
     534               0 :         poDS->pszProjection = CPLStrdup("LOCAL_CS[\"State Plane - Zone Unknown\",UNIT[\"US survey foot\",0.3048006096012192]]");
     535                 :     }
     536                 :     else 
     537                 :     {
     538                 :         poDS->pszProjection = 
     539               0 :             CPLStrdup("LOCAL_CS[\"Unknown\",UNIT[\"Meter\",1]]");
     540                 :     }
     541                 : 
     542                 : /* -------------------------------------------------------------------- */
     543                 : /*      Check for a trailer file with a colormap in it.                 */
     544                 : /* -------------------------------------------------------------------- */
     545              22 :     char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     546              22 :     char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
     547                 :     const char *pszTRLFilename = 
     548              22 :         CPLFormCIFilename( pszPath, pszBasename, "trl" );
     549                 :     VSILFILE *fpTRL;
     550                 : 
     551              22 :     fpTRL = VSIFOpenL( pszTRLFilename, "rb" );
     552              22 :     if( fpTRL != NULL )
     553                 :     {
     554                 :         char szTRLData[896];
     555                 :         int iColor;
     556                 :         GDALColorTable *poCT;
     557                 : 
     558               0 :         VSIFReadL( szTRLData, 1, 896, fpTRL );
     559               0 :         VSIFCloseL( fpTRL );
     560                 :         
     561               0 :         poCT = new GDALColorTable();
     562               0 :         for( iColor = 0; iColor < 256; iColor++ )
     563                 :         {
     564                 :             GDALColorEntry sEntry;
     565                 : 
     566               0 :             sEntry.c2 = ((GByte *) szTRLData)[iColor+128];
     567               0 :             sEntry.c1 = ((GByte *) szTRLData)[iColor+128+256];
     568               0 :             sEntry.c3 = ((GByte *) szTRLData)[iColor+128+512];
     569               0 :             sEntry.c4 = 255;
     570               0 :             poCT->SetColorEntry( iColor, &sEntry );
     571                 : 
     572                 :             // only 16 colors in 4bit files.
     573               0 :             if( nPixelOffset == -1 && iColor == 15 )
     574               0 :                 break;
     575                 :         }
     576                 : 
     577               0 :         poDS->GetRasterBand(1)->SetColorTable( poCT );
     578               0 :         poDS->GetRasterBand(1)->SetColorInterpretation( GCI_PaletteIndex );
     579                 :         
     580               0 :         delete poCT;
     581                 :     }
     582                 : 
     583              22 :     CPLFree( pszPath );
     584              22 :     CPLFree( pszBasename );
     585                 : 
     586              22 :     return( poDS );
     587                 : }
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                          GetGeoTransform()                           */
     591                 : /************************************************************************/
     592                 : 
     593               7 : CPLErr LANDataset::GetGeoTransform( double * padfTransform )
     594                 : 
     595                 : {
     596               7 :     if( adfGeoTransform[1] != 0.0 && adfGeoTransform[5] != 0.0 )
     597                 :     {
     598               7 :         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
     599               7 :         return CE_None;
     600                 :     }
     601                 :     else
     602               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     603                 : }
     604                 : 
     605                 : /************************************************************************/
     606                 : /*                          SetGeoTransform()                           */
     607                 : /************************************************************************/
     608                 : 
     609              13 : CPLErr LANDataset::SetGeoTransform( double * padfTransform )
     610                 : 
     611                 : {
     612                 :     unsigned char abyHeader[128];
     613                 : 
     614              13 :     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
     615                 : 
     616              13 :     VSIFSeekL( fpImage, 0, SEEK_SET );
     617              13 :     VSIFReadL( abyHeader, 128, 1, fpImage );
     618                 : 
     619                 :     // Upper Left X
     620                 :     float f32Val;
     621                 : 
     622              13 :     f32Val = (float) (adfGeoTransform[0] + 0.5 * adfGeoTransform[1]);
     623              13 :     memcpy( abyHeader + 112, &f32Val, 4 );
     624                 :     
     625                 :     // Upper Left Y
     626              13 :     f32Val = (float) (adfGeoTransform[3] + 0.5 * adfGeoTransform[5]);
     627              13 :     memcpy( abyHeader + 116, &f32Val, 4 );
     628                 :     
     629                 :     // width of pixel
     630              13 :     f32Val = (float) adfGeoTransform[1];
     631              13 :     memcpy( abyHeader + 120, &f32Val, 4 );
     632                 :     
     633                 :     // height of pixel
     634              13 :     f32Val = (float) fabs(adfGeoTransform[5]);
     635              13 :     memcpy( abyHeader + 124, &f32Val, 4 );
     636                 : 
     637              13 :     if( VSIFSeekL( fpImage, 0, SEEK_SET ) != 0 
     638                 :         || VSIFWriteL( abyHeader, 128, 1, fpImage ) != 1 )
     639                 :     {
     640                 :         CPLError( CE_Failure, CPLE_FileIO,
     641               0 :                   "File IO Error writing header with new geotransform." );
     642               0 :         return CE_Failure;
     643                 :     }
     644                 :     else
     645              13 :         return CE_None;
     646                 : }
     647                 : 
     648                 : /************************************************************************/
     649                 : /*                          GetProjectionRef()                          */
     650                 : /*                                                                      */
     651                 : /*      Use PAM coordinate system if available in preference to the     */
     652                 : /*      generally poor value derived from the file itself.              */
     653                 : /************************************************************************/
     654                 : 
     655               0 : const char *LANDataset::GetProjectionRef()
     656                 : 
     657                 : {
     658               0 :     const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
     659                 : 
     660               0 :     if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
     661               0 :         return pszProjection;
     662                 :     else
     663               0 :         return pszPamPrj;
     664                 : }
     665                 : 
     666                 : /************************************************************************/
     667                 : /*                           SetProjection()                            */
     668                 : /************************************************************************/
     669                 : 
     670              13 : CPLErr LANDataset::SetProjection( const char * pszWKT )
     671                 : 
     672                 : {
     673                 :     unsigned char abyHeader[128];
     674                 : 
     675              13 :     VSIFSeekL( fpImage, 0, SEEK_SET );
     676              13 :     VSIFReadL( abyHeader, 128, 1, fpImage );
     677                 : 
     678              13 :     OGRSpatialReference oSRS( pszWKT );
     679                 :     
     680              13 :     GUInt16 nProjCode = 0;
     681                 : 
     682              13 :     if( oSRS.IsGeographic() )
     683              13 :         nProjCode = 0;
     684                 : 
     685               0 :     else if( oSRS.GetUTMZone() != 0 )
     686               0 :         nProjCode = 1;
     687                 : 
     688                 :     // Too bad we have no way of recognising state plane projections. 
     689                 : 
     690                 :     else 
     691                 :     {
     692               0 :         const char *pszProjection = oSRS.GetAttrValue("PROJECTION");
     693                 : 
     694               0 :         if( pszProjection == NULL )
     695                 :             ;
     696               0 :         else if( EQUAL(pszProjection,
     697                 :                        SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     698               0 :             nProjCode = 3;
     699               0 :         else if( EQUAL(pszProjection,
     700                 :                        SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     701               0 :             nProjCode = 4;
     702               0 :         else if( EQUAL(pszProjection,
     703                 :                        SRS_PT_MERCATOR_1SP) )
     704               0 :             nProjCode = 5;
     705               0 :         else if( EQUAL(pszProjection,
     706                 :                        SRS_PT_POLAR_STEREOGRAPHIC) )
     707               0 :             nProjCode = 6;
     708               0 :         else if( EQUAL(pszProjection,
     709                 :                        SRS_PT_POLYCONIC) )
     710               0 :             nProjCode = 7;
     711               0 :         else if( EQUAL(pszProjection,
     712                 :                        SRS_PT_EQUIDISTANT_CONIC) )
     713               0 :             nProjCode = 8;
     714               0 :         else if( EQUAL(pszProjection,
     715                 :                        SRS_PT_TRANSVERSE_MERCATOR) )
     716               0 :             nProjCode = 9;
     717               0 :         else if( EQUAL(pszProjection,
     718                 :                        SRS_PT_STEREOGRAPHIC) )
     719               0 :             nProjCode = 10;
     720               0 :         else if( EQUAL(pszProjection,
     721                 :                        SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     722               0 :             nProjCode = 11;
     723               0 :         else if( EQUAL(pszProjection,
     724                 :                        SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     725               0 :             nProjCode = 12;
     726               0 :         else if( EQUAL(pszProjection,
     727                 :                        SRS_PT_GNOMONIC) )
     728               0 :             nProjCode = 13;
     729               0 :         else if( EQUAL(pszProjection,
     730                 :                        SRS_PT_ORTHOGRAPHIC) )
     731               0 :             nProjCode = 14;
     732                 :         // we don't have GVNP.
     733               0 :         else if( EQUAL(pszProjection,
     734                 :                        SRS_PT_SINUSOIDAL) )
     735               0 :             nProjCode = 16;
     736               0 :         else if( EQUAL(pszProjection,
     737                 :                        SRS_PT_EQUIRECTANGULAR) )
     738               0 :             nProjCode = 17;
     739               0 :         else if( EQUAL(pszProjection,
     740                 :                        SRS_PT_MILLER_CYLINDRICAL) )
     741               0 :             nProjCode = 18;
     742               0 :         else if( EQUAL(pszProjection,
     743                 :                        SRS_PT_VANDERGRINTEN) )
     744               0 :             nProjCode = 19;
     745               0 :         else if( EQUAL(pszProjection,
     746                 :                        SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     747               0 :             nProjCode = 20;
     748                 :     }
     749                 : 
     750              13 :     memcpy( abyHeader + 88, &nProjCode, 2 );
     751                 : 
     752              13 :     VSIFSeekL( fpImage, 0, SEEK_SET );
     753              13 :     VSIFWriteL( abyHeader, 128, 1, fpImage );
     754                 : 
     755              13 :     return GDALPamDataset::SetProjection( pszWKT );
     756                 : }
     757                 : 
     758                 : /************************************************************************/
     759                 : /*                            GetFileList()                             */
     760                 : /************************************************************************/
     761                 : 
     762               0 : char **LANDataset::GetFileList()
     763                 : 
     764                 : {
     765               0 :     char **papszFileList = NULL;
     766                 : 
     767                 :     // Main data file, etc. 
     768               0 :     papszFileList = GDALPamDataset::GetFileList();
     769                 : 
     770               0 :     if( strlen(osSTAFilename) > 0 )
     771               0 :         papszFileList = CSLAddString( papszFileList, osSTAFilename );
     772                 : 
     773               0 :     return papszFileList;
     774                 : }
     775                 : 
     776                 : /************************************************************************/
     777                 : /*                         CheckForStatistics()                         */
     778                 : /************************************************************************/
     779                 : 
     780              22 : void LANDataset::CheckForStatistics()
     781                 : 
     782                 : {
     783                 : /* -------------------------------------------------------------------- */
     784                 : /*      Do we have a statistics file?                                   */
     785                 : /* -------------------------------------------------------------------- */
     786              22 :     osSTAFilename = CPLResetExtension(GetDescription(),"sta");
     787                 : 
     788              22 :     VSILFILE *fpSTA = VSIFOpenL( osSTAFilename, "r" );
     789                 : 
     790              44 :     if( fpSTA == NULL && VSIIsCaseSensitiveFS(osSTAFilename) )
     791                 :     {
     792              22 :         osSTAFilename = CPLResetExtension(GetDescription(),"STA");
     793              22 :         fpSTA = VSIFOpenL( osSTAFilename, "r" );
     794                 :     }
     795                 : 
     796              22 :     if( fpSTA == NULL )
     797                 :     {
     798              22 :         osSTAFilename = "";
     799              22 :         return;
     800                 :     }
     801                 : 
     802                 : /* -------------------------------------------------------------------- */
     803                 : /*      Read it one band at a time.                                     */
     804                 : /* -------------------------------------------------------------------- */
     805                 :     GByte abyBandInfo[1152];
     806                 :     int iBand;
     807                 : 
     808               0 :     for( iBand = 0; iBand < nBands; iBand++ )
     809                 :     {
     810               0 :         if( VSIFReadL( abyBandInfo, 1152, 1, fpSTA ) != 1 )
     811               0 :             break;
     812                 : 
     813               0 :         int nBandNumber = abyBandInfo[7];
     814               0 :         GDALRasterBand *poBand = GetRasterBand(nBandNumber);
     815               0 :         if( poBand == NULL )
     816               0 :             break;
     817                 : 
     818                 :         float fMean, fStdDev;
     819                 :         GInt16 nMin, nMax;
     820                 : 
     821               0 :         if( poBand->GetRasterDataType() != GDT_Byte )
     822                 :         {
     823               0 :             memcpy( &nMin, abyBandInfo + 28, 2 );
     824               0 :             memcpy( &nMax, abyBandInfo + 30, 2 );
     825                 :             CPL_LSBPTR16( &nMin );
     826                 :             CPL_LSBPTR16( &nMax );
     827                 :         }
     828                 :         else
     829                 :         {
     830               0 :             nMin = abyBandInfo[9];
     831               0 :             nMax = abyBandInfo[8];
     832                 :         }
     833                 :         
     834               0 :         memcpy( &fMean, abyBandInfo + 12, 4 );
     835               0 :         memcpy( &fStdDev, abyBandInfo + 24, 4 );
     836                 :         CPL_LSBPTR32( &fMean );
     837                 :         CPL_LSBPTR32( &fStdDev );
     838                 :         
     839               0 :         poBand->SetStatistics( nMin, nMax, fMean, fStdDev );
     840                 :     }
     841                 :     
     842               0 :     VSIFCloseL( fpSTA );
     843                 : }
     844                 : 
     845                 : /************************************************************************/
     846                 : /*                               Create()                               */
     847                 : /************************************************************************/
     848                 : 
     849              49 : GDALDataset *LANDataset::Create( const char * pszFilename,
     850                 :                                  int nXSize, int nYSize, int nBands,
     851                 :                                  GDALDataType eType,
     852                 :                                  char ** papszOptions )
     853                 : 
     854                 : {
     855              49 :     if( eType != GDT_Byte && eType != GDT_Int16 )
     856                 :     {
     857                 :         CPLError( CE_Failure, CPLE_AppDefined,
     858                 :                   "Attempt to create .GIS file with unsupported data type '%s'.",
     859              27 :                   GDALGetDataTypeName( eType ) );
     860              27 :         return NULL;
     861                 :     }
     862                 : 
     863                 : /* -------------------------------------------------------------------- */
     864                 : /*      Try to create the file.                                         */
     865                 : /* -------------------------------------------------------------------- */
     866                 :     VSILFILE  *fp;
     867                 : 
     868              22 :     fp = VSIFOpenL( pszFilename, "wb" );
     869                 : 
     870              22 :     if( fp == NULL )
     871                 :     {
     872                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     873                 :                   "Attempt to create file `%s' failed.\n",
     874               8 :                   pszFilename );
     875               8 :         return NULL;
     876                 :     }
     877                 : 
     878                 : /* -------------------------------------------------------------------- */
     879                 : /*      Write out the header.                                           */
     880                 : /* -------------------------------------------------------------------- */
     881                 :     unsigned char abyHeader[128];
     882                 :     GInt16  n16Val;
     883                 :     GInt32  n32Val;
     884                 : 
     885              14 :     memset( abyHeader, 0, sizeof(abyHeader) );
     886                 :     
     887              14 :     memcpy( abyHeader + 0, "HEAD74", 6 );
     888                 : 
     889                 :     // Pixel type
     890              14 :     if( eType == GDT_Byte ) // do we want 4bit?
     891              11 :         n16Val = 0;
     892                 :     else
     893               3 :         n16Val = 2;
     894              14 :     memcpy( abyHeader + 6, &n16Val, 2 );
     895                 : 
     896                 :     // Number of Bands.
     897              14 :     n16Val = (GInt16) nBands;
     898              14 :     memcpy( abyHeader + 8, &n16Val, 2 );
     899                 : 
     900                 :     // Unknown (6)
     901                 : 
     902                 :     // Width
     903              14 :     n32Val = nXSize;
     904              14 :     memcpy( abyHeader + 16, &n32Val, 4 );
     905                 :     
     906                 :     // Height
     907              14 :     n32Val = nYSize;
     908              14 :     memcpy( abyHeader + 20, &n32Val, 4 );
     909                 : 
     910                 :     // X Start (4)
     911                 :     // Y Start (4)
     912                 : 
     913                 :     // Unknown (56)
     914                 : 
     915                 :     // Coordinate System
     916              14 :     n16Val = 0;
     917              14 :     memcpy( abyHeader + 88, &n16Val, 2 );
     918                 : 
     919                 :     // Classes in coverage 
     920              14 :     n16Val = 0;
     921              14 :     memcpy( abyHeader + 90, &n16Val, 2 );
     922                 : 
     923                 :     // Unknown (14)
     924                 : 
     925                 :     // Area Unit
     926              14 :     n16Val = 0;
     927              14 :     memcpy( abyHeader + 106, &n16Val, 2 );
     928                 : 
     929                 :     // Pixel Area
     930                 :     float f32Val;
     931                 : 
     932              14 :     f32Val = 0.0f;
     933              14 :     memcpy( abyHeader + 108, &f32Val, 4 );
     934                 : 
     935                 :     // Upper Left X
     936              14 :     f32Val = 0.5f;
     937              14 :     memcpy( abyHeader + 112, &f32Val, 4 );
     938                 :     
     939                 :     // Upper Left Y
     940              14 :     f32Val = (float) (nYSize - 0.5);
     941              14 :     memcpy( abyHeader + 116, &f32Val, 4 );
     942                 :     
     943                 :     // width of pixel
     944              14 :     f32Val = 1.0f;
     945              14 :     memcpy( abyHeader + 120, &f32Val, 4 );
     946                 :     
     947                 :     // height of pixel
     948              14 :     f32Val = 1.0f;
     949              14 :     memcpy( abyHeader + 124, &f32Val, 4 );
     950                 : 
     951              14 :     VSIFWriteL( abyHeader, sizeof(abyHeader), 1, fp );
     952                 : 
     953                 : /* -------------------------------------------------------------------- */
     954                 : /*      Extend the file to the target size.                             */
     955                 : /* -------------------------------------------------------------------- */
     956                 :     vsi_l_offset nImageBytes;
     957                 : 
     958              14 :     if( eType != GDT_Byte )
     959               3 :         nImageBytes = nXSize * (vsi_l_offset) nYSize * 2;
     960                 :     else
     961              11 :         nImageBytes = nXSize * (vsi_l_offset) nYSize;
     962                 : 
     963              14 :     memset( abyHeader, 0, sizeof(abyHeader) );
     964                 :     
     965             823 :     while( nImageBytes > 0 )
     966                 :     {
     967             795 :         vsi_l_offset nWriteThisTime = MIN(nImageBytes,sizeof(abyHeader));
     968                 :         
     969             795 :         if( VSIFWriteL( abyHeader, 1, (size_t)nWriteThisTime, fp ) 
     970                 :             != nWriteThisTime )
     971                 :         {
     972               0 :             VSIFCloseL( fp );
     973                 :             CPLError( CE_Failure, CPLE_FileIO,
     974               0 :                       "Failed to write whole Istar file." );
     975               0 :             return NULL;
     976                 :         }
     977             795 :         nImageBytes -= nWriteThisTime;
     978                 :     }
     979                 : 
     980              14 :     VSIFCloseL( fp );
     981                 : 
     982              14 :     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     983                 : }
     984                 : 
     985                 : /************************************************************************/
     986                 : /*                          GDALRegister_LAN()                          */
     987                 : /************************************************************************/
     988                 : 
     989             582 : void GDALRegister_LAN()
     990                 : 
     991                 : {
     992                 :     GDALDriver  *poDriver;
     993                 : 
     994             582 :     if( GDALGetDriverByName( "LAN" ) == NULL )
     995                 :     {
     996             561 :         poDriver = new GDALDriver();
     997                 :         
     998             561 :         poDriver->SetDescription( "LAN" );
     999                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1000             561 :                                    "Erdas .LAN/.GIS" );
    1001                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1002             561 :                                    "frmt_various.html#LAN" );
    1003             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1004                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1005             561 :                                    "Byte Int16" );
    1006                 :         
    1007             561 :         poDriver->pfnOpen = LANDataset::Open;
    1008             561 :         poDriver->pfnCreate = LANDataset::Create;
    1009                 : 
    1010             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1011                 :     }
    1012             582 : }
    1013                 : 

Generated by: LCOV version 1.7