LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 237 246 96.3 %
Date: 2025-01-18 12:42:00 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      695951 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      28      695951 :     : m_poGDS(poDSIn)
      29             : {
      30      695889 :     poDS = poDSIn;
      31      695889 :     nBand = nBandIn;
      32             : 
      33             :     /* -------------------------------------------------------------------- */
      34             :     /*      Get the GDAL data type.                                         */
      35             :     /* -------------------------------------------------------------------- */
      36      695889 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      37      695889 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      38             : 
      39      695889 :     eDataType = GDT_Unknown;
      40             : 
      41      695889 :     if (nBitsPerSample <= 8)
      42             :     {
      43      689118 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      44          80 :             eDataType = GDT_Int8;
      45             :         else
      46      689038 :             eDataType = GDT_Byte;
      47             :     }
      48        6771 :     else if (nBitsPerSample <= 16)
      49             :     {
      50        2393 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      51        1186 :             eDataType = GDT_Int16;
      52             :         else
      53        1207 :             eDataType = GDT_UInt16;
      54             :     }
      55        4378 :     else if (nBitsPerSample == 32)
      56             :     {
      57        2900 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      58         461 :             eDataType = GDT_CInt16;
      59        2439 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      60        1681 :             eDataType = GDT_Float32;
      61         758 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      62         402 :             eDataType = GDT_Int32;
      63             :         else
      64         356 :             eDataType = GDT_UInt32;
      65             :     }
      66        1478 :     else if (nBitsPerSample == 64)
      67             :     {
      68        1154 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      69         617 :             eDataType = GDT_Float64;
      70         537 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      71         235 :             eDataType = GDT_CFloat32;
      72         302 :         else if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      73         214 :             eDataType = GDT_CInt32;
      74          88 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      75          52 :             eDataType = GDT_Int64;
      76             :         else
      77          36 :             eDataType = GDT_UInt64;
      78             :     }
      79         324 :     else if (nBitsPerSample == 128)
      80             :     {
      81         252 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP)
      82         252 :             eDataType = GDT_CFloat64;
      83             :     }
      84             : 
      85             :     /* -------------------------------------------------------------------- */
      86             :     /*      Try to work out band color interpretation.                      */
      87             :     /* -------------------------------------------------------------------- */
      88      695889 :     bool bLookForExtraSamples = false;
      89             : 
      90      695889 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
      91             :     {
      92         161 :         m_eBandInterp = GCI_PaletteIndex;
      93             :     }
      94     1375340 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
      95      679594 :              (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       16905 :         if (nBand == 1)
     100        5297 :             m_eBandInterp = GCI_RedBand;
     101       11608 :         else if (nBand == 2)
     102        5299 :             m_eBandInterp = GCI_GreenBand;
     103        6309 :         else if (nBand == 3)
     104        5299 :             m_eBandInterp = GCI_BlueBand;
     105             :         else
     106        1010 :             bLookForExtraSamples = true;
     107             :     }
     108      678844 :     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      678805 :     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      678709 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     133             :     {
     134       20667 :         m_eBandInterp = GCI_GrayIndex;
     135             :     }
     136             :     else
     137             :     {
     138      658042 :         bLookForExtraSamples = true;
     139             :     }
     140             : 
     141      695910 :     if (bLookForExtraSamples)
     142             :     {
     143      659005 :         uint16_t *v = nullptr;
     144      659005 :         uint16_t count = 0;
     145             : 
     146      659005 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     147             :         {
     148      593132 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     149      593132 :             const int nExpectedBaseSamples =
     150      594148 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     151        2032 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     152        1022 :                 : (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      593132 :             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      593132 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     167      593127 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     168      593110 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     169             :             {
     170        1088 :                 if (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA)
     171          17 :                     m_oGTiffMDMD.SetMetadataItem("ALPHA", "PREMULTIPLIED",
     172             :                                                  "IMAGE_STRUCTURE");
     173        1088 :                 m_eBandInterp = GCI_AlphaBand;
     174             :             }
     175             :             else
     176      592044 :                 m_eBandInterp = GCI_Undefined;
     177             :         }
     178             :         else
     179             :         {
     180       65873 :             m_eBandInterp = GCI_Undefined;
     181             :         }
     182             :     }
     183             : 
     184             :     /* -------------------------------------------------------------------- */
     185             :     /*      Establish block size for strip or tiles.                        */
     186             :     /* -------------------------------------------------------------------- */
     187      695910 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     188      695910 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     189      695910 :     nRasterXSize = m_poGDS->nRasterXSize;
     190      695910 :     nRasterYSize = m_poGDS->nRasterYSize;
     191      695910 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     192      695910 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     193      695910 : }
     194             : 
     195             : /************************************************************************/
     196             : /*                          ~GTiffRasterBand()                          */
     197             : /************************************************************************/
     198             : 
     199     1259871 : 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      695955 :     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     1259867 : }
     214             : 
     215             : /************************************************************************/
     216             : /*                            IRasterIO()                               */
     217             : /************************************************************************/
     218             : 
     219     5409770 : 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     5409770 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     233             :     {
     234      161938 :         int bTried = FALSE;
     235      161938 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     236      161582 :             ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     237      161938 :         const CPLErr eErr = TryOverviewRasterIO(
     238             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     239             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     240      161938 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     241      161582 :             --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     242      161938 :         if (bTried)
     243          44 :             return eErr;
     244             :     }
     245             : 
     246     5409730 :     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     5409370 :     if (m_poGDS->m_bDirectIO)
     255             :     {
     256             :         int nErr =
     257        2098 :             DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     258             :                      nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     259        2098 :         if (nErr >= 0)
     260         985 :             return static_cast<CPLErr>(nErr);
     261             :     }
     262             : 
     263     5408380 :     bool bCanUseMultiThreadedRead = false;
     264     5408080 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     265     3147160 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     266    10816500 :         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         250 :         void Init(void *pBufferedData, TIFF *hTIFF)
     287             :         {
     288         250 :             m_pBufferedData = pBufferedData;
     289         250 :             m_hTIFF = hTIFF;
     290         250 :         }
     291             : 
     292     5408550 :         ~BufferedDataFreer()
     293     5408550 :         {
     294     5408550 :             if (m_pBufferedData)
     295             :             {
     296          35 :                 VSIFree(m_pBufferedData);
     297          35 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     298             :                                         nullptr, nullptr);
     299             :             }
     300     5408550 :         }
     301             :     };
     302             : 
     303             :     // bufferedDataFreer must be left in this scope !
     304     5408660 :     BufferedDataFreer bufferedDataFreer;
     305             : 
     306     8238400 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     307     2830100 :         m_poGDS->HasOptimizedReadMultiRange())
     308             :     {
     309         256 :         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         250 :             bCanUseMultiThreadedRead = false;
     318         250 :             GTiffRasterBand *poBandForCache = this;
     319         250 :             if (!m_poGDS->m_bStreamingIn && m_poGDS->m_bBlockOrderRowMajor &&
     320         106 :                 m_poGDS->m_bLeaderSizeAsUInt4 &&
     321         106 :                 m_poGDS->m_bMaskInterleavedWithImagery &&
     322         102 :                 m_poGDS->m_poImageryDS)
     323             :             {
     324          63 :                 poBandForCache = cpl::down_cast<GTiffRasterBand *>(
     325          63 :                     m_poGDS->m_poImageryDS->GetRasterBand(1));
     326             :             }
     327         250 :             bufferedDataFreer.Init(poBandForCache->CacheMultiRange(
     328             :                                        nXOff, nYOff, nXSize, nYSize, nBufXSize,
     329             :                                        nBufYSize, psExtraArg),
     330         250 :                                    poBandForCache->m_poGDS->m_hTIFF);
     331             :         }
     332             :     }
     333             : 
     334     5408290 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     335             :     {
     336     2951820 :         const int nBlockX1 = nXOff / nBlockXSize;
     337     2951820 :         const int nBlockY1 = nYOff / nBlockYSize;
     338     2951820 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     339     2951820 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     340     2951820 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     341     2951820 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     342             : 
     343     2951820 :         if (bCanUseMultiThreadedRead)
     344             :         {
     345         198 :             return m_poGDS->MultiThreadedRead(nXOff, nYOff, nXSize, nYSize,
     346          99 :                                               pData, eBufType, 1, &nBand,
     347          99 :                                               nPixelSpace, nLineSpace, 0);
     348             :         }
     349     2951720 :         else if (m_poGDS->nBands != 1 &&
     350      688543 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     351             :         {
     352             :             const GIntBig nRequiredMem =
     353      636647 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     354      636647 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     355      636599 :             if (nRequiredMem > GDALGetCacheMax64())
     356             :             {
     357        9060 :                 if (!m_poGDS->m_bHasWarnedDisableAggressiveBandCaching)
     358             :                 {
     359          14 :                     CPLDebug("GTiff",
     360             :                              "Disable aggressive band caching. "
     361             :                              "Cache not big enough. "
     362             :                              "At least " CPL_FRMT_GIB " bytes necessary",
     363             :                              nRequiredMem);
     364          14 :                     m_poGDS->m_bHasWarnedDisableAggressiveBandCaching = true;
     365             :                 }
     366        9060 :                 m_poGDS->m_bLoadingOtherBands = true;
     367             :             }
     368     2951670 :         }
     369             :     }
     370             : 
     371             :     // Write optimization when writing whole blocks, by-passing the block cache.
     372             :     // We require the block cache to be non instantiated to simplify things
     373             :     // (otherwise we might need to evict corresponding existing blocks from the
     374             :     // block cache).
     375     4717380 :     else if (eRWFlag == GF_Write &&
     376             :              // Could be extended to "odd bit" case, but more work
     377     2260930 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
     378     2108760 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     379       44417 :              !m_poGDS->m_bLoadedBlockDirty &&
     380       44420 :              (m_poGDS->nBands == 1 ||
     381        1760 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     382       43363 :              (nXOff % nBlockXSize) == 0 && (nYOff % nBlockYSize) == 0 &&
     383     4760570 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     384       43182 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     385             :     {
     386       42887 :         m_poGDS->Crystalize();
     387             : 
     388       42889 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     389           0 :             return CE_None;
     390             : 
     391       42889 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     392       42887 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     393       41516 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     394       41460 :             nLineSpace == nPixelSpace * nBlockXSize)
     395             :         {
     396             :             // If writing one single block with the right data type and layout,
     397             :             // we don't need a temporary buffer
     398             :             const int nBlockId =
     399       41464 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     400       41462 :             return m_poGDS->WriteEncodedTileOrStrip(
     401       41461 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     402             :         }
     403             : 
     404             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     405             :         // We could actually use any temporary buffer
     406        1423 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     407        1428 :                                   /* bReadFromDisk = */ false) != CE_None)
     408             :         {
     409           0 :             return CE_Failure;
     410             :         }
     411             : 
     412             :         // Iterate over all blocks defined by
     413             :         // [nXOff, nXOff+nXSize[ * [nYOff, nYOff+nYSize[
     414             :         // and write their content as a nBlockXSize x nBlockYSize strile
     415             :         // in a temporary buffer, before calling WriteEncodedTileOrStrip()
     416             :         // on it
     417        1428 :         const int nYBlockStart = nYOff / nBlockYSize;
     418        1428 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     419        1428 :         const int nXBlockStart = nXOff / nBlockXSize;
     420        1428 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     421       25783 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     422             :         {
     423             :             const int nValidY =
     424       24355 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     425       62476 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     426             :             {
     427             :                 const int nValidX =
     428       38121 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     429       38121 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     430             :                 {
     431             :                     // Make sure padding bytes at the right/bottom of the
     432             :                     // tile are initialized to zero.
     433        2216 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     434        2216 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     435        2216 :                                nDTSize);
     436             :                 }
     437       38121 :                 const GByte *pabySrcData =
     438             :                     static_cast<const GByte *>(pData) +
     439       38121 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     440       38121 :                         nLineSpace +
     441       38121 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     442       38121 :                         nPixelSpace;
     443     1249950 :                 for (int iY = 0; iY < nValidY; ++iY)
     444             :                 {
     445     1211830 :                     GDALCopyWords64(
     446     1211830 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     447             :                         eBufType, static_cast<int>(nPixelSpace),
     448     1211830 :                         m_poGDS->m_pabyBlockBuf +
     449     1211830 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     450             :                         eDataType, nDTSize, nValidX);
     451             :                 }
     452       38121 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     453       76242 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     454       38121 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     455       38121 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     456             :                 {
     457           0 :                     return CE_Failure;
     458             :                 }
     459             :             }
     460             :         }
     461        1428 :         return CE_None;
     462             :     }
     463             : 
     464     5365240 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     465     5363020 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     466     5365240 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     467             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     468             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     469     5365670 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     470     5363130 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     471             : 
     472     5365670 :     m_poGDS->m_bLoadingOtherBands = false;
     473             : 
     474     5365670 :     return eErr;
     475             : }
     476             : 
     477             : /************************************************************************/
     478             : /*                        ComputeBlockId()                              */
     479             : /************************************************************************/
     480             : 
     481             : /** Computes the TIFF block identifier from the tile coordinate, band
     482             :  * number and planar configuration.
     483             :  */
     484     3150560 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     485             : {
     486     3150560 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     487     3150560 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     488             :     {
     489      403297 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     490             :     }
     491     2747260 :     return nBlockId;
     492             : }

Generated by: LCOV version 1.14