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: 2024-11-21 22:18:42 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_Float32:
     131             :         case GDT_CFloat32:
     132           2 :             eWrkDT = GDT_Float32;
     133           2 :             break;
     134             : 
     135           2 :         case GDT_Float64:
     136             :         case GDT_CFloat64:
     137           2 :             eWrkDT = GDT_Float64;
     138           2 :             break;
     139             : 
     140           0 :         case GDT_Int64:
     141             :         case GDT_UInt64:
     142             :             // Lossy mapping...
     143           0 :             eWrkDT = GDT_Float64;
     144           0 :             break;
     145             : 
     146           0 :         case GDT_Unknown:
     147             :         case GDT_TypeCount:
     148           0 :             CPLAssert(false);
     149             :             eWrkDT = GDT_Float64;
     150             :             break;
     151             :     }
     152             : 
     153             :     /* -------------------------------------------------------------------- */
     154             :     /*      Read the image data.                                            */
     155             :     /* -------------------------------------------------------------------- */
     156          38 :     const int nBands = poDS->GetRasterCount();
     157          38 :     const int nWrkDTSize = GDALGetDataTypeSizeBytes(eWrkDT);
     158          38 :     GByte *pabySrc = static_cast<GByte *>(VSI_MALLOC3_VERBOSE(
     159             :         cpl::fits_on<int>(nBands * nWrkDTSize), nBlockXSize, nBlockYSize));
     160          38 :     if (pabySrc == nullptr)
     161             :     {
     162           0 :         return CE_Failure;
     163             :     }
     164             : 
     165          38 :     int nXSizeRequest = 0;
     166          38 :     int nYSizeRequest = 0;
     167          38 :     GetActualBlockSize(nXBlockOff, nYBlockOff, &nXSizeRequest, &nYSizeRequest);
     168             : 
     169          38 :     if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
     170             :     {
     171             :         // memset the whole buffer to avoid Valgrind warnings in case we can't
     172             :         // fetch a full block.
     173           0 :         memset(pabySrc, 0,
     174           0 :                static_cast<size_t>(nBands) * nWrkDTSize * nBlockXSize *
     175           0 :                    nBlockYSize);
     176             :     }
     177             : 
     178          38 :     const GPtrDiff_t nBlockOffsetPixels =
     179          38 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize;
     180          38 :     const GPtrDiff_t nBandOffsetByte = nWrkDTSize * nBlockOffsetPixels;
     181         152 :     for (int iBand = 0; iBand < nBands; ++iBand)
     182             :     {
     183         114 :         const CPLErr eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
     184         114 :             GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
     185         114 :             nXSizeRequest, nYSizeRequest, pabySrc + iBand * nBandOffsetByte,
     186             :             nXSizeRequest, nYSizeRequest, eWrkDT, 0,
     187         114 :             static_cast<GSpacing>(nBlockXSize) * nWrkDTSize, nullptr);
     188         114 :         if (eErr != CE_None)
     189           0 :             return eErr;
     190             :     }
     191             : 
     192             :     /* -------------------------------------------------------------------- */
     193             :     /*      Process different cases.                                        */
     194             :     /* -------------------------------------------------------------------- */
     195          38 :     switch (eWrkDT)
     196             :     {
     197          30 :         case GDT_Byte:
     198             :         {
     199          30 :             FillOutBuffer<GByte>(nBlockOffsetPixels, nBands, pabySrc,
     200          30 :                                  padfNodataValues, pImage);
     201             :         }
     202          30 :         break;
     203             : 
     204           2 :         case GDT_UInt32:
     205             :         {
     206           2 :             FillOutBuffer<GUInt32>(nBlockOffsetPixels, nBands, pabySrc,
     207           2 :                                    padfNodataValues, pImage);
     208             :         }
     209           2 :         break;
     210             : 
     211           2 :         case GDT_Int32:
     212             :         {
     213           2 :             FillOutBuffer<GInt32>(nBlockOffsetPixels, nBands, pabySrc,
     214           2 :                                   padfNodataValues, pImage);
     215             :         }
     216           2 :         break;
     217             : 
     218           2 :         case GDT_Float32:
     219             :         {
     220           2 :             FillOutBuffer<float>(nBlockOffsetPixels, nBands, pabySrc,
     221           2 :                                  padfNodataValues, pImage);
     222             :         }
     223           2 :         break;
     224             : 
     225           2 :         case GDT_Float64:
     226             :         {
     227           2 :             FillOutBuffer<double>(nBlockOffsetPixels, nBands, pabySrc,
     228           2 :                                   padfNodataValues, pImage);
     229             :         }
     230           2 :         break;
     231             : 
     232           0 :         default:
     233           0 :             CPLAssert(false);
     234             :             break;
     235             :     }
     236             : 
     237          38 :     CPLFree(pabySrc);
     238             : 
     239          38 :     return CE_None;
     240             : }
     241             : 
     242             : //! @endcond

Generated by: LCOV version 1.14