LCOV - code coverage report
Current view: directory - frmts/raw - genbindataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 260 163 62.7 %
Date: 2012-12-26 Functions: 16 7 43.8 %

       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                 :     VSILFILE  *fpImage; // image data file.
     198                 : 
     199                 :     int         bGotTransform;
     200                 :     double      adfGeoTransform[6];
     201                 :     char       *pszProjection;
     202                 : 
     203                 :     char      **papszHDR;
     204                 : 
     205                 :     void        ParseCoordinateSystem( char ** );
     206                 : 
     207                 :   public:
     208                 :     GenBinDataset();
     209                 :     ~GenBinDataset();
     210                 :     
     211                 :     virtual CPLErr GetGeoTransform( double * padfTransform );
     212                 :     virtual const char *GetProjectionRef(void);
     213                 :     
     214                 :     virtual char **GetFileList();
     215                 : 
     216                 :     static GDALDataset *Open( GDALOpenInfo * );
     217                 : };
     218                 : 
     219                 : /************************************************************************/
     220                 : /* ==================================================================== */
     221                 : /*                       GenBinBitRasterBand                            */
     222                 : /* ==================================================================== */
     223                 : /************************************************************************/
     224                 : 
     225                 : class GenBinBitRasterBand : public GDALPamRasterBand
     226               0 : {
     227                 :     int            nBits;
     228                 : 
     229                 :   public:
     230                 :     GenBinBitRasterBand( GenBinDataset *poDS, int nBits );
     231                 : 
     232                 :     virtual CPLErr IReadBlock( int, int, void * );
     233                 : };
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                        GenBinBitRasterBand()                         */
     237                 : /************************************************************************/
     238                 : 
     239               0 : GenBinBitRasterBand::GenBinBitRasterBand( GenBinDataset *poDS, int nBitsIn )
     240                 : {
     241                 :     SetMetadataItem( "NBITS", 
     242                 :                      CPLString().Printf("%d",nBitsIn), 
     243               0 :                      "IMAGE_STRUCTURE" );
     244                 : 
     245               0 :     this->poDS = poDS;
     246               0 :     nBits = nBitsIn;
     247               0 :     nBand = 1;
     248                 : 
     249               0 :     eDataType = GDT_Byte;
     250                 : 
     251               0 :     nBlockXSize = poDS->nRasterXSize;
     252               0 :     nBlockYSize = 1;
     253               0 : }
     254                 : 
     255                 : /************************************************************************/
     256                 : /*                             IReadBlock()                             */
     257                 : /************************************************************************/
     258                 : 
     259               0 : CPLErr GenBinBitRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     260                 :                                         void * pImage )
     261                 : 
     262                 : {
     263               0 :     GenBinDataset *poGDS = (GenBinDataset *) poDS;
     264                 :     vsi_l_offset   nLineStart;
     265                 :     unsigned int   nLineBytes;
     266                 :     int            iBitOffset;
     267                 :     GByte         *pabyBuffer;
     268                 : 
     269                 : /* -------------------------------------------------------------------- */
     270                 : /*      Establish desired position.                                     */
     271                 : /* -------------------------------------------------------------------- */
     272               0 :     nLineStart = (((vsi_l_offset)nBlockXSize) * nBlockYOff * nBits) / 8;
     273               0 :     iBitOffset = (int)((((vsi_l_offset)nBlockXSize) * nBlockYOff * nBits) % 8);
     274               0 :     nLineBytes = (int) ((((vsi_l_offset)nBlockXSize) * (nBlockYOff+1) * nBits + 7) / 8 - nLineStart);
     275                 : 
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      Read data into buffer.                                          */
     278                 : /* -------------------------------------------------------------------- */
     279               0 :     pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
     280                 : 
     281               0 :     if( VSIFSeekL( poGDS->fpImage, nLineStart, SEEK_SET ) != 0 
     282                 :         || VSIFReadL( pabyBuffer, 1, nLineBytes, poGDS->fpImage) != nLineBytes )
     283                 :     {
     284                 :         CPLError( CE_Failure, CPLE_FileIO,
     285                 :                   "Failed to read %u bytes at offset %lu.\n%s",
     286                 :                   nLineBytes, (unsigned long)nLineStart, 
     287               0 :                   VSIStrerror( errno ) );
     288               0 :         return CE_Failure;
     289                 :     }
     290                 : 
     291                 : /* -------------------------------------------------------------------- */
     292                 : /*      Copy data, promoting to 8bit.                                   */
     293                 : /* -------------------------------------------------------------------- */
     294                 :     int iX;
     295                 : 
     296               0 :     if( nBits == 1 )
     297                 :     {
     298               0 :         for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
     299                 :         {
     300               0 :             if( pabyBuffer[iBitOffset>>3]  & (0x80 >>(iBitOffset & 7)) )
     301               0 :                 ((GByte *) pImage)[iX] = 1;
     302                 :             else
     303               0 :                 ((GByte *) pImage)[iX] = 0;
     304                 :         }
     305                 :     }
     306               0 :     else if( nBits == 2 )
     307                 :     {
     308               0 :         for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
     309                 :         {
     310               0 :             ((GByte *) pImage)[iX] = 
     311               0 :                 ((pabyBuffer[iBitOffset>>3]) >> (6-(iBitOffset&0x7)) & 0x3);
     312                 :         }
     313                 :     }
     314               0 :     else if( nBits == 4 )
     315                 :     {
     316               0 :         for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
     317                 :         {
     318               0 :             if( iBitOffset == 0 )
     319               0 :                 ((GByte *) pImage)[iX] = (pabyBuffer[iBitOffset>>3]) >> 4;
     320                 :             else
     321               0 :                 ((GByte *) pImage)[iX] = (pabyBuffer[iBitOffset>>3]) & 0xf;
     322                 :         }
     323                 :     }
     324                 :     else
     325               0 :         CPLAssert( FALSE );
     326                 : 
     327               0 :     CPLFree( pabyBuffer );
     328                 : 
     329               0 :     return CE_None;
     330                 : }
     331                 : 
     332                 : /************************************************************************/
     333                 : /* ==================================================================== */
     334                 : /*        GenBinDataset       */
     335                 : /* ==================================================================== */
     336                 : /************************************************************************/
     337                 : 
     338                 : /************************************************************************/
     339                 : /*                            GenBinDataset()                             */
     340                 : /************************************************************************/
     341                 : 
     342               1 : GenBinDataset::GenBinDataset()
     343                 : {
     344               1 :     fpImage = NULL;
     345               1 :     pszProjection = CPLStrdup("");
     346               1 :     bGotTransform = FALSE;
     347               1 :     adfGeoTransform[0] = 0.0;
     348               1 :     adfGeoTransform[1] = 1.0;
     349               1 :     adfGeoTransform[2] = 0.0;
     350               1 :     adfGeoTransform[3] = 0.0;
     351               1 :     adfGeoTransform[4] = 0.0;
     352               1 :     adfGeoTransform[5] = 1.0;
     353               1 :     papszHDR = NULL;
     354               1 : }
     355                 : 
     356                 : /************************************************************************/
     357                 : /*                            ~GenBinDataset()                            */
     358                 : /************************************************************************/
     359                 : 
     360               1 : GenBinDataset::~GenBinDataset()
     361                 : 
     362                 : {
     363               1 :     FlushCache();
     364                 : 
     365               1 :     if( fpImage != NULL )
     366               1 :         VSIFCloseL( fpImage );
     367                 : 
     368               1 :     CPLFree( pszProjection );
     369               1 :     CSLDestroy( papszHDR );
     370               1 : }
     371                 : 
     372                 : /************************************************************************/
     373                 : /*                          GetProjectionRef()                          */
     374                 : /************************************************************************/
     375                 : 
     376               1 : const char *GenBinDataset::GetProjectionRef()
     377                 : 
     378                 : {
     379               1 :     if (pszProjection && strlen(pszProjection) > 0)
     380               1 :         return pszProjection;
     381                 : 
     382               0 :     return GDALPamDataset::GetProjectionRef();
     383                 : }
     384                 : 
     385                 : /************************************************************************/
     386                 : /*                          GetGeoTransform()                           */
     387                 : /************************************************************************/
     388                 : 
     389               1 : CPLErr GenBinDataset::GetGeoTransform( double * padfTransform )
     390                 : 
     391                 : {
     392               1 :     if( bGotTransform )
     393                 :     {
     394               1 :         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     395               1 :         return CE_None;
     396                 :     }
     397                 :     else
     398                 :     {
     399               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     400                 :     }
     401                 : }
     402                 : 
     403                 : /************************************************************************/
     404                 : /*                            GetFileList()                             */
     405                 : /************************************************************************/
     406                 : 
     407               0 : char **GenBinDataset::GetFileList()
     408                 : 
     409                 : {
     410               0 :     CPLString osPath = CPLGetPath( GetDescription() );
     411               0 :     CPLString osName = CPLGetBasename( GetDescription() );
     412               0 :     char **papszFileList = NULL;
     413                 : 
     414                 :     // Main data file, etc. 
     415               0 :     papszFileList = GDALPamDataset::GetFileList();
     416                 : 
     417                 :     // Header file.
     418               0 :     CPLString osFilename = CPLFormCIFilename( osPath, osName, "hdr" );
     419               0 :     papszFileList = CSLAddString( papszFileList, osFilename );
     420                 : 
     421               0 :     return papszFileList;
     422                 : }
     423                 : 
     424                 : /************************************************************************/
     425                 : /*                       ParseCoordinateSystem()                        */
     426                 : /************************************************************************/
     427                 : 
     428               1 : void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
     429                 : 
     430                 : {
     431               1 :     const char *pszProjName = CSLFetchNameValue( papszHdr, "PROJECTION_NAME" );
     432               1 :     OGRSpatialReference oSRS;
     433                 : 
     434               1 :     if( pszProjName == NULL )
     435                 :         return;
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Translate zone and parameters into numeric form.                */
     439                 : /* -------------------------------------------------------------------- */
     440               1 :     int nZone = 0;
     441                 :     double adfProjParms[15];
     442               1 :     const char *pszUnits = CSLFetchNameValue( papszHdr, "MAP_UNITS" );
     443               1 :     const char *pszDatumName = CSLFetchNameValue( papszHdr, "DATUM_NAME" );
     444                 : 
     445               1 :     if( CSLFetchNameValue( papszHdr, "PROJECTION_ZONE" ) )
     446               1 :         nZone = atoi(CSLFetchNameValue( papszHdr, "PROJECTION_ZONE" ));
     447                 : 
     448               1 :     memset( adfProjParms, 0, sizeof(adfProjParms) );
     449               1 :     if( CSLFetchNameValue( papszHdr, "PROJECTION_PARAMETERS" ) )
     450                 :     {
     451                 :         int i;
     452                 :         char **papszTokens = CSLTokenizeString( 
     453               1 :             CSLFetchNameValue( papszHdr, "PROJECTION_PARAMETERS" ) );
     454                 : 
     455              15 :         for( i = 0; i < 15 && papszTokens[i] != NULL; i++ )
     456              14 :             adfProjParms[i] = CPLAtofM( papszTokens[i] );
     457                 : 
     458               1 :         CSLDestroy( papszTokens );
     459                 :     }
     460                 : 
     461                 : /* -------------------------------------------------------------------- */
     462                 : /*      Handle projections.                                             */
     463                 : /* -------------------------------------------------------------------- */
     464               1 :     if( EQUAL(pszProjName,"UTM") && nZone != 0 )
     465                 :     {
     466                 :         // honestly, I'm just getting that the negative zone for 
     467                 :         // southern hemisphere is used.
     468               0 :         oSRS.SetUTM( ABS(nZone), nZone > 0 );
     469                 :     }
     470                 : 
     471               1 :     else if( EQUAL(pszProjName,"State Plane") && nZone != 0 )
     472                 :     {
     473               1 :         int   nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
     474                 :         int   i;
     475               1 :         double          dfUnits = 0.0;
     476                 :         
     477             109 :         for( i = 0; i < nPairs; i++ )
     478                 :         {
     479             109 :             if( anUsgsEsriZones[i*2+1] == nZone )
     480                 :             {
     481               1 :                 nZone = anUsgsEsriZones[i*2];
     482               1 :                 break;
     483                 :             }
     484                 :             
     485                 :         }
     486                 : 
     487               1 :         if( EQUAL(pszUnits,"feet") )
     488               1 :             dfUnits = CPLAtofM(SRS_UL_US_FOOT_CONV);
     489               0 :         else if( EQUALN(pszUnits,"MET",3) )
     490               0 :             dfUnits = 1.0;
     491                 :         else
     492               0 :             pszUnits = NULL;
     493                 : 
     494                 :         oSRS.SetStatePlane( ABS(nZone), 
     495                 :                             pszDatumName==NULL || !EQUAL(pszDatumName,"NAD27"),
     496               1 :                             pszUnits, dfUnits );
     497                 :     }
     498                 : 
     499                 : /* -------------------------------------------------------------------- */
     500                 : /*      Setup the geographic coordinate system.                         */
     501                 : /* -------------------------------------------------------------------- */
     502               1 :     if( oSRS.GetAttrNode( "GEOGCS" ) == NULL )
     503                 :     {
     504               0 :         if( pszDatumName != NULL 
     505                 :             && oSRS.SetWellKnownGeogCS( pszDatumName ) == OGRERR_NONE )
     506                 :         {
     507                 :             // good
     508                 :         }
     509               0 :         else if( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ) 
     510                 :                  && CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS" )
     511                 :                  && CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS" ) )
     512                 :         {
     513               0 :             double dfSemiMajor = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS"));
     514               0 :             double dfSemiMinor = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS"));
     515                 :             
     516                 :             oSRS.SetGeogCS( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
     517                 :                             CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
     518                 :                             CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
     519                 :                             dfSemiMajor, 
     520               0 :                             1.0 / (1.0 - dfSemiMinor/dfSemiMajor) );
     521                 :         }
     522                 :         else // fallback default.
     523               0 :             oSRS.SetWellKnownGeogCS( "WGS84" );
     524                 :     }
     525                 : 
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Convert to WKT.                                                 */
     528                 : /* -------------------------------------------------------------------- */
     529               1 :     CPLFree( pszProjection );
     530               1 :     pszProjection = NULL;
     531                 :     
     532               1 :     oSRS.exportToWkt( &pszProjection );
     533                 : }
     534                 : 
     535                 : /************************************************************************/
     536                 : /*                                Open()                                */
     537                 : /************************************************************************/
     538                 : 
     539           12149 : GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
     540                 : 
     541                 : {
     542                 :     int   i, bSelectedHDR;
     543                 :     
     544                 : /* -------------------------------------------------------------------- */
     545                 : /*  We assume the user is pointing to the binary (ie. .bil) file. */
     546                 : /* -------------------------------------------------------------------- */
     547           12149 :     if( poOpenInfo->nHeaderBytes < 2 )
     548           11319 :         return NULL;
     549                 : 
     550                 : /* -------------------------------------------------------------------- */
     551                 : /*      Now we need to tear apart tfhe filename to form a .HDR           */
     552                 : /*      filename.                                                       */
     553                 : /* -------------------------------------------------------------------- */
     554             830 :     CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
     555             830 :     CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
     556             830 :     CPLString osHDRFilename;
     557                 : 
     558             830 :     if( poOpenInfo->papszSiblingFiles )
     559                 :     {
     560                 :         int iFile = CSLFindString(poOpenInfo->papszSiblingFiles, 
     561             826 :                                   CPLFormFilename( NULL, osName, "hdr" ) );
     562             826 :         if( iFile < 0 ) // return if there is no corresponding .hdr file
     563             795 :             return NULL;
     564                 : 
     565                 :         osHDRFilename = 
     566              31 :             CPLFormFilename( osPath, poOpenInfo->papszSiblingFiles[iFile],
     567              62 :                              NULL );
     568                 :     }
     569                 :     else
     570                 :     {
     571               4 :         osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
     572                 :     }
     573                 : 
     574              35 :     bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
     575                 : 
     576                 : /* -------------------------------------------------------------------- */
     577                 : /*      Do we have a .hdr file?                                         */
     578                 : /* -------------------------------------------------------------------- */
     579                 :     VSILFILE  *fp;
     580                 : 
     581              35 :     fp = VSIFOpenL( osHDRFilename, "r" );
     582                 :     
     583              35 :     if( fp == NULL )
     584                 :     {
     585               4 :         return NULL;
     586                 :     }
     587                 : 
     588                 : /* -------------------------------------------------------------------- */
     589                 : /*      Read a chunk to skim for expected keywords.                     */
     590                 : /* -------------------------------------------------------------------- */
     591                 :     char achHeader[1000];
     592                 :     
     593              31 :     int nRead = VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp );
     594              31 :     achHeader[nRead] = '\0';
     595              31 :     VSIFSeekL( fp, 0, SEEK_SET );
     596                 : 
     597              31 :     if( strstr( achHeader, "BANDS:" ) == NULL 
     598                 :         || strstr( achHeader, "ROWS:" ) == NULL 
     599                 :         || strstr( achHeader, "COLS:" ) == NULL )
     600                 :     {
     601              30 :         VSIFCloseL( fp );
     602              30 :         return NULL;
     603                 :     }
     604                 : 
     605                 : /* -------------------------------------------------------------------- */
     606                 : /*      Has the user selected the .hdr file to open?                    */
     607                 : /* -------------------------------------------------------------------- */
     608               1 :     if( bSelectedHDR )
     609                 :     {
     610                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     611                 :                   "The selected file is an Generic Binary header file, but to\n"
     612                 :                   "open Generic Binary datasets, the data file should be selected\n"
     613                 :                   "instead of the .hdr file.  Please try again selecting\n"
     614                 :                   "the raw data file corresponding to the header file: %s\n", 
     615               0 :                   poOpenInfo->pszFilename );
     616               0 :         VSIFCloseL( fp );
     617               0 :         return NULL;
     618                 :     }
     619                 : 
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      Read the .hdr file.                                             */
     622                 : /* -------------------------------------------------------------------- */
     623               1 :     char **papszHdr = NULL;
     624               1 :     const char *pszLine = CPLReadLineL( fp );
     625                 : 
     626              24 :     while( pszLine != NULL )
     627                 :     {
     628              22 :         if( EQUAL(pszLine,"PROJECTION_PARAMETERS:") )
     629                 :         {
     630               1 :             CPLString osPP = pszLine;
     631                 : 
     632               1 :             pszLine = CPLReadLineL(fp);
     633              17 :             while( pszLine != NULL 
     634                 :                    && (*pszLine == '\t' || *pszLine == ' ') )
     635                 :             {
     636              15 :                 osPP += pszLine;
     637              15 :                 pszLine = CPLReadLineL(fp);
     638                 :             }
     639               1 :             papszHdr = CSLAddString( papszHdr, osPP );
     640                 :         }
     641                 :         else
     642                 :         {
     643                 :             char *pszName;
     644              21 :             CPLString osValue;
     645                 :             
     646              21 :             osValue = CPLParseNameValue( pszLine, &pszName );
     647              21 :             osValue.Trim();
     648                 :             
     649              21 :             papszHdr = CSLSetNameValue( papszHdr, pszName, osValue );
     650              21 :             CPLFree( pszName );
     651                 :             
     652              21 :             pszLine = CPLReadLineL( fp );
     653                 :         }
     654                 :     }
     655                 : 
     656               1 :     VSIFCloseL( fp );
     657                 : 
     658               1 :     if( CSLFetchNameValue( papszHdr, "COLS" ) == NULL
     659                 :         || CSLFetchNameValue( papszHdr, "ROWS" ) == NULL
     660                 :         || CSLFetchNameValue( papszHdr, "BANDS" ) == NULL )
     661                 :     {
     662               0 :         CSLDestroy( papszHdr );
     663               0 :         return NULL;
     664                 :     }
     665                 : 
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      Create a corresponding GDALDataset.                             */
     668                 : /* -------------------------------------------------------------------- */
     669                 :     GenBinDataset     *poDS;
     670                 : 
     671               1 :     poDS = new GenBinDataset();
     672                 : 
     673                 : /* -------------------------------------------------------------------- */
     674                 : /*      Capture some information from the file that is of interest.     */
     675                 : /* -------------------------------------------------------------------- */
     676               2 :     int nBands = atoi(CSLFetchNameValue( papszHdr, "BANDS" ));
     677                 : 
     678               1 :     poDS->nRasterXSize = atoi(CSLFetchNameValue( papszHdr, "COLS" ));
     679               1 :     poDS->nRasterYSize = atoi(CSLFetchNameValue( papszHdr, "ROWS" ));
     680               1 :     poDS->papszHDR = papszHdr;
     681                 : 
     682               1 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
     683                 :         !GDALCheckBandCount(nBands, FALSE))
     684                 :     {
     685               0 :         delete poDS;
     686               0 :         return NULL;
     687                 :     }
     688                 : 
     689                 : /* -------------------------------------------------------------------- */
     690                 : /*      Open target binary file.                                        */
     691                 : /* -------------------------------------------------------------------- */
     692               1 :     if( poOpenInfo->eAccess == GA_ReadOnly )
     693               1 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     694                 :     else
     695               0 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
     696                 : 
     697               1 :     if( poDS->fpImage == NULL )
     698                 :     {
     699                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     700                 :                   "Failed to open %s with write permission.\n%s", 
     701               0 :                   osName.c_str(), VSIStrerror( errno ) );
     702               0 :         delete poDS;
     703               0 :         return NULL;
     704                 :     }
     705                 : 
     706               1 :     poDS->eAccess = poOpenInfo->eAccess;
     707                 : 
     708                 : /* -------------------------------------------------------------------- */
     709                 : /*      Figure out the data type.                                       */
     710                 : /* -------------------------------------------------------------------- */
     711               1 :     const char *pszDataType = CSLFetchNameValue( papszHdr, "DATATYPE" );
     712                 :     GDALDataType eDataType;
     713               1 :     int nBits = -1; // Only needed for partial byte types
     714                 : 
     715               1 :     if( pszDataType == NULL )
     716               0 :         eDataType = GDT_Byte;
     717               1 :     else if( EQUAL(pszDataType,"U16") )
     718               0 :         eDataType = GDT_UInt16;
     719               1 :     else if( EQUAL(pszDataType,"S16") )
     720               0 :         eDataType = GDT_Int16;
     721               1 :     else if( EQUAL(pszDataType,"F32") )
     722               0 :         eDataType = GDT_Float32;
     723               1 :     else if( EQUAL(pszDataType,"F64") )
     724               0 :         eDataType = GDT_Float64;
     725               1 :     else if( EQUAL(pszDataType,"U8") )
     726               1 :         eDataType = GDT_Byte;
     727               0 :     else if( EQUAL(pszDataType,"U1") 
     728                 :              || EQUAL(pszDataType,"U2")
     729                 :              || EQUAL(pszDataType,"U4") )
     730                 :     {
     731               0 :         nBits = atoi(pszDataType+1);
     732               0 :         eDataType = GDT_Byte;
     733               0 :         if( nBands != 1 )
     734                 :         {
     735                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     736               0 :                       "Only one band is supported for U1/U2/U4 data type" );
     737               0 :             delete poDS;
     738               0 :             return NULL;
     739                 :         }
     740                 :     }
     741                 :     else
     742                 :     {
     743               0 :         eDataType = GDT_Byte;
     744                 :         CPLError( CE_Warning, CPLE_AppDefined,
     745                 :                   "DATATYPE=%s not recognised, assuming Byte.",
     746               0 :                   pszDataType );
     747                 :     }
     748                 : 
     749                 : /* -------------------------------------------------------------------- */
     750                 : /*      Do we need byte swapping?                                       */
     751                 : /* -------------------------------------------------------------------- */
     752               1 :     const char *pszBYTE_ORDER = CSLFetchNameValue(papszHdr,"BYTE_ORDER");
     753               1 :     int bNative = TRUE;
     754                 :     
     755               1 :     if( pszBYTE_ORDER != NULL )
     756                 :     {
     757                 : #ifdef CPL_LSB
     758               1 :         bNative = EQUALN(pszBYTE_ORDER,"LSB",3);
     759                 : #else
     760                 :         bNative = !EQUALN(pszBYTE_ORDER,"LSB",3);
     761                 : #endif        
     762                 :     }
     763                 : 
     764                 : /* -------------------------------------------------------------------- */
     765                 : /*  Work out interleaving info.         */
     766                 : /* -------------------------------------------------------------------- */
     767               1 :     int nItemSize = GDALGetDataTypeSize(eDataType)/8;
     768               1 :     const char *pszInterleaving = CSLFetchNameValue(papszHdr,"INTERLEAVING");
     769                 :     int             nPixelOffset, nLineOffset;
     770                 :     vsi_l_offset    nBandOffset;
     771               1 :     int bIntOverflow = FALSE;
     772                 : 
     773               1 :     if( pszInterleaving == NULL )
     774               0 :         pszInterleaving = "BIL";
     775                 :     
     776               2 :     if( EQUAL(pszInterleaving,"BSQ") || EQUAL(pszInterleaving,"NA") )
     777                 :     {
     778               1 :         nPixelOffset = nItemSize;
     779               1 :         if (poDS->nRasterXSize > INT_MAX / nItemSize) bIntOverflow = TRUE;
     780               1 :         nLineOffset = nItemSize * poDS->nRasterXSize;
     781               1 :         nBandOffset = nLineOffset * poDS->nRasterYSize;
     782                 :     }
     783               0 :     else if( EQUAL(pszInterleaving,"BIP") )
     784                 :     {
     785               0 :         nPixelOffset = nItemSize * nBands;
     786               0 :         if (poDS->nRasterXSize > INT_MAX / nPixelOffset) bIntOverflow = TRUE;
     787               0 :         nLineOffset = nPixelOffset * poDS->nRasterXSize;
     788               0 :         nBandOffset = nItemSize;
     789                 :     }
     790                 :     else
     791                 :     {
     792               0 :         if( !EQUAL(pszInterleaving,"BIL") )
     793                 :             CPLError( CE_Warning, CPLE_AppDefined,
     794                 :                       "INTERLEAVING:%s not recognised, assume BIL.",
     795               0 :                       pszInterleaving );
     796                 : 
     797               0 :         nPixelOffset = nItemSize;
     798               0 :         if (poDS->nRasterXSize > INT_MAX / (nPixelOffset * nBands)) bIntOverflow = TRUE;
     799               0 :         nLineOffset = nPixelOffset * nBands * poDS->nRasterXSize;
     800               0 :         nBandOffset = nItemSize * poDS->nRasterXSize;
     801                 :     }
     802                 : 
     803               1 :     if (bIntOverflow)
     804                 :     {
     805               0 :         delete poDS;
     806                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     807               0 :                   "Int overflow occured.");
     808               0 :         return NULL;
     809                 :     }
     810                 : 
     811               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
     812               1 :     poDS->PamInitialize();
     813                 : 
     814                 : /* -------------------------------------------------------------------- */
     815                 : /*      Create band information objects.                                */
     816                 : /* -------------------------------------------------------------------- */
     817               1 :     poDS->nBands = nBands;
     818               8 :     for( i = 0; i < poDS->nBands; i++ )
     819                 :     {
     820               7 :         if( nBits != -1 )
     821                 :         {
     822               0 :             poDS->SetBand( i+1, new GenBinBitRasterBand( poDS, nBits ) );
     823                 :         }
     824                 :         else
     825                 :             poDS->SetBand( 
     826                 :                 i+1, 
     827                 :                 new RawRasterBand( poDS, i+1, poDS->fpImage,
     828                 :                                    nBandOffset * i, nPixelOffset, nLineOffset,
     829               7 :                                    eDataType, bNative, TRUE ) );
     830                 :     }
     831                 : 
     832                 : /* -------------------------------------------------------------------- */
     833                 : /*      Get geotransform.                                               */
     834                 : /* -------------------------------------------------------------------- */
     835               1 :     if( CSLFetchNameValue(papszHdr,"UL_X_COORDINATE") != NULL
     836                 :         && CSLFetchNameValue(papszHdr,"UL_Y_COORDINATE") != NULL
     837                 :         && CSLFetchNameValue(papszHdr,"LR_X_COORDINATE") != NULL
     838                 :         && CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE") != NULL )
     839                 :     {
     840               1 :         double dfULX = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_X_COORDINATE"));
     841               1 :         double dfULY = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_Y_COORDINATE"));
     842               1 :         double dfLRX = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_X_COORDINATE"));
     843               1 :         double dfLRY = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE"));
     844                 : 
     845               1 :         poDS->adfGeoTransform[1] = (dfLRX - dfULX) / (poDS->nRasterXSize-1);
     846               1 :         poDS->adfGeoTransform[2] = 0.0;
     847               1 :         poDS->adfGeoTransform[4] = 0.0;
     848               1 :         poDS->adfGeoTransform[5] = (dfLRY - dfULY) / (poDS->nRasterYSize-1);
     849                 : 
     850               1 :         poDS->adfGeoTransform[0] = dfULX - poDS->adfGeoTransform[1] * 0.5;
     851               1 :         poDS->adfGeoTransform[3] = dfULY - poDS->adfGeoTransform[5] * 0.5;
     852                 : 
     853               1 :         poDS->bGotTransform = TRUE;
     854                 :     }
     855                 : 
     856                 : /* -------------------------------------------------------------------- */
     857                 : /*      Try and parse the coordinate system.                            */
     858                 : /* -------------------------------------------------------------------- */
     859               1 :     poDS->ParseCoordinateSystem( papszHdr );
     860                 : 
     861                 : /* -------------------------------------------------------------------- */
     862                 : /*      Initialize any PAM information.                                 */
     863                 : /* -------------------------------------------------------------------- */
     864               1 :     poDS->TryLoadXML();
     865                 :     
     866                 : /* -------------------------------------------------------------------- */
     867                 : /*      Check for overviews.                                            */
     868                 : /* -------------------------------------------------------------------- */
     869               1 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     870                 : 
     871               1 :     return( poDS );
     872                 : }
     873                 : 
     874                 : /************************************************************************/
     875                 : /*                         GDALRegister_GenBin()                          */
     876                 : /************************************************************************/
     877                 : 
     878             582 : void GDALRegister_GenBin()
     879                 : 
     880                 : {
     881                 :     GDALDriver  *poDriver;
     882                 : 
     883             582 :     if( GDALGetDriverByName( "GenBin" ) == NULL )
     884                 :     {
     885             561 :         poDriver = new GDALDriver();
     886                 :         
     887             561 :         poDriver->SetDescription( "GenBin" );
     888                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     889             561 :                                    "Generic Binary (.hdr Labelled)" );
     890                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     891             561 :                                    "frmt_various.html#GenBin" );
     892             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     893                 : 
     894             561 :         poDriver->pfnOpen = GenBinDataset::Open;
     895                 : 
     896             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     897                 :     }
     898             582 : }

Generated by: LCOV version 1.7