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-05-31 00:00:17 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      833700 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      28      833700 :     : m_poGDS(poDSIn)
      29             : {
      30      833663 :     poDS = poDSIn;
      31      833663 :     nBand = nBandIn;
      32             : 
      33             :     /* -------------------------------------------------------------------- */
      34             :     /*      Get the GDAL data type.                                         */
      35             :     /* -------------------------------------------------------------------- */
      36      833663 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      37      833663 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      38             : 
      39      833663 :     eDataType = GDT_Unknown;
      40             : 
      41      833663 :     if (nBitsPerSample <= 8)
      42             :     {
      43      823026 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      44         310 :             eDataType = GDT_Int8;
      45             :         else
      46      822716 :             eDataType = GDT_Byte;
      47             :     }
      48       10637 :     else if (nBitsPerSample <= 16)
      49             :     {
      50        3220 :         if (nBitsPerSample == 16 && nSampleFormat == SAMPLEFORMAT_IEEEFP)
      51         248 :             eDataType = GDT_Float16;
      52        2972 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      53        1534 :             eDataType = GDT_Int16;
      54             :         else
      55        1438 :             eDataType = GDT_UInt16;
      56             :     }
      57        7417 :     else if (nBitsPerSample == 32)
      58             :     {
      59        4414 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      60         683 :             eDataType = GDT_CInt16;
      61        3731 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      62         224 :             eDataType = GDT_CFloat16;
      63        3507 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      64        2286 :             eDataType = GDT_Float32;
      65        1221 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      66         644 :             eDataType = GDT_Int32;
      67             :         else
      68         577 :             eDataType = GDT_UInt32;
      69             :     }
      70        3003 :     else if (nBitsPerSample == 64)
      71             :     {
      72        2457 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      73        1024 :             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      833663 :     bool bLookForExtraSamples = false;
      93             : 
      94      833663 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
      95             :     {
      96         172 :         m_eBandInterp = GCI_PaletteIndex;
      97             :     }
      98     1649680 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
      99      816170 :              (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       18068 :         if (nBand == 1)
     104        5679 :             m_eBandInterp = GCI_RedBand;
     105       12389 :         else if (nBand == 2)
     106        5684 :             m_eBandInterp = GCI_GreenBand;
     107        6705 :         else if (nBand == 3)
     108        5684 :             m_eBandInterp = GCI_BlueBand;
     109             :         else
     110        1021 :             bLookForExtraSamples = true;
     111             :     }
     112      815441 :     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      815402 :     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      815306 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     137             :     {
     138       25631 :         m_eBandInterp = GCI_GrayIndex;
     139             :     }
     140             :     else
     141             :     {
     142      789675 :         bLookForExtraSamples = true;
     143             :     }
     144             : 
     145      833681 :     if (bLookForExtraSamples)
     146             :     {
     147      790605 :         uint16_t *v = nullptr;
     148      790605 :         uint16_t count = 0;
     149             : 
     150      790605 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     151             :         {
     152      724679 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     153      724679 :             const int nExpectedBaseSamples =
     154      725704 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     155        2050 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     156        1031 :                 : (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      724679 :             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      724679 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     171      724674 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     172      724657 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     173             :             {
     174        1116 :                 if (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA)
     175          17 :                     m_oGTiffMDMD.SetMetadataItem("ALPHA", "PREMULTIPLIED",
     176             :                                                  "IMAGE_STRUCTURE");
     177        1116 :                 m_eBandInterp = GCI_AlphaBand;
     178             :             }
     179             :             else
     180      723563 :                 m_eBandInterp = GCI_Undefined;
     181             :         }
     182             :         else
     183             :         {
     184       65926 :             m_eBandInterp = GCI_Undefined;
     185             :         }
     186             :     }
     187             : 
     188             :     /* -------------------------------------------------------------------- */
     189             :     /*      Establish block size for strip or tiles.                        */
     190             :     /* -------------------------------------------------------------------- */
     191      833681 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     192      833681 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     193      833681 :     nRasterXSize = m_poGDS->nRasterXSize;
     194      833681 :     nRasterYSize = m_poGDS->nRasterYSize;
     195      833681 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     196      833681 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     197      833681 : }
     198             : 
     199             : /************************************************************************/
     200             : /*                          ~GTiffRasterBand()                          */
     201             : /************************************************************************/
     202             : 
     203     1535370 : 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      833720 :     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     1535367 : }
     218             : 
     219             : /************************************************************************/
     220             : /*                            IRasterIO()                               */
     221             : /************************************************************************/
     222             : 
     223     5714600 : 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     5714600 :     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     5714560 :     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     5714190 :     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     5712780 :     bool bCanUseMultiThreadedRead = false;
     268     5712470 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     269     3253720 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     270    11425300 :         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     5712750 :         ~BufferedDataFreer()
     297     5712750 :         {
     298     5712750 :             if (m_pBufferedData)
     299             :             {
     300          35 :                 VSIFree(m_pBufferedData);
     301          35 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     302             :                                         nullptr, nullptr);
     303             :             }
     304     5712750 :         }
     305             :     };
     306             : 
     307             :     // bufferedDataFreer must be left in this scope !
     308     5712720 :     BufferedDataFreer bufferedDataFreer;
     309             : 
     310     8468840 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     311     2756080 :         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     5712760 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     341             :     {
     342     2857920 :         const int nBlockX1 = nXOff / nBlockXSize;
     343     2857920 :         const int nBlockY1 = nYOff / nBlockYSize;
     344     2857920 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     345     2857920 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     346     2857920 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     347     2857920 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     348             : 
     349     2857920 :         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     2857820 :         else if (m_poGDS->nBands != 1 &&
     356      638527 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     357             :         {
     358             :             const GIntBig nRequiredMem =
     359      579847 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     360      579847 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     361      579857 :             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     2857810 :         }
     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     5313450 :     else if (eRWFlag == GF_Write &&
     382             :              // Could be extended to "odd bit" case, but more work
     383     2458790 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
     384     2306490 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     385       49348 :              !m_poGDS->m_bLoadedBlockDirty &&
     386       49378 :              (m_poGDS->nBands == 1 ||
     387        4471 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     388       48270 :              !m_poGDS->m_bLeaderSizeAsUInt4 && (nXOff % nBlockXSize) == 0 &&
     389       48205 :              (nYOff % nBlockYSize) == 0 &&
     390     5361540 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     391       48017 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     392             :     {
     393       47679 :         m_poGDS->Crystalize();
     394             : 
     395       47690 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     396           0 :             return CE_None;
     397             : 
     398       47690 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     399       47624 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     400       43712 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     401       41939 :             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       41951 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     407       42125 :             return m_poGDS->WriteEncodedTileOrStrip(
     408       42130 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     409             :         }
     410             : 
     411             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     412             :         // We could actually use any temporary buffer
     413        5673 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     414        5717 :                                   /* 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        5717 :         const int nYBlockStart = nYOff / nBlockYSize;
     425        5717 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     426        5717 :         const int nXBlockStart = nXOff / nBlockXSize;
     427        5717 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     428       48547 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     429             :         {
     430             :             const int nValidY =
     431       42830 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     432      101417 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     433             :             {
     434             :                 const int nValidX =
     435       58587 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     436       58582 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     437             :                 {
     438             :                     // Make sure padding bytes at the right/bottom of the
     439             :                     // tile are initialized to zero.
     440        2873 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     441        2873 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     442        2873 :                                nDTSize);
     443             :                 }
     444       58582 :                 const GByte *pabySrcData =
     445             :                     static_cast<const GByte *>(pData) +
     446       58582 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     447       58582 :                         nLineSpace +
     448       58582 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     449       58582 :                         nPixelSpace;
     450     3782790 :                 for (int iY = 0; iY < nValidY; ++iY)
     451             :                 {
     452     3724200 :                     GDALCopyWords64(
     453     3724200 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     454             :                         eBufType, static_cast<int>(nPixelSpace),
     455     3724200 :                         m_poGDS->m_pabyBlockBuf +
     456     3724200 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     457             :                         eDataType, nDTSize, nValidX);
     458             :                 }
     459       58588 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     460      117173 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     461       58587 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     462       58586 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     463             :                 {
     464           0 :                     return CE_Failure;
     465             :                 }
     466             :             }
     467             :         }
     468        5717 :         return CE_None;
     469             :     }
     470             : 
     471     5664870 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     472     5662330 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     473     5664870 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     474             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     475             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     476     5664780 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     477     5662240 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     478             : 
     479     5664780 :     m_poGDS->m_bLoadingOtherBands = false;
     480             : 
     481     5664780 :     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     3194840 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     492             : {
     493     3194840 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     494     3194840 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     495             :     {
     496      662624 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     497             :     }
     498     2532220 :     return nBlockId;
     499             : }

Generated by: LCOV version 1.14