LCOV - code coverage report
Current view: directory - frmts/pcraster - pcrasterdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 122 106 86.9 %
Date: 2012-12-26 Functions: 15 10 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: pcrasterdataset.cpp 22609 2011-06-28 21:01:48Z rouault $
       3                 :  *
       4                 :  * Project:  PCRaster Integration
       5                 :  * Purpose:  PCRaster CSF 2.0 raster file driver
       6                 :  * Author:   Kor de Jong, k.dejong at geog.uu.nl
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Kor de Jong
      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 "gdal_pam.h"
      31                 : #include "cpl_string.h"
      32                 : 
      33                 : CPL_CVSID("$Id: pcrasterdataset.cpp 22609 2011-06-28 21:01:48Z rouault $");
      34                 : 
      35                 : #ifndef INCLUDED_PCRASTERDATASET
      36                 : #include "pcrasterdataset.h"
      37                 : #define INCLUDED_PCRASTERDATASET
      38                 : #endif
      39                 : 
      40                 : #ifndef INCLUDED_IOSTREAM
      41                 : #include <iostream>
      42                 : #define INCLUDED_IOSTREAM
      43                 : #endif
      44                 : 
      45                 : // PCRaster library headers.
      46                 : 
      47                 : // Module headers.
      48                 : #ifndef INCLUDED_PCRASTERRASTERBAND
      49                 : #include "pcrasterrasterband.h"
      50                 : #define INCLUDED_PCRASTERRASTERBAND
      51                 : #endif
      52                 : 
      53                 : #ifndef INCLUDED_PCRASTERUTIL
      54                 : #include "pcrasterutil.h"
      55                 : #define INCLUDED_PCRASTERUTIL
      56                 : #endif
      57                 : 
      58                 : 
      59                 : 
      60                 : /*!
      61                 :   \file
      62                 :   This file contains the implementation of the PCRasterDataset class.
      63                 : */
      64                 : 
      65                 : 
      66                 : 
      67                 : //------------------------------------------------------------------------------
      68                 : // DEFINITION OF STATIC PCRDATASET MEMBERS
      69                 : //------------------------------------------------------------------------------
      70                 : 
      71                 : //! Tries to open the file described by \a info.
      72                 : /*!
      73                 :   \param     info Object with information about the dataset to open.
      74                 :   \return    Pointer to newly allocated GDALDataset or 0.
      75                 : 
      76                 :   Returns 0 if the file could not be opened.
      77                 : */
      78           13562 : GDALDataset* PCRasterDataset::open(
      79                 :          GDALOpenInfo* info)
      80                 : {
      81           13562 :   PCRasterDataset* dataset = 0;
      82                 : 
      83           13562 :   if(info->fp && info->nHeaderBytes >= static_cast<int>(CSF_SIZE_SIG) &&
      84                 :          strncmp((char*)info->pabyHeader, CSF_SIG, CSF_SIZE_SIG) == 0) {
      85                 :     MOPEN_PERM mode = info->eAccess == GA_Update
      86                 :          ? M_READ_WRITE
      87               6 :          : M_READ;
      88                 : 
      89               6 :     MAP* map = mapOpen(info->pszFilename, mode);
      90                 : 
      91               6 :     if(map) {
      92               6 :       dataset = new PCRasterDataset(map);
      93                 :     }
      94                 :   }
      95                 : 
      96                 : /* -------------------------------------------------------------------- */
      97                 : /*      Initialize any PAM information and overviews.                   */
      98                 : /* -------------------------------------------------------------------- */
      99           13562 :   if( dataset )
     100                 :   {
     101               6 :       dataset->SetDescription( info->pszFilename );
     102               6 :       dataset->TryLoadXML();
     103                 : 
     104               6 :       dataset->oOvManager.Initialize( dataset, info->pszFilename );
     105                 :   }
     106                 : 
     107           13562 :   return dataset;
     108                 : }
     109                 : 
     110                 : 
     111                 : 
     112                 : //! Writes a raster to \a filename as a PCRaster raster file.
     113                 : /*!
     114                 :   \warning   The source raster must have only 1 band. Currently, the values in
     115                 :              the source raster must be stored in one of the supported cell
     116                 :              representations (CR_UINT1, CR_INT4, CR_REAL4, CR_REAL8).
     117                 : 
     118                 :   The meta data item PCRASTER_VALUESCALE will be checked to see what value
     119                 :   scale to use. Otherwise a value scale is determined using
     120                 :   GDALType2ValueScale(GDALDataType).
     121                 : 
     122                 :   This function always writes rasters using CR_UINT1, CR_INT4 or CR_REAL4
     123                 :   cell representations.
     124                 : */
     125              22 : GDALDataset* PCRasterDataset::createCopy(
     126                 :          char const* filename,
     127                 :          GDALDataset* source,
     128                 :          int strict,
     129                 :          char** options,
     130                 :          GDALProgressFunc progress,
     131                 :          void* progressData)
     132                 : {
     133                 :   // Checks.
     134              22 :   int nrBands = source->GetRasterCount();
     135              22 :   if(nrBands != 1) {
     136                 :     CPLError(CE_Failure, CPLE_NotSupported,
     137               5 :          "PCRaster driver: Too many bands ('%d'): must be 1 band", nrBands);
     138               5 :     return 0;
     139                 :   }
     140                 : 
     141              17 :   GDALRasterBand* raster = source->GetRasterBand(1);
     142                 : 
     143                 :   // Create PCRaster raster. Determine properties of raster to create.
     144              17 :   size_t nrRows = raster->GetYSize();
     145              17 :   size_t nrCols = raster->GetXSize();
     146              17 :   std::string string;
     147                 : 
     148                 :   // The in-file type of the cells.
     149                 :   CSF_CR fileCellRepresentation = GDALType2CellRepresentation(
     150              17 :          raster->GetRasterDataType(), false);
     151                 : 
     152              17 :   if(fileCellRepresentation == CR_UNDEFINED) {
     153                 :     CPLError(CE_Failure, CPLE_NotSupported,
     154               4 :          "PCRaster driver: Cannot determine a valid cell representation");
     155               4 :     return 0;
     156                 :   }
     157                 : 
     158                 :   // The value scale of the values.
     159              13 :   CSF_VS valueScale = VS_UNDEFINED;
     160              13 :   if(source->GetMetadataItem("PCRASTER_VALUESCALE")) {
     161               0 :     string = source->GetMetadataItem("PCRASTER_VALUESCALE");
     162                 :   }
     163                 : 
     164                 :   valueScale = !string.empty()
     165                 :          ? string2ValueScale(string)
     166              13 :          : GDALType2ValueScale(raster->GetRasterDataType());
     167                 : 
     168              13 :   if(valueScale == VS_UNDEFINED) {
     169                 :     CPLError(CE_Failure, CPLE_NotSupported,
     170               0 :          "PCRaster driver: Cannot determine a valid value scale");
     171               0 :     return 0;
     172                 :   }
     173                 : 
     174              13 :   CSF_PT const projection = PT_YDECT2B;
     175              13 :   REAL8  const angle = 0.0;
     176              13 :   REAL8 west = 0.0;
     177              13 :   REAL8 north = 0.0;
     178              13 :   REAL8 cellSize = 1.0;
     179                 : 
     180                 :   double transform[6];
     181              13 :   if(source->GetGeoTransform(transform) == CE_None) {
     182              13 :     if(transform[2] == 0.0 && transform[4] == 0.0) {
     183              13 :       west = static_cast<REAL8>(transform[0]);
     184              13 :       north = static_cast<REAL8>(transform[3]);
     185              13 :       cellSize = static_cast<REAL8>(transform[1]);
     186                 :     }
     187                 :   }
     188                 : 
     189                 :   // The in-memory type of the cells.
     190              13 :   CSF_CR appCellRepresentation = CR_UNDEFINED;
     191                 :   appCellRepresentation = GDALType2CellRepresentation(
     192              13 :          raster->GetRasterDataType(), true);
     193                 : 
     194              13 :   if(appCellRepresentation == CR_UNDEFINED) {
     195                 :     CPLError(CE_Failure, CPLE_NotSupported,
     196               0 :          "PCRaster driver: Cannot determine a valid cell representation");
     197               0 :     return 0;
     198                 :   }
     199                 : 
     200                 :   // Check whether value scale fits the cell representation. Adjust when
     201                 :   // needed.
     202              13 :   valueScale = fitValueScale(valueScale, appCellRepresentation);
     203                 : 
     204                 :   // Create a raster with the in file cell representation.
     205                 :   MAP* map = Rcreate(filename, nrRows, nrCols, fileCellRepresentation,
     206              13 :          valueScale, projection, west, north, angle, cellSize);
     207                 : 
     208              13 :   if(!map) {
     209                 :     CPLError(CE_Failure, CPLE_OpenFailed,
     210               6 :          "PCRaster driver: Unable to create raster %s", filename);
     211               6 :     return 0;
     212                 :   }
     213                 : 
     214                 :   // Try to convert in app cell representation to the cell representation
     215                 :   // of the file.
     216               7 :   if(RuseAs(map, appCellRepresentation)) {
     217                 :     CPLError(CE_Failure, CPLE_NotSupported,
     218               3 :          "PCRaster driver: Cannot convert cells: %s", MstrError());
     219               3 :     Mclose(map);
     220               3 :     return 0;
     221                 :   }
     222                 : 
     223                 :   int hasMissingValue;
     224               4 :   double missingValue = raster->GetNoDataValue(&hasMissingValue);
     225                 : 
     226                 :   // This is needed to get my (KDJ) unit tests running.
     227                 :   // I am still uncertain why this is needed. If the input raster has float32
     228                 :   // values and the output int32, than the missing value in the dataset object
     229                 :   // is not updated like the values are.
     230               4 :   if(missingValue == ::missingValue(CR_REAL4) &&
     231                 :          fileCellRepresentation == CR_INT4) {
     232               0 :     missingValue = ::missingValue(fileCellRepresentation);
     233                 :   }
     234                 : 
     235                 :   // TODO conversie van INT2 naar INT4 ondersteunen. zie ruseas.c regel 503.
     236                 :   // conversie op r 159.
     237                 : 
     238                 :   // Create buffer for one row of values.
     239               4 :   void* buffer = Rmalloc(map, nrCols);
     240                 : 
     241                 :   // Copy values from source to target.
     242               4 :   CPLErr errorCode = CE_None;
     243              44 :   for(size_t row = 0; errorCode == CE_None && row < nrRows; ++row) {
     244                 : 
     245                 :     // Get row from source.
     246              40 :     if(raster->RasterIO(GF_Read, 0, row, nrCols, 1, buffer, nrCols, 1,
     247                 :          raster->GetRasterDataType(), 0, 0) != CE_None) {
     248                 :       CPLError(CE_Failure, CPLE_FileIO,
     249               0 :          "PCRaster driver: Error reading from source raster");
     250               0 :       errorCode = CE_Failure;
     251               0 :       break;
     252                 :     }
     253                 : 
     254                 :     // Upon reading values are converted to the
     255                 :     // right data type. This includes the missing value. If the source
     256                 :     // value cannot be represented in the target data type it is set to a
     257                 :     // missing value.
     258                 : 
     259              40 :     if(hasMissingValue) {
     260               0 :       alterToStdMV(buffer, nrCols, appCellRepresentation, missingValue);
     261                 :     }
     262                 : 
     263              40 :     if(valueScale == VS_BOOLEAN) {
     264              10 :       castValuesToBooleanRange(buffer, nrCols, appCellRepresentation);
     265                 :     }
     266                 : 
     267                 :     // Write row in target.
     268              40 :     RputRow(map, row, buffer);
     269                 : 
     270              40 :     if(!progress((row + 1) / (static_cast<double>(nrRows)), 0, progressData)) {
     271                 :       CPLError(CE_Failure, CPLE_UserInterrupt,
     272               0 :          "PCRaster driver: User terminated CreateCopy()");
     273               0 :       errorCode = CE_Failure;
     274               0 :       break;
     275                 :     }
     276                 :   }
     277                 : 
     278               4 :   Mclose(map);
     279               4 :   map = 0;
     280                 : 
     281               4 :   free(buffer);
     282               4 :   buffer = 0;
     283                 : 
     284               4 :   if( errorCode != CE_None )
     285               0 :       return NULL;
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Re-open dataset, and copy any auxilary pam information.         */
     289                 : /* -------------------------------------------------------------------- */
     290                 :   GDALPamDataset *poDS = (GDALPamDataset *) 
     291               4 :         GDALOpen( filename, GA_Update );
     292                 : 
     293               4 :   if( poDS )
     294               4 :       poDS->CloneInfo( source, GCIF_PAM_DEFAULT );
     295                 :   
     296               4 :   return poDS;
     297                 : }
     298                 : 
     299                 : 
     300                 : 
     301                 : //------------------------------------------------------------------------------
     302                 : // DEFINITION OF PCRDATASET MEMBERS
     303                 : //------------------------------------------------------------------------------
     304                 : 
     305                 : //! Constructor.
     306                 : /*!
     307                 :   \param     map PCRaster map handle. It is ours to close.
     308                 : */
     309               6 : PCRasterDataset::PCRasterDataset(
     310                 :          MAP* map)
     311                 : 
     312                 :   : GDALPamDataset(),
     313               6 :     d_map(map), d_west(0.0), d_north(0.0), d_cellSize(0.0)
     314                 : 
     315                 : {
     316                 :   // Read header info.
     317               6 :   nRasterXSize = RgetNrCols(d_map);
     318               6 :   nRasterYSize = RgetNrRows(d_map);
     319               6 :   d_west = static_cast<double>(RgetXUL(d_map));
     320               6 :   d_north = static_cast<double>(RgetYUL(d_map));
     321               6 :   d_cellSize = static_cast<double>(RgetCellSize(d_map));
     322               6 :   d_cellRepresentation = RgetUseCellRepr(d_map);
     323               6 :   CPLAssert(d_cellRepresentation != CR_UNDEFINED);
     324               6 :   d_valueScale = RgetValueScale(d_map);
     325               6 :   CPLAssert(d_valueScale != VS_UNDEFINED);
     326               6 :   d_missingValue = ::missingValue(d_cellRepresentation);
     327                 : 
     328                 :   // Create band information objects.
     329               6 :   nBands = 1;
     330               6 :   SetBand(1, new PCRasterRasterBand(this));
     331                 : 
     332                 :   SetMetadataItem("PCRASTER_VALUESCALE", valueScale2String(
     333               6 :          d_valueScale).c_str());
     334               6 : }
     335                 : 
     336                 : 
     337                 : 
     338                 : //! Destructor.
     339                 : /*!
     340                 :   \warning   The map given in the constructor is closed.
     341                 : */
     342               6 : PCRasterDataset::~PCRasterDataset()
     343                 : {
     344               6 :     FlushCache();
     345               6 :     Mclose(d_map);
     346               6 : }
     347                 : 
     348                 : 
     349                 : 
     350                 : //! Sets projections info.
     351                 : /*!
     352                 :   \param     transform Array to fill.
     353                 : 
     354                 :   CSF 2.0 supports the notion of y coordinates which increase from north to
     355                 :   south. Support for this has been dropped and applications reading PCRaster
     356                 :   rasters will treat or already treat y coordinates as increasing from south
     357                 :   to north only.
     358                 : */
     359               5 : CPLErr PCRasterDataset::GetGeoTransform(double* transform)
     360                 : {
     361                 :   // x = west + nrCols * cellsize
     362               5 :   transform[0] = d_west;
     363               5 :   transform[1] = d_cellSize;
     364               5 :   transform[2] = 0.0;
     365                 : 
     366                 :   // y = north + nrRows * -cellsize
     367               5 :   transform[3] = d_north;
     368               5 :   transform[4] = 0.0;
     369               5 :   transform[5] = -1.0 * d_cellSize;
     370                 : 
     371               5 :   return CE_None;
     372                 : }
     373                 : 
     374                 : 
     375                 : 
     376                 : //! Returns the map handle.
     377                 : /*!
     378                 :   \return    Map handle.
     379                 : */
     380             100 : MAP* PCRasterDataset::map() const
     381                 : {
     382             100 :   return d_map;
     383                 : }
     384                 : 
     385                 : 
     386                 : 
     387                 : //! Returns the in-app cell representation.
     388                 : /*!
     389                 :   \return    cell representation
     390                 :   \warning   This might not be the same representation as use to store the values in the file.
     391                 :   \sa        valueScale()
     392                 : */
     393             106 : CSF_CR PCRasterDataset::cellRepresentation() const
     394                 : {
     395             106 :   return d_cellRepresentation;
     396                 : }
     397                 : 
     398                 : 
     399                 : 
     400                 : //! Returns the value scale of the data.
     401                 : /*!
     402                 :   \return    Value scale
     403                 :   \sa        cellRepresentation()
     404                 : */
     405               0 : CSF_VS PCRasterDataset::valueScale() const
     406                 : {
     407               0 :   return d_valueScale;
     408                 : }
     409                 : 
     410                 : 
     411                 : 
     412                 : //! Returns the value of the missing value.
     413                 : /*!
     414                 :   \return    Missing value
     415                 : */
     416             101 : double PCRasterDataset::missingValue() const
     417                 : {
     418             101 :   return d_missingValue;
     419            2139 : }
     420                 : 
     421                 : 
     422                 : 
     423                 : //------------------------------------------------------------------------------
     424                 : // DEFINITION OF FREE OPERATORS
     425                 : //------------------------------------------------------------------------------
     426                 : 
     427                 : 
     428                 : 
     429                 : //------------------------------------------------------------------------------
     430                 : // DEFINITION OF FREE FUNCTIONS
     431                 : //------------------------------------------------------------------------------
     432                 : 
     433                 : 
     434                 : 

Generated by: LCOV version 1.7