LCOV - code coverage report
Current view: directory - frmts/blx - blxdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 176 144 81.8 %
Date: 2011-12-18 Functions: 19 13 68.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: blxdataset.cpp 21821 2011-02-24 04:07:16Z warmerdam $
       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 21821 2011-02-24 04:07:16Z warmerdam $");
      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 GDALPamDataset
      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 GDALPamRasterBand
      66              55 : {
      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           10689 : GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
      80                 : 
      81                 : {
      82                 :     // -------------------------------------------------------------------- 
      83                 :     //      First that the header looks like a BLX header
      84                 :     // -------------------------------------------------------------------- 
      85           10689 :     if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 102 )
      86           10430 :         return NULL;
      87                 : 
      88             259 :     if(!blx_checkheader((char *)poOpenInfo->pabyHeader))
      89             248 :   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                 : /* -------------------------------------------------------------------- */
     149                 : /*      Initialize any PAM information.                                 */
     150                 : /* -------------------------------------------------------------------- */
     151              11 :     poDS->SetDescription( poOpenInfo->pszFilename );
     152              11 :     poDS->TryLoadXML();
     153                 : 
     154              11 :     return( poDS );
     155                 : }
     156                 : 
     157              55 : BLXDataset::BLXDataset() {
     158              55 :     blxcontext = NULL;
     159              55 :     bIsOverview = FALSE;
     160              55 :     nOverviewCount = 0;
     161                 :     
     162              55 :     for(int i=0; i < nOverviewCount; i++)
     163               0 :   papoOverviewDS[i]=NULL;
     164              55 : }
     165                 : 
     166              55 : BLXDataset::~BLXDataset() {
     167              55 :     if(!bIsOverview) {
     168              11 :   if(blxcontext) {
     169              11 :       blxclose(blxcontext);
     170              11 :       blx_free_context(blxcontext);
     171                 :   }
     172              55 :   for(int i=0; i < nOverviewCount; i++)
     173              44 :       if(papoOverviewDS[i])
     174              44 :     delete papoOverviewDS[i];
     175                 :     }
     176              55 : }
     177                 : 
     178                 : 
     179               8 : CPLErr BLXDataset::GetGeoTransform( double * padfTransform )
     180                 : 
     181                 : {
     182               8 :     padfTransform[0] = blxcontext->lon;
     183               8 :     padfTransform[1] = blxcontext->pixelsize_lon;
     184               8 :     padfTransform[2] = 0.0;
     185               8 :     padfTransform[3] = blxcontext->lat;
     186               8 :     padfTransform[4] = 0.0;
     187               8 :     padfTransform[5] = blxcontext->pixelsize_lat;
     188                 : 
     189               8 :     return CE_None;
     190                 : }
     191                 : 
     192               6 : const char *BLXDataset::GetProjectionRef()
     193                 : {
     194               6 :     return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
     195                 : }
     196                 : 
     197              55 : BLXRasterBand::BLXRasterBand( BLXDataset *poDS, int nBand, int overviewLevel )
     198                 : 
     199                 : {
     200              55 :     BLXDataset *poGDS = (BLXDataset *) poDS;
     201                 : 
     202              55 :     this->poDS = poDS;
     203              55 :     this->nBand = nBand;
     204              55 :     this->overviewLevel = overviewLevel;
     205                 :     
     206              55 :     eDataType = GDT_Int16;
     207                 : 
     208              55 :     nBlockXSize = poGDS->blxcontext->cell_xsize >> overviewLevel;
     209              55 :     nBlockYSize = poGDS->blxcontext->cell_ysize >> overviewLevel;
     210              55 : }
     211                 : 
     212               1 : int BLXRasterBand::GetOverviewCount()
     213                 : {
     214               1 :     BLXDataset *poGDS = (BLXDataset *) poDS;
     215                 :     
     216               1 :     return poGDS->nOverviewCount;
     217                 : }
     218                 : 
     219               4 : GDALRasterBand *BLXRasterBand::GetOverview( int i )
     220                 : {
     221               4 :     BLXDataset        *poGDS = (BLXDataset *) poDS;
     222                 : 
     223               4 :     if( i < 0 || i >= poGDS->nOverviewCount )
     224               0 :   return NULL;
     225                 :     else
     226               4 :       return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
     227                 : }
     228                 : 
     229             192 : CPLErr BLXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     230                 :                                   void * pImage )
     231                 : 
     232                 : {
     233             192 :     BLXDataset *poGDS = (BLXDataset *) poDS;
     234                 : 
     235             192 :     if(blx_readcell(poGDS->blxcontext, nBlockYOff, nBlockXOff, (short *)pImage, nBlockXSize*nBlockYSize*2, overviewLevel) == NULL) {
     236                 :   CPLError(CE_Failure, CPLE_AppDefined,
     237               0 :      "Failed to read BLX cell");
     238               0 :   return CE_Failure;
     239                 :     }
     240                 : 
     241             192 :     return CE_None;
     242                 : }
     243                 : 
     244               6 : double BLXRasterBand::GetNoDataValue( int * pbSuccess )
     245                 : {
     246               6 :     if (pbSuccess)
     247               6 :         *pbSuccess = TRUE;
     248               6 :     return BLX_UNDEF;
     249                 : }
     250                 : 
     251               0 : GDALColorInterp BLXRasterBand::GetColorInterpretation(void) {
     252               0 :     return GCI_GrayIndex;
     253                 : }
     254                 : 
     255                 : /* TODO: check if georeference is the same as for BLX files, WGS84
     256                 : */
     257                 : static GDALDataset *
     258              20 : BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     259                 :                 int bStrict, char ** papszOptions, 
     260                 :                 GDALProgressFunc pfnProgress, void * pProgressData )
     261                 : 
     262                 : {
     263              20 :     int  nBands = poSrcDS->GetRasterCount();
     264              20 :     int  nXSize = poSrcDS->GetRasterXSize();
     265              20 :     int  nYSize = poSrcDS->GetRasterYSize();
     266                 :     
     267              20 :     int zscale = 1;
     268              20 :     int fillundef = 1, fillundefval = 0;
     269              20 :     int endian = LITTLEENDIAN;
     270                 : 
     271                 : // -------------------------------------------------------------------- 
     272                 : //      Some rudimentary checks                                    
     273                 : // -------------------------------------------------------------------- 
     274              20 :     if( nBands != 1 )
     275                 :     {
     276                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     277                 :                   "BLX driver doesn't support %d bands.  Must be 1 (grey) ",
     278               5 :                   nBands );
     279               5 :         return NULL;
     280                 :     }
     281                 : 
     282              15 :     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int16 && bStrict )
     283                 :     {
     284                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     285                 :                   "BLX driver doesn't support data type %s. "
     286                 :                   "Only 16 bit byte bands supported.\n", 
     287                 :                   GDALGetDataTypeName( 
     288              10 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
     289                 : 
     290              10 :         return NULL;
     291                 :     }
     292                 : 
     293               5 :     if( (nXSize % 128 != 0) || (nYSize % 128 != 0) ) {
     294                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     295               1 :                   "BLX driver doesn't support dimensions that are not a multiple of 128.\n");
     296                 : 
     297               1 :         return NULL;
     298                 :     }
     299                 :     
     300                 : // -------------------------------------------------------------------- 
     301                 : //      What options has the user selected?                             
     302                 : // -------------------------------------------------------------------- 
     303               4 :     if( CSLFetchNameValue(papszOptions,"ZSCALE") != NULL ) {
     304               0 :         zscale = atoi(CSLFetchNameValue(papszOptions,"ZSCALE"));
     305               0 :         if( zscale < 1 ) {
     306                 :             CPLError( CE_Failure, CPLE_IllegalArg,
     307                 :                       "ZSCALE=%s is not a legal value in the range >= 1.",
     308               0 :                       CSLFetchNameValue(papszOptions,"ZSCALE") );
     309               0 :             return NULL;
     310                 :         }
     311                 :     }
     312                 : 
     313               4 :     if( CSLFetchNameValue(papszOptions,"FILLUNDEF") != NULL 
     314                 :                 && EQUAL(CSLFetchNameValue(papszOptions,"FILLUNDEF"),"NO") )
     315               0 :   fillundef = 0;
     316                 :     else  
     317               4 :   fillundef = 1;
     318                 : 
     319               4 :     if( CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") != NULL ) {
     320               0 :         fillundefval = atoi(CSLFetchNameValue(papszOptions,"FILLUNDEFVAL"));
     321               0 :         if( (fillundefval < -32768) || (fillundefval > 32767) ) {
     322                 :             CPLError( CE_Failure, CPLE_IllegalArg,
     323                 :                       "FILLUNDEFVAL=%s is not a legal value in the range -32768, 32767.",
     324               0 :                       CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") );
     325               0 :             return NULL;
     326                 :         }
     327                 :     }
     328               4 :     if( CSLFetchNameValue(papszOptions,"BIGENDIAN") != NULL 
     329                 :   && !EQUAL(CSLFetchNameValue(papszOptions,"BIGENDIAN"),"NO") )
     330               1 :   endian = BIGENDIAN;
     331                 :   
     332                 :     
     333                 : 
     334                 : // -------------------------------------------------------------------- 
     335                 : //      Create the dataset.                                             
     336                 : // -------------------------------------------------------------------- 
     337                 :     blxcontext_t *ctx;
     338                 : 
     339                 :     // Create a BLX context
     340               4 :     ctx = blx_create_context();
     341                 : 
     342                 :     // Setup BLX parameters
     343               4 :     ctx->cell_rows = nYSize / ctx->cell_ysize;
     344               4 :     ctx->cell_cols = nXSize / ctx->cell_xsize;
     345               4 :     ctx->zscale = zscale;
     346               4 :     ctx->fillundef = fillundef;
     347               4 :     ctx->fillundefval = fillundefval;
     348               4 :     ctx->endian = endian;
     349                 : 
     350               4 :     if(blxopen(ctx, pszFilename, "wb")) {
     351                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     352                 :                   "Unable to create blx file %s.\n", 
     353               2 :                   pszFilename );
     354               2 :         blx_free_context(ctx);
     355               2 :         return NULL;
     356                 :     }
     357                 : 
     358                 : // -------------------------------------------------------------------- 
     359                 : //      Loop over image, copying image data.                            
     360                 : // -------------------------------------------------------------------- 
     361                 :     GInt16     *pabyTile;
     362               2 :     CPLErr      eErr=CE_None;
     363                 : 
     364               2 :     pabyTile = (GInt16 *) VSIMalloc( sizeof(GInt16)*ctx->cell_xsize*ctx->cell_ysize );
     365               2 :     if (pabyTile == NULL)
     366                 :     {
     367               0 :         CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
     368               0 :         blxclose(ctx);
     369               0 :         blx_free_context(ctx);
     370               0 :         return NULL;
     371                 :     }
     372                 : 
     373               2 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     374               0 :         eErr = CE_Failure;
     375                 : 
     376              10 :     for(int i=0; (i < ctx->cell_rows) && (eErr == CE_None); i++)
     377              40 :   for(int j=0; j < ctx->cell_cols; j++) {
     378                 :       blxdata *celldata;
     379              32 :       GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
     380                 :       eErr = poBand->RasterIO( GF_Read, j*ctx->cell_xsize, i*ctx->cell_ysize, 
     381                 :              ctx->cell_xsize, ctx->cell_ysize, 
     382                 :              pabyTile, ctx->cell_xsize, ctx->cell_ysize, GDT_Int16,
     383              32 :              0, 0 );
     384              32 :       if(eErr >= CE_Failure) 
     385               0 :          break;
     386              32 :       celldata = pabyTile;
     387              32 :       if (blx_writecell(ctx, celldata, i, j) != 0)
     388                 :             {
     389               0 :                 eErr = CE_Failure;
     390               0 :                 break;
     391                 :             }
     392                 : 
     393              32 :             if ( ! pfnProgress( 1.0 * (i * ctx->cell_cols + j) / (ctx->cell_rows * ctx->cell_cols), NULL, pProgressData ))
     394                 :             {
     395               0 :                 eErr = CE_Failure;
     396               0 :                 break;
     397                 :             }
     398                 :     }
     399                 : 
     400               2 :     pfnProgress( 1.0, NULL, pProgressData );
     401                 : 
     402               2 :     CPLFree( pabyTile );
     403                 : 
     404                 :     double        adfGeoTransform[6];
     405               2 :     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     406                 :     {
     407               2 :   ctx->lon = adfGeoTransform[0];
     408               2 :   ctx->lat = adfGeoTransform[3];
     409               2 :   ctx->pixelsize_lon = adfGeoTransform[1]; 
     410               2 :   ctx->pixelsize_lat = adfGeoTransform[5]; 
     411                 :     }
     412                 : 
     413               2 :     blxclose(ctx);
     414               2 :     blx_free_context(ctx);
     415                 : 
     416               2 :     if (eErr == CE_None)
     417               2 :         return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
     418                 :     else
     419               0 :         return NULL;
     420                 : }
     421                 : 
     422                 : 
     423             558 : void GDALRegister_BLX()
     424                 : 
     425                 : {
     426                 :     GDALDriver  *poDriver;
     427                 : 
     428             558 :     if( GDALGetDriverByName( "BLX" ) == NULL )
     429                 :     {
     430             537 :         poDriver = new GDALDriver();
     431                 :         
     432             537 :         poDriver->SetDescription( "BLX" );
     433                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     434             537 :                                    "Magellan topo (.blx)" );
     435                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     436             537 :                                    "frmt_various.html#BLX" );
     437             537 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "blx" );
     438                 : 
     439             537 :         poDriver->pfnOpen = BLXDataset::Open;
     440             537 :   poDriver->pfnCreateCopy = BLXCreateCopy;
     441                 : 
     442             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     443                 :     }
     444             558 : }
     445                 : 

Generated by: LCOV version 1.7