LCOV - code coverage report
Current view: top level - gcore - gdalnodatamaskband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 241 267 90.3 %
Date: 2026-02-21 16:21:44 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        1282 : GDALNoDataMaskBand::GDALNoDataMaskBand(GDALRasterBand *poParentIn)
      36        1282 :     : m_poParent(poParentIn)
      37             : {
      38        1282 :     poDS = nullptr;
      39        1282 :     nBand = 0;
      40             : 
      41        1282 :     nRasterXSize = m_poParent->GetXSize();
      42        1282 :     nRasterYSize = m_poParent->GetYSize();
      43             : 
      44        1282 :     eDataType = GDT_UInt8;
      45        1282 :     m_poParent->GetBlockSize(&nBlockXSize, &nBlockYSize);
      46             : 
      47        1282 :     const auto eParentDT = m_poParent->GetRasterDataType();
      48        1282 :     if (eParentDT == GDT_Int64)
      49          15 :         m_nNoDataValueInt64 = m_poParent->GetNoDataValueAsInt64();
      50        1267 :     else if (eParentDT == GDT_UInt64)
      51          14 :         m_nNoDataValueUInt64 = m_poParent->GetNoDataValueAsUInt64();
      52             :     else
      53        1253 :         m_dfNoDataValue = m_poParent->GetNoDataValue();
      54        1282 : }
      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_UInt8;
      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       18023 : static GDALDataType GetWorkDataType(GDALDataType eDataType)
      93             : {
      94       18023 :     GDALDataType eWrkDT = GDT_Unknown;
      95       18023 :     switch (eDataType)
      96             :     {
      97        1663 :         case GDT_UInt8:
      98        1663 :             eWrkDT = GDT_UInt8;
      99        1663 :             break;
     100             : 
     101        1850 :         case GDT_Int16:
     102        1850 :             eWrkDT = GDT_Int16;
     103        1850 :             break;
     104             : 
     105          67 :         case GDT_UInt16:
     106          67 :             eWrkDT = GDT_UInt16;
     107          67 :             break;
     108             : 
     109          33 :         case GDT_UInt32:
     110          33 :             eWrkDT = GDT_UInt32;
     111          33 :             break;
     112             : 
     113         132 :         case GDT_Int8:
     114             :         case GDT_Int32:
     115             :         case GDT_CInt16:
     116             :         case GDT_CInt32:
     117         132 :             eWrkDT = GDT_Int32;
     118         132 :             break;
     119             : 
     120       14117 :         case GDT_Float16:
     121             :         case GDT_CFloat16:
     122             :         case GDT_Float32:
     123             :         case GDT_CFloat32:
     124       14117 :             eWrkDT = GDT_Float32;
     125       14117 :             break;
     126             : 
     127         113 :         case GDT_Float64:
     128             :         case GDT_CFloat64:
     129         113 :             eWrkDT = GDT_Float64;
     130         113 :             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       18023 :     return eWrkDT;
     144             : }
     145             : 
     146             : /************************************************************************/
     147             : /*                          IsNoDataInRange()                           */
     148             : /************************************************************************/
     149             : 
     150        1301 : bool GDALNoDataMaskBand::IsNoDataInRange(double dfNoDataValue,
     151             :                                          GDALDataType eDataTypeIn)
     152             : {
     153        1301 :     GDALDataType eWrkDT = GetWorkDataType(eDataTypeIn);
     154        1301 :     switch (eWrkDT)
     155             :     {
     156         597 :         case GDT_UInt8:
     157             :         {
     158         597 :             return GDALIsValueInRange<GByte>(dfNoDataValue);
     159             :         }
     160             : 
     161           0 :         case GDT_Int8:
     162             :         {
     163           0 :             return GDALIsValueInRange<signed char>(dfNoDataValue);
     164             :         }
     165             : 
     166         141 :         case GDT_Int16:
     167             :         {
     168         141 :             return GDALIsValueInRange<GInt16>(dfNoDataValue);
     169             :         }
     170             : 
     171          55 :         case GDT_UInt16:
     172             :         {
     173          55 :             return GDALIsValueInRange<GUInt16>(dfNoDataValue);
     174             :         }
     175             : 
     176          22 :         case GDT_UInt32:
     177             :         {
     178          22 :             return GDALIsValueInRange<GUInt32>(dfNoDataValue);
     179             :         }
     180          45 :         case GDT_Int32:
     181             :         {
     182          45 :             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         372 :         case GDT_Float32:
     202             :         {
     203         709 :             return std::isnan(dfNoDataValue) || std::isinf(dfNoDataValue) ||
     204         709 :                    GDALIsValueInRange<float>(dfNoDataValue);
     205             :         }
     206             : 
     207          69 :         case GDT_Float64:
     208             :         {
     209          69 :             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          68 :     return IRasterIO(GF_Read, nXOff, nYOff, nXSizeRequest, nYSizeRequest,
     247             :                      pImage, nXSizeRequest, nYSizeRequest, GDT_UInt8, 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         965 : static void SetZeroOr255(GByte *pabyDestAndSrc, size_t nBufSize, GByte byNoData)
     259             : {
     260     4673420 :     for (size_t i = 0; i < nBufSize; ++i)
     261             :     {
     262     4672460 :         pabyDestAndSrc[i] = (pabyDestAndSrc[i] == byNoData) ? 0 : 255;
     263             :     }
     264         965 : }
     265             : 
     266             : template <class T>
     267             : #if (defined(__GNUC__) && !defined(__clang__))
     268             : __attribute__((optimize("tree-vectorize")))
     269             : #endif
     270        3444 : static void SetZeroOr255(GByte *pabyDest, const T *panSrc, size_t nBufSize,
     271             :                          T nNoData)
     272             : {
     273      999312 :     for (size_t i = 0; i < nBufSize; ++i)
     274             :     {
     275      995868 :         pabyDest[i] = (panSrc[i] == nNoData) ? 0 : 255;
     276             :     }
     277        3444 : }
     278             : 
     279             : template <class T>
     280        1845 : static void SetZeroOr255(GByte *pabyDest, const T *panSrc, int nBufXSize,
     281             :                          int nBufYSize, GSpacing nPixelSpace,
     282             :                          GSpacing nLineSpace, T nNoData)
     283             : {
     284        1845 :     if (nPixelSpace == 1)
     285             :     {
     286        5281 :         for (int iY = 0; iY < nBufYSize; iY++)
     287             :         {
     288        3444 :             SetZeroOr255(pabyDest, panSrc, nBufXSize, nNoData);
     289        3444 :             pabyDest += nLineSpace;
     290        3444 :             panSrc += nBufXSize;
     291             :         }
     292             :     }
     293             :     else
     294             :     {
     295           8 :         size_t i = 0;
     296          40 :         for (int iY = 0; iY < nBufYSize; iY++)
     297             :         {
     298          32 :             GByte *pabyLineDest = pabyDest + iY * nLineSpace;
     299         224 :             for (int iX = 0; iX < nBufXSize; iX++)
     300             :             {
     301         192 :                 *pabyLineDest = (panSrc[i] == nNoData) ? 0 : 255;
     302         192 :                 ++i;
     303         192 :                 pabyLineDest += nPixelSpace;
     304             :             }
     305             :         }
     306             :     }
     307        1845 : }
     308             : 
     309             : /************************************************************************/
     310             : /*                             IRasterIO()                              */
     311             : /************************************************************************/
     312             : 
     313       16722 : CPLErr GDALNoDataMaskBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     314             :                                      int nXSize, int nYSize, void *pData,
     315             :                                      int nBufXSize, int nBufYSize,
     316             :                                      GDALDataType eBufType,
     317             :                                      GSpacing nPixelSpace, GSpacing nLineSpace,
     318             :                                      GDALRasterIOExtraArg *psExtraArg)
     319             : {
     320       16722 :     if (eRWFlag != GF_Read)
     321             :     {
     322           0 :         return CE_Failure;
     323             :     }
     324       16722 :     const auto eParentDT = m_poParent->GetRasterDataType();
     325       16722 :     const GDALDataType eWrkDT = GetWorkDataType(eParentDT);
     326             : 
     327             :     // Optimization in common use case (#4488).
     328             :     // This avoids triggering the block cache on this band, which helps
     329             :     // reducing the global block cache consumption.
     330       16722 :     if (eBufType == GDT_UInt8 && eWrkDT == GDT_UInt8 && nPixelSpace == 1 &&
     331         962 :         nLineSpace >= nBufXSize)
     332             :     {
     333         962 :         const CPLErr eErr = m_poParent->RasterIO(
     334             :             GF_Read, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     335             :             eBufType, nPixelSpace, nLineSpace, psExtraArg);
     336         962 :         if (eErr != CE_None)
     337           0 :             return eErr;
     338             : 
     339         962 :         GByte *pabyData = static_cast<GByte *>(pData);
     340         962 :         const GByte byNoData = static_cast<GByte>(m_dfNoDataValue);
     341             : 
     342         962 :         if (nLineSpace == nBufXSize)
     343             :         {
     344         961 :             const size_t nBufSize = static_cast<size_t>(nBufXSize) * nBufYSize;
     345         961 :             SetZeroOr255(pabyData, nBufSize, byNoData);
     346             :         }
     347             :         else
     348             :         {
     349           1 :             assert(nLineSpace > nBufXSize);
     350           5 :             for (int iY = 0; iY < nBufYSize; iY++)
     351             :             {
     352           4 :                 SetZeroOr255(pabyData, nBufXSize, byNoData);
     353           4 :                 pabyData += nLineSpace;
     354             :             }
     355             :         }
     356         962 :         return CE_None;
     357             :     }
     358             : 
     359             :     const auto AllocTempBufferOrFallback =
     360       15760 :         [this, eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     361             :          nBufYSize, eBufType, nPixelSpace, nLineSpace,
     362       31576 :          psExtraArg](int nWrkDTSize) -> std::pair<CPLErr, void *>
     363             :     {
     364       15760 :         auto poParentDS = m_poParent->GetDataset();
     365             :         // Check if we must simulate a memory allocation failure
     366             :         // Before checking the env variable, which is slightly expensive,
     367             :         // check first for a special dataset name, which is a cheap test.
     368             :         const char *pszOptVal =
     369       15760 :             poParentDS && strcmp(poParentDS->GetDescription(), "__debug__") == 0
     370       31520 :                 ? CPLGetConfigOption(
     371             :                       "GDAL_SIMUL_MEM_ALLOC_FAILURE_NODATA_MASK_BAND", "NO")
     372       15760 :                 : "NO";
     373             :         const bool bSimulMemAllocFailure =
     374       31516 :             EQUAL(pszOptVal, "ALWAYS") ||
     375       15756 :             (CPLTestBool(pszOptVal) &&
     376          14 :              GDALMajorObject::GetMetadataItem(__func__, "__INTERNAL__") ==
     377       15760 :                  nullptr);
     378       15760 :         void *pTemp = nullptr;
     379       15760 :         if (!bSimulMemAllocFailure)
     380             :         {
     381       15748 :             CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
     382       15748 :             pTemp = VSI_MALLOC3_VERBOSE(nWrkDTSize, nBufXSize, nBufYSize);
     383             :         }
     384       15760 :         if (!pTemp)
     385             :         {
     386             :             const bool bAllocHasAlreadyFailed =
     387          12 :                 GDALMajorObject::GetMetadataItem(__func__, "__INTERNAL__") !=
     388          12 :                 nullptr;
     389          12 :             CPLError(bAllocHasAlreadyFailed ? CE_Failure : CE_Warning,
     390             :                      CPLE_OutOfMemory,
     391             :                      "GDALNoDataMaskBand::IRasterIO(): cannot allocate %d x %d "
     392             :                      "x %d bytes%s",
     393             :                      nBufXSize, nBufYSize, nWrkDTSize,
     394             :                      bAllocHasAlreadyFailed
     395             :                          ? ""
     396             :                          : ". Falling back to block-based approach");
     397          12 :             if (bAllocHasAlreadyFailed)
     398           2 :                 return std::pair(CE_Failure, nullptr);
     399             :             // Sets a metadata item to prevent potential infinite recursion
     400          10 :             GDALMajorObject::SetMetadataItem(__func__, "IN", "__INTERNAL__");
     401          10 :             const CPLErr eErr = GDALRasterBand::IRasterIO(
     402             :                 eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     403          10 :                 nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     404          10 :             GDALMajorObject::SetMetadataItem(__func__, nullptr, "__INTERNAL__");
     405          10 :             return std::pair(eErr, nullptr);
     406             :         }
     407       15748 :         return std::pair(CE_None, pTemp);
     408       15760 :     };
     409             : 
     410       15760 :     if (eBufType == GDT_UInt8)
     411             :     {
     412       15635 :         const int nWrkDTSize = GDALGetDataTypeSizeBytes(eWrkDT);
     413       15635 :         auto [eErr, pTemp] = AllocTempBufferOrFallback(nWrkDTSize);
     414       15635 :         if (!pTemp)
     415          12 :             return eErr;
     416             : 
     417       31246 :         eErr = m_poParent->RasterIO(
     418             :             GF_Read, nXOff, nYOff, nXSize, nYSize, pTemp, nBufXSize, nBufYSize,
     419       15623 :             eWrkDT, nWrkDTSize, static_cast<GSpacing>(nBufXSize) * nWrkDTSize,
     420             :             psExtraArg);
     421       15623 :         if (eErr != CE_None)
     422             :         {
     423           0 :             VSIFree(pTemp);
     424           0 :             return eErr;
     425             :         }
     426             : 
     427       15623 :         const bool bIsNoDataNan = std::isnan(m_dfNoDataValue) != 0;
     428       15623 :         GByte *pabyDest = static_cast<GByte *>(pData);
     429             : 
     430             :         /* --------------------------------------------------------------------
     431             :          */
     432             :         /*      Process different cases. */
     433             :         /* --------------------------------------------------------------------
     434             :          */
     435       15623 :         switch (eWrkDT)
     436             :         {
     437           1 :             case GDT_UInt8:
     438             :             {
     439           1 :                 const auto nNoData = static_cast<GByte>(m_dfNoDataValue);
     440           1 :                 const auto *panSrc = static_cast<const GByte *>(pTemp);
     441           1 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     442             :                              nPixelSpace, nLineSpace, nNoData);
     443             :             }
     444           1 :             break;
     445             : 
     446        1707 :             case GDT_Int16:
     447             :             {
     448        1707 :                 const auto nNoData = static_cast<int16_t>(m_dfNoDataValue);
     449        1707 :                 const auto *panSrc = static_cast<const int16_t *>(pTemp);
     450        1707 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     451             :                              nPixelSpace, nLineSpace, nNoData);
     452             :             }
     453        1707 :             break;
     454             : 
     455          10 :             case GDT_UInt16:
     456             :             {
     457          10 :                 const auto nNoData = static_cast<uint16_t>(m_dfNoDataValue);
     458          10 :                 const auto *panSrc = static_cast<const uint16_t *>(pTemp);
     459          10 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     460             :                              nPixelSpace, nLineSpace, nNoData);
     461             :             }
     462          10 :             break;
     463             : 
     464           9 :             case GDT_UInt32:
     465             :             {
     466           9 :                 const auto nNoData = static_cast<GUInt32>(m_dfNoDataValue);
     467           9 :                 const auto *panSrc = static_cast<const GUInt32 *>(pTemp);
     468           9 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     469             :                              nPixelSpace, nLineSpace, nNoData);
     470             :             }
     471           9 :             break;
     472             : 
     473          84 :             case GDT_Int32:
     474             :             {
     475          84 :                 const auto nNoData = static_cast<GInt32>(m_dfNoDataValue);
     476          84 :                 const auto *panSrc = static_cast<const GInt32 *>(pTemp);
     477          84 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     478             :                              nPixelSpace, nLineSpace, nNoData);
     479             :             }
     480          84 :             break;
     481             : 
     482       13739 :             case GDT_Float32:
     483             :             {
     484       13739 :                 const float fNoData = static_cast<float>(m_dfNoDataValue);
     485       13739 :                 const float *pafSrc = static_cast<const float *>(pTemp);
     486             : 
     487       13739 :                 size_t i = 0;
     488       30730 :                 for (int iY = 0; iY < nBufYSize; iY++)
     489             :                 {
     490       16991 :                     GByte *pabyLineDest = pabyDest + iY * nLineSpace;
     491    15400200 :                     for (int iX = 0; iX < nBufXSize; iX++)
     492             :                     {
     493    15383200 :                         const float fVal = pafSrc[i];
     494    15383200 :                         if (bIsNoDataNan && std::isnan(fVal))
     495          48 :                             *pabyLineDest = 0;
     496    15383200 :                         else if (ARE_REAL_EQUAL(fVal, fNoData))
     497      972982 :                             *pabyLineDest = 0;
     498             :                         else
     499    14410200 :                             *pabyLineDest = 255;
     500    15383200 :                         ++i;
     501    15383200 :                         pabyLineDest += nPixelSpace;
     502             :                     }
     503             :                 }
     504             :             }
     505       13739 :             break;
     506             : 
     507          39 :             case GDT_Float64:
     508             :             {
     509          39 :                 const double *padfSrc = static_cast<const double *>(pTemp);
     510             : 
     511          39 :                 size_t i = 0;
     512         159 :                 for (int iY = 0; iY < nBufYSize; iY++)
     513             :                 {
     514         120 :                     GByte *pabyLineDest = pabyDest + iY * nLineSpace;
     515         665 :                     for (int iX = 0; iX < nBufXSize; iX++)
     516             :                     {
     517         545 :                         const double dfVal = padfSrc[i];
     518         545 :                         if (bIsNoDataNan && std::isnan(dfVal))
     519          54 :                             *pabyLineDest = 0;
     520         491 :                         else if (ARE_REAL_EQUAL(dfVal, m_dfNoDataValue))
     521         241 :                             *pabyLineDest = 0;
     522             :                         else
     523         250 :                             *pabyLineDest = 255;
     524         545 :                         ++i;
     525         545 :                         pabyLineDest += nPixelSpace;
     526             :                     }
     527             :                 }
     528             :             }
     529          39 :             break;
     530             : 
     531          17 :             case GDT_Int64:
     532             :             {
     533          17 :                 const auto *panSrc = static_cast<const int64_t *>(pTemp);
     534          17 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     535             :                              nPixelSpace, nLineSpace, m_nNoDataValueInt64);
     536             :             }
     537          17 :             break;
     538             : 
     539          17 :             case GDT_UInt64:
     540             :             {
     541          17 :                 const auto *panSrc = static_cast<const uint64_t *>(pTemp);
     542          17 :                 SetZeroOr255(pabyDest, panSrc, nBufXSize, nBufYSize,
     543             :                              nPixelSpace, nLineSpace, m_nNoDataValueUInt64);
     544             :             }
     545          17 :             break;
     546             : 
     547           0 :             default:
     548           0 :                 CPLAssert(false);
     549             :                 break;
     550             :         }
     551             : 
     552       15623 :         VSIFree(pTemp);
     553       15623 :         return CE_None;
     554             :     }
     555             : 
     556             :     // Output buffer is non-Byte. Ask for Byte and expand to user requested
     557             :     // type
     558         125 :     auto [eErr, pTemp] = AllocTempBufferOrFallback(sizeof(GByte));
     559         125 :     if (!pTemp)
     560           0 :         return eErr;
     561             : 
     562         125 :     eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pTemp, nBufXSize,
     563             :                      nBufYSize, GDT_UInt8, 1, nBufXSize, psExtraArg);
     564         125 :     if (eErr != CE_None)
     565             :     {
     566           0 :         VSIFree(pTemp);
     567           0 :         return eErr;
     568             :     }
     569             : 
     570         282 :     for (int iY = 0; iY < nBufYSize; iY++)
     571             :     {
     572         157 :         GDALCopyWords64(
     573         157 :             static_cast<GByte *>(pTemp) + static_cast<size_t>(iY) * nBufXSize,
     574         157 :             GDT_UInt8, 1, static_cast<GByte *>(pData) + iY * nLineSpace,
     575             :             eBufType, static_cast<int>(nPixelSpace), nBufXSize);
     576             :     }
     577         125 :     VSIFree(pTemp);
     578         125 :     return CE_None;
     579             : }
     580             : 
     581             : /************************************************************************/
     582             : /*                EmitErrorMessageIfWriteNotSupported()                 */
     583             : /************************************************************************/
     584             : 
     585           2 : bool GDALNoDataMaskBand::EmitErrorMessageIfWriteNotSupported(
     586             :     const char *pszCaller) const
     587             : {
     588           2 :     ReportError(CE_Failure, CPLE_NoWriteAccess,
     589             :                 "%s: attempt to write to a nodata implicit mask band.",
     590             :                 pszCaller);
     591             : 
     592           2 :     return true;
     593             : }
     594             : 
     595             : //! @endcond

Generated by: LCOV version 1.14