LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 242 251 96.4 %
Date: 2025-07-08 21:33:46 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GeoTIFF Driver
       4             :  * Purpose:  General methods of 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             : 
      17             : #include <algorithm>
      18             : #include <set>
      19             : 
      20             : #include "cpl_vsi_virtual.h"
      21             : #include "tifvsi.h"
      22             : 
      23             : /************************************************************************/
      24             : /*                           GTiffRasterBand()                          */
      25             : /************************************************************************/
      26             : 
      27     1031530 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      28     1031530 :     : m_poGDS(poDSIn)
      29             : {
      30     1031460 :     poDS = poDSIn;
      31     1031460 :     nBand = nBandIn;
      32             : 
      33             :     /* -------------------------------------------------------------------- */
      34             :     /*      Get the GDAL data type.                                         */
      35             :     /* -------------------------------------------------------------------- */
      36     1031460 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      37     1031460 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      38             : 
      39     1031460 :     eDataType = GDT_Unknown;
      40             : 
      41     1031460 :     if (nBitsPerSample <= 8)
      42             :     {
      43      889336 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      44         310 :             eDataType = GDT_Int8;
      45             :         else
      46      889026 :             eDataType = GDT_Byte;
      47             :     }
      48      142125 :     else if (nBitsPerSample <= 16)
      49             :     {
      50      134353 :         if (nBitsPerSample == 16 && nSampleFormat == SAMPLEFORMAT_IEEEFP)
      51         248 :             eDataType = GDT_Float16;
      52      134105 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      53       67117 :             eDataType = GDT_Int16;
      54             :         else
      55       66988 :             eDataType = GDT_UInt16;
      56             :     }
      57        7772 :     else if (nBitsPerSample == 32)
      58             :     {
      59        4665 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      60         683 :             eDataType = GDT_CInt16;
      61        3982 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      62         224 :             eDataType = GDT_CFloat16;
      63        3758 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      64        2537 :             eDataType = GDT_Float32;
      65        1221 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      66         644 :             eDataType = GDT_Int32;
      67             :         else
      68         577 :             eDataType = GDT_UInt32;
      69             :     }
      70        3107 :     else if (nBitsPerSample == 64)
      71             :     {
      72        2561 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      73        1128 :             eDataType = GDT_Float64;
      74        1433 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      75         460 :             eDataType = GDT_CFloat32;
      76         973 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      77         436 :             eDataType = GDT_CInt32;
      78         537 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      79         277 :             eDataType = GDT_Int64;
      80             :         else
      81         260 :             eDataType = GDT_UInt64;
      82             :     }
      83         546 :     else if (nBitsPerSample == 128)
      84             :     {
      85         474 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      86         474 :             eDataType = GDT_CFloat64;
      87             :     }
      88             : 
      89             :     /* -------------------------------------------------------------------- */
      90             :     /*      Try to work out band color interpretation.                      */
      91             :     /* -------------------------------------------------------------------- */
      92     1031460 :     bool bLookForExtraSamples = false;
      93             : 
      94     1031460 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
      95             :     {
      96         172 :         m_eBandInterp = GCI_PaletteIndex;
      97             :     }
      98     2044990 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
      99     1013700 :              (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR &&
     100         897 :               m_poGDS->m_nCompression == COMPRESSION_JPEG &&
     101         858 :               CPLTestBool(CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES"))))
     102             :     {
     103       18306 :         if (nBand == 1)
     104        5756 :             m_eBandInterp = GCI_RedBand;
     105       12550 :         else if (nBand == 2)
     106        5765 :             m_eBandInterp = GCI_GreenBand;
     107        6785 :         else if (nBand == 3)
     108        5765 :             m_eBandInterp = GCI_BlueBand;
     109             :         else
     110        1020 :             bLookForExtraSamples = true;
     111             :     }
     112     1012980 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)
     113             :     {
     114          39 :         if (nBand == 1)
     115          13 :             m_eBandInterp = GCI_YCbCr_YBand;
     116          26 :         else if (nBand == 2)
     117          13 :             m_eBandInterp = GCI_YCbCr_CbBand;
     118          13 :         else if (nBand == 3)
     119          13 :             m_eBandInterp = GCI_YCbCr_CrBand;
     120             :         else
     121           0 :             bLookForExtraSamples = true;
     122             :     }
     123     1012940 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)
     124             :     {
     125          96 :         if (nBand == 1)
     126          24 :             m_eBandInterp = GCI_CyanBand;
     127          72 :         else if (nBand == 2)
     128          24 :             m_eBandInterp = GCI_MagentaBand;
     129          48 :         else if (nBand == 3)
     130          24 :             m_eBandInterp = GCI_YellowBand;
     131          24 :         else if (nBand == 4)
     132          24 :             m_eBandInterp = GCI_BlackBand;
     133             :         else
     134           0 :             bLookForExtraSamples = true;
     135             :     }
     136     1012850 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     137             :     {
     138       25958 :         m_eBandInterp = GCI_GrayIndex;
     139             :     }
     140             :     else
     141             :     {
     142      986888 :         bLookForExtraSamples = true;
     143             :     }
     144             : 
     145     1031460 :     if (bLookForExtraSamples)
     146             :     {
     147      987773 :         uint16_t *v = nullptr;
     148      987773 :         uint16_t count = 0;
     149             : 
     150      987773 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     151             :         {
     152      921846 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     153      921846 :             const int nExpectedBaseSamples =
     154      922870 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     155        2048 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     156        1030 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB)        ? 3
     157          12 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)      ? 3
     158           6 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)  ? 4
     159             :                                                                       : 0;
     160             : 
     161      921846 :             if (nExpectedBaseSamples > 0 && nBand == nExpectedBaseSamples + 1 &&
     162             :                 nBaseSamples != nExpectedBaseSamples)
     163             :             {
     164           1 :                 ReportError(
     165             :                     CE_Warning, CPLE_AppDefined,
     166             :                     "Wrong number of ExtraSamples : %d. %d were expected",
     167           1 :                     count, m_poGDS->m_nSamplesPerPixel - nExpectedBaseSamples);
     168             :             }
     169             : 
     170      921846 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     171      921841 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     172      921824 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     173             :             {
     174        1113 :                 if (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA)
     175          17 :                     m_oGTiffMDMD.SetMetadataItem("ALPHA", "PREMULTIPLIED",
     176             :                                                  "IMAGE_STRUCTURE");
     177        1113 :                 m_eBandInterp = GCI_AlphaBand;
     178             :             }
     179             :             else
     180      920733 :                 m_eBandInterp = GCI_Undefined;
     181             :         }
     182             :         else
     183             :         {
     184       65927 :             m_eBandInterp = GCI_Undefined;
     185             :         }
     186             :     }
     187             : 
     188             :     /* -------------------------------------------------------------------- */
     189             :     /*      Establish block size for strip or tiles.                        */
     190             :     /* -------------------------------------------------------------------- */
     191     1031460 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     192     1031460 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     193     1031460 :     nRasterXSize = m_poGDS->nRasterXSize;
     194     1031460 :     nRasterYSize = m_poGDS->nRasterYSize;
     195     1031460 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     196     1031460 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     197     1031460 : }
     198             : 
     199             : /************************************************************************/
     200             : /*                          ~GTiffRasterBand()                          */
     201             : /************************************************************************/
     202             : 
     203     1931014 : GTiffRasterBand::~GTiffRasterBand()
     204             : {
     205             :     // So that any future DropReferenceVirtualMem() will not try to access the
     206             :     // raster band object, but this would not conform to the advertised
     207             :     // contract.
     208     1031540 :     if (!m_aSetPSelf.empty())
     209             :     {
     210           0 :         ReportError(CE_Warning, CPLE_AppDefined,
     211             :                     "Virtual memory objects still exist at GTiffRasterBand "
     212             :                     "destruction");
     213           0 :         std::set<GTiffRasterBand **>::iterator oIter = m_aSetPSelf.begin();
     214           0 :         for (; oIter != m_aSetPSelf.end(); ++oIter)
     215           0 :             *(*oIter) = nullptr;
     216             :     }
     217     1931014 : }
     218             : 
     219             : /************************************************************************/
     220             : /*                            IRasterIO()                               */
     221             : /************************************************************************/
     222             : 
     223     5814450 : CPLErr GTiffRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     224             :                                   int nXSize, int nYSize, void *pData,
     225             :                                   int nBufXSize, int nBufYSize,
     226             :                                   GDALDataType eBufType, GSpacing nPixelSpace,
     227             :                                   GSpacing nLineSpace,
     228             :                                   GDALRasterIOExtraArg *psExtraArg)
     229             : {
     230             : #if DEBUG_VERBOSE
     231             :     CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)", nXOff, nYOff, nXSize,
     232             :              nYSize, nBufXSize, nBufYSize);
     233             : #endif
     234             : 
     235             :     // Try to pass the request to the most appropriate overview dataset.
     236     5814450 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     237             :     {
     238      362407 :         int bTried = FALSE;
     239      362407 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     240      362039 :             ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     241      362407 :         const CPLErr eErr = TryOverviewRasterIO(
     242             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     243             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     244      362407 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     245      362039 :             --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     246      362407 :         if (bTried)
     247          44 :             return eErr;
     248             :     }
     249             : 
     250     5814410 :     if (m_poGDS->m_eVirtualMemIOUsage != GTiffDataset::VirtualMemIOEnum::NO)
     251             :     {
     252         904 :         const int nErr = m_poGDS->VirtualMemIO(
     253             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     254         452 :             eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
     255         452 :         if (nErr >= 0)
     256         363 :             return static_cast<CPLErr>(nErr);
     257             :     }
     258     5814050 :     if (m_poGDS->m_bDirectIO)
     259             :     {
     260             :         int nErr =
     261        2522 :             DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     262             :                      nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     263        2522 :         if (nErr >= 0)
     264        1409 :             return static_cast<CPLErr>(nErr);
     265             :     }
     266             : 
     267     5812640 :     bool bCanUseMultiThreadedRead = false;
     268     5812680 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     269     3354190 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     270    11625300 :         nYSize == nBufYSize && m_poGDS->IsMultiThreadedReadCompatible())
     271             :     {
     272         103 :         const int nBlockX1 = nXOff / nBlockXSize;
     273         103 :         const int nBlockY1 = nYOff / nBlockYSize;
     274         103 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     275         103 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     276         103 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     277         103 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     278         103 :         if (nXBlocks > 1 || nYBlocks > 1)
     279             :         {
     280         100 :             bCanUseMultiThreadedRead = true;
     281             :         }
     282             :     }
     283             : 
     284             :     // Cleanup data cached by below CacheMultiRange() call.
     285             :     struct BufferedDataFreer
     286             :     {
     287             :         void *m_pBufferedData = nullptr;
     288             :         TIFF *m_hTIFF = nullptr;
     289             : 
     290         256 :         void Init(void *pBufferedData, TIFF *hTIFF)
     291             :         {
     292         256 :             m_pBufferedData = pBufferedData;
     293         256 :             m_hTIFF = hTIFF;
     294         256 :         }
     295             : 
     296     5813440 :         ~BufferedDataFreer()
     297     5813440 :         {
     298     5813440 :             if (m_pBufferedData)
     299             :             {
     300          35 :                 VSIFree(m_pBufferedData);
     301          35 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     302             :                                         nullptr, nullptr);
     303             :             }
     304     5813440 :         }
     305             :     };
     306             : 
     307             :     // bufferedDataFreer must be left in this scope !
     308     5813680 :     BufferedDataFreer bufferedDataFreer;
     309             : 
     310     8668080 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     311     2854790 :         m_poGDS->HasOptimizedReadMultiRange())
     312             :     {
     313         264 :         if (bCanUseMultiThreadedRead &&
     314           4 :             VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF))->HasPRead())
     315             :         {
     316             :             // use the multi-threaded implementation rather than the multi-range
     317             :             // one
     318             :         }
     319             :         else
     320             :         {
     321         256 :             bCanUseMultiThreadedRead = false;
     322         256 :             GTiffDataset *poDSForCache = m_poGDS;
     323         256 :             int nBandForCache = nBand;
     324         256 :             if (!m_poGDS->m_bStreamingIn && m_poGDS->m_bBlockOrderRowMajor &&
     325         112 :                 m_poGDS->m_bLeaderSizeAsUInt4 &&
     326         112 :                 m_poGDS->m_bMaskInterleavedWithImagery &&
     327         102 :                 m_poGDS->m_poImageryDS)
     328             :             {
     329          63 :                 poDSForCache = m_poGDS->m_poImageryDS;
     330          63 :                 nBandForCache = 1;
     331             :             }
     332         256 :             bufferedDataFreer.Init(
     333             :                 poDSForCache->CacheMultiRange(nXOff, nYOff, nXSize, nYSize,
     334             :                                               nBufXSize, nBufYSize,
     335             :                                               &nBandForCache, 1, psExtraArg),
     336             :                 poDSForCache->m_hTIFF);
     337             :         }
     338             :     }
     339             : 
     340     5813300 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     341             :     {
     342     2955780 :         const int nBlockX1 = nXOff / nBlockXSize;
     343     2955780 :         const int nBlockY1 = nYOff / nBlockYSize;
     344     2955780 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     345     2955780 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     346     2955780 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     347     2955780 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     348             : 
     349     2955780 :         if (bCanUseMultiThreadedRead)
     350             :         {
     351         200 :             return m_poGDS->MultiThreadedRead(nXOff, nYOff, nXSize, nYSize,
     352         100 :                                               pData, eBufType, 1, &nBand,
     353         100 :                                               nPixelSpace, nLineSpace, 0);
     354             :         }
     355     2955680 :         else if (m_poGDS->nBands != 1 &&
     356      735644 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     357             :         {
     358             :             const GIntBig nRequiredMem =
     359      675647 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     360      675647 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     361      675855 :             if (nRequiredMem > GDALGetCacheMax64())
     362             :             {
     363        9061 :                 if (!m_poGDS->m_bHasWarnedDisableAggressiveBandCaching)
     364             :                 {
     365          15 :                     CPLDebug("GTiff",
     366             :                              "Disable aggressive band caching. "
     367             :                              "Cache not big enough. "
     368             :                              "At least " CPL_FRMT_GIB " bytes necessary",
     369             :                              nRequiredMem);
     370          15 :                     m_poGDS->m_bHasWarnedDisableAggressiveBandCaching = true;
     371             :                 }
     372        9061 :                 m_poGDS->m_bLoadingOtherBands = true;
     373             :             }
     374     2956970 :         }
     375             :     }
     376             : 
     377             :     // Write optimization when writing whole blocks, by-passing the block cache.
     378             :     // We require the block cache to be non instantiated to simplify things
     379             :     // (otherwise we might need to evict corresponding existing blocks from the
     380             :     // block cache).
     381     5315440 :     else if (eRWFlag == GF_Write &&
     382             :              // Could be extended to "odd bit" case, but more work
     383     2458500 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSizeBits(eDataType) &&
     384     2305620 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     385       48527 :              !m_poGDS->m_bLoadedBlockDirty &&
     386       48111 :              (m_poGDS->nBands == 1 ||
     387        4476 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     388       47001 :              !m_poGDS->m_bLeaderSizeAsUInt4 && (nXOff % nBlockXSize) == 0 &&
     389       46856 :              (nYOff % nBlockYSize) == 0 &&
     390     5363130 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     391       47221 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     392             :     {
     393       46475 :         m_poGDS->Crystalize();
     394             : 
     395       46716 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     396           0 :             return CE_None;
     397             : 
     398       46716 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     399       46435 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     400       41768 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     401       40253 :             nLineSpace == nPixelSpace * nBlockXSize)
     402             :         {
     403             :             // If writing one single block with the right data type and layout,
     404             :             // we don't need a temporary buffer
     405             :             const int nBlockId =
     406       41009 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     407       40910 :             return m_poGDS->WriteEncodedTileOrStrip(
     408       41564 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     409             :         }
     410             : 
     411             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     412             :         // We could actually use any temporary buffer
     413        5426 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     414        5738 :                                   /* bReadFromDisk = */ false) != CE_None)
     415             :         {
     416           0 :             return CE_Failure;
     417             :         }
     418             : 
     419             :         // Iterate over all blocks defined by
     420             :         // [nXOff, nXOff+nXSize[ * [nYOff, nYOff+nYSize[
     421             :         // and write their content as a nBlockXSize x nBlockYSize strile
     422             :         // in a temporary buffer, before calling WriteEncodedTileOrStrip()
     423             :         // on it
     424        5738 :         const int nYBlockStart = nYOff / nBlockYSize;
     425        5738 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     426        5738 :         const int nXBlockStart = nXOff / nBlockXSize;
     427        5738 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     428       48744 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     429             :         {
     430             :             const int nValidY =
     431       43006 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     432      101772 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     433             :             {
     434             :                 const int nValidX =
     435       58766 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     436       58762 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     437             :                 {
     438             :                     // Make sure padding bytes at the right/bottom of the
     439             :                     // tile are initialized to zero.
     440        2884 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     441        2884 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     442        2884 :                                nDTSize);
     443             :                 }
     444       58762 :                 const GByte *pabySrcData =
     445             :                     static_cast<const GByte *>(pData) +
     446       58762 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     447       58762 :                         nLineSpace +
     448       58762 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     449       58762 :                         nPixelSpace;
     450     3788880 :                 for (int iY = 0; iY < nValidY; ++iY)
     451             :                 {
     452     3730110 :                     GDALCopyWords64(
     453     3730110 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     454             :                         eBufType, static_cast<int>(nPixelSpace),
     455     3730110 :                         m_poGDS->m_pabyBlockBuf +
     456     3730110 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     457             :                         eDataType, nDTSize, nValidX);
     458             :                 }
     459       58767 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     460      117533 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     461       58767 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     462       58766 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     463             :                 {
     464           0 :                     return CE_Failure;
     465             :                 }
     466             :             }
     467             :         }
     468        5738 :         return CE_None;
     469             :     }
     470             : 
     471     5767910 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     472     5760930 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     473     5767910 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     474             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     475             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     476     5766280 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     477     5763740 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     478             : 
     479     5766280 :     m_poGDS->m_bLoadingOtherBands = false;
     480             : 
     481     5766280 :     return eErr;
     482             : }
     483             : 
     484             : /************************************************************************/
     485             : /*                        ComputeBlockId()                              */
     486             : /************************************************************************/
     487             : 
     488             : /** Computes the TIFF block identifier from the tile coordinate, band
     489             :  * number and planar configuration.
     490             :  */
     491     3292980 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     492             : {
     493     3292980 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     494     3292980 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     495             :     {
     496      662118 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     497             :     }
     498     2630870 :     return nBlockId;
     499             : }

Generated by: LCOV version 1.14