LCOV - code coverage report
Current view: top level - gcore - gdalnodatamaskband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 242 268 90.3 %
Date: 2025-08-19 18:03:11 Functions: 22 23 95.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Implementation of GDALNoDataMaskBand, a class implementing all
       5             :  *           a default band mask based on nodata values.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2007, Frank Warmerdam
      10             :  * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "cpl_port.h"
      16             : #include "gdal_priv.h"
      17             : 
      18             : #include <algorithm>
      19             : #include <cassert>
      20             : #include <cmath>
      21             : #include <cstring>
      22             : #include <utility>
      23             : 
      24             : #include "cpl_conv.h"
      25             : #include "cpl_error.h"
      26             : #include "cpl_vsi.h"
      27             : #include "gdal.h"
      28             : #include "gdal_priv_templates.hpp"
      29             : 
      30             : //! @cond Doxygen_Suppress
      31             : /************************************************************************/
      32             : /*                        GDALNoDataMaskBand()                          */
      33             : /************************************************************************/
      34             : 
      35        1083 : GDALNoDataMaskBand::GDALNoDataMaskBand(GDALRasterBand *poParentIn)
      36        1083 :     : m_poParent(poParentIn)
      37             : {
      38        1083 :     poDS = nullptr;
      39        1083 :     nBand = 0;
      40             : 
      41        1083 :     nRasterXSize = m_poParent->GetXSize();
      42        1083 :     nRasterYSize = m_poParent->GetYSize();
      43             : 
      44        1083 :     eDataType = GDT_Byte;
      45        1083 :     m_poParent->GetBlockSize(&nBlockXSize, &nBlockYSize);
      46             : 
      47        1083 :     const auto eParentDT = m_poParent->GetRasterDataType();
      48        1083 :     if (eParentDT == GDT_Int64)
      49          15 :         m_nNoDataValueInt64 = m_poParent->GetNoDataValueAsInt64();
      50        1068 :     else if (eParentDT == GDT_UInt64)
      51          14 :         m_nNoDataValueUInt64 = m_poParent->GetNoDataValueAsUInt64();
      52             :     else
      53        1054 :         m_dfNoDataValue = m_poParent->GetNoDataValue();
      54        1083 : }
      55             : 
      56             : /************************************************************************/
      57             : /*                        GDALNoDataMaskBand()                          */
      58             : /************************************************************************/
      59             : 
      60           4 : GDALNoDataMaskBand::GDALNoDataMaskBand(GDALRasterBand *poParentIn,
      61           4 :                                        double dfNoDataValue)
      62           4 :     : m_poParent(poParentIn)
      63             : {
      64           4 :     poDS = nullptr;
      65           4 :     nBand = 0;
      66             : 
      67           4 :     nRasterXSize = m_poParent->GetXSize();
      68           4 :     nRasterYSize = m_poParent->GetYSize();
      69             : 
      70           4 :     eDataType = GDT_Byte;
      71           4 :     m_poParent->GetBlockSize(&nBlockXSize, &nBlockYSize);
      72             : 
      73           4 :     const auto eParentDT = m_poParent->GetRasterDataType();
      74           4 :     if (eParentDT == GDT_Int64)
      75           0 :         m_nNoDataValueInt64 = static_cast<int64_t>(dfNoDataValue);
      76           4 :     else if (eParentDT == GDT_UInt64)
      77           0 :         m_nNoDataValueUInt64 = static_cast<uint64_t>(dfNoDataValue);
      78             :     else
      79           4 :         m_dfNoDataValue = dfNoDataValue;
      80           4 : }
      81             : 
      82             : /************************************************************************/
      83             : /*                       ~GDALNoDataMaskBand()                          */
      84             : /************************************************************************/
      85             : 
      86             : GDALNoDataMaskBand::~GDALNoDataMaskBand() = default;
      87             : 
      88             : /************************************************************************/
      89             : /*                          GetWorkDataType()                           */
      90             : /************************************************************************/
      91             : 
      92       16623 : static GDALDataType GetWorkDataType(GDALDataType eDataType)
      93             : {
      94       16623 :     GDALDataType eWrkDT = GDT_Unknown;
      95       16623 :     switch (eDataType)
      96             :     {
      97        1461 :         case GDT_Byte:
      98        1461 :             eWrkDT = GDT_Byte;
      99        1461 :             break;
     100             : 
     101        1830 :         case GDT_Int16:
     102        1830 :             eWrkDT = GDT_Int16;
     103        1830 :             break;
     104             : 
     105          67 :         case GDT_UInt16:
     106          67 :             eWrkDT = GDT_UInt16;
     107          67 :             break;
     108             : 
     109          31 :         case GDT_UInt32:
     110          31 :             eWrkDT = GDT_UInt32;
     111          31 :             break;
     112             : 
     113         129 :         case GDT_Int8:
     114             :         case GDT_Int32:
     115             :         case GDT_CInt16:
     116             :         case GDT_CInt32:
     117         129 :             eWrkDT = GDT_Int32;
     118         129 :             break;
     119             : 
     120       12957 :         case GDT_Float16:
     121             :         case GDT_CFloat16:
     122             :         case GDT_Float32:
     123             :         case GDT_CFloat32:
     124       12957 :             eWrkDT = GDT_Float32;
     125       12957 :             break;
     126             : 
     127         100 :         case GDT_Float64:
     128             :         case GDT_CFloat64:
     129         100 :             eWrkDT = GDT_Float64;
     130         100 :             break;
     131             : 
     132          48 :         case GDT_Int64:
     133             :         case GDT_UInt64:
     134          48 :             eWrkDT = eDataType;
     135          48 :             break;
     136             : 
     137           0 :         case GDT_Unknown:
     138             :         case GDT_TypeCount:
     139           0 :             CPLAssert(false);
     140             :             eWrkDT = GDT_Float64;
     141             :             break;
     142             :     }
     143       16623 :     return eWrkDT;
     144             : }
     145             : 
     146             : /************************************************************************/
     147             : /*                          IsNoDataInRange()                           */
     148             : /************************************************************************/
     149             : 
     150        1062 : bool GDALNoDataMaskBand::IsNoDataInRange(double dfNoDataValue,
     151             :                                          GDALDataType eDataTypeIn)
     152             : {
     153        1062 :     GDALDataType eWrkDT = GetWorkDataType(eDataTypeIn);
     154        1062 :     switch (eWrkDT)
     155             :     {
     156         445 :         case GDT_Byte:
     157             :         {
     158         445 :             return GDALIsValueInRange<GByte>(dfNoDataValue);
     159             :         }
     160             : 
     161           0 :         case GDT_Int8:
     162             :         {
     163           0 :             return GDALIsValueInRange<signed char>(dfNoDataValue);
     164             :         }
     165             : 
     166         121 :         case GDT_Int16:
     167             :         {
     168         121 :             return GDALIsValueInRange<GInt16>(dfNoDataValue);
     169             :         }
     170             : 
     171          55 :         case GDT_UInt16:
     172             :         {
     173          55 :             return GDALIsValueInRange<GUInt16>(dfNoDataValue);
     174             :         }
     175             : 
     176          20 :         case GDT_UInt32:
     177             :         {
     178          20 :             return GDALIsValueInRange<GUInt32>(dfNoDataValue);
     179             :         }
     180          42 :         case GDT_Int32:
     181             :         {
     182          42 :             return GDALIsValueInRange<GInt32>(dfNoDataValue);
     183             :         }
     184             : 
     185           0 :         case GDT_UInt64:
     186             :         {
     187           0 :             return GDALIsValueInRange<uint64_t>(dfNoDataValue);
     188             :         }
     189             : 
     190           0 :         case GDT_Int64:
     191             :         {
     192           0 :             return GDALIsValueInRange<int64_t>(dfNoDataValue);
     193             :         }
     194             : 
     195           0 :         case GDT_Float16:
     196             :         {
     197           0 :             return std::isnan(dfNoDataValue) || std::isinf(dfNoDataValue) ||
     198           0 :                    GDALIsValueInRange<GFloat16>(dfNoDataValue);
     199             :         }
     200             : 
     201         320 :         case GDT_Float32:
     202             :         {
     203         609 :             return std::isnan(dfNoDataValue) || std::isinf(dfNoDataValue) ||
     204         609 :                    GDALIsValueInRange<float>(dfNoDataValue);
     205             :         }
     206             : 
     207          59 :         case GDT_Float64:
     208             :         {
     209          59 :             return true;
     210             :         }
     211             : 
     212           0 :         case GDT_CFloat16:
     213             :         case GDT_CFloat32:
     214             :         case GDT_CFloat64:
     215             :         case GDT_CInt16:
     216             :         case GDT_CInt32:
     217             :         case GDT_Unknown:
     218             :         case GDT_TypeCount:
     219           0 :             break;
     220             :     }
     221             : 
     222           0 :     CPLAssert(false);
     223             :     return false;
     224             : }
     225             : 
     226             : /************************************************************************/
     227             : /*                             IReadBlock()                             */
     228             : /************************************************************************/
     229             : 
     230          34 : CPLErr GDALNoDataMaskBand::IReadBlock(int nXBlockOff, int nYBlockOff,
     231             :                                       void *pImage)
     232             : 
     233             : {
     234          34 :     const int nXOff = nXBlockOff * nBlockXSize;
     235          34 :     const int nXSizeRequest = std::min(nBlockXSize, nRasterXSize - nXOff);
     236          34 :     const int nYOff = nYBlockOff * nBlockYSize;
     237          34 :     const int nYSizeRequest = std::min(nBlockYSize, nRasterYSize - nYOff);
     238             : 
     239          34 :     if (nBlockXSize != nXSizeRequest || nBlockYSize != nYSizeRequest)
     240             :     {
     241           0 :         memset(pImage, 0, static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize);
     242             :     }
     243             : 
     244             :     GDALRasterIOExtraArg sExtraArg;
     245          34 :     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
     246          34 :     return IRasterIO(GF_Read, nXOff, nYOff, nXSizeRequest, nYSizeRequest,
     247             :                      pImage, nXSizeRequest, nYSizeRequest, GDT_Byte, 1,
     248          68 :                      nBlockXSize, &sExtraArg);
     249             : }
     250             : 
     251             : /************************************************************************/
     252             : /*                            SetZeroOr255()                            */
     253             : /************************************************************************/
     254             : 
     255             : #if (defined(__GNUC__) && !defined(__clang__))
     256             : __attribute__((optimize("tree-vectorize")))
     257             : #endif
     258             : static void
     259         915 : SetZeroOr255(GByte *pabyDestAndSrc, size_t nBufSize, GByte byNoData)
     260             : {
     261     4671760 :     for (size_t i = 0; i < nBufSize; ++i)
     262             :     {
     263     4670840 :         pabyDestAndSrc[i] = (pabyDestAndSrc[i] == byNoData) ? 0 : 255;
     264             :     }
     265         915 : }
     266             : 
     267             : template <class T>
     268             : #if (defined(__GNUC__) && !defined(__clang__))
     269             : __attribute__((optimize("tree-vectorize")))
     270             : #endif
     271             : static void
     272        3444 : SetZeroOr255(GByte *pabyDest, const T *panSrc, size_t nBufSize, T nNoData)
     273             : {
     274      999312 :     for (size_t i = 0; i < nBufSize; ++i)
     275             :     {
     276      995868 :         pabyDest[i] = (panSrc[i] == nNoData) ? 0 : 255;
     277             :     }
     278        3444 : }
     279             : 
     280             : template <class T>
     281        1845 : static void SetZeroOr255(GByte *pabyDest, const T *panSrc, int nBufXSize,
     282             :                          int nBufYSize, GSpacing nPixelSpace,
     283             :                          GSpacing nLineSpace, T nNoData)
     284             : {
     285        1845 :     if (nPixelSpace == 1)
     286             :     {
     287        5281 :         for (int iY = 0; iY < nBufYSize; iY++)
     288             :         {
     289        3444 :             SetZeroOr255(pabyDest, panSrc, nBufXSize, nNoData);
     290        3444 :             pabyDest += nLineSpace;
     291        3444 :             panSrc += nBufXSize;
     292             :         }
     293             :     }
     294             :     else
     295             :     {
     296           8 :         size_t i = 0;
     297          40 :         for (int iY = 0; iY < nBufYSize; iY++)
     298             :         {
     299          32 :             GByte *pabyLineDest = pabyDest + iY * nLineSpace;
     300         224 :             for (int iX = 0; iX < nBufXSize; iX++)
     301             :             {
     302         192 :                 *pabyLineDest = (panSrc[i] == nNoData) ? 0 : 255;
     303         192 :                 ++i;
     304         192 :                 pabyLineDest += nPixelSpace;
     305             :             }
     306             :         }
     307             :     }
     308        1845 : }
     309             : 
     310             : /************************************************************************/
     311             : /*                             IRasterIO()                              */
     312             : /************************************************************************/
     313             : 
     314       15561 : CPLErr GDALNoDataMaskBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     315             :                                      int nXSize, int nYSize, void *pData,
     316             :                                      int nBufXSize, int nBufYSize,
     317             :                                      GDALDataType eBufType,
     318             :                                      GSpacing nPixelSpace, GSpacing nLineSpace,
     319             :                                      GDALRasterIOExtraArg *psExtraArg)
     320             : {
     321       15561 :     if (eRWFlag != GF_Read)
     322             :     {
     323           0 :         return CE_Failure;
     324             :     }
     325       15561 :     const auto eParentDT = m_poParent->GetRasterDataType();
     326       15561 :     const GDALDataType eWrkDT = GetWorkDataType(eParentDT);
     327             : 
     328             :     // Optimization in common use case (#4488).
     329             :     // This avoids triggering the block cache on this band, which helps
     330             :     // reducing the global block cache consumption.
     331       15561 :     if (eBufType == GDT_Byte && eWrkDT == GDT_Byte && nPixelSpace == 1 &&
     332         912 :         nLineSpace >= nBufXSize)
     333             :     {
     334         912 :         const CPLErr eErr = m_poParent->RasterIO(
     335             :             GF_Read, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     336             :             eBufType, nPixelSpace, nLineSpace, psExtraArg);
     337         912 :         if (eErr != CE_None)
     338           0 :             return eErr;
     339             : 
     340         912 :         GByte *pabyData = static_cast<GByte *>(pData);
     341         912 :         const GByte byNoData = static_cast<GByte>(m_dfNoDataValue);
     342             : 
     343         912 :         if (nLineSpace == nBufXSize)
     344             :         {
     345         911 :             const size_t nBufSize = static_cast<size_t>(nBufXSize) * nBufYSize;
     346         911 :             SetZeroOr255(pabyData, nBufSize, byNoData);
     347             :         }
     348             :         else
     349             :         {
     350           1 :             assert(nLineSpace > nBufXSize);
     351           5 :             for (int iY = 0; iY < nBufYSize; iY++)
     352             :             {
     353           4 :                 SetZeroOr255(pabyData, nBufXSize, byNoData);
     354           4 :                 pabyData += nLineSpace;
     355             :             }
     356             :         }
     357         912 :         return CE_None;
     358             :     }
     359             : 
     360             :     const auto AllocTempBufferOrFallback =
     361       14649 :         [this, eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     362             :          nBufYSize, eBufType, nPixelSpace, nLineSpace,
     363       29354 :          psExtraArg](int nWrkDTSize) -> std::pair<CPLErr, void *>
     364             :     {
     365       14649 :         auto poParentDS = m_poParent->GetDataset();
     366             :         // Check if we must simulate a memory allocation failure
     367             :         // Before checking the env variable, which is slightly expensive,
     368             :         // check first for a special dataset name, which is a cheap test.
     369             :         const char *pszOptVal =
     370       14649 :             poParentDS && strcmp(poParentDS->GetDescription(), "__debug__") == 0
     371       29298 :                 ? CPLGetConfigOption(
     372             :                       "GDAL_SIMUL_MEM_ALLOC_FAILURE_NODATA_MASK_BAND", "NO")
     373       14649 :                 : "NO";
     374             :         const bool bSimulMemAllocFailure =
     375       29294 :             EQUAL(pszOptVal, "ALWAYS") ||
     376       14645 :             (CPLTestBool(pszOptVal) &&
     377          14 :              GDALMajorObject::GetMetadataItem(__func__, "__INTERNAL__") ==
     378       14649 :                  nullptr);
     379       14649 :         void *pTemp = nullptr;
     380       14649 :         if (!bSimulMemAllocFailure)
     381             :         {
     382       14637 :             CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
     383       14637 :             pTemp = VSI_MALLOC3_VERBOSE(nWrkDTSize, nBufXSize, nBufYSize);
     384             :         }
     385       14649 :         if (!pTemp)
     386             :         {
     387             :             const bool bAllocHasAlreadyFailed =
     388          12 :                 GDALMajorObject::GetMetadataItem(__func__, "__INTERNAL__") !=
     389          12 :                 nullptr;
     390          12 :             CPLError(bAllocHasAlreadyFailed ? CE_Failure : CE_Warning,
     391             :                      CPLE_OutOfMemory,
     392             :                      "GDALNoDataMaskBand::IRasterIO(): cannot allocate %d x %d "
     393             :                      "x %d bytes%s",
     394             :                      nBufXSize, nBufYSize, nWrkDTSize,
     395             :                      bAllocHasAlreadyFailed
     396             :                          ? ""
     397             :                          : ". Falling back to block-based approach");
     398          12 :             if (bAllocHasAlreadyFailed)
     399           2 :                 return std::pair(CE_Failure, nullptr);
     400             :             // Sets a metadata item to prevent potential infinite recursion
     401          10 :             GDALMajorObject::SetMetadataItem(__func__, "IN", "__INTERNAL__");
     402          10 :             const CPLErr eErr = GDALRasterBand::IRasterIO(
     403             :                 eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     404          10 :                 nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     405          10 :             GDALMajorObject::SetMetadataItem(__func__, nullptr, "__INTERNAL__");
     406          10 :             return std::pair(eErr, nullptr);
     407             :         }
     408       14637 :         return std::pair(CE_None, pTemp);
     409       14649 :     };
     410             : 
     411       14649 :     if (eBufType == GDT_Byte)
     412             :     {
     413       14524 :         const int nWrkDTSize = GDALGetDataTypeSizeBytes(eWrkDT);
     414       14524 :         auto [eErr, pTemp] = AllocTempBufferOrFallback(nWrkDTSize);
     415       14524 :         if (!pTemp)
     416          12 :             return eErr;
     417             : 
     418       29024 :         eErr = m_poParent->RasterIO(
     419             :             GF_Read, nXOff, nYOff, nXSize, nYSize, pTemp, nBufXSize, nBufYSize,
     420       14512 :             eWrkDT, nWrkDTSize, static_cast<GSpacing>(nBufXSize) * nWrkDTSize,
     421             :             psExtraArg);
     422       14512 :         if (eErr != CE_None)
     423             :         {
     424           0 :             VSIFree(pTemp);
     425           0 :             return eErr;
     426             :         }
     427             : 
     428       14512 :         const bool bIsNoDataNan = std::isnan(m_dfNoDataValue) != 0;
     429       14512 :         GByte *pabyDest = static_cast<GByte *>(pData);
     430             : 
     431             :         /* --------------------------------------------------------------------
     432             :          */
     433             :         /*      Process different cases. */
     434             :         /* --------------------------------------------------------------------
     435             :          */
     436       14512 :         switch (eWrkDT)
     437             :         {
     438           1 :             case GDT_Byte:
     439             :             {
     440           1 :                 const auto nNoData = static_cast<GByte>(m_dfNoDataValue);
     441           1 :                 const auto *panSrc = static_cast<const GByte *>(pTemp);
     442           1 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     443             :                              nPixelSpace, nLineSpace, nNoData);
     444             :             }
     445           1 :             break;
     446             : 
     447        1707 :             case GDT_Int16:
     448             :             {
     449        1707 :                 const auto nNoData = static_cast<int16_t>(m_dfNoDataValue);
     450        1707 :                 const auto *panSrc = static_cast<const int16_t *>(pTemp);
     451        1707 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     452             :                              nPixelSpace, nLineSpace, nNoData);
     453             :             }
     454        1707 :             break;
     455             : 
     456          10 :             case GDT_UInt16:
     457             :             {
     458          10 :                 const auto nNoData = static_cast<uint16_t>(m_dfNoDataValue);
     459          10 :                 const auto *panSrc = static_cast<const uint16_t *>(pTemp);
     460          10 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     461             :                              nPixelSpace, nLineSpace, nNoData);
     462             :             }
     463          10 :             break;
     464             : 
     465           9 :             case GDT_UInt32:
     466             :             {
     467           9 :                 const auto nNoData = static_cast<GUInt32>(m_dfNoDataValue);
     468           9 :                 const auto *panSrc = static_cast<const GUInt32 *>(pTemp);
     469           9 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     470             :                              nPixelSpace, nLineSpace, nNoData);
     471             :             }
     472           9 :             break;
     473             : 
     474          84 :             case GDT_Int32:
     475             :             {
     476          84 :                 const auto nNoData = static_cast<GInt32>(m_dfNoDataValue);
     477          84 :                 const auto *panSrc = static_cast<const GInt32 *>(pTemp);
     478          84 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     479             :                              nPixelSpace, nLineSpace, nNoData);
     480             :             }
     481          84 :             break;
     482             : 
     483       12631 :             case GDT_Float32:
     484             :             {
     485       12631 :                 const float fNoData = static_cast<float>(m_dfNoDataValue);
     486       12631 :                 const float *pafSrc = static_cast<const float *>(pTemp);
     487             : 
     488       12631 :                 size_t i = 0;
     489       25962 :                 for (int iY = 0; iY < nBufYSize; iY++)
     490             :                 {
     491       13331 :                     GByte *pabyLineDest = pabyDest + iY * nLineSpace;
     492    15237700 :                     for (int iX = 0; iX < nBufXSize; iX++)
     493             :                     {
     494    15224400 :                         const float fVal = pafSrc[i];
     495    15224400 :                         if (bIsNoDataNan && std::isnan(fVal))
     496          48 :                             *pabyLineDest = 0;
     497    15224300 :                         else if (ARE_REAL_EQUAL(fVal, fNoData))
     498      971228 :                             *pabyLineDest = 0;
     499             :                         else
     500    14253100 :                             *pabyLineDest = 255;
     501    15224400 :                         ++i;
     502    15224400 :                         pabyLineDest += nPixelSpace;
     503             :                     }
     504             :                 }
     505             :             }
     506       12631 :             break;
     507             : 
     508          36 :             case GDT_Float64:
     509             :             {
     510          36 :                 const double *padfSrc = static_cast<const double *>(pTemp);
     511             : 
     512          36 :                 size_t i = 0;
     513         132 :                 for (int iY = 0; iY < nBufYSize; iY++)
     514             :                 {
     515          96 :                     GByte *pabyLineDest = pabyDest + iY * nLineSpace;
     516         429 :                     for (int iX = 0; iX < nBufXSize; iX++)
     517             :                     {
     518         333 :                         const double dfVal = padfSrc[i];
     519         333 :                         if (bIsNoDataNan && std::isnan(dfVal))
     520          54 :                             *pabyLineDest = 0;
     521         279 :                         else if (ARE_REAL_EQUAL(dfVal, m_dfNoDataValue))
     522         104 :                             *pabyLineDest = 0;
     523             :                         else
     524         175 :                             *pabyLineDest = 255;
     525         333 :                         ++i;
     526         333 :                         pabyLineDest += nPixelSpace;
     527             :                     }
     528             :                 }
     529             :             }
     530          36 :             break;
     531             : 
     532          17 :             case GDT_Int64:
     533             :             {
     534          17 :                 const auto *panSrc = static_cast<const int64_t *>(pTemp);
     535          17 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     536             :                              nPixelSpace, nLineSpace, m_nNoDataValueInt64);
     537             :             }
     538          17 :             break;
     539             : 
     540          17 :             case GDT_UInt64:
     541             :             {
     542          17 :                 const auto *panSrc = static_cast<const uint64_t *>(pTemp);
     543          17 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     544             :                              nPixelSpace, nLineSpace, m_nNoDataValueUInt64);
     545             :             }
     546          17 :             break;
     547             : 
     548           0 :             default:
     549           0 :                 CPLAssert(false);
     550             :                 break;
     551             :         }
     552             : 
     553       14512 :         VSIFree(pTemp);
     554       14512 :         return CE_None;
     555             :     }
     556             : 
     557             :     // Output buffer is non-Byte. Ask for Byte and expand to user requested
     558             :     // type
     559         125 :     auto [eErr, pTemp] = AllocTempBufferOrFallback(sizeof(GByte));
     560         125 :     if (!pTemp)
     561           0 :         return eErr;
     562             : 
     563         250 :     eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pTemp, nBufXSize,
     564         125 :                      nBufYSize, GDT_Byte, 1, nBufXSize, psExtraArg);
     565         125 :     if (eErr != CE_None)
     566             :     {
     567           0 :         VSIFree(pTemp);
     568           0 :         return eErr;
     569             :     }
     570             : 
     571         282 :     for (int iY = 0; iY < nBufYSize; iY++)
     572             :     {
     573         157 :         GDALCopyWords64(
     574         157 :             static_cast<GByte *>(pTemp) + static_cast<size_t>(iY) * nBufXSize,
     575         157 :             GDT_Byte, 1, static_cast<GByte *>(pData) + iY * nLineSpace,
     576             :             eBufType, static_cast<int>(nPixelSpace), nBufXSize);
     577             :     }
     578         125 :     VSIFree(pTemp);
     579         125 :     return CE_None;
     580             : }
     581             : 
     582             : /************************************************************************/
     583             : /*                   EmitErrorMessageIfWriteNotSupported()              */
     584             : /************************************************************************/
     585             : 
     586           2 : bool GDALNoDataMaskBand::EmitErrorMessageIfWriteNotSupported(
     587             :     const char *pszCaller) const
     588             : {
     589           2 :     ReportError(CE_Failure, CPLE_NoWriteAccess,
     590             :                 "%s: attempt to write to a nodata implicit mask band.",
     591             :                 pszCaller);
     592             : 
     593           2 :     return true;
     594             : }
     595             : 
     596             : //! @endcond

Generated by: LCOV version 1.14