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

Generated by: LCOV version 1.14