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

Generated by: LCOV version 1.14