LCOV - code coverage report
Current view: top level - frmts/gtiff - gtiffrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 235 244 96.3 %
Date: 2024-11-21 22:18:42 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      695103 : GTiffRasterBand::GTiffRasterBand(GTiffDataset *poDSIn, int nBandIn)
      28      695103 :     : m_poGDS(poDSIn)
      29             : {
      30      695058 :     poDS = poDSIn;
      31      695058 :     nBand = nBandIn;
      32             : 
      33             :     /* -------------------------------------------------------------------- */
      34             :     /*      Get the GDAL data type.                                         */
      35             :     /* -------------------------------------------------------------------- */
      36      695058 :     const uint16_t nBitsPerSample = m_poGDS->m_nBitsPerSample;
      37      695058 :     const uint16_t nSampleFormat = m_poGDS->m_nSampleFormat;
      38             : 
      39      695058 :     eDataType = GDT_Unknown;
      40             : 
      41      695058 :     if (nBitsPerSample <= 8)
      42             :     {
      43      688423 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      44          80 :             eDataType = GDT_Int8;
      45             :         else
      46      688343 :             eDataType = GDT_Byte;
      47             :     }
      48        6635 :     else if (nBitsPerSample <= 16)
      49             :     {
      50        2347 :         if (nSampleFormat == SAMPLEFORMAT_INT)
      51        1162 :             eDataType = GDT_Int16;
      52             :         else
      53        1185 :             eDataType = GDT_UInt16;
      54             :     }
      55        4288 :     else if (nBitsPerSample == 32)
      56             :     {
      57        2866 :         if (nSampleFormat == SAMPLEFORMAT_COMPLEXINT)
      58         461 :             eDataType = GDT_CInt16;
      59        2405 :         else if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      60        1647 :             eDataType = GDT_Float32;
      61         758 :         else if (nSampleFormat == SAMPLEFORMAT_INT)
      62         402 :             eDataType = GDT_Int32;
      63             :         else
      64         356 :             eDataType = GDT_UInt32;
      65             :     }
      66        1422 :     else if (nBitsPerSample == 64)
      67             :     {
      68        1098 :         if (nSampleFormat == SAMPLEFORMAT_IEEEFP)
      69         561 :             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      695058 :     bool bLookForExtraSamples = false;
      89             : 
      90      695058 :     if (m_poGDS->m_poColorTable != nullptr && nBand == 1)
      91             :     {
      92         161 :         m_eBandInterp = GCI_PaletteIndex;
      93             :     }
      94     1373920 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_RGB ||
      95      679001 :              (m_poGDS->m_nPhotometric == PHOTOMETRIC_YCBCR &&
      96         873 :               m_poGDS->m_nCompression == COMPRESSION_JPEG &&
      97         834 :               CPLTestBool(CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES"))))
      98             :     {
      99       16643 :         if (nBand == 1)
     100        5218 :             m_eBandInterp = GCI_RedBand;
     101       11425 :         else if (nBand == 2)
     102        5221 :             m_eBandInterp = GCI_GreenBand;
     103        6204 :         else if (nBand == 3)
     104        5223 :             m_eBandInterp = GCI_BlueBand;
     105             :         else
     106         981 :             bLookForExtraSamples = true;
     107             :     }
     108      678274 :     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      678235 :     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      678139 :     else if (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1)
     133             :     {
     134       20181 :         m_eBandInterp = GCI_GrayIndex;
     135             :     }
     136             :     else
     137             :     {
     138      657958 :         bLookForExtraSamples = true;
     139             :     }
     140             : 
     141      695078 :     if (bLookForExtraSamples)
     142             :     {
     143      658821 :         uint16_t *v = nullptr;
     144      658821 :         uint16_t count = 0;
     145             : 
     146      658821 :         if (TIFFGetField(m_poGDS->m_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v))
     147             :         {
     148      592968 :             const int nBaseSamples = m_poGDS->m_nSamplesPerPixel - count;
     149      592968 :             const int nExpectedBaseSamples =
     150      593952 :                 (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK)   ? 1
     151        1968 :                 : (m_poGDS->m_nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1
     152         990 :                 : (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      592968 :             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      592968 :             if (nBand > nBaseSamples && nBand - nBaseSamples - 1 < count &&
     167      592963 :                 (v[nBand - nBaseSamples - 1] == EXTRASAMPLE_ASSOCALPHA ||
     168      592954 :                  v[nBand - nBaseSamples - 1] == EXTRASAMPLE_UNASSALPHA))
     169        1036 :                 m_eBandInterp = GCI_AlphaBand;
     170             :             else
     171      591932 :                 m_eBandInterp = GCI_Undefined;
     172             :         }
     173             :         else
     174             :         {
     175       65853 :             m_eBandInterp = GCI_Undefined;
     176             :         }
     177             :     }
     178             : 
     179             :     /* -------------------------------------------------------------------- */
     180             :     /*      Establish block size for strip or tiles.                        */
     181             :     /* -------------------------------------------------------------------- */
     182      695078 :     nBlockXSize = m_poGDS->m_nBlockXSize;
     183      695078 :     nBlockYSize = m_poGDS->m_nBlockYSize;
     184      695078 :     nRasterXSize = m_poGDS->nRasterXSize;
     185      695078 :     nRasterYSize = m_poGDS->nRasterYSize;
     186      695078 :     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     187      695078 :     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
     188      695078 : }
     189             : 
     190             : /************************************************************************/
     191             : /*                          ~GTiffRasterBand()                          */
     192             : /************************************************************************/
     193             : 
     194     1258222 : GTiffRasterBand::~GTiffRasterBand()
     195             : {
     196             :     // So that any future DropReferenceVirtualMem() will not try to access the
     197             :     // raster band object, but this would not conform to the advertised
     198             :     // contract.
     199      695122 :     if (!m_aSetPSelf.empty())
     200             :     {
     201           0 :         ReportError(CE_Warning, CPLE_AppDefined,
     202             :                     "Virtual memory objects still exist at GTiffRasterBand "
     203             :                     "destruction");
     204           0 :         std::set<GTiffRasterBand **>::iterator oIter = m_aSetPSelf.begin();
     205           0 :         for (; oIter != m_aSetPSelf.end(); ++oIter)
     206           0 :             *(*oIter) = nullptr;
     207             :     }
     208     1258211 : }
     209             : 
     210             : /************************************************************************/
     211             : /*                            IRasterIO()                               */
     212             : /************************************************************************/
     213             : 
     214     5326270 : CPLErr GTiffRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     215             :                                   int nXSize, int nYSize, void *pData,
     216             :                                   int nBufXSize, int nBufYSize,
     217             :                                   GDALDataType eBufType, GSpacing nPixelSpace,
     218             :                                   GSpacing nLineSpace,
     219             :                                   GDALRasterIOExtraArg *psExtraArg)
     220             : {
     221             : #if DEBUG_VERBOSE
     222             :     CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)", nXOff, nYOff, nXSize,
     223             :              nYSize, nBufXSize, nBufYSize);
     224             : #endif
     225             : 
     226             :     // Try to pass the request to the most appropriate overview dataset.
     227     5326270 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     228             :     {
     229      161930 :         int bTried = FALSE;
     230      161930 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     231      161575 :             ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     232      161930 :         const CPLErr eErr = TryOverviewRasterIO(
     233             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     234             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     235      161930 :         if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     236      161575 :             --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     237      161930 :         if (bTried)
     238          44 :             return eErr;
     239             :     }
     240             : 
     241     5326230 :     if (m_poGDS->m_eVirtualMemIOUsage != GTiffDataset::VirtualMemIOEnum::NO)
     242             :     {
     243         904 :         const int nErr = m_poGDS->VirtualMemIO(
     244             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     245         452 :             eBufType, 1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
     246         452 :         if (nErr >= 0)
     247         363 :             return static_cast<CPLErr>(nErr);
     248             :     }
     249     5325870 :     if (m_poGDS->m_bDirectIO)
     250             :     {
     251             :         int nErr =
     252        2098 :             DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
     253             :                      nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg);
     254        2098 :         if (nErr >= 0)
     255         985 :             return static_cast<CPLErr>(nErr);
     256             :     }
     257             : 
     258     5324880 :     bool bCanUseMultiThreadedRead = false;
     259     5324470 :     if (m_poGDS->m_nDisableMultiThreadedRead == 0 && eRWFlag == GF_Read &&
     260     3105440 :         m_poGDS->m_poThreadPool != nullptr && nXSize == nBufXSize &&
     261    10649400 :         nYSize == nBufYSize && m_poGDS->IsMultiThreadedReadCompatible())
     262             :     {
     263         101 :         const int nBlockX1 = nXOff / nBlockXSize;
     264         101 :         const int nBlockY1 = nYOff / nBlockYSize;
     265         101 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     266         101 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     267         101 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     268         101 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     269         101 :         if (nXBlocks > 1 || nYBlocks > 1)
     270             :         {
     271          98 :             bCanUseMultiThreadedRead = true;
     272             :         }
     273             :     }
     274             : 
     275             :     // Cleanup data cached by below CacheMultiRange() call.
     276             :     struct BufferedDataFreer
     277             :     {
     278             :         void *m_pBufferedData = nullptr;
     279             :         TIFF *m_hTIFF = nullptr;
     280             : 
     281         250 :         void Init(void *pBufferedData, TIFF *hTIFF)
     282             :         {
     283         250 :             m_pBufferedData = pBufferedData;
     284         250 :             m_hTIFF = hTIFF;
     285         250 :         }
     286             : 
     287     5325020 :         ~BufferedDataFreer()
     288     5325020 :         {
     289     5325020 :             if (m_pBufferedData)
     290             :             {
     291          35 :                 VSIFree(m_pBufferedData);
     292          35 :                 VSI_TIFFSetCachedRanges(TIFFClientdata(m_hTIFF), 0, nullptr,
     293             :                                         nullptr, nullptr);
     294             :             }
     295     5325020 :         }
     296             :     };
     297             : 
     298             :     // bufferedDataFreer must be left in this scope !
     299     5325080 :     BufferedDataFreer bufferedDataFreer;
     300             : 
     301     8113220 :     if (m_poGDS->eAccess == GA_ReadOnly && eRWFlag == GF_Read &&
     302     2788400 :         m_poGDS->HasOptimizedReadMultiRange())
     303             :     {
     304         254 :         if (bCanUseMultiThreadedRead &&
     305           2 :             VSI_TIFFGetVSILFile(TIFFClientdata(m_poGDS->m_hTIFF))->HasPRead())
     306             :         {
     307             :             // use the multi-threaded implementation rather than the multi-range
     308             :             // one
     309             :         }
     310             :         else
     311             :         {
     312         250 :             bCanUseMultiThreadedRead = false;
     313         250 :             GTiffRasterBand *poBandForCache = this;
     314         250 :             if (!m_poGDS->m_bStreamingIn && m_poGDS->m_bBlockOrderRowMajor &&
     315         106 :                 m_poGDS->m_bLeaderSizeAsUInt4 &&
     316         106 :                 m_poGDS->m_bMaskInterleavedWithImagery &&
     317         102 :                 m_poGDS->m_poImageryDS)
     318             :             {
     319          63 :                 poBandForCache = cpl::down_cast<GTiffRasterBand *>(
     320          63 :                     m_poGDS->m_poImageryDS->GetRasterBand(1));
     321             :             }
     322         250 :             bufferedDataFreer.Init(poBandForCache->CacheMultiRange(
     323             :                                        nXOff, nYOff, nXSize, nYSize, nBufXSize,
     324             :                                        nBufYSize, psExtraArg),
     325         250 :                                    poBandForCache->m_poGDS->m_hTIFF);
     326             :         }
     327             :     }
     328             : 
     329     5324620 :     if (eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize)
     330             :     {
     331     2910020 :         const int nBlockX1 = nXOff / nBlockXSize;
     332     2910020 :         const int nBlockY1 = nYOff / nBlockYSize;
     333     2910020 :         const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
     334     2910020 :         const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
     335     2910020 :         const int nXBlocks = nBlockX2 - nBlockX1 + 1;
     336     2910020 :         const int nYBlocks = nBlockY2 - nBlockY1 + 1;
     337             : 
     338     2910020 :         if (bCanUseMultiThreadedRead)
     339             :         {
     340         196 :             return m_poGDS->MultiThreadedRead(nXOff, nYOff, nXSize, nYSize,
     341          98 :                                               pData, eBufType, 1, &nBand,
     342          98 :                                               nPixelSpace, nLineSpace, 0);
     343             :         }
     344     2909930 :         else if (m_poGDS->nBands != 1 &&
     345      687764 :                  m_poGDS->m_nPlanarConfig == PLANARCONFIG_CONTIG)
     346             :         {
     347             :             const GIntBig nRequiredMem =
     348      635753 :                 static_cast<GIntBig>(m_poGDS->nBands) * nXBlocks * nYBlocks *
     349      635753 :                 nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     350      635879 :             if (nRequiredMem > GDALGetCacheMax64())
     351             :             {
     352        9060 :                 if (!m_poGDS->m_bHasWarnedDisableAggressiveBandCaching)
     353             :                 {
     354          14 :                     CPLDebug("GTiff",
     355             :                              "Disable aggressive band caching. "
     356             :                              "Cache not big enough. "
     357             :                              "At least " CPL_FRMT_GIB " bytes necessary",
     358             :                              nRequiredMem);
     359          14 :                     m_poGDS->m_bHasWarnedDisableAggressiveBandCaching = true;
     360             :                 }
     361        9060 :                 m_poGDS->m_bLoadingOtherBands = true;
     362             :             }
     363     2910050 :         }
     364             :     }
     365             : 
     366             :     // Write optimization when writing whole blocks, by-passing the block cache.
     367             :     // We require the block cache to be non instantiated to simplify things
     368             :     // (otherwise we might need to evict corresponding existing blocks from the
     369             :     // block cache).
     370     4633670 :     else if (eRWFlag == GF_Write &&
     371             :              // Could be extended to "odd bit" case, but more work
     372     2219070 :              m_poGDS->m_nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
     373     2066910 :              nXSize == nBufXSize && nYSize == nBufYSize && !HasBlockCache() &&
     374        4391 :              !m_poGDS->m_bLoadedBlockDirty &&
     375        4379 :              (m_poGDS->nBands == 1 ||
     376        1731 :               m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE) &&
     377        3348 :              (nXOff % nBlockXSize) == 0 && (nYOff % nBlockYSize) == 0 &&
     378     4636840 :              (nXOff + nXSize == nRasterXSize || (nXSize % nBlockXSize) == 0) &&
     379        3170 :              (nYOff + nYSize == nRasterYSize || (nYSize % nBlockYSize) == 0))
     380             :     {
     381        2877 :         m_poGDS->Crystalize();
     382             : 
     383        2877 :         if (m_poGDS->m_bDebugDontWriteBlocks)
     384           0 :             return CE_None;
     385             : 
     386        2877 :         const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     387        2877 :         if (nXSize == nBlockXSize && nYSize == nBlockYSize &&
     388        1510 :             eBufType == eDataType && nPixelSpace == nDTSize &&
     389        1458 :             nLineSpace == nPixelSpace * nBlockXSize)
     390             :         {
     391             :             // If writing one single block with the right data type and layout,
     392             :             // we don't need a temporary buffer
     393             :             const int nBlockId =
     394        1458 :                 ComputeBlockId(nXOff / nBlockXSize, nYOff / nBlockYSize);
     395        1458 :             return m_poGDS->WriteEncodedTileOrStrip(
     396        1458 :                 nBlockId, pData, /* bPreserveDataBuffer= */ true);
     397             :         }
     398             : 
     399             :         // Make sure m_poGDS->m_pabyBlockBuf is allocated.
     400             :         // We could actually use any temporary buffer
     401        1419 :         if (m_poGDS->LoadBlockBuf(/* nBlockId = */ -1,
     402        1419 :                                   /* bReadFromDisk = */ false) != CE_None)
     403             :         {
     404           0 :             return CE_Failure;
     405             :         }
     406             : 
     407             :         // Iterate over all blocks defined by
     408             :         // [nXOff, nXOff+nXSize[ * [nYOff, nYOff+nYSize[
     409             :         // and write their content as a nBlockXSize x nBlockYSize strile
     410             :         // in a temporary buffer, before calling WriteEncodedTileOrStrip()
     411             :         // on it
     412        1419 :         const int nYBlockStart = nYOff / nBlockYSize;
     413        1419 :         const int nYBlockEnd = 1 + (nYOff + nYSize - 1) / nBlockYSize;
     414        1419 :         const int nXBlockStart = nXOff / nBlockXSize;
     415        1419 :         const int nXBlockEnd = 1 + (nXOff + nXSize - 1) / nBlockXSize;
     416       25675 :         for (int nYBlock = nYBlockStart; nYBlock < nYBlockEnd; ++nYBlock)
     417             :         {
     418             :             const int nValidY =
     419       24256 :                 std::min(nBlockYSize, nRasterYSize - nYBlock * nBlockYSize);
     420       62278 :             for (int nXBlock = nXBlockStart; nXBlock < nXBlockEnd; ++nXBlock)
     421             :             {
     422             :                 const int nValidX =
     423       38022 :                     std::min(nBlockXSize, nRasterXSize - nXBlock * nBlockXSize);
     424       38021 :                 if (nValidY < nBlockYSize || nValidX < nBlockXSize)
     425             :                 {
     426             :                     // Make sure padding bytes at the right/bottom of the
     427             :                     // tile are initialized to zero.
     428        2203 :                     memset(m_poGDS->m_pabyBlockBuf, 0,
     429        2203 :                            static_cast<size_t>(nBlockXSize) * nBlockYSize *
     430        2203 :                                nDTSize);
     431             :                 }
     432       38021 :                 const GByte *pabySrcData =
     433             :                     static_cast<const GByte *>(pData) +
     434       38021 :                     static_cast<size_t>(nYBlock - nYBlockStart) * nBlockYSize *
     435       38021 :                         nLineSpace +
     436       38021 :                     static_cast<size_t>(nXBlock - nXBlockStart) * nBlockXSize *
     437       38021 :                         nPixelSpace;
     438     1250130 :                 for (int iY = 0; iY < nValidY; ++iY)
     439             :                 {
     440     1212100 :                     GDALCopyWords64(
     441     1212100 :                         pabySrcData + static_cast<size_t>(iY) * nLineSpace,
     442             :                         eBufType, static_cast<int>(nPixelSpace),
     443     1212100 :                         m_poGDS->m_pabyBlockBuf +
     444     1212100 :                             static_cast<size_t>(iY) * nBlockXSize * nDTSize,
     445             :                         eDataType, nDTSize, nValidX);
     446             :                 }
     447       38022 :                 const int nBlockId = ComputeBlockId(nXBlock, nYBlock);
     448       76044 :                 if (m_poGDS->WriteEncodedTileOrStrip(
     449       38022 :                         nBlockId, m_poGDS->m_pabyBlockBuf,
     450       38022 :                         /* bPreserveDataBuffer= */ false) != CE_None)
     451             :                 {
     452           0 :                     return CE_Failure;
     453             :                 }
     454             :             }
     455             :         }
     456        1419 :         return CE_None;
     457             :     }
     458             : 
     459     5321770 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     460     5319450 :         ++m_poGDS->m_nJPEGOverviewVisibilityCounter;
     461     5321770 :     const CPLErr eErr = GDALPamRasterBand::IRasterIO(
     462             :         eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     463             :         eBufType, nPixelSpace, nLineSpace, psExtraArg);
     464     5322110 :     if (psExtraArg->eResampleAlg == GRIORA_NearestNeighbour)
     465     5319610 :         --m_poGDS->m_nJPEGOverviewVisibilityCounter;
     466             : 
     467     5322110 :     m_poGDS->m_bLoadingOtherBands = false;
     468             : 
     469     5322110 :     return eErr;
     470             : }
     471             : 
     472             : /************************************************************************/
     473             : /*                        ComputeBlockId()                              */
     474             : /************************************************************************/
     475             : 
     476             : /** Computes the TIFF block identifier from the tile coordinate, band
     477             :  * number and planar configuration.
     478             :  */
     479     3098440 : int GTiffRasterBand::ComputeBlockId(int nBlockXOff, int nBlockYOff) const
     480             : {
     481     3098440 :     const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
     482     3098440 :     if (m_poGDS->m_nPlanarConfig == PLANARCONFIG_SEPARATE)
     483             :     {
     484      403202 :         return nBlockId + (nBand - 1) * m_poGDS->m_nBlocksPerBand;
     485             :     }
     486     2695240 :     return nBlockId;
     487             : }

Generated by: LCOV version 1.14