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-05-03 15:49:35 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      14             :  * copy of this software and associated documentation files (the "Software"),
      15             :  * to deal in the Software without restriction, including without limitation
      16             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17             :  * and/or sell copies of the Software, and to permit persons to whom the
      18             :  * Software is furnished to do so, subject to the following conditions:
      19             :  *
      20             :  * The above copyright notice and this permission notice shall be included
      21             :  * in all copies or substantial portions of the Software.
      22             :  *
      23             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29             :  * DEALINGS IN THE SOFTWARE.
      30             :  ****************************************************************************/
      31             : 
      32             : #include "cpl_port.h"
      33             : #include "gdal_priv.h"
      34             : 
      35             : #include <cstring>
      36             : 
      37             : #include "cpl_conv.h"
      38             : #include "cpl_error.h"
      39             : #include "cpl_string.h"
      40             : #include "cpl_vsi.h"
      41             : #include "gdal.h"
      42             : 
      43             : //! @cond Doxygen_Suppress
      44             : /************************************************************************/
      45             : /*                   GDALNoDataValuesMaskBand()                         */
      46             : /************************************************************************/
      47             : 
      48          56 : GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand(GDALDataset *poDSIn)
      49          56 :     : padfNodataValues(nullptr)
      50             : {
      51          56 :     const char *pszNoDataValues = poDSIn->GetMetadataItem("NODATA_VALUES");
      52             :     char **papszNoDataValues =
      53          56 :         CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
      54             : 
      55          56 :     padfNodataValues = static_cast<double *>(
      56          56 :         CPLMalloc(sizeof(double) * poDSIn->GetRasterCount()));
      57         224 :     for (int i = 0; i < poDSIn->GetRasterCount(); ++i)
      58             :     {
      59         168 :         padfNodataValues[i] = CPLAtof(papszNoDataValues[i]);
      60             :     }
      61             : 
      62          56 :     CSLDestroy(papszNoDataValues);
      63             : 
      64          56 :     poDS = poDSIn;
      65          56 :     nBand = 0;
      66             : 
      67          56 :     nRasterXSize = poDS->GetRasterXSize();
      68          56 :     nRasterYSize = poDS->GetRasterYSize();
      69             : 
      70          56 :     eDataType = GDT_Byte;
      71          56 :     poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
      72          56 : }
      73             : 
      74             : /************************************************************************/
      75             : /*                    ~GDALNoDataValuesMaskBand()                       */
      76             : /************************************************************************/
      77             : 
      78         112 : GDALNoDataValuesMaskBand::~GDALNoDataValuesMaskBand()
      79             : 
      80             : {
      81          56 :     CPLFree(padfNodataValues);
      82         112 : }
      83             : 
      84             : /************************************************************************/
      85             : /*                            FillOutBuffer()                           */
      86             : /************************************************************************/
      87             : 
      88             : template <class T>
      89          38 : static void FillOutBuffer(GPtrDiff_t nBlockOffsetPixels, int nBands,
      90             :                           const void *pabySrc, const double *padfNodataValues,
      91             :                           void *pImage)
      92             : {
      93          38 :     T *paNoData = static_cast<T *>(CPLMalloc(nBands * sizeof(T)));
      94         152 :     for (int iBand = 0; iBand < nBands; ++iBand)
      95             :     {
      96         114 :         paNoData[iBand] = static_cast<T>(padfNodataValues[iBand]);
      97             :     }
      98             : 
      99      127547 :     for (GPtrDiff_t i = 0; i < nBlockOffsetPixels; i++)
     100             :     {
     101      127509 :         int nCountNoData = 0;
     102      510036 :         for (int iBand = 0; iBand < nBands; ++iBand)
     103             :         {
     104      382527 :             if (static_cast<const T *>(
     105      382527 :                     pabySrc)[i + iBand * nBlockOffsetPixels] == paNoData[iBand])
     106      109087 :                 ++nCountNoData;
     107             :         }
     108      127509 :         static_cast<GByte *>(pImage)[i] = nCountNoData == nBands ? 0 : 255;
     109             :     }
     110             : 
     111          38 :     CPLFree(paNoData);
     112          38 : }
     113             : 
     114             : /************************************************************************/
     115             : /*                             IReadBlock()                             */
     116             : /************************************************************************/
     117             : 
     118          38 : CPLErr GDALNoDataValuesMaskBand::IReadBlock(int nXBlockOff, int nYBlockOff,
     119             :                                             void *pImage)
     120             : 
     121             : {
     122          38 :     GDALDataType eWrkDT = GDT_Unknown;
     123             : 
     124             :     /* -------------------------------------------------------------------- */
     125             :     /*      Decide on a working type.                                       */
     126             :     /* -------------------------------------------------------------------- */
     127          38 :     switch (poDS->GetRasterBand(1)->GetRasterDataType())
     128             :     {
     129          30 :         case GDT_Byte:
     130          30 :             eWrkDT = GDT_Byte;
     131          30 :             break;
     132             : 
     133           2 :         case GDT_UInt16:
     134             :         case GDT_UInt32:
     135           2 :             eWrkDT = GDT_UInt32;
     136           2 :             break;
     137             : 
     138           2 :         case GDT_Int8:
     139             :         case GDT_Int16:
     140             :         case GDT_Int32:
     141             :         case GDT_CInt16:
     142             :         case GDT_CInt32:
     143           2 :             eWrkDT = GDT_Int32;
     144           2 :             break;
     145             : 
     146           2 :         case GDT_Float32:
     147             :         case GDT_CFloat32:
     148           2 :             eWrkDT = GDT_Float32;
     149           2 :             break;
     150             : 
     151           2 :         case GDT_Float64:
     152             :         case GDT_CFloat64:
     153           2 :             eWrkDT = GDT_Float64;
     154           2 :             break;
     155             : 
     156           0 :         case GDT_Int64:
     157             :         case GDT_UInt64:
     158             :             // Lossy mapping...
     159           0 :             eWrkDT = GDT_Float64;
     160           0 :             break;
     161             : 
     162           0 :         case GDT_Unknown:
     163             :         case GDT_TypeCount:
     164           0 :             CPLAssert(false);
     165             :             eWrkDT = GDT_Float64;
     166             :             break;
     167             :     }
     168             : 
     169             :     /* -------------------------------------------------------------------- */
     170             :     /*      Read the image data.                                            */
     171             :     /* -------------------------------------------------------------------- */
     172          38 :     const int nBands = poDS->GetRasterCount();
     173          38 :     const int nWrkDTSize = GDALGetDataTypeSizeBytes(eWrkDT);
     174          38 :     GByte *pabySrc = static_cast<GByte *>(VSI_MALLOC3_VERBOSE(
     175             :         cpl::fits_on<int>(nBands * nWrkDTSize), nBlockXSize, nBlockYSize));
     176          38 :     if (pabySrc == nullptr)
     177             :     {
     178           0 :         return CE_Failure;
     179             :     }
     180             : 
     181          38 :     int nXSizeRequest = 0;
     182          38 :     int nYSizeRequest = 0;
     183          38 :     GetActualBlockSize(nXBlockOff, nYBlockOff, &nXSizeRequest, &nYSizeRequest);
     184             : 
     185          38 :     if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
     186             :     {
     187             :         // memset the whole buffer to avoid Valgrind warnings in case we can't
     188             :         // fetch a full block.
     189           0 :         memset(pabySrc, 0,
     190           0 :                static_cast<size_t>(nBands) * nWrkDTSize * nBlockXSize *
     191           0 :                    nBlockYSize);
     192             :     }
     193             : 
     194          38 :     const GPtrDiff_t nBlockOffsetPixels =
     195          38 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize;
     196          38 :     const GPtrDiff_t nBandOffsetByte = nWrkDTSize * nBlockOffsetPixels;
     197         152 :     for (int iBand = 0; iBand < nBands; ++iBand)
     198             :     {
     199         114 :         const CPLErr eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
     200         114 :             GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
     201         114 :             nXSizeRequest, nYSizeRequest, pabySrc + iBand * nBandOffsetByte,
     202             :             nXSizeRequest, nYSizeRequest, eWrkDT, 0,
     203         114 :             static_cast<GSpacing>(nBlockXSize) * nWrkDTSize, nullptr);
     204         114 :         if (eErr != CE_None)
     205           0 :             return eErr;
     206             :     }
     207             : 
     208             :     /* -------------------------------------------------------------------- */
     209             :     /*      Process different cases.                                        */
     210             :     /* -------------------------------------------------------------------- */
     211          38 :     switch (eWrkDT)
     212             :     {
     213          30 :         case GDT_Byte:
     214             :         {
     215          30 :             FillOutBuffer<GByte>(nBlockOffsetPixels, nBands, pabySrc,
     216          30 :                                  padfNodataValues, pImage);
     217             :         }
     218          30 :         break;
     219             : 
     220           2 :         case GDT_UInt32:
     221             :         {
     222           2 :             FillOutBuffer<GUInt32>(nBlockOffsetPixels, nBands, pabySrc,
     223           2 :                                    padfNodataValues, pImage);
     224             :         }
     225           2 :         break;
     226             : 
     227           2 :         case GDT_Int32:
     228             :         {
     229           2 :             FillOutBuffer<GInt32>(nBlockOffsetPixels, nBands, pabySrc,
     230           2 :                                   padfNodataValues, pImage);
     231             :         }
     232           2 :         break;
     233             : 
     234           2 :         case GDT_Float32:
     235             :         {
     236           2 :             FillOutBuffer<float>(nBlockOffsetPixels, nBands, pabySrc,
     237           2 :                                  padfNodataValues, pImage);
     238             :         }
     239           2 :         break;
     240             : 
     241           2 :         case GDT_Float64:
     242             :         {
     243           2 :             FillOutBuffer<double>(nBlockOffsetPixels, nBands, pabySrc,
     244           2 :                                   padfNodataValues, pImage);
     245             :         }
     246           2 :         break;
     247             : 
     248           0 :         default:
     249           0 :             CPLAssert(false);
     250             :             break;
     251             :     }
     252             : 
     253          38 :     CPLFree(pabySrc);
     254             : 
     255          38 :     return CE_None;
     256             : }
     257             : 
     258             : //! @endcond

Generated by: LCOV version 1.14