LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 238 247 96.4 %
Date: 2025-03-28 21:34:50 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      696813 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      28      696813 :     : m_poGDS(poDSIn)
      29             : {
      30      696704 :     poDS = poDSIn;
      31      696704 :     nBand = nBandIn;
      32             : 
      33             :     /* -------------------------------------------------------------------- */
      34             :     /*      Get the GDAL data type.                                         */
      35             :     /* -------------------------------------------------------------------- */
      36      696704 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      37      696704 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      38             : 
      39      696704 :     eDataType = GDT_Unknown;
      40             : 
      41      696704 :     if (nBitsPerSample <= 8)
      42             :     {
      43      689829 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      44          84 :             eDataType = GDT_Int8;
      45             :         else
      46      689745 :             eDataType = GDT_Byte;
      47             :     }
      48        6875 :     else if (nBitsPerSample <= 16)
      49             :     {
      50        2390 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      51        1180 :             eDataType = GDT_Int16;
      52             :         else
      53        1210 :             eDataType = GDT_UInt16;
      54             :     }
      55        4485 :     else if (nBitsPerSample == 32)
      56             :     {
      57        2912 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      58         459 :             eDataType = GDT_CInt16;
      59        2453 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      60        1701 :             eDataType = GDT_Float32;
      61         752 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      62         399 :             eDataType = GDT_Int32;
      63             :         else
      64         353 :             eDataType = GDT_UInt32;
      65             :     }
      66        1573 :     else if (nBitsPerSample == 64)
      67             :     {
      68        1251 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      69         718 :             eDataType = GDT_Float64;
      70         533 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      71         233 :             eDataType = GDT_CFloat32;
      72         300 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      73         212 :             eDataType = GDT_CInt32;
      74          88 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      75          52 :             eDataType = GDT_Int64;
      76             :         else
      77          36 :             eDataType = GDT_UInt64;
      78             :     }
      79         322 :     else if (nBitsPerSample == 128)
      80             :     {
      81         250 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      82         250 :             eDataType = GDT_CFloat64;
      83             :     }
      84             : 
      85             :     /* -------------------------------------------------------------------- */
      86             :     /*      Try to work out band color interpretation.                      */
      87             :     /* -------------------------------------------------------------------- */
      88      696704 :     bool bLookForExtraSamples = false;
      89             : 
      90      696704 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
      91             :     {
      92         162 :         m_eBandInterp = GCI_PaletteIndex;
      93             :     }
      94     1376340 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
      95      679737 :              (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR &&
      96         897 :               m_poGDS->m_nCompression == COMPRESSION_JPEG &&
      97         858 :               CPLTestBool(CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES"))))
      98             :     {
      99       17433 :         if (nBand == 1)
     100        5470 :             m_eBandInterp = GCI_RedBand;
     101       11963 :         else if (nBand == 2)
     102        5471 :             m_eBandInterp = GCI_GreenBand;
     103        6492 :         else if (nBand == 3)
     104        5471 :             m_eBandInterp = GCI_BlueBand;
     105             :         else
     106        1021 :             bLookForExtraSamples = true;
     107             :     }
     108      679167 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)
     109             :     {
     110          39 :         if (nBand == 1)
     111          13 :             m_eBandInterp = GCI_YCbCr_YBand;
     112          26 :         else if (nBand == 2)
     113          13 :             m_eBandInterp = GCI_YCbCr_CbBand;
     114          13 :         else if (nBand == 3)
     115          13 :             m_eBandInterp = GCI_YCbCr_CrBand;
     116             :         else
     117           0 :             bLookForExtraSamples = true;
     118             :     }
     119      679128 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)
     120             :     {
     121          96 :         if (nBand == 1)
     122          24 :             m_eBandInterp = GCI_CyanBand;
     123          72 :         else if (nBand == 2)
     124          24 :             m_eBandInterp = GCI_MagentaBand;
     125          48 :         else if (nBand == 3)
     126          24 :             m_eBandInterp = GCI_YellowBand;
     127          24 :         else if (nBand == 4)
     128          24 :             m_eBandInterp = GCI_BlackBand;
     129             :         else
     130           0 :             bLookForExtraSamples = true;
     131             :     }
     132      679032 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     133             :     {
     134       20603 :         m_eBandInterp = GCI_GrayIndex;
     135             :     }
     136             :     else
     137             :     {
     138      658429 :         bLookForExtraSamples = true;
     139             :     }
     140             : 
     141      696762 :     if (bLookForExtraSamples)
     142             :     {
     143      659139 :         uint16_t *v = nullptr;
     144      659139 :         uint16_t count = 0;
     145             : 
     146      659139 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     147             :         {
     148      593220 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     149      593220 :             const int nExpectedBaseSamples =
     150      594245 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     151        2050 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     152        1031 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB)        ? 3
     153          12 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR)      ? 3
     154           6 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_SEPARATED)  ? 4
     155             :                                                                       : 0;
     156             : 
     157      593220 :             if (nExpectedBaseSamples > 0 && nBand == nExpectedBaseSamples + 1 &&
     158             :                 nBaseSamples != nExpectedBaseSamples)
     159             :             {
     160           1 :                 ReportError(
     161             :                     CE_Warning, CPLE_AppDefined,
     162             :                     "Wrong number of ExtraSamples : %d. %d were expected",
     163           1 :                     count, m_poGDS->m_nSamplesPerPixel - nExpectedBaseSamples);
     164             :             }
     165             : 
     166      593220 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     167      593215 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     168      593198 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     169             :             {
     170        1097 :                 if (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA)
     171          17 :                     m_oGTiffMDMD.SetMetadataItem("ALPHA", "PREMULTIPLIED",
     172             :                                                  "IMAGE_STRUCTURE");
     173        1097 :                 m_eBandInterp = GCI_AlphaBand;
     174             :             }
     175             :             else
     176      592123 :                 m_eBandInterp = GCI_Undefined;
     177             :         }
     178             :         else
     179             :         {
     180       65919 :             m_eBandInterp = GCI_Undefined;
     181             :         }
     182             :     }
     183             : 
     184             :     /* -------------------------------------------------------------------- */
     185             :     /*      Establish block size for strip or tiles.                        */
     186             :     /* -------------------------------------------------------------------- */
     187      696762 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     188      696762 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     189      696762 :     nRasterXSize = m_poGDS->nRasterXSize;
     190      696762 :     nRasterYSize = m_poGDS->nRasterYSize;
     191      696762 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     192      696762 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     193      696762 : }
     194             : 
     195             : /************************************************************************/
     196             : /*                          ~GTiffRasterBand()                          */
     197             : /************************************************************************/
     198             : 
     199     1261599 : GTiffRasterBand::~GTiffRasterBand()
     200             : {
     201             :     // So that any future DropReferenceVirtualMem() will not try to access the
     202             :     // raster band object, but this would not conform to the advertised
     203             :     // contract.
     204      696841 :     if (!m_aSetPSelf.empty())
     205             :     {
     206           0 :         ReportError(CE_Warning, CPLE_AppDefined,
     207             :                     "Virtual memory objects still exist at GTiffRasterBand "
     208             :                     "destruction");
     209           0 :         std::set<GTiffRasterBand **>::iterator oIter = m_aSetPSelf.begin();
     210           0 :         for (; oIter != m_aSetPSelf.end(); ++oIter)
     211           0 :             *(*oIter) = nullptr;
     212             :     }
     213     1261598 : }
     214             : 
     215             : /************************************************************************/
     216             : /*                            IRasterIO()                               */
     217             : /************************************************************************/
     218             : 
     219     5373680 : CPLErr GTiffRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     220             :                                   int nXSize, int nYSize, void *pData,
     221             :                                   int nBufXSize, int nBufYSize,
     222             :                                   GDALDataType eBufType, GSpacing nPixelSpace,
     223             :                                   GSpacing nLineSpace,
     224             :                                   GDALRasterIOExtraArg *psExtraArg)
     225             : {
     226             : #if DEBUG_VERBOSE
     227             :     CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)", nXOff, nYOff, nXSize,
     228             :              nYSize, nBufXSize, nBufYSize);
     229             : #endif
     230             : 
     231             :     // Try to pass the request to the most appropriate overview dataset.
     232     5373680 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     233             :     {
     234      162004 :         int bTried = FALSE;
     235      162004 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     236      161647 :             ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     237      162004 :         const CPLErr eErr = TryOverviewRasterIO(
     238             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     239             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     240      162004 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     241      161647 :             --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     242      162004 :         if (bTried)
     243          44 :             return eErr;
     244             :     }
     245             : 
     246     5373640 :     if (m_poGDS->m_eVirtualMemIOUsage != GTiffDataset::VirtualMemIOEnum::NO)
     247             :     {
     248         904 :         const int nErr = m_poGDS->VirtualMemIO(
     249             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     250         452 :             eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
     251         452 :         if (nErr >= 0)
     252         363 :             return static_cast<CPLErr>(nErr);
     253             :     }
     254     5373270 :     if (m_poGDS->m_bDirectIO)
     255             :     {
     256             :         int nErr =
     257        2522 :             DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     258             :                      nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     259        2522 :         if (nErr >= 0)
     260        1409 :             return static_cast<CPLErr>(nErr);
     261             :     }
     262             : 
     263     5371860 :     bool bCanUseMultiThreadedRead = false;
     264     5369630 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     265     3106020 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     266    10741500 :         nYSize == nBufYSize && m_poGDS->IsMultiThreadedReadCompatible())
     267             :     {
     268         102 :         const int nBlockX1 = nXOff / nBlockXSize;
     269         102 :         const int nBlockY1 = nYOff / nBlockYSize;
     270         102 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     271         102 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     272         102 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     273         102 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     274         102 :         if (nXBlocks > 1 || nYBlocks > 1)
     275             :         {
     276          99 :             bCanUseMultiThreadedRead = true;
     277             :         }
     278             :     }
     279             : 
     280             :     // Cleanup data cached by below CacheMultiRange() call.
     281             :     struct BufferedDataFreer
     282             :     {
     283             :         void *m_pBufferedData = nullptr;
     284             :         TIFF *m_hTIFF = nullptr;
     285             : 
     286         256 :         void Init(void *pBufferedData, TIFF *hTIFF)
     287             :         {
     288         256 :             m_pBufferedData = pBufferedData;
     289         256 :             m_hTIFF = hTIFF;
     290         256 :         }
     291             : 
     292     5372010 :         ~BufferedDataFreer()
     293     5372010 :         {
     294     5372010 :             if (m_pBufferedData)
     295             :             {
     296          35 :                 VSIFree(m_pBufferedData);
     297          35 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     298             :                                         nullptr, nullptr);
     299             :             }
     300     5372010 :         }
     301             :     };
     302             : 
     303             :     // bufferedDataFreer must be left in this scope !
     304     5372160 :     BufferedDataFreer bufferedDataFreer;
     305             : 
     306     8161400 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     307     2788380 :         m_poGDS->HasOptimizedReadMultiRange())
     308             :     {
     309         262 :         if (bCanUseMultiThreadedRead &&
     310           3 :             VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF))->HasPRead())
     311             :         {
     312             :             // use the multi-threaded implementation rather than the multi-range
     313             :             // one
     314             :         }
     315             :         else
     316             :         {
     317         256 :             bCanUseMultiThreadedRead = false;
     318         256 :             GTiffDataset *poDSForCache = m_poGDS;
     319         256 :             int nBandForCache = nBand;
     320         256 :             if (!m_poGDS->m_bStreamingIn && m_poGDS->m_bBlockOrderRowMajor &&
     321         112 :                 m_poGDS->m_bLeaderSizeAsUInt4 &&
     322         112 :                 m_poGDS->m_bMaskInterleavedWithImagery &&
     323         102 :                 m_poGDS->m_poImageryDS)
     324             :             {
     325          63 :                 poDSForCache = m_poGDS->m_poImageryDS;
     326          63 :                 nBandForCache = 1;
     327             :             }
     328         256 :             bufferedDataFreer.Init(
     329             :                 poDSForCache->CacheMultiRange(nXOff, nYOff, nXSize, nYSize,
     330             :                                               nBufXSize, nBufYSize,
     331             :                                               &nBandForCache, 1, psExtraArg),
     332             :                 poDSForCache->m_hTIFF);
     333             :         }
     334             :     }
     335             : 
     336     5373020 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     337             :     {
     338     2909460 :         const int nBlockX1 = nXOff / nBlockXSize;
     339     2909460 :         const int nBlockY1 = nYOff / nBlockYSize;
     340     2909460 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     341     2909460 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     342     2909460 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     343     2909460 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     344             : 
     345     2909460 :         if (bCanUseMultiThreadedRead)
     346             :         {
     347         198 :             return m_poGDS->MultiThreadedRead(nXOff, nYOff, nXSize, nYSize,
     348          99 :                                               pData, eBufType, 1, &nBand,
     349          99 :                                               nPixelSpace, nLineSpace, 0);
     350             :         }
     351     2909360 :         else if (m_poGDS->nBands != 1 &&
     352      646974 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     353             :         {
     354             :             const GIntBig nRequiredMem =
     355      590389 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     356      590389 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     357      591605 :             if (nRequiredMem > GDALGetCacheMax64())
     358             :             {
     359        9060 :                 if (!m_poGDS->m_bHasWarnedDisableAggressiveBandCaching)
     360             :                 {
     361          14 :                     CPLDebug("GTiff",
     362             :                              "Disable aggressive band caching. "
     363             :                              "Cache not big enough. "
     364             :                              "At least " CPL_FRMT_GIB " bytes necessary",
     365             :                              nRequiredMem);
     366          14 :                     m_poGDS->m_bHasWarnedDisableAggressiveBandCaching = true;
     367             :                 }
     368        9060 :                 m_poGDS->m_bLoadingOtherBands = true;
     369             :             }
     370     2912040 :         }
     371             :     }
     372             : 
     373             :     // Write optimization when writing whole blocks, by-passing the block cache.
     374             :     // We require the block cache to be non instantiated to simplify things
     375             :     // (otherwise we might need to evict corresponding existing blocks from the
     376             :     // block cache).
     377     4726970 :     else if (eRWFlag == GF_Write &&
     378             :              // Could be extended to "odd bit" case, but more work
     379     2263540 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
     380     2111270 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     381       46886 :              !m_poGDS->m_bLoadedBlockDirty &&
     382       46825 :              (m_poGDS->nBands == 1 ||
     383        4350 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     384       45757 :              !m_poGDS->m_bLeaderSizeAsUInt4 && (nXOff % nBlockXSize) == 0 &&
     385       45656 :              (nYOff % nBlockYSize) == 0 &&
     386     4772660 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     387       45605 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     388             :     {
     389       45275 :         m_poGDS->Crystalize();
     390             : 
     391       45302 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     392           0 :             return CE_None;
     393             : 
     394       45302 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     395       45181 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     396       41212 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     397       41162 :             nLineSpace == nPixelSpace * nBlockXSize)
     398             :         {
     399             :             // If writing one single block with the right data type and layout,
     400             :             // we don't need a temporary buffer
     401             :             const int nBlockId =
     402       41345 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     403       41315 :             return m_poGDS->WriteEncodedTileOrStrip(
     404       41464 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     405             :         }
     406             : 
     407             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     408             :         // We could actually use any temporary buffer
     409        3836 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     410        3966 :                                   /* bReadFromDisk = */ false) != CE_None)
     411             :         {
     412           0 :             return CE_Failure;
     413             :         }
     414             : 
     415             :         // Iterate over all blocks defined by
     416             :         // [nXOff, nXOff+nXSize[ * [nYOff, nYOff+nYSize[
     417             :         // and write their content as a nBlockXSize x nBlockYSize strile
     418             :         // in a temporary buffer, before calling WriteEncodedTileOrStrip()
     419             :         // on it
     420        3966 :         const int nYBlockStart = nYOff / nBlockYSize;
     421        3966 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     422        3966 :         const int nXBlockStart = nXOff / nBlockXSize;
     423        3966 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     424       44614 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     425             :         {
     426             :             const int nValidY =
     427       40648 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     428       96922 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     429             :             {
     430             :                 const int nValidX =
     431       56274 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     432       56272 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     433             :                 {
     434             :                     // Make sure padding bytes at the right/bottom of the
     435             :                     // tile are initialized to zero.
     436        2842 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     437        2842 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     438        2842 :                                nDTSize);
     439             :                 }
     440       56272 :                 const GByte *pabySrcData =
     441             :                     static_cast<const GByte *>(pData) +
     442       56272 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     443       56272 :                         nLineSpace +
     444       56272 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     445       56272 :                         nPixelSpace;
     446     3734320 :                 for (int iY = 0; iY < nValidY; ++iY)
     447             :                 {
     448     3678040 :                     GDALCopyWords64(
     449     3678040 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     450             :                         eBufType, static_cast<int>(nPixelSpace),
     451     3678040 :                         m_poGDS->m_pabyBlockBuf +
     452     3678040 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     453             :                         eDataType, nDTSize, nValidX);
     454             :                 }
     455       56274 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     456      112548 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     457       56274 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     458       56274 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     459             :                 {
     460           0 :                     return CE_Failure;
     461             :                 }
     462             :             }
     463             :         }
     464        3966 :         return CE_None;
     465             :     }
     466             : 
     467     5330280 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     468     5322220 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     469     5330280 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     470             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     471             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     472     5326640 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     473     5323540 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     474             : 
     475     5326640 :     m_poGDS->m_bLoadingOtherBands = false;
     476             : 
     477     5326640 :     return eErr;
     478             : }
     479             : 
     480             : /************************************************************************/
     481             : /*                        ComputeBlockId()                              */
     482             : /************************************************************************/
     483             : 
     484             : /** Computes the TIFF block identifier from the tile coordinate, band
     485             :  * number and planar configuration.
     486             :  */
     487     3185990 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     488             : {
     489     3185990 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     490     3185990 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     491             :     {
     492      660027 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     493             :     }
     494     2525960 :     return nBlockId;
     495             : }

Generated by: LCOV version 1.14