LCOV - code coverage report
Current view: top level - frmts/pcraster - pcrasterrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 44 158 27.8 %
Date: 2024-11-25 13:07:18 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PCRaster Integration
       4             :  * Purpose:  PCRaster raster band implementation.
       5             :  * Author:   Kor de Jong, Oliver Schmitz
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) PCRaster owners
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "csf.h"
      14             : #include "csfimpl.h"
      15             : #include "pcrasterdataset.h"
      16             : #include "pcrasterrasterband.h"
      17             : #include "pcrasterutil.h"
      18             : 
      19             : /*!
      20             :   \file
      21             :   This file contains the implementation of the PCRasterRasterBand class.
      22             : */
      23             : 
      24             : //------------------------------------------------------------------------------
      25             : // DEFINITION OF PCRRASTERBAND MEMBERS
      26             : //------------------------------------------------------------------------------
      27             : 
      28             : //! Constructor.
      29             : /*!
      30             :   \param     dataset The dataset we are a part of.
      31             : */
      32          13 : PCRasterRasterBand::PCRasterRasterBand(PCRasterDataset *dataset)
      33             :     : GDALPamRasterBand(), d_dataset(dataset), d_noDataValue(),
      34          13 :       d_defaultNoDataValueOverridden(false), d_create_in(GDT_Unknown)
      35             : {
      36          13 :     poDS = dataset;
      37          13 :     nBand = 1;
      38          13 :     eDataType = cellRepresentation2GDALType(dataset->cellRepresentation());
      39          13 :     nBlockXSize = dataset->GetRasterXSize();
      40          13 :     nBlockYSize = 1;
      41          13 : }
      42             : 
      43             : //! Destructor.
      44             : /*!
      45             :  */
      46          26 : PCRasterRasterBand::~PCRasterRasterBand()
      47             : {
      48          26 : }
      49             : 
      50         455 : double PCRasterRasterBand::GetNoDataValue(int *success)
      51             : {
      52         455 :     if (success)
      53             :     {
      54          12 :         *success = 1;
      55             :     }
      56             : 
      57         455 :     return d_defaultNoDataValueOverridden ? d_noDataValue
      58         455 :                                           : d_dataset->defaultNoDataValue();
      59             : }
      60             : 
      61           0 : double PCRasterRasterBand::GetMinimum(int *success)
      62             : {
      63             :     double result;
      64             :     bool isValid;
      65             : 
      66           0 :     switch (d_dataset->cellRepresentation())
      67             :     {
      68             :         // CSF version 2.
      69             :         // ----------------------------------------------------------
      70           0 :         case CR_UINT1:
      71             :         {
      72             :             UINT1 min;
      73           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
      74           0 :             result = static_cast<double>(min);
      75           0 :             break;
      76             :         }
      77           0 :         case CR_INT4:
      78             :         {
      79             :             INT4 min;
      80           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
      81           0 :             result = static_cast<double>(min);
      82           0 :             break;
      83             :         }
      84           0 :         case CR_REAL4:
      85             :         {
      86             :             REAL4 min;
      87           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
      88           0 :             result = static_cast<double>(min);
      89           0 :             break;
      90             :         }
      91           0 :         case CR_REAL8:
      92             :         {
      93             :             REAL8 min;
      94           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
      95           0 :             result = static_cast<double>(min);
      96           0 :             break;
      97             :         }
      98             :         // CSF version 1.
      99             :         // ----------------------------------------------------------
     100           0 :         case CR_INT1:
     101             :         {
     102             :             INT1 min;
     103           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
     104           0 :             result = static_cast<double>(min);
     105           0 :             break;
     106             :         }
     107           0 :         case CR_INT2:
     108             :         {
     109             :             INT2 min;
     110           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
     111           0 :             result = static_cast<double>(min);
     112           0 :             break;
     113             :         }
     114           0 :         case CR_UINT2:
     115             :         {
     116             :             UINT2 min;
     117           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
     118           0 :             result = static_cast<double>(min);
     119           0 :             break;
     120             :         }
     121           0 :         case CR_UINT4:
     122             :         {
     123             :             UINT4 min;
     124           0 :             isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
     125           0 :             result = static_cast<double>(min);
     126           0 :             break;
     127             :         }
     128           0 :         default:
     129             :         {
     130           0 :             result = 0.0;
     131           0 :             isValid = false;
     132           0 :             break;
     133             :         }
     134             :     }
     135             : 
     136           0 :     if (success)
     137             :     {
     138           0 :         *success = isValid ? 1 : 0;
     139             :     }
     140             : 
     141           0 :     return result;
     142             : }
     143             : 
     144           0 : double PCRasterRasterBand::GetMaximum(int *success)
     145             : {
     146             :     double result;
     147             :     bool isValid;
     148             : 
     149           0 :     switch (d_dataset->cellRepresentation())
     150             :     {
     151           0 :         case CR_UINT1:
     152             :         {
     153             :             UINT1 max;
     154           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     155           0 :             result = static_cast<double>(max);
     156           0 :             break;
     157             :         }
     158           0 :         case CR_INT4:
     159             :         {
     160             :             INT4 max;
     161           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     162           0 :             result = static_cast<double>(max);
     163           0 :             break;
     164             :         }
     165           0 :         case CR_REAL4:
     166             :         {
     167             :             REAL4 max;
     168           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     169           0 :             result = static_cast<double>(max);
     170           0 :             break;
     171             :         }
     172             :         // CSF version 1.
     173             :         // ----------------------------------------------------------
     174           0 :         case CR_INT1:
     175             :         {
     176             :             INT1 max;
     177           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     178           0 :             result = static_cast<double>(max);
     179           0 :             break;
     180             :         }
     181           0 :         case CR_INT2:
     182             :         {
     183             :             INT2 max;
     184           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     185           0 :             result = static_cast<double>(max);
     186           0 :             break;
     187             :         }
     188           0 :         case CR_UINT2:
     189             :         {
     190             :             UINT2 max;
     191           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     192           0 :             result = static_cast<double>(max);
     193           0 :             break;
     194             :         }
     195           0 :         case CR_UINT4:
     196             :         {
     197             :             UINT4 max;
     198           0 :             isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
     199           0 :             result = static_cast<double>(max);
     200           0 :             break;
     201             :         }
     202           0 :         default:
     203             :         {
     204           0 :             result = 0.0;
     205           0 :             isValid = false;
     206           0 :             break;
     207             :         }
     208             :     }
     209             : 
     210           0 :     if (success)
     211             :     {
     212           0 :         *success = isValid ? 1 : 0;
     213             :     }
     214             : 
     215           0 :     return result;
     216             : }
     217             : 
     218         420 : CPLErr PCRasterRasterBand::IReadBlock(CPL_UNUSED int nBlockXoff, int nBlockYoff,
     219             :                                       void *buffer)
     220             : {
     221         420 :     size_t nrCellsRead = RgetRow(d_dataset->map(), nBlockYoff, buffer);
     222             : 
     223             :     // Now we have raw values, missing values are set according to the CSF
     224             :     // conventions. This means that floating points should not be evaluated.
     225             :     // Since this is done by the GDal library we replace these with valid
     226             :     // values. Non-MV values are not touched.
     227             : 
     228             :     // Replace in-file MV with in-app MV which may be different.
     229         420 :     alterFromStdMV(buffer, nrCellsRead, d_dataset->cellRepresentation(),
     230             :                    GetNoDataValue());
     231             : 
     232         420 :     return CE_None;
     233             : }
     234             : 
     235         441 : CPLErr PCRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     236             :                                      int nXSize, int nYSize, void *pData,
     237             :                                      int nBufXSize, int nBufYSize,
     238             :                                      GDALDataType eBufType,
     239             :                                      GSpacing nPixelSpace, GSpacing nLineSpace,
     240             :                                      GDALRasterIOExtraArg *psExtraArg)
     241             : {
     242         441 :     if (eRWFlag == GF_Read)
     243             :     {
     244             :         // read should just be the default
     245         440 :         return GDALRasterBand::IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
     246             :                                          pData, nBufXSize, nBufYSize, eBufType,
     247         440 :                                          nPixelSpace, nLineSpace, psExtraArg);
     248             :     }
     249             :     else
     250             :     {
     251             :         // the datatype of the incoming data can be of different type than the
     252             :         // cell representation used in the raster
     253             :         // 'remember' the GDAL type to distinguish it later on in iWriteBlock
     254           1 :         d_create_in = eBufType;
     255           1 :         return GDALRasterBand::IRasterIO(GF_Write, nXOff, nYOff, nXSize, nYSize,
     256             :                                          pData, nBufXSize, nBufYSize, eBufType,
     257           1 :                                          nPixelSpace, nLineSpace, psExtraArg);
     258             :     }
     259             : }
     260             : 
     261          20 : CPLErr PCRasterRasterBand::IWriteBlock(CPL_UNUSED int nBlockXoff,
     262             :                                        int nBlockYoff, void *source)
     263             : {
     264          20 :     CSF_VS valuescale = d_dataset->valueScale();
     265             : 
     266          20 :     if (valuescale == VS_LDD)
     267             :     {
     268           0 :         if ((d_create_in == GDT_Byte) || (d_create_in == GDT_Float32) ||
     269           0 :             (d_create_in == GDT_Float64))
     270             :         {
     271           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     272             :                      "PCRaster driver: "
     273             :                      "conversion from %s to LDD not supported",
     274             :                      GDALGetDataTypeName(d_create_in));
     275           0 :             return CE_Failure;
     276             :         }
     277             :     }
     278             : 
     279             :     // set new location attributes to the header
     280          20 :     if (d_dataset->location_changed())
     281             :     {
     282           0 :         REAL8 west = 0.0;
     283           0 :         REAL8 north = 0.0;
     284           0 :         REAL8 cellSize = 1.0;
     285             :         double transform[6];
     286           0 :         if (this->poDS->GetGeoTransform(transform) == CE_None)
     287             :         {
     288           0 :             if (transform[2] == 0.0 && transform[4] == 0.0)
     289             :             {
     290           0 :                 west = static_cast<REAL8>(transform[0]);
     291           0 :                 north = static_cast<REAL8>(transform[3]);
     292           0 :                 cellSize = static_cast<REAL8>(transform[1]);
     293             :             }
     294             :         }
     295           0 :         (void)RputXUL(d_dataset->map(), west);
     296           0 :         (void)RputYUL(d_dataset->map(), north);
     297           0 :         (void)RputCellSize(d_dataset->map(), cellSize);
     298             :     }
     299             : 
     300          20 :     const int nr_cols = this->poDS->GetRasterXSize();
     301             : 
     302             :     // new maps from create() set min/max to MV
     303             :     // in case of reopening that map the min/max
     304             :     // value tracking is disabled (MM_WRONGVALUE)
     305             :     // reactivate it again to ensure that the output will
     306             :     // get the correct values when values are written to map
     307          20 :     d_dataset->map()->minMaxStatus = MM_KEEPTRACK;
     308             : 
     309             :     // allocate memory for row
     310          20 :     void *buffer = Rmalloc(d_dataset->map(), nr_cols);
     311          20 :     memcpy(buffer, source, nr_cols * 4);
     312             : 
     313             :     // convert source no_data values to MV in dest
     314          20 :     switch (valuescale)
     315             :     {
     316           0 :         case VS_BOOLEAN:
     317             :         case VS_LDD:
     318             :         {
     319           0 :             alterToStdMV(buffer, nr_cols, CR_UINT1, GetNoDataValue());
     320           0 :             break;
     321             :         }
     322           0 :         case VS_NOMINAL:
     323             :         case VS_ORDINAL:
     324             :         {
     325           0 :             alterToStdMV(buffer, nr_cols, CR_INT4, GetNoDataValue());
     326           0 :             break;
     327             :         }
     328          20 :         case VS_SCALAR:
     329             :         case VS_DIRECTION:
     330             :         {
     331          20 :             alterToStdMV(buffer, nr_cols, CR_REAL4, GetNoDataValue());
     332          20 :             break;
     333             :         }
     334           0 :         default:
     335             :         {
     336           0 :             break;
     337             :         }
     338             :     }
     339             : 
     340             :     // conversion of values according to value scale
     341          20 :     switch (valuescale)
     342             :     {
     343           0 :         case VS_BOOLEAN:
     344             :         {
     345           0 :             castValuesToBooleanRange(buffer, nr_cols, CR_UINT1);
     346           0 :             break;
     347             :         }
     348           0 :         case VS_LDD:
     349             :         {
     350           0 :             castValuesToLddRange(buffer, nr_cols);
     351           0 :             break;
     352             :         }
     353           0 :         case VS_DIRECTION:
     354             :         {
     355           0 :             castValuesToDirectionRange(buffer, nr_cols);
     356           0 :             break;
     357             :         }
     358          20 :         default:
     359             :         {
     360          20 :             break;
     361             :         }
     362             :     }
     363             : 
     364          20 :     RputRow(d_dataset->map(), nBlockYoff, buffer);
     365          20 :     free(buffer);
     366             : 
     367          20 :     return CE_None;
     368             : }
     369             : 
     370           0 : CPLErr PCRasterRasterBand::SetNoDataValue(double nodata)
     371             : {
     372           0 :     d_noDataValue = nodata;
     373           0 :     d_defaultNoDataValueOverridden = true;
     374             : 
     375           0 :     return CE_None;
     376             : }

Generated by: LCOV version 1.14