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-02-09 23:21:11 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      307980 : GDALRasterAttributeTable *GTiffRasterBand::GetDefaultRAT()
      37             : 
      38             : {
      39      307980 :     if (m_poGDS->m_poBaseDS != nullptr)
      40          52 :         return m_poRAT.get();
      41             : 
      42      307928 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
      43             : 
      44             :     // RAT from PAM has priority over RAT in GDAL_METADATA TIFF tag
      45      307928 :     if (!m_bRATTriedReadingFromPAM)
      46             :     {
      47      305781 :         m_bRATTriedReadingFromPAM = true;
      48      305781 :         auto poRAT = GDALPamRasterBand::GetDefaultRAT();
      49      305781 :         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      307926 :     if (m_bRATSet)
      58        2164 :         return m_poRAT.get();
      59             : 
      60      305762 :     m_bRATSet = true;
      61             : 
      62             :     // Try reading from a .vat.dbf side car file
      63      305762 :     if (!GDALCanFileAcceptSidecarFile(m_poGDS->m_osFilename.c_str()))
      64           0 :         return nullptr;
      65      611524 :     const std::string osVATDBF = m_poGDS->m_osFilename + ".vat.dbf";
      66      305762 :     CSLConstList papszSiblingFiles = m_poGDS->GetSiblingFiles();
      67      611487 :     if (papszSiblingFiles &&
      68             :         // cppcheck-suppress knownConditionTrueFalse
      69      305725 :         GDALCanReliablyUseSiblingFileList(osVATDBF.c_str()))
      70             :     {
      71             :         int iSibling =
      72      305725 :             CSLFindString(papszSiblingFiles, CPLGetFilename(osVATDBF.c_str()));
      73      305725 :         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      305725 :         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     2318580 : CPLErr GTiffRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     751             : 
     752             : {
     753     2318580 :     m_poGDS->Crystalize();
     754             : 
     755     2318580 :     GPtrDiff_t nBlockBufSize = 0;
     756     2318580 :     if (TIFFIsTiled(m_poGDS->m_hTIFF))
     757             :     {
     758       58205 :         nBlockBufSize = static_cast<GPtrDiff_t>(TIFFTileSize(m_poGDS->m_hTIFF));
     759             :     }
     760             :     else
     761             :     {
     762     2260370 :         CPLAssert(nBlockXOff == 0);
     763             :         nBlockBufSize =
     764     2260370 :             static_cast<GPtrDiff_t>(TIFFStripSize(m_poGDS->m_hTIFF));
     765             :     }
     766             : 
     767     2318580 :     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     2318580 :     auto nBlockReqSize = nBlockBufSize;
     775             : 
     776     2318580 :     if (nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize)
     777             :     {
     778        6470 :         nBlockReqSize =
     779        6470 :             (nBlockBufSize / nBlockYSize) *
     780        6470 :             (nBlockYSize -
     781             :              static_cast<int>(
     782        6470 :                  (static_cast<GIntBig>(nBlockYOff + 1) * nBlockYSize) %
     783        6470 :                  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     2318580 :     vsi_l_offset nOffset = 0;
     791     2318580 :     bool bErrOccurred = false;
     792     4504180 :     if (nBlockId != m_poGDS->m_nLoadedBlock &&
     793     2185600 :         !m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr, &bErrOccurred))
     794             :     {
     795       52887 :         NullBlock(pImage);
     796       52887 :         if (bErrOccurred)
     797           1 :             return CE_Failure;
     798       52886 :         return CE_None;
     799             :     }
     800             : 
     801     2265690 :     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     2264690 :     CPLErr eErr = CE_None;
     822     2264690 :     if (m_poGDS->nBands == 1 ||
     823      209029 :         m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     824             :     {
     825     2081040 :         if (nBlockReqSize < nBlockBufSize)
     826        3032 :             memset(pImage, 0, nBlockBufSize);
     827             : 
     828     2081040 :         if (!m_poGDS->ReadStrile(nBlockId, pImage, nBlockReqSize))
     829             :         {
     830          83 :             memset(pImage, 0, nBlockBufSize);
     831          83 :             return CE_Failure;
     832             :         }
     833             :     }
     834             :     else
     835             :     {
     836             :         /* --------------------------------------------------------------------
     837             :          */
     838             :         /*      Load desired block */
     839             :         /* --------------------------------------------------------------------
     840             :          */
     841      183655 :         eErr = m_poGDS->LoadBlockBuf(nBlockId);
     842      183655 :         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      183629 :         bool bDoCopyWords = true;
     851       52166 :         if (nBand == 1 && !m_poGDS->m_bLoadingOtherBands &&
     852       46467 :             eAccess == GA_ReadOnly &&
     853       37199 :             (m_poGDS->nBands == 3 || m_poGDS->nBands == 4) &&
     854       36412 :             ((eDataType == GDT_UInt8 && m_poGDS->m_nBitsPerSample == 8) ||
     855         436 :              (eDataType == GDT_Int16 && m_poGDS->m_nBitsPerSample == 16) ||
     856      236065 :              (eDataType == GDT_UInt16 && m_poGDS->m_nBitsPerSample == 16)) &&
     857       72498 :             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     858       36249 :                     GDALGetDataTypeSizeBytes(eDataType) <
     859       36249 :                 GDALGetCacheMax64() / m_poGDS->nBands)
     860             :         {
     861       36249 :             bDoCopyWords = false;
     862             :             void *ppDestBuffers[4];
     863       36249 :             GDALRasterBlock *apoLockedBlocks[4] = {nullptr, nullptr, nullptr,
     864             :                                                    nullptr};
     865      156134 :             for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
     866             :             {
     867      119885 :                 if (iBand == nBand)
     868             :                 {
     869       36249 :                     ppDestBuffers[iBand - 1] = pImage;
     870             :                 }
     871             :                 else
     872             :                 {
     873             :                     GDALRasterBlock *poBlock =
     874       83636 :                         m_poGDS->GetRasterBand(iBand)->GetLockedBlockRef(
     875       83636 :                             nBlockXOff, nBlockYOff, true);
     876       83636 :                     if (poBlock == nullptr)
     877             :                     {
     878           0 :                         bDoCopyWords = true;
     879           0 :                         break;
     880             :                     }
     881       83636 :                     ppDestBuffers[iBand - 1] = poBlock->GetDataRef();
     882       83636 :                     apoLockedBlocks[iBand - 1] = poBlock;
     883             :                 }
     884             :             }
     885       36249 :             if (!bDoCopyWords)
     886             :             {
     887       36249 :                 GDALDeinterleave(m_poGDS->m_pabyBlockBuf, eDataType,
     888       36249 :                                  m_poGDS->nBands, ppDestBuffers, eDataType,
     889       36249 :                                  static_cast<size_t>(nBlockXSize) *
     890       36249 :                                      nBlockYSize);
     891             :             }
     892      156134 :             for (int iBand = 1; iBand <= m_poGDS->nBands; ++iBand)
     893             :             {
     894      119885 :                 if (apoLockedBlocks[iBand - 1])
     895             :                 {
     896       83636 :                     apoLockedBlocks[iBand - 1]->DropLock();
     897             :                 }
     898             :             }
     899             :         }
     900             : 
     901      183629 :         if (bDoCopyWords)
     902             :         {
     903      147380 :             const int nWordBytes = m_poGDS->m_nBitsPerSample / 8;
     904      147380 :             GByte *pabyImage =
     905      147380 :                 m_poGDS->m_pabyBlockBuf + (nBand - 1) * nWordBytes;
     906             : 
     907      147380 :             GDALCopyWords64(pabyImage, eDataType, m_poGDS->nBands * nWordBytes,
     908             :                             pImage, eDataType, nWordBytes,
     909      147380 :                             static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize);
     910             : 
     911      147380 :             eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
     912             :         }
     913             :     }
     914             : 
     915     2264580 :     CacheMaskForBlock(nBlockXOff, nBlockYOff);
     916             : 
     917     2264580 :     return eErr;
     918             : }
     919             : 
     920             : /************************************************************************/
     921             : /*                         CacheMaskForBlock()                          */
     922             : /************************************************************************/
     923             : 
     924     2266960 : void GTiffRasterBand::CacheMaskForBlock(int nBlockXOff, int nBlockYOff)
     925             : 
     926             : {
     927             :     // Preload mask data if layout compatible and we have cached ranges
     928     2267070 :     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     2266960 : }
     943             : 
     944             : /************************************************************************/
     945             : /*                       FillCacheForOtherBands()                       */
     946             : /************************************************************************/
     947             : 
     948      147594 : 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      147594 :     CPLErr eErr = CE_None;
     968      442782 :     if (m_poGDS->nBands != 1 &&
     969      147594 :         m_poGDS->nBands <
     970       49160 :             128 &&  // avoid caching for datasets with too many bands
     971      308118 :         !m_poGDS->m_bLoadingOtherBands &&
     972       25860 :         static_cast<GPtrDiff_t>(nBlockXSize) * nBlockYSize *
     973       12930 :                 GDALGetDataTypeSizeBytes(eDataType) <
     974       12930 :             GDALGetCacheMax64() / m_poGDS->nBands)
     975             :     {
     976       12930 :         m_poGDS->m_bLoadingOtherBands = true;
     977             : 
     978       53054 :         for (int iOtherBand = 1; iOtherBand <= m_poGDS->nBands; ++iOtherBand)
     979             :         {
     980       40124 :             if (iOtherBand == nBand)
     981       12930 :                 continue;
     982             : 
     983             :             GDALRasterBlock *poBlock =
     984       27194 :                 m_poGDS->GetRasterBand(iOtherBand)
     985       27194 :                     ->GetLockedBlockRef(nBlockXOff, nBlockYOff);
     986       27194 :             if (poBlock == nullptr)
     987             :             {
     988           0 :                 eErr = CE_Failure;
     989           0 :                 break;
     990             :             }
     991       27194 :             poBlock->DropLock();
     992             :         }
     993             : 
     994       12930 :         m_poGDS->m_bLoadingOtherBands = false;
     995             :     }
     996             : 
     997      147594 :     return eErr;
     998             : }
     999             : 
    1000             : /************************************************************************/
    1001             : /*                           GetDescription()                           */
    1002             : /************************************************************************/
    1003             : 
    1004      310932 : const char *GTiffRasterBand::GetDescription() const
    1005             : {
    1006      310932 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1007             : 
    1008      310932 :     return m_osDescription;
    1009             : }
    1010             : 
    1011             : /************************************************************************/
    1012             : /*                             GetOffset()                              */
    1013             : /************************************************************************/
    1014             : 
    1015      316416 : double GTiffRasterBand::GetOffset(int *pbSuccess)
    1016             : 
    1017             : {
    1018      316416 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1019             : 
    1020      316416 :     if (pbSuccess)
    1021        7779 :         *pbSuccess = m_bHaveOffsetScale;
    1022      316416 :     return m_dfOffset;
    1023             : }
    1024             : 
    1025             : /************************************************************************/
    1026             : /*                              GetScale()                              */
    1027             : /************************************************************************/
    1028             : 
    1029      316419 : double GTiffRasterBand::GetScale(int *pbSuccess)
    1030             : 
    1031             : {
    1032      316419 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1033             : 
    1034      316419 :     if (pbSuccess)
    1035        7782 :         *pbSuccess = m_bHaveOffsetScale;
    1036      316419 :     return m_dfScale;
    1037             : }
    1038             : 
    1039             : /************************************************************************/
    1040             : /*                            GetUnitType()                             */
    1041             : /************************************************************************/
    1042             : 
    1043      307363 : const char *GTiffRasterBand::GetUnitType()
    1044             : 
    1045             : {
    1046      307363 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1047      307363 :     if (m_osUnitType.empty())
    1048             :     {
    1049      307162 :         m_poGDS->LookForProjection();
    1050      307162 :         if (m_poGDS->m_pszVertUnit)
    1051           9 :             return m_poGDS->m_pszVertUnit;
    1052             :     }
    1053             : 
    1054      307354 :     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       20110 : CSLConstList GTiffRasterBand::GetMetadata(const char *pszDomain)
    1075             : 
    1076             : {
    1077       20110 :     if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
    1078             :     {
    1079       19922 :         m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1080             : 
    1081       19922 :         m_poGDS->LoadENVIHdrIfNeeded();
    1082             :     }
    1083         188 :     else if (EQUAL(pszDomain, MD_DOMAIN_IMAGERY))
    1084             :     {
    1085           0 :         m_poGDS->LoadENVIHdrIfNeeded();
    1086             :     }
    1087             : 
    1088       20110 :     return m_oGTiffMDMD.GetMetadata(pszDomain);
    1089             : }
    1090             : 
    1091             : /************************************************************************/
    1092             : /*                          GetMetadataItem()                           */
    1093             : /************************************************************************/
    1094             : 
    1095       24003 : const char *GTiffRasterBand::GetMetadataItem(const char *pszName,
    1096             :                                              const char *pszDomain)
    1097             : 
    1098             : {
    1099       24003 :     if (pszName != nullptr && pszDomain != nullptr && EQUAL(pszDomain, "TIFF"))
    1100             :     {
    1101        5243 :         int nBlockXOff = 0;
    1102        5243 :         int nBlockYOff = 0;
    1103             : 
    1104        5243 :         if (EQUAL(pszName, "JPEGTABLES"))
    1105             :         {
    1106          11 :             uint32_t nJPEGTableSize = 0;
    1107          11 :             void *pJPEGTable = nullptr;
    1108          11 :             if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_JPEGTABLES,
    1109          11 :                              &nJPEGTableSize, &pJPEGTable) != 1 ||
    1110          11 :                 pJPEGTable == nullptr || nJPEGTableSize > INT_MAX)
    1111             :             {
    1112           0 :                 return nullptr;
    1113             :             }
    1114          11 :             char *const pszHex = CPLBinaryToHex(
    1115             :                 nJPEGTableSize, static_cast<const GByte *>(pJPEGTable));
    1116          11 :             const char *pszReturn = CPLSPrintf("%s", pszHex);
    1117          11 :             CPLFree(pszHex);
    1118             : 
    1119          11 :             return pszReturn;
    1120             :         }
    1121             : 
    1122        5232 :         if (EQUAL(pszName, "IFD_OFFSET"))
    1123             :         {
    1124         180 :             return CPLSPrintf(CPL_FRMT_GUIB,
    1125          90 :                               static_cast<GUIntBig>(m_poGDS->m_nDirOffset));
    1126             :         }
    1127             : 
    1128        5142 :         if (sscanf(pszName, "BLOCK_OFFSET_%d_%d", &nBlockXOff, &nBlockYOff) ==
    1129             :             2)
    1130             :         {
    1131        4422 :             if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
    1132        4421 :                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
    1133          19 :                 return nullptr;
    1134             : 
    1135        4403 :             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
    1136        4403 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
    1137             :             {
    1138        3592 :                 nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
    1139             :             }
    1140             : 
    1141        4403 :             vsi_l_offset nOffset = 0;
    1142        4403 :             if (!m_poGDS->IsBlockAvailable(nBlockId, &nOffset, nullptr,
    1143             :                                            nullptr))
    1144             :             {
    1145         185 :                 return nullptr;
    1146             :             }
    1147             : 
    1148        4218 :             return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nOffset));
    1149             :         }
    1150             : 
    1151         720 :         if (sscanf(pszName, "BLOCK_SIZE_%d_%d", &nBlockXOff, &nBlockYOff) == 2)
    1152             :         {
    1153         720 :             if (nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
    1154         719 :                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn)
    1155           2 :                 return nullptr;
    1156             : 
    1157         718 :             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
    1158         718 :             if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
    1159             :             {
    1160         244 :                 nBlockId += (nBand - 1) * m_poGDS->m_nBlocksPerBand;
    1161             :             }
    1162             : 
    1163         718 :             vsi_l_offset nByteCount = 0;
    1164         718 :             if (!m_poGDS->IsBlockAvailable(nBlockId, nullptr, &nByteCount,
    1165             :                                            nullptr))
    1166             :             {
    1167          87 :                 return nullptr;
    1168             :             }
    1169             : 
    1170         631 :             return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nByteCount));
    1171           0 :         }
    1172             :     }
    1173       18760 :     else if (pszName && pszDomain && EQUAL(pszDomain, "_DEBUG_"))
    1174             :     {
    1175         131 :         if (EQUAL(pszName, "HAS_BLOCK_CACHE"))
    1176         131 :             return HasBlockCache() ? "1" : "0";
    1177             :     }
    1178       18629 :     else if (pszDomain == nullptr || !EQUAL(pszDomain, "IMAGE_STRUCTURE"))
    1179             :     {
    1180        3912 :         m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1181             : 
    1182        3912 :         m_poGDS->LoadENVIHdrIfNeeded();
    1183             :     }
    1184       14717 :     else if (EQUAL(pszDomain, MD_DOMAIN_IMAGERY))
    1185             :     {
    1186           0 :         m_poGDS->LoadENVIHdrIfNeeded();
    1187             :     }
    1188             : 
    1189       18629 :     const char *pszRet = m_oGTiffMDMD.GetMetadataItem(pszName, pszDomain);
    1190             : 
    1191       18629 :     if (pszRet == nullptr && eDataType == GDT_UInt8 && pszName && pszDomain &&
    1192       16000 :         EQUAL(pszDomain, "IMAGE_STRUCTURE") && EQUAL(pszName, "PIXELTYPE"))
    1193             :     {
    1194             :         // to get a chance of emitting the warning about this legacy usage
    1195        3723 :         pszRet = GDALRasterBand::GetMetadataItem(pszName, pszDomain);
    1196             :     }
    1197       18629 :     return pszRet;
    1198             : }
    1199             : 
    1200             : /************************************************************************/
    1201             : /*                       GetColorInterpretation()                       */
    1202             : /************************************************************************/
    1203             : 
    1204      461705 : GDALColorInterp GTiffRasterBand::GetColorInterpretation()
    1205             : 
    1206             : {
    1207      461705 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1208             : 
    1209      461705 :     return m_eBandInterp;
    1210             : }
    1211             : 
    1212             : /************************************************************************/
    1213             : /*                           GetColorTable()                            */
    1214             : /************************************************************************/
    1215             : 
    1216       12537 : GDALColorTable *GTiffRasterBand::GetColorTable()
    1217             : 
    1218             : {
    1219       12537 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1220             : 
    1221       12537 :     if (nBand == 1)
    1222       10551 :         return m_poGDS->m_poColorTable.get();
    1223             : 
    1224        1986 :     return nullptr;
    1225             : }
    1226             : 
    1227             : /************************************************************************/
    1228             : /*                           GetNoDataValue()                           */
    1229             : /************************************************************************/
    1230             : 
    1231      969632 : double GTiffRasterBand::GetNoDataValue(int *pbSuccess)
    1232             : 
    1233             : {
    1234      969632 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1235             : 
    1236      969632 :     int bSuccess = FALSE;
    1237      969632 :     double dfNoDataValue = GDALPamRasterBand::GetNoDataValue(&bSuccess);
    1238      969632 :     if (bSuccess)
    1239             :     {
    1240           4 :         if (pbSuccess)
    1241           4 :             *pbSuccess = TRUE;
    1242             : 
    1243           4 :         return dfNoDataValue;
    1244             :     }
    1245             : 
    1246      969628 :     if (m_bNoDataSet)
    1247             :     {
    1248        4999 :         if (pbSuccess)
    1249        4952 :             *pbSuccess = TRUE;
    1250             : 
    1251        4999 :         return m_dfNoDataValue;
    1252             :     }
    1253             : 
    1254      964629 :     if (m_poGDS->m_bNoDataSet)
    1255             :     {
    1256      424323 :         if (pbSuccess)
    1257      424097 :             *pbSuccess = TRUE;
    1258             : 
    1259      424323 :         return m_poGDS->m_dfNoDataValue;
    1260             :     }
    1261             : 
    1262      540306 :     if (m_bNoDataSetAsInt64)
    1263             :     {
    1264           0 :         if (pbSuccess)
    1265           0 :             *pbSuccess = TRUE;
    1266             : 
    1267           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
    1268             :     }
    1269             : 
    1270      540306 :     if (m_poGDS->m_bNoDataSetAsInt64)
    1271             :     {
    1272           0 :         if (pbSuccess)
    1273           0 :             *pbSuccess = TRUE;
    1274             : 
    1275           0 :         return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueInt64);
    1276             :     }
    1277             : 
    1278      540306 :     if (m_bNoDataSetAsUInt64)
    1279             :     {
    1280           0 :         if (pbSuccess)
    1281           0 :             *pbSuccess = TRUE;
    1282             : 
    1283           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
    1284             :     }
    1285             : 
    1286      540306 :     if (m_poGDS->m_bNoDataSetAsUInt64)
    1287             :     {
    1288           0 :         if (pbSuccess)
    1289           0 :             *pbSuccess = TRUE;
    1290             : 
    1291           0 :         return GDALGetNoDataValueCastToDouble(m_poGDS->m_nNoDataValueUInt64);
    1292             :     }
    1293             : 
    1294      540306 :     if (pbSuccess)
    1295      540166 :         *pbSuccess = FALSE;
    1296      540306 :     return dfNoDataValue;
    1297             : }
    1298             : 
    1299             : /************************************************************************/
    1300             : /*                       GetNoDataValueAsInt64()                        */
    1301             : /************************************************************************/
    1302             : 
    1303          64 : int64_t GTiffRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
    1304             : 
    1305             : {
    1306          64 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1307             : 
    1308          64 :     if (eDataType == GDT_UInt64)
    1309             :     {
    1310           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1311             :                  "GetNoDataValueAsUInt64() should be called instead");
    1312           0 :         if (pbSuccess)
    1313           0 :             *pbSuccess = FALSE;
    1314           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1315             :     }
    1316          64 :     if (eDataType != GDT_Int64)
    1317             :     {
    1318           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1319             :                  "GetNoDataValue() should be called instead");
    1320           0 :         if (pbSuccess)
    1321           0 :             *pbSuccess = FALSE;
    1322           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1323             :     }
    1324             : 
    1325          64 :     int bSuccess = FALSE;
    1326             :     const auto nNoDataValue =
    1327          64 :         GDALPamRasterBand::GetNoDataValueAsInt64(&bSuccess);
    1328          64 :     if (bSuccess)
    1329             :     {
    1330           0 :         if (pbSuccess)
    1331           0 :             *pbSuccess = TRUE;
    1332             : 
    1333           0 :         return nNoDataValue;
    1334             :     }
    1335             : 
    1336          64 :     if (m_bNoDataSetAsInt64)
    1337             :     {
    1338           2 :         if (pbSuccess)
    1339           2 :             *pbSuccess = TRUE;
    1340             : 
    1341           2 :         return m_nNoDataValueInt64;
    1342             :     }
    1343             : 
    1344          62 :     if (m_poGDS->m_bNoDataSetAsInt64)
    1345             :     {
    1346          11 :         if (pbSuccess)
    1347          10 :             *pbSuccess = TRUE;
    1348             : 
    1349          11 :         return m_poGDS->m_nNoDataValueInt64;
    1350             :     }
    1351             : 
    1352          51 :     if (pbSuccess)
    1353          51 :         *pbSuccess = FALSE;
    1354          51 :     return nNoDataValue;
    1355             : }
    1356             : 
    1357             : /************************************************************************/
    1358             : /*                       GetNoDataValueAsUInt64()                       */
    1359             : /************************************************************************/
    1360             : 
    1361          46 : uint64_t GTiffRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
    1362             : 
    1363             : {
    1364          46 :     m_poGDS->LoadGeoreferencingAndPamIfNeeded();
    1365             : 
    1366          46 :     if (eDataType == GDT_Int64)
    1367             :     {
    1368           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1369             :                  "GetNoDataValueAsInt64() should be called instead");
    1370           0 :         if (pbSuccess)
    1371           0 :             *pbSuccess = FALSE;
    1372           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1373             :     }
    1374          46 :     if (eDataType != GDT_UInt64)
    1375             :     {
    1376           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1377             :                  "GetNoDataValue() should be called instead");
    1378           0 :         if (pbSuccess)
    1379           0 :             *pbSuccess = FALSE;
    1380           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1381             :     }
    1382             : 
    1383          46 :     int bSuccess = FALSE;
    1384             :     const auto nNoDataValue =
    1385          46 :         GDALPamRasterBand::GetNoDataValueAsUInt64(&bSuccess);
    1386          46 :     if (bSuccess)
    1387             :     {
    1388           0 :         if (pbSuccess)
    1389           0 :             *pbSuccess = TRUE;
    1390             : 
    1391           0 :         return nNoDataValue;
    1392             :     }
    1393             : 
    1394          46 :     if (m_bNoDataSetAsUInt64)
    1395             :     {
    1396           4 :         if (pbSuccess)
    1397           4 :             *pbSuccess = TRUE;
    1398             : 
    1399           4 :         return m_nNoDataValueUInt64;
    1400             :     }
    1401             : 
    1402          42 :     if (m_poGDS->m_bNoDataSetAsUInt64)
    1403             :     {
    1404           7 :         if (pbSuccess)
    1405           6 :             *pbSuccess = TRUE;
    1406             : 
    1407           7 :         return m_poGDS->m_nNoDataValueUInt64;
    1408             :     }
    1409             : 
    1410          35 :     if (pbSuccess)
    1411          35 :         *pbSuccess = FALSE;
    1412          35 :     return nNoDataValue;
    1413             : }
    1414             : 
    1415             : /************************************************************************/
    1416             : /*                          GetOverviewCount()                          */
    1417             : /************************************************************************/
    1418             : 
    1419     1320070 : int GTiffRasterBand::GetOverviewCount()
    1420             : 
    1421             : {
    1422     1320070 :     if (!m_poGDS->AreOverviewsEnabled())
    1423          30 :         return 0;
    1424             : 
    1425     1320040 :     m_poGDS->ScanDirectories();
    1426             : 
    1427     1320040 :     if (!m_poGDS->m_apoOverviewDS.empty())
    1428             :     {
    1429      267339 :         return static_cast<int>(m_poGDS->m_apoOverviewDS.size());
    1430             :     }
    1431             : 
    1432     1052700 :     const int nOverviewCount = GDALRasterBand::GetOverviewCount();
    1433     1052700 :     if (nOverviewCount > 0)
    1434         391 :         return nOverviewCount;
    1435             : 
    1436             :     // Implicit JPEG overviews are normally hidden, except when doing
    1437             :     // IRasterIO() operations.
    1438     1052310 :     if (m_poGDS->m_nJPEGOverviewVisibilityCounter)
    1439     1044190 :         return m_poGDS->GetJPEGOverviewCount();
    1440             : 
    1441        8123 :     return 0;
    1442             : }
    1443             : 
    1444             : /************************************************************************/
    1445             : /*                            GetOverview()                             */
    1446             : /************************************************************************/
    1447             : 
    1448       74187 : GDALRasterBand *GTiffRasterBand::GetOverview(int i)
    1449             : 
    1450             : {
    1451       74187 :     m_poGDS->ScanDirectories();
    1452             : 
    1453       74187 :     if (!m_poGDS->m_apoOverviewDS.empty())
    1454             :     {
    1455             :         // Do we have internal overviews?
    1456       73591 :         if (i < 0 || static_cast<size_t>(i) >= m_poGDS->m_apoOverviewDS.size())
    1457           8 :             return nullptr;
    1458             : 
    1459       73583 :         return m_poGDS->m_apoOverviewDS[i]->GetRasterBand(nBand);
    1460             :     }
    1461             : 
    1462         596 :     GDALRasterBand *const poOvrBand = GDALRasterBand::GetOverview(i);
    1463         596 :     if (poOvrBand != nullptr)
    1464         391 :         return poOvrBand;
    1465             : 
    1466             :     // For consistency with GetOverviewCount(), we should also test
    1467             :     // m_nJPEGOverviewVisibilityCounter, but it is also convenient to be able
    1468             :     // to query them for testing purposes.
    1469         205 :     if (i >= 0 && i < m_poGDS->GetJPEGOverviewCount())
    1470         164 :         return m_poGDS->m_apoJPEGOverviewDS[i]->GetRasterBand(nBand);
    1471             : 
    1472          41 :     return nullptr;
    1473             : }
    1474             : 
    1475             : /************************************************************************/
    1476             : /*                            GetMaskFlags()                            */
    1477             : /************************************************************************/
    1478             : 
    1479       22613 : int GTiffRasterBand::GetMaskFlags()
    1480             : {
    1481       22613 :     m_poGDS->ScanDirectories();
    1482             : 
    1483       22613 :     if (m_poGDS->m_poExternalMaskDS != nullptr)
    1484             :     {
    1485           0 :         return GMF_PER_DATASET;
    1486             :     }
    1487             : 
    1488       22613 :     if (m_poGDS->m_poMaskDS != nullptr)
    1489             :     {
    1490         222 :         if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
    1491             :         {
    1492         214 :             return GMF_PER_DATASET;
    1493             :         }
    1494             : 
    1495           8 :         return 0;
    1496             :     }
    1497             : 
    1498       22391 :     if (m_poGDS->m_bIsOverview)
    1499             :     {
    1500         444 :         return m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskFlags();
    1501             :     }
    1502             : 
    1503       21947 :     return GDALPamRasterBand::GetMaskFlags();
    1504             : }
    1505             : 
    1506             : /************************************************************************/
    1507             : /*                            GetMaskBand()                             */
    1508             : /************************************************************************/
    1509             : 
    1510      117861 : GDALRasterBand *GTiffRasterBand::GetMaskBand()
    1511             : {
    1512      117861 :     m_poGDS->ScanDirectories();
    1513             : 
    1514      117861 :     if (m_poGDS->m_poExternalMaskDS != nullptr)
    1515             :     {
    1516          31 :         return m_poGDS->m_poExternalMaskDS->GetRasterBand(1);
    1517             :     }
    1518             : 
    1519      117830 :     if (m_poGDS->m_poMaskDS != nullptr)
    1520             :     {
    1521         691 :         if (m_poGDS->m_poMaskDS->GetRasterCount() == 1)
    1522         674 :             return m_poGDS->m_poMaskDS->GetRasterBand(1);
    1523             : 
    1524          17 :         return m_poGDS->m_poMaskDS->GetRasterBand(nBand);
    1525             :     }
    1526             : 
    1527      117139 :     if (m_poGDS->m_bIsOverview)
    1528             :     {
    1529             :         GDALRasterBand *poBaseMask =
    1530         119 :             m_poGDS->m_poBaseDS->GetRasterBand(nBand)->GetMaskBand();
    1531         119 :         if (poBaseMask)
    1532             :         {
    1533         119 :             const int nOverviews = poBaseMask->GetOverviewCount();
    1534         164 :             for (int i = 0; i < nOverviews; i++)
    1535             :             {
    1536          93 :                 GDALRasterBand *poOvr = poBaseMask->GetOverview(i);
    1537         141 :                 if (poOvr && poOvr->GetXSize() == GetXSize() &&
    1538          48 :                     poOvr->GetYSize() == GetYSize())
    1539             :                 {
    1540          48 :                     return poOvr;
    1541             :                 }
    1542             :             }
    1543             :         }
    1544             :     }
    1545             : 
    1546      117091 :     return GDALPamRasterBand::GetMaskBand();
    1547             : }
    1548             : 
    1549             : /************************************************************************/
    1550             : /*                             IsMaskBand()                             */
    1551             : /************************************************************************/
    1552             : 
    1553        1039 : bool GTiffRasterBand::IsMaskBand() const
    1554             : {
    1555        1071 :     return (m_poGDS->m_poImageryDS != nullptr &&
    1556          32 :             m_poGDS->m_poImageryDS->m_poMaskDS.get() == m_poGDS) ||
    1557        2023 :            m_eBandInterp == GCI_AlphaBand ||
    1558        1991 :            m_poGDS->GetMetadataItem("INTERNAL_MASK_FLAGS_1") != nullptr;
    1559             : }
    1560             : 
    1561             : /************************************************************************/
    1562             : /*                         GetMaskValueRange()                          */
    1563             : /************************************************************************/
    1564             : 
    1565           0 : GDALMaskValueRange GTiffRasterBand::GetMaskValueRange() const
    1566             : {
    1567           0 :     if (!IsMaskBand())
    1568           0 :         return GMVR_UNKNOWN;
    1569           0 :     if (m_poGDS->m_nBitsPerSample == 1)
    1570           0 :         return m_poGDS->m_bPromoteTo8Bits ? GMVR_0_AND_255_ONLY
    1571           0 :                                           : GMVR_0_AND_1_ONLY;
    1572           0 :     return GMVR_UNKNOWN;
    1573             : }

Generated by: LCOV version 1.14