LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband_read.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 656 742 88.4 %
Date: 2026-01-30 03:16:47 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      307962 : GDALRasterAttributeTable *GTiffRasterBand::GetDefaultRAT()
      37             : 
      38             : {
      39      307962 :     if (m_poGDS->m_poBaseDS != nullptr)
      40          52 :         return m_poRAT.get();
      41             : 
      42      307910 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
      43             : 
      44             :     // RAT from PAM has priority over RAT in GDAL_METADATA TIFF tag
      45      307910 :     if (!m_bRATTriedReadingFromPAM)
      46             :     {
      47      305763 :         m_bRATTriedReadingFromPAM = true;
      48      305763 :         auto poRAT = GDALPamRasterBand::GetDefaultRAT();
      49      305763 :         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      307908 :     if (m_bRATSet)
      58        2164 :         return m_poRAT.get();
      59             : 
      60      305744 :     m_bRATSet = true;
      61             : 
      62             :     // Try reading from a .vat.dbf side car file
      63      305744 :     if (!GDALCanFileAcceptSidecarFile(m_poGDS->m_osFilename.c_str()))
      64           0 :         return nullptr;
      65      611488 :     const std::string osVATDBF = m_poGDS->m_osFilename + ".vat.dbf";
      66      305744 :     CSLConstList papszSiblingFiles = m_poGDS->GetSiblingFiles();
      67      611451 :     if (papszSiblingFiles &&
      68             :         // cppcheck-suppress knownConditionTrueFalse
      69      305707 :         GDALCanReliablyUseSiblingFileList(osVATDBF.c_str()))
      70             :     {
      71             :         int iSibling =
      72      305707 :             CSLFindString(papszSiblingFiles, CPLGetFilename(osVATDBF.c_str()));
      73      305707 :         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      305707 :         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_UInt8 || 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             :                                                   CSLConstList 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(
     414             :     GDALRWFlag eRWFlag, int *pnPixelSpace, GIntBig *pnLineSpace,
     415             :     CSLConstList papszOptions)
     416             : {
     417          20 :     int nLineSize = nBlockXSize * GDALGetDataTypeSizeBytes(eDataType);
     418          20 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     419          14 :         nLineSize *= m_poGDS->nBands;
     420             : 
     421          20 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     422             :     {
     423             :         // In case of a pixel interleaved file, we save virtual memory space
     424             :         // by reusing a base mapping that embraces the whole imagery.
     425          14 :         if (m_poGDS->m_pBaseMapping != nullptr)
     426             :         {
     427             :             // Offset between the base mapping and the requested mapping.
     428           8 :             vsi_l_offset nOffset = static_cast<vsi_l_offset>(nBand - 1) *
     429           8 :                                    GDALGetDataTypeSizeBytes(eDataType);
     430             : 
     431             :             GTiffRasterBand **ppoSelf = static_cast<GTiffRasterBand **>(
     432           8 :                 CPLCalloc(1, sizeof(GTiffRasterBand *)));
     433           8 :             *ppoSelf = this;
     434             : 
     435          24 :             CPLVirtualMem *pVMem = CPLVirtualMemDerivedNew(
     436           8 :                 m_poGDS->m_pBaseMapping, nOffset,
     437           8 :                 CPLVirtualMemGetSize(m_poGDS->m_pBaseMapping) - nOffset,
     438             :                 GTiffRasterBand::DropReferenceVirtualMem, ppoSelf);
     439           8 :             if (pVMem == nullptr)
     440             :             {
     441           0 :                 CPLFree(ppoSelf);
     442           0 :                 return nullptr;
     443             :             }
     444             : 
     445             :             // Mechanism used so that the memory mapping object can be
     446             :             // destroyed after the raster band.
     447           8 :             m_aSetPSelf.insert(ppoSelf);
     448           8 :             ++m_poGDS->m_nRefBaseMapping;
     449           8 :             *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
     450           8 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     451           8 :                 *pnPixelSpace *= m_poGDS->nBands;
     452           8 :             *pnLineSpace = nLineSize;
     453           8 :             return pVMem;
     454             :         }
     455             :     }
     456             : 
     457          12 :     VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
     458             : 
     459          12 :     vsi_l_offset nLength = static_cast<vsi_l_offset>(nRasterYSize) * nLineSize;
     460             : 
     461          24 :     if (!(CPLIsVirtualMemFileMapAvailable() &&
     462          12 :           VSIFGetNativeFileDescriptorL(fp) != nullptr &&
     463             : #if SIZEOF_VOIDP == 4
     464             :           nLength == static_cast<size_t>(nLength) &&
     465             : #endif
     466          10 :           m_poGDS->m_nCompression == COMPRESSION_NONE &&
     467          10 :           (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK ||
     468           0 :            m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
     469           0 :            m_poGDS->m_nPhotometric == PHOTOMETRIC_PALETTE) &&
     470          10 :           m_poGDS->m_nBitsPerSample == GDALGetDataTypeSizeBits(eDataType) &&
     471          10 :           !TIFFIsTiled(m_poGDS->m_hTIFF) &&
     472          10 :           !TIFFIsByteSwapped(m_poGDS->m_hTIFF)))
     473             :     {
     474           2 :         return nullptr;
     475             :     }
     476             : 
     477             :     // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
     478          10 :     if (m_poGDS->GetAccess() == GA_Update)
     479             :     {
     480           7 :         m_poGDS->FlushCache(false);
     481           7 :         VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
     482             :     }
     483             : 
     484             :     // Get strip offsets.
     485          10 :     toff_t *panTIFFOffsets = nullptr;
     486          10 :     if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPOFFSETS,
     487          20 :                       &panTIFFOffsets) ||
     488          10 :         panTIFFOffsets == nullptr)
     489             :     {
     490           0 :         return nullptr;
     491             :     }
     492             : 
     493          10 :     GPtrDiff_t nBlockSize = static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     494          10 :                             GDALGetDataTypeSizeBytes(eDataType);
     495          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     496           4 :         nBlockSize *= m_poGDS->nBands;
     497             : 
     498          10 :     int nBlocks = m_poGDS->m_nBlocksPerBand;
     499          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     500           6 :         nBlocks *= m_poGDS->nBands;
     501          10 :     int i = 0;  // Used after for.
     502         103 :     for (; i < nBlocks; ++i)
     503             :     {
     504         100 :         if (panTIFFOffsets[i] != 0)
     505           7 :             break;
     506             :     }
     507          10 :     if (i == nBlocks)
     508             :     {
     509             :         // All zeroes.
     510           3 :         if (m_poGDS->eAccess == GA_Update)
     511             :         {
     512             :             // Initialize the file with empty blocks so that the file has
     513             :             // the appropriate size.
     514             : 
     515           3 :             toff_t *panByteCounts = nullptr;
     516           3 :             if (!TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_STRIPBYTECOUNTS,
     517           6 :                               &panByteCounts) ||
     518           3 :                 panByteCounts == nullptr)
     519             :             {
     520           0 :                 return nullptr;
     521             :             }
     522           3 :             if (VSIFSeekL(fp, 0, SEEK_END) != 0)
     523           0 :                 return nullptr;
     524           3 :             vsi_l_offset nBaseOffset = VSIFTellL(fp);
     525             : 
     526             :             // Just write one tile with libtiff to put it in appropriate state.
     527             :             GByte *pabyData =
     528           3 :                 static_cast<GByte *>(VSI_CALLOC_VERBOSE(1, nBlockSize));
     529           3 :             if (pabyData == nullptr)
     530             :             {
     531           0 :                 return nullptr;
     532             :             }
     533           3 :             const auto ret = TIFFWriteEncodedStrip(m_poGDS->m_hTIFF, 0,
     534             :                                                    pabyData, nBlockSize);
     535           3 :             VSI_TIFFFlushBufferedWrite(TIFFClientdata(m_poGDS->m_hTIFF));
     536           3 :             VSIFree(pabyData);
     537           3 :             if (ret != nBlockSize)
     538             :             {
     539           0 :                 return nullptr;
     540             :             }
     541           3 :             CPLAssert(panTIFFOffsets[0] == nBaseOffset);
     542           3 :             CPLAssert(panByteCounts[0] == static_cast<toff_t>(nBlockSize));
     543             : 
     544             :             // Now simulate the writing of other blocks.
     545           3 :             assert(nBlocks > 0);
     546           3 :             assert(static_cast<vsi_l_offset>(nBlockSize) <
     547             :                    std::numeric_limits<vsi_l_offset>::max() / nBlocks);
     548           3 :             const vsi_l_offset nDataSize =
     549           3 :                 static_cast<vsi_l_offset>(nBlockSize) * nBlocks;
     550           3 :             if (VSIFTruncateL(fp, nBaseOffset + nDataSize) != 0)
     551           0 :                 return nullptr;
     552             : 
     553          93 :             for (i = 1; i < nBlocks; ++i)
     554             :             {
     555          90 :                 panTIFFOffsets[i] =
     556          90 :                     nBaseOffset + i * static_cast<toff_t>(nBlockSize);
     557          90 :                 panByteCounts[i] = nBlockSize;
     558             :             }
     559             :         }
     560             :         else
     561             :         {
     562           0 :             CPLDebug("GTiff", "Sparse files not supported in file mapping");
     563           0 :             return nullptr;
     564             :         }
     565             :     }
     566             : 
     567          10 :     GIntBig nBlockSpacing = 0;
     568          10 :     bool bCompatibleSpacing = true;
     569          10 :     toff_t nPrevOffset = 0;
     570         229 :     for (i = 0; i < m_poGDS->m_nBlocksPerBand; ++i)
     571             :     {
     572         219 :         toff_t nCurOffset = 0;
     573         219 :         if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     574          96 :             nCurOffset =
     575          96 :                 panTIFFOffsets[m_poGDS->m_nBlocksPerBand * (nBand - 1) + i];
     576             :         else
     577         123 :             nCurOffset = panTIFFOffsets[i];
     578         219 :         if (nCurOffset == 0)
     579             :         {
     580           0 :             bCompatibleSpacing = false;
     581           0 :             break;
     582             :         }
     583         219 :         if (i > 0)
     584             :         {
     585         209 :             const GIntBig nCurSpacing = nCurOffset - nPrevOffset;
     586         209 :             if (i == 1)
     587             :             {
     588          10 :                 if (nCurSpacing !=
     589          10 :                     static_cast<GIntBig>(nBlockYSize) * nLineSize)
     590             :                 {
     591           0 :                     bCompatibleSpacing = false;
     592           0 :                     break;
     593             :                 }
     594          10 :                 nBlockSpacing = nCurSpacing;
     595             :             }
     596         199 :             else if (nBlockSpacing != nCurSpacing)
     597             :             {
     598           0 :                 bCompatibleSpacing = false;
     599           0 :                 break;
     600             :             }
     601             :         }
     602         219 :         nPrevOffset = nCurOffset;
     603             :     }
     604             : 
     605          10 :     if (!bCompatibleSpacing)
     606             :     {
     607           0 :         return nullptr;
     608             :     }
     609             : 
     610          10 :     vsi_l_offset nOffset = 0;
     611          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     612             :     {
     613           4 :         CPLAssert(m_poGDS->m_pBaseMapping == nullptr);
     614           4 :         nOffset = panTIFFOffsets[0];
     615             :     }
     616             :     else
     617             :     {
     618           6 :         nOffset = panTIFFOffsets[m_poGDS->m_nBlocksPerBand * (nBand - 1)];
     619             :     }
     620          10 :     CPLVirtualMem *pVMem = CPLVirtualMemFileMapNew(
     621             :         fp, nOffset, nLength,
     622             :         eRWFlag == GF_Write ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
     623             :         nullptr, nullptr);
     624          10 :     if (pVMem == nullptr)
     625             :     {
     626           0 :         return nullptr;
     627             :     }
     628             : 
     629          10 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     630             :     {
     631             :         // TODO(schwehr): Revisit this block.
     632           4 :         m_poGDS->m_pBaseMapping = pVMem;
     633           4 :         pVMem = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
     634             :                                           papszOptions);
     635             :         // Drop ref on base mapping.
     636           4 :         CPLVirtualMemFree(m_poGDS->m_pBaseMapping);
     637           4 :         if (pVMem == nullptr)
     638           0 :             m_poGDS->m_pBaseMapping = nullptr;
     639             :     }
     640             :     else
     641             :     {
     642           6 :         *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
     643           6 :         if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     644           0 :             *pnPixelSpace *= m_poGDS->nBands;
     645           6 :         *pnLineSpace = nLineSize;
     646             :     }
     647          10 :     return pVMem;
     648             : }
     649             : 
     650             : /************************************************************************/
     651             : /*                       IGetDataCoverageStatus()                       */
     652             : /************************************************************************/
     653             : 
     654         904 : int GTiffRasterBand::IGetDataCoverageStatus(int nXOff, int nYOff, int nXSize,
     655             :                                             int nYSize, int nMaskFlagStop,
     656             :                                             double *pdfDataPct)
     657             : {
     658         904 :     if (eAccess == GA_Update)
     659          95 :         m_poGDS->FlushCache(false);
     660             : 
     661         904 :     const int iXBlockStart = nXOff / nBlockXSize;
     662         904 :     const int iXBlockEnd = (nXOff + nXSize - 1) / nBlockXSize;
     663         904 :     const int iYBlockStart = nYOff / nBlockYSize;
     664         904 :     const int iYBlockEnd = (nYOff + nYSize - 1) / nBlockYSize;
     665         904 :     int nStatus = 0;
     666         904 :     VSILFILE *fp = VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF));
     667         904 :     GIntBig nPixelsData = 0;
     668        2502 :     for (int iY = iYBlockStart; iY <= iYBlockEnd; ++iY)
     669             :     {
     670        4312 :         for (int iX = iXBlockStart; iX <= iXBlockEnd; ++iX)
     671             :         {
     672        2714 :             const int nBlockIdBand0 = iX + iY * nBlocksPerRow;
     673        2714 :             int nBlockId = nBlockIdBand0;
     674        2714 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     675         136 :                 nBlockId =
     676         136 :                     nBlockIdBand0 + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     677        2714 :             vsi_l_offset nOffset = 0;
     678        2714 :             vsi_l_offset nLength = 0;
     679        2714 :             bool bHasData = false;
     680        2714 :             bool bError = false;
     681        2714 :             if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, &nLength,
     682             :                                            &bError))
     683             :             {
     684        1866 :                 if (bError)
     685         842 :                     return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED;
     686        1866 :                 nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
     687             :             }
     688             :             else
     689             :             {
     690         848 :                 if (m_poGDS->m_nCompression == COMPRESSION_NONE &&
     691         737 :                     m_poGDS->eAccess == GA_ReadOnly &&
     692         695 :                     ((!m_bNoDataSet && !m_bNoDataSetAsInt64 &&
     693         695 :                       !m_bNoDataSetAsUInt64) ||
     694           0 :                      (m_bNoDataSet && m_dfNoDataValue == 0.0) ||
     695           0 :                      (m_bNoDataSetAsInt64 && m_nNoDataValueInt64 == 0) ||
     696           0 :                      (m_bNoDataSetAsUInt64 && m_nNoDataValueUInt64 == 0)))
     697             :                 {
     698             :                     VSIRangeStatus eStatus =
     699         695 :                         VSIFGetRangeStatusL(fp, nOffset, nLength);
     700         695 :                     if (eStatus == VSI_RANGE_STATUS_HOLE)
     701             :                     {
     702           0 :                         nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
     703             :                     }
     704             :                     else
     705             :                     {
     706         695 :                         bHasData = true;
     707         695 :                     }
     708             :                 }
     709             :                 else
     710             :                 {
     711         153 :                     bHasData = true;
     712             :                 }
     713             :             }
     714        2714 :             if (bHasData)
     715             :             {
     716         848 :                 const int nXBlockRight =
     717         848 :                     (iX * nBlockXSize > INT_MAX - nBlockXSize)
     718         848 :                         ? INT_MAX
     719         848 :                         : (iX + 1) * nBlockXSize;
     720         848 :                 const int nYBlockBottom =
     721         848 :                     (iY * nBlockYSize > INT_MAX - nBlockYSize)
     722         848 :                         ? INT_MAX
     723         848 :                         : (iY + 1) * nBlockYSize;
     724             : 
     725        1696 :                 nPixelsData += (static_cast<GIntBig>(
     726         848 :                                     std::min(nXBlockRight, nXOff + nXSize)) -
     727         848 :                                 std::max(iX * nBlockXSize, nXOff)) *
     728         848 :                                (std::min(nYBlockBottom, nYOff + nYSize) -
     729         848 :                                 std::max(iY * nBlockYSize, nYOff));
     730         848 :                 nStatus |= GDAL_DATA_COVERAGE_STATUS_DATA;
     731             :             }
     732        2714 :             if (nMaskFlagStop != 0 && (nMaskFlagStop & nStatus) != 0)
     733             :             {
     734         842 :                 if (pdfDataPct)
     735           0 :                     *pdfDataPct = -1.0;
     736         842 :                 return nStatus;
     737             :             }
     738             :         }
     739             :     }
     740          62 :     if (pdfDataPct)
     741           8 :         *pdfDataPct =
     742           8 :             100.0 * nPixelsData / (static_cast<GIntBig>(nXSize) * nYSize);
     743          62 :     return nStatus;
     744             : }
     745             : 
     746             : /************************************************************************/
     747             : /*                             IReadBlock()                             */
     748             : /************************************************************************/
     749             : 
     750     2318530 : CPLErr GTiffRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     751             : 
     752             : {
     753     2318530 :     m_poGDS->Crystalize();
     754             : 
     755     2318530 :     GPtrDiff_t nBlockBufSize = 0;
     756     2318530 :     if (TIFFIsTiled(m_poGDS->m_hTIFF))
     757             :     {
     758       58194 :         nBlockBufSize = static_cast<GPtrDiff_t>(TIFFTileSize(m_poGDS->m_hTIFF));
     759             :     }
     760             :     else
     761             :     {
     762     2260340 :         CPLAssert(nBlockXOff == 0);
     763             :         nBlockBufSize =
     764     2260340 :             static_cast<GPtrDiff_t>(TIFFStripSize(m_poGDS->m_hTIFF));
     765             :     }
     766             : 
     767     2318530 :     const int nBlockId = ComputeBlockId(nBlockXOff, nBlockYOff);
     768             : 
     769             :     /* -------------------------------------------------------------------- */
     770             :     /*      The bottom most partial tiles and strips are sometimes only     */
     771             :     /*      partially encoded.  This code reduces the requested data so     */
     772             :     /*      an error won't be reported in this case. (#1179)                */
     773             :     /* -------------------------------------------------------------------- */
     774     2318530 :     auto nBlockReqSize = nBlockBufSize;
     775             : 
     776     2318530 :     if (nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize)
     777             :     {
     778        6463 :         nBlockReqSize =
     779        6463 :             (nBlockBufSize / nBlockYSize) *
     780        6463 :             (nBlockYSize -
     781             :              static_cast<int>(
     782        6463 :                  (static_cast<GIntBig>(nBlockYOff + 1) * nBlockYSize) %
     783        6463 :                  nRasterYSize));
     784             :     }
     785             : 
     786             :     /* -------------------------------------------------------------------- */
     787             :     /*      Handle the case of a strip or tile that doesn't exist yet.      */
     788             :     /*      Just set to zeros and return.                                   */
     789             :     /* -------------------------------------------------------------------- */
     790     2318530 :     vsi_l_offset nOffset = 0;
     791     2318530 :     bool bErrOccurred = false;
     792     4504090 :     if (nBlockId != m_poGDS->m_nLoadedBlock &&
     793     2185560 :         !m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr, &bErrOccurred))
     794             :     {
     795       52879 :         NullBlock(pImage);
     796       52879 :         if (bErrOccurred)
     797           1 :             return CE_Failure;
     798       52878 :         return CE_None;
     799             :     }
     800             : 
     801     2265650 :     if (m_poGDS->m_bStreamingIn &&
     802       10936 :         !(m_poGDS->nBands > 1 &&
     803       10423 :           m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG &&
     804       10048 :           nBlockId == m_poGDS->m_nLoadedBlock))
     805             :     {
     806        3436 :         if (nOffset < VSIFTellL(m_poGDS->m_fpL))
     807             :         {
     808        2000 :             ReportError(CE_Failure, CPLE_NotSupported,
     809             :                         "Trying to load block %d at offset " CPL_FRMT_GUIB
     810             :                         " whereas current pos is " CPL_FRMT_GUIB
     811             :                         " (backward read not supported)",
     812             :                         nBlockId, static_cast<GUIntBig>(nOffset),
     813        1000 :                         static_cast<GUIntBig>(VSIFTellL(m_poGDS->m_fpL)));
     814        1000 :             return CE_Failure;
     815             :         }
     816             :     }
     817             : 
     818             :     /* -------------------------------------------------------------------- */
     819             :     /*      Handle simple case (separate, onesampleperpixel)                */
     820             :     /* -------------------------------------------------------------------- */
     821     2264650 :     CPLErr eErr = CE_None;
     822     2264650 :     if (m_poGDS->nBands == 1 ||
     823      209030 :         m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     824             :     {
     825     2081000 :         if (nBlockReqSize < nBlockBufSize)
     826        3024 :             memset(pImage, 0, nBlockBufSize);
     827             : 
     828     2081000 :         if (!m_poGDS->ReadStrile(nBlockId, pImage, nBlockReqSize))
     829             :         {
     830          81 :             memset(pImage, 0, nBlockBufSize);
     831          81 :             return CE_Failure;
     832             :         }
     833             :     }
     834             :     else
     835             :     {
     836             :         /* --------------------------------------------------------------------
     837             :          */
     838             :         /*      Load desired block */
     839             :         /* --------------------------------------------------------------------
     840             :          */
     841      183656 :         eErr = m_poGDS->LoadBlockBuf(nBlockId);
     842      183656 :         if (eErr != CE_None)
     843             :         {
     844          26 :             memset(pImage, 0,
     845          52 :                    static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     846          26 :                        GDALGetDataTypeSizeBytes(eDataType));
     847          26 :             return eErr;
     848             :         }
     849             : 
     850      183630 :         bool bDoCopyWords = true;
     851       52169 :         if (nBand == 1 && !m_poGDS->m_bLoadingOtherBands &&
     852       46470 :             eAccess == GA_ReadOnly &&
     853       37202 :             (m_poGDS->nBands == 3 || m_poGDS->nBands == 4) &&
     854       36417 :             ((eDataType == GDT_UInt8 && m_poGDS->m_nBitsPerSample == 8) ||
     855         436 :              (eDataType == GDT_Int16 && m_poGDS->m_nBitsPerSample == 16) ||
     856      236069 :              (eDataType == GDT_UInt16 && m_poGDS->m_nBitsPerSample == 16)) &&
     857       72508 :             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     858       36254 :                     GDALGetDataTypeSizeBytes(eDataType) <
     859       36254 :                 GDALGetCacheMax64() / m_poGDS->nBands)
     860             :         {
     861       36254 :             bDoCopyWords = false;
     862             :             void *ppDestBuffers[4];
     863       36254 :             GDALRasterBlock *apoLockedBlocks[4] = {nullptr, nullptr, nullptr,
     864             :                                                    nullptr};
     865      156159 :             for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
     866             :             {
     867      119905 :                 if (iBand == nBand)
     868             :                 {
     869       36254 :                     ppDestBuffers[iBand - 1] = pImage;
     870             :                 }
     871             :                 else
     872             :                 {
     873             :                     GDALRasterBlock *poBlock =
     874       83651 :                         m_poGDS->GetRasterBand(iBand)->GetLockedBlockRef(
     875       83651 :                             nBlockXOff, nBlockYOff, true);
     876       83651 :                     if (poBlock == nullptr)
     877             :                     {
     878           0 :                         bDoCopyWords = true;
     879           0 :                         break;
     880             :                     }
     881       83651 :                     ppDestBuffers[iBand - 1] = poBlock->GetDataRef();
     882       83651 :                     apoLockedBlocks[iBand - 1] = poBlock;
     883             :                 }
     884             :             }
     885       36254 :             if (!bDoCopyWords)
     886             :             {
     887       36254 :                 GDALDeinterleave(m_poGDS->m_pabyBlockBuf, eDataType,
     888       36254 :                                  m_poGDS->nBands, ppDestBuffers, eDataType,
     889       36254 :                                  static_cast<size_t>(nBlockXSize) *
     890       36254 :                                      nBlockYSize);
     891             :             }
     892      156159 :             for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
     893             :             {
     894      119905 :                 if (apoLockedBlocks[iBand - 1])
     895             :                 {
     896       83651 :                     apoLockedBlocks[iBand - 1]->DropLock();
     897             :                 }
     898             :             }
     899             :         }
     900             : 
     901      183630 :         if (bDoCopyWords)
     902             :         {
     903      147376 :             const int nWordBytes = m_poGDS->m_nBitsPerSample / 8;
     904      147376 :             GByte *pabyImage =
     905      147376 :                 m_poGDS->m_pabyBlockBuf + (nBand - 1) * nWordBytes;
     906             : 
     907      147376 :             GDALCopyWords64(pabyImage, eDataType, m_poGDS->nBands * nWordBytes,
     908             :                             pImage, eDataType, nWordBytes,
     909      147376 :                             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize);
     910             : 
     911      147376 :             eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
     912             :         }
     913             :     }
     914             : 
     915     2264550 :     CacheMaskForBlock(nBlockXOff, nBlockYOff);
     916             : 
     917     2264550 :     return eErr;
     918             : }
     919             : 
     920             : /************************************************************************/
     921             : /*                         CacheMaskForBlock()                          */
     922             : /************************************************************************/
     923             : 
     924     2266930 : void GTiffRasterBand::CacheMaskForBlock(int nBlockXOff, int nBlockYOff)
     925             : 
     926             : {
     927             :     // Preload mask data if layout compatible and we have cached ranges
     928     2267040 :     if (m_poGDS->m_bMaskInterleavedWithImagery && m_poGDS->m_poMaskDS &&
     929         108 :         VSI_TIFFHasCachedRanges(TIFFClientdata(m_poGDS->m_hTIFF)))
     930             :     {
     931          97 :         auto poBand = cpl::down_cast<GTiffRasterBand *>(
     932          97 :             m_poGDS->m_poMaskDS->GetRasterBand(1));
     933          97 :         if (m_poGDS->m_poMaskDS->m_oCacheStrileToOffsetByteCount.contains(
     934          97 :                 poBand->ComputeBlockId(nBlockXOff, nBlockYOff)))
     935             :         {
     936             :             GDALRasterBlock *poBlock =
     937          93 :                 poBand->GetLockedBlockRef(nBlockXOff, nBlockYOff);
     938          93 :             if (poBlock)
     939          93 :                 poBlock->DropLock();
     940             :         }
     941             :     }
     942     2266930 : }
     943             : 
     944             : /************************************************************************/
     945             : /*                       FillCacheForOtherBands()                       */
     946             : /************************************************************************/
     947             : 
     948      147590 : CPLErr GTiffRasterBand::FillCacheForOtherBands(int nBlockXOff, int nBlockYOff)
     949             : 
     950             : {
     951             :     /* -------------------------------------------------------------------- */
     952             :     /*      In the fairly common case of pixel interleaved 8bit data        */
     953             :     /*      that is multi-band, lets push the rest of the data into the     */
     954             :     /*      block cache too, to avoid (hopefully) having to redecode it.    */
     955             :     /*                                                                      */
     956             :     /*      Our following logic actually depends on the fact that the       */
     957             :     /*      this block is already loaded, so subsequent calls will end      */
     958             :     /*      up back in this method and pull from the loaded block.          */
     959             :     /*                                                                      */
     960             :     /*      Be careful not entering this portion of code from               */
     961             :     /*      the other bands, otherwise we'll get very deep nested calls     */
     962             :     /*      and O(nBands^2) performance !                                   */
     963             :     /*                                                                      */
     964             :     /*      If there are many bands and the block cache size is not big     */
     965             :     /*      enough to accommodate the size of all the blocks, don't enter   */
     966             :     /* -------------------------------------------------------------------- */
     967      147590 :     CPLErr eErr = CE_None;
     968      442770 :     if (m_poGDS->nBands != 1 &&
     969      147590 :         m_poGDS->nBands <
     970       49156 :             128 &&  // avoid caching for datasets with too many bands
     971      308108 :         !m_poGDS->m_bLoadingOtherBands &&
     972       25856 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     973       12928 :                 GDALGetDataTypeSizeBytes(eDataType) <
     974       12928 :             GDALGetCacheMax64() / m_poGDS->nBands)
     975             :     {
     976       12928 :         m_poGDS->m_bLoadingOtherBands = true;
     977             : 
     978       53048 :         for (int iOtherBand = 1; iOtherBand <= m_poGDS->nBands; ++iOtherBand)
     979             :         {
     980       40120 :             if (iOtherBand == nBand)
     981       12928 :                 continue;
     982             : 
     983             :             GDALRasterBlock *poBlock =
     984       27192 :                 m_poGDS->GetRasterBand(iOtherBand)
     985       27192 :                     ->GetLockedBlockRef(nBlockXOff, nBlockYOff);
     986       27192 :             if (poBlock == nullptr)
     987             :             {
     988           0 :                 eErr = CE_Failure;
     989           0 :                 break;
     990             :             }
     991       27192 :             poBlock->DropLock();
     992             :         }
     993             : 
     994       12928 :         m_poGDS->m_bLoadingOtherBands = false;
     995             :     }
     996             : 
     997      147590 :     return eErr;
     998             : }
     999             : 
    1000             : /************************************************************************/
    1001             : /*                           GetDescription()                           */
    1002             : /************************************************************************/
    1003             : 
    1004      310910 : const char *GTiffRasterBand::GetDescription() const
    1005             : {
    1006      310910 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1007             : 
    1008      310910 :     return m_osDescription;
    1009             : }
    1010             : 
    1011             : /************************************************************************/
    1012             : /*                             GetOffset()                              */
    1013             : /************************************************************************/
    1014             : 
    1015      316377 : double GTiffRasterBand::GetOffset(int *pbSuccess)
    1016             : 
    1017             : {
    1018      316377 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1019             : 
    1020      316377 :     if (pbSuccess)
    1021        7763 :         *pbSuccess = m_bHaveOffsetScale;
    1022      316377 :     return m_dfOffset;
    1023             : }
    1024             : 
    1025             : /************************************************************************/
    1026             : /*                              GetScale()                              */
    1027             : /************************************************************************/
    1028             : 
    1029      316380 : double GTiffRasterBand::GetScale(int *pbSuccess)
    1030             : 
    1031             : {
    1032      316380 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1033             : 
    1034      316380 :     if (pbSuccess)
    1035        7766 :         *pbSuccess = m_bHaveOffsetScale;
    1036      316380 :     return m_dfScale;
    1037             : }
    1038             : 
    1039             : /************************************************************************/
    1040             : /*                            GetUnitType()                             */
    1041             : /************************************************************************/
    1042             : 
    1043      307349 : const char *GTiffRasterBand::GetUnitType()
    1044             : 
    1045             : {
    1046      307349 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1047      307349 :     if (m_osUnitType.empty())
    1048             :     {
    1049      307148 :         m_poGDS->LookForProjection();
    1050      307148 :         if (m_poGDS->m_pszVertUnit)
    1051           9 :             return m_poGDS->m_pszVertUnit;
    1052             :     }
    1053             : 
    1054      307340 :     return m_osUnitType.c_str();
    1055             : }
    1056             : 
    1057             : /************************************************************************/
    1058             : /*                       GetMetadataDomainList()                        */
    1059             : /************************************************************************/
    1060             : 
    1061          13 : char **GTiffRasterBand::GetMetadataDomainList()
    1062             : {
    1063          13 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1064             : 
    1065          13 :     m_poGDS->LoadENVIHdrIfNeeded();
    1066             : 
    1067          13 :     return CSLDuplicate(m_oGTiffMDMD.GetDomainList());
    1068             : }
    1069             : 
    1070             : /************************************************************************/
    1071             : /*                            GetMetadata()                             */
    1072             : /************************************************************************/
    1073             : 
    1074       20093 : CSLConstList GTiffRasterBand::GetMetadata(const char *pszDomain)
    1075             : 
    1076             : {
    1077       20093 :     if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
    1078             :     {
    1079       19905 :         m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1080             : 
    1081       19905 :         m_poGDS->LoadENVIHdrIfNeeded();
    1082             :     }
    1083         188 :     else if (EQUAL(pszDomain, MD_DOMAIN_IMAGERY))
    1084             :     {
    1085           0 :         m_poGDS->LoadENVIHdrIfNeeded();
    1086             :     }
    1087             : 
    1088       20093 :     return m_oGTiffMDMD.GetMetadata(pszDomain);
    1089             : }
    1090             : 
    1091             : /************************************************************************/
    1092             : /*                          GetMetadataItem()                           */
    1093             : /************************************************************************/
    1094             : 
    1095       23961 : const char *GTiffRasterBand::GetMetadataItem(const char *pszName,
    1096             :                                              const char *pszDomain)
    1097             : 
    1098             : {
    1099       23961 :     if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
    1100             :     {
    1101        9259 :         m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1102             : 
    1103        9259 :         m_poGDS->LoadENVIHdrIfNeeded();
    1104             :     }
    1105       14702 :     else if (EQUAL(pszDomain, MD_DOMAIN_IMAGERY))
    1106             :     {
    1107           0 :         m_poGDS->LoadENVIHdrIfNeeded();
    1108             :     }
    1109             : 
    1110       23961 :     if (pszName != nullptr && pszDomain != nullptr && EQUAL(pszDomain, "TIFF"))
    1111             :     {
    1112        5242 :         int nBlockXOff = 0;
    1113        5242 :         int nBlockYOff = 0;
    1114             : 
    1115        5242 :         if (EQUAL(pszName, "JPEGTABLES"))
    1116             :         {
    1117          11 :             uint32_t nJPEGTableSize = 0;
    1118          11 :             void *pJPEGTable = nullptr;
    1119          11 :             if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_JPEGTABLES,
    1120          11 :                              &nJPEGTableSize, &pJPEGTable) != 1 ||
    1121          11 :                 pJPEGTable == nullptr || nJPEGTableSize > INT_MAX)
    1122             :             {
    1123           0 :                 return nullptr;
    1124             :             }
    1125          11 :             char *const pszHex = CPLBinaryToHex(
    1126             :                 nJPEGTableSize, static_cast<const GByte *>(pJPEGTable));
    1127          11 :             const char *pszReturn = CPLSPrintf("%s", pszHex);
    1128          11 :             CPLFree(pszHex);
    1129             : 
    1130          11 :             return pszReturn;
    1131             :         }
    1132             : 
    1133        5231 :         if (EQUAL(pszName, "IFD_OFFSET"))
    1134             :         {
    1135         178 :             return CPLSPrintf(CPL_FRMT_GUIB,
    1136          89 :                               static_cast<GUIntBig>(m_poGDS->m_nDirOffset));
    1137             :         }
    1138             : 
    1139        5142 :         if (sscanf(pszName, "BLOCK_OFFSET_%d_%d", &nBlockXOff, &nBlockYOff) ==
    1140             :             2)
    1141             :         {
    1142        4422 :             if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
    1143        4421 :                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
    1144          19 :                 return nullptr;
    1145             : 
    1146        4403 :             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
    1147        4403 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
    1148             :             {
    1149        3592 :                 nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
    1150             :             }
    1151             : 
    1152        4403 :             vsi_l_offset nOffset = 0;
    1153        4403 :             if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr,
    1154             :                                            nullptr))
    1155             :             {
    1156         185 :                 return nullptr;
    1157             :             }
    1158             : 
    1159        4218 :             return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nOffset));
    1160             :         }
    1161             : 
    1162         720 :         if (sscanf(pszName, "BLOCK_SIZE_%d_%d", &nBlockXOff, &nBlockYOff) == 2)
    1163             :         {
    1164         720 :             if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
    1165         719 :                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
    1166           2 :                 return nullptr;
    1167             : 
    1168         718 :             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
    1169         718 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
    1170             :             {
    1171         244 :                 nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
    1172             :             }
    1173             : 
    1174         718 :             vsi_l_offset nByteCount = 0;
    1175         718 :             if (!m_poGDS->IsBlockAvailable(nBlockId, nullptr, &nByteCount,
    1176             :                                            nullptr))
    1177             :             {
    1178          87 :                 return nullptr;
    1179             :             }
    1180             : 
    1181         631 :             return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nByteCount));
    1182           0 :         }
    1183             :     }
    1184       18719 :     else if (pszName && pszDomain && EQUAL(pszDomain, "_DEBUG_"))
    1185             :     {
    1186         131 :         if (EQUAL(pszName, "HAS_BLOCK_CACHE"))
    1187         131 :             return HasBlockCache() ? "1" : "0";
    1188             :     }
    1189             : 
    1190       18588 :     const char *pszRet = m_oGTiffMDMD.GetMetadataItem(pszName, pszDomain);
    1191             : 
    1192       18588 :     if (pszRet == nullptr && eDataType == GDT_UInt8 && pszName && pszDomain &&
    1193       15962 :         EQUAL(pszDomain, "IMAGE_STRUCTURE") && EQUAL(pszName, "PIXELTYPE"))
    1194             :     {
    1195             :         // to get a chance of emitting the warning about this legacy usage
    1196        3716 :         pszRet = GDALRasterBand::GetMetadataItem(pszName, pszDomain);
    1197             :     }
    1198       18588 :     return pszRet;
    1199             : }
    1200             : 
    1201             : /************************************************************************/
    1202             : /*                       GetColorInterpretation()                       */
    1203             : /************************************************************************/
    1204             : 
    1205      461680 : GDALColorInterp GTiffRasterBand::GetColorInterpretation()
    1206             : 
    1207             : {
    1208      461680 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1209             : 
    1210      461680 :     return m_eBandInterp;
    1211             : }
    1212             : 
    1213             : /************************************************************************/
    1214             : /*                           GetColorTable()                            */
    1215             : /************************************************************************/
    1216             : 
    1217       12531 : GDALColorTable *GTiffRasterBand::GetColorTable()
    1218             : 
    1219             : {
    1220       12531 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1221             : 
    1222       12531 :     if (nBand == 1)
    1223       10545 :         return m_poGDS->m_poColorTable.get();
    1224             : 
    1225        1986 :     return nullptr;
    1226             : }
    1227             : 
    1228             : /************************************************************************/
    1229             : /*                           GetNoDataValue()                           */
    1230             : /************************************************************************/
    1231             : 
    1232      957144 : double GTiffRasterBand::GetNoDataValue(int *pbSuccess)
    1233             : 
    1234             : {
    1235      957144 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1236             : 
    1237      957144 :     int bSuccess = FALSE;
    1238      957144 :     double dfNoDataValue = GDALPamRasterBand::GetNoDataValue(&bSuccess);
    1239      957144 :     if (bSuccess)
    1240             :     {
    1241           4 :         if (pbSuccess)
    1242           4 :             *pbSuccess = TRUE;
    1243             : 
    1244           4 :         return dfNoDataValue;
    1245             :     }
    1246             : 
    1247      957140 :     if (m_bNoDataSet)
    1248             :     {
    1249        4999 :         if (pbSuccess)
    1250        4952 :             *pbSuccess = TRUE;
    1251             : 
    1252        4999 :         return m_dfNoDataValue;
    1253             :     }
    1254             : 
    1255      952141 :     if (m_poGDS->m_bNoDataSet)
    1256             :     {
    1257      423522 :         if (pbSuccess)
    1258      423296 :             *pbSuccess = TRUE;
    1259             : 
    1260      423522 :         return m_poGDS->m_dfNoDataValue;
    1261             :     }
    1262             : 
    1263      528619 :     if (m_bNoDataSetAsInt64)
    1264             :     {
    1265           0 :         if (pbSuccess)
    1266           0 :             *pbSuccess = TRUE;
    1267             : 
    1268           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
    1269             :     }
    1270             : 
    1271      528619 :     if (m_poGDS->m_bNoDataSetAsInt64)
    1272             :     {
    1273           0 :         if (pbSuccess)
    1274           0 :             *pbSuccess = TRUE;
    1275             : 
    1276           0 :         return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueInt64);
    1277             :     }
    1278             : 
    1279      528619 :     if (m_bNoDataSetAsUInt64)
    1280             :     {
    1281           0 :         if (pbSuccess)
    1282           0 :             *pbSuccess = TRUE;
    1283             : 
    1284           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
    1285             :     }
    1286             : 
    1287      528619 :     if (m_poGDS->m_bNoDataSetAsUInt64)
    1288             :     {
    1289           0 :         if (pbSuccess)
    1290           0 :             *pbSuccess = TRUE;
    1291             : 
    1292           0 :         return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueUInt64);
    1293             :     }
    1294             : 
    1295      528619 :     if (pbSuccess)
    1296      528479 :         *pbSuccess = FALSE;
    1297      528619 :     return dfNoDataValue;
    1298             : }
    1299             : 
    1300             : /************************************************************************/
    1301             : /*                       GetNoDataValueAsInt64()                        */
    1302             : /************************************************************************/
    1303             : 
    1304          64 : int64_t GTiffRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
    1305             : 
    1306             : {
    1307          64 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1308             : 
    1309          64 :     if (eDataType == GDT_UInt64)
    1310             :     {
    1311           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1312             :                  "GetNoDataValueAsUInt64() should be called instead");
    1313           0 :         if (pbSuccess)
    1314           0 :             *pbSuccess = FALSE;
    1315           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1316             :     }
    1317          64 :     if (eDataType != GDT_Int64)
    1318             :     {
    1319           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1320             :                  "GetNoDataValue() should be called instead");
    1321           0 :         if (pbSuccess)
    1322           0 :             *pbSuccess = FALSE;
    1323           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1324             :     }
    1325             : 
    1326          64 :     int bSuccess = FALSE;
    1327             :     const auto nNoDataValue =
    1328          64 :         GDALPamRasterBand::GetNoDataValueAsInt64(&bSuccess);
    1329          64 :     if (bSuccess)
    1330             :     {
    1331           0 :         if (pbSuccess)
    1332           0 :             *pbSuccess = TRUE;
    1333             : 
    1334           0 :         return nNoDataValue;
    1335             :     }
    1336             : 
    1337          64 :     if (m_bNoDataSetAsInt64)
    1338             :     {
    1339           2 :         if (pbSuccess)
    1340           2 :             *pbSuccess = TRUE;
    1341             : 
    1342           2 :         return m_nNoDataValueInt64;
    1343             :     }
    1344             : 
    1345          62 :     if (m_poGDS->m_bNoDataSetAsInt64)
    1346             :     {
    1347          11 :         if (pbSuccess)
    1348          10 :             *pbSuccess = TRUE;
    1349             : 
    1350          11 :         return m_poGDS->m_nNoDataValueInt64;
    1351             :     }
    1352             : 
    1353          51 :     if (pbSuccess)
    1354          51 :         *pbSuccess = FALSE;
    1355          51 :     return nNoDataValue;
    1356             : }
    1357             : 
    1358             : /************************************************************************/
    1359             : /*                       GetNoDataValueAsUInt64()                       */
    1360             : /************************************************************************/
    1361             : 
    1362          46 : uint64_t GTiffRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
    1363             : 
    1364             : {
    1365          46 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1366             : 
    1367          46 :     if (eDataType == GDT_Int64)
    1368             :     {
    1369           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1370             :                  "GetNoDataValueAsInt64() should be called instead");
    1371           0 :         if (pbSuccess)
    1372           0 :             *pbSuccess = FALSE;
    1373           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1374             :     }
    1375          46 :     if (eDataType != GDT_UInt64)
    1376             :     {
    1377           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1378             :                  "GetNoDataValue() should be called instead");
    1379           0 :         if (pbSuccess)
    1380           0 :             *pbSuccess = FALSE;
    1381           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1382             :     }
    1383             : 
    1384          46 :     int bSuccess = FALSE;
    1385             :     const auto nNoDataValue =
    1386          46 :         GDALPamRasterBand::GetNoDataValueAsUInt64(&bSuccess);
    1387          46 :     if (bSuccess)
    1388             :     {
    1389           0 :         if (pbSuccess)
    1390           0 :             *pbSuccess = TRUE;
    1391             : 
    1392           0 :         return nNoDataValue;
    1393             :     }
    1394             : 
    1395          46 :     if (m_bNoDataSetAsUInt64)
    1396             :     {
    1397           4 :         if (pbSuccess)
    1398           4 :             *pbSuccess = TRUE;
    1399             : 
    1400           4 :         return m_nNoDataValueUInt64;
    1401             :     }
    1402             : 
    1403          42 :     if (m_poGDS->m_bNoDataSetAsUInt64)
    1404             :     {
    1405           7 :         if (pbSuccess)
    1406           6 :             *pbSuccess = TRUE;
    1407             : 
    1408           7 :         return m_poGDS->m_nNoDataValueUInt64;
    1409             :     }
    1410             : 
    1411          35 :     if (pbSuccess)
    1412          35 :         *pbSuccess = FALSE;
    1413          35 :     return nNoDataValue;
    1414             : }
    1415             : 
    1416             : /************************************************************************/
    1417             : /*                          GetOverviewCount()                          */
    1418             : /************************************************************************/
    1419             : 
    1420     1320040 : int GTiffRasterBand::GetOverviewCount()
    1421             : 
    1422             : {
    1423     1320040 :     if (!m_poGDS->AreOverviewsEnabled())
    1424          30 :         return 0;
    1425             : 
    1426     1320010 :     m_poGDS->ScanDirectories();
    1427             : 
    1428     1320010 :     if (!m_poGDS->m_apoOverviewDS.empty())
    1429             :     {
    1430      267339 :         return static_cast<int>(m_poGDS->m_apoOverviewDS.size());
    1431             :     }
    1432             : 
    1433     1052670 :     const int nOverviewCount = GDALRasterBand::GetOverviewCount();
    1434     1052670 :     if (nOverviewCount > 0)
    1435         391 :         return nOverviewCount;
    1436             : 
    1437             :     // Implicit JPEG overviews are normally hidden, except when doing
    1438             :     // IRasterIO() operations.
    1439     1052280 :     if (m_poGDS->m_nJPEGOverviewVisibilityCounter)
    1440     1044190 :         return m_poGDS->GetJPEGOverviewCount();
    1441             : 
    1442        8092 :     return 0;
    1443             : }
    1444             : 
    1445             : /************************************************************************/
    1446             : /*                            GetOverview()                             */
    1447             : /************************************************************************/
    1448             : 
    1449       74187 : GDALRasterBand *GTiffRasterBand::GetOverview(int i)
    1450             : 
    1451             : {
    1452       74187 :     m_poGDS->ScanDirectories();
    1453             : 
    1454       74187 :     if (!m_poGDS->m_apoOverviewDS.empty())
    1455             :     {
    1456             :         // Do we have internal overviews?
    1457       73591 :         if (i < 0 || static_cast<size_t>(i) >= m_poGDS->m_apoOverviewDS.size())
    1458           8 :             return nullptr;
    1459             : 
    1460       73583 :         return m_poGDS->m_apoOverviewDS[i]->GetRasterBand(nBand);
    1461             :     }
    1462             : 
    1463         596 :     GDALRasterBand *const poOvrBand = GDALRasterBand::GetOverview(i);
    1464         596 :     if (poOvrBand != nullptr)
    1465         391 :         return poOvrBand;
    1466             : 
    1467             :     // For consistency with GetOverviewCount(), we should also test
    1468             :     // m_nJPEGOverviewVisibilityCounter, but it is also convenient to be able
    1469             :     // to query them for testing purposes.
    1470         205 :     if (i >= 0 && i < m_poGDS->GetJPEGOverviewCount())
    1471         164 :         return m_poGDS->m_apoJPEGOverviewDS[i]->GetRasterBand(nBand);
    1472             : 
    1473          41 :     return nullptr;
    1474             : }
    1475             : 
    1476             : /************************************************************************/
    1477             : /*                            GetMaskFlags()                            */
    1478             : /************************************************************************/
    1479             : 
    1480       22590 : int GTiffRasterBand::GetMaskFlags()
    1481             : {
    1482       22590 :     m_poGDS->ScanDirectories();
    1483             : 
    1484       22590 :     if (m_poGDS->m_poExternalMaskDS != nullptr)
    1485             :     {
    1486           0 :         return GMF_PER_DATASET;
    1487             :     }
    1488             : 
    1489       22590 :     if (m_poGDS->m_poMaskDS != nullptr)
    1490             :     {
    1491         222 :         if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
    1492             :         {
    1493         214 :             return GMF_PER_DATASET;
    1494             :         }
    1495             : 
    1496           8 :         return 0;
    1497             :     }
    1498             : 
    1499       22368 :     if (m_poGDS->m_bIsOverview)
    1500             :     {
    1501         444 :         return m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskFlags();
    1502             :     }
    1503             : 
    1504       21924 :     return GDALPamRasterBand::GetMaskFlags();
    1505             : }
    1506             : 
    1507             : /************************************************************************/
    1508             : /*                            GetMaskBand()                             */
    1509             : /************************************************************************/
    1510             : 
    1511      117846 : GDALRasterBand *GTiffRasterBand::GetMaskBand()
    1512             : {
    1513      117846 :     m_poGDS->ScanDirectories();
    1514             : 
    1515      117846 :     if (m_poGDS->m_poExternalMaskDS != nullptr)
    1516             :     {
    1517          31 :         return m_poGDS->m_poExternalMaskDS->GetRasterBand(1);
    1518             :     }
    1519             : 
    1520      117815 :     if (m_poGDS->m_poMaskDS != nullptr)
    1521             :     {
    1522         691 :         if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
    1523         674 :             return m_poGDS->m_poMaskDS->GetRasterBand(1);
    1524             : 
    1525          17 :         return m_poGDS->m_poMaskDS->GetRasterBand(nBand);
    1526             :     }
    1527             : 
    1528      117124 :     if (m_poGDS->m_bIsOverview)
    1529             :     {
    1530             :         GDALRasterBand *poBaseMask =
    1531         119 :             m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskBand();
    1532         119 :         if (poBaseMask)
    1533             :         {
    1534         119 :             const int nOverviews = poBaseMask->GetOverviewCount();
    1535         164 :             for (int i = 0; i < nOverviews; i++)
    1536             :             {
    1537          93 :                 GDALRasterBand *poOvr = poBaseMask->GetOverview(i);
    1538         141 :                 if (poOvr && poOvr->GetXSize() == GetXSize() &&
    1539          48 :                     poOvr->GetYSize() == GetYSize())
    1540             :                 {
    1541          48 :                     return poOvr;
    1542             :                 }
    1543             :             }
    1544             :         }
    1545             :     }
    1546             : 
    1547      117076 :     return GDALPamRasterBand::GetMaskBand();
    1548             : }
    1549             : 
    1550             : /************************************************************************/
    1551             : /*                             IsMaskBand()                             */
    1552             : /************************************************************************/
    1553             : 
    1554        1039 : bool GTiffRasterBand::IsMaskBand() const
    1555             : {
    1556        1071 :     return (m_poGDS->m_poImageryDS != nullptr &&
    1557          32 :             m_poGDS->m_poImageryDS->m_poMaskDS.get() == m_poGDS) ||
    1558        2023 :            m_eBandInterp == GCI_AlphaBand ||
    1559        1991 :            m_poGDS->GetMetadataItem("INTERNAL_MASK_FLAGS_1") != nullptr;
    1560             : }
    1561             : 
    1562             : /************************************************************************/
    1563             : /*                         GetMaskValueRange()                          */
    1564             : /************************************************************************/
    1565             : 
    1566           0 : GDALMaskValueRange GTiffRasterBand::GetMaskValueRange() const
    1567             : {
    1568           0 :     if (!IsMaskBand())
    1569           0 :         return GMVR_UNKNOWN;
    1570           0 :     if (m_poGDS->m_nBitsPerSample == 1)
    1571           0 :         return m_poGDS->m_bPromoteTo8Bits ? GMVR_0_AND_255_ONLY
    1572           0 :                                           : GMVR_0_AND_1_ONLY;
    1573           0 :     return GMVR_UNKNOWN;
    1574             : }

Generated by: LCOV version 1.14