LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband_read.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 640 728 87.9 %
Date: 2025-10-14 12:36:07 Functions: 28 29 96.6 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GeoTIFF Driver
       4             :  * Purpose:  Read/get 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             : #include "gtiffjpegoverviewds.h"
      17             : 
      18             : #include <algorithm>
      19             : #include <cassert>
      20             : #include <limits>
      21             : #include <map>
      22             : #include <set>
      23             : #include <utility>
      24             : 
      25             : #include "cpl_vsi_virtual.h"
      26             : #include "fetchbufferdirectio.h"
      27             : #include "gdal_priv.h"
      28             : #include "gtiff.h"
      29             : #include "tifvsi.h"
      30             : 
      31             : /************************************************************************/
      32             : /*                           GetDefaultRAT()                            */
      33             : /************************************************************************/
      34             : 
      35        3888 : GDALRasterAttributeTable *GTiffRasterBand::GetDefaultRAT()
      36             : 
      37             : {
      38        3888 :     if (m_poRAT || m_poGDS->m_poBaseDS != nullptr)
      39          48 :         return m_poRAT.get();
      40             : 
      41        3840 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
      42        3840 :     auto poRAT = GDALPamRasterBand::GetDefaultRAT();
      43        3840 :     if (poRAT)
      44           7 :         return poRAT;
      45             : 
      46        3833 :     if (!GDALCanFileAcceptSidecarFile(m_poGDS->m_osFilename.c_str()))
      47           0 :         return nullptr;
      48        7666 :     const std::string osVATDBF = m_poGDS->m_osFilename + ".vat.dbf";
      49        3833 :     CSLConstList papszSiblingFiles = m_poGDS->GetSiblingFiles();
      50        7632 :     if (papszSiblingFiles &&
      51             :         // cppcheck-suppress knownConditionTrueFalse
      52        3799 :         GDALCanReliablyUseSiblingFileList(osVATDBF.c_str()))
      53             :     {
      54             :         int iSibling =
      55        3799 :             CSLFindString(papszSiblingFiles, CPLGetFilename(osVATDBF.c_str()));
      56        3799 :         if (iSibling >= 0)
      57             :         {
      58           2 :             CPLString osFilename = m_poGDS->m_osFilename;
      59           2 :             osFilename.resize(
      60           2 :                 m_poGDS->m_osFilename.size() -
      61           2 :                 strlen(CPLGetFilename(m_poGDS->m_osFilename.c_str())));
      62           2 :             osFilename += papszSiblingFiles[iSibling];
      63           2 :             m_poRAT = GDALLoadVATDBF(osFilename.c_str());
      64             :         }
      65        3799 :         return m_poRAT.get();
      66             :     }
      67             :     VSIStatBufL sStatBuf;
      68          34 :     if (VSIStatL(osVATDBF.c_str(), &sStatBuf) == 0)
      69           1 :         m_poRAT = GDALLoadVATDBF(osVATDBF.c_str());
      70          34 :     return m_poRAT.get();
      71             : }
      72             : 
      73             : /************************************************************************/
      74             : /*                           GetHistogram()                             */
      75             : /************************************************************************/
      76             : 
      77          21 : CPLErr GTiffRasterBand::GetHistogram(double dfMin, double dfMax, int nBuckets,
      78             :                                      GUIntBig *panHistogram,
      79             :                                      int bIncludeOutOfRange, int bApproxOK,
      80             :                                      GDALProgressFunc pfnProgress,
      81             :                                      void *pProgressData)
      82             : {
      83          21 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
      84          21 :     return GDALPamRasterBand::GetHistogram(dfMin, dfMax, nBuckets, panHistogram,
      85             :                                            bIncludeOutOfRange, bApproxOK,
      86          21 :                                            pfnProgress, pProgressData);
      87             : }
      88             : 
      89             : /************************************************************************/
      90             : /*                       GetDefaultHistogram()                          */
      91             : /************************************************************************/
      92             : 
      93          22 : CPLErr GTiffRasterBand::GetDefaultHistogram(
      94             :     double *pdfMin, double *pdfMax, int *pnBuckets, GUIntBig **ppanHistogram,
      95             :     int bForce, GDALProgressFunc pfnProgress, void *pProgressData)
      96             : {
      97          22 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
      98          22 :     return GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
      99             :                                                   ppanHistogram, bForce,
     100          22 :                                                   pfnProgress, pProgressData);
     101             : }
     102             : 
     103             : /************************************************************************/
     104             : /*                           DirectIO()                                 */
     105             : /************************************************************************/
     106             : 
     107             : // Reads directly bytes from the file using ReadMultiRange(), and by-pass
     108             : // block reading. Restricted to simple TIFF configurations
     109             : // (uncompressed data, standard data types). Particularly useful to extract
     110             : // sub-windows of data on a large /vsicurl dataset).
     111             : // Returns -1 if DirectIO() can't be supported on that file.
     112             : 
     113        2522 : int GTiffRasterBand::DirectIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     114             :                               int nXSize, int nYSize, void *pData,
     115             :                               int nBufXSize, int nBufYSize,
     116             :                               GDALDataType eBufType, GSpacing nPixelSpace,
     117             :                               GSpacing nLineSpace,
     118             :                               GDALRasterIOExtraArg *psExtraArg)
     119             : {
     120        2522 :     const int nDTSizeBits = GDALGetDataTypeSizeBits(eDataType);
     121        5044 :     if (!(eRWFlag == GF_Read && m_poGDS->m_nCompression == COMPRESSION_NONE &&
     122        2522 :           (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK ||
     123         795 :            m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
     124           0 :            m_poGDS->m_nPhotometric == PHOTOMETRIC_PALETTE) &&
     125        2522 :           IsBaseGTiffClass()))
     126             :     {
     127           0 :         return -1;
     128             :     }
     129        2522 :     m_poGDS->Crystalize();
     130             : 
     131             :     // Only know how to deal with nearest neighbour in this optimized routine.
     132        2522 :     if ((nXSize != nBufXSize || nYSize != nBufYSize) && psExtraArg != nullptr &&
     133         607 :         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour)
     134             :     {
     135          66 :         return -1;
     136             :     }
     137             : 
     138             : #if DEBUG_VERBOSE
     139             :     CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)", nXOff, nYOff, nXSize,
     140             :              nYSize, nBufXSize, nBufYSize);
     141             : #endif
     142             : 
     143             :     // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
     144        2456 :     if (m_poGDS->GetAccess() == GA_Update)
     145             :     {
     146           0 :         m_poGDS->FlushCache(false);
     147           0 :         VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
     148             :     }
     149             : 
     150        2456 :     if (TIFFIsTiled(m_poGDS->m_hTIFF))
     151             :     {
     152         716 :         const int nDTSize = nDTSizeBits / 8;
     153         716 :         const size_t nTempBufferForCommonDirectIOSize = static_cast<size_t>(
     154        1432 :             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize * nDTSize *
     155         716 :             (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG ? m_poGDS->nBands
     156             :                                                              : 1));
     157         716 :         if (m_poGDS->m_pTempBufferForCommonDirectIO == nullptr)
     158             :         {
     159          28 :             m_poGDS->m_pTempBufferForCommonDirectIO = static_cast<GByte *>(
     160          14 :                 VSI_MALLOC_VERBOSE(nTempBufferForCommonDirectIOSize));
     161          14 :             if (m_poGDS->m_pTempBufferForCommonDirectIO == nullptr)
     162           0 :                 return CE_Failure;
     163             :         }
     164             : 
     165         716 :         VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
     166             :         FetchBufferDirectIO oFetcher(fp,
     167         716 :                                      m_poGDS->m_pTempBufferForCommonDirectIO,
     168         716 :                                      nTempBufferForCommonDirectIOSize);
     169             : 
     170        1432 :         return m_poGDS->CommonDirectIOClassic(
     171             :             oFetcher, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     172         716 :             eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0);
     173             :     }
     174             : 
     175             :     // Get strip offsets.
     176        1740 :     toff_t *panTIFFOffsets = nullptr;
     177        1740 :     if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPOFFSETS,
     178        3480 :                       &panTIFFOffsets) ||
     179        1740 :         panTIFFOffsets == nullptr)
     180             :     {
     181           0 :         return CE_Failure;
     182             :     }
     183             : 
     184             :     // Sub-sampling or over-sampling can only be done at last stage.
     185        1740 :     int nReqXSize = nXSize;
     186             :     // Can do sub-sampling at the extraction stage.
     187        1740 :     const int nReqYSize = std::min(nBufYSize, nYSize);
     188             :     // TODO(schwehr): Make ppData be GByte**.
     189             :     void **ppData =
     190        1740 :         static_cast<void **>(VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void *)));
     191             :     vsi_l_offset *panOffsets = static_cast<vsi_l_offset *>(
     192        1740 :         VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset)));
     193             :     size_t *panSizes =
     194        1740 :         static_cast<size_t *>(VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t)));
     195        1740 :     const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     196        1740 :     void *pTmpBuffer = nullptr;
     197        1740 :     int eErr = CE_None;
     198        1740 :     int nContigBands =
     199        1740 :         m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG ? m_poGDS->nBands : 1;
     200        1740 :     int nSrcPixelSize = nDTSize * nContigBands;
     201             : 
     202        1740 :     if (ppData == nullptr || panOffsets == nullptr || panSizes == nullptr)
     203           0 :         eErr = CE_Failure;
     204        1427 :     else if (nXSize != nBufXSize || nYSize != nBufYSize ||
     205        1427 :              eBufType != eDataType ||
     206        3167 :              nPixelSpace != GDALGetDataTypeSizeBytes(eBufType) ||
     207             :              nContigBands > 1)
     208             :     {
     209             :         // We need a temporary buffer for over-sampling/sub-sampling
     210             :         // and/or data type conversion.
     211        1534 :         pTmpBuffer = VSI_MALLOC3_VERBOSE(nReqXSize, nReqYSize, nSrcPixelSize);
     212        1534 :         if (pTmpBuffer == nullptr)
     213           0 :             eErr = CE_Failure;
     214             :     }
     215             : 
     216             :     // Prepare data extraction.
     217        1740 :     const double dfSrcYInc = nYSize / static_cast<double>(nBufYSize);
     218             : 
     219       58549 :     for (int iLine = 0; eErr == CE_None && iLine < nReqYSize; ++iLine)
     220             :     {
     221       56809 :         if (pTmpBuffer == nullptr)
     222       17766 :             ppData[iLine] = static_cast<GByte *>(pData) + iLine * nLineSpace;
     223             :         else
     224       39043 :             ppData[iLine] =
     225       39043 :                 static_cast<GByte *>(pTmpBuffer) +
     226       39043 :                 static_cast<size_t>(iLine) * nReqXSize * nSrcPixelSize;
     227       56809 :         int nSrcLine = 0;
     228       56809 :         if (nBufYSize < nYSize)  // Sub-sampling in y.
     229        3720 :             nSrcLine = nYOff + static_cast<int>((iLine + 0.5) * dfSrcYInc);
     230             :         else
     231       53089 :             nSrcLine = nYOff + iLine;
     232             : 
     233       56809 :         const int nBlockXOff = 0;
     234       56809 :         const int nBlockYOff = nSrcLine / nBlockYSize;
     235       56809 :         const int nYOffsetInBlock = nSrcLine % nBlockYSize;
     236       56809 :         const int nBlockId = ComputeBlockId(nBlockXOff, nBlockYOff);
     237             : 
     238       56809 :         panOffsets[iLine] = panTIFFOffsets[nBlockId];
     239       56809 :         if (panOffsets[iLine] == 0)  // We don't support sparse files.
     240        1047 :             eErr = -1;
     241             : 
     242       56809 :         panOffsets[iLine] +=
     243       56809 :             (nXOff + static_cast<vsi_l_offset>(nYOffsetInBlock) * nBlockXSize) *
     244       56809 :             nSrcPixelSize;
     245       56809 :         panSizes[iLine] = static_cast<size_t>(nReqXSize) * nSrcPixelSize;
     246             :     }
     247             : 
     248             :     // Extract data from the file.
     249        1740 :     if (eErr == CE_None)
     250             :     {
     251         693 :         VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
     252             :         const int nRet =
     253         693 :             VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
     254         693 :         if (nRet != 0)
     255          16 :             eErr = CE_Failure;
     256             :     }
     257             : 
     258             :     // Byte-swap if necessary.
     259        1740 :     if (eErr == CE_None && TIFFIsByteSwapped(m_poGDS->m_hTIFF))
     260             :     {
     261       20878 :         for (int iLine = 0; iLine < nReqYSize; ++iLine)
     262             :         {
     263       20620 :             if (GDALDataTypeIsComplex(eDataType))
     264       10315 :                 GDALSwapWords(ppData[iLine], nDTSize / 2,
     265       10315 :                               2 * nReqXSize * nContigBands, nDTSize / 2);
     266             :             else
     267       10305 :                 GDALSwapWords(ppData[iLine], nDTSize, nReqXSize * nContigBands,
     268             :                               nDTSize);
     269             :         }
     270             :     }
     271             : 
     272             :     // Over-sampling/sub-sampling and/or data type conversion.
     273        1740 :     const double dfSrcXInc = nXSize / static_cast<double>(nBufXSize);
     274        1740 :     if (eErr == CE_None && pTmpBuffer != nullptr)
     275             :     {
     276         508 :         const bool bOneByteCopy =
     277         904 :             (eDataType == eBufType &&
     278         396 :              (eDataType == GDT_Byte || eDataType == GDT_Int8));
     279      150707 :         for (int iY = 0; iY < nBufYSize; ++iY)
     280             :         {
     281      300398 :             const int iSrcY = nBufYSize <= nYSize
     282      150199 :                                   ? iY
     283      120528 :                                   : static_cast<int>((iY + 0.5) * dfSrcYInc);
     284             : 
     285      300398 :             GByte *pabySrcData = static_cast<GByte *>(ppData[iSrcY]) +
     286      150199 :                                  (nContigBands > 1 ? (nBand - 1) : 0) * nDTSize;
     287      150199 :             GByte *pabyDstData = static_cast<GByte *>(pData) + iY * nLineSpace;
     288      150199 :             if (nBufXSize == nXSize)
     289             :             {
     290       25952 :                 GDALCopyWords(pabySrcData, eDataType, nSrcPixelSize,
     291             :                               pabyDstData, eBufType,
     292             :                               static_cast<int>(nPixelSpace), nBufXSize);
     293             :             }
     294             :             else
     295             :             {
     296      124247 :                 if (bOneByteCopy)
     297             :                 {
     298       25435 :                     double dfSrcX = 0.5 * dfSrcXInc;
     299     2147110 :                     for (int iX = 0; iX < nBufXSize; ++iX, dfSrcX += dfSrcXInc)
     300             :                     {
     301     2121670 :                         const int iSrcX = static_cast<int>(dfSrcX);
     302     2121670 :                         pabyDstData[iX * nPixelSpace] =
     303     2121670 :                             pabySrcData[iSrcX * nSrcPixelSize];
     304             :                     }
     305             :                 }
     306             :                 else
     307             :                 {
     308       98812 :                     double dfSrcX = 0.5 * dfSrcXInc;
     309     7730840 :                     for (int iX = 0; iX < nBufXSize; ++iX, dfSrcX += dfSrcXInc)
     310             :                     {
     311     7632030 :                         const int iSrcX = static_cast<int>(dfSrcX);
     312     7632030 :                         GDALCopyWords(
     313     7632030 :                             pabySrcData + iSrcX * nSrcPixelSize, eDataType, 0,
     314     7632030 :                             pabyDstData + iX * nPixelSpace, eBufType, 0, 1);
     315             :                     }
     316             :                 }
     317             :             }
     318             :         }
     319             :     }
     320             : 
     321             :     // Cleanup.
     322        1740 :     CPLFree(pTmpBuffer);
     323        1740 :     CPLFree(ppData);
     324        1740 :     CPLFree(panOffsets);
     325        1740 :     CPLFree(panSizes);
     326             : 
     327        1740 :     return eErr;
     328             : }
     329             : 
     330             : /************************************************************************/
     331             : /*                           GetVirtualMemAuto()                        */
     332             : /************************************************************************/
     333             : 
     334          17 : CPLVirtualMem *GTiffRasterBand::GetVirtualMemAuto(GDALRWFlag eRWFlag,
     335             :                                                   int *pnPixelSpace,
     336             :                                                   GIntBig *pnLineSpace,
     337             :                                                   char **papszOptions)
     338             : {
     339          17 :     const char *pszImpl = CSLFetchNameValueDef(
     340             :         papszOptions, "USE_DEFAULT_IMPLEMENTATION", "AUTO");
     341          17 :     if (EQUAL(pszImpl, "YES") || EQUAL(pszImpl, "ON") || EQUAL(pszImpl, "1") ||
     342          16 :         EQUAL(pszImpl, "TRUE"))
     343             :     {
     344           1 :         return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
     345           1 :                                                  pnLineSpace, papszOptions);
     346             :     }
     347             : 
     348          16 :     CPLVirtualMem *psRet = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace,
     349             :                                                      pnLineSpace, papszOptions);
     350          16 :     if (psRet != nullptr)
     351             :     {
     352          14 :         CPLDebug("GTiff", "GetVirtualMemAuto(): Using memory file mapping");
     353          14 :         return psRet;
     354             :     }
     355             : 
     356           2 :     if (EQUAL(pszImpl, "NO") || EQUAL(pszImpl, "OFF") || EQUAL(pszImpl, "0") ||
     357           1 :         EQUAL(pszImpl, "FALSE"))
     358             :     {
     359           1 :         return nullptr;
     360             :     }
     361             : 
     362           1 :     CPLDebug("GTiff", "GetVirtualMemAuto(): Defaulting to base implementation");
     363           1 :     return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace, pnLineSpace,
     364           1 :                                              papszOptions);
     365             : }
     366             : 
     367             : /************************************************************************/
     368             : /*                     DropReferenceVirtualMem()                        */
     369             : /************************************************************************/
     370             : 
     371           8 : void GTiffRasterBand::DropReferenceVirtualMem(void *pUserData)
     372             : {
     373             :     // This function may also be called when the dataset and rasterband
     374             :     // objects have been destroyed.
     375             :     // If they are still alive, it updates the reference counter of the
     376             :     // base mapping to invalidate the pointer to it if needed.
     377             : 
     378           8 :     GTiffRasterBand **ppoSelf = static_cast<GTiffRasterBand **>(pUserData);
     379           8 :     GTiffRasterBand *poSelf = *ppoSelf;
     380             : 
     381           8 :     if (poSelf != nullptr)
     382             :     {
     383           8 :         if (--(poSelf->m_poGDS->m_nRefBaseMapping) == 0)
     384             :         {
     385           4 :             poSelf->m_poGDS->m_pBaseMapping = nullptr;
     386             :         }
     387           8 :         poSelf->m_aSetPSelf.erase(ppoSelf);
     388             :     }
     389           8 :     CPLFree(pUserData);
     390           8 : }
     391             : 
     392             : /************************************************************************/
     393             : /*                     GetVirtualMemAutoInternal()                      */
     394             : /************************************************************************/
     395             : 
     396          20 : CPLVirtualMem *GTiffRasterBand::GetVirtualMemAutoInternal(GDALRWFlag eRWFlag,
     397             :                                                           int *pnPixelSpace,
     398             :                                                           GIntBig *pnLineSpace,
     399             :                                                           char **papszOptions)
     400             : {
     401          20 :     int nLineSize = nBlockXSize * GDALGetDataTypeSizeBytes(eDataType);
     402          20 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     403          14 :         nLineSize *= m_poGDS->nBands;
     404             : 
     405          20 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     406             :     {
     407             :         // In case of a pixel interleaved file, we save virtual memory space
     408             :         // by reusing a base mapping that embraces the whole imagery.
     409          14 :         if (m_poGDS->m_pBaseMapping != nullptr)
     410             :         {
     411             :             // Offset between the base mapping and the requested mapping.
     412           8 :             vsi_l_offset nOffset = static_cast<vsi_l_offset>(nBand - 1) *
     413           8 :                                    GDALGetDataTypeSizeBytes(eDataType);
     414             : 
     415             :             GTiffRasterBand **ppoSelf = static_cast<GTiffRasterBand **>(
     416           8 :                 CPLCalloc(1, sizeof(GTiffRasterBand *)));
     417           8 :             *ppoSelf = this;
     418             : 
     419          24 :             CPLVirtualMem *pVMem = CPLVirtualMemDerivedNew(
     420           8 :                 m_poGDS->m_pBaseMapping, nOffset,
     421           8 :                 CPLVirtualMemGetSize(m_poGDS->m_pBaseMapping) - nOffset,
     422             :                 GTiffRasterBand::DropReferenceVirtualMem, ppoSelf);
     423           8 :             if (pVMem == nullptr)
     424             :             {
     425           0 :                 CPLFree(ppoSelf);
     426           0 :                 return nullptr;
     427             :             }
     428             : 
     429             :             // Mechanism used so that the memory mapping object can be
     430             :             // destroyed after the raster band.
     431           8 :             m_aSetPSelf.insert(ppoSelf);
     432           8 :             ++m_poGDS->m_nRefBaseMapping;
     433           8 :             *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
     434           8 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     435           8 :                 *pnPixelSpace *= m_poGDS->nBands;
     436           8 :             *pnLineSpace = nLineSize;
     437           8 :             return pVMem;
     438             :         }
     439             :     }
     440             : 
     441          12 :     VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
     442             : 
     443          12 :     vsi_l_offset nLength = static_cast<vsi_l_offset>(nRasterYSize) * nLineSize;
     444             : 
     445          24 :     if (!(CPLIsVirtualMemFileMapAvailable() &&
     446          12 :           VSIFGetNativeFileDescriptorL(fp) != nullptr &&
     447             : #if SIZEOF_VOIDP == 4
     448             :           nLength == static_cast<size_t>(nLength) &&
     449             : #endif
     450          10 :           m_poGDS->m_nCompression == COMPRESSION_NONE &&
     451          10 :           (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK ||
     452           0 :            m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
     453           0 :            m_poGDS->m_nPhotometric == PHOTOMETRIC_PALETTE) &&
     454          10 :           m_poGDS->m_nBitsPerSample == GDALGetDataTypeSizeBits(eDataType) &&
     455          10 :           !TIFFIsTiled(m_poGDS->m_hTIFF) &&
     456          10 :           !TIFFIsByteSwapped(m_poGDS->m_hTIFF)))
     457             :     {
     458           2 :         return nullptr;
     459             :     }
     460             : 
     461             :     // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
     462          10 :     if (m_poGDS->GetAccess() == GA_Update)
     463             :     {
     464           7 :         m_poGDS->FlushCache(false);
     465           7 :         VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
     466             :     }
     467             : 
     468             :     // Get strip offsets.
     469          10 :     toff_t *panTIFFOffsets = nullptr;
     470          10 :     if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPOFFSETS,
     471          20 :                       &panTIFFOffsets) ||
     472          10 :         panTIFFOffsets == nullptr)
     473             :     {
     474           0 :         return nullptr;
     475             :     }
     476             : 
     477          10 :     GPtrDiff_t nBlockSize = static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     478          10 :                             GDALGetDataTypeSizeBytes(eDataType);
     479          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     480           4 :         nBlockSize *= m_poGDS->nBands;
     481             : 
     482          10 :     int nBlocks = m_poGDS->m_nBlocksPerBand;
     483          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     484           6 :         nBlocks *= m_poGDS->nBands;
     485          10 :     int i = 0;  // Used after for.
     486         103 :     for (; i < nBlocks; ++i)
     487             :     {
     488         100 :         if (panTIFFOffsets[i] != 0)
     489           7 :             break;
     490             :     }
     491          10 :     if (i == nBlocks)
     492             :     {
     493             :         // All zeroes.
     494           3 :         if (m_poGDS->eAccess == GA_Update)
     495             :         {
     496             :             // Initialize the file with empty blocks so that the file has
     497             :             // the appropriate size.
     498             : 
     499           3 :             toff_t *panByteCounts = nullptr;
     500           3 :             if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPBYTECOUNTS,
     501           6 :                               &panByteCounts) ||
     502           3 :                 panByteCounts == nullptr)
     503             :             {
     504           0 :                 return nullptr;
     505             :             }
     506           3 :             if (VSIFSeekL(fp, 0, SEEK_END) != 0)
     507           0 :                 return nullptr;
     508           3 :             vsi_l_offset nBaseOffset = VSIFTellL(fp);
     509             : 
     510             :             // Just write one tile with libtiff to put it in appropriate state.
     511             :             GByte *pabyData =
     512           3 :                 static_cast<GByte *>(VSI_CALLOC_VERBOSE(1, nBlockSize));
     513           3 :             if (pabyData == nullptr)
     514             :             {
     515           0 :                 return nullptr;
     516             :             }
     517           3 :             const auto ret = TIFFWriteEncodedStrip(m_poGDS->m_hTIFF, 0,
     518             :                                                    pabyData, nBlockSize);
     519           3 :             VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
     520           3 :             VSIFree(pabyData);
     521           3 :             if (ret != nBlockSize)
     522             :             {
     523           0 :                 return nullptr;
     524             :             }
     525           3 :             CPLAssert(panTIFFOffsets[0] == nBaseOffset);
     526           3 :             CPLAssert(panByteCounts[0] == static_cast<toff_t>(nBlockSize));
     527             : 
     528             :             // Now simulate the writing of other blocks.
     529           3 :             assert(nBlocks > 0);
     530           3 :             assert(static_cast<vsi_l_offset>(nBlockSize) <
     531             :                    std::numeric_limits<vsi_l_offset>::max() / nBlocks);
     532           3 :             const vsi_l_offset nDataSize =
     533           3 :                 static_cast<vsi_l_offset>(nBlockSize) * nBlocks;
     534           3 :             if (VSIFTruncateL(fp, nBaseOffset + nDataSize) != 0)
     535           0 :                 return nullptr;
     536             : 
     537          93 :             for (i = 1; i < nBlocks; ++i)
     538             :             {
     539          90 :                 panTIFFOffsets[i] =
     540          90 :                     nBaseOffset + i * static_cast<toff_t>(nBlockSize);
     541          90 :                 panByteCounts[i] = nBlockSize;
     542             :             }
     543             :         }
     544             :         else
     545             :         {
     546           0 :             CPLDebug("GTiff", "Sparse files not supported in file mapping");
     547           0 :             return nullptr;
     548             :         }
     549             :     }
     550             : 
     551          10 :     GIntBig nBlockSpacing = 0;
     552          10 :     bool bCompatibleSpacing = true;
     553          10 :     toff_t nPrevOffset = 0;
     554         229 :     for (i = 0; i < m_poGDS->m_nBlocksPerBand; ++i)
     555             :     {
     556         219 :         toff_t nCurOffset = 0;
     557         219 :         if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     558          96 :             nCurOffset =
     559          96 :                 panTIFFOffsets[m_poGDS->m_nBlocksPerBand * (nBand - 1) + i];
     560             :         else
     561         123 :             nCurOffset = panTIFFOffsets[i];
     562         219 :         if (nCurOffset == 0)
     563             :         {
     564           0 :             bCompatibleSpacing = false;
     565           0 :             break;
     566             :         }
     567         219 :         if (i > 0)
     568             :         {
     569         209 :             const GIntBig nCurSpacing = nCurOffset - nPrevOffset;
     570         209 :             if (i == 1)
     571             :             {
     572          10 :                 if (nCurSpacing !=
     573          10 :                     static_cast<GIntBig>(nBlockYSize) * nLineSize)
     574             :                 {
     575           0 :                     bCompatibleSpacing = false;
     576           0 :                     break;
     577             :                 }
     578          10 :                 nBlockSpacing = nCurSpacing;
     579             :             }
     580         199 :             else if (nBlockSpacing != nCurSpacing)
     581             :             {
     582           0 :                 bCompatibleSpacing = false;
     583           0 :                 break;
     584             :             }
     585             :         }
     586         219 :         nPrevOffset = nCurOffset;
     587             :     }
     588             : 
     589          10 :     if (!bCompatibleSpacing)
     590             :     {
     591           0 :         return nullptr;
     592             :     }
     593             : 
     594          10 :     vsi_l_offset nOffset = 0;
     595          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     596             :     {
     597           4 :         CPLAssert(m_poGDS->m_pBaseMapping == nullptr);
     598           4 :         nOffset = panTIFFOffsets[0];
     599             :     }
     600             :     else
     601             :     {
     602           6 :         nOffset = panTIFFOffsets[m_poGDS->m_nBlocksPerBand * (nBand - 1)];
     603             :     }
     604          10 :     CPLVirtualMem *pVMem = CPLVirtualMemFileMapNew(
     605             :         fp, nOffset, nLength,
     606             :         eRWFlag == GF_Write ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
     607             :         nullptr, nullptr);
     608          10 :     if (pVMem == nullptr)
     609             :     {
     610           0 :         return nullptr;
     611             :     }
     612             : 
     613          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     614             :     {
     615             :         // TODO(schwehr): Revisit this block.
     616           4 :         m_poGDS->m_pBaseMapping = pVMem;
     617           4 :         pVMem = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
     618             :                                           papszOptions);
     619             :         // Drop ref on base mapping.
     620           4 :         CPLVirtualMemFree(m_poGDS->m_pBaseMapping);
     621           4 :         if (pVMem == nullptr)
     622           0 :             m_poGDS->m_pBaseMapping = nullptr;
     623             :     }
     624             :     else
     625             :     {
     626           6 :         *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
     627           6 :         if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     628           0 :             *pnPixelSpace *= m_poGDS->nBands;
     629           6 :         *pnLineSpace = nLineSize;
     630             :     }
     631          10 :     return pVMem;
     632             : }
     633             : 
     634             : /************************************************************************/
     635             : /*                       IGetDataCoverageStatus()                       */
     636             : /************************************************************************/
     637             : 
     638         888 : int GTiffRasterBand::IGetDataCoverageStatus(int nXOff, int nYOff, int nXSize,
     639             :                                             int nYSize, int nMaskFlagStop,
     640             :                                             double *pdfDataPct)
     641             : {
     642         888 :     if (eAccess == GA_Update)
     643          95 :         m_poGDS->FlushCache(false);
     644             : 
     645         888 :     const int iXBlockStart = nXOff / nBlockXSize;
     646         888 :     const int iXBlockEnd = (nXOff + nXSize - 1) / nBlockXSize;
     647         888 :     const int iYBlockStart = nYOff / nBlockYSize;
     648         888 :     const int iYBlockEnd = (nYOff + nYSize - 1) / nBlockYSize;
     649         888 :     int nStatus = 0;
     650         888 :     VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
     651         888 :     GIntBig nPixelsData = 0;
     652        2486 :     for (int iY = iYBlockStart; iY <= iYBlockEnd; ++iY)
     653             :     {
     654        4296 :         for (int iX = iXBlockStart; iX <= iXBlockEnd; ++iX)
     655             :         {
     656        2698 :             const int nBlockIdBand0 = iX + iY * nBlocksPerRow;
     657        2698 :             int nBlockId = nBlockIdBand0;
     658        2698 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     659         133 :                 nBlockId =
     660         133 :                     nBlockIdBand0 + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     661        2698 :             vsi_l_offset nOffset = 0;
     662        2698 :             vsi_l_offset nLength = 0;
     663        2698 :             bool bHasData = false;
     664        2698 :             bool bError = false;
     665        2698 :             if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, &nLength,
     666             :                                            &bError))
     667             :             {
     668        1866 :                 if (bError)
     669         826 :                     return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED;
     670        1866 :                 nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
     671             :             }
     672             :             else
     673             :             {
     674         832 :                 if (m_poGDS->m_nCompression == COMPRESSION_NONE &&
     675         726 :                     m_poGDS->eAccess == GA_ReadOnly &&
     676         684 :                     ((!m_bNoDataSet && !m_bNoDataSetAsInt64 &&
     677         684 :                       !m_bNoDataSetAsUInt64) ||
     678           0 :                      (m_bNoDataSet && m_dfNoDataValue == 0.0) ||
     679           0 :                      (m_bNoDataSetAsInt64 && m_nNoDataValueInt64 == 0) ||
     680           0 :                      (m_bNoDataSetAsUInt64 && m_nNoDataValueUInt64 == 0)))
     681             :                 {
     682             :                     VSIRangeStatus eStatus =
     683         684 :                         VSIFGetRangeStatusL(fp, nOffset, nLength);
     684         684 :                     if (eStatus == VSI_RANGE_STATUS_HOLE)
     685             :                     {
     686           0 :                         nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
     687             :                     }
     688             :                     else
     689             :                     {
     690         684 :                         bHasData = true;
     691         684 :                     }
     692             :                 }
     693             :                 else
     694             :                 {
     695         148 :                     bHasData = true;
     696             :                 }
     697             :             }
     698        2698 :             if (bHasData)
     699             :             {
     700         832 :                 const int nXBlockRight =
     701         832 :                     (iX * nBlockXSize > INT_MAX - nBlockXSize)
     702         832 :                         ? INT_MAX
     703         832 :                         : (iX + 1) * nBlockXSize;
     704         832 :                 const int nYBlockBottom =
     705         832 :                     (iY * nBlockYSize > INT_MAX - nBlockYSize)
     706         832 :                         ? INT_MAX
     707         832 :                         : (iY + 1) * nBlockYSize;
     708             : 
     709        1664 :                 nPixelsData += (static_cast<GIntBig>(
     710         832 :                                     std::min(nXBlockRight, nXOff + nXSize)) -
     711         832 :                                 std::max(iX * nBlockXSize, nXOff)) *
     712         832 :                                (std::min(nYBlockBottom, nYOff + nYSize) -
     713         832 :                                 std::max(iY * nBlockYSize, nYOff));
     714         832 :                 nStatus |= GDAL_DATA_COVERAGE_STATUS_DATA;
     715             :             }
     716        2698 :             if (nMaskFlagStop != 0 && (nMaskFlagStop & nStatus) != 0)
     717             :             {
     718         826 :                 if (pdfDataPct)
     719           0 :                     *pdfDataPct = -1.0;
     720         826 :                 return nStatus;
     721             :             }
     722             :         }
     723             :     }
     724          62 :     if (pdfDataPct)
     725           8 :         *pdfDataPct =
     726           8 :             100.0 * nPixelsData / (static_cast<GIntBig>(nXSize) * nYSize);
     727          62 :     return nStatus;
     728             : }
     729             : 
     730             : /************************************************************************/
     731             : /*                             IReadBlock()                             */
     732             : /************************************************************************/
     733             : 
     734     2310440 : CPLErr GTiffRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     735             : 
     736             : {
     737     2310440 :     m_poGDS->Crystalize();
     738             : 
     739     2310300 :     GPtrDiff_t nBlockBufSize = 0;
     740     2310300 :     if (TIFFIsTiled(m_poGDS->m_hTIFF))
     741             :     {
     742       57850 :         nBlockBufSize = static_cast<GPtrDiff_t>(TIFFTileSize(m_poGDS->m_hTIFF));
     743             :     }
     744             :     else
     745             :     {
     746     2252410 :         CPLAssert(nBlockXOff == 0);
     747             :         nBlockBufSize =
     748     2252410 :             static_cast<GPtrDiff_t>(TIFFStripSize(m_poGDS->m_hTIFF));
     749             :     }
     750             : 
     751     2310210 :     const int nBlockId = ComputeBlockId(nBlockXOff, nBlockYOff);
     752             : 
     753             :     /* -------------------------------------------------------------------- */
     754             :     /*      The bottom most partial tiles and strips are sometimes only     */
     755             :     /*      partially encoded.  This code reduces the requested data so     */
     756             :     /*      an error won't be reported in this case. (#1179)                */
     757             :     /* -------------------------------------------------------------------- */
     758     2310210 :     auto nBlockReqSize = nBlockBufSize;
     759             : 
     760     2310210 :     if (nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize)
     761             :     {
     762        6219 :         nBlockReqSize =
     763        6219 :             (nBlockBufSize / nBlockYSize) *
     764        6219 :             (nBlockYSize -
     765             :              static_cast<int>(
     766        6219 :                  (static_cast<GIntBig>(nBlockYOff + 1) * nBlockYSize) %
     767        6219 :                  nRasterYSize));
     768             :     }
     769             : 
     770             :     /* -------------------------------------------------------------------- */
     771             :     /*      Handle the case of a strip or tile that doesn't exist yet.      */
     772             :     /*      Just set to zeros and return.                                   */
     773             :     /* -------------------------------------------------------------------- */
     774     2310210 :     vsi_l_offset nOffset = 0;
     775     2310210 :     bool bErrOccurred = false;
     776     4487700 :     if (nBlockId != m_poGDS->m_nLoadedBlock &&
     777     2177410 :         !m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr, &bErrOccurred))
     778             :     {
     779       50229 :         NullBlock(pImage);
     780       50229 :         if (bErrOccurred)
     781           1 :             return CE_Failure;
     782       50228 :         return CE_None;
     783             :     }
     784             : 
     785     2260060 :     if (m_poGDS->m_bStreamingIn &&
     786       10936 :         !(m_poGDS->nBands > 1 &&
     787       10423 :           m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG &&
     788       10048 :           nBlockId == m_poGDS->m_nLoadedBlock))
     789             :     {
     790        3436 :         if (nOffset < VSIFTellL(m_poGDS->m_fpL))
     791             :         {
     792        2000 :             ReportError(CE_Failure, CPLE_NotSupported,
     793             :                         "Trying to load block %d at offset " CPL_FRMT_GUIB
     794             :                         " whereas current pos is " CPL_FRMT_GUIB
     795             :                         " (backward read not supported)",
     796             :                         nBlockId, static_cast<GUIntBig>(nOffset),
     797        1000 :                         static_cast<GUIntBig>(VSIFTellL(m_poGDS->m_fpL)));
     798        1000 :             return CE_Failure;
     799             :         }
     800             :     }
     801             : 
     802             :     /* -------------------------------------------------------------------- */
     803             :     /*      Handle simple case (separate, onesampleperpixel)                */
     804             :     /* -------------------------------------------------------------------- */
     805     2259060 :     CPLErr eErr = CE_None;
     806     2259060 :     if (m_poGDS->nBands == 1 ||
     807      208103 :         m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     808             :     {
     809     2075620 :         if (nBlockReqSize < nBlockBufSize)
     810        2883 :             memset(pImage, 0, nBlockBufSize);
     811             : 
     812     2075620 :         if (!m_poGDS->ReadStrile(nBlockId, pImage, nBlockReqSize))
     813             :         {
     814          81 :             memset(pImage, 0, nBlockBufSize);
     815          81 :             return CE_Failure;
     816             :         }
     817             :     }
     818             :     else
     819             :     {
     820             :         /* --------------------------------------------------------------------
     821             :          */
     822             :         /*      Load desired block */
     823             :         /* --------------------------------------------------------------------
     824             :          */
     825      183448 :         eErr = m_poGDS->LoadBlockBuf(nBlockId);
     826      183448 :         if (eErr != CE_None)
     827             :         {
     828          25 :             memset(pImage, 0,
     829          50 :                    static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     830          25 :                        GDALGetDataTypeSizeBytes(eDataType));
     831          25 :             return eErr;
     832             :         }
     833             : 
     834      183423 :         bool bDoCopyWords = true;
     835       52021 :         if (nBand == 1 && !m_poGDS->m_bLoadingOtherBands &&
     836       46328 :             eAccess == GA_ReadOnly &&
     837       37068 :             (m_poGDS->nBands == 3 || m_poGDS->nBands == 4) &&
     838       36298 :             ((eDataType == GDT_Byte && m_poGDS->m_nBitsPerSample == 8) ||
     839         432 :              (eDataType == GDT_Int16 && m_poGDS->m_nBitsPerSample == 16) ||
     840      235714 :              (eDataType == GDT_UInt16 && m_poGDS->m_nBitsPerSample == 16)) &&
     841       72278 :             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     842       36139 :                     GDALGetDataTypeSizeBytes(eDataType) <
     843       36139 :                 GDALGetCacheMax64() / m_poGDS->nBands)
     844             :         {
     845       36139 :             bDoCopyWords = false;
     846             :             void *ppDestBuffers[4];
     847       36139 :             GDALRasterBlock *apoLockedBlocks[4] = {nullptr, nullptr, nullptr,
     848             :                                                    nullptr};
     849      155660 :             for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
     850             :             {
     851      119521 :                 if (iBand == nBand)
     852             :                 {
     853       36139 :                     ppDestBuffers[iBand - 1] = pImage;
     854             :                 }
     855             :                 else
     856             :                 {
     857             :                     GDALRasterBlock *poBlock =
     858       83382 :                         m_poGDS->GetRasterBand(iBand)->GetLockedBlockRef(
     859       83382 :                             nBlockXOff, nBlockYOff, true);
     860       83382 :                     if (poBlock == nullptr)
     861             :                     {
     862           0 :                         bDoCopyWords = true;
     863           0 :                         break;
     864             :                     }
     865       83382 :                     ppDestBuffers[iBand - 1] = poBlock->GetDataRef();
     866       83382 :                     apoLockedBlocks[iBand - 1] = poBlock;
     867             :                 }
     868             :             }
     869       36139 :             if (!bDoCopyWords)
     870             :             {
     871       36139 :                 GDALDeinterleave(m_poGDS->m_pabyBlockBuf, eDataType,
     872       36139 :                                  m_poGDS->nBands, ppDestBuffers, eDataType,
     873       36139 :                                  static_cast<size_t>(nBlockXSize) *
     874       36139 :                                      nBlockYSize);
     875             :             }
     876      155660 :             for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
     877             :             {
     878      119521 :                 if (apoLockedBlocks[iBand - 1])
     879             :                 {
     880       83382 :                     apoLockedBlocks[iBand - 1]->DropLock();
     881             :                 }
     882             :             }
     883             :         }
     884             : 
     885      183423 :         if (bDoCopyWords)
     886             :         {
     887      147284 :             const int nWordBytes = m_poGDS->m_nBitsPerSample / 8;
     888      147284 :             GByte *pabyImage =
     889      147284 :                 m_poGDS->m_pabyBlockBuf + (nBand - 1) * nWordBytes;
     890             : 
     891      147284 :             GDALCopyWords64(pabyImage, eDataType, m_poGDS->nBands * nWordBytes,
     892             :                             pImage, eDataType, nWordBytes,
     893      147284 :                             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize);
     894             : 
     895      147284 :             eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
     896             :         }
     897             :     }
     898             : 
     899     2259070 :     CacheMaskForBlock(nBlockXOff, nBlockYOff);
     900             : 
     901     2259130 :     return eErr;
     902             : }
     903             : 
     904             : /************************************************************************/
     905             : /*                           CacheMaskForBlock()                       */
     906             : /************************************************************************/
     907             : 
     908     2261500 : void GTiffRasterBand::CacheMaskForBlock(int nBlockXOff, int nBlockYOff)
     909             : 
     910             : {
     911             :     // Preload mask data if layout compatible and we have cached ranges
     912     2261510 :     if (m_poGDS->m_bMaskInterleavedWithImagery && m_poGDS->m_poMaskDS &&
     913         108 :         VSI_TIFFHasCachedRanges(TIFFClientdata(m_poGDS->m_hTIFF)))
     914             :     {
     915          97 :         auto poBand = cpl::down_cast<GTiffRasterBand *>(
     916          97 :             m_poGDS->m_poMaskDS->GetRasterBand(1));
     917         291 :         if (m_poGDS->m_poMaskDS->m_oCacheStrileToOffsetByteCount.contains(
     918          97 :                 poBand->ComputeBlockId(nBlockXOff, nBlockYOff)))
     919             :         {
     920             :             GDALRasterBlock *poBlock =
     921          93 :                 poBand->GetLockedBlockRef(nBlockXOff, nBlockYOff);
     922          93 :             if (poBlock)
     923          93 :                 poBlock->DropLock();
     924             :         }
     925             :     }
     926     2261410 : }
     927             : 
     928             : /************************************************************************/
     929             : /*                       FillCacheForOtherBands()                       */
     930             : /************************************************************************/
     931             : 
     932      147498 : CPLErr GTiffRasterBand::FillCacheForOtherBands(int nBlockXOff, int nBlockYOff)
     933             : 
     934             : {
     935             :     /* -------------------------------------------------------------------- */
     936             :     /*      In the fairly common case of pixel interleaved 8bit data        */
     937             :     /*      that is multi-band, lets push the rest of the data into the     */
     938             :     /*      block cache too, to avoid (hopefully) having to redecode it.    */
     939             :     /*                                                                      */
     940             :     /*      Our following logic actually depends on the fact that the       */
     941             :     /*      this block is already loaded, so subsequent calls will end      */
     942             :     /*      up back in this method and pull from the loaded block.          */
     943             :     /*                                                                      */
     944             :     /*      Be careful not entering this portion of code from               */
     945             :     /*      the other bands, otherwise we'll get very deep nested calls     */
     946             :     /*      and O(nBands^2) performance !                                   */
     947             :     /*                                                                      */
     948             :     /*      If there are many bands and the block cache size is not big     */
     949             :     /*      enough to accommodate the size of all the blocks, don't enter   */
     950             :     /* -------------------------------------------------------------------- */
     951      147498 :     CPLErr eErr = CE_None;
     952      442494 :     if (m_poGDS->nBands != 1 &&
     953      147498 :         m_poGDS->nBands <
     954       49064 :             128 &&  // avoid caching for datasets with too many bands
     955      307891 :         !m_poGDS->m_bLoadingOtherBands &&
     956       25790 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     957       12895 :                 GDALGetDataTypeSizeBytes(eDataType) <
     958       12895 :             GDALGetCacheMax64() / m_poGDS->nBands)
     959             :     {
     960       12895 :         m_poGDS->m_bLoadingOtherBands = true;
     961             : 
     962       52923 :         for (int iOtherBand = 1; iOtherBand <= m_poGDS->nBands; ++iOtherBand)
     963             :         {
     964       40028 :             if (iOtherBand == nBand)
     965       12895 :                 continue;
     966             : 
     967             :             GDALRasterBlock *poBlock =
     968       27133 :                 m_poGDS->GetRasterBand(iOtherBand)
     969       27133 :                     ->GetLockedBlockRef(nBlockXOff, nBlockYOff);
     970       27133 :             if (poBlock == nullptr)
     971             :             {
     972           0 :                 eErr = CE_Failure;
     973           0 :                 break;
     974             :             }
     975       27133 :             poBlock->DropLock();
     976             :         }
     977             : 
     978       12895 :         m_poGDS->m_bLoadingOtherBands = false;
     979             :     }
     980             : 
     981      147498 :     return eErr;
     982             : }
     983             : 
     984             : /************************************************************************/
     985             : /*                           GetDescription()                           */
     986             : /************************************************************************/
     987             : 
     988      308005 : const char *GTiffRasterBand::GetDescription() const
     989             : {
     990      308005 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
     991             : 
     992      308005 :     return m_osDescription;
     993             : }
     994             : 
     995             : /************************************************************************/
     996             : /*                             GetOffset()                              */
     997             : /************************************************************************/
     998             : 
     999      315633 : double GTiffRasterBand::GetOffset(int *pbSuccess)
    1000             : 
    1001             : {
    1002      315633 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1003             : 
    1004      315633 :     if (pbSuccess)
    1005        7504 :         *pbSuccess = m_bHaveOffsetScale;
    1006      315633 :     return m_dfOffset;
    1007             : }
    1008             : 
    1009             : /************************************************************************/
    1010             : /*                              GetScale()                              */
    1011             : /************************************************************************/
    1012             : 
    1013      315636 : double GTiffRasterBand::GetScale(int *pbSuccess)
    1014             : 
    1015             : {
    1016      315636 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1017             : 
    1018      315636 :     if (pbSuccess)
    1019        7507 :         *pbSuccess = m_bHaveOffsetScale;
    1020      315636 :     return m_dfScale;
    1021             : }
    1022             : 
    1023             : /************************************************************************/
    1024             : /*                            GetUnitType()                             */
    1025             : /************************************************************************/
    1026             : 
    1027      306825 : const char *GTiffRasterBand::GetUnitType()
    1028             : 
    1029             : {
    1030      306825 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1031      306825 :     if (m_osUnitType.empty())
    1032             :     {
    1033      306632 :         m_poGDS->LookForProjection();
    1034      306632 :         if (m_poGDS->m_pszVertUnit)
    1035           9 :             return m_poGDS->m_pszVertUnit;
    1036             :     }
    1037             : 
    1038      306816 :     return m_osUnitType.c_str();
    1039             : }
    1040             : 
    1041             : /************************************************************************/
    1042             : /*                      GetMetadataDomainList()                         */
    1043             : /************************************************************************/
    1044             : 
    1045          12 : char **GTiffRasterBand::GetMetadataDomainList()
    1046             : {
    1047          12 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1048             : 
    1049          12 :     return CSLDuplicate(m_oGTiffMDMD.GetDomainList());
    1050             : }
    1051             : 
    1052             : /************************************************************************/
    1053             : /*                            GetMetadata()                             */
    1054             : /************************************************************************/
    1055             : 
    1056       17175 : char **GTiffRasterBand::GetMetadata(const char *pszDomain)
    1057             : 
    1058             : {
    1059       17175 :     if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
    1060             :     {
    1061       16996 :         m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1062             :     }
    1063             : 
    1064       17175 :     return m_oGTiffMDMD.GetMetadata(pszDomain);
    1065             : }
    1066             : 
    1067             : /************************************************************************/
    1068             : /*                          GetMetadataItem()                           */
    1069             : /************************************************************************/
    1070             : 
    1071       23389 : const char *GTiffRasterBand::GetMetadataItem(const char *pszName,
    1072             :                                              const char *pszDomain)
    1073             : 
    1074             : {
    1075       23389 :     if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
    1076             :     {
    1077        9019 :         m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1078             :     }
    1079             : 
    1080       23389 :     if (pszName != nullptr && pszDomain != nullptr && EQUAL(pszDomain, "TIFF"))
    1081             :     {
    1082        5240 :         int nBlockXOff = 0;
    1083        5240 :         int nBlockYOff = 0;
    1084             : 
    1085        5240 :         if (EQUAL(pszName, "JPEGTABLES"))
    1086             :         {
    1087          11 :             uint32_t nJPEGTableSize = 0;
    1088          11 :             void *pJPEGTable = nullptr;
    1089          11 :             if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_JPEGTABLES,
    1090          11 :                              &nJPEGTableSize, &pJPEGTable) != 1 ||
    1091          11 :                 pJPEGTable == nullptr || nJPEGTableSize > INT_MAX)
    1092             :             {
    1093           0 :                 return nullptr;
    1094             :             }
    1095          11 :             char *const pszHex = CPLBinaryToHex(
    1096             :                 nJPEGTableSize, static_cast<const GByte *>(pJPEGTable));
    1097          11 :             const char *pszReturn = CPLSPrintf("%s", pszHex);
    1098          11 :             CPLFree(pszHex);
    1099             : 
    1100          11 :             return pszReturn;
    1101             :         }
    1102             : 
    1103        5229 :         if (EQUAL(pszName, "IFD_OFFSET"))
    1104             :         {
    1105         178 :             return CPLSPrintf(CPL_FRMT_GUIB,
    1106          89 :                               static_cast<GUIntBig>(m_poGDS->m_nDirOffset));
    1107             :         }
    1108             : 
    1109        5140 :         if (sscanf(pszName, "BLOCK_OFFSET_%d_%d", &nBlockXOff, &nBlockYOff) ==
    1110             :             2)
    1111             :         {
    1112        4421 :             if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
    1113        4420 :                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
    1114          19 :                 return nullptr;
    1115             : 
    1116        4402 :             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
    1117        4402 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
    1118             :             {
    1119        3592 :                 nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
    1120             :             }
    1121             : 
    1122        4402 :             vsi_l_offset nOffset = 0;
    1123        4402 :             if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr,
    1124             :                                            nullptr))
    1125             :             {
    1126         184 :                 return nullptr;
    1127             :             }
    1128             : 
    1129        4218 :             return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nOffset));
    1130             :         }
    1131             : 
    1132         719 :         if (sscanf(pszName, "BLOCK_SIZE_%d_%d", &nBlockXOff, &nBlockYOff) == 2)
    1133             :         {
    1134         719 :             if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
    1135         718 :                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
    1136           2 :                 return nullptr;
    1137             : 
    1138         717 :             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
    1139         717 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
    1140             :             {
    1141         244 :                 nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
    1142             :             }
    1143             : 
    1144         717 :             vsi_l_offset nByteCount = 0;
    1145         717 :             if (!m_poGDS->IsBlockAvailable(nBlockId, nullptr, &nByteCount,
    1146             :                                            nullptr))
    1147             :             {
    1148          86 :                 return nullptr;
    1149             :             }
    1150             : 
    1151         631 :             return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nByteCount));
    1152           0 :         }
    1153             :     }
    1154       18149 :     else if (pszName && pszDomain && EQUAL(pszDomain, "_DEBUG_"))
    1155             :     {
    1156         131 :         if (EQUAL(pszName, "HAS_BLOCK_CACHE"))
    1157         131 :             return HasBlockCache() ? "1" : "0";
    1158             :     }
    1159             : 
    1160       18018 :     const char *pszRet = m_oGTiffMDMD.GetMetadataItem(pszName, pszDomain);
    1161             : 
    1162       18018 :     if (pszRet == nullptr && eDataType == GDT_Byte && pszName && pszDomain &&
    1163       15519 :         EQUAL(pszDomain, "IMAGE_STRUCTURE") && EQUAL(pszName, "PIXELTYPE"))
    1164             :     {
    1165             :         // to get a chance of emitting the warning about this legacy usage
    1166        3602 :         pszRet = GDALRasterBand::GetMetadataItem(pszName, pszDomain);
    1167             :     }
    1168       18018 :     return pszRet;
    1169             : }
    1170             : 
    1171             : /************************************************************************/
    1172             : /*                       GetColorInterpretation()                       */
    1173             : /************************************************************************/
    1174             : 
    1175      460519 : GDALColorInterp GTiffRasterBand::GetColorInterpretation()
    1176             : 
    1177             : {
    1178      460519 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1179             : 
    1180      460519 :     return m_eBandInterp;
    1181             : }
    1182             : 
    1183             : /************************************************************************/
    1184             : /*                           GetColorTable()                            */
    1185             : /************************************************************************/
    1186             : 
    1187       12232 : GDALColorTable *GTiffRasterBand::GetColorTable()
    1188             : 
    1189             : {
    1190       12232 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1191             : 
    1192       12232 :     if (nBand == 1)
    1193       10317 :         return m_poGDS->m_poColorTable.get();
    1194             : 
    1195        1915 :     return nullptr;
    1196             : }
    1197             : 
    1198             : /************************************************************************/
    1199             : /*                           GetNoDataValue()                           */
    1200             : /************************************************************************/
    1201             : 
    1202      952358 : double GTiffRasterBand::GetNoDataValue(int *pbSuccess)
    1203             : 
    1204             : {
    1205      952358 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1206             : 
    1207      952956 :     int bSuccess = FALSE;
    1208      952956 :     double dfNoDataValue = GDALPamRasterBand::GetNoDataValue(&bSuccess);
    1209      950238 :     if (bSuccess)
    1210             :     {
    1211           4 :         if (pbSuccess)
    1212           4 :             *pbSuccess = TRUE;
    1213             : 
    1214           4 :         return dfNoDataValue;
    1215             :     }
    1216             : 
    1217      950234 :     if (m_bNoDataSet)
    1218             :     {
    1219        2751 :         if (pbSuccess)
    1220        2711 :             *pbSuccess = TRUE;
    1221             : 
    1222        2751 :         return m_dfNoDataValue;
    1223             :     }
    1224             : 
    1225      947483 :     if (m_poGDS->m_bNoDataSet)
    1226             :     {
    1227      423452 :         if (pbSuccess)
    1228      423229 :             *pbSuccess = TRUE;
    1229             : 
    1230      423452 :         return m_poGDS->m_dfNoDataValue;
    1231             :     }
    1232             : 
    1233      524031 :     if (m_bNoDataSetAsInt64)
    1234             :     {
    1235           0 :         if (pbSuccess)
    1236           0 :             *pbSuccess = TRUE;
    1237             : 
    1238           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
    1239             :     }
    1240             : 
    1241      524031 :     if (m_poGDS->m_bNoDataSetAsInt64)
    1242             :     {
    1243           0 :         if (pbSuccess)
    1244           0 :             *pbSuccess = TRUE;
    1245             : 
    1246           0 :         return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueInt64);
    1247             :     }
    1248             : 
    1249      524031 :     if (m_bNoDataSetAsUInt64)
    1250             :     {
    1251           0 :         if (pbSuccess)
    1252           0 :             *pbSuccess = TRUE;
    1253             : 
    1254           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
    1255             :     }
    1256             : 
    1257      524031 :     if (m_poGDS->m_bNoDataSetAsUInt64)
    1258             :     {
    1259           0 :         if (pbSuccess)
    1260           0 :             *pbSuccess = TRUE;
    1261             : 
    1262           0 :         return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueUInt64);
    1263             :     }
    1264             : 
    1265      524031 :     if (pbSuccess)
    1266      526059 :         *pbSuccess = FALSE;
    1267      524031 :     return dfNoDataValue;
    1268             : }
    1269             : 
    1270             : /************************************************************************/
    1271             : /*                       GetNoDataValueAsInt64()                        */
    1272             : /************************************************************************/
    1273             : 
    1274          35 : int64_t GTiffRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
    1275             : 
    1276             : {
    1277          35 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1278             : 
    1279          35 :     if (eDataType == GDT_UInt64)
    1280             :     {
    1281           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1282             :                  "GetNoDataValueAsUInt64() should be called instead");
    1283           0 :         if (pbSuccess)
    1284           0 :             *pbSuccess = FALSE;
    1285           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1286             :     }
    1287          35 :     if (eDataType != GDT_Int64)
    1288             :     {
    1289           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1290             :                  "GetNoDataValue() should be called instead");
    1291           0 :         if (pbSuccess)
    1292           0 :             *pbSuccess = FALSE;
    1293           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1294             :     }
    1295             : 
    1296          35 :     int bSuccess = FALSE;
    1297             :     const auto nNoDataValue =
    1298          35 :         GDALPamRasterBand::GetNoDataValueAsInt64(&bSuccess);
    1299          35 :     if (bSuccess)
    1300             :     {
    1301           0 :         if (pbSuccess)
    1302           0 :             *pbSuccess = TRUE;
    1303             : 
    1304           0 :         return nNoDataValue;
    1305             :     }
    1306             : 
    1307          35 :     if (m_bNoDataSetAsInt64)
    1308             :     {
    1309           2 :         if (pbSuccess)
    1310           2 :             *pbSuccess = TRUE;
    1311             : 
    1312           2 :         return m_nNoDataValueInt64;
    1313             :     }
    1314             : 
    1315          33 :     if (m_poGDS->m_bNoDataSetAsInt64)
    1316             :     {
    1317           7 :         if (pbSuccess)
    1318           6 :             *pbSuccess = TRUE;
    1319             : 
    1320           7 :         return m_poGDS->m_nNoDataValueInt64;
    1321             :     }
    1322             : 
    1323          26 :     if (pbSuccess)
    1324          26 :         *pbSuccess = FALSE;
    1325          26 :     return nNoDataValue;
    1326             : }
    1327             : 
    1328             : /************************************************************************/
    1329             : /*                      GetNoDataValueAsUInt64()                        */
    1330             : /************************************************************************/
    1331             : 
    1332          21 : uint64_t GTiffRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
    1333             : 
    1334             : {
    1335          21 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1336             : 
    1337          21 :     if (eDataType == GDT_Int64)
    1338             :     {
    1339           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1340             :                  "GetNoDataValueAsInt64() should be called instead");
    1341           0 :         if (pbSuccess)
    1342           0 :             *pbSuccess = FALSE;
    1343           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1344             :     }
    1345          21 :     if (eDataType != GDT_UInt64)
    1346             :     {
    1347           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1348             :                  "GetNoDataValue() should be called instead");
    1349           0 :         if (pbSuccess)
    1350           0 :             *pbSuccess = FALSE;
    1351           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1352             :     }
    1353             : 
    1354          21 :     int bSuccess = FALSE;
    1355             :     const auto nNoDataValue =
    1356          21 :         GDALPamRasterBand::GetNoDataValueAsUInt64(&bSuccess);
    1357          21 :     if (bSuccess)
    1358             :     {
    1359           0 :         if (pbSuccess)
    1360           0 :             *pbSuccess = TRUE;
    1361             : 
    1362           0 :         return nNoDataValue;
    1363             :     }
    1364             : 
    1365          21 :     if (m_bNoDataSetAsUInt64)
    1366             :     {
    1367           0 :         if (pbSuccess)
    1368           0 :             *pbSuccess = TRUE;
    1369             : 
    1370           0 :         return m_nNoDataValueUInt64;
    1371             :     }
    1372             : 
    1373          21 :     if (m_poGDS->m_bNoDataSetAsUInt64)
    1374             :     {
    1375           7 :         if (pbSuccess)
    1376           6 :             *pbSuccess = TRUE;
    1377             : 
    1378           7 :         return m_poGDS->m_nNoDataValueUInt64;
    1379             :     }
    1380             : 
    1381          14 :     if (pbSuccess)
    1382          14 :         *pbSuccess = FALSE;
    1383          14 :     return nNoDataValue;
    1384             : }
    1385             : 
    1386             : /************************************************************************/
    1387             : /*                          GetOverviewCount()                          */
    1388             : /************************************************************************/
    1389             : 
    1390     1319780 : int GTiffRasterBand::GetOverviewCount()
    1391             : 
    1392             : {
    1393     1319780 :     if (!m_poGDS->AreOverviewsEnabled())
    1394          30 :         return 0;
    1395             : 
    1396     1319750 :     m_poGDS->ScanDirectories();
    1397             : 
    1398     1319750 :     if (m_poGDS->m_nOverviewCount > 0)
    1399             :     {
    1400      267308 :         return m_poGDS->m_nOverviewCount;
    1401             :     }
    1402             : 
    1403     1052440 :     const int nOverviewCount = GDALRasterBand::GetOverviewCount();
    1404     1052440 :     if (nOverviewCount > 0)
    1405         391 :         return nOverviewCount;
    1406             : 
    1407             :     // Implicit JPEG overviews are normally hidden, except when doing
    1408             :     // IRasterIO() operations.
    1409     1052050 :     if (m_poGDS->m_nJPEGOverviewVisibilityCounter)
    1410     1044190 :         return m_poGDS->GetJPEGOverviewCount();
    1411             : 
    1412        7861 :     return 0;
    1413             : }
    1414             : 
    1415             : /************************************************************************/
    1416             : /*                            GetOverview()                             */
    1417             : /************************************************************************/
    1418             : 
    1419       74175 : GDALRasterBand *GTiffRasterBand::GetOverview(int i)
    1420             : 
    1421             : {
    1422       74175 :     m_poGDS->ScanDirectories();
    1423             : 
    1424       74172 :     if (m_poGDS->m_nOverviewCount > 0)
    1425             :     {
    1426             :         // Do we have internal overviews?
    1427       73576 :         if (i < 0 || i >= m_poGDS->m_nOverviewCount)
    1428           8 :             return nullptr;
    1429             : 
    1430       73568 :         return m_poGDS->m_papoOverviewDS[i]->GetRasterBand(nBand);
    1431             :     }
    1432             : 
    1433         596 :     GDALRasterBand *const poOvrBand = GDALRasterBand::GetOverview(i);
    1434         596 :     if (poOvrBand != nullptr)
    1435         391 :         return poOvrBand;
    1436             : 
    1437             :     // For consistency with GetOverviewCount(), we should also test
    1438             :     // m_nJPEGOverviewVisibilityCounter, but it is also convenient to be able
    1439             :     // to query them for testing purposes.
    1440         205 :     if (i >= 0 && i < m_poGDS->GetJPEGOverviewCount())
    1441         164 :         return m_poGDS->m_papoJPEGOverviewDS[i]->GetRasterBand(nBand);
    1442             : 
    1443          41 :     return nullptr;
    1444             : }
    1445             : 
    1446             : /************************************************************************/
    1447             : /*                           GetMaskFlags()                             */
    1448             : /************************************************************************/
    1449             : 
    1450       21626 : int GTiffRasterBand::GetMaskFlags()
    1451             : {
    1452       21626 :     m_poGDS->ScanDirectories();
    1453             : 
    1454       21626 :     if (m_poGDS->m_poExternalMaskDS != nullptr)
    1455             :     {
    1456           0 :         return GMF_PER_DATASET;
    1457             :     }
    1458             : 
    1459       21626 :     if (m_poGDS->m_poMaskDS != nullptr)
    1460             :     {
    1461         215 :         if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
    1462             :         {
    1463         207 :             return GMF_PER_DATASET;
    1464             :         }
    1465             : 
    1466           8 :         return 0;
    1467             :     }
    1468             : 
    1469       21411 :     if (m_poGDS->m_bIsOverview)
    1470             :     {
    1471         440 :         return m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskFlags();
    1472             :     }
    1473             : 
    1474       20971 :     return GDALPamRasterBand::GetMaskFlags();
    1475             : }
    1476             : 
    1477             : /************************************************************************/
    1478             : /*                            GetMaskBand()                             */
    1479             : /************************************************************************/
    1480             : 
    1481      115323 : GDALRasterBand *GTiffRasterBand::GetMaskBand()
    1482             : {
    1483      115323 :     m_poGDS->ScanDirectories();
    1484             : 
    1485      114555 :     if (m_poGDS->m_poExternalMaskDS != nullptr)
    1486             :     {
    1487           0 :         return m_poGDS->m_poExternalMaskDS->GetRasterBand(1);
    1488             :     }
    1489             : 
    1490      114776 :     if (m_poGDS->m_poMaskDS != nullptr)
    1491             :     {
    1492         691 :         if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
    1493         674 :             return m_poGDS->m_poMaskDS->GetRasterBand(1);
    1494             : 
    1495          17 :         return m_poGDS->m_poMaskDS->GetRasterBand(nBand);
    1496             :     }
    1497             : 
    1498      114085 :     if (m_poGDS->m_bIsOverview)
    1499             :     {
    1500             :         GDALRasterBand *poBaseMask =
    1501         119 :             m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskBand();
    1502         119 :         if (poBaseMask)
    1503             :         {
    1504         119 :             const int nOverviews = poBaseMask->GetOverviewCount();
    1505         164 :             for (int i = 0; i < nOverviews; i++)
    1506             :             {
    1507          93 :                 GDALRasterBand *poOvr = poBaseMask->GetOverview(i);
    1508         141 :                 if (poOvr && poOvr->GetXSize() == GetXSize() &&
    1509          48 :                     poOvr->GetYSize() == GetYSize())
    1510             :                 {
    1511          48 :                     return poOvr;
    1512             :                 }
    1513             :             }
    1514             :         }
    1515             :     }
    1516             : 
    1517      114037 :     return GDALPamRasterBand::GetMaskBand();
    1518             : }
    1519             : 
    1520             : /************************************************************************/
    1521             : /*                            IsMaskBand()                              */
    1522             : /************************************************************************/
    1523             : 
    1524        1035 : bool GTiffRasterBand::IsMaskBand() const
    1525             : {
    1526        1067 :     return (m_poGDS->m_poImageryDS != nullptr &&
    1527          32 :             m_poGDS->m_poImageryDS->m_poMaskDS == m_poGDS) ||
    1528        2015 :            m_eBandInterp == GCI_AlphaBand ||
    1529        1983 :            m_poGDS->GetMetadataItem("INTERNAL_MASK_FLAGS_1") != nullptr;
    1530             : }
    1531             : 
    1532             : /************************************************************************/
    1533             : /*                         GetMaskValueRange()                          */
    1534             : /************************************************************************/
    1535             : 
    1536           0 : GDALMaskValueRange GTiffRasterBand::GetMaskValueRange() const
    1537             : {
    1538           0 :     if (!IsMaskBand())
    1539           0 :         return GMVR_UNKNOWN;
    1540           0 :     if (m_poGDS->m_nBitsPerSample == 1)
    1541           0 :         return m_poGDS->m_bPromoteTo8Bits ? GMVR_0_AND_255_ONLY
    1542           0 :                                           : GMVR_0_AND_1_ONLY;
    1543           0 :     return GMVR_UNKNOWN;
    1544             : }

Generated by: LCOV version 1.14