LCOV - code coverage report
Current view: directory - frmts/blx - blxdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 168 138 82.1 %
Date: 2010-01-09 Functions: 16 15 93.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: blxdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
       3                 :  *
       4                 :  * Project:  BLX Driver
       5                 :  * Purpose:  GDAL BLX support.
       6                 :  * Author:   Henrik Johansson, henrik@johome.net
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2006, Henrik Johansson <henrik@johome.net>
      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                 : */
      31                 : 
      32                 : #include "gdal_pam.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35                 : CPL_CVSID("$Id: blxdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
      36                 : 
      37                 : CPL_C_START
      38                 : #include <blx.h>
      39                 : CPL_C_END
      40                 : 
      41                 : CPL_C_START
      42                 : void    GDALRegister_BLX(void);
      43                 : CPL_C_END
      44                 : 
      45                 : class BLXDataset : public GDALDataset
      46                 : {
      47                 :     friend class BLXRasterBand;
      48                 : 
      49                 :     CPLErr      GetGeoTransform( double * padfTransform );
      50                 :     const char *GetProjectionRef();
      51                 : 
      52                 :     blxcontext_t *blxcontext;
      53                 : 
      54                 :     int nOverviewCount;
      55                 :     int bIsOverview;
      56                 :     BLXDataset *papoOverviewDS[BLX_OVERVIEWLEVELS];
      57                 : 
      58                 :   public:
      59                 :     BLXDataset();
      60                 :     ~BLXDataset();
      61                 : 
      62                 :     static GDALDataset *Open( GDALOpenInfo * );
      63                 : };
      64                 : 
      65                 : class BLXRasterBand : public GDALRasterBand
      66             110 : {
      67                 :     int overviewLevel;
      68                 :   public:
      69                 :     BLXRasterBand( BLXDataset *, int, int overviewLevel=0 );
      70                 : 
      71                 :     virtual double  GetNoDataValue( int *pbSuccess = NULL );
      72                 :     virtual GDALColorInterp GetColorInterpretation(void);
      73                 :     virtual int GetOverviewCount();
      74                 :     virtual GDALRasterBand *GetOverview( int );
      75                 : 
      76                 :     virtual CPLErr IReadBlock( int, int, void * );
      77                 : };
      78                 : 
      79            8432 : GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
      80                 : 
      81                 : {
      82                 :     // -------------------------------------------------------------------- 
      83                 :     //      First that the header looks like a BLX header
      84                 :     // -------------------------------------------------------------------- 
      85            8432 :     if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 102 )
      86            8326 :         return NULL;
      87                 : 
      88             106 :     if(!blx_checkheader((char *)poOpenInfo->pabyHeader))
      89              95 :   return NULL;
      90                 :     
      91                 :     // -------------------------------------------------------------------- 
      92                 :     //      Create a corresponding GDALDataset.                             
      93                 :     // -------------------------------------------------------------------- 
      94                 :     BLXDataset  *poDS;
      95                 : 
      96              11 :     poDS = new BLXDataset();
      97                 : 
      98                 :     // -------------------------------------------------------------------- 
      99                 :     //      Open BLX file
     100                 :     // -------------------------------------------------------------------- 
     101              11 :     poDS->blxcontext = blx_create_context();
     102              11 :     blxopen(poDS->blxcontext, poOpenInfo->pszFilename, "rb");
     103                 : 
     104              11 :     if(poDS->blxcontext==NULL)
     105               0 :   return NULL;
     106                 :     
     107              11 :     if ((poDS->blxcontext->cell_xsize % (1 << (1+BLX_OVERVIEWLEVELS))) != 0 ||
     108                 :         (poDS->blxcontext->cell_ysize % (1 << (1+BLX_OVERVIEWLEVELS))) != 0)
     109                 :     {
     110               0 :         delete poDS;
     111               0 :         return NULL;
     112                 :     }
     113                 : 
     114                 :     // Update dataset header from BLX context
     115              11 :     poDS->nRasterXSize = poDS->blxcontext->xsize;
     116              11 :     poDS->nRasterYSize = poDS->blxcontext->ysize;
     117                 : 
     118                 :     // -------------------------------------------------------------------- 
     119                 :     //      Create band information objects.                                
     120                 :     // -------------------------------------------------------------------- 
     121              11 :     poDS->nBands = 1;
     122              11 :     poDS->SetBand( 1, new BLXRasterBand( poDS, 1 ));
     123                 : 
     124                 :     // Create overview bands
     125              11 :     poDS->nOverviewCount = BLX_OVERVIEWLEVELS; 
     126             110 :     for(int i=0; i < poDS->nOverviewCount; i++) {
     127              44 :   poDS->papoOverviewDS[i] = new BLXDataset();
     128              44 :   poDS->papoOverviewDS[i]->blxcontext = poDS->blxcontext;
     129              44 :   poDS->papoOverviewDS[i]->bIsOverview = TRUE;
     130              44 :   poDS->papoOverviewDS[i]->nRasterXSize = poDS->nRasterXSize >> (i+1);
     131              44 :   poDS->papoOverviewDS[i]->nRasterYSize = poDS->nRasterYSize >> (i+1);
     132              44 :   poDS->nBands = 1;
     133              88 :   poDS->papoOverviewDS[i]->SetBand(1, new BLXRasterBand( poDS->papoOverviewDS[i], 1, i+1));
     134                 :     }
     135                 :     
     136                 : /* -------------------------------------------------------------------- */
     137                 : /*      Confirm the requested access is supported.                      */
     138                 : /* -------------------------------------------------------------------- */
     139              11 :     if( poOpenInfo->eAccess == GA_Update )
     140                 :     {
     141               0 :         delete poDS;
     142                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     143                 :                   "The BLX driver does not support update access to existing"
     144               0 :                   " datasets.\n" );
     145               0 :         return NULL;
     146                 :     }
     147                 : 
     148              11 :     return( poDS );
     149                 : }
     150                 : 
     151              55 : BLXDataset::BLXDataset() {
     152              55 :     blxcontext = NULL;
     153              55 :     bIsOverview = FALSE;
     154              55 :     nOverviewCount = 0;
     155                 :     
     156              55 :     for(int i=0; i < nOverviewCount; i++)
     157               0 :   papoOverviewDS[i]=NULL;
     158              55 : }
     159                 : 
     160             110 : BLXDataset::~BLXDataset() {
     161              55 :     if(!bIsOverview) {
     162              11 :   if(blxcontext) {
     163              11 :       blxclose(blxcontext);
     164              11 :       blx_free_context(blxcontext);
     165                 :   }
     166              55 :   for(int i=0; i < nOverviewCount; i++)
     167              44 :       if(papoOverviewDS[i])
     168              44 :     delete papoOverviewDS[i];
     169                 :     }
     170             110 : }
     171                 : 
     172                 : 
     173               8 : CPLErr BLXDataset::GetGeoTransform( double * padfTransform )
     174                 : 
     175                 : {
     176               8 :     padfTransform[0] = blxcontext->lon;
     177               8 :     padfTransform[1] = blxcontext->pixelsize_lon;
     178               8 :     padfTransform[2] = 0.0;
     179               8 :     padfTransform[3] = blxcontext->lat;
     180               8 :     padfTransform[4] = 0.0;
     181               8 :     padfTransform[5] = blxcontext->pixelsize_lat;
     182                 : 
     183               8 :     return CE_None;
     184                 : }
     185                 : 
     186               6 : const char *BLXDataset::GetProjectionRef()
     187                 : {
     188               6 :     return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
     189                 : }
     190                 : 
     191              55 : BLXRasterBand::BLXRasterBand( BLXDataset *poDS, int nBand, int overviewLevel )
     192                 : 
     193                 : {
     194              55 :     BLXDataset *poGDS = (BLXDataset *) poDS;
     195                 : 
     196              55 :     this->poDS = poDS;
     197              55 :     this->nBand = nBand;
     198              55 :     this->overviewLevel = overviewLevel;
     199                 :     
     200              55 :     eDataType = GDT_Int16;
     201                 : 
     202              55 :     nBlockXSize = poGDS->blxcontext->cell_xsize >> overviewLevel;
     203              55 :     nBlockYSize = poGDS->blxcontext->cell_ysize >> overviewLevel;
     204              55 : }
     205                 : 
     206               1 : int BLXRasterBand::GetOverviewCount()
     207                 : {
     208               1 :     BLXDataset *poGDS = (BLXDataset *) poDS;
     209                 :     
     210               1 :     return poGDS->nOverviewCount;
     211                 : }
     212                 : 
     213               4 : GDALRasterBand *BLXRasterBand::GetOverview( int i )
     214                 : {
     215               4 :     BLXDataset        *poGDS = (BLXDataset *) poDS;
     216                 : 
     217               4 :     if( i < 0 || i >= poGDS->nOverviewCount )
     218               0 :   return NULL;
     219                 :     else
     220               4 :       return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
     221                 : }
     222                 : 
     223             192 : CPLErr BLXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     224                 :                                   void * pImage )
     225                 : 
     226                 : {
     227             192 :     BLXDataset *poGDS = (BLXDataset *) poDS;
     228                 : 
     229             192 :     if(blx_readcell(poGDS->blxcontext, nBlockYOff, nBlockXOff, (short *)pImage, nBlockXSize*nBlockYSize*2, overviewLevel) == NULL) {
     230                 :   CPLError(CE_Failure, CPLE_AppDefined,
     231               0 :      "Failed to read BLX cell");
     232               0 :   return CE_Failure;
     233                 :     }
     234                 : 
     235             192 :     return CE_None;
     236                 : }
     237                 : 
     238               6 : double BLXRasterBand::GetNoDataValue( int * pbSuccess )
     239                 : {
     240               6 :     if (pbSuccess)
     241               6 :         *pbSuccess = TRUE;
     242               6 :     return BLX_UNDEF;
     243                 : }
     244                 : 
     245               0 : GDALColorInterp BLXRasterBand::GetColorInterpretation(void) {
     246               0 :     return GCI_GrayIndex;
     247                 : }
     248                 : 
     249                 : /* TODO: check if georeference is the same as for BLX files, WGS84
     250                 : */
     251                 : static GDALDataset *
     252              18 : BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     253                 :                 int bStrict, char ** papszOptions, 
     254                 :                 GDALProgressFunc pfnProgress, void * pProgressData )
     255                 : 
     256                 : {
     257              18 :     int  nBands = poSrcDS->GetRasterCount();
     258              18 :     int  nXSize = poSrcDS->GetRasterXSize();
     259              18 :     int  nYSize = poSrcDS->GetRasterYSize();
     260                 :     
     261              18 :     int zscale = 1;
     262              18 :     int fillundef = 1, fillundefval = 0;
     263              18 :     int endian = LITTLEENDIAN;
     264                 : 
     265                 : // -------------------------------------------------------------------- 
     266                 : //      Some rudimentary checks                                    
     267                 : // -------------------------------------------------------------------- 
     268              18 :     if( nBands != 1 )
     269                 :     {
     270                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     271                 :                   "BLX driver doesn't support %d bands.  Must be 1 (grey) ",
     272               5 :                   nBands );
     273               5 :         return NULL;
     274                 :     }
     275                 : 
     276              13 :     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int16 && bStrict )
     277                 :     {
     278                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     279                 :                   "BLX driver doesn't support data type %s. "
     280                 :                   "Only 16 bit byte bands supported.\n", 
     281                 :                   GDALGetDataTypeName( 
     282              10 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
     283                 : 
     284              10 :         return NULL;
     285                 :     }
     286                 : 
     287               3 :     if( (nXSize % 128 != 0) || (nYSize % 128 != 0) ) {
     288                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     289               1 :                   "BLX driver doesn't support dimensions that are not a multiple of 128.\n");
     290                 : 
     291               1 :         return NULL;
     292                 :     }
     293                 :     
     294                 : // -------------------------------------------------------------------- 
     295                 : //      What options has the user selected?                             
     296                 : // -------------------------------------------------------------------- 
     297               2 :     if( CSLFetchNameValue(papszOptions,"ZSCALE") != NULL ) {
     298               0 :         zscale = atoi(CSLFetchNameValue(papszOptions,"ZSCALE"));
     299               0 :         if( zscale < 1 ) {
     300                 :             CPLError( CE_Failure, CPLE_IllegalArg,
     301                 :                       "ZSCALE=%s is not a legal value in the range >= 1.",
     302               0 :                       CSLFetchNameValue(papszOptions,"ZSCALE") );
     303               0 :             return NULL;
     304                 :         }
     305                 :     }
     306                 : 
     307               2 :     if( CSLFetchNameValue(papszOptions,"FILLUNDEF") != NULL 
     308                 :                 && EQUAL(CSLFetchNameValue(papszOptions,"FILLUNDEF"),"NO") )
     309               0 :   fillundef = 0;
     310                 :     else  
     311               2 :   fillundef = 1;
     312                 : 
     313               2 :     if( CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") != NULL ) {
     314               0 :         fillundefval = atoi(CSLFetchNameValue(papszOptions,"FILLUNDEFVAL"));
     315               0 :         if( (fillundefval < -32768) || (fillundefval > 32767) ) {
     316                 :             CPLError( CE_Failure, CPLE_IllegalArg,
     317                 :                       "FILLUNDEFVAL=%s is not a legal value in the range -32768, 32767.",
     318               0 :                       CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") );
     319               0 :             return NULL;
     320                 :         }
     321                 :     }
     322               2 :     if( CSLFetchNameValue(papszOptions,"BIGENDIAN") != NULL 
     323                 :   && !EQUAL(CSLFetchNameValue(papszOptions,"BIGENDIAN"),"NO") )
     324               1 :   endian = BIGENDIAN;
     325                 :   
     326                 :     
     327                 : 
     328                 : // -------------------------------------------------------------------- 
     329                 : //      Create the dataset.                                             
     330                 : // -------------------------------------------------------------------- 
     331                 :     blxcontext_t *ctx;
     332                 : 
     333                 :     // Create a BLX context
     334               2 :     ctx = blx_create_context();
     335                 : 
     336                 :     // Setup BLX parameters
     337               2 :     ctx->cell_rows = nYSize / ctx->cell_ysize;
     338               2 :     ctx->cell_cols = nXSize / ctx->cell_xsize;
     339               2 :     ctx->zscale = zscale;
     340               2 :     ctx->fillundef = fillundef;
     341               2 :     ctx->fillundefval = fillundefval;
     342               2 :     ctx->endian = endian;
     343                 : 
     344               2 :     if(blxopen(ctx, pszFilename, "wb")) {
     345                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     346                 :                   "Unable to create blx file %s.\n", 
     347               0 :                   pszFilename );
     348               0 :         return NULL;
     349                 :     }
     350                 : 
     351                 : // -------------------------------------------------------------------- 
     352                 : //      Loop over image, copying image data.                            
     353                 : // -------------------------------------------------------------------- 
     354                 :     GInt16     *pabyTile;
     355               2 :     CPLErr      eErr=CE_None;
     356                 : 
     357               2 :     pabyTile = (GInt16 *) CPLMalloc( sizeof(GInt16)*ctx->cell_xsize*ctx->cell_ysize );
     358                 : 
     359               2 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     360               0 :         eErr = CE_Failure;
     361                 : 
     362              10 :     for(int i=0; (i < ctx->cell_rows) && (eErr == CE_None); i++)
     363              40 :   for(int j=0; j < ctx->cell_cols; j++) {
     364                 :       blxdata *celldata;
     365              32 :       GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
     366                 :       eErr = poBand->RasterIO( GF_Read, j*ctx->cell_xsize, i*ctx->cell_ysize, 
     367                 :              ctx->cell_xsize, ctx->cell_ysize, 
     368                 :              pabyTile, ctx->cell_xsize, ctx->cell_ysize, GDT_Int16,
     369              32 :              0, 0 );
     370              32 :       if(eErr >= CE_Failure) 
     371               0 :          break;
     372              32 :       celldata = pabyTile;
     373              32 :       if (blx_writecell(ctx, celldata, i, j) != 0)
     374                 :             {
     375               0 :                 eErr = CE_Failure;
     376               0 :                 break;
     377                 :             }
     378                 : 
     379              32 :             if ( ! pfnProgress( 1.0 * (i * ctx->cell_cols + j) / (ctx->cell_rows * ctx->cell_cols), NULL, pProgressData ))
     380                 :             {
     381               0 :                 eErr = CE_Failure;
     382               0 :                 break;
     383                 :             }
     384                 :     }
     385                 : 
     386               2 :     pfnProgress( 1.0, NULL, pProgressData );
     387                 : 
     388               2 :     CPLFree( pabyTile );
     389                 : 
     390                 :     double        adfGeoTransform[6];
     391               2 :     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     392                 :     {
     393               2 :   ctx->lon = adfGeoTransform[0];
     394               2 :   ctx->lat = adfGeoTransform[3];
     395               2 :   ctx->pixelsize_lon = adfGeoTransform[1]; 
     396               2 :   ctx->pixelsize_lat = adfGeoTransform[5]; 
     397                 :     }
     398                 : 
     399               2 :     blxclose(ctx);
     400               2 :     blx_free_context(ctx);
     401                 : 
     402               2 :     if (eErr == CE_None)
     403               2 :         return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
     404                 :     else
     405               0 :         return NULL;
     406                 : }
     407                 : 
     408                 : 
     409             338 : void GDALRegister_BLX()
     410                 : 
     411                 : {
     412                 :     GDALDriver  *poDriver;
     413                 : 
     414             338 :     if( GDALGetDriverByName( "BLX" ) == NULL )
     415                 :     {
     416             336 :         poDriver = new GDALDriver();
     417                 :         
     418             336 :         poDriver->SetDescription( "BLX" );
     419                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     420             336 :                                    "Magellan topo (.blx)" );
     421                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     422             336 :                                    "frmt_various.html#BLX" );
     423             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "blx" );
     424                 : 
     425             336 :         poDriver->pfnOpen = BLXDataset::Open;
     426             336 :   poDriver->pfnCreateCopy = BLXCreateCopy;
     427                 : 
     428             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     429                 :     }
     430             338 : }
     431                 : 

Generated by: LCOV version 1.7