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

Generated by: LCOV version 1.14