LCOV - code coverage report
Current view: top level - gcore - gdalnodatavaluesmaskband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 90 102 88.2 %
Date: 2025-02-20 10:14:44 Functions: 9 9 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          56 : GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand(GDALDataset *poDSIn)
      33          56 :     : padfNodataValues(nullptr)
      34             : {
      35          56 :     const char *pszNoDataValues = poDSIn->GetMetadataItem("NODATA_VALUES");
      36             :     char **papszNoDataValues =
      37          56 :         CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
      38             : 
      39          56 :     padfNodataValues = static_cast<double *>(
      40          56 :         CPLMalloc(sizeof(double) * poDSIn->GetRasterCount()));
      41         224 :     for (int i = 0; i < poDSIn->GetRasterCount(); ++i)
      42             :     {
      43         168 :         padfNodataValues[i] = CPLAtof(papszNoDataValues[i]);
      44             :     }
      45             : 
      46          56 :     CSLDestroy(papszNoDataValues);
      47             : 
      48          56 :     poDS = poDSIn;
      49          56 :     nBand = 0;
      50             : 
      51          56 :     nRasterXSize = poDS->GetRasterXSize();
      52          56 :     nRasterYSize = poDS->GetRasterYSize();
      53             : 
      54          56 :     eDataType = GDT_Byte;
      55          56 :     poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
      56          56 : }
      57             : 
      58             : /************************************************************************/
      59             : /*                    ~GDALNoDataValuesMaskBand()                       */
      60             : /************************************************************************/
      61             : 
      62         112 : GDALNoDataValuesMaskBand::~GDALNoDataValuesMaskBand()
      63             : 
      64             : {
      65          56 :     CPLFree(padfNodataValues);
      66         112 : }
      67             : 
      68             : /************************************************************************/
      69             : /*                            FillOutBuffer()                           */
      70             : /************************************************************************/
      71             : 
      72             : template <class T>
      73          38 : static void FillOutBuffer(GPtrDiff_t nBlockOffsetPixels, int nBands,
      74             :                           const void *pabySrc, const double *padfNodataValues,
      75             :                           void *pImage)
      76             : {
      77          38 :     T *paNoData = static_cast<T *>(CPLMalloc(nBands * sizeof(T)));
      78         152 :     for (int iBand = 0; iBand < nBands; ++iBand)
      79             :     {
      80         114 :         paNoData[iBand] = static_cast<T>(padfNodataValues[iBand]);
      81             :     }
      82             : 
      83      127547 :     for (GPtrDiff_t i = 0; i < nBlockOffsetPixels; i++)
      84             :     {
      85      127509 :         int nCountNoData = 0;
      86      510036 :         for (int iBand = 0; iBand < nBands; ++iBand)
      87             :         {
      88      382527 :             if (static_cast<const T *>(
      89      382527 :                     pabySrc)[i + iBand * nBlockOffsetPixels] == paNoData[iBand])
      90      109087 :                 ++nCountNoData;
      91             :         }
      92      127509 :         static_cast<GByte *>(pImage)[i] = nCountNoData == nBands ? 0 : 255;
      93             :     }
      94             : 
      95          38 :     CPLFree(paNoData);
      96          38 : }
      97             : 
      98             : /************************************************************************/
      99             : /*                             IReadBlock()                             */
     100             : /************************************************************************/
     101             : 
     102          38 : CPLErr GDALNoDataValuesMaskBand::IReadBlock(int nXBlockOff, int nYBlockOff,
     103             :                                             void *pImage)
     104             : 
     105             : {
     106          38 :     GDALDataType eWrkDT = GDT_Unknown;
     107             : 
     108             :     /* -------------------------------------------------------------------- */
     109             :     /*      Decide on a working type.                                       */
     110             :     /* -------------------------------------------------------------------- */
     111          38 :     switch (poDS->GetRasterBand(1)->GetRasterDataType())
     112             :     {
     113          30 :         case GDT_Byte:
     114          30 :             eWrkDT = GDT_Byte;
     115          30 :             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          38 :     const int nBands = poDS->GetRasterCount();
     159          38 :     const int nWrkDTSize = GDALGetDataTypeSizeBytes(eWrkDT);
     160          38 :     GByte *pabySrc = static_cast<GByte *>(VSI_MALLOC3_VERBOSE(
     161             :         cpl::fits_on<int>(nBands * nWrkDTSize), nBlockXSize, nBlockYSize));
     162          38 :     if (pabySrc == nullptr)
     163             :     {
     164           0 :         return CE_Failure;
     165             :     }
     166             : 
     167          38 :     int nXSizeRequest = 0;
     168          38 :     int nYSizeRequest = 0;
     169          38 :     GetActualBlockSize(nXBlockOff, nYBlockOff, &nXSizeRequest, &nYSizeRequest);
     170             : 
     171          38 :     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          38 :     const GPtrDiff_t nBlockOffsetPixels =
     181          38 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize;
     182          38 :     const GPtrDiff_t nBandOffsetByte = nWrkDTSize * nBlockOffsetPixels;
     183         152 :     for (int iBand = 0; iBand < nBands; ++iBand)
     184             :     {
     185         114 :         const CPLErr eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
     186         114 :             GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
     187         114 :             nXSizeRequest, nYSizeRequest, pabySrc + iBand * nBandOffsetByte,
     188             :             nXSizeRequest, nYSizeRequest, eWrkDT, 0,
     189         114 :             static_cast<GSpacing>(nBlockXSize) * nWrkDTSize, nullptr);
     190         114 :         if (eErr != CE_None)
     191           0 :             return eErr;
     192             :     }
     193             : 
     194             :     /* -------------------------------------------------------------------- */
     195             :     /*      Process different cases.                                        */
     196             :     /* -------------------------------------------------------------------- */
     197          38 :     switch (eWrkDT)
     198             :     {
     199          30 :         case GDT_Byte:
     200             :         {
     201          30 :             FillOutBuffer<GByte>(nBlockOffsetPixels, nBands, pabySrc,
     202          30 :                                  padfNodataValues, pImage);
     203             :         }
     204          30 :         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          38 :     CPLFree(pabySrc);
     240             : 
     241          38 :     return CE_None;
     242             : }
     243             : 
     244             : //! @endcond

Generated by: LCOV version 1.14