LCOV - code coverage report
Current view: directory - frmts/raw - doq2dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 175 138 78.9 %
Date: 2012-12-26 Functions: 9 5 55.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: doq2dataset.cpp 21717 2011-02-13 20:16:30Z rouault $
       3                 :  *
       4                 :  * Project:  USGS DOQ Driver (Second Generation Format)
       5                 :  * Purpose:  Implementation of DOQ2Dataset
       6                 :  * Author:   Derrick J Brashear, shadow@dementia.org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Derrick J Brashear
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "rawdataset.h"
      31                 : #include "cpl_string.h"
      32                 : 
      33                 : CPL_CVSID("$Id: doq2dataset.cpp 21717 2011-02-13 20:16:30Z rouault $");
      34                 : 
      35                 : CPL_C_START
      36                 : void  GDALRegister_DOQ2(void);
      37                 : CPL_C_END
      38                 : 
      39                 : #define UTM_FORMAT \
      40                 : "PROJCS[\"%s / UTM zone %dN\",GEOGCS[%s,PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%d],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],%s]"
      41                 : 
      42                 : #define WGS84_DATUM \
      43                 : "\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]]"
      44                 : 
      45                 : #define WGS72_DATUM \
      46                 : "\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"NWL 10D\",6378135,298.26]]"
      47                 : 
      48                 : #define NAD27_DATUM \
      49                 : "\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.978698213901]]"
      50                 : 
      51                 : #define NAD83_DATUM \
      52                 : "\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101]]"
      53                 : 
      54                 : /************************************************************************/
      55                 : /* ==================================================================== */
      56                 : /*        DOQ2Dataset       */
      57                 : /* ==================================================================== */
      58                 : /************************************************************************/
      59                 : 
      60                 : class DOQ2Dataset : public RawDataset
      61                 : {
      62                 :     VSILFILE  *fpImage; // image data file.
      63                 :     
      64                 :     double  dfULX, dfULY;
      65                 :     double  dfXPixelSize, dfYPixelSize;
      66                 : 
      67                 :     char  *pszProjection;
      68                 : 
      69                 :   public:
      70                 :         DOQ2Dataset();
      71                 :               ~DOQ2Dataset();
      72                 : 
      73                 :     CPLErr  GetGeoTransform( double * padfTransform );
      74                 :     const char  *GetProjectionRef( void );
      75                 :     
      76                 :     static GDALDataset *Open( GDALOpenInfo * );
      77                 : };
      78                 : 
      79                 : /************************************************************************/
      80                 : /*                            DOQ2Dataset()                             */
      81                 : /************************************************************************/
      82                 : 
      83               1 : DOQ2Dataset::DOQ2Dataset()
      84                 : {
      85               1 :     pszProjection = NULL;
      86               1 :     fpImage = NULL;
      87               1 : }
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                            ~DOQ2Dataset()                            */
      91                 : /************************************************************************/
      92                 : 
      93               1 : DOQ2Dataset::~DOQ2Dataset()
      94                 : 
      95                 : {
      96               1 :     FlushCache();
      97                 : 
      98               1 :     CPLFree( pszProjection );
      99               1 :     if( fpImage != NULL )
     100               1 :         VSIFCloseL( fpImage );
     101               1 : }
     102                 : 
     103                 : /************************************************************************/
     104                 : /*                          GetGeoTransform()                           */
     105                 : /************************************************************************/
     106                 : 
     107               1 : CPLErr DOQ2Dataset::GetGeoTransform( double * padfTransform )
     108                 : 
     109                 : {
     110               1 :     padfTransform[0] = dfULX;
     111               1 :     padfTransform[1] = dfXPixelSize;
     112               1 :     padfTransform[2] = 0.0;
     113               1 :     padfTransform[3] = dfULY;
     114               1 :     padfTransform[4] = 0.0;
     115               1 :     padfTransform[5] = -1 * dfYPixelSize;
     116                 :     
     117               1 :     return( CE_None );
     118                 : }
     119                 : 
     120                 : /************************************************************************/
     121                 : /*                        GetProjectionString()                         */
     122                 : /************************************************************************/
     123                 : 
     124               0 : const char *DOQ2Dataset::GetProjectionRef()
     125                 : 
     126                 : {
     127               0 :     return pszProjection;
     128                 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*                                Open()                                */
     132                 : /************************************************************************/
     133                 : 
     134           12339 : GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
     135                 : 
     136                 : {
     137           12339 :     int   nWidth=0, nHeight=0, nBandStorage=0, nBandTypes=0;
     138                 :     
     139                 : /* -------------------------------------------------------------------- */
     140                 : /*  We assume the user is pointing to the binary (ie. .bil) file. */
     141                 : /* -------------------------------------------------------------------- */
     142           12339 :     if( poOpenInfo->nHeaderBytes < 212 )
     143           11652 :         return NULL;
     144                 : 
     145             687 :     int         nLineCount = 0;
     146                 :     const char *pszLine;
     147             687 :     int   nBytesPerPixel=0;
     148             687 :     const char *pszDatumLong=NULL, *pszDatumShort=NULL;
     149             687 :     const char *pszUnits=NULL;
     150             687 :     char *pszQuadname = NULL;
     151             687 :     char *pszQuadquad = NULL;
     152             687 :     char *pszState = NULL;
     153             687 :     int         nZone=0, nProjType=0;
     154             687 :     int   nSkipBytes=0, nBytesPerLine, i, nBandCount = 0;
     155             687 :     double      dfULXMap=0.0, dfULYMap = 0.0;
     156             687 :     double      dfXDim=0.0, dfYDim=0.0;
     157             687 :     char  **papszMetadata = NULL;
     158                 : 
     159             687 :     if(! EQUALN((const char *) poOpenInfo->pabyHeader,
     160                 :                 "BEGIN_USGS_DOQ_HEADER", 21) )
     161             686 :         return NULL;
     162                 : 
     163               1 :     VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     164               1 :     if (fp == NULL)
     165               0 :         return NULL;
     166                 : 
     167                 :     /* read and discard the first line */
     168               1 :     pszLine = CPLReadLineL( fp );
     169                 : 
     170              47 :     while( (pszLine = CPLReadLineL( fp )) != NULL )
     171                 :     {
     172                 :   char    **papszTokens;
     173                 : 
     174              46 :         nLineCount++;
     175                 : 
     176              46 :   if( EQUAL(pszLine,"END_USGS_DOQ_HEADER") )
     177               0 :             break;
     178                 : 
     179              46 :   papszTokens = CSLTokenizeString( pszLine );
     180              46 :         if( CSLCount( papszTokens ) < 2 )
     181                 :         {
     182               1 :             CSLDestroy( papszTokens );
     183               1 :             break;
     184                 :         }
     185                 :         
     186              45 :         if( EQUAL(papszTokens[0],"SAMPLES_AND_LINES") && CSLCount(papszTokens) >= 3 )
     187                 :         {
     188               1 :             nWidth = atoi(papszTokens[1]);
     189               1 :             nHeight = atoi(papszTokens[2]);
     190                 :         }
     191              44 :         else if( EQUAL(papszTokens[0],"BYTE_COUNT") )
     192                 :         {
     193               1 :             nSkipBytes = atoi(papszTokens[1]);
     194                 :         }
     195              43 :         else if( EQUAL(papszTokens[0],"XY_ORIGIN") && CSLCount(papszTokens) >= 3 )
     196                 :         {
     197               1 :             dfULXMap = atof(papszTokens[1]);
     198               1 :             dfULYMap = atof(papszTokens[2]);
     199                 :         }
     200              42 :         else if( EQUAL(papszTokens[0],"HORIZONTAL_RESOLUTION") )
     201                 :         {
     202               1 :             dfXDim = dfYDim = atof(papszTokens[1]);
     203                 :         }
     204              41 :   else if( EQUAL(papszTokens[0],"BAND_ORGANIZATION") )
     205                 :         {
     206               1 :             if( EQUAL(papszTokens[1],"SINGLE FILE") )
     207               0 :                 nBandStorage = 1;
     208               1 :             if( EQUAL(papszTokens[1],"BSQ") )
     209               0 :                 nBandStorage = 1;
     210               1 :             if( EQUAL(papszTokens[1],"BIL") )
     211               0 :                 nBandStorage = 1;
     212               1 :             if( EQUAL(papszTokens[1],"BIP") )
     213               1 :                 nBandStorage = 4;
     214                 :   }
     215              40 :   else if( EQUAL(papszTokens[0],"BAND_CONTENT") )
     216                 :         {
     217               3 :             if( EQUAL(papszTokens[1],"BLACK&WHITE") )
     218               0 :                 nBandTypes = 1;
     219               3 :             else if( EQUAL(papszTokens[1],"COLOR") )
     220               0 :                 nBandTypes = 5;
     221               3 :             else if( EQUAL(papszTokens[1],"RGB") )
     222               0 :                 nBandTypes = 5;
     223               3 :             else if( EQUAL(papszTokens[1],"RED") )
     224               1 :                 nBandTypes = 5;
     225               2 :             else if( EQUAL(papszTokens[1],"GREEN") )
     226               1 :                 nBandTypes = 5;
     227               1 :             else if( EQUAL(papszTokens[1],"BLUE") )
     228               1 :                 nBandTypes = 5;
     229                 : 
     230               3 :             nBandCount++;
     231                 :         }
     232              37 :         else if( EQUAL(papszTokens[0],"BITS_PER_PIXEL") )
     233                 :         {
     234               1 :       nBytesPerPixel = (atoi(papszTokens[1]) / 8);
     235                 :         }
     236              36 :         else if( EQUAL(papszTokens[0],"HORIZONTAL_COORDINATE_SYSTEM") )
     237                 :         {
     238               1 :       if( EQUAL(papszTokens[1],"UTM") ) 
     239               1 :                 nProjType = 1;
     240               0 :       else if( EQUAL(papszTokens[1],"SPCS") ) 
     241               0 :                 nProjType = 2;
     242               0 :       else if( EQUAL(papszTokens[1],"GEOGRAPHIC") ) 
     243               0 :                 nProjType = 0;
     244                 :         }
     245              35 :         else if( EQUAL(papszTokens[0],"COORDINATE_ZONE") )
     246                 :         {
     247               1 :             nZone = atoi(papszTokens[1]);
     248                 :         }
     249              34 :         else if( EQUAL(papszTokens[0],"HORIZONTAL_UNITS") )
     250                 :         {
     251               1 :       if( EQUAL(papszTokens[1],"METERS") )
     252               1 :                 pszUnits = "UNIT[\"metre\",1]";
     253               0 :       else if( EQUAL(papszTokens[1],"FEET") )
     254               0 :                 pszUnits = "UNIT[\"US survey foot\",0.304800609601219]";
     255                 :         }
     256              33 :         else if( EQUAL(papszTokens[0],"HORIZONTAL_DATUM") )
     257                 :         {
     258               1 :       if( EQUAL(papszTokens[1],"NAD27") ) 
     259                 :             {
     260               0 :     pszDatumLong = NAD27_DATUM;
     261               0 :     pszDatumShort = "NAD 27";
     262                 :             }
     263               1 :       else if( EQUAL(papszTokens[1],"WGS72") ) 
     264                 :             {
     265               0 :     pszDatumLong = WGS72_DATUM;
     266               0 :     pszDatumShort = "WGS 72";
     267                 :             }
     268               1 :       else if( EQUAL(papszTokens[1],"WGS84") ) 
     269                 :             {
     270               0 :     pszDatumLong = WGS84_DATUM;
     271               0 :     pszDatumShort = "WGS 84";
     272                 :             }
     273               1 :       else if( EQUAL(papszTokens[1],"NAD83") ) 
     274                 :             {
     275               1 :     pszDatumLong = NAD83_DATUM;
     276               1 :     pszDatumShort = "NAD 83";
     277                 :             }
     278                 :       else
     279                 :             {
     280               0 :     pszDatumLong = "DATUM[\"unknown\"]";
     281               0 :     pszDatumShort = "unknown";
     282                 :             }
     283                 :         }    
     284                 :         else
     285                 :         {
     286                 :             /* we want to generically capture all the other metadata */
     287              32 :             CPLString osMetaDataValue;
     288                 :             int  iToken;
     289                 : 
     290             250 :             for( iToken = 1; papszTokens[iToken] != NULL; iToken++ )
     291                 :             {
     292             218 :                 if( EQUAL(papszTokens[iToken],"*") )
     293               1 :                     continue;
     294                 : 
     295             217 :                 if( iToken > 1 )
     296             186 :                     osMetaDataValue += " " ;
     297             217 :                 osMetaDataValue += papszTokens[iToken];
     298                 :             }
     299                 :             papszMetadata = CSLAddNameValue( papszMetadata, 
     300              32 :                                              papszTokens[0], 
     301              64 :                                              osMetaDataValue );
     302                 :         }
     303                 :   
     304              45 :         CSLDestroy( papszTokens );
     305                 :     }
     306                 : 
     307               1 :     CPLReadLineL( NULL );
     308                 : 
     309                 : /* -------------------------------------------------------------------- */
     310                 : /*      Do these values look coherent for a DOQ file?  It would be      */
     311                 : /*      nice to do a more comprehensive test than this!                 */
     312                 : /* -------------------------------------------------------------------- */
     313               1 :     if( nWidth < 500 || nWidth > 25000
     314                 :         || nHeight < 500 || nHeight > 25000
     315                 :         || nBandStorage < 0 || nBandStorage > 4
     316                 :         || nBandTypes < 1 || nBandTypes > 9 )
     317                 :     {
     318               0 :         CSLDestroy( papszMetadata );
     319               0 :         VSIFCloseL(fp);
     320               0 :         return NULL;
     321                 :     }
     322                 : 
     323                 : /* -------------------------------------------------------------------- */
     324                 : /*      Check the configuration.  We don't currently handle all         */
     325                 : /*      variations, only the common ones.                               */
     326                 : /* -------------------------------------------------------------------- */
     327               1 :     if( nBandTypes > 5 )
     328                 :     {
     329                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     330                 :                   "DOQ Data Type (%d) is not a supported configuration.\n",
     331               0 :                   nBandTypes );
     332               0 :         CSLDestroy( papszMetadata );
     333               0 :         VSIFCloseL(fp);
     334               0 :         return NULL;
     335                 :     }
     336                 :     
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Confirm the requested access is supported.                      */
     339                 : /* -------------------------------------------------------------------- */
     340               1 :     if( poOpenInfo->eAccess == GA_Update )
     341                 :     {
     342               0 :         CSLDestroy( papszMetadata );
     343                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     344                 :                   "The DOQ2 driver does not support update access to existing"
     345               0 :                   " datasets.\n" );
     346               0 :         VSIFCloseL(fp);
     347               0 :         return NULL;
     348                 :     }
     349                 : /* -------------------------------------------------------------------- */
     350                 : /*      Create a corresponding GDALDataset.                             */
     351                 : /* -------------------------------------------------------------------- */
     352                 :     DOQ2Dataset   *poDS;
     353                 : 
     354               1 :     poDS = new DOQ2Dataset();
     355                 : 
     356               1 :     poDS->nRasterXSize = nWidth;
     357               1 :     poDS->nRasterYSize = nHeight;
     358                 : 
     359               1 :     poDS->SetMetadata( papszMetadata );
     360               1 :     CSLDestroy( papszMetadata );
     361                 : 
     362               1 :     poDS->fpImage = fp;
     363                 : 
     364                 : /* -------------------------------------------------------------------- */
     365                 : /*      Compute layout of data.                                         */
     366                 : /* -------------------------------------------------------------------- */
     367               1 :     if( nBandCount < 2 )
     368               0 :         nBandCount = nBytesPerPixel;
     369                 :     else
     370               1 :         nBytesPerPixel *= nBandCount;
     371                 : 
     372               1 :     nBytesPerLine = nBytesPerPixel * nWidth;
     373                 :     
     374                 : /* -------------------------------------------------------------------- */
     375                 : /*      Create band information objects.                                */
     376                 : /* -------------------------------------------------------------------- */
     377               8 :     for( i = 0; i < nBandCount; i++ )
     378                 :     {
     379                 :         poDS->SetBand( i+1, 
     380                 :             new RawRasterBand( poDS, i+1, poDS->fpImage,
     381                 :                                nSkipBytes + i, nBytesPerPixel, nBytesPerLine,
     382               3 :                                GDT_Byte, TRUE, TRUE ) );
     383                 :     }
     384                 : 
     385               1 :     if (nProjType == 1)
     386                 :     {
     387                 :   poDS->pszProjection = 
     388                 :             CPLStrdup(CPLSPrintf( UTM_FORMAT, pszDatumShort, nZone, 
     389               1 :                                   pszDatumLong, nZone * 6 - 183, pszUnits ));
     390                 :     } 
     391                 :     else 
     392                 :     {
     393               0 :   poDS->pszProjection = CPLStrdup("");
     394                 :     }
     395                 : 
     396               1 :     poDS->dfULX = dfULXMap;
     397               1 :     poDS->dfULY = dfULYMap;
     398                 : 
     399               1 :     poDS->dfXPixelSize = dfXDim;
     400               1 :     poDS->dfYPixelSize = dfYDim;
     401                 : 
     402               1 :     if ( pszQuadname ) CPLFree( pszQuadname );
     403               1 :     if ( pszQuadquad) CPLFree( pszQuadquad );
     404               1 :     if ( pszState) CPLFree( pszState );
     405                 : 
     406                 : /* -------------------------------------------------------------------- */
     407                 : /*      Initialize any PAM information.                                 */
     408                 : /* -------------------------------------------------------------------- */
     409               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
     410               1 :     poDS->TryLoadXML();
     411                 : 
     412                 : /* -------------------------------------------------------------------- */
     413                 : /*      Check for overviews.                                            */
     414                 : /* -------------------------------------------------------------------- */
     415               1 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     416                 : 
     417               1 :     return( poDS );
     418                 : }
     419                 : 
     420                 : /************************************************************************/
     421                 : /*                         GDALRegister_DOQ1()                          */
     422                 : /************************************************************************/
     423                 : 
     424             582 : void GDALRegister_DOQ2()
     425                 : 
     426                 : {
     427                 :     GDALDriver  *poDriver;
     428                 : 
     429             582 :     if( GDALGetDriverByName( "DOQ2" ) == NULL )
     430                 :     {
     431             561 :         poDriver = new GDALDriver();
     432                 :         
     433             561 :         poDriver->SetDescription( "DOQ2" );
     434                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     435             561 :                                    "USGS DOQ (New Style)" );
     436                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     437             561 :                                    "frmt_various.html#DOQ2" );
     438             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     439                 : 
     440             561 :         poDriver->pfnOpen = DOQ2Dataset::Open;
     441                 : 
     442             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     443                 :     }
     444             582 : }
     445                 : 

Generated by: LCOV version 1.7