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-10-21 22:35:35 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 "gdal_priv.h"
      21             : #include "cpl_vsi_virtual.h"
      22             : #include "tifvsi.h"
      23             : 
      24             : /************************************************************************/
      25             : /*                           GTiffRasterBand()                          */
      26             : /************************************************************************/
      27             : 
      28     1032150 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      29     1032150 :     : m_poGDS(poDSIn)
      30             : {
      31     1032090 :     poDS = poDSIn;
      32     1032090 :     nBand = nBandIn;
      33             : 
      34             :     /* -------------------------------------------------------------------- */
      35             :     /*      Get the GDAL data type.                                         */
      36             :     /* -------------------------------------------------------------------- */
      37     1032090 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      38     1032090 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      39             : 
      40     1032090 :     eDataType = GDT_Unknown;
      41             : 
      42     1032090 :     if (nBitsPerSample <= 8)
      43             :     {
      44      889871 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      45         310 :             eDataType = GDT_Int8;
      46             :         else
      47      889561 :             eDataType = GDT_Byte;
      48             :     }
      49      142221 :     else if (nBitsPerSample <= 16)
      50             :     {
      51      134423 :         if (nBitsPerSample == 16 && nSampleFormat == SAMPLEFORMAT_IEEEFP)
      52         248 :             eDataType = GDT_Float16;
      53      134175 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      54       67148 :             eDataType = GDT_Int16;
      55             :         else
      56       67027 :             eDataType = GDT_UInt16;
      57             :     }
      58        7798 :     else if (nBitsPerSample == 32)
      59             :     {
      60        4673 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      61         683 :             eDataType = GDT_CInt16;
      62        3990 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      63         224 :             eDataType = GDT_CFloat16;
      64        3766 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      65        2544 :             eDataType = GDT_Float32;
      66        1222 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      67         645 :             eDataType = GDT_Int32;
      68             :         else
      69         577 :             eDataType = GDT_UInt32;
      70             :     }
      71        3125 :     else if (nBitsPerSample == 64)
      72             :     {
      73        2579 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      74        1137 :             eDataType = GDT_Float64;
      75        1442 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      76         467 :             eDataType = GDT_CFloat32;
      77         975 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      78         436 :             eDataType = GDT_CInt32;
      79         539 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      80         278 :             eDataType = GDT_Int64;
      81             :         else
      82         261 :             eDataType = GDT_UInt64;
      83             :     }
      84         546 :     else if (nBitsPerSample == 128)
      85             :     {
      86         474 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      87         474 :             eDataType = GDT_CFloat64;
      88             :     }
      89             : 
      90             :     /* -------------------------------------------------------------------- */
      91             :     /*      Try to work out band color interpretation.                      */
      92             :     /* -------------------------------------------------------------------- */
      93     1032090 :     bool bLookForExtraSamples = false;
      94             : 
      95     1032090 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
      96             :     {
      97         171 :         m_eBandInterp = GCI_PaletteIndex;
      98             :     }
      99     2045950 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
     100     1014020 :              (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR &&
     101         858 :               m_poGDS->m_nCompression == COMPRESSION_JPEG &&
     102         819 :               CPLTestBool(CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES"))))
     103             :     {
     104       18661 :         if (nBand == 1)
     105        5875 :             m_eBandInterp = GCI_RedBand;
     106       12786 :         else if (nBand == 2)
     107        5883 :             m_eBandInterp = GCI_GreenBand;
     108        6903 :         else if (nBand == 3)
     109        5882 :             m_eBandInterp = GCI_BlueBand;
     110             :         else
     111        1021 :             bLookForExtraSamples = true;
     112             :     }
     113     1013280 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)
     114             :     {
     115          39 :         if (nBand == 1)
     116          13 :             m_eBandInterp = GCI_YCbCr_YBand;
     117          26 :         else if (nBand == 2)
     118          13 :             m_eBandInterp = GCI_YCbCr_CbBand;
     119          13 :         else if (nBand == 3)
     120          13 :             m_eBandInterp = GCI_YCbCr_CrBand;
     121             :         else
     122           0 :             bLookForExtraSamples = true;
     123             :     }
     124     1013240 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)
     125             :     {
     126          96 :         if (nBand == 1)
     127          24 :             m_eBandInterp = GCI_CyanBand;
     128          72 :         else if (nBand == 2)
     129          24 :             m_eBandInterp = GCI_MagentaBand;
     130          48 :         else if (nBand == 3)
     131          24 :             m_eBandInterp = GCI_YellowBand;
     132          24 :         else if (nBand == 4)
     133          24 :             m_eBandInterp = GCI_BlackBand;
     134             :         else
     135           0 :             bLookForExtraSamples = true;
     136             :     }
     137     1013140 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     138             :     {
     139       26241 :         m_eBandInterp = GCI_GrayIndex;
     140             :     }
     141             :     else
     142             :     {
     143      986899 :         bLookForExtraSamples = true;
     144             :     }
     145             : 
     146     1032110 :     if (bLookForExtraSamples)
     147             :     {
     148      987775 :         uint16_t *v = nullptr;
     149      987775 :         uint16_t count = 0;
     150             : 
     151      987775 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     152             :         {
     153      921855 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     154      921855 :             const int nExpectedBaseSamples =
     155      922880 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     156        2050 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     157        1031 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB)        ? 3
     158          12 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)      ? 3
     159           6 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)  ? 4
     160             :                                                                       : 0;
     161             : 
     162      921855 :             if (nExpectedBaseSamples > 0 && nBand == nExpectedBaseSamples + 1 &&
     163             :                 nBaseSamples != nExpectedBaseSamples)
     164             :             {
     165           1 :                 ReportError(
     166             :                     CE_Warning, CPLE_AppDefined,
     167             :                     "Wrong number of ExtraSamples : %d. %d were expected",
     168           1 :                     count, m_poGDS->m_nSamplesPerPixel - nExpectedBaseSamples);
     169             :             }
     170             : 
     171      921855 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     172      921850 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     173      921833 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     174             :             {
     175        1119 :                 if (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA)
     176          17 :                     m_oGTiffMDMD.SetMetadataItem("ALPHA", "PREMULTIPLIED",
     177             :                                                  "IMAGE_STRUCTURE");
     178        1119 :                 m_eBandInterp = GCI_AlphaBand;
     179             :             }
     180             :             else
     181      920736 :                 m_eBandInterp = GCI_Undefined;
     182             :         }
     183             :         else
     184             :         {
     185       65920 :             m_eBandInterp = GCI_Undefined;
     186             :         }
     187             :     }
     188             : 
     189             :     /* -------------------------------------------------------------------- */
     190             :     /*      Establish block size for strip or tiles.                        */
     191             :     /* -------------------------------------------------------------------- */
     192     1032110 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     193     1032110 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     194     1032110 :     nRasterXSize = m_poGDS->nRasterXSize;
     195     1032110 :     nRasterYSize = m_poGDS->nRasterYSize;
     196     1032110 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     197     1032110 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     198     1032110 : }
     199             : 
     200             : /************************************************************************/
     201             : /*                          ~GTiffRasterBand()                          */
     202             : /************************************************************************/
     203             : 
     204     1932274 : GTiffRasterBand::~GTiffRasterBand()
     205             : {
     206             :     // So that any future DropReferenceVirtualMem() will not try to access the
     207             :     // raster band object, but this would not conform to the advertised
     208             :     // contract.
     209     1032170 :     if (!m_aSetPSelf.empty())
     210             :     {
     211           0 :         ReportError(CE_Warning, CPLE_AppDefined,
     212             :                     "Virtual memory objects still exist at GTiffRasterBand "
     213             :                     "destruction");
     214           0 :         std::set<GTiffRasterBand **>::iterator oIter = m_aSetPSelf.begin();
     215           0 :         for (; oIter != m_aSetPSelf.end(); ++oIter)
     216           0 :             *(*oIter) = nullptr;
     217             :     }
     218     1932264 : }
     219             : 
     220             : /************************************************************************/
     221             : /*                            IRasterIO()                               */
     222             : /************************************************************************/
     223             : 
     224     5817160 : CPLErr GTiffRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     225             :                                   int nXSize, int nYSize, void *pData,
     226             :                                   int nBufXSize, int nBufYSize,
     227             :                                   GDALDataType eBufType, GSpacing nPixelSpace,
     228             :                                   GSpacing nLineSpace,
     229             :                                   GDALRasterIOExtraArg *psExtraArg)
     230             : {
     231             : #if DEBUG_VERBOSE
     232             :     CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)", nXOff, nYOff, nXSize,
     233             :              nYSize, nBufXSize, nBufYSize);
     234             : #endif
     235             : 
     236             :     // Try to pass the request to the most appropriate overview dataset.
     237     5817160 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     238             :     {
     239      362408 :         int bTried = FALSE;
     240      362408 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     241      362040 :             ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     242      362408 :         const CPLErr eErr = TryOverviewRasterIO(
     243             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     244             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     245      362408 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     246      362040 :             --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     247      362408 :         if (bTried)
     248          44 :             return eErr;
     249             :     }
     250             : 
     251     5817120 :     if (m_poGDS->m_eVirtualMemIOUsage != GTiffDataset::VirtualMemIOEnum::NO)
     252             :     {
     253         904 :         const int nErr = m_poGDS->VirtualMemIO(
     254             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     255         452 :             eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
     256         452 :         if (nErr >= 0)
     257         363 :             return static_cast<CPLErr>(nErr);
     258             :     }
     259     5816760 :     if (m_poGDS->m_bDirectIO)
     260             :     {
     261             :         int nErr =
     262        2522 :             DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     263             :                      nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     264        2522 :         if (nErr >= 0)
     265        1409 :             return static_cast<CPLErr>(nErr);
     266             :     }
     267             : 
     268     5815350 :     bool bCanUseMultiThreadedRead = false;
     269     5815090 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     270     3356060 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     271    11630400 :         nYSize == nBufYSize && m_poGDS->IsMultiThreadedReadCompatible())
     272             :     {
     273         103 :         const int nBlockX1 = nXOff / nBlockXSize;
     274         103 :         const int nBlockY1 = nYOff / nBlockYSize;
     275         103 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     276         103 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     277         103 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     278         103 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     279         103 :         if (nXBlocks > 1 || nYBlocks > 1)
     280             :         {
     281         100 :             bCanUseMultiThreadedRead = true;
     282             :         }
     283             :     }
     284             : 
     285             :     // Cleanup data cached by below CacheMultiRange() call.
     286             :     struct BufferedDataFreer
     287             :     {
     288             :         void *m_pBufferedData = nullptr;
     289             :         TIFF *m_hTIFF = nullptr;
     290             : 
     291         254 :         void Init(void *pBufferedData, TIFF *hTIFF)
     292             :         {
     293         254 :             m_pBufferedData = pBufferedData;
     294         254 :             m_hTIFF = hTIFF;
     295         254 :         }
     296             : 
     297     5815330 :         ~BufferedDataFreer()
     298     5815330 :         {
     299     5815330 :             if (m_pBufferedData)
     300             :             {
     301          34 :                 VSIFree(m_pBufferedData);
     302          34 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     303             :                                         nullptr, nullptr);
     304             :             }
     305     5815330 :         }
     306             :     };
     307             : 
     308             :     // bufferedDataFreer must be left in this scope !
     309     5815430 :     BufferedDataFreer bufferedDataFreer;
     310             : 
     311     8673680 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     312     2858360 :         m_poGDS->HasOptimizedReadMultiRange())
     313             :     {
     314         262 :         if (bCanUseMultiThreadedRead &&
     315           4 :             VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF))->HasPRead())
     316             :         {
     317             :             // use the multi-threaded implementation rather than the multi-range
     318             :             // one
     319             :         }
     320             :         else
     321             :         {
     322         254 :             bCanUseMultiThreadedRead = false;
     323         254 :             GTiffDataset *poDSForCache = m_poGDS;
     324         254 :             int nBandForCache = nBand;
     325         254 :             if (!m_poGDS->m_bStreamingIn && m_poGDS->m_bBlockOrderRowMajor &&
     326         110 :                 m_poGDS->m_bLeaderSizeAsUInt4 &&
     327         110 :                 m_poGDS->m_bMaskInterleavedWithImagery &&
     328         100 :                 m_poGDS->m_poImageryDS)
     329             :             {
     330          62 :                 poDSForCache = m_poGDS->m_poImageryDS;
     331          62 :                 nBandForCache = 1;
     332             :             }
     333         254 :             bufferedDataFreer.Init(
     334             :                 poDSForCache->CacheMultiRange(nXOff, nYOff, nXSize, nYSize,
     335             :                                               nBufXSize, nBufYSize,
     336             :                                               &nBandForCache, 1, psExtraArg),
     337             :                 poDSForCache->m_hTIFF);
     338             :         }
     339             :     }
     340             : 
     341     5815320 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     342             :     {
     343     2960310 :         const int nBlockX1 = nXOff / nBlockXSize;
     344     2960310 :         const int nBlockY1 = nYOff / nBlockYSize;
     345     2960310 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     346     2960310 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     347     2960310 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     348     2960310 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     349             : 
     350     2960310 :         if (bCanUseMultiThreadedRead)
     351             :         {
     352         200 :             return m_poGDS->MultiThreadedRead(nXOff, nYOff, nXSize, nYSize,
     353         100 :                                               pData, eBufType, 1, &nBand,
     354         100 :                                               nPixelSpace, nLineSpace, 0);
     355             :         }
     356     2960210 :         else if (m_poGDS->nBands != 1 &&
     357      738291 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     358             :         {
     359             :             const GIntBig nRequiredMem =
     360      678777 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     361      678777 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     362      678846 :             if (nRequiredMem > GDALGetCacheMax64())
     363             :             {
     364        9061 :                 if (!m_poGDS->m_bHasWarnedDisableAggressiveBandCaching)
     365             :                 {
     366          15 :                     CPLDebug("GTiff",
     367             :                              "Disable aggressive band caching. "
     368             :                              "Cache not big enough. "
     369             :                              "At least " CPL_FRMT_GIB " bytes necessary",
     370             :                              nRequiredMem);
     371          15 :                     m_poGDS->m_bHasWarnedDisableAggressiveBandCaching = true;
     372             :                 }
     373        9061 :                 m_poGDS->m_bLoadingOtherBands = true;
     374             :             }
     375     2960260 :         }
     376             :     }
     377             : 
     378             :     // Write optimization when writing whole blocks, by-passing the block cache.
     379             :     // We require the block cache to be non instantiated to simplify things
     380             :     // (otherwise we might need to evict corresponding existing blocks from the
     381             :     // block cache).
     382     5314030 :     else if (eRWFlag == GF_Write &&
     383             :              // Could be extended to "odd bit" case, but more work
     384     2459040 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSizeBits(eDataType) &&
     385     2306860 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     386       49686 :              !m_poGDS->m_bLoadedBlockDirty &&
     387       49673 :              (m_poGDS->nBands == 1 ||
     388        4488 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     389       48584 :              !m_poGDS->m_bLeaderSizeAsUInt4 && (nXOff % nBlockXSize) == 0 &&
     390       48543 :              (nYOff % nBlockYSize) == 0 &&
     391     5362420 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     392       48379 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     393             :     {
     394       48032 :         m_poGDS->Crystalize();
     395             : 
     396       48035 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     397           0 :             return CE_None;
     398             : 
     399       48035 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     400       48039 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     401       44017 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     402       42269 :             nLineSpace == nPixelSpace * nBlockXSize)
     403             :         {
     404             :             // If writing one single block with the right data type and layout,
     405             :             // we don't need a temporary buffer
     406             :             const int nBlockId =
     407       42276 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     408       42272 :             return m_poGDS->WriteEncodedTileOrStrip(
     409       42276 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     410             :         }
     411             : 
     412             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     413             :         // We could actually use any temporary buffer
     414        5763 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     415        5761 :                                   /* bReadFromDisk = */ false) != CE_None)
     416             :         {
     417           0 :             return CE_Failure;
     418             :         }
     419             : 
     420             :         // Iterate over all blocks defined by
     421             :         // [nXOff, nXOff+nXSize[ * [nYOff, nYOff+nYSize[
     422             :         // and write their content as a nBlockXSize x nBlockYSize strile
     423             :         // in a temporary buffer, before calling WriteEncodedTileOrStrip()
     424             :         // on it
     425        5761 :         const int nYBlockStart = nYOff / nBlockYSize;
     426        5761 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     427        5761 :         const int nXBlockStart = nXOff / nBlockXSize;
     428        5761 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     429       49756 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     430             :         {
     431             :             const int nValidY =
     432       43995 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     433      103968 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     434             :             {
     435             :                 const int nValidX =
     436       59973 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     437       59958 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     438             :                 {
     439             :                     // Make sure padding bytes at the right/bottom of the
     440             :                     // tile are initialized to zero.
     441        2977 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     442        2977 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     443        2977 :                                nDTSize);
     444             :                 }
     445       59958 :                 const GByte *pabySrcData =
     446             :                     static_cast<const GByte *>(pData) +
     447       59958 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     448       59958 :                         nLineSpace +
     449       59958 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     450       59958 :                         nPixelSpace;
     451     3811830 :                 for (int iY = 0; iY < nValidY; ++iY)
     452             :                 {
     453     3751850 :                     GDALCopyWords64(
     454     3751850 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     455             :                         eBufType, static_cast<int>(nPixelSpace),
     456     3751850 :                         m_poGDS->m_pabyBlockBuf +
     457     3751850 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     458             :                         eDataType, nDTSize, nValidX);
     459             :                 }
     460       59975 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     461      119942 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     462       59969 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     463       59973 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     464             :                 {
     465           0 :                     return CE_Failure;
     466             :                 }
     467             :             }
     468             :         }
     469        5761 :         return CE_None;
     470             :     }
     471             : 
     472     5767230 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     473     5764790 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     474     5767230 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     475             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     476             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     477     5767290 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     478     5764750 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     479             : 
     480     5767290 :     m_poGDS->m_bLoadingOtherBands = false;
     481             : 
     482     5767290 :     return eErr;
     483             : }
     484             : 
     485             : /************************************************************************/
     486             : /*                        ComputeBlockId()                              */
     487             : /************************************************************************/
     488             : 
     489             : /** Computes the TIFF block identifier from the tile coordinate, band
     490             :  * number and planar configuration.
     491             :  */
     492     3296760 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     493             : {
     494     3296760 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     495     3296760 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     496             :     {
     497      663981 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     498             :     }
     499     2632780 :     return nBlockId;
     500             : }

Generated by: LCOV version 1.14