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

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

Generated by: LCOV version 1.7