LCOV - code coverage report
Current view: top level - gcore - gdalnodatavaluesmaskband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 93 105 88.6 %
Date: 2025-03-25 20:12:57 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Implementation of GDALNoDataValuesMaskBand, a class implementing
       5             :  *           a default band mask based on the NODATA_VALUES metadata item.
       6             :  *           A pixel is considered nodata in all bands if and only if all bands
       7             :  *           match the corresponding value in the NODATA_VALUES tuple
       8             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       9             :  *
      10             :  ******************************************************************************
      11             :  * Copyright (c) 2008-2009, Even Rouault <even dot rouault at spatialys.com>
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  ****************************************************************************/
      15             : 
      16             : #include "cpl_port.h"
      17             : #include "gdal_priv.h"
      18             : 
      19             : #include <cstring>
      20             : 
      21             : #include "cpl_conv.h"
      22             : #include "cpl_error.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_vsi.h"
      25             : #include "gdal.h"
      26             : 
      27             : //! @cond Doxygen_Suppress
      28             : /************************************************************************/
      29             : /*                   GDALNoDataValuesMaskBand()                         */
      30             : /************************************************************************/
      31             : 
      32          66 : GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand(GDALDataset *poDSIn)
      33          66 :     : padfNodataValues(nullptr)
      34             : {
      35          66 :     const char *pszNoDataValues = poDSIn->GetMetadataItem("NODATA_VALUES");
      36             :     char **papszNoDataValues =
      37          66 :         CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
      38             : 
      39          66 :     padfNodataValues = static_cast<double *>(
      40          66 :         CPLMalloc(sizeof(double) * poDSIn->GetRasterCount()));
      41         263 :     for (int i = 0; i < poDSIn->GetRasterCount(); ++i)
      42             :     {
      43         197 :         padfNodataValues[i] = CPLAtof(papszNoDataValues[i]);
      44             :     }
      45             : 
      46          66 :     CSLDestroy(papszNoDataValues);
      47             : 
      48          66 :     poDS = poDSIn;
      49          66 :     nBand = 0;
      50             : 
      51          66 :     nRasterXSize = poDS->GetRasterXSize();
      52          66 :     nRasterYSize = poDS->GetRasterYSize();
      53             : 
      54          66 :     eDataType = GDT_Byte;
      55          66 :     poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
      56          66 : }
      57             : 
      58             : /************************************************************************/
      59             : /*                    ~GDALNoDataValuesMaskBand()                       */
      60             : /************************************************************************/
      61             : 
      62         132 : GDALNoDataValuesMaskBand::~GDALNoDataValuesMaskBand()
      63             : 
      64             : {
      65          66 :     CPLFree(padfNodataValues);
      66         132 : }
      67             : 
      68             : /************************************************************************/
      69             : /*                            FillOutBuffer()                           */
      70             : /************************************************************************/
      71             : 
      72             : template <class T>
      73          44 : static void FillOutBuffer(GPtrDiff_t nBlockOffsetPixels, int nBands,
      74             :                           const void *pabySrc, const double *padfNodataValues,
      75             :                           void *pImage)
      76             : {
      77          44 :     T *paNoData = static_cast<T *>(CPLMalloc(nBands * sizeof(T)));
      78         176 :     for (int iBand = 0; iBand < nBands; ++iBand)
      79             :     {
      80         132 :         paNoData[iBand] = static_cast<T>(padfNodataValues[iBand]);
      81             :     }
      82             : 
      83      324161 :     for (GPtrDiff_t i = 0; i < nBlockOffsetPixels; i++)
      84             :     {
      85      324117 :         int nCountNoData = 0;
      86     1296472 :         for (int iBand = 0; iBand < nBands; ++iBand)
      87             :         {
      88      972351 :             if (static_cast<const T *>(
      89      972351 :                     pabySrc)[i + iBand * nBlockOffsetPixels] == paNoData[iBand])
      90      698884 :                 ++nCountNoData;
      91             :         }
      92      324117 :         static_cast<GByte *>(pImage)[i] = nCountNoData == nBands ? 0 : 255;
      93             :     }
      94             : 
      95          44 :     CPLFree(paNoData);
      96          44 : }
      97             : 
      98             : /************************************************************************/
      99             : /*                             IReadBlock()                             */
     100             : /************************************************************************/
     101             : 
     102          44 : CPLErr GDALNoDataValuesMaskBand::IReadBlock(int nXBlockOff, int nYBlockOff,
     103             :                                             void *pImage)
     104             : 
     105             : {
     106          44 :     GDALDataType eWrkDT = GDT_Unknown;
     107             : 
     108             :     /* -------------------------------------------------------------------- */
     109             :     /*      Decide on a working type.                                       */
     110             :     /* -------------------------------------------------------------------- */
     111          44 :     switch (poDS->GetRasterBand(1)->GetRasterDataType())
     112             :     {
     113          36 :         case GDT_Byte:
     114          36 :             eWrkDT = GDT_Byte;
     115          36 :             break;
     116             : 
     117           2 :         case GDT_UInt16:
     118             :         case GDT_UInt32:
     119           2 :             eWrkDT = GDT_UInt32;
     120           2 :             break;
     121             : 
     122           2 :         case GDT_Int8:
     123             :         case GDT_Int16:
     124             :         case GDT_Int32:
     125             :         case GDT_CInt16:
     126             :         case GDT_CInt32:
     127           2 :             eWrkDT = GDT_Int32;
     128           2 :             break;
     129             : 
     130           2 :         case GDT_Float16:
     131             :         case GDT_CFloat16:
     132             :         case GDT_Float32:
     133             :         case GDT_CFloat32:
     134           2 :             eWrkDT = GDT_Float32;
     135           2 :             break;
     136             : 
     137           2 :         case GDT_Float64:
     138             :         case GDT_CFloat64:
     139           2 :             eWrkDT = GDT_Float64;
     140           2 :             break;
     141             : 
     142           0 :         case GDT_Int64:
     143             :         case GDT_UInt64:
     144             :             // Lossy mapping...
     145           0 :             eWrkDT = GDT_Float64;
     146           0 :             break;
     147             : 
     148           0 :         case GDT_Unknown:
     149             :         case GDT_TypeCount:
     150           0 :             CPLAssert(false);
     151             :             eWrkDT = GDT_Float64;
     152             :             break;
     153             :     }
     154             : 
     155             :     /* -------------------------------------------------------------------- */
     156             :     /*      Read the image data.                                            */
     157             :     /* -------------------------------------------------------------------- */
     158          44 :     const int nBands = poDS->GetRasterCount();
     159          44 :     const int nWrkDTSize = GDALGetDataTypeSizeBytes(eWrkDT);
     160          44 :     GByte *pabySrc = static_cast<GByte *>(VSI_MALLOC3_VERBOSE(
     161             :         cpl::fits_on<int>(nBands * nWrkDTSize), nBlockXSize, nBlockYSize));
     162          44 :     if (pabySrc == nullptr)
     163             :     {
     164           0 :         return CE_Failure;
     165             :     }
     166             : 
     167          44 :     int nXSizeRequest = 0;
     168          44 :     int nYSizeRequest = 0;
     169          44 :     GetActualBlockSize(nXBlockOff, nYBlockOff, &nXSizeRequest, &nYSizeRequest);
     170             : 
     171          44 :     if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
     172             :     {
     173             :         // memset the whole buffer to avoid Valgrind warnings in case we can't
     174             :         // fetch a full block.
     175           0 :         memset(pabySrc, 0,
     176           0 :                static_cast<size_t>(nBands) * nWrkDTSize * nBlockXSize *
     177           0 :                    nBlockYSize);
     178             :     }
     179             : 
     180          44 :     const GPtrDiff_t nBlockOffsetPixels =
     181          44 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize;
     182          44 :     const GPtrDiff_t nBandOffsetByte = nWrkDTSize * nBlockOffsetPixels;
     183         176 :     for (int iBand = 0; iBand < nBands; ++iBand)
     184             :     {
     185         132 :         const CPLErr eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
     186         132 :             GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
     187         132 :             nXSizeRequest, nYSizeRequest, pabySrc + iBand * nBandOffsetByte,
     188             :             nXSizeRequest, nYSizeRequest, eWrkDT, 0,
     189         132 :             static_cast<GSpacing>(nBlockXSize) * nWrkDTSize, nullptr);
     190         132 :         if (eErr != CE_None)
     191           0 :             return eErr;
     192             :     }
     193             : 
     194             :     /* -------------------------------------------------------------------- */
     195             :     /*      Process different cases.                                        */
     196             :     /* -------------------------------------------------------------------- */
     197          44 :     switch (eWrkDT)
     198             :     {
     199          36 :         case GDT_Byte:
     200             :         {
     201          36 :             FillOutBuffer<GByte>(nBlockOffsetPixels, nBands, pabySrc,
     202          36 :                                  padfNodataValues, pImage);
     203             :         }
     204          36 :         break;
     205             : 
     206           2 :         case GDT_UInt32:
     207             :         {
     208           2 :             FillOutBuffer<GUInt32>(nBlockOffsetPixels, nBands, pabySrc,
     209           2 :                                    padfNodataValues, pImage);
     210             :         }
     211           2 :         break;
     212             : 
     213           2 :         case GDT_Int32:
     214             :         {
     215           2 :             FillOutBuffer<GInt32>(nBlockOffsetPixels, nBands, pabySrc,
     216           2 :                                   padfNodataValues, pImage);
     217             :         }
     218           2 :         break;
     219             : 
     220           2 :         case GDT_Float32:
     221             :         {
     222           2 :             FillOutBuffer<float>(nBlockOffsetPixels, nBands, pabySrc,
     223           2 :                                  padfNodataValues, pImage);
     224             :         }
     225           2 :         break;
     226             : 
     227           2 :         case GDT_Float64:
     228             :         {
     229           2 :             FillOutBuffer<double>(nBlockOffsetPixels, nBands, pabySrc,
     230           2 :                                   padfNodataValues, pImage);
     231             :         }
     232           2 :         break;
     233             : 
     234           0 :         default:
     235           0 :             CPLAssert(false);
     236             :             break;
     237             :     }
     238             : 
     239          44 :     CPLFree(pabySrc);
     240             : 
     241          44 :     return CE_None;
     242             : }
     243             : 
     244             : /************************************************************************/
     245             : /*                   EmitErrorMessageIfWriteNotSupported()              */
     246             : /************************************************************************/
     247             : 
     248           2 : bool GDALNoDataValuesMaskBand::EmitErrorMessageIfWriteNotSupported(
     249             :     const char *pszCaller) const
     250             : {
     251           2 :     ReportError(CE_Failure, CPLE_NoWriteAccess,
     252             :                 "%s: attempt to write to a nodata implicit mask band.",
     253             :                 pszCaller);
     254             : 
     255           2 :     return true;
     256             : }
     257             : 
     258             : //! @endcond

Generated by: LCOV version 1.14