LTP GCOV extension - code coverage report
Current view: directory - frmts/raw - genbindataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 258
Code covered: 62.8 % Executed lines: 162

       1                 : /******************************************************************************
       2                 :  * $Id: ehdrdataset.cpp 12350 2007-10-08 17:41:32Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL
       5                 :  * Purpose:  Generic Binary format driver (.hdr but not ESRI .hdr!)
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
      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 "ogr_spatialref.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ehdrdataset.cpp 12350 2007-10-08 17:41:32Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void  GDALRegister_GenBin(void);
      38                 : CPL_C_END
      39                 : 
      40                 : /* ==================================================================== */
      41                 : /*      Table relating USGS and ESRI state plane zones.                 */
      42                 : /* ==================================================================== */
      43                 : static const int anUsgsEsriZones[] =
      44                 : {
      45                 :   101, 3101,
      46                 :   102, 3126,
      47                 :   201, 3151,
      48                 :   202, 3176,
      49                 :   203, 3201,
      50                 :   301, 3226,
      51                 :   302, 3251,
      52                 :   401, 3276,
      53                 :   402, 3301,
      54                 :   403, 3326,
      55                 :   404, 3351,
      56                 :   405, 3376,
      57                 :   406, 3401,
      58                 :   407, 3426,
      59                 :   501, 3451,
      60                 :   502, 3476,
      61                 :   503, 3501,
      62                 :   600, 3526,
      63                 :   700, 3551,
      64                 :   901, 3601,
      65                 :   902, 3626,
      66                 :   903, 3576,
      67                 :  1001, 3651,
      68                 :  1002, 3676,
      69                 :  1101, 3701,
      70                 :  1102, 3726,
      71                 :  1103, 3751,
      72                 :  1201, 3776,
      73                 :  1202, 3801,
      74                 :  1301, 3826,
      75                 :  1302, 3851,
      76                 :  1401, 3876,
      77                 :  1402, 3901,
      78                 :  1501, 3926,
      79                 :  1502, 3951,
      80                 :  1601, 3976,
      81                 :  1602, 4001,
      82                 :  1701, 4026,
      83                 :  1702, 4051,
      84                 :  1703, 6426,
      85                 :  1801, 4076,
      86                 :  1802, 4101,
      87                 :  1900, 4126,
      88                 :  2001, 4151,
      89                 :  2002, 4176,
      90                 :  2101, 4201,
      91                 :  2102, 4226,
      92                 :  2103, 4251,
      93                 :  2111, 6351,
      94                 :  2112, 6376,
      95                 :  2113, 6401,
      96                 :  2201, 4276,
      97                 :  2202, 4301,
      98                 :  2203, 4326,
      99                 :  2301, 4351,
     100                 :  2302, 4376,
     101                 :  2401, 4401,
     102                 :  2402, 4426,
     103                 :  2403, 4451,
     104                 :  2500,    0,
     105                 :  2501, 4476,
     106                 :  2502, 4501,
     107                 :  2503, 4526,
     108                 :  2600,    0,
     109                 :  2601, 4551,
     110                 :  2602, 4576,
     111                 :  2701, 4601,
     112                 :  2702, 4626,
     113                 :  2703, 4651,
     114                 :  2800, 4676,
     115                 :  2900, 4701,
     116                 :  3001, 4726,
     117                 :  3002, 4751,
     118                 :  3003, 4776,
     119                 :  3101, 4801,
     120                 :  3102, 4826,
     121                 :  3103, 4851,
     122                 :  3104, 4876,
     123                 :  3200, 4901,
     124                 :  3301, 4926,
     125                 :  3302, 4951,
     126                 :  3401, 4976,
     127                 :  3402, 5001,
     128                 :  3501, 5026,
     129                 :  3502, 5051,
     130                 :  3601, 5076,
     131                 :  3602, 5101,
     132                 :  3701, 5126,
     133                 :  3702, 5151,
     134                 :  3800, 5176,
     135                 :  3900,    0,
     136                 :  3901, 5201,
     137                 :  3902, 5226,
     138                 :  4001, 5251,
     139                 :  4002, 5276,
     140                 :  4100, 5301,
     141                 :  4201, 5326,
     142                 :  4202, 5351,
     143                 :  4203, 5376,
     144                 :  4204, 5401,
     145                 :  4205, 5426,
     146                 :  4301, 5451,
     147                 :  4302, 5476,
     148                 :  4303, 5501,
     149                 :  4400, 5526,
     150                 :  4501, 5551,
     151                 :  4502, 5576,
     152                 :  4601, 5601,
     153                 :  4602, 5626,
     154                 :  4701, 5651,
     155                 :  4702, 5676,
     156                 :  4801, 5701,
     157                 :  4802, 5726,
     158                 :  4803, 5751,
     159                 :  4901, 5776,
     160                 :  4902, 5801,
     161                 :  4903, 5826,
     162                 :  4904, 5851,
     163                 :  5001, 6101,
     164                 :  5002, 6126,
     165                 :  5003, 6151,
     166                 :  5004, 6176,
     167                 :  5005, 6201,
     168                 :  5006, 6226,
     169                 :  5007, 6251,
     170                 :  5008, 6276,
     171                 :  5009, 6301,
     172                 :  5010, 6326,
     173                 :  5101, 5876,
     174                 :  5102, 5901,
     175                 :  5103, 5926,
     176                 :  5104, 5951,
     177                 :  5105, 5976,
     178                 :  5201, 6001,
     179                 :  5200, 6026,
     180                 :  5200, 6076,
     181                 :  5201, 6051,
     182                 :  5202, 6051,
     183                 :  5300,    0,
     184                 :  5400,    0
     185                 : };
     186                 : 
     187                 : /************************************************************************/
     188                 : /* ==================================================================== */
     189                 : /*        GenBinDataset       */
     190                 : /* ==================================================================== */
     191                 : /************************************************************************/
     192                 : 
     193                 : class GenBinDataset : public RawDataset
     194                 : {
     195                 :     friend class GenBinBitRasterBand;
     196                 : 
     197                 :     FILE  *fpImage; // image data file.
     198                 : 
     199                 :     int         bGotTransform;
     200                 :     double      adfGeoTransform[6];
     201                 :     char       *pszProjection;
     202                 : 
     203                 :     int         bHDRDirty;
     204                 :     char      **papszHDR;
     205                 : 
     206                 :     void        ParseCoordinateSystem( char ** );
     207                 : 
     208                 :   public:
     209                 :     GenBinDataset();
     210                 :     ~GenBinDataset();
     211                 :     
     212                 :     virtual CPLErr GetGeoTransform( double * padfTransform );
     213                 :     virtual const char *GetProjectionRef(void);
     214                 :     
     215                 :     virtual char **GetFileList();
     216                 : 
     217                 :     static GDALDataset *Open( GDALOpenInfo * );
     218                 : };
     219                 : 
     220                 : /************************************************************************/
     221                 : /* ==================================================================== */
     222                 : /*                       GenBinBitRasterBand                            */
     223                 : /* ==================================================================== */
     224                 : /************************************************************************/
     225                 : 
     226                 : class GenBinBitRasterBand : public GDALPamRasterBand
     227               0 : {
     228                 :     int            nBits;
     229                 :     long           nStartBit;
     230                 :     int            nPixelOffsetBits;
     231                 :     int            nLineOffsetBits;
     232                 : 
     233                 :   public:
     234                 :     GenBinBitRasterBand( GenBinDataset *poDS, int nBits );
     235                 : 
     236                 :     virtual CPLErr IReadBlock( int, int, void * );
     237                 : };
     238                 : 
     239                 : /************************************************************************/
     240                 : /*                        GenBinBitRasterBand()                         */
     241                 : /************************************************************************/
     242                 : 
     243               0 : GenBinBitRasterBand::GenBinBitRasterBand( GenBinDataset *poDS, int nBitsIn )
     244                 : {
     245                 :     SetMetadataItem( "NBITS", 
     246                 :                      CPLString().Printf("%d",nBitsIn), 
     247               0 :                      "IMAGE_STRUCTURE" );
     248                 : 
     249               0 :     this->poDS = poDS;
     250               0 :     nBits = nBitsIn;
     251               0 :     nBand = 1;
     252                 : 
     253               0 :     eDataType = GDT_Byte;
     254                 : 
     255               0 :     nBlockXSize = poDS->nRasterXSize;
     256               0 :     nBlockYSize = 1;
     257               0 : }
     258                 : 
     259                 : /************************************************************************/
     260                 : /*                             IReadBlock()                             */
     261                 : /************************************************************************/
     262                 : 
     263                 : CPLErr GenBinBitRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     264               0 :                                         void * pImage )
     265                 : 
     266                 : {
     267               0 :     GenBinDataset *poGDS = (GenBinDataset *) poDS;
     268                 :     vsi_l_offset   nLineStart;
     269                 :     unsigned int   nLineBytes;
     270                 :     int            iBitOffset;
     271                 :     GByte         *pabyBuffer;
     272                 : 
     273                 : /* -------------------------------------------------------------------- */
     274                 : /*      Establish desired position.                                     */
     275                 : /* -------------------------------------------------------------------- */
     276               0 :     nLineStart = (((vsi_l_offset)nBlockXSize) * nBlockYOff * nBits) / 8;
     277               0 :     iBitOffset = (int)((((vsi_l_offset)nBlockXSize) * nBlockYOff * nBits) % 8);
     278               0 :     nLineBytes = (int) ((((vsi_l_offset)nBlockXSize) * (nBlockYOff+1) * nBits + 7) / 8 - nLineStart);
     279                 : 
     280                 : /* -------------------------------------------------------------------- */
     281                 : /*      Read data into buffer.                                          */
     282                 : /* -------------------------------------------------------------------- */
     283               0 :     pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
     284                 : 
     285               0 :     if( VSIFSeekL( poGDS->fpImage, nLineStart, SEEK_SET ) != 0 
     286                 :         || VSIFReadL( pabyBuffer, 1, nLineBytes, poGDS->fpImage) != nLineBytes )
     287                 :     {
     288                 :         CPLError( CE_Failure, CPLE_FileIO,
     289                 :                   "Failed to read %u bytes at offset %lu.\n%s",
     290                 :                   nLineBytes, (unsigned long)nLineStart, 
     291               0 :                   VSIStrerror( errno ) );
     292               0 :         return CE_Failure;
     293                 :     }
     294                 : 
     295                 : /* -------------------------------------------------------------------- */
     296                 : /*      Copy data, promoting to 8bit.                                   */
     297                 : /* -------------------------------------------------------------------- */
     298                 :     int iX;
     299                 : 
     300               0 :     if( nBits == 1 )
     301                 :     {
     302               0 :         for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
     303                 :         {
     304               0 :             if( pabyBuffer[iBitOffset>>3]  & (0x80 >>(iBitOffset & 7)) )
     305               0 :                 ((GByte *) pImage)[iX] = 1;
     306                 :             else
     307               0 :                 ((GByte *) pImage)[iX] = 0;
     308                 :         }
     309                 :     }
     310               0 :     else if( nBits == 2 )
     311                 :     {
     312               0 :         for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
     313                 :         {
     314                 :             ((GByte *) pImage)[iX] = 
     315               0 :                 ((pabyBuffer[iBitOffset>>3]) >> (6-(iBitOffset&0x7)) & 0x3);
     316                 :         }
     317                 :     }
     318               0 :     else if( nBits == 4 )
     319                 :     {
     320               0 :         for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
     321                 :         {
     322               0 :             if( iBitOffset == 0 )
     323               0 :                 ((GByte *) pImage)[iX] = (pabyBuffer[iBitOffset>>3]) >> 4;
     324                 :             else
     325               0 :                 ((GByte *) pImage)[iX] = (pabyBuffer[iBitOffset>>3]) & 0xf;
     326                 :         }
     327                 :     }
     328                 :     else
     329               0 :         CPLAssert( FALSE );
     330                 : 
     331               0 :     CPLFree( pabyBuffer );
     332                 : 
     333               0 :     return CE_None;
     334                 : }
     335                 : 
     336                 : /************************************************************************/
     337                 : /* ==================================================================== */
     338                 : /*        GenBinDataset       */
     339                 : /* ==================================================================== */
     340                 : /************************************************************************/
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                            GenBinDataset()                             */
     344                 : /************************************************************************/
     345                 : 
     346               1 : GenBinDataset::GenBinDataset()
     347                 : {
     348               1 :     fpImage = NULL;
     349               1 :     pszProjection = CPLStrdup("");
     350               1 :     bGotTransform = FALSE;
     351               1 :     adfGeoTransform[0] = 0.0;
     352               1 :     adfGeoTransform[1] = 1.0;
     353               1 :     adfGeoTransform[2] = 0.0;
     354               1 :     adfGeoTransform[3] = 0.0;
     355               1 :     adfGeoTransform[4] = 0.0;
     356               1 :     adfGeoTransform[5] = 1.0;
     357               1 :     papszHDR = NULL;
     358               1 : }
     359                 : 
     360                 : /************************************************************************/
     361                 : /*                            ~GenBinDataset()                            */
     362                 : /************************************************************************/
     363                 : 
     364               1 : GenBinDataset::~GenBinDataset()
     365                 : 
     366                 : {
     367               1 :     FlushCache();
     368                 : 
     369               1 :     if( fpImage != NULL )
     370               1 :         VSIFCloseL( fpImage );
     371                 : 
     372               1 :     CPLFree( pszProjection );
     373               1 :     CSLDestroy( papszHDR );
     374               1 : }
     375                 : 
     376                 : /************************************************************************/
     377                 : /*                          GetProjectionRef()                          */
     378                 : /************************************************************************/
     379                 : 
     380               1 : const char *GenBinDataset::GetProjectionRef()
     381                 : 
     382                 : {
     383               1 :     if (pszProjection && strlen(pszProjection) > 0)
     384               1 :         return pszProjection;
     385                 : 
     386               0 :     return GDALPamDataset::GetProjectionRef();
     387                 : }
     388                 : 
     389                 : /************************************************************************/
     390                 : /*                          GetGeoTransform()                           */
     391                 : /************************************************************************/
     392                 : 
     393               1 : CPLErr GenBinDataset::GetGeoTransform( double * padfTransform )
     394                 : 
     395                 : {
     396               1 :     if( bGotTransform )
     397                 :     {
     398               1 :         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     399               1 :         return CE_None;
     400                 :     }
     401                 :     else
     402                 :     {
     403               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     404                 :     }
     405                 : }
     406                 : 
     407                 : /************************************************************************/
     408                 : /*                            GetFileList()                             */
     409                 : /************************************************************************/
     410                 : 
     411               0 : char **GenBinDataset::GetFileList()
     412                 : 
     413                 : {
     414               0 :     CPLString osPath = CPLGetPath( GetDescription() );
     415               0 :     CPLString osName = CPLGetBasename( GetDescription() );
     416               0 :     char **papszFileList = NULL;
     417                 : 
     418                 :     // Main data file, etc. 
     419               0 :     papszFileList = GDALPamDataset::GetFileList();
     420                 : 
     421                 :     // Header file.
     422               0 :     CPLString osFilename = CPLFormCIFilename( osPath, osName, "hdr" );
     423               0 :     papszFileList = CSLAddString( papszFileList, osFilename );
     424                 : 
     425               0 :     return papszFileList;
     426                 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                       ParseCoordinateSystem()                        */
     430                 : /************************************************************************/
     431                 : 
     432               1 : void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
     433                 : 
     434                 : {
     435               1 :     const char *pszProjName = CSLFetchNameValue( papszHdr, "PROJECTION_NAME" );
     436               1 :     OGRSpatialReference oSRS;
     437                 : 
     438               1 :     if( pszProjName == NULL )
     439               0 :         return;
     440                 : 
     441                 : /* -------------------------------------------------------------------- */
     442                 : /*      Translate zone and parameters into numeric form.                */
     443                 : /* -------------------------------------------------------------------- */
     444               1 :     int nZone = 0;
     445                 :     double adfProjParms[15];
     446               1 :     const char *pszUnits = CSLFetchNameValue( papszHdr, "MAP_UNITS" );
     447               1 :     const char *pszDatumName = CSLFetchNameValue( papszHdr, "DATUM_NAME" );
     448                 : 
     449               1 :     if( CSLFetchNameValue( papszHdr, "PROJECTION_ZONE" ) )
     450               1 :         nZone = atoi(CSLFetchNameValue( papszHdr, "PROJECTION_ZONE" ));
     451                 : 
     452               1 :     memset( adfProjParms, 0, sizeof(adfProjParms) );
     453               1 :     if( CSLFetchNameValue( papszHdr, "PROJECTION_PARAMETERS" ) )
     454                 :     {
     455                 :         int i;
     456                 :         char **papszTokens = CSLTokenizeString( 
     457               1 :             CSLFetchNameValue( papszHdr, "PROJECTION_PARAMETERS" ) );
     458                 : 
     459              15 :         for( i = 0; i < 15 && papszTokens[i] != NULL; i++ )
     460              14 :             adfProjParms[i] = CPLAtofM( papszTokens[i] );
     461                 : 
     462               1 :         CSLDestroy( papszTokens );
     463                 :     }
     464                 : 
     465                 : /* -------------------------------------------------------------------- */
     466                 : /*      Handle projections.                                             */
     467                 : /* -------------------------------------------------------------------- */
     468               1 :     if( EQUAL(pszProjName,"UTM") && nZone != 0 )
     469                 :     {
     470                 :         // honestly, I'm just getting that the negative zone for 
     471                 :         // southern hemisphere is used.
     472               0 :         oSRS.SetUTM( ABS(nZone), nZone > 0 );
     473                 :     }
     474                 : 
     475               1 :     else if( EQUAL(pszProjName,"State Plane") && nZone != 0 )
     476                 :     {
     477               1 :         int   nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
     478                 :         int   i;
     479               1 :         double          dfUnits = 0.0;
     480                 :         
     481             109 :         for( i = 0; i < nPairs; i++ )
     482                 :         {
     483             109 :             if( anUsgsEsriZones[i*2+1] == nZone )
     484                 :             {
     485               1 :                 nZone = anUsgsEsriZones[i*2];
     486               1 :                 break;
     487                 :             }
     488                 :             
     489                 :         }
     490                 : 
     491               1 :         if( EQUAL(pszUnits,"feet") )
     492               1 :             dfUnits = CPLAtofM(SRS_UL_US_FOOT_CONV);
     493               0 :         else if( EQUALN(pszUnits,"MET",3) )
     494               0 :             dfUnits = 1.0;
     495                 :         else
     496               0 :             pszUnits = NULL;
     497                 : 
     498                 :         oSRS.SetStatePlane( ABS(nZone), 
     499                 :                             pszDatumName==NULL || !EQUAL(pszDatumName,"NAD27"),
     500               1 :                             pszUnits, dfUnits );
     501                 :     }
     502                 : 
     503                 : /* -------------------------------------------------------------------- */
     504                 : /*      Setup the geographic coordinate system.                         */
     505                 : /* -------------------------------------------------------------------- */
     506               1 :     if( oSRS.GetAttrNode( "GEOGCS" ) == NULL )
     507                 :     {
     508               0 :         if( pszDatumName != NULL 
     509                 :             && oSRS.SetWellKnownGeogCS( pszDatumName ) == OGRERR_NONE )
     510                 :         {
     511                 :             // good
     512                 :         }
     513               0 :         else if( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ) 
     514                 :                  && CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS" )
     515                 :                  && CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS" ) )
     516                 :         {
     517               0 :             double dfSemiMajor = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS"));
     518               0 :             double dfSemiMinor = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS"));
     519                 :             
     520                 :             oSRS.SetGeogCS( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
     521                 :                             CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
     522                 :                             CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
     523                 :                             dfSemiMajor, 
     524               0 :                             1.0 / (1.0 - dfSemiMinor/dfSemiMajor) );
     525                 :         }
     526                 :         else // fallback default.
     527               0 :             oSRS.SetWellKnownGeogCS( "WGS84" );
     528                 :     }
     529                 : 
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Convert to WKT.                                                 */
     532                 : /* -------------------------------------------------------------------- */
     533               1 :     CPLFree( pszProjection );
     534               1 :     pszProjection = NULL;
     535                 :     
     536               1 :     oSRS.exportToWkt( &pszProjection );
     537                 : }
     538                 : 
     539                 : /************************************************************************/
     540                 : /*                                Open()                                */
     541                 : /************************************************************************/
     542                 : 
     543            9796 : GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
     544                 : 
     545                 : {
     546                 :     int   i, bSelectedHDR;
     547                 :     
     548                 : /* -------------------------------------------------------------------- */
     549                 : /*  We assume the user is pointing to the binary (ie. .bil) file. */
     550                 : /* -------------------------------------------------------------------- */
     551            9796 :     if( poOpenInfo->nHeaderBytes < 2 )
     552            9304 :         return NULL;
     553                 : 
     554                 : /* -------------------------------------------------------------------- */
     555                 : /*      Now we need to tear apart tfhe filename to form a .HDR           */
     556                 : /*      filename.                                                       */
     557                 : /* -------------------------------------------------------------------- */
     558             492 :     CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
     559             492 :     CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
     560             492 :     CPLString osHDRFilename;
     561                 : 
     562             492 :     if( poOpenInfo->papszSiblingFiles )
     563                 :     {
     564                 :         int iFile = CSLFindString(poOpenInfo->papszSiblingFiles, 
     565             450 :                                   CPLFormFilename( NULL, osName, "hdr" ) );
     566             450 :         if( iFile < 0 ) // return if there is no corresponding .hdr file
     567             421 :             return NULL;
     568                 : 
     569                 :         osHDRFilename = 
     570                 :             CPLFormFilename( osPath, poOpenInfo->papszSiblingFiles[iFile],
     571              29 :                              NULL );
     572                 :     }
     573                 :     else
     574                 :     {
     575              42 :         osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
     576                 :     }
     577                 : 
     578              71 :     bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
     579                 : 
     580                 : /* -------------------------------------------------------------------- */
     581                 : /*      Do we have a .hdr file?                                         */
     582                 : /* -------------------------------------------------------------------- */
     583                 :     FILE  *fp;
     584                 : 
     585              71 :     fp = VSIFOpenL( osHDRFilename, "r" );
     586                 :     
     587              71 :     if( fp == NULL )
     588                 :     {
     589              42 :         return NULL;
     590                 :     }
     591                 : 
     592                 : /* -------------------------------------------------------------------- */
     593                 : /*      Read a chunk to skim for expected keywords.                     */
     594                 : /* -------------------------------------------------------------------- */
     595                 :     char achHeader[1000];
     596                 :     
     597              29 :     int nRead = VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp );
     598              29 :     achHeader[nRead] = '\0';
     599              29 :     VSIFSeekL( fp, 0, SEEK_SET );
     600                 : 
     601              29 :     if( strstr( achHeader, "BANDS:" ) == NULL 
     602                 :         || strstr( achHeader, "ROWS:" ) == NULL 
     603                 :         || strstr( achHeader, "COLS:" ) == NULL )
     604                 :     {
     605              28 :         VSIFCloseL( fp );
     606              28 :         return NULL;
     607                 :     }
     608                 : 
     609                 : /* -------------------------------------------------------------------- */
     610                 : /*      Has the user selected the .hdr file to open?                    */
     611                 : /* -------------------------------------------------------------------- */
     612               1 :     if( bSelectedHDR )
     613                 :     {
     614                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     615                 :                   "The selected file is an Generic Binary header file, but to\n"
     616                 :                   "open Generic Binary datasets, the data file should be selected\n"
     617                 :                   "instead of the .hdr file.  Please try again selecting\n"
     618                 :                   "the raw data file corresponding to the header file: %s\n", 
     619               0 :                   poOpenInfo->pszFilename );
     620               0 :         VSIFCloseL( fp );
     621               0 :         return NULL;
     622                 :     }
     623                 : 
     624                 : /* -------------------------------------------------------------------- */
     625                 : /*      Read the .hdr file.                                             */
     626                 : /* -------------------------------------------------------------------- */
     627               1 :     char **papszHdr = NULL;
     628               1 :     const char *pszLine = CPLReadLineL( fp );
     629                 : 
     630              24 :     while( pszLine != NULL )
     631                 :     {
     632              22 :         if( EQUAL(pszLine,"PROJECTION_PARAMETERS:") )
     633                 :         {
     634               1 :             CPLString osPP = pszLine;
     635                 : 
     636               1 :             pszLine = CPLReadLineL(fp);
     637              17 :             while( pszLine != NULL 
     638                 :                    && (*pszLine == '\t' || *pszLine == ' ') )
     639                 :             {
     640              15 :                 osPP += pszLine;
     641              15 :                 pszLine = CPLReadLineL(fp);
     642                 :             }
     643               1 :             papszHdr = CSLAddString( papszHdr, osPP );
     644                 :         }
     645                 :         else
     646                 :         {
     647                 :             char *pszName;
     648              21 :             CPLString osValue;
     649                 :             
     650              21 :             osValue = CPLParseNameValue( pszLine, &pszName );
     651              21 :             osValue.Trim();
     652                 :             
     653              21 :             papszHdr = CSLSetNameValue( papszHdr, pszName, osValue );
     654              21 :             CPLFree( pszName );
     655                 :             
     656              21 :             pszLine = CPLReadLineL( fp );
     657                 :         }
     658                 :     }
     659                 : 
     660               1 :     VSIFCloseL( fp );
     661                 : 
     662               1 :     if( CSLFetchNameValue( papszHdr, "COLS" ) == NULL
     663                 :         || CSLFetchNameValue( papszHdr, "ROWS" ) == NULL
     664                 :         || CSLFetchNameValue( papszHdr, "BANDS" ) == NULL )
     665                 :     {
     666               0 :         CSLDestroy( papszHdr );
     667               0 :         return NULL;
     668                 :     }
     669                 : 
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*      Create a corresponding GDALDataset.                             */
     672                 : /* -------------------------------------------------------------------- */
     673                 :     GenBinDataset     *poDS;
     674                 : 
     675               1 :     poDS = new GenBinDataset();
     676                 : 
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Capture some information from the file that is of interest.     */
     679                 : /* -------------------------------------------------------------------- */
     680               2 :     int nBands = atoi(CSLFetchNameValue( papszHdr, "BANDS" ));
     681                 : 
     682               1 :     poDS->nRasterXSize = atoi(CSLFetchNameValue( papszHdr, "COLS" ));
     683               1 :     poDS->nRasterYSize = atoi(CSLFetchNameValue( papszHdr, "ROWS" ));
     684               1 :     poDS->papszHDR = papszHdr;
     685                 : 
     686               1 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
     687                 :         !GDALCheckBandCount(nBands, FALSE))
     688                 :     {
     689               0 :         delete poDS;
     690             492 :         return NULL;
     691                 :     }
     692                 : 
     693                 : /* -------------------------------------------------------------------- */
     694                 : /*      Open target binary file.                                        */
     695                 : /* -------------------------------------------------------------------- */
     696               1 :     if( poOpenInfo->eAccess == GA_ReadOnly )
     697               1 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     698                 :     else
     699               0 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
     700                 : 
     701               1 :     if( poDS->fpImage == NULL )
     702                 :     {
     703                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     704                 :                   "Failed to open %s with write permission.\n%s", 
     705               0 :                   osName.c_str(), VSIStrerror( errno ) );
     706               0 :         delete poDS;
     707               0 :         return NULL;
     708                 :     }
     709                 : 
     710               1 :     poDS->eAccess = poOpenInfo->eAccess;
     711                 : 
     712                 : /* -------------------------------------------------------------------- */
     713                 : /*      Figure out the data type.                                       */
     714                 : /* -------------------------------------------------------------------- */
     715               1 :     const char *pszDataType = CSLFetchNameValue( papszHdr, "DATATYPE" );
     716                 :     GDALDataType eDataType;
     717               1 :     int nBits = -1; // Only needed for partial byte types
     718                 : 
     719               1 :     if( pszDataType == NULL )
     720               0 :         eDataType = GDT_Byte;
     721               1 :     else if( EQUAL(pszDataType,"U16") )
     722               0 :         eDataType = GDT_UInt16;
     723               1 :     else if( EQUAL(pszDataType,"S16") )
     724               0 :         eDataType = GDT_Int16;
     725               1 :     else if( EQUAL(pszDataType,"F32") )
     726               0 :         eDataType = GDT_Float32;
     727               1 :     else if( EQUAL(pszDataType,"F64") )
     728               0 :         eDataType = GDT_Float64;
     729               1 :     else if( EQUAL(pszDataType,"U8") )
     730               1 :         eDataType = GDT_Byte;
     731               0 :     else if( EQUAL(pszDataType,"U1") 
     732                 :              || EQUAL(pszDataType,"U2")
     733                 :              || EQUAL(pszDataType,"U4") )
     734                 :     {
     735               0 :         nBits = atoi(pszDataType+1);
     736               0 :         eDataType = GDT_Byte;
     737               0 :         if( nBands != 1 )
     738                 :         {
     739                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     740               0 :                       "Only one band is supported for U1/U2/U4 data type" );
     741               0 :             delete poDS;
     742               0 :             return NULL;
     743                 :         }
     744                 :     }
     745                 :     else
     746                 :     {
     747               0 :         eDataType = GDT_Byte;
     748                 :         CPLError( CE_Warning, CPLE_AppDefined,
     749                 :                   "DATATYPE=%s not recognised, assuming Byte.",
     750               0 :                   pszDataType );
     751                 :     }
     752                 : 
     753                 : /* -------------------------------------------------------------------- */
     754                 : /*      Do we need byte swapping?                                       */
     755                 : /* -------------------------------------------------------------------- */
     756               1 :     const char *pszBYTE_ORDER = CSLFetchNameValue(papszHdr,"BYTE_ORDER");
     757               1 :     int bNative = TRUE;
     758                 :     
     759               1 :     if( pszBYTE_ORDER != NULL )
     760                 :     {
     761                 : #ifdef CPL_LSB
     762               1 :         bNative = EQUALN(pszBYTE_ORDER,"LSB",3);
     763                 : #else
     764                 :         bNative = !EQUALN(pszBYTE_ORDER,"LSB",3);
     765                 : #endif        
     766                 :     }
     767                 : 
     768                 : /* -------------------------------------------------------------------- */
     769                 : /*  Work out interleaving info.         */
     770                 : /* -------------------------------------------------------------------- */
     771               1 :     int nItemSize = GDALGetDataTypeSize(eDataType)/8;
     772               1 :     const char *pszInterleaving = CSLFetchNameValue(papszHdr,"INTERLEAVING");
     773                 :     int             nPixelOffset, nLineOffset;
     774                 :     vsi_l_offset    nBandOffset;
     775               1 :     int bIntOverflow = FALSE;
     776                 : 
     777               1 :     if( pszInterleaving == NULL )
     778               0 :         pszInterleaving = "BIL";
     779                 :     
     780               2 :     if( EQUAL(pszInterleaving,"BSQ") || EQUAL(pszInterleaving,"NA") )
     781                 :     {
     782               1 :         nPixelOffset = nItemSize;
     783               1 :         if (poDS->nRasterXSize > INT_MAX / nItemSize) bIntOverflow = TRUE;
     784               1 :         nLineOffset = nItemSize * poDS->nRasterXSize;
     785               1 :         nBandOffset = nLineOffset * poDS->nRasterYSize;
     786                 :     }
     787               0 :     else if( EQUAL(pszInterleaving,"BIP") )
     788                 :     {
     789               0 :         nPixelOffset = nItemSize * nBands;
     790               0 :         if (poDS->nRasterXSize > INT_MAX / nPixelOffset) bIntOverflow = TRUE;
     791               0 :         nLineOffset = nPixelOffset * poDS->nRasterXSize;
     792               0 :         nBandOffset = nItemSize;
     793                 :     }
     794                 :     else
     795                 :     {
     796               0 :         if( !EQUAL(pszInterleaving,"BIL") )
     797                 :             CPLError( CE_Warning, CPLE_AppDefined,
     798                 :                       "INTERLEAVING:%s not recognised, assume BIL.",
     799               0 :                       pszInterleaving );
     800                 : 
     801               0 :         nPixelOffset = nItemSize;
     802               0 :         if (poDS->nRasterXSize > INT_MAX / (nPixelOffset * nBands)) bIntOverflow = TRUE;
     803               0 :         nLineOffset = nPixelOffset * nBands * poDS->nRasterXSize;
     804               0 :         nBandOffset = nItemSize * poDS->nRasterXSize;
     805                 :     }
     806                 : 
     807               1 :     if (bIntOverflow)
     808                 :     {
     809               0 :         delete poDS;
     810                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     811               0 :                   "Int overflow occured.");
     812               0 :         return NULL;
     813                 :     }
     814                 : 
     815               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
     816               1 :     poDS->PamInitialize();
     817                 : 
     818                 : /* -------------------------------------------------------------------- */
     819                 : /*      Create band information objects.                                */
     820                 : /* -------------------------------------------------------------------- */
     821               1 :     poDS->nBands = nBands;
     822               8 :     for( i = 0; i < poDS->nBands; i++ )
     823                 :     {
     824               7 :         if( nBits != -1 )
     825                 :         {
     826               0 :             poDS->SetBand( i+1, new GenBinBitRasterBand( poDS, nBits ) );
     827                 :         }
     828                 :         else
     829                 :             poDS->SetBand( 
     830                 :                 i+1, 
     831                 :                 new RawRasterBand( poDS, i+1, poDS->fpImage,
     832                 :                                    nBandOffset * i, nPixelOffset, nLineOffset,
     833               7 :                                    eDataType, bNative, TRUE ) );
     834                 :     }
     835                 : 
     836                 : /* -------------------------------------------------------------------- */
     837                 : /*      Get geotransform.                                               */
     838                 : /* -------------------------------------------------------------------- */
     839               1 :     if( CSLFetchNameValue(papszHdr,"UL_X_COORDINATE") != NULL
     840                 :         && CSLFetchNameValue(papszHdr,"UL_Y_COORDINATE") != NULL
     841                 :         && CSLFetchNameValue(papszHdr,"LR_X_COORDINATE") != NULL
     842                 :         && CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE") != NULL )
     843                 :     {
     844               1 :         double dfULX = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_X_COORDINATE"));
     845               1 :         double dfULY = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_Y_COORDINATE"));
     846               1 :         double dfLRX = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_X_COORDINATE"));
     847               1 :         double dfLRY = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE"));
     848                 : 
     849               1 :         poDS->adfGeoTransform[1] = (dfLRX - dfULX) / (poDS->nRasterXSize-1);
     850               1 :         poDS->adfGeoTransform[2] = 0.0;
     851               1 :         poDS->adfGeoTransform[4] = 0.0;
     852               1 :         poDS->adfGeoTransform[5] = (dfLRY - dfULY) / (poDS->nRasterYSize-1);
     853                 : 
     854               1 :         poDS->adfGeoTransform[0] = dfULX - poDS->adfGeoTransform[1] * 0.5;
     855               1 :         poDS->adfGeoTransform[3] = dfULY - poDS->adfGeoTransform[5] * 0.5;
     856                 : 
     857               1 :         poDS->bGotTransform = TRUE;
     858                 :     }
     859                 : 
     860                 : /* -------------------------------------------------------------------- */
     861                 : /*      Try and parse the coordinate system.                            */
     862                 : /* -------------------------------------------------------------------- */
     863               1 :     poDS->ParseCoordinateSystem( papszHdr );
     864                 : 
     865                 : /* -------------------------------------------------------------------- */
     866                 : /*      Initialize any PAM information.                                 */
     867                 : /* -------------------------------------------------------------------- */
     868               1 :     poDS->TryLoadXML();
     869                 :     
     870                 : /* -------------------------------------------------------------------- */
     871                 : /*      Check for overviews.                                            */
     872                 : /* -------------------------------------------------------------------- */
     873               1 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     874                 : 
     875               1 :     return( poDS );
     876                 : }
     877                 : 
     878                 : /************************************************************************/
     879                 : /*                         GDALRegister_GenBin()                          */
     880                 : /************************************************************************/
     881                 : 
     882             409 : void GDALRegister_GenBin()
     883                 : 
     884                 : {
     885                 :     GDALDriver  *poDriver;
     886                 : 
     887             409 :     if( GDALGetDriverByName( "GenBin" ) == NULL )
     888                 :     {
     889             392 :         poDriver = new GDALDriver();
     890                 :         
     891             392 :         poDriver->SetDescription( "GenBin" );
     892                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     893             392 :                                    "Generic Binary (.hdr Labelled)" );
     894                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     895             392 :                                    "frmt_various.html#GenBin" );
     896             392 :         poDriver->pfnOpen = GenBinDataset::Open;
     897                 : 
     898             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     899                 :     }
     900             409 : }

Generated by: LTP GCOV extension version 1.5