LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband_write.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 396 444 89.2 %
Date: 2024-11-21 22:18:42 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GeoTIFF Driver
       4             :  * Purpose:  Write/set operations on GTiffRasterBand
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1998, 2002, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2007-2015, Even Rouault <even dot rouault at spatialys dot com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "gtiffrasterband.h"
      15             : #include "gtiffdataset.h"
      16             : 
      17             : #include <algorithm>
      18             : #include <cmath>
      19             : #include <limits>
      20             : 
      21             : #include "cpl_vsi_virtual.h"
      22             : #include "gdal_priv_templates.hpp"
      23             : #include "gtiff.h"
      24             : #include "tifvsi.h"
      25             : 
      26             : /************************************************************************/
      27             : /*                           SetDefaultRAT()                            */
      28             : /************************************************************************/
      29             : 
      30           8 : CPLErr GTiffRasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
      31             : {
      32           8 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
      33           8 :     return GDALPamRasterBand::SetDefaultRAT(poRAT);
      34             : }
      35             : 
      36             : /************************************************************************/
      37             : /*                            IWriteBlock()                             */
      38             : /************************************************************************/
      39             : 
      40       53684 : CPLErr GTiffRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
      41             :                                     void *pImage)
      42             : 
      43             : {
      44       53684 :     m_poGDS->Crystalize();
      45             : 
      46       53684 :     if (m_poGDS->m_bDebugDontWriteBlocks)
      47           0 :         return CE_None;
      48             : 
      49       53684 :     if (m_poGDS->m_bWriteError)
      50             :     {
      51             :         // Report as an error if a previously loaded block couldn't be written
      52             :         // correctly.
      53           0 :         return CE_Failure;
      54             :     }
      55             : 
      56       53684 :     const int nBlockId = ComputeBlockId(nBlockXOff, nBlockYOff);
      57             : 
      58             :     /* -------------------------------------------------------------------- */
      59             :     /*      Handle case of "separate" images                                */
      60             :     /* -------------------------------------------------------------------- */
      61       53684 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE ||
      62       38849 :         m_poGDS->nBands == 1)
      63             :     {
      64             :         const CPLErr eErr =
      65       24791 :             m_poGDS->WriteEncodedTileOrStrip(nBlockId, pImage, true);
      66             : 
      67       24787 :         return eErr;
      68             :     }
      69             : 
      70             :     /* -------------------------------------------------------------------- */
      71             :     /*      Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images.  */
      72             :     /* -------------------------------------------------------------------- */
      73             :     // Why 10 ? Somewhat arbitrary
      74       28893 :     constexpr int MAX_BANDS_FOR_DIRTY_CHECK = 10;
      75       28893 :     GDALRasterBlock *apoBlocks[MAX_BANDS_FOR_DIRTY_CHECK] = {};
      76       28893 :     const int nBands = m_poGDS->nBands;
      77       28893 :     bool bAllBlocksDirty = false;
      78             : 
      79             :     /* -------------------------------------------------------------------- */
      80             :     /*     If all blocks are cached and dirty then we do not need to reload */
      81             :     /*     the tile/strip from disk                                         */
      82             :     /* -------------------------------------------------------------------- */
      83       28893 :     if (nBands <= MAX_BANDS_FOR_DIRTY_CHECK)
      84             :     {
      85       28891 :         bAllBlocksDirty = true;
      86      120105 :         for (int iBand = 0; iBand < nBands; ++iBand)
      87             :         {
      88       91214 :             if (iBand + 1 != nBand)
      89             :             {
      90       62323 :                 apoBlocks[iBand] =
      91       62323 :                     cpl::down_cast<GTiffRasterBand *>(
      92       62323 :                         m_poGDS->GetRasterBand(iBand + 1))
      93       62323 :                         ->TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
      94             : 
      95       62323 :                 if (apoBlocks[iBand] == nullptr)
      96             :                 {
      97        1532 :                     bAllBlocksDirty = false;
      98             :                 }
      99       60791 :                 else if (!apoBlocks[iBand]->GetDirty())
     100             :                 {
     101         100 :                     apoBlocks[iBand]->DropLock();
     102         100 :                     apoBlocks[iBand] = nullptr;
     103         100 :                     bAllBlocksDirty = false;
     104             :                 }
     105             :             }
     106             :             else
     107       28891 :                 apoBlocks[iBand] = nullptr;
     108             :         }
     109             : #if DEBUG_VERBOSE
     110             :         if (bAllBlocksDirty)
     111             :             CPLDebug("GTIFF", "Saved reloading block %d", nBlockId);
     112             :         else
     113             :             CPLDebug("GTIFF", "Must reload block %d", nBlockId);
     114             : #endif
     115             :     }
     116             : 
     117             :     {
     118       28893 :         const CPLErr eErr = m_poGDS->LoadBlockBuf(nBlockId, !bAllBlocksDirty);
     119       28893 :         if (eErr != CE_None)
     120             :         {
     121           1 :             if (nBands <= MAX_BANDS_FOR_DIRTY_CHECK)
     122             :             {
     123           4 :                 for (int iBand = 0; iBand < nBands; ++iBand)
     124             :                 {
     125           3 :                     if (apoBlocks[iBand] != nullptr)
     126           0 :                         apoBlocks[iBand]->DropLock();
     127             :                 }
     128             :             }
     129           1 :             return eErr;
     130             :         }
     131             :     }
     132             : 
     133             :     /* -------------------------------------------------------------------- */
     134             :     /*      On write of pixel interleaved data, we might as well flush      */
     135             :     /*      out any other bands that are dirty in our cache.  This is       */
     136             :     /*      especially helpful when writing compressed blocks.              */
     137             :     /* -------------------------------------------------------------------- */
     138       28892 :     const int nWordBytes = m_poGDS->m_nBitsPerSample / 8;
     139             : 
     140      120125 :     for (int iBand = 0; iBand < nBands; ++iBand)
     141             :     {
     142       91233 :         const GByte *pabyThisImage = nullptr;
     143       91233 :         GDALRasterBlock *poBlock = nullptr;
     144             : 
     145       91233 :         if (iBand + 1 == nBand)
     146             :         {
     147       28892 :             pabyThisImage = static_cast<GByte *>(pImage);
     148             :         }
     149             :         else
     150             :         {
     151       62341 :             if (nBands <= MAX_BANDS_FOR_DIRTY_CHECK)
     152       62321 :                 poBlock = apoBlocks[iBand];
     153             :             else
     154          20 :                 poBlock = cpl::down_cast<GTiffRasterBand *>(
     155          20 :                               m_poGDS->GetRasterBand(iBand + 1))
     156          20 :                               ->TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
     157             : 
     158       62341 :             if (poBlock == nullptr)
     159        1641 :                 continue;
     160             : 
     161       60700 :             if (!poBlock->GetDirty())
     162             :             {
     163           8 :                 poBlock->DropLock();
     164           8 :                 continue;
     165             :             }
     166             : 
     167       60692 :             pabyThisImage = static_cast<GByte *>(poBlock->GetDataRef());
     168             :         }
     169             : 
     170       89584 :         GByte *pabyOut = m_poGDS->m_pabyBlockBuf + iBand * nWordBytes;
     171             : 
     172       89584 :         GDALCopyWords64(pabyThisImage, eDataType, nWordBytes, pabyOut,
     173             :                         eDataType, nWordBytes * nBands,
     174       89584 :                         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize);
     175             : 
     176       89584 :         if (poBlock != nullptr)
     177             :         {
     178       60692 :             poBlock->MarkClean();
     179       60692 :             poBlock->DropLock();
     180             :         }
     181             :     }
     182             : 
     183       28892 :     if (bAllBlocksDirty)
     184             :     {
     185             :         // We can synchronously write the block now.
     186       56158 :         const CPLErr eErr = m_poGDS->WriteEncodedTileOrStrip(
     187       28079 :             nBlockId, m_poGDS->m_pabyBlockBuf, true);
     188       28079 :         m_poGDS->m_bLoadedBlockDirty = false;
     189       28079 :         return eErr;
     190             :     }
     191             : 
     192         813 :     m_poGDS->m_bLoadedBlockDirty = true;
     193             : 
     194         813 :     return CE_None;
     195             : }
     196             : 
     197             : /************************************************************************/
     198             : /*                           SetDescription()                           */
     199             : /************************************************************************/
     200             : 
     201          16 : void GTiffRasterBand::SetDescription(const char *pszDescription)
     202             : 
     203             : {
     204          16 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     205             : 
     206          16 :     if (pszDescription == nullptr)
     207           0 :         pszDescription = "";
     208             : 
     209          16 :     if (m_osDescription != pszDescription)
     210           9 :         m_poGDS->m_bMetadataChanged = true;
     211             : 
     212          16 :     m_osDescription = pszDescription;
     213          16 : }
     214             : 
     215             : /************************************************************************/
     216             : /*                             SetOffset()                              */
     217             : /************************************************************************/
     218             : 
     219          18 : CPLErr GTiffRasterBand::SetOffset(double dfNewValue)
     220             : 
     221             : {
     222          18 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     223             : 
     224          18 :     if (!m_bHaveOffsetScale || dfNewValue != m_dfOffset)
     225          14 :         m_poGDS->m_bMetadataChanged = true;
     226             : 
     227          18 :     m_bHaveOffsetScale = true;
     228          18 :     m_dfOffset = dfNewValue;
     229          18 :     return CE_None;
     230             : }
     231             : 
     232             : /************************************************************************/
     233             : /*                              SetScale()                              */
     234             : /************************************************************************/
     235             : 
     236          19 : CPLErr GTiffRasterBand::SetScale(double dfNewValue)
     237             : 
     238             : {
     239          19 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     240             : 
     241          19 :     if (!m_bHaveOffsetScale || dfNewValue != m_dfScale)
     242          19 :         m_poGDS->m_bMetadataChanged = true;
     243             : 
     244          19 :     m_bHaveOffsetScale = true;
     245          19 :     m_dfScale = dfNewValue;
     246          19 :     return CE_None;
     247             : }
     248             : 
     249             : /************************************************************************/
     250             : /*                           SetUnitType()                              */
     251             : /************************************************************************/
     252             : 
     253          26 : CPLErr GTiffRasterBand::SetUnitType(const char *pszNewValue)
     254             : 
     255             : {
     256          26 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     257             : 
     258          26 :     CPLString osNewValue(pszNewValue ? pszNewValue : "");
     259          26 :     if (osNewValue.compare(m_osUnitType) != 0)
     260          19 :         m_poGDS->m_bMetadataChanged = true;
     261             : 
     262          26 :     m_osUnitType = std::move(osNewValue);
     263          52 :     return CE_None;
     264             : }
     265             : 
     266             : /************************************************************************/
     267             : /*                            SetMetadata()                             */
     268             : /************************************************************************/
     269             : 
     270        4653 : CPLErr GTiffRasterBand::SetMetadata(char **papszMD, const char *pszDomain)
     271             : 
     272             : {
     273        4653 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     274             : 
     275        4653 :     if (m_poGDS->m_bStreamingOut && m_poGDS->m_bCrystalized)
     276             :     {
     277           1 :         ReportError(CE_Failure, CPLE_NotSupported,
     278             :                     "Cannot modify metadata at that point in a streamed "
     279             :                     "output file");
     280           1 :         return CE_Failure;
     281             :     }
     282             : 
     283        4652 :     CPLErr eErr = CE_None;
     284        4652 :     if (eAccess == GA_Update)
     285             :     {
     286        4645 :         if (pszDomain == nullptr || !EQUAL(pszDomain, "_temporary_"))
     287             :         {
     288        4645 :             if (papszMD != nullptr || GetMetadata(pszDomain) != nullptr)
     289             :             {
     290          92 :                 m_poGDS->m_bMetadataChanged = true;
     291             :                 // Cancel any existing metadata from PAM file.
     292          92 :                 if (GDALPamRasterBand::GetMetadata(pszDomain) != nullptr)
     293           1 :                     GDALPamRasterBand::SetMetadata(nullptr, pszDomain);
     294             :             }
     295             :         }
     296             :     }
     297             :     else
     298             :     {
     299           7 :         CPLDebug(
     300             :             "GTIFF",
     301             :             "GTiffRasterBand::SetMetadata() goes to PAM instead of TIFF tags");
     302           7 :         eErr = GDALPamRasterBand::SetMetadata(papszMD, pszDomain);
     303             :     }
     304             : 
     305        4652 :     if (eErr == CE_None)
     306             :     {
     307        4652 :         eErr = m_oGTiffMDMD.SetMetadata(papszMD, pszDomain);
     308             :     }
     309        4652 :     return eErr;
     310             : }
     311             : 
     312             : /************************************************************************/
     313             : /*                          SetMetadataItem()                           */
     314             : /************************************************************************/
     315             : 
     316         503 : CPLErr GTiffRasterBand::SetMetadataItem(const char *pszName,
     317             :                                         const char *pszValue,
     318             :                                         const char *pszDomain)
     319             : 
     320             : {
     321         503 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     322             : 
     323         503 :     if (m_poGDS->m_bStreamingOut && m_poGDS->m_bCrystalized)
     324             :     {
     325           1 :         ReportError(CE_Failure, CPLE_NotSupported,
     326             :                     "Cannot modify metadata at that point in a streamed "
     327             :                     "output file");
     328           1 :         return CE_Failure;
     329             :     }
     330             : 
     331         502 :     CPLErr eErr = CE_None;
     332         502 :     if (eAccess == GA_Update)
     333             :     {
     334         311 :         if (pszDomain == nullptr || !EQUAL(pszDomain, "_temporary_"))
     335             :         {
     336         311 :             m_poGDS->m_bMetadataChanged = true;
     337             :             // Cancel any existing metadata from PAM file.
     338         311 :             if (GDALPamRasterBand::GetMetadataItem(pszName, pszDomain) !=
     339             :                 nullptr)
     340           1 :                 GDALPamRasterBand::SetMetadataItem(pszName, nullptr, pszDomain);
     341             :         }
     342             :     }
     343             :     else
     344             :     {
     345         191 :         CPLDebug("GTIFF", "GTiffRasterBand::SetMetadataItem() goes to PAM "
     346             :                           "instead of TIFF tags");
     347         191 :         eErr = GDALPamRasterBand::SetMetadataItem(pszName, pszValue, pszDomain);
     348             :     }
     349             : 
     350         502 :     if (eErr == CE_None)
     351             :     {
     352         502 :         eErr = m_oGTiffMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
     353             :     }
     354         502 :     return eErr;
     355             : }
     356             : 
     357             : /************************************************************************/
     358             : /*                       SetColorInterpretation()                       */
     359             : /************************************************************************/
     360             : 
     361         672 : CPLErr GTiffRasterBand::SetColorInterpretation(GDALColorInterp eInterp)
     362             : 
     363             : {
     364         672 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     365             : 
     366         672 :     if (eInterp == m_eBandInterp)
     367         565 :         return CE_None;
     368             : 
     369         107 :     m_eBandInterp = eInterp;
     370             : 
     371         107 :     if (eAccess != GA_Update)
     372             :     {
     373           1 :         CPLDebug("GTIFF",
     374             :                  "ColorInterpretation %s for band %d goes to PAM "
     375             :                  "instead of TIFF tag",
     376             :                  GDALGetColorInterpretationName(eInterp), nBand);
     377           1 :         return GDALPamRasterBand::SetColorInterpretation(eInterp);
     378             :     }
     379             : 
     380         106 :     m_poGDS->m_bNeedsRewrite = true;
     381         106 :     m_poGDS->m_bMetadataChanged = true;
     382             : 
     383             :     // Try to autoset TIFFTAG_PHOTOMETRIC = PHOTOMETRIC_RGB if possible.
     384          53 :     if (m_poGDS->nBands >= 3 && m_poGDS->m_nCompression != COMPRESSION_JPEG &&
     385          53 :         m_poGDS->m_nPhotometric != PHOTOMETRIC_RGB &&
     386          28 :         CSLFetchNameValue(m_poGDS->m_papszCreationOptions, "PHOTOMETRIC") ==
     387         159 :             nullptr &&
     388          18 :         ((nBand == 1 && eInterp == GCI_RedBand) ||
     389          15 :          (nBand == 2 && eInterp == GCI_GreenBand) ||
     390          12 :          (nBand == 3 && eInterp == GCI_BlueBand)))
     391             :     {
     392           9 :         if (m_poGDS->GetRasterBand(1)->GetColorInterpretation() ==
     393           7 :                 GCI_RedBand &&
     394           7 :             m_poGDS->GetRasterBand(2)->GetColorInterpretation() ==
     395          16 :                 GCI_GreenBand &&
     396           5 :             m_poGDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand)
     397             :         {
     398           3 :             m_poGDS->m_nPhotometric = PHOTOMETRIC_RGB;
     399           3 :             TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_PHOTOMETRIC,
     400           3 :                          m_poGDS->m_nPhotometric);
     401             : 
     402             :             // We need to update the number of extra samples.
     403           3 :             uint16_t *v = nullptr;
     404           3 :             uint16_t count = 0;
     405           3 :             const uint16_t nNewExtraSamplesCount =
     406           3 :                 static_cast<uint16_t>(m_poGDS->nBands - 3);
     407           7 :             if (m_poGDS->nBands >= 4 &&
     408           1 :                 TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count,
     409           4 :                              &v) &&
     410           1 :                 count > nNewExtraSamplesCount)
     411             :             {
     412             :                 uint16_t *const pasNewExtraSamples = static_cast<uint16_t *>(
     413           1 :                     CPLMalloc(nNewExtraSamplesCount * sizeof(uint16_t)));
     414           1 :                 memcpy(pasNewExtraSamples, v + count - nNewExtraSamplesCount,
     415           1 :                        nNewExtraSamplesCount * sizeof(uint16_t));
     416             : 
     417           1 :                 TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES,
     418             :                              nNewExtraSamplesCount, pasNewExtraSamples);
     419             : 
     420           1 :                 CPLFree(pasNewExtraSamples);
     421             :             }
     422             :         }
     423           9 :         return CE_None;
     424             :     }
     425             : 
     426             :     // On the contrary, cancel the above if needed
     427         291 :     if (m_poGDS->m_nCompression != COMPRESSION_JPEG &&
     428          97 :         m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB &&
     429          25 :         CSLFetchNameValue(m_poGDS->m_papszCreationOptions, "PHOTOMETRIC") ==
     430         194 :             nullptr &&
     431           7 :         ((nBand == 1 && eInterp != GCI_RedBand) ||
     432           3 :          (nBand == 2 && eInterp != GCI_GreenBand) ||
     433           3 :          (nBand == 3 && eInterp != GCI_BlueBand)))
     434             :     {
     435           4 :         m_poGDS->m_nPhotometric = PHOTOMETRIC_MINISBLACK;
     436           4 :         TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_PHOTOMETRIC,
     437           4 :                      m_poGDS->m_nPhotometric);
     438             : 
     439             :         // We need to update the number of extra samples.
     440           4 :         uint16_t *v = nullptr;
     441           4 :         uint16_t count = 0;
     442           4 :         const uint16_t nNewExtraSamplesCount =
     443           4 :             static_cast<uint16_t>(m_poGDS->nBands - 1);
     444           4 :         if (m_poGDS->nBands >= 2)
     445             :         {
     446           4 :             TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v);
     447           4 :             if (nNewExtraSamplesCount > count)
     448             :             {
     449             :                 uint16_t *const pasNewExtraSamples = static_cast<uint16_t *>(
     450           4 :                     CPLMalloc(nNewExtraSamplesCount * sizeof(uint16_t)));
     451           4 :                 for (int i = 0;
     452          12 :                      i < static_cast<int>(nNewExtraSamplesCount - count); ++i)
     453           8 :                     pasNewExtraSamples[i] = EXTRASAMPLE_UNSPECIFIED;
     454           4 :                 if (count > 0)
     455             :                 {
     456           2 :                     memcpy(pasNewExtraSamples + nNewExtraSamplesCount - count,
     457           2 :                            v, count * sizeof(uint16_t));
     458             :                 }
     459             : 
     460           4 :                 TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES,
     461             :                              nNewExtraSamplesCount, pasNewExtraSamples);
     462             : 
     463           4 :                 CPLFree(pasNewExtraSamples);
     464             :             }
     465             :         }
     466             :     }
     467             : 
     468             :     // Mark alpha band / undefined in extrasamples.
     469          97 :     if (eInterp == GCI_AlphaBand || eInterp == GCI_Undefined)
     470             :     {
     471          83 :         uint16_t *v = nullptr;
     472          83 :         uint16_t count = 0;
     473          83 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     474             :         {
     475          70 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     476             : 
     477          70 :             if (eInterp == GCI_AlphaBand)
     478             :             {
     479         256 :                 for (int i = 1; i <= m_poGDS->nBands; ++i)
     480             :                 {
     481         317 :                     if (i != nBand &&
     482         126 :                         m_poGDS->GetRasterBand(i)->GetColorInterpretation() ==
     483             :                             GCI_AlphaBand)
     484             :                     {
     485           4 :                         if (i == nBaseSamples + 1 &&
     486           2 :                             CSLFetchNameValue(m_poGDS->m_papszCreationOptions,
     487             :                                               "ALPHA") != nullptr)
     488             :                         {
     489           1 :                             ReportError(
     490             :                                 CE_Warning, CPLE_AppDefined,
     491             :                                 "Band %d was already identified as alpha band, "
     492             :                                 "and band %d is now marked as alpha too. "
     493             :                                 "Presumably ALPHA creation option is not "
     494             :                                 "needed",
     495             :                                 i, nBand);
     496             :                         }
     497             :                         else
     498             :                         {
     499           1 :                             ReportError(
     500             :                                 CE_Warning, CPLE_AppDefined,
     501             :                                 "Band %d was already identified as alpha band, "
     502             :                                 "and band %d is now marked as alpha too",
     503             :                                 i, nBand);
     504             :                         }
     505             :                     }
     506             :                 }
     507             :             }
     508             : 
     509          70 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count)
     510             :             {
     511             :                 // We need to allocate a new array as (current) libtiff
     512             :                 // versions will not like that we reuse the array we got from
     513             :                 // TIFFGetField().
     514             : 
     515             :                 uint16_t *pasNewExtraSamples = static_cast<uint16_t *>(
     516          69 :                     CPLMalloc(count * sizeof(uint16_t)));
     517          69 :                 memcpy(pasNewExtraSamples, v, count * sizeof(uint16_t));
     518          69 :                 if (eInterp == GCI_AlphaBand)
     519             :                 {
     520         130 :                     pasNewExtraSamples[nBand - nBaseSamples - 1] =
     521          65 :                         GTiffGetAlphaValue(
     522             :                             CPLGetConfigOption("GTIFF_ALPHA", nullptr),
     523             :                             DEFAULT_ALPHA_TYPE);
     524             :                 }
     525             :                 else
     526             :                 {
     527           4 :                     pasNewExtraSamples[nBand - nBaseSamples - 1] =
     528             :                         EXTRASAMPLE_UNSPECIFIED;
     529             :                 }
     530             : 
     531          69 :                 TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, count,
     532             :                              pasNewExtraSamples);
     533             : 
     534          69 :                 CPLFree(pasNewExtraSamples);
     535             : 
     536          69 :                 return CE_None;
     537             :             }
     538             :         }
     539             :     }
     540             : 
     541          28 :     if (m_poGDS->m_nPhotometric != PHOTOMETRIC_MINISBLACK &&
     542           0 :         CSLFetchNameValue(m_poGDS->m_papszCreationOptions, "PHOTOMETRIC") ==
     543             :             nullptr)
     544             :     {
     545           0 :         m_poGDS->m_nPhotometric = PHOTOMETRIC_MINISBLACK;
     546           0 :         TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_PHOTOMETRIC,
     547           0 :                      m_poGDS->m_nPhotometric);
     548             :     }
     549             : 
     550          28 :     return CE_None;
     551             : }
     552             : 
     553             : /************************************************************************/
     554             : /*                           SetColorTable()                            */
     555             : /************************************************************************/
     556             : 
     557          37 : CPLErr GTiffRasterBand::SetColorTable(GDALColorTable *poCT)
     558             : 
     559             : {
     560          37 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     561             : 
     562             :     /* -------------------------------------------------------------------- */
     563             :     /*      Check if this is even a candidate for applying a PCT.           */
     564             :     /* -------------------------------------------------------------------- */
     565          37 :     if (eAccess == GA_Update)
     566             :     {
     567          35 :         if (nBand != 1)
     568             :         {
     569           1 :             ReportError(CE_Failure, CPLE_NotSupported,
     570             :                         "SetColorTable() can only be called on band 1.");
     571           1 :             return CE_Failure;
     572             :         }
     573             : 
     574          34 :         if (m_poGDS->m_nSamplesPerPixel != 1 &&
     575           3 :             m_poGDS->m_nSamplesPerPixel != 2)
     576             :         {
     577           1 :             ReportError(CE_Failure, CPLE_NotSupported,
     578             :                         "SetColorTable() not supported for multi-sample TIFF "
     579             :                         "files.");
     580           1 :             return CE_Failure;
     581             :         }
     582             : 
     583          33 :         if (eDataType != GDT_Byte && eDataType != GDT_UInt16)
     584             :         {
     585           1 :             ReportError(
     586             :                 CE_Failure, CPLE_NotSupported,
     587             :                 "SetColorTable() only supported for Byte or UInt16 bands "
     588             :                 "in TIFF format.");
     589           1 :             return CE_Failure;
     590             :         }
     591             : 
     592             :         // Clear any existing PAM color table
     593          32 :         if (GDALPamRasterBand::GetColorTable() != nullptr)
     594             :         {
     595           1 :             GDALPamRasterBand::SetColorTable(nullptr);
     596           1 :             GDALPamRasterBand::SetColorInterpretation(GCI_Undefined);
     597             :         }
     598             :     }
     599             : 
     600             :     /* -------------------------------------------------------------------- */
     601             :     /*      Is this really a request to clear the color table?              */
     602             :     /* -------------------------------------------------------------------- */
     603          34 :     if (poCT == nullptr || poCT->GetColorEntryCount() == 0)
     604             :     {
     605           1 :         if (eAccess == GA_Update)
     606             :         {
     607           1 :             TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_PHOTOMETRIC,
     608             :                          PHOTOMETRIC_MINISBLACK);
     609             : 
     610           1 :             TIFFUnsetField(m_poGDS->m_hTIFF, TIFFTAG_COLORMAP);
     611             :         }
     612             : 
     613           1 :         m_poGDS->m_poColorTable.reset();
     614             : 
     615           1 :         return CE_None;
     616             :     }
     617             : 
     618             :     /* -------------------------------------------------------------------- */
     619             :     /*      Write out the colortable, and update the configuration.         */
     620             :     /* -------------------------------------------------------------------- */
     621          33 :     CPLErr eErr = CE_None;
     622          33 :     if (eAccess == GA_Update)
     623             :     {
     624          31 :         int nColors = 65536;
     625             : 
     626          31 :         if (eDataType == GDT_Byte)
     627          30 :             nColors = 256;
     628             : 
     629             :         unsigned short *panTRed = static_cast<unsigned short *>(
     630          31 :             CPLMalloc(sizeof(unsigned short) * nColors));
     631             :         unsigned short *panTGreen = static_cast<unsigned short *>(
     632          31 :             CPLMalloc(sizeof(unsigned short) * nColors));
     633             :         unsigned short *panTBlue = static_cast<unsigned short *>(
     634          31 :             CPLMalloc(sizeof(unsigned short) * nColors));
     635             : 
     636          31 :         if (m_poGDS->m_nColorTableMultiplier == 0)
     637           0 :             m_poGDS->m_nColorTableMultiplier =
     638             :                 GTiffDataset::DEFAULT_COLOR_TABLE_MULTIPLIER_257;
     639             : 
     640       73247 :         for (int iColor = 0; iColor < nColors; ++iColor)
     641             :         {
     642       73216 :             if (iColor < poCT->GetColorEntryCount())
     643             :             {
     644             :                 GDALColorEntry sRGB;
     645        3396 :                 poCT->GetColorEntryAsRGB(iColor, &sRGB);
     646             : 
     647        6792 :                 panTRed[iColor] = GTiffDataset::ClampCTEntry(
     648        3396 :                     iColor, 1, sRGB.c1, m_poGDS->m_nColorTableMultiplier);
     649        6792 :                 panTGreen[iColor] = GTiffDataset::ClampCTEntry(
     650        3396 :                     iColor, 2, sRGB.c2, m_poGDS->m_nColorTableMultiplier);
     651        3396 :                 panTBlue[iColor] = GTiffDataset::ClampCTEntry(
     652        3396 :                     iColor, 3, sRGB.c3, m_poGDS->m_nColorTableMultiplier);
     653             :             }
     654             :             else
     655             :             {
     656       69820 :                 panTRed[iColor] = 0;
     657       69820 :                 panTGreen[iColor] = 0;
     658       69820 :                 panTBlue[iColor] = 0;
     659             :             }
     660             :         }
     661             : 
     662          31 :         TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_PHOTOMETRIC,
     663             :                      PHOTOMETRIC_PALETTE);
     664          31 :         TIFFSetField(m_poGDS->m_hTIFF, TIFFTAG_COLORMAP, panTRed, panTGreen,
     665             :                      panTBlue);
     666             : 
     667          31 :         CPLFree(panTRed);
     668          31 :         CPLFree(panTGreen);
     669          31 :         CPLFree(panTBlue);
     670             : 
     671             :         // libtiff 3.X needs setting this in all cases (creation or update)
     672             :         // whereas libtiff 4.X would just need it if there
     673             :         // was no color table before.
     674          31 :         m_poGDS->m_bNeedsRewrite = true;
     675             :     }
     676             :     else
     677             :     {
     678           2 :         eErr = GDALPamRasterBand::SetColorTable(poCT);
     679             :     }
     680             : 
     681          33 :     m_poGDS->m_poColorTable.reset(poCT->Clone());
     682          33 :     m_eBandInterp = GCI_PaletteIndex;
     683             : 
     684          33 :     return eErr;
     685             : }
     686             : 
     687             : /************************************************************************/
     688             : /*                           SetNoDataValue()                           */
     689             : /************************************************************************/
     690             : 
     691         412 : CPLErr GTiffRasterBand::SetNoDataValue(double dfNoData)
     692             : 
     693             : {
     694         823 :     const auto SetNoDataMembers = [this, dfNoData]()
     695             :     {
     696         411 :         m_bNoDataSet = true;
     697         411 :         m_dfNoDataValue = dfNoData;
     698             : 
     699         411 :         m_poGDS->m_bNoDataSet = true;
     700         411 :         m_poGDS->m_dfNoDataValue = dfNoData;
     701             : 
     702         411 :         if (eDataType == GDT_Int64 && GDALIsValueExactAs<int64_t>(dfNoData))
     703             :         {
     704           1 :             m_bNoDataSetAsInt64 = true;
     705           1 :             m_nNoDataValueInt64 = static_cast<int64_t>(dfNoData);
     706             : 
     707           1 :             m_poGDS->m_bNoDataSetAsInt64 = true;
     708           1 :             m_poGDS->m_nNoDataValueInt64 = static_cast<int64_t>(dfNoData);
     709             :         }
     710         410 :         else if (eDataType == GDT_UInt64 &&
     711           0 :                  GDALIsValueExactAs<uint64_t>(dfNoData))
     712             :         {
     713           0 :             m_bNoDataSetAsUInt64 = true;
     714           0 :             m_nNoDataValueUInt64 = static_cast<uint64_t>(dfNoData);
     715             : 
     716           0 :             m_poGDS->m_bNoDataSetAsUInt64 = true;
     717           0 :             m_poGDS->m_nNoDataValueUInt64 = static_cast<uint64_t>(dfNoData);
     718             :         }
     719         823 :     };
     720             : 
     721         412 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     722             : 
     723         550 :     if (m_poGDS->m_bNoDataSet &&
     724         145 :         (m_poGDS->m_dfNoDataValue == dfNoData ||
     725           9 :          (std::isnan(m_poGDS->m_dfNoDataValue) && std::isnan(dfNoData))))
     726             :     {
     727         133 :         ResetNoDataValues(false);
     728             : 
     729         133 :         SetNoDataMembers();
     730             : 
     731         133 :         return CE_None;
     732             :     }
     733             : 
     734         279 :     if (m_poGDS->nBands > 1 && m_poGDS->m_eProfile == GTiffProfile::GDALGEOTIFF)
     735             :     {
     736          82 :         int bOtherBandHasNoData = FALSE;
     737          82 :         const int nOtherBand = nBand > 1 ? 1 : 2;
     738          82 :         double dfOtherNoData = m_poGDS->GetRasterBand(nOtherBand)
     739          82 :                                    ->GetNoDataValue(&bOtherBandHasNoData);
     740          82 :         if (bOtherBandHasNoData && dfOtherNoData != dfNoData)
     741             :         {
     742           2 :             ReportError(
     743             :                 CE_Warning, CPLE_AppDefined,
     744             :                 "Setting nodata to %.17g on band %d, but band %d has nodata "
     745             :                 "at %.17g. The TIFFTAG_GDAL_NODATA only support one value "
     746             :                 "per dataset. This value of %.17g will be used for all bands "
     747             :                 "on re-opening",
     748             :                 dfNoData, nBand, nOtherBand, dfOtherNoData, dfNoData);
     749             :         }
     750             :     }
     751             : 
     752         279 :     if (m_poGDS->m_bStreamingOut && m_poGDS->m_bCrystalized)
     753             :     {
     754           1 :         ReportError(
     755             :             CE_Failure, CPLE_NotSupported,
     756             :             "Cannot modify nodata at that point in a streamed output file");
     757           1 :         return CE_Failure;
     758             :     }
     759             : 
     760         278 :     CPLErr eErr = CE_None;
     761         278 :     if (eAccess == GA_Update)
     762             :     {
     763         273 :         m_poGDS->m_bNoDataChanged = true;
     764         273 :         int bSuccess = FALSE;
     765         273 :         CPL_IGNORE_RET_VAL(GDALPamRasterBand::GetNoDataValue(&bSuccess));
     766         273 :         if (bSuccess)
     767             :         {
     768             :             // Cancel any existing nodata from PAM file.
     769           1 :             eErr = GDALPamRasterBand::DeleteNoDataValue();
     770             :         }
     771             :     }
     772             :     else
     773             :     {
     774           5 :         CPLDebug("GTIFF", "SetNoDataValue() goes to PAM instead of TIFF tags");
     775           5 :         eErr = GDALPamRasterBand::SetNoDataValue(dfNoData);
     776             :     }
     777             : 
     778         278 :     if (eErr == CE_None)
     779             :     {
     780         278 :         ResetNoDataValues(true);
     781             : 
     782         278 :         SetNoDataMembers();
     783             :     }
     784             : 
     785         278 :     return eErr;
     786             : }
     787             : 
     788             : /************************************************************************/
     789             : /*                       SetNoDataValueAsInt64()                        */
     790             : /************************************************************************/
     791             : 
     792           1 : CPLErr GTiffRasterBand::SetNoDataValueAsInt64(int64_t nNoData)
     793             : 
     794             : {
     795           1 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     796             : 
     797           1 :     if (m_poGDS->m_bNoDataSetAsInt64 && m_poGDS->m_nNoDataValueInt64 == nNoData)
     798             :     {
     799           0 :         ResetNoDataValues(false);
     800             : 
     801           0 :         m_bNoDataSetAsInt64 = true;
     802           0 :         m_nNoDataValueInt64 = nNoData;
     803             : 
     804           0 :         return CE_None;
     805             :     }
     806             : 
     807           1 :     if (m_poGDS->nBands > 1 && m_poGDS->m_eProfile == GTiffProfile::GDALGEOTIFF)
     808             :     {
     809           0 :         int bOtherBandHasNoData = FALSE;
     810           0 :         const int nOtherBand = nBand > 1 ? 1 : 2;
     811             :         const auto nOtherNoData =
     812           0 :             m_poGDS->GetRasterBand(nOtherBand)
     813           0 :                 ->GetNoDataValueAsInt64(&bOtherBandHasNoData);
     814           0 :         if (bOtherBandHasNoData && nOtherNoData != nNoData)
     815             :         {
     816           0 :             ReportError(CE_Warning, CPLE_AppDefined,
     817             :                         "Setting nodata to " CPL_FRMT_GIB
     818             :                         " on band %d, but band %d has nodata "
     819             :                         "at " CPL_FRMT_GIB
     820             :                         ". The TIFFTAG_GDAL_NODATA only support one value "
     821             :                         "per dataset. This value of " CPL_FRMT_GIB
     822             :                         " will be used for all bands "
     823             :                         "on re-opening",
     824             :                         static_cast<GIntBig>(nNoData), nBand, nOtherBand,
     825             :                         static_cast<GIntBig>(nOtherNoData),
     826             :                         static_cast<GIntBig>(nNoData));
     827             :         }
     828             :     }
     829             : 
     830           1 :     if (m_poGDS->m_bStreamingOut && m_poGDS->m_bCrystalized)
     831             :     {
     832           0 :         ReportError(
     833             :             CE_Failure, CPLE_NotSupported,
     834             :             "Cannot modify nodata at that point in a streamed output file");
     835           0 :         return CE_Failure;
     836             :     }
     837             : 
     838           1 :     CPLErr eErr = CE_None;
     839           1 :     if (eAccess == GA_Update)
     840             :     {
     841           1 :         m_poGDS->m_bNoDataChanged = true;
     842           1 :         int bSuccess = FALSE;
     843           1 :         CPL_IGNORE_RET_VAL(GDALPamRasterBand::GetNoDataValueAsInt64(&bSuccess));
     844           1 :         if (bSuccess)
     845             :         {
     846             :             // Cancel any existing nodata from PAM file.
     847           0 :             eErr = GDALPamRasterBand::DeleteNoDataValue();
     848             :         }
     849             :     }
     850             :     else
     851             :     {
     852           0 :         CPLDebug("GTIFF", "SetNoDataValue() goes to PAM instead of TIFF tags");
     853           0 :         eErr = GDALPamRasterBand::SetNoDataValueAsInt64(nNoData);
     854             :     }
     855             : 
     856           1 :     if (eErr == CE_None)
     857             :     {
     858           1 :         ResetNoDataValues(true);
     859             : 
     860           1 :         m_poGDS->m_bNoDataSetAsInt64 = true;
     861           1 :         m_poGDS->m_nNoDataValueInt64 = nNoData;
     862             :     }
     863             : 
     864           1 :     return eErr;
     865             : }
     866             : 
     867             : /************************************************************************/
     868             : /*                      SetNoDataValueAsUInt64()                        */
     869             : /************************************************************************/
     870             : 
     871           1 : CPLErr GTiffRasterBand::SetNoDataValueAsUInt64(uint64_t nNoData)
     872             : 
     873             : {
     874           1 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     875             : 
     876           1 :     if (m_poGDS->m_bNoDataSetAsUInt64 &&
     877           0 :         m_poGDS->m_nNoDataValueUInt64 == nNoData)
     878             :     {
     879           0 :         ResetNoDataValues(false);
     880             : 
     881           0 :         m_bNoDataSetAsUInt64 = true;
     882           0 :         m_nNoDataValueUInt64 = nNoData;
     883             : 
     884           0 :         return CE_None;
     885             :     }
     886             : 
     887           1 :     if (m_poGDS->nBands > 1 && m_poGDS->m_eProfile == GTiffProfile::GDALGEOTIFF)
     888             :     {
     889           0 :         int bOtherBandHasNoData = FALSE;
     890           0 :         const int nOtherBand = nBand > 1 ? 1 : 2;
     891             :         const auto nOtherNoData =
     892           0 :             m_poGDS->GetRasterBand(nOtherBand)
     893           0 :                 ->GetNoDataValueAsUInt64(&bOtherBandHasNoData);
     894           0 :         if (bOtherBandHasNoData && nOtherNoData != nNoData)
     895             :         {
     896           0 :             ReportError(CE_Warning, CPLE_AppDefined,
     897             :                         "Setting nodata to " CPL_FRMT_GUIB
     898             :                         " on band %d, but band %d has nodata "
     899             :                         "at " CPL_FRMT_GUIB
     900             :                         ". The TIFFTAG_GDAL_NODATA only support one value "
     901             :                         "per dataset. This value of " CPL_FRMT_GUIB
     902             :                         " will be used for all bands "
     903             :                         "on re-opening",
     904             :                         static_cast<GUIntBig>(nNoData), nBand, nOtherBand,
     905             :                         static_cast<GUIntBig>(nOtherNoData),
     906             :                         static_cast<GUIntBig>(nNoData));
     907             :         }
     908             :     }
     909             : 
     910           1 :     if (m_poGDS->m_bStreamingOut && m_poGDS->m_bCrystalized)
     911             :     {
     912           0 :         ReportError(
     913             :             CE_Failure, CPLE_NotSupported,
     914             :             "Cannot modify nodata at that point in a streamed output file");
     915           0 :         return CE_Failure;
     916             :     }
     917             : 
     918           1 :     CPLErr eErr = CE_None;
     919           1 :     if (eAccess == GA_Update)
     920             :     {
     921           1 :         m_poGDS->m_bNoDataChanged = true;
     922           1 :         int bSuccess = FALSE;
     923           1 :         CPL_IGNORE_RET_VAL(
     924           1 :             GDALPamRasterBand::GetNoDataValueAsUInt64(&bSuccess));
     925           1 :         if (bSuccess)
     926             :         {
     927             :             // Cancel any existing nodata from PAM file.
     928           0 :             eErr = GDALPamRasterBand::DeleteNoDataValue();
     929             :         }
     930             :     }
     931             :     else
     932             :     {
     933           0 :         CPLDebug("GTIFF", "SetNoDataValue() goes to PAM instead of TIFF tags");
     934           0 :         eErr = GDALPamRasterBand::SetNoDataValueAsUInt64(nNoData);
     935             :     }
     936             : 
     937           1 :     if (eErr == CE_None)
     938             :     {
     939           1 :         ResetNoDataValues(true);
     940             : 
     941           1 :         m_poGDS->m_bNoDataSetAsUInt64 = true;
     942           1 :         m_poGDS->m_nNoDataValueUInt64 = nNoData;
     943             : 
     944           1 :         m_bNoDataSetAsUInt64 = true;
     945           1 :         m_nNoDataValueUInt64 = nNoData;
     946             :     }
     947             : 
     948           1 :     return eErr;
     949             : }
     950             : 
     951             : /************************************************************************/
     952             : /*                        ResetNoDataValues()                           */
     953             : /************************************************************************/
     954             : 
     955         415 : void GTiffRasterBand::ResetNoDataValues(bool bResetDatasetToo)
     956             : {
     957         415 :     if (bResetDatasetToo)
     958             :     {
     959         282 :         m_poGDS->m_bNoDataSet = false;
     960         282 :         m_poGDS->m_dfNoDataValue = DEFAULT_NODATA_VALUE;
     961             :     }
     962             : 
     963         415 :     m_bNoDataSet = false;
     964         415 :     m_dfNoDataValue = DEFAULT_NODATA_VALUE;
     965             : 
     966         415 :     if (bResetDatasetToo)
     967             :     {
     968         282 :         m_poGDS->m_bNoDataSetAsInt64 = false;
     969         282 :         m_poGDS->m_nNoDataValueInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
     970             :     }
     971             : 
     972         415 :     m_bNoDataSetAsInt64 = false;
     973         415 :     m_nNoDataValueInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
     974             : 
     975         415 :     if (bResetDatasetToo)
     976             :     {
     977         282 :         m_poGDS->m_bNoDataSetAsUInt64 = false;
     978         282 :         m_poGDS->m_nNoDataValueUInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
     979             :     }
     980             : 
     981         415 :     m_bNoDataSetAsUInt64 = false;
     982         415 :     m_nNoDataValueUInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
     983         415 : }
     984             : 
     985             : /************************************************************************/
     986             : /*                        DeleteNoDataValue()                           */
     987             : /************************************************************************/
     988             : 
     989           2 : CPLErr GTiffRasterBand::DeleteNoDataValue()
     990             : 
     991             : {
     992           2 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     993             : 
     994           2 :     if (m_poGDS->m_bStreamingOut && m_poGDS->m_bCrystalized)
     995             :     {
     996           0 :         ReportError(
     997             :             CE_Failure, CPLE_NotSupported,
     998             :             "Cannot modify nodata at that point in a streamed output file");
     999           0 :         return CE_Failure;
    1000             :     }
    1001             : 
    1002           2 :     if (eAccess == GA_Update)
    1003             :     {
    1004           1 :         if (m_poGDS->m_bNoDataSet)
    1005           1 :             m_poGDS->m_bNoDataChanged = true;
    1006             :     }
    1007             :     else
    1008             :     {
    1009           1 :         CPLDebug("GTIFF",
    1010             :                  "DeleteNoDataValue() goes to PAM instead of TIFF tags");
    1011             :     }
    1012             : 
    1013           2 :     CPLErr eErr = GDALPamRasterBand::DeleteNoDataValue();
    1014           2 :     if (eErr == CE_None)
    1015             :     {
    1016           2 :         ResetNoDataValues(true);
    1017             :     }
    1018             : 
    1019           2 :     return eErr;
    1020             : }
    1021             : 
    1022             : /************************************************************************/
    1023             : /*                             NullBlock()                              */
    1024             : /*                                                                      */
    1025             : /*      Set the block data to the null value if it is set, or zero      */
    1026             : /*      if there is no null data value.                                 */
    1027             : /************************************************************************/
    1028             : 
    1029       53958 : void GTiffRasterBand::NullBlock(void *pData)
    1030             : 
    1031             : {
    1032       53958 :     const GPtrDiff_t nWords =
    1033       53958 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize;
    1034       53958 :     const int nChunkSize = std::max(1, GDALGetDataTypeSizeBytes(eDataType));
    1035             : 
    1036       53958 :     int l_bNoDataSet = FALSE;
    1037       53958 :     if (eDataType == GDT_Int64)
    1038             :     {
    1039           2 :         const auto nVal = GetNoDataValueAsInt64(&l_bNoDataSet);
    1040           2 :         if (!l_bNoDataSet)
    1041             :         {
    1042           1 :             memset(pData, 0, nWords * nChunkSize);
    1043             :         }
    1044             :         else
    1045             :         {
    1046           1 :             GDALCopyWords64(&nVal, GDT_Int64, 0, pData, eDataType, nChunkSize,
    1047             :                             nWords);
    1048             :         }
    1049             :     }
    1050       53956 :     else if (eDataType == GDT_UInt64)
    1051             :     {
    1052           2 :         const auto nVal = GetNoDataValueAsUInt64(&l_bNoDataSet);
    1053           2 :         if (!l_bNoDataSet)
    1054             :         {
    1055           2 :             memset(pData, 0, nWords * nChunkSize);
    1056             :         }
    1057             :         else
    1058             :         {
    1059           0 :             GDALCopyWords64(&nVal, GDT_UInt64, 0, pData, eDataType, nChunkSize,
    1060             :                             nWords);
    1061             :         }
    1062             :     }
    1063             :     else
    1064             :     {
    1065       53954 :         double dfNoData = GetNoDataValue(&l_bNoDataSet);
    1066       53954 :         if (!l_bNoDataSet)
    1067             :         {
    1068             : #ifdef ESRI_BUILD
    1069             :             if (m_poGDS->m_nBitsPerSample >= 2)
    1070             :                 memset(pData, 0, nWords * nChunkSize);
    1071             :             else
    1072             :                 memset(pData, 1, nWords * nChunkSize);
    1073             : #else
    1074       51306 :             memset(pData, 0, nWords * nChunkSize);
    1075             : #endif
    1076             :         }
    1077             :         else
    1078             :         {
    1079             :             // Will convert nodata value to the right type and copy efficiently.
    1080        2648 :             GDALCopyWords64(&dfNoData, GDT_Float64, 0, pData, eDataType,
    1081             :                             nChunkSize, nWords);
    1082             :         }
    1083             :     }
    1084       53958 : }

Generated by: LCOV version 1.14